1 |
/* |
2 |
* editpolicy.c |
3 |
* |
4 |
* TOMOYO Linux's utilities. |
5 |
* |
6 |
* Copyright (C) 2005-2008 NTT DATA CORPORATION |
7 |
* |
8 |
* Version: 1.6.0-pre 2008/01/03 |
9 |
* |
10 |
*/ |
11 |
#include "ccstools.h" |
12 |
|
13 |
/// add color start |
14 |
#ifdef COLOR_ON |
15 |
#define OFF 0 |
16 |
#define ON !OFF |
17 |
|
18 |
#define ENV_KEYWORD "EDITPOLICY_COLORS" |
19 |
#define ENV_DELIM ":" |
20 |
|
21 |
enum color_pair { NORMAL, |
22 |
DOMAIN_HEAD, DOMAIN_CURSOR, |
23 |
SYSTEM_HEAD, SYSTEM_CURSOR, |
24 |
EXCEPTION_HEAD, EXCEPTION_CURSOR, |
25 |
ACL_HEAD, ACL_CURSOR, |
26 |
DISP_ERR }; |
27 |
|
28 |
static struct color_env_t { |
29 |
enum color_pair tag; |
30 |
short fore; |
31 |
short back; |
32 |
char *name; |
33 |
} color_env[] = { |
34 |
{DOMAIN_HEAD, COLOR_BLACK, COLOR_GREEN, "DOMAIN_HEAD="}, |
35 |
{DOMAIN_CURSOR, COLOR_BLACK, COLOR_GREEN, "DOMAIN_CURSOR="}, |
36 |
{SYSTEM_HEAD, COLOR_WHITE, COLOR_BLUE, "SYSTEM_HEAD="}, |
37 |
{SYSTEM_CURSOR, COLOR_WHITE, COLOR_BLUE, "SYSTEM_CURSOR="}, |
38 |
{EXCEPTION_HEAD, COLOR_BLACK, COLOR_CYAN, "EXCEPTION_HEAD="}, |
39 |
{EXCEPTION_CURSOR, COLOR_BLACK, COLOR_CYAN, "EXCEPTION_CURSOR="}, |
40 |
{ACL_HEAD, COLOR_BLACK, COLOR_YELLOW, "ACL_HEAD="}, |
41 |
{ACL_CURSOR, COLOR_BLACK, COLOR_YELLOW, "ACL_CURSOR="}, |
42 |
{NORMAL, COLOR_WHITE, COLOR_BLACK, NULL} |
43 |
}; |
44 |
|
45 |
static void getColorEnv(char *env) |
46 |
{ |
47 |
int i, len; |
48 |
char *p; |
49 |
short fore, back; |
50 |
|
51 |
for (i = 0; color_env[i].name != NULL; i++) { |
52 |
p = color_env[i].name; |
53 |
len = strlen(p); |
54 |
if (strncmp(p, env, len)) continue; |
55 |
env += len; |
56 |
if (strlen(env) != 2) break; |
57 |
fore = (*env++) - '0'; // foreground color |
58 |
back = (*env) - '0'; // background color |
59 |
if (fore < 0 || fore > 7 || |
60 |
back < 0 || back > 7) break; |
61 |
color_env[i].fore = fore; |
62 |
color_env[i].back = back; |
63 |
break; |
64 |
} |
65 |
} |
66 |
|
67 |
static void ColorInit(void){ |
68 |
char *env, *p; |
69 |
int i; |
70 |
struct color_env_t *colorp; |
71 |
|
72 |
env = getenv(ENV_KEYWORD); |
73 |
if (env) { |
74 |
p = strtok(env, ENV_DELIM); |
75 |
if (p) { |
76 |
getColorEnv(p); |
77 |
while ((p = strtok(NULL, ENV_DELIM)) != NULL) { |
78 |
getColorEnv(p); |
79 |
} |
80 |
} |
81 |
} |
82 |
|
83 |
start_color(); |
84 |
|
85 |
for (i = 0; color_env[i].name != NULL; i++) { |
86 |
colorp = &color_env[i]; |
87 |
init_pair(colorp->tag, colorp->fore, colorp->back); |
88 |
} |
89 |
|
90 |
init_pair(DISP_ERR, COLOR_RED, COLOR_BLACK); // error massage |
91 |
} |
92 |
|
93 |
static void ColorSave(int flg) { |
94 |
static int save_color = NORMAL; |
95 |
if (flg == ON) |
96 |
save_color = getattrs(stdscr); |
97 |
else |
98 |
attrset(save_color); |
99 |
} |
100 |
|
101 |
#define colorChange(attr, flg) {flg ? attron(COLOR_PAIR(attr)) : attroff(COLOR_PAIR(attr));} |
102 |
#define attrChange(attr, flg) {flg ? attron(attr) : attroff(attr);} |
103 |
|
104 |
#define sttrSave() ColorSave(ON) |
105 |
#define sttrRestore() ColorSave(OFF) |
106 |
|
107 |
#define colorHead() ( \ |
108 |
(current_screen == SCREEN_DOMAIN_LIST) ? DOMAIN_HEAD \ |
109 |
: (current_screen == SCREEN_SYSTEM_LIST) ? SYSTEM_HEAD \ |
110 |
: (current_screen == SCREEN_EXCEPTION_LIST) ? EXCEPTION_HEAD \ |
111 |
: ACL_HEAD ) |
112 |
|
113 |
#define colorCursor() ( \ |
114 |
(current_screen == SCREEN_DOMAIN_LIST) ? DOMAIN_CURSOR \ |
115 |
: (current_screen == SCREEN_SYSTEM_LIST) ? SYSTEM_CURSOR \ |
116 |
: (current_screen == SCREEN_EXCEPTION_LIST) ? EXCEPTION_CURSOR \ |
117 |
: ACL_CURSOR ) |
118 |
|
119 |
|
120 |
|
121 |
#else // no color |
122 |
|
123 |
#define ColorInit() |
124 |
#define colorChange(attr, flg) |
125 |
#define attrChange(attr, flg) |
126 |
#define sttrSave() |
127 |
#define sttrRestore() |
128 |
#define colorHead() |
129 |
#define colorCursor() |
130 |
|
131 |
#endif |
132 |
/// add color end |
133 |
|
134 |
static int string_acl_compare(const void *a, const void *b) { |
135 |
const char *a0 = * (char **) a; |
136 |
const char *b0 = * (char **) b; |
137 |
if (*a0 && *b0) return strcmp(a0 + 1, b0 + 1); |
138 |
return 0; |
139 |
} |
140 |
|
141 |
static char *ReadFile(const char *filename) { |
142 |
char *read_buffer = NULL; |
143 |
int fd; |
144 |
if ((fd = open(filename, O_RDONLY)) != EOF) { |
145 |
int read_buffer_len = 0; |
146 |
while (1) { |
147 |
char *cp = realloc(read_buffer, read_buffer_len + 4096); |
148 |
int len; |
149 |
if (!cp) { |
150 |
free(read_buffer); |
151 |
return NULL; |
152 |
} |
153 |
read_buffer = cp; |
154 |
len = read(fd, read_buffer + read_buffer_len, 4095); |
155 |
if (len <= 0) break; |
156 |
read_buffer_len += len; |
157 |
} |
158 |
close(fd); |
159 |
read_buffer[read_buffer_len] = '\0'; |
160 |
} |
161 |
return read_buffer; |
162 |
} |
163 |
|
164 |
static struct path_group_entry *path_group_list = NULL; |
165 |
static int path_group_list_len = 0; |
166 |
static struct address_group_entry *address_group_list = NULL; |
167 |
static int address_group_list_len = 0; |
168 |
|
169 |
static struct domain_info *domain_list = NULL, *shadow_domain_list = NULL; |
170 |
static int domain_list_count = 0, shadow_domain_list_count = 0; |
171 |
static unsigned char *domain_list_selected = NULL; |
172 |
|
173 |
static void SwapDomainList(void) { |
174 |
struct domain_info *tmp_list = domain_list; |
175 |
int tmp_list_count = domain_list_count; |
176 |
domain_list = shadow_domain_list; |
177 |
domain_list_count = shadow_domain_list_count; |
178 |
shadow_domain_list = tmp_list; |
179 |
shadow_domain_list_count = tmp_list_count; |
180 |
} |
181 |
|
182 |
static const char *DomainName(const int index) { |
183 |
return domain_list[index].domainname->name; |
184 |
} |
185 |
|
186 |
static const char *GetLastName(const int index) { |
187 |
const char *cp0 = DomainName(index), *cp1; |
188 |
if ((cp1 = strrchr(cp0, ' ')) != NULL) return cp1 + 1; |
189 |
return cp0; |
190 |
} |
191 |
|
192 |
static int AddStringEntry(const char *entry, const int index) { |
193 |
const struct path_info **acl_ptr; |
194 |
int acl_count; |
195 |
const struct path_info *cp; |
196 |
int i; |
197 |
if (index < 0 || index >= domain_list_count) { |
198 |
fprintf(stderr, "AddStringEntry: ERROR: domain is out of range.\n"); |
199 |
return -EINVAL; |
200 |
} |
201 |
if (!entry || !*entry) return -EINVAL; |
202 |
if ((cp = SaveName(entry)) == NULL) OutOfMemory(); |
203 |
|
204 |
acl_ptr = domain_list[index].string_ptr; |
205 |
acl_count = domain_list[index].string_count; |
206 |
|
207 |
// Check for the same entry. |
208 |
for (i = 0; i < acl_count; i++) { |
209 |
// Faster comparison, for they are SaveName'd. |
210 |
if (cp == acl_ptr[i]) return 0; |
211 |
} |
212 |
|
213 |
if ((acl_ptr = (const struct path_info **) realloc(acl_ptr, (acl_count + 1) * sizeof(const struct path_info *))) == NULL) OutOfMemory(); |
214 |
acl_ptr[acl_count++] = cp; |
215 |
domain_list[index].string_ptr = acl_ptr; |
216 |
domain_list[index].string_count = acl_count; |
217 |
return 0; |
218 |
} |
219 |
|
220 |
static int DelStringEntry(const char *entry, const int index) { |
221 |
const struct path_info **acl_ptr; |
222 |
int acl_count; |
223 |
const struct path_info *cp; |
224 |
int i; |
225 |
if (index < 0 || index >= domain_list_count) { |
226 |
fprintf(stderr, "DelStringEntry: ERROR: domain is out of range.\n"); |
227 |
return -EINVAL; |
228 |
} |
229 |
if (!entry || !*entry) return -EINVAL; |
230 |
if ((cp = SaveName(entry)) == NULL) OutOfMemory(); |
231 |
|
232 |
acl_ptr = domain_list[index].string_ptr; |
233 |
acl_count = domain_list[index].string_count; |
234 |
|
235 |
for (i = 0; i < acl_count; i++) { |
236 |
// Faster comparison, for they are SaveName'd. |
237 |
if (cp != acl_ptr[i]) continue; |
238 |
domain_list[index].string_count--; |
239 |
for (; i < acl_count - 1; i++) acl_ptr[i] = acl_ptr[i + 1]; |
240 |
return 0; |
241 |
} |
242 |
return -ENOENT; |
243 |
} |
244 |
|
245 |
static void ClearDomainPolicy(void) { |
246 |
int index; |
247 |
for (index = 0; index < domain_list_count; index++) { |
248 |
free(domain_list[index].string_ptr); |
249 |
domain_list[index].string_ptr = NULL; |
250 |
domain_list[index].string_count = 0; |
251 |
} |
252 |
free(domain_list); |
253 |
domain_list = NULL; |
254 |
domain_list_count = 0; |
255 |
} |
256 |
|
257 |
static int FindDomain(const char *domainname0, const int is_domain_initializer_source, const int is_domain_deleted) { |
258 |
int i; |
259 |
struct path_info domainname; |
260 |
domainname.name = domainname0; |
261 |
fill_path_info(&domainname); |
262 |
for (i = 0; i < domain_list_count; i++) { |
263 |
if (domain_list[i].is_domain_initializer_source == is_domain_initializer_source && domain_list[i].is_domain_deleted == is_domain_deleted && !pathcmp(&domainname, domain_list[i].domainname)) return i; |
264 |
} |
265 |
return EOF; |
266 |
} |
267 |
|
268 |
static int FindOrAssignNewDomain(const char *domainname, const int is_domain_initializer_source, const int is_domain_deleted) { |
269 |
const struct path_info *saved_domainname; |
270 |
int index; |
271 |
if ((index = FindDomain(domainname, is_domain_initializer_source, is_domain_deleted)) == EOF) { |
272 |
if (IsCorrectDomain(domainname)) { |
273 |
if ((domain_list = (struct domain_info *) realloc(domain_list, (domain_list_count + 1) * sizeof(struct domain_info))) == NULL) OutOfMemory(); |
274 |
memset(&domain_list[domain_list_count], 0, sizeof(struct domain_info)); |
275 |
if ((saved_domainname = SaveName(domainname)) == NULL) OutOfMemory(); |
276 |
domain_list[domain_list_count].domainname = saved_domainname; |
277 |
domain_list[domain_list_count].is_domain_initializer_source = is_domain_initializer_source; |
278 |
domain_list[domain_list_count].is_domain_deleted = is_domain_deleted; |
279 |
index = domain_list_count++; |
280 |
} else { |
281 |
fprintf(stderr, "FindOrAssignNewDomain: Invalid domainname '%s'\n", domainname); |
282 |
} |
283 |
} |
284 |
return index; |
285 |
} |
286 |
|
287 |
static void DeleteDomain(const int index) { |
288 |
if (index > 0 && index < domain_list_count) { |
289 |
int i; |
290 |
free(domain_list[index].string_ptr); |
291 |
for (i = index; i < domain_list_count - 1; i++) domain_list[i] = domain_list[i + 1]; |
292 |
domain_list_count--; |
293 |
} |
294 |
} |
295 |
|
296 |
static int domainname_compare(const void *a, const void *b) { |
297 |
return strcmp(((struct domain_info *) a)->domainname->name, ((struct domain_info *) b)->domainname->name); |
298 |
} |
299 |
|
300 |
static int path_info_compare(const void *a, const void *b) { |
301 |
const char *a0 = (* (struct path_info **) a)->name; |
302 |
const char *b0 = (* (struct path_info **) b)->name; |
303 |
if (*a0 && *b0) return strcmp(a0 + 1, b0 + 1); |
304 |
return 0; |
305 |
} |
306 |
|
307 |
static void SortPolicy(void) { |
308 |
int i; |
309 |
qsort(domain_list, domain_list_count, sizeof(struct domain_info), domainname_compare); |
310 |
for (i = 0; i < domain_list_count; i++) qsort(domain_list[i].string_ptr, domain_list[i].string_count, sizeof(struct path_info *), path_info_compare); |
311 |
} |
312 |
|
313 |
static int WriteDomainPolicy(const int fd) { |
314 |
int i, j; |
315 |
for (i = 0; i < domain_list_count; i++) { |
316 |
const struct path_info **string_ptr = domain_list[i].string_ptr; |
317 |
const int string_count = domain_list[i].string_count; |
318 |
write(fd, domain_list[i].domainname->name, domain_list[i].domainname->total_len); |
319 |
write(fd, "\n\n", 2); |
320 |
for (j = 0; j < string_count; j++) { |
321 |
write(fd, string_ptr[j]->name, string_ptr[j]->total_len); |
322 |
write(fd, "\n", 1); |
323 |
} |
324 |
write(fd, "\n", 1); |
325 |
} |
326 |
return 0; |
327 |
} |
328 |
|
329 |
static int IsSameDomainList(void) { |
330 |
if (domain_list_count == shadow_domain_list_count) { |
331 |
int i, j; |
332 |
for (i = 0; i < domain_list_count; i++) { |
333 |
const struct path_info **string_ptr = domain_list[i].string_ptr; |
334 |
const int string_count = domain_list[i].string_count; |
335 |
if (string_count == shadow_domain_list[i].string_count) { |
336 |
const struct path_info **ptr = shadow_domain_list[i].string_ptr; |
337 |
for (j = 0; j < string_count; j++) { |
338 |
/* Faster comparison, for they are SaveName'd and sorted pointers. */ |
339 |
if (string_ptr[j] != ptr[j]) break; |
340 |
} |
341 |
if (j == string_count) continue; |
342 |
} |
343 |
break; |
344 |
} |
345 |
if (i == domain_list_count) return 1; |
346 |
} |
347 |
return 0; |
348 |
} |
349 |
|
350 |
static int IsKeeperDomain(const int index) { |
351 |
return domain_list[index].is_domain_keeper; |
352 |
} |
353 |
|
354 |
static int IsInitializerSource(const int index) { |
355 |
return domain_list[index].is_domain_initializer_source; |
356 |
} |
357 |
|
358 |
static int IsInitializerTarget(const int index) { |
359 |
return domain_list[index].is_domain_initializer_target; |
360 |
} |
361 |
|
362 |
static int IsDomainUnreachable(const int index) { |
363 |
return domain_list[index].is_domain_unreachable; |
364 |
} |
365 |
|
366 |
static int IsDeletedDomain(const int index) { |
367 |
return domain_list[index].is_domain_deleted; |
368 |
} |
369 |
|
370 |
static void ReadDomainPolicy(const char *filename) { |
371 |
FILE *fp = stdin; |
372 |
int index; |
373 |
if (filename) { |
374 |
if ((fp = fopen(filename, "r")) == NULL) { |
375 |
fprintf(stderr, "Can't open %s\n", filename); |
376 |
return; |
377 |
} |
378 |
} |
379 |
index = EOF; |
380 |
get(); |
381 |
while (freadline(fp)) { |
382 |
if (IsDomainDef(shared_buffer)) { |
383 |
index = FindOrAssignNewDomain(shared_buffer, 0, 0); |
384 |
} else if (index >= 0 && shared_buffer[0]) { |
385 |
AddStringEntry(shared_buffer, index); |
386 |
} |
387 |
} |
388 |
put(); |
389 |
if (fp != stdin) fclose(fp); |
390 |
SortPolicy(); |
391 |
} |
392 |
|
393 |
/***** sortpolicy start *****/ |
394 |
|
395 |
int sortpolicy_main(int argc, char *argv[]) { |
396 |
ReadDomainPolicy(NULL); |
397 |
WriteDomainPolicy(1); |
398 |
return 0; |
399 |
} |
400 |
|
401 |
/***** sortpolicy end *****/ |
402 |
|
403 |
/***** savepolicy start *****/ |
404 |
|
405 |
int savepolicy_main(int argc, char *argv[]) { |
406 |
int remount_root = 0; |
407 |
char filename[1024]; |
408 |
int save_system_policy = 0; |
409 |
int save_exception_policy = 0; |
410 |
int save_domain_policy = 0; |
411 |
int force_save = 0; |
412 |
int repeat; |
413 |
time_t now = time(NULL); |
414 |
struct tm *tm = localtime(&now); |
415 |
memset(filename, 0, sizeof(filename)); |
416 |
if (access("/proc/self/", F_OK)) mount("/proc", "/proc", "proc", 0, NULL); |
417 |
if (access(proc_policy_dir, F_OK)) { |
418 |
fprintf(stderr, "You can't run this program for this kernel.\n"); |
419 |
return 0; |
420 |
} |
421 |
if (argc == 1) { |
422 |
force_save = save_system_policy = save_exception_policy = save_domain_policy = 1; |
423 |
} else { |
424 |
int i; |
425 |
for (i = 1; i < argc; i++) { |
426 |
char *p = argv[i]; |
427 |
char *s = strchr(p, 's'); |
428 |
char *e = strchr(p, 'e'); |
429 |
char *d = strchr(p, 'd'); |
430 |
char *a = strchr(p, 'a'); |
431 |
char *f = strchr(p, 'f'); |
432 |
if (s || a) save_system_policy = 1; |
433 |
if (e || a) save_exception_policy = 1; |
434 |
if (d || a) save_domain_policy = 1; |
435 |
if (f) force_save = 1; |
436 |
if (strcspn(p, "sedaf")) { |
437 |
printf("%s [s][e][d][a][f]\n" |
438 |
"s : Save system_policy.\n" |
439 |
"e : Save exception_policy.\n" |
440 |
"d : Save domain_policy.\n" |
441 |
"a : Save all policies.\n" |
442 |
"f : Save even if on-disk policy and on-memory policy are the same.\n\n" |
443 |
"If no options given, this program assumes 'a' and 'f' are given.\n", argv[0]); |
444 |
return 0; |
445 |
} |
446 |
} |
447 |
} |
448 |
if (chdir(disk_policy_dir)) { |
449 |
printf("Directory %s doesn't exist.\n", disk_policy_dir); |
450 |
return 1; |
451 |
} |
452 |
if (access(".", W_OK) == EOF) { |
453 |
if (errno != EROFS || mount("/", "/", "rootfs", MS_REMOUNT, NULL) == EOF) { |
454 |
printf("Can't remount for read-write. (%s)\n", strerror(errno)); |
455 |
return 1; |
456 |
} |
457 |
remount_root = 1; |
458 |
} |
459 |
|
460 |
/* Exclude nonexistent policy. */ |
461 |
if (access(proc_policy_system_policy, R_OK)) save_system_policy = 0; |
462 |
if (access(proc_policy_exception_policy, R_OK)) save_exception_policy = 0; |
463 |
if (access(proc_policy_domain_policy, R_OK)) save_domain_policy = 0; |
464 |
|
465 |
/* Repeat twice so that necessary permissions for this program are included in domain policy. */ |
466 |
for (repeat = 0; repeat < 2; repeat++) { |
467 |
|
468 |
if (save_system_policy) { |
469 |
char *new_policy = ReadFile(proc_policy_system_policy); |
470 |
char *old_policy = ReadFile(disk_policy_system_policy); |
471 |
if (new_policy && (force_save || !old_policy || strcmp(new_policy, old_policy))) { |
472 |
int fd; |
473 |
snprintf(filename, sizeof(filename) - 1, "system_policy.%02d-%02d-%02d.%02d:%02d:%02d.conf", tm->tm_year % 100, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec); |
474 |
if ((fd = open(filename, O_WRONLY | O_CREAT, 0600)) != EOF) { |
475 |
ftruncate(fd, 0); |
476 |
write(fd, new_policy, strlen(new_policy)); |
477 |
close(fd); |
478 |
unlink(disk_policy_system_policy); |
479 |
symlink(filename, "system_policy.conf"); |
480 |
} else { |
481 |
printf("Can't create %s\n", filename); |
482 |
} |
483 |
} |
484 |
free(old_policy); |
485 |
free(new_policy); |
486 |
} |
487 |
|
488 |
if (save_exception_policy) { |
489 |
char *new_policy = ReadFile(proc_policy_exception_policy); |
490 |
char *old_policy = ReadFile(disk_policy_exception_policy); |
491 |
if (new_policy && (force_save || !old_policy || strcmp(new_policy, old_policy))) { |
492 |
int fd; |
493 |
snprintf(filename, sizeof(filename) - 1, "exception_policy.%02d-%02d-%02d.%02d:%02d:%02d.conf", tm->tm_year % 100, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec); |
494 |
if ((fd = open(filename, O_WRONLY | O_CREAT, 0600)) != EOF) { |
495 |
ftruncate(fd, 0); |
496 |
write(fd, new_policy, strlen(new_policy)); |
497 |
close(fd); |
498 |
unlink(disk_policy_exception_policy); |
499 |
symlink(filename, "exception_policy.conf"); |
500 |
} else { |
501 |
printf("Can't create %s\n", filename); |
502 |
} |
503 |
} |
504 |
free(old_policy); |
505 |
free(new_policy); |
506 |
} |
507 |
|
508 |
} |
509 |
|
510 |
if (save_domain_policy) { |
511 |
ReadDomainPolicy(proc_policy_domain_policy); |
512 |
for (repeat = 0; repeat < 10; repeat++) { |
513 |
//if (repeat) printf("Domain policy has changed while saving domain policy. Retrying.\n"); |
514 |
if (access(disk_policy_domain_policy, R_OK) == 0) { |
515 |
SwapDomainList(); |
516 |
ReadDomainPolicy(disk_policy_domain_policy); |
517 |
SwapDomainList(); |
518 |
} |
519 |
/* Need to save domain policy? */ |
520 |
if (force_save || !IsSameDomainList()) { |
521 |
int fd; |
522 |
snprintf(filename, sizeof(filename) - 1, "domain_policy.%02d-%02d-%02d.%02d:%02d:%02d.conf", tm->tm_year % 100, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec); |
523 |
if ((fd = open(filename, O_WRONLY | O_CREAT, 0600)) != EOF) { |
524 |
ftruncate(fd, 0); |
525 |
WriteDomainPolicy(fd); |
526 |
close(fd); |
527 |
unlink(disk_policy_domain_policy); |
528 |
symlink(filename, "domain_policy.conf"); |
529 |
} else { |
530 |
printf("Can't create %s\n", filename); |
531 |
} |
532 |
} |
533 |
/* Has domain policy changed while saving domain policy? */ |
534 |
ClearDomainPolicy(); |
535 |
ReadDomainPolicy(proc_policy_domain_policy); |
536 |
if (IsSameDomainList()) break; |
537 |
SwapDomainList(); ClearDomainPolicy(); SwapDomainList(); |
538 |
} |
539 |
ClearDomainPolicy(); |
540 |
SwapDomainList(); ClearDomainPolicy(); SwapDomainList(); |
541 |
} |
542 |
if (remount_root) mount("/", "/", "rootfs", MS_REMOUNT | MS_RDONLY, NULL); |
543 |
return 0; |
544 |
} |
545 |
|
546 |
/***** savepolicy end *****/ |
547 |
|
548 |
/***** loadpolicy start *****/ |
549 |
|
550 |
int loadpolicy_main(int argc, char *argv[]) { |
551 |
int read_from_stdin = 0; |
552 |
int load_profile = 0; |
553 |
int load_manager = 0; |
554 |
int load_system_policy = 0; |
555 |
int load_exception_policy = 0; |
556 |
int load_domain_policy = 0; |
557 |
int refresh_policy = 0; |
558 |
if (access(proc_policy_dir, F_OK)) { |
559 |
fprintf(stderr, "You can't run this program for this kernel.\n"); |
560 |
return 0; |
561 |
} |
562 |
if (argc == 1) { |
563 |
goto usage; |
564 |
} else { |
565 |
int i; |
566 |
for (i = 1; i < argc; i++) { |
567 |
char *ptr = argv[i]; |
568 |
char *s = strchr(ptr, 's'); |
569 |
char *e = strchr(ptr, 'e'); |
570 |
char *d = strchr(ptr, 'd'); |
571 |
char *a = strchr(ptr, 'a'); |
572 |
char *f = strchr(ptr, 'f'); |
573 |
char *p = strchr(ptr, 'p'); |
574 |
char *m = strchr(ptr, 'm'); |
575 |
char *i = strchr(ptr, '-'); |
576 |
if (s || a) load_system_policy = 1; |
577 |
if (e || a) load_exception_policy = 1; |
578 |
if (d || a) load_domain_policy = 1; |
579 |
if (p) load_profile = 1; |
580 |
if (m) load_manager = 1; |
581 |
if (f) refresh_policy = 1; |
582 |
if (i) read_from_stdin = 1; |
583 |
if (strcspn(ptr, "sedafpm-") || |
584 |
(read_from_stdin && load_system_policy + load_exception_policy + load_domain_policy + load_profile + load_manager != 1)) { |
585 |
usage: ; |
586 |
printf("%s [s][e][d][a][f][p][m][-]\n" |
587 |
"s : Load system_policy.\n" |
588 |
"e : Load exception_policy.\n" |
589 |
"d : Load domain_policy.\n" |
590 |
"a : Load system_policy,exception_policy,domain_policy.\n" |
591 |
"p : Load profile.\n" |
592 |
"m : Load manager.\n" |
593 |
"- : Load policy from stdin. (Only one of 'sedpm' is possible when using '-'.)\n" |
594 |
"f : Delete on-memory policy before loading on-disk policy. (Valid for 'sed'.)\n\n", argv[0]); |
595 |
return 0; |
596 |
} |
597 |
} |
598 |
} |
599 |
if (chdir(disk_policy_dir)) { |
600 |
printf("Directory %s doesn't exist.\n", disk_policy_dir); |
601 |
return 1; |
602 |
} |
603 |
|
604 |
if (load_profile) { |
605 |
FILE *file_fp, *proc_fp; |
606 |
const char *policy_src = disk_policy_profile; |
607 |
if ((file_fp = read_from_stdin ? stdin : fopen(policy_src, "r")) == NULL) { |
608 |
fprintf(stderr, "Can't open %s\n", policy_src); |
609 |
goto out_system; |
610 |
} |
611 |
if ((proc_fp = fopen(proc_policy_profile, "w")) == NULL) { |
612 |
fprintf(stderr, "Can't open %s\n", proc_policy_profile); |
613 |
fclose(file_fp); |
614 |
goto out_profile; |
615 |
} |
616 |
get(); |
617 |
while (freadline(file_fp)) { |
618 |
if (shared_buffer[0]) fprintf(proc_fp, "%s\n", shared_buffer); |
619 |
} |
620 |
put(); |
621 |
fclose(proc_fp); |
622 |
fclose(file_fp); |
623 |
} |
624 |
out_profile: ; |
625 |
|
626 |
if (load_manager) { |
627 |
FILE *file_fp, *proc_fp; |
628 |
const char *policy_src = disk_policy_manager; |
629 |
if ((file_fp = read_from_stdin ? stdin : fopen(policy_src, "r")) == NULL) { |
630 |
fprintf(stderr, "Can't open %s\n", policy_src); |
631 |
goto out_system; |
632 |
} |
633 |
if ((proc_fp = fopen(proc_policy_manager, "w")) == NULL) { |
634 |
fprintf(stderr, "Can't open %s\n", proc_policy_manager); |
635 |
fclose(file_fp); |
636 |
goto out_manager; |
637 |
} |
638 |
get(); |
639 |
while (freadline(file_fp)) { |
640 |
if (shared_buffer[0]) fprintf(proc_fp, "%s\n", shared_buffer); |
641 |
} |
642 |
put(); |
643 |
fclose(proc_fp); |
644 |
fclose(file_fp); |
645 |
} |
646 |
out_manager: ; |
647 |
|
648 |
if (load_system_policy) { |
649 |
FILE *file_fp, *proc_fp; |
650 |
const char *policy_src = disk_policy_system_policy; |
651 |
if ((file_fp = read_from_stdin ? stdin : fopen(policy_src, "r")) == NULL) { |
652 |
fprintf(stderr, "Can't open %s\n", policy_src); |
653 |
goto out_system; |
654 |
} |
655 |
if ((proc_fp = fopen(proc_policy_system_policy, "w")) == NULL) { |
656 |
fprintf(stderr, "Can't open %s\n", proc_policy_system_policy); |
657 |
fclose(file_fp); |
658 |
goto out_system; |
659 |
} |
660 |
if (refresh_policy) { |
661 |
FILE *proc_clear_fp = fopen(proc_policy_system_policy, "r"); |
662 |
if (!proc_clear_fp) { |
663 |
fprintf(stderr, "Can't open %s\n", proc_policy_system_policy); |
664 |
fclose(file_fp); |
665 |
fclose(proc_fp); |
666 |
goto out_system; |
667 |
} |
668 |
get(); |
669 |
while (freadline(proc_clear_fp)) { |
670 |
if (shared_buffer[0]) fprintf(proc_fp, "delete %s\n", shared_buffer); |
671 |
} |
672 |
put(); |
673 |
fclose(proc_clear_fp); |
674 |
fflush(proc_fp); |
675 |
} |
676 |
get(); |
677 |
while (freadline(file_fp)) { |
678 |
if (shared_buffer[0]) fprintf(proc_fp, "%s\n", shared_buffer); |
679 |
} |
680 |
put(); |
681 |
fclose(proc_fp); |
682 |
fclose(file_fp); |
683 |
} |
684 |
out_system: ; |
685 |
|
686 |
if (load_exception_policy) { |
687 |
FILE *file_fp, *proc_fp; |
688 |
const char *policy_src = disk_policy_exception_policy; |
689 |
if ((file_fp = read_from_stdin ? stdin : fopen(policy_src, "r")) == NULL) { |
690 |
fprintf(stderr, "Can't open %s\n", policy_src); |
691 |
goto out_exception; |
692 |
} |
693 |
if ((proc_fp = fopen(proc_policy_exception_policy, "w")) == NULL) { |
694 |
fprintf(stderr, "Can't open %s\n", proc_policy_exception_policy); |
695 |
fclose(file_fp); |
696 |
goto out_exception; |
697 |
} |
698 |
if (refresh_policy) { |
699 |
FILE *proc_clear_fp = fopen(proc_policy_exception_policy, "r"); |
700 |
if (!proc_clear_fp) { |
701 |
fprintf(stderr, "Can't open %s\n", proc_policy_exception_policy); |
702 |
fclose(file_fp); |
703 |
fclose(proc_fp); |
704 |
goto out_exception; |
705 |
} |
706 |
get(); |
707 |
while (freadline(proc_clear_fp)) { |
708 |
if (shared_buffer[0]) fprintf(proc_fp, "delete %s\n", shared_buffer); |
709 |
} |
710 |
put(); |
711 |
fclose(proc_clear_fp); |
712 |
fflush(proc_fp); |
713 |
} |
714 |
get(); |
715 |
while (freadline(file_fp)) { |
716 |
if (shared_buffer[0]) fprintf(proc_fp, "%s\n", shared_buffer); |
717 |
} |
718 |
put(); |
719 |
fclose(proc_fp); |
720 |
fclose(file_fp); |
721 |
} |
722 |
out_exception: ; |
723 |
|
724 |
if (load_domain_policy) { |
725 |
int new_index; |
726 |
const char *policy_src = read_from_stdin ? NULL : disk_policy_domain_policy; |
727 |
FILE *proc_fp = fopen(proc_policy_domain_policy, "w"); |
728 |
struct path_info reserved; |
729 |
reserved.name = ""; |
730 |
fill_path_info(&reserved); |
731 |
if (!proc_fp) { |
732 |
fprintf(stderr, "Can't open %s\n", proc_policy_domain_policy); |
733 |
goto out_domain; |
734 |
} |
735 |
ReadDomainPolicy(policy_src); |
736 |
SwapDomainList(); |
737 |
ReadDomainPolicy(proc_policy_domain_policy); |
738 |
SwapDomainList(); |
739 |
if (domain_list_count == 0) { |
740 |
fprintf(stderr, "Can't open %s\n", policy_src); |
741 |
fclose(proc_fp); |
742 |
goto out_domain; |
743 |
} |
744 |
for (new_index = 0; new_index < domain_list_count; new_index++) { |
745 |
const char *domainname = DomainName(new_index); |
746 |
const struct path_info **new_string_ptr = domain_list[new_index].string_ptr; |
747 |
const int new_string_count = domain_list[new_index].string_count; |
748 |
int old_index; |
749 |
int i, j; |
750 |
SwapDomainList(); old_index = FindDomain(domainname, 0, 0); SwapDomainList(); |
751 |
if (refresh_policy && old_index >= 0) { |
752 |
/* Old policy for this domain found. */ |
753 |
const struct path_info **old_string_ptr = shadow_domain_list[old_index].string_ptr; |
754 |
const int old_string_count = shadow_domain_list[old_index].string_count; |
755 |
fprintf(proc_fp, "select %s\n", domainname); |
756 |
for (j = 0; j < old_string_count; j++) { |
757 |
for (i = 0; i < new_string_count; i++) { |
758 |
if (new_string_ptr[i] == old_string_ptr[j]) break; |
759 |
} |
760 |
/* Delete this entry from old policy if not found in new policy. */ |
761 |
if (i == new_string_count) fprintf(proc_fp, "delete %s\n", old_string_ptr[j]->name); |
762 |
} |
763 |
} else { |
764 |
/* Old policy for this domain not found or Append to old policy. */ |
765 |
fprintf(proc_fp, "%s\n", domainname); |
766 |
} |
767 |
for (i = 0; i < new_string_count; i++) fprintf(proc_fp, "%s\n", new_string_ptr[i]->name); |
768 |
if (old_index >= 0) shadow_domain_list[old_index].domainname = &reserved; /* Don't delete this domain later. */ |
769 |
} |
770 |
if (refresh_policy) { |
771 |
int old_index; |
772 |
/* Delete all domains that are not defined in new policy. */ |
773 |
for (old_index = 0; old_index < shadow_domain_list_count; old_index++) { |
774 |
if (shadow_domain_list[old_index].domainname != &reserved) fprintf(proc_fp, "delete %s\n", shadow_domain_list[old_index].domainname->name); |
775 |
} |
776 |
} |
777 |
fclose(proc_fp); |
778 |
} |
779 |
out_domain: ; |
780 |
|
781 |
return 0; |
782 |
} |
783 |
|
784 |
/***** loadpolicy end *****/ |
785 |
|
786 |
/***** editpolicy start *****/ |
787 |
|
788 |
static const char *policy_file = DOMAIN_POLICY_FILE; |
789 |
static const char *list_caption = NULL; |
790 |
static char *current_domain = NULL; |
791 |
|
792 |
static int current_screen = SCREEN_DOMAIN_LIST; |
793 |
|
794 |
// List for generic policy. |
795 |
static char **generic_acl_list = NULL; |
796 |
static int generic_acl_list_count = 0; |
797 |
static unsigned char *generic_acl_list_selected = NULL; |
798 |
|
799 |
static struct domain_keeper_entry *domain_keeper_list = NULL; |
800 |
static int domain_keeper_list_len = 0; |
801 |
static struct domain_initializer_entry *domain_initializer_list = NULL; |
802 |
static int domain_initializer_list_len = 0; |
803 |
|
804 |
/////////////////////////// ACL HANDLER ////////////////////////////// |
805 |
|
806 |
static const struct domain_keeper_entry *IsDomainKeeper(const struct path_info *domainname, const char *program) { |
807 |
int i; |
808 |
const struct domain_keeper_entry *flag = NULL; |
809 |
struct path_info last_name; |
810 |
if ((last_name.name = strrchr(domainname->name, ' ')) != NULL) last_name.name++; |
811 |
else last_name.name = domainname->name; |
812 |
fill_path_info(&last_name); |
813 |
for (i = 0; i < domain_keeper_list_len; i++) { |
814 |
struct domain_keeper_entry *ptr = &domain_keeper_list[i]; |
815 |
if (!ptr->is_last_name) { |
816 |
if (pathcmp(ptr->domainname, domainname)) continue; |
817 |
} else { |
818 |
if (pathcmp(ptr->domainname, &last_name)) continue; |
819 |
} |
820 |
if (ptr->program && strcmp(ptr->program->name, program)) continue; |
821 |
if (ptr->is_not) return NULL; |
822 |
flag = ptr; |
823 |
} |
824 |
return flag; |
825 |
} |
826 |
|
827 |
static const struct domain_initializer_entry *IsDomainInitializer(const struct path_info *domainname, const char *program) { |
828 |
int i; |
829 |
const struct domain_initializer_entry *flag = NULL; |
830 |
struct path_info last_name; |
831 |
if ((last_name.name = strrchr(domainname->name, ' ')) != NULL) last_name.name++; |
832 |
else last_name.name = domainname->name; |
833 |
fill_path_info(&last_name); |
834 |
for (i = 0; i < domain_initializer_list_len; i++) { |
835 |
struct domain_initializer_entry *ptr = &domain_initializer_list[i]; |
836 |
if (ptr->domainname) { |
837 |
if (!ptr->is_last_name) { |
838 |
if (pathcmp(ptr->domainname, domainname)) continue; |
839 |
} else { |
840 |
if (pathcmp(ptr->domainname, &last_name)) continue; |
841 |
} |
842 |
} |
843 |
if (strcmp(ptr->program->name, program)) continue; |
844 |
if (ptr->is_not) return NULL; |
845 |
flag = ptr; |
846 |
} |
847 |
return flag; |
848 |
} |
849 |
|
850 |
/////////////////////////// UTILITY FUNCTIONS ////////////////////////////// |
851 |
|
852 |
static int offline_mode = 0; |
853 |
static int persistent_fd = EOF; |
854 |
|
855 |
static void SendFD(char *data, int *fd) { |
856 |
struct msghdr msg; |
857 |
struct iovec iov = { data, strlen(data) }; |
858 |
char cmsg_buf[CMSG_SPACE(sizeof(int))]; |
859 |
struct cmsghdr *cmsg = (struct cmsghdr *) cmsg_buf; |
860 |
memset(&msg, 0, sizeof(msg)); |
861 |
msg.msg_iov = &iov; |
862 |
msg.msg_iovlen = 1; |
863 |
msg.msg_control = cmsg_buf; |
864 |
msg.msg_controllen = sizeof(cmsg_buf); |
865 |
cmsg->cmsg_level = SOL_SOCKET; |
866 |
cmsg->cmsg_type = SCM_RIGHTS; |
867 |
msg.msg_controllen = cmsg->cmsg_len = CMSG_LEN(sizeof(int)); |
868 |
memmove(CMSG_DATA(cmsg), fd, sizeof(int)); |
869 |
sendmsg(persistent_fd, &msg, 0); |
870 |
close(*fd); |
871 |
} |
872 |
|
873 |
static FILE *open_read(const char *filename) { |
874 |
if (offline_mode) { |
875 |
char request[1024]; |
876 |
int fd[2]; |
877 |
FILE *fp; |
878 |
if (socketpair(PF_UNIX, SOCK_STREAM, 0, fd)) { |
879 |
fprintf(stderr, "socketpair()\n"); |
880 |
exit(1); |
881 |
} |
882 |
if (shutdown(fd[0], SHUT_WR) || (fp = fdopen(fd[0], "r")) == NULL) { |
883 |
close(fd[1]); close(fd[0]); |
884 |
exit(1); |
885 |
} |
886 |
memset(request, 0, sizeof(request)); |
887 |
snprintf(request, sizeof(request) - 1, "GET %s", filename); |
888 |
SendFD(request, &fd[1]); |
889 |
return fp; |
890 |
} else { |
891 |
return fopen(filename, "r"); |
892 |
} |
893 |
} |
894 |
|
895 |
static FILE *open_write(const char *filename) { |
896 |
if (offline_mode) { |
897 |
char request[1024]; |
898 |
int fd[2]; |
899 |
if (socketpair(PF_UNIX, SOCK_STREAM, 0, fd)) { |
900 |
fprintf(stderr, "socketpair()\n"); |
901 |
exit(1); |
902 |
} |
903 |
if (shutdown(fd[0], SHUT_RD)) { |
904 |
close(fd[1]); close(fd[0]); |
905 |
exit(1); |
906 |
} |
907 |
memset(request, 0, sizeof(request)); |
908 |
snprintf(request, sizeof(request) - 1, "POST %s", filename); |
909 |
SendFD(request, &fd[1]); |
910 |
return fdopen(fd[0], "w"); |
911 |
} else { |
912 |
return fdopen(open(filename, O_WRONLY), "w"); |
913 |
} |
914 |
} |
915 |
|
916 |
static void ReadGenericPolicy(void) { |
917 |
FILE *fp; |
918 |
while (generic_acl_list_count) free(generic_acl_list[--generic_acl_list_count]); |
919 |
if ((fp = open_read(policy_file)) != NULL) { |
920 |
if (current_screen == SCREEN_ACL_LIST) { |
921 |
int flag = 0; |
922 |
get(); |
923 |
while (freadline(fp)) { |
924 |
if (IsDomainDef(shared_buffer)) { |
925 |
flag = strcmp(shared_buffer, current_domain) == 0 ? 1 : 0; |
926 |
} else if (flag && shared_buffer[0] && strncmp(shared_buffer, KEYWORD_USE_PROFILE, KEYWORD_USE_PROFILE_LEN)) { |
927 |
if ((generic_acl_list = (char **) realloc(generic_acl_list, (generic_acl_list_count + 1) * sizeof(char *))) == NULL |
928 |
|| (generic_acl_list[generic_acl_list_count++] = strdup(shared_buffer)) == NULL) OutOfMemory(); |
929 |
} |
930 |
} |
931 |
put(); |
932 |
qsort(generic_acl_list, generic_acl_list_count, sizeof(char *), string_acl_compare); |
933 |
} else { |
934 |
get(); |
935 |
while (freadline(fp)) { |
936 |
if (!shared_buffer[0]) continue; |
937 |
if ((generic_acl_list = (char **) realloc(generic_acl_list, (generic_acl_list_count + 1) * sizeof(char *))) == NULL |
938 |
|| (generic_acl_list[generic_acl_list_count++] = strdup(shared_buffer)) == NULL) OutOfMemory(); |
939 |
} |
940 |
put(); |
941 |
qsort(generic_acl_list, generic_acl_list_count, sizeof(char *), string_compare); |
942 |
} |
943 |
fclose(fp); |
944 |
} |
945 |
generic_acl_list_selected = realloc(generic_acl_list_selected, generic_acl_list_count); |
946 |
if (generic_acl_list_count && !generic_acl_list_selected) OutOfMemory(); |
947 |
memset(generic_acl_list_selected, 0, generic_acl_list_count); |
948 |
} |
949 |
|
950 |
static int AddDomainInitializerEntry(const char *domainname, const char *program, const int is_not) { |
951 |
struct domain_initializer_entry *ptr; |
952 |
int is_last_name = 0; |
953 |
if (!IsCorrectPath(program, 1, 0, -1)) return -EINVAL; |
954 |
if (domainname) { |
955 |
if (IsCorrectPath(domainname, 1, -1, -1)) { |
956 |
is_last_name = 1; |
957 |
} else if (!IsCorrectDomain(domainname)) { |
958 |
return -EINVAL; |
959 |
} |
960 |
} |
961 |
if ((domain_initializer_list = (struct domain_initializer_entry *) realloc(domain_initializer_list, (domain_initializer_list_len + 1) * sizeof(struct domain_initializer_entry))) == NULL) OutOfMemory(); |
962 |
ptr = &domain_initializer_list[domain_initializer_list_len++]; |
963 |
memset(ptr, 0, sizeof(struct domain_initializer_entry)); |
964 |
if ((ptr->program = SaveName(program)) == NULL) OutOfMemory(); |
965 |
if (domainname && (ptr->domainname = SaveName(domainname)) == NULL) OutOfMemory(); |
966 |
ptr->is_not = is_not; |
967 |
ptr->is_last_name = is_last_name; |
968 |
return 0; |
969 |
} |
970 |
|
971 |
static int AddDomainInitializerPolicy(char *data, const int is_not) { |
972 |
char *cp = strstr(data, " from "); |
973 |
if (cp) { |
974 |
*cp = '\0'; |
975 |
return AddDomainInitializerEntry(cp + 6, data, is_not); |
976 |
} else { |
977 |
return AddDomainInitializerEntry(NULL, data, is_not); |
978 |
} |
979 |
} |
980 |
|
981 |
static int AddDomainKeeperEntry(const char *domainname, const char *program, const int is_not) { |
982 |
struct domain_keeper_entry *ptr; |
983 |
int is_last_name = 0; |
984 |
if (IsCorrectPath(domainname, 1, -1, -1)) { |
985 |
is_last_name = 1; |
986 |
} else if (!IsCorrectDomain(domainname)) { |
987 |
return -EINVAL; |
988 |
} |
989 |
if (program && !IsCorrectPath(program, 1, 0, -1)) return -EINVAL; |
990 |
if ((domain_keeper_list = (struct domain_keeper_entry *) realloc(domain_keeper_list, (domain_keeper_list_len + 1) * sizeof(struct domain_keeper_entry))) == NULL) OutOfMemory(); |
991 |
ptr = &domain_keeper_list[domain_keeper_list_len++]; |
992 |
memset(ptr, 0, sizeof(struct domain_keeper_entry)); |
993 |
if ((ptr->domainname = SaveName(domainname)) == NULL) OutOfMemory(); |
994 |
if (program && (ptr->program = SaveName(program)) == NULL) OutOfMemory(); |
995 |
ptr->is_not = is_not; |
996 |
ptr->is_last_name = is_last_name; |
997 |
return 0; |
998 |
} |
999 |
|
1000 |
static int AddDomainKeeperPolicy(char *data, const int is_not) { |
1001 |
char *cp = strstr(data, " from "); |
1002 |
if (cp) { |
1003 |
*cp = '\0'; |
1004 |
return AddDomainKeeperEntry(cp + 6, data, is_not); |
1005 |
} else { |
1006 |
return AddDomainKeeperEntry(data, NULL, is_not); |
1007 |
} |
1008 |
} |
1009 |
|
1010 |
static int AddPathGroupEntry(const char *group_name, const char *member_name, const int is_delete) { |
1011 |
const struct path_info *saved_group_name, *saved_member_name; |
1012 |
int i, j; |
1013 |
struct path_group_entry *group = NULL; |
1014 |
if (!IsCorrectPath(group_name, 0, 0, 0) || |
1015 |
!IsCorrectPath(member_name, 0, 0, 0)) return -EINVAL; |
1016 |
if ((saved_group_name = SaveName(group_name)) == NULL || |
1017 |
(saved_member_name = SaveName(member_name)) == NULL) return -ENOMEM; |
1018 |
for (i = 0; i < path_group_list_len; i++) { |
1019 |
group = &path_group_list[i]; |
1020 |
if (saved_group_name != group->group_name) continue; |
1021 |
for (j = 0; j < group->member_name_len; j++) { |
1022 |
if (group->member_name[j] == saved_member_name) { |
1023 |
if (is_delete) { |
1024 |
while (j < group->member_name_len - 1) group->member_name[j] = group->member_name[j + 1]; |
1025 |
group->member_name_len--; |
1026 |
} else { |
1027 |
return 0; |
1028 |
} |
1029 |
} |
1030 |
} |
1031 |
break; |
1032 |
} |
1033 |
if (is_delete) return -ENOENT; |
1034 |
if (i == path_group_list_len) { |
1035 |
if ((path_group_list = (struct path_group_entry *) realloc(path_group_list, (path_group_list_len + 1) * sizeof(struct path_group_entry))) == NULL) OutOfMemory(); |
1036 |
group = &path_group_list[path_group_list_len++]; |
1037 |
memset(group, 0, sizeof(struct path_group_entry)); |
1038 |
group->group_name = saved_group_name; |
1039 |
} |
1040 |
if ((group->member_name = (const struct path_info **) realloc(group->member_name, (group->member_name_len + 1) * sizeof(const struct path_info *))) == NULL) OutOfMemory(); |
1041 |
group->member_name[group->member_name_len++] = saved_member_name; |
1042 |
return 0; |
1043 |
} |
1044 |
|
1045 |
static int AddPathGroupPolicy(char *data, const int is_delete) { |
1046 |
char *cp = strchr(data, ' '); |
1047 |
if (!cp) return -EINVAL; |
1048 |
*cp++ = '\0'; |
1049 |
return AddPathGroupEntry(data, cp, is_delete); |
1050 |
} |
1051 |
|
1052 |
static struct path_group_entry *FindPathGroup(const char *group_name) { |
1053 |
int i; |
1054 |
for (i = 0; i < path_group_list_len; i++) { |
1055 |
if (strcmp(group_name, path_group_list[i].group_name->name) == 0) return &path_group_list[i]; |
1056 |
} |
1057 |
return NULL; |
1058 |
} |
1059 |
|
1060 |
static int parse_ip(const char *address, struct ip_address_entry *entry) { |
1061 |
unsigned int min[8], max[8]; |
1062 |
int i, j; |
1063 |
memset(entry, 0, sizeof(*entry)); |
1064 |
i = sscanf(address, "%u.%u.%u.%u-%u.%u.%u.%u", &min[0], &min[1], &min[2], &min[3], &max[0], &max[1], &max[2], &max[3]); |
1065 |
if (i == 4) for (j = 0; j < 4; j++) max[j] = min[j]; |
1066 |
if (i == 4 || i == 8) { |
1067 |
for (j = 0; j < 4; j++) { |
1068 |
entry->min[j] = (u8) min[j]; |
1069 |
entry->max[j] = (u8) max[j]; |
1070 |
} |
1071 |
return 0; |
1072 |
} |
1073 |
i = sscanf(address, "%X:%X:%X:%X:%X:%X:%X:%X-%X:%X:%X:%X:%X:%X:%X:%X", |
1074 |
&min[0], &min[1], &min[2], &min[3], &min[4], &min[5], &min[6], &min[7], |
1075 |
&max[0], &max[1], &max[2], &max[3], &max[4], &max[5], &max[6], &max[7]); |
1076 |
if (i == 8) for (j = 0; j < 8; j++) max[j] = min[j]; |
1077 |
if (i == 8 || i == 16) { |
1078 |
for (j = 0; j < 8; j++) { |
1079 |
entry->min[j * 2] = (u8) (min[j] >> 8); entry->min[j * 2 + 1] = (u8) min[j]; |
1080 |
entry->min[j * 2] = (u8) (min[j] >> 8); entry->min[j * 2 + 1] = (u8) min[j]; |
1081 |
} |
1082 |
entry->is_ipv6 = 1; |
1083 |
return 0; |
1084 |
} |
1085 |
return -EINVAL; |
1086 |
} |
1087 |
|
1088 |
static int AddAddressGroupEntry(const char *group_name, const char *member_name, const int is_delete) { |
1089 |
const struct path_info *saved_group_name; |
1090 |
int i, j; |
1091 |
struct ip_address_entry entry; |
1092 |
struct address_group_entry *group = NULL; |
1093 |
if (parse_ip(member_name, &entry)) return -EINVAL; |
1094 |
if (!IsCorrectPath(group_name, 0, 0, 0)) return -EINVAL; |
1095 |
if ((saved_group_name = SaveName(group_name)) == NULL) return -ENOMEM; |
1096 |
for (i = 0; i < address_group_list_len; i++) { |
1097 |
group = &address_group_list[i]; |
1098 |
if (saved_group_name != group->group_name) continue; |
1099 |
for (j = 0; j < group->member_name_len; j++) { |
1100 |
if (memcmp(&group->member_name[j], &entry, sizeof(entry)) == 0) { |
1101 |
if (is_delete) { |
1102 |
while (j < group->member_name_len - 1) group->member_name[j] = group->member_name[j + 1]; |
1103 |
group->member_name_len--; |
1104 |
} else { |
1105 |
return 0; |
1106 |
} |
1107 |
} |
1108 |
} |
1109 |
break; |
1110 |
} |
1111 |
if (is_delete) return -ENOENT; |
1112 |
if (i == address_group_list_len) { |
1113 |
if ((address_group_list = (struct address_group_entry *) realloc(address_group_list, (address_group_list_len + 1) * sizeof(struct address_group_entry))) == NULL) OutOfMemory(); |
1114 |
group = &address_group_list[address_group_list_len++]; |
1115 |
memset(group, 0, sizeof(struct address_group_entry)); |
1116 |
group->group_name = saved_group_name; |
1117 |
} |
1118 |
if ((group->member_name = (struct ip_address_entry *) realloc(group->member_name, (group->member_name_len + 1) * sizeof(const struct ip_address_entry))) == NULL) OutOfMemory(); |
1119 |
group->member_name[group->member_name_len++] = entry; |
1120 |
return 0; |
1121 |
} |
1122 |
|
1123 |
static int AddAddressGroupPolicy(char *data, const int is_delete) { |
1124 |
char *cp = strchr(data, ' '); |
1125 |
if (!cp) return -EINVAL; |
1126 |
*cp++ = '\0'; |
1127 |
return AddAddressGroupEntry(data, cp, is_delete); |
1128 |
} |
1129 |
|
1130 |
static struct address_group_entry *FindAddressGroup(const char *group_name) { |
1131 |
int i; |
1132 |
for (i = 0; i < address_group_list_len; i++) { |
1133 |
if (strcmp(group_name, address_group_list[i].group_name->name) == 0) return &address_group_list[i]; |
1134 |
} |
1135 |
return NULL; |
1136 |
} |
1137 |
|
1138 |
static void AssignDomainInitializerSource(const struct path_info *domainname, const char *program) { |
1139 |
if (IsDomainInitializer(domainname, program)) { |
1140 |
get(); |
1141 |
memset(shared_buffer, 0, shared_buffer_len); |
1142 |
snprintf(shared_buffer, shared_buffer_len - 1, "%s %s", domainname->name, program); |
1143 |
NormalizeLine(shared_buffer); |
1144 |
if (FindOrAssignNewDomain(shared_buffer, 1, 0) == EOF) OutOfMemory(); |
1145 |
put(); |
1146 |
} |
1147 |
} |
1148 |
|
1149 |
static int domainname_attribute_compare(const void *a, const void *b) { |
1150 |
const int k = strcmp(((struct domain_info *) a)->domainname->name, ((struct domain_info *) b)->domainname->name); |
1151 |
if (k > 0 || (k == 0 && ((struct domain_info *) a)->is_domain_initializer_source < ((struct domain_info *) b)->is_domain_initializer_source)) return 1; |
1152 |
return k; |
1153 |
} |
1154 |
|
1155 |
static int unnumbered_domain_count = 0; |
1156 |
|
1157 |
static void ReadDomainAndExceptionPolicy(void) { |
1158 |
FILE *fp; |
1159 |
int i, j; |
1160 |
ClearDomainPolicy(); |
1161 |
domain_keeper_list_len = 0; |
1162 |
domain_initializer_list_len = 0; |
1163 |
while (path_group_list_len) free(path_group_list[--path_group_list_len].member_name); |
1164 |
//while (address_group_list_len) free(address_group_list[--address_group_list_len].member_name); |
1165 |
address_group_list_len = 0; |
1166 |
FindOrAssignNewDomain(ROOT_NAME, 0, 0); |
1167 |
|
1168 |
// Load domain_initializer list, domain_keeper list. |
1169 |
if ((fp = open_read(EXCEPTION_POLICY_FILE)) != NULL) { |
1170 |
get(); |
1171 |
while (freadline(fp)) { |
1172 |
if (strncmp(shared_buffer, KEYWORD_INITIALIZE_DOMAIN, KEYWORD_INITIALIZE_DOMAIN_LEN) == 0) { |
1173 |
AddDomainInitializerPolicy(shared_buffer + KEYWORD_INITIALIZE_DOMAIN_LEN, 0); |
1174 |
} else if (strncmp(shared_buffer, KEYWORD_NO_INITIALIZE_DOMAIN, KEYWORD_NO_INITIALIZE_DOMAIN_LEN) == 0) { |
1175 |
AddDomainInitializerPolicy(shared_buffer + KEYWORD_NO_INITIALIZE_DOMAIN_LEN, 1); |
1176 |
} else if (strncmp(shared_buffer, KEYWORD_KEEP_DOMAIN, KEYWORD_KEEP_DOMAIN_LEN) == 0) { |
1177 |
AddDomainKeeperPolicy(shared_buffer + KEYWORD_KEEP_DOMAIN_LEN, 0); |
1178 |
} else if (strncmp(shared_buffer, KEYWORD_NO_KEEP_DOMAIN, KEYWORD_NO_KEEP_DOMAIN_LEN) == 0) { |
1179 |
AddDomainKeeperPolicy(shared_buffer + KEYWORD_NO_KEEP_DOMAIN_LEN, 1); |
1180 |
} else if (strncmp(shared_buffer, KEYWORD_PATH_GROUP, KEYWORD_PATH_GROUP_LEN) == 0) { |
1181 |
AddPathGroupPolicy(shared_buffer + KEYWORD_PATH_GROUP_LEN, 0); |
1182 |
} else if (strncmp(shared_buffer, KEYWORD_ADDRESS_GROUP, KEYWORD_ADDRESS_GROUP_LEN) == 0) { |
1183 |
AddAddressGroupPolicy(shared_buffer + KEYWORD_ADDRESS_GROUP_LEN, 0); |
1184 |
} |
1185 |
} |
1186 |
put(); |
1187 |
fclose(fp); |
1188 |
} |
1189 |
|
1190 |
// Load all domain list. |
1191 |
if ((fp = open_read(DOMAIN_POLICY_FILE)) != NULL) { |
1192 |
int index = EOF; |
1193 |
get(); |
1194 |
while (freadline(fp)) { |
1195 |
char *cp, *cp2; |
1196 |
unsigned int profile; |
1197 |
if (IsDomainDef(shared_buffer)) { |
1198 |
index = FindOrAssignNewDomain(shared_buffer, 0, 0); |
1199 |
} else if (index >= 0 && ((atoi(shared_buffer) & 1) == 1 || strncmp(shared_buffer, "allow_execute ", 14) == 0) && (cp = strchr(shared_buffer, ' ')) != NULL) { |
1200 |
cp++; |
1201 |
if ((cp2 = strchr(cp, ' ')) != NULL) *cp2 = '\0'; |
1202 |
if (*cp == '@' || IsCorrectPath(cp, 1, 0, -1)) AddStringEntry(cp, index); |
1203 |
} else if (index >= 0 && sscanf(shared_buffer, "use_profile %u", &profile) == 1) { |
1204 |
domain_list[index].profile = (unsigned char) profile; |
1205 |
} |
1206 |
} |
1207 |
put(); |
1208 |
fclose(fp); |
1209 |
} |
1210 |
|
1211 |
{ |
1212 |
int index, max_index = domain_list_count; |
1213 |
|
1214 |
// Find unreachable domains. |
1215 |
for (index = 0; index < max_index; index++) { |
1216 |
char *cp; |
1217 |
get(); |
1218 |
memset(shared_buffer, 0, shared_buffer_len); |
1219 |
snprintf(shared_buffer, shared_buffer_len - 1, "%s", DomainName(index)); |
1220 |
while ((cp = strrchr(shared_buffer, ' ')) != NULL) { |
1221 |
const struct domain_initializer_entry *domain_initializer; |
1222 |
const struct domain_keeper_entry *domain_keeper; |
1223 |
struct path_info parent; |
1224 |
*cp++ = '\0'; |
1225 |
parent.name = shared_buffer; |
1226 |
fill_path_info(&parent); |
1227 |
if ((domain_initializer = IsDomainInitializer(&parent, cp)) != NULL) { |
1228 |
if (parent.total_len == ROOT_NAME_LEN) break; /* Initializer under <kernel> is reachable. */ |
1229 |
domain_list[index].domain_initializer = domain_initializer; |
1230 |
domain_list[index].domain_keeper = NULL; |
1231 |
} else if ((domain_keeper = IsDomainKeeper(&parent, cp)) != NULL) { |
1232 |
domain_list[index].domain_initializer = NULL; |
1233 |
domain_list[index].domain_keeper = domain_keeper; |
1234 |
} |
1235 |
} |
1236 |
put(); |
1237 |
if (domain_list[index].domain_initializer || domain_list[index].domain_keeper) domain_list[index].is_domain_unreachable = 1; |
1238 |
} |
1239 |
|
1240 |
// Find domain initializer target domains. |
1241 |
for (index = 0; index < max_index; index++) { |
1242 |
char *cp; |
1243 |
if ((cp = strchr(DomainName(index), ' ')) != NULL && strchr(cp + 1, ' ') == NULL) { |
1244 |
for (i = 0; i < domain_initializer_list_len; i++) { |
1245 |
struct domain_initializer_entry *ptr = &domain_initializer_list[i]; |
1246 |
if (ptr->is_not) continue; |
1247 |
if (strcmp(ptr->program->name, cp + 1)) continue; |
1248 |
domain_list[index].is_domain_initializer_target = 1; |
1249 |
} |
1250 |
} |
1251 |
} |
1252 |
|
1253 |
// Find domain keeper domains. |
1254 |
for (index = 0; index < max_index; index++) { |
1255 |
for (i = 0; i < domain_keeper_list_len; i++) { |
1256 |
struct domain_keeper_entry *ptr = &domain_keeper_list[i]; |
1257 |
if (ptr->is_not) continue; |
1258 |
if (!ptr->is_last_name) { |
1259 |
if (pathcmp(ptr->domainname, domain_list[index].domainname)) continue; |
1260 |
} else { |
1261 |
char *cp = strrchr(domain_list[index].domainname->name, ' '); |
1262 |
if (!cp || strcmp(ptr->domainname->name, cp + 1)) continue; |
1263 |
} |
1264 |
domain_list[index].is_domain_keeper = 1; |
1265 |
} |
1266 |
} |
1267 |
|
1268 |
// Create domain initializer source domains. |
1269 |
for (index = 0; index < max_index; index++) { |
1270 |
const struct path_info *domainname = domain_list[index].domainname; |
1271 |
const struct path_info **string_ptr = domain_list[index].string_ptr; |
1272 |
const int max_count = domain_list[index].string_count; |
1273 |
if (domainname->total_len == ROOT_NAME_LEN) continue; // Don't create source domain under <kernel> because they will become target domains. |
1274 |
for (i = 0; i < max_count; i++) { |
1275 |
const struct path_info *cp = string_ptr[i]; |
1276 |
if (cp->name[0] == '@') { |
1277 |
struct path_group_entry *group = FindPathGroup(cp->name + 1); |
1278 |
if (group) { |
1279 |
for (j = 0; j < group->member_name_len; j++) AssignDomainInitializerSource(domainname, group->member_name[j]->name); |
1280 |
} |
1281 |
} else { |
1282 |
AssignDomainInitializerSource(domainname, cp->name); |
1283 |
} |
1284 |
} |
1285 |
} |
1286 |
|
1287 |
// Create missing parent domains. |
1288 |
for (index = 0; index < max_index; index++) { |
1289 |
char *cp; |
1290 |
get(); |
1291 |
memset(shared_buffer, 0, shared_buffer_len); |
1292 |
snprintf(shared_buffer, shared_buffer_len - 1, "%s", DomainName(index)); |
1293 |
while ((cp = strrchr(shared_buffer, ' ')) != NULL) { |
1294 |
*cp = '\0'; |
1295 |
if (FindDomain(shared_buffer, 0, 0) != EOF) continue; |
1296 |
if (FindOrAssignNewDomain(shared_buffer, 0, 1) == EOF) OutOfMemory(); |
1297 |
} |
1298 |
put(); |
1299 |
} |
1300 |
|
1301 |
} |
1302 |
// Sort by domain name. |
1303 |
qsort(domain_list, domain_list_count, sizeof(struct domain_info), domainname_attribute_compare); |
1304 |
|
1305 |
// Assign domain numbers. |
1306 |
{ |
1307 |
int number = 0, index; |
1308 |
unnumbered_domain_count= 0; |
1309 |
for (index = 0; index < domain_list_count; index++) { |
1310 |
if (IsDeletedDomain(index) || IsInitializerSource(index)) { |
1311 |
domain_list[index].number = -1; |
1312 |
unnumbered_domain_count++; |
1313 |
} else { |
1314 |
domain_list[index].number = number++; |
1315 |
} |
1316 |
} |
1317 |
} |
1318 |
|
1319 |
domain_list_selected = realloc(domain_list_selected, domain_list_count); |
1320 |
if (domain_list_count && !domain_list_selected) OutOfMemory(); |
1321 |
memset(domain_list_selected, 0, domain_list_count); |
1322 |
} |
1323 |
|
1324 |
static void ShowCurrent(void); |
1325 |
|
1326 |
static int window_width = 0, window_height = 0; |
1327 |
static int current_y[MAXSCREEN], current_item_index[MAXSCREEN], list_item_count[MAXSCREEN]; |
1328 |
|
1329 |
static const int header_lines = 3; |
1330 |
static int body_lines = 0; |
1331 |
|
1332 |
static int max_eat_col[MAXSCREEN]; |
1333 |
static int eat_col = 0; |
1334 |
static int max_col = 0; |
1335 |
|
1336 |
static const char *eat(const char *str) { |
1337 |
while (*str && eat_col) { |
1338 |
str++; eat_col--; |
1339 |
} |
1340 |
return str; |
1341 |
} |
1342 |
|
1343 |
static void ShowList(void) { |
1344 |
const int offset = current_item_index[current_screen]; |
1345 |
int i, tmp_col; |
1346 |
if (current_screen == SCREEN_DOMAIN_LIST) list_item_count[SCREEN_DOMAIN_LIST] = domain_list_count; |
1347 |
else list_item_count[current_screen] = generic_acl_list_count; |
1348 |
clear(); |
1349 |
if (window_height < header_lines + 1) { |
1350 |
mvprintw(0, 0, "Please resize window. This program needs at least %d lines.\n", header_lines + 1); |
1351 |
refresh(); |
1352 |
return; |
1353 |
} |
1354 |
colorChange(colorHead(), ON); // add color |
1355 |
if (current_screen == SCREEN_DOMAIN_LIST) mvprintw(0, 0, "<<< Domain Transition Editor >>> %d domain%c '?' for help", list_item_count[SCREEN_DOMAIN_LIST] - unnumbered_domain_count, list_item_count[SCREEN_DOMAIN_LIST] - unnumbered_domain_count > 1 ? 's' : ' '); |
1356 |
else mvprintw(0, 0, "<<< %s Editor >>> %d entr%s '?' for help", list_caption, list_item_count[current_screen], list_item_count[current_screen] > 1 ? "ies" : "y"); |
1357 |
colorChange(colorHead(), OFF); // add color |
1358 |
eat_col = max_eat_col[current_screen]; |
1359 |
max_col = 0; |
1360 |
if (current_screen == SCREEN_ACL_LIST) { |
1361 |
get(); |
1362 |
memset(shared_buffer, 0, shared_buffer_len); |
1363 |
snprintf(shared_buffer, shared_buffer_len - 1, "%s", eat(current_domain)); |
1364 |
attrChange(A_REVERSE, ON); // add color --- 2007/11/27 changed |
1365 |
mvprintw(2, 0, "%s", shared_buffer); |
1366 |
attrChange(A_REVERSE, OFF); // add color --- 2007/11/27 changed |
1367 |
put(); |
1368 |
} |
1369 |
for (i = 0; i < body_lines; i++) { |
1370 |
const int index = offset + i; |
1371 |
eat_col = max_eat_col[current_screen]; |
1372 |
tmp_col = 0; |
1373 |
if (index >= list_item_count[current_screen]) break; |
1374 |
if (current_screen == SCREEN_DOMAIN_LIST) { |
1375 |
const struct domain_initializer_entry *domain_initializer; |
1376 |
const struct domain_keeper_entry *domain_keeper; |
1377 |
const char *sp, *cp; |
1378 |
const int number = domain_list[index].number; |
1379 |
if (number >= 0) mvprintw(header_lines + i, 0, "%c%4d:%3u %c%c%c ", domain_list_selected[index] ? '&' : ' ', number, domain_list[index].profile, IsKeeperDomain(index) ? '#' : ' ', IsInitializerTarget(index) ? '*' : ' ', IsDomainUnreachable(index) ? '!' : ' '); |
1380 |
else mvprintw(header_lines + i, 0, " "); |
1381 |
tmp_col += 14; |
1382 |
sp = DomainName(index); |
1383 |
while ((cp = strchr(sp, ' ')) != NULL) { printw("%s", eat(" ")); tmp_col += 4; sp = cp + 1; } |
1384 |
if (IsDeletedDomain(index)) { printw("%s", eat("( ")); tmp_col += 2; } |
1385 |
printw("%s", eat(sp)); tmp_col += strlen(sp); |
1386 |
if (IsDeletedDomain(index)) { printw("%s", eat(" )")); tmp_col += 2; } |
1387 |
if ((domain_initializer = domain_list[index].domain_initializer) != NULL) { |
1388 |
get(); |
1389 |
memset(shared_buffer, 0, shared_buffer_len); |
1390 |
if (domain_initializer->domainname) snprintf(shared_buffer, shared_buffer_len - 1, " ( " KEYWORD_INITIALIZE_DOMAIN "%s from %s )", domain_initializer->program->name, domain_initializer->domainname->name); |
1391 |
else snprintf(shared_buffer, shared_buffer_len - 1, " ( " KEYWORD_INITIALIZE_DOMAIN "%s )", domain_initializer->program->name); |
1392 |
printw("%s", eat(shared_buffer)); tmp_col += strlen(shared_buffer); |
1393 |
put(); |
1394 |
} else if ((domain_keeper = domain_list[index].domain_keeper) != NULL) { |
1395 |
get(); |
1396 |
memset(shared_buffer, 0, shared_buffer_len); |
1397 |
if (domain_keeper->program) snprintf(shared_buffer, shared_buffer_len - 1, " ( " KEYWORD_KEEP_DOMAIN "%s from %s )", domain_keeper->program->name, domain_keeper->domainname->name); |
1398 |
else snprintf(shared_buffer, shared_buffer_len - 1, " ( " KEYWORD_KEEP_DOMAIN "%s )", domain_keeper->domainname->name); |
1399 |
printw("%s", eat(shared_buffer)); tmp_col += strlen(shared_buffer); |
1400 |
put(); |
1401 |
} else if (IsInitializerSource(index)) { |
1402 |
int redirect_index; |
1403 |
get(); |
1404 |
memset(shared_buffer, 0, shared_buffer_len); |
1405 |
snprintf(shared_buffer, shared_buffer_len - 1, ROOT_NAME "%s", strrchr(DomainName(index), ' ')); |
1406 |
redirect_index = FindDomain(shared_buffer, 0, 0); |
1407 |
if (redirect_index >= 0) snprintf(shared_buffer, shared_buffer_len - 1, " ( -> %d )", domain_list[redirect_index].number); |
1408 |
else snprintf(shared_buffer, shared_buffer_len - 1, " ( -> Not Found )"); |
1409 |
printw("%s", eat(shared_buffer)); tmp_col += strlen(shared_buffer); |
1410 |
put(); |
1411 |
} |
1412 |
} else { |
1413 |
const char *cp = generic_acl_list[index]; |
1414 |
mvprintw(header_lines + i, 0, "%c%4d: %s", generic_acl_list_selected[index] ? '&' : ' ', index, eat(cp)); tmp_col += strlen(cp) + 7; |
1415 |
} |
1416 |
clrtoeol(); |
1417 |
tmp_col -= window_width; |
1418 |
if (tmp_col > max_col) max_col = tmp_col; |
1419 |
} |
1420 |
ShowCurrent(); |
1421 |
} |
1422 |
|
1423 |
static void ResizeWindow(void) { |
1424 |
getmaxyx(stdscr, window_height, window_width); |
1425 |
body_lines = window_height - header_lines; |
1426 |
if (body_lines <= current_y[current_screen]) current_y[current_screen] = body_lines - 1; |
1427 |
if (current_y[current_screen] < 0) current_y[current_screen] = 0; |
1428 |
} |
1429 |
|
1430 |
static void UpArrowKey(void) { |
1431 |
if (current_y[current_screen] > 0) { |
1432 |
current_y[current_screen]--; |
1433 |
ShowCurrent(); |
1434 |
} else if (current_item_index[current_screen] > 0) { |
1435 |
current_item_index[current_screen]--; |
1436 |
ShowList(); |
1437 |
} |
1438 |
} |
1439 |
|
1440 |
static void DownArrowKey(void) { |
1441 |
if (current_y[current_screen] < body_lines - 1) { |
1442 |
if (current_item_index[current_screen] + current_y[current_screen] < list_item_count[current_screen] - 1) { |
1443 |
current_y[current_screen]++; |
1444 |
ShowCurrent(); |
1445 |
} |
1446 |
} else if (current_item_index[current_screen] + current_y[current_screen] < list_item_count[current_screen] - 1) { |
1447 |
current_item_index[current_screen]++; |
1448 |
ShowList(); |
1449 |
} |
1450 |
} |
1451 |
|
1452 |
static void PageUpKey(void) { |
1453 |
if (current_item_index[current_screen] + current_y[current_screen] > body_lines) { |
1454 |
current_item_index[current_screen] -= body_lines; |
1455 |
if (current_item_index[current_screen] < 0) current_item_index[current_screen] = 0; |
1456 |
ShowList(); |
1457 |
} else if (current_item_index[current_screen] + current_y[current_screen] > 0) { |
1458 |
current_item_index[current_screen] = 0; |
1459 |
current_y[current_screen] = 0; |
1460 |
ShowList(); |
1461 |
} |
1462 |
} |
1463 |
|
1464 |
static void PageDownKey(void) { |
1465 |
if (list_item_count[current_screen] - current_item_index[current_screen] > body_lines) { |
1466 |
current_item_index[current_screen] += body_lines; |
1467 |
if (current_item_index[current_screen] + current_y[current_screen] > list_item_count[current_screen] - 1) current_y[current_screen] = list_item_count[current_screen] - 1 - current_item_index[current_screen]; |
1468 |
ShowList(); |
1469 |
} else if (current_item_index[current_screen] + current_y[current_screen] < list_item_count[current_screen] - 1) { |
1470 |
current_y[current_screen] = list_item_count[current_screen] - current_item_index[current_screen] - 1; |
1471 |
ShowCurrent(); |
1472 |
} |
1473 |
} |
1474 |
|
1475 |
static int GetCurrent(void) { |
1476 |
if (list_item_count[current_screen] == 0) return EOF; |
1477 |
if (current_item_index[current_screen] + current_y[current_screen] < 0 || current_item_index[current_screen] + current_y[current_screen] >= list_item_count[current_screen]) { |
1478 |
fprintf(stderr, "ERROR: current_item_index=%d current_y=%d\n", current_item_index[current_screen], current_y[current_screen]); |
1479 |
exit(127); |
1480 |
} |
1481 |
return current_item_index[current_screen] + current_y[current_screen]; |
1482 |
} |
1483 |
|
1484 |
/// add color start |
1485 |
#ifdef COLOR_ON |
1486 |
static int before_current[MAXSCREEN] = {-1, -1, -1, -1}; |
1487 |
static int before_y[MAXSCREEN] = {-1, -1, -1, -1}; |
1488 |
|
1489 |
static void LineDraw(void) { |
1490 |
int current = GetCurrent(); |
1491 |
int y, x; |
1492 |
|
1493 |
if (current == EOF) return; |
1494 |
|
1495 |
getyx(stdscr, y, x); |
1496 |
if (-1 < before_current[current_screen] && current != before_current[current_screen]){ |
1497 |
move(header_lines + before_y[current_screen], 0); |
1498 |
chgat(-1, A_NORMAL, NORMAL, NULL); |
1499 |
} |
1500 |
|
1501 |
move(y, x); |
1502 |
chgat(-1, A_NORMAL, colorCursor(), NULL); |
1503 |
touchwin(stdscr); |
1504 |
|
1505 |
before_current[current_screen] = current; |
1506 |
before_y[current_screen] = current_y[current_screen]; |
1507 |
} |
1508 |
#else |
1509 |
#define LineDraw() |
1510 |
#endif |
1511 |
/// add color end |
1512 |
|
1513 |
static void ShowCurrent(void) { |
1514 |
if (current_screen == SCREEN_DOMAIN_LIST) { |
1515 |
get(); |
1516 |
memset(shared_buffer, 0, shared_buffer_len); |
1517 |
eat_col = max_eat_col[current_screen]; |
1518 |
snprintf(shared_buffer, shared_buffer_len - 1, "%s", eat(DomainName(GetCurrent()))); |
1519 |
if (window_width < shared_buffer_len) shared_buffer[window_width] = '\0'; |
1520 |
move(2, 0); |
1521 |
clrtoeol(); |
1522 |
attrChange(A_REVERSE, ON); // add color |
1523 |
printw("%s", shared_buffer); |
1524 |
attrChange(A_REVERSE, OFF); // add color |
1525 |
put(); |
1526 |
} |
1527 |
move(header_lines + current_y[current_screen], 0); |
1528 |
LineDraw(); // add color |
1529 |
refresh(); |
1530 |
} |
1531 |
|
1532 |
static void AdjustCursorPos(const int item_count) { |
1533 |
if (item_count == 0) { |
1534 |
current_item_index[current_screen] = current_y[current_screen] = 0; |
1535 |
} else { |
1536 |
while (current_item_index[current_screen] + current_y[current_screen] >= item_count) { |
1537 |
if (current_y[current_screen] > 0) current_y[current_screen]--; |
1538 |
else if (current_item_index[current_screen] > 0) current_item_index[current_screen]--; |
1539 |
} |
1540 |
} |
1541 |
} |
1542 |
|
1543 |
static void SetCursorPos(const int index) { |
1544 |
while (index < current_y[current_screen] + current_item_index[current_screen]) { |
1545 |
if (current_y[current_screen] > 0) current_y[current_screen]--; |
1546 |
else current_item_index[current_screen]--; |
1547 |
} |
1548 |
while (index > current_y[current_screen] + current_item_index[current_screen]) { |
1549 |
if (current_y[current_screen] < body_lines - 1) current_y[current_screen]++; |
1550 |
else current_item_index[current_screen]++; |
1551 |
} |
1552 |
} |
1553 |
|
1554 |
static int count(const unsigned char *array, const int len) { |
1555 |
int i, c = 0; |
1556 |
for (i = 0; i < len; i++) if (array[i]) c++; |
1557 |
return c; |
1558 |
} |
1559 |
|
1560 |
static int SelectItem(const int current) { |
1561 |
if (current >= 0) { |
1562 |
int x, y; |
1563 |
if (current_screen == SCREEN_DOMAIN_LIST) { |
1564 |
if (IsDeletedDomain(current) || IsInitializerSource(current)) return 0; |
1565 |
domain_list_selected[current] ^= 1; |
1566 |
} else { |
1567 |
generic_acl_list_selected[current] ^= 1; |
1568 |
} |
1569 |
getyx(stdscr, y, x); |
1570 |
sttrSave(); // add color |
1571 |
ShowList(); |
1572 |
sttrRestore(); // add color |
1573 |
move(y, x); |
1574 |
return 1; |
1575 |
} |
1576 |
return 0; |
1577 |
} |
1578 |
|
1579 |
static int PathMatchesToPattern(const struct path_info *pathname0, const struct path_info *pattern0) { |
1580 |
//if (!pathname || !pattern) return 0; |
1581 |
const char *pathname = pathname0->name, *pattern = pattern0->name; |
1582 |
const int len = pattern0->const_len; |
1583 |
if (!pattern0->is_patterned) return !pathcmp(pathname0, pattern0); |
1584 |
if (pathname0->depth != pattern0->depth) return 0; |
1585 |
if (strncmp(pathname, pattern, len)) return 0; |
1586 |
pathname += len; pattern += len; |
1587 |
while (*pathname && *pattern) { |
1588 |
const char *pathname_delimiter = strchr(pathname, '/'), *pattern_delimiter = strchr(pattern, '/'); |
1589 |
if (!pathname_delimiter) pathname_delimiter = strchr(pathname, '\0'); |
1590 |
if (!pattern_delimiter) pattern_delimiter = strchr(pattern, '\0'); |
1591 |
if (!FileMatchesToPattern(pathname, pathname_delimiter, pattern, pattern_delimiter)) return 0; |
1592 |
pathname = *pathname_delimiter ? pathname_delimiter + 1 : pathname_delimiter; |
1593 |
pattern = *pattern_delimiter ? pattern_delimiter + 1 : pattern_delimiter; |
1594 |
} |
1595 |
while (*pattern == '\\' && (*(pattern + 1) == '*' || *(pattern + 1) == '@')) pattern += 2; |
1596 |
return (!*pathname && !*pattern); |
1597 |
} |
1598 |
|
1599 |
static void split_acl(char *data, struct path_info *arg1, struct path_info *arg2, struct path_info *arg3) { |
1600 |
/* data = word[0] word[1] ... word[n-1] word[n] if cond[0] cond[1] ... cond[m] */ |
1601 |
/* */ |
1602 |
/* arg1 = word[0] */ |
1603 |
/* arg2 = word[1] ... word[n-1] word[n] */ |
1604 |
/* arg3 = if cond[0] cond[1] ... cond[m] */ |
1605 |
char *cp; |
1606 |
arg1->name = data; |
1607 |
cp = strstr(data, " if "); |
1608 |
if (cp) { |
1609 |
char *cp2; |
1610 |
while ((cp2 = strstr(cp + 3, " if ")) != NULL) cp = cp2; |
1611 |
*cp++ = '\0'; |
1612 |
} else { |
1613 |
cp = ""; |
1614 |
} |
1615 |
arg3->name = cp; |
1616 |
cp = strchr(data, ' '); |
1617 |
if (cp) *cp++ = '\0'; |
1618 |
else cp = ""; |
1619 |
arg2->name = cp; |
1620 |
fill_path_info(arg1); |
1621 |
fill_path_info(arg2); |
1622 |
fill_path_info(arg3); |
1623 |
} |
1624 |
|
1625 |
static void try_optimize(const int current) { |
1626 |
char *cp; |
1627 |
const char *directive; |
1628 |
int directive_index, directive_len, index; |
1629 |
struct path_info sarg1, sarg2, sarg3; |
1630 |
struct path_info darg1, darg2, darg3; |
1631 |
#define max_optimize_directive_index 35 |
1632 |
static const char *directive_list[max_optimize_directive_index] = { |
1633 |
[0] = "1 ", |
1634 |
[1] = "2 ", |
1635 |
[2] = "3 ", |
1636 |
[3] = "4 ", |
1637 |
[4] = "5 ", |
1638 |
[5] = "6 ", |
1639 |
[6] = "7 ", |
1640 |
[7] = "allow_execute ", |
1641 |
[8] = "allow_read ", |
1642 |
[9] = "allow_write ", |
1643 |
[10] = "allow_read/write ", |
1644 |
[11] = "allow_create ", |
1645 |
[12] = "allow_unlink ", |
1646 |
[13] = "allow_mkdir ", |
1647 |
[14] = "allow_rmdir ", |
1648 |
[15] = "allow_mkfifo ", |
1649 |
[16] = "allow_mksock ", |
1650 |
[17] = "allow_mkblock ", |
1651 |
[18] = "allow_mkchar ", |
1652 |
[19] = "allow_truncate ", |
1653 |
[20] = "allow_symlink ", |
1654 |
[21] = "allow_link ", |
1655 |
[22] = "allow_rename ", |
1656 |
[23] = "allow_rewrite ", |
1657 |
[24] = "allow_argv0 ", |
1658 |
[25] = "allow_signal ", |
1659 |
[26] = "allow_network UDP bind ", |
1660 |
[27] = "allow_network UDP connect ", |
1661 |
[28] = "allow_network TCP bind ", |
1662 |
[29] = "allow_network TCP listen ", |
1663 |
[30] = "allow_network TCP connect ", |
1664 |
[31] = "allow_network TCP accept ", |
1665 |
[32] = "allow_network RAW bind ", |
1666 |
[33] = "allow_network RAW connect ", |
1667 |
[34] = "allow_env ", |
1668 |
}; |
1669 |
static int directive_list_len[max_optimize_directive_index]; |
1670 |
static int first = 1; |
1671 |
if (first) { |
1672 |
first = 0; |
1673 |
for (directive_index = 0; directive_index < max_optimize_directive_index; directive_index++) { |
1674 |
directive_list_len[directive_index] = strlen(directive_list[directive_index]); |
1675 |
} |
1676 |
} |
1677 |
if (current < 0) return; |
1678 |
cp = generic_acl_list[current]; |
1679 |
for (directive_index = 0; directive_index < max_optimize_directive_index; directive_index++) { |
1680 |
if (strncmp(cp, directive_list[directive_index], directive_list_len[directive_index]) == 0) break; |
1681 |
} |
1682 |
if (directive_index == max_optimize_directive_index) return; |
1683 |
cp = strdup(cp); |
1684 |
if (!cp) return; |
1685 |
|
1686 |
directive = directive_list[directive_index]; |
1687 |
directive_len = directive_list_len[directive_index]; |
1688 |
|
1689 |
split_acl(cp + directive_len, &sarg1, &sarg2, &sarg3); |
1690 |
|
1691 |
get(); |
1692 |
for (index = 0; index < list_item_count[current_screen]; index++) { |
1693 |
const char *cp = generic_acl_list[index]; |
1694 |
if (index == current) continue; |
1695 |
if (generic_acl_list_selected[index]) continue; |
1696 |
if (strncmp(cp, directive, directive_len)) continue; |
1697 |
memmove(shared_buffer, cp, shared_buffer_len - 1); |
1698 |
|
1699 |
split_acl(shared_buffer + directive_len, &darg1, &darg2, &darg3); |
1700 |
|
1701 |
/* Compare condition part. */ |
1702 |
if (pathcmp(&sarg3, &darg3)) continue; |
1703 |
|
1704 |
/* Compare first word. */ |
1705 |
if (directive_index < 24) { |
1706 |
if (pathcmp(&sarg1, &darg1)) { |
1707 |
const int may_use_pattern = !darg1.is_patterned |
1708 |
&& (directive_index != 0) && (directive_index != 2) && (directive_index != 4) && (directive_index != 6) && (directive_index != 7); |
1709 |
if (darg1.name[0] == '@') continue; |
1710 |
if (sarg1.name[0] == '@') { |
1711 |
/* path_group component. */ |
1712 |
int i; |
1713 |
struct path_group_entry *group = FindPathGroup(sarg1.name + 1); |
1714 |
if (!group) continue; |
1715 |
for (i = 0; i < group->member_name_len; i++) { |
1716 |
const struct path_info *member_name = group->member_name[i]; |
1717 |
if (!pathcmp(member_name, &darg1)) break; |
1718 |
if (may_use_pattern && PathMatchesToPattern(&darg1, member_name)) break; |
1719 |
} |
1720 |
if (i == group->member_name_len) continue; |
1721 |
} else { |
1722 |
/* Pathname component. */ |
1723 |
if (!may_use_pattern || !PathMatchesToPattern(&darg1, &sarg1)) continue; |
1724 |
} |
1725 |
} |
1726 |
} else if (directive_index == 24) { |
1727 |
/* Pathname component. */ |
1728 |
if (pathcmp(&sarg1, &darg1)) { |
1729 |
/* allow_argv0 doesn't support path_group. */ |
1730 |
if (darg1.name[0] == '@' || darg1.is_patterned || !PathMatchesToPattern(&darg1, &sarg1)) continue; |
1731 |
} |
1732 |
} else if (directive_index == 25) { |
1733 |
/* Signal number component. */ |
1734 |
if (strcmp(sarg1.name, darg1.name)) continue; |
1735 |
} else if (directive_index < 34) { |
1736 |
struct ip_address_entry dentry; |
1737 |
if (parse_ip(darg1.name, &dentry)) continue; |
1738 |
if (sarg1.name[0] == '@') { |
1739 |
/* IP address group component. */ |
1740 |
int i; |
1741 |
struct address_group_entry *group = FindAddressGroup(sarg1.name + 1); |
1742 |
if (!group) continue; |
1743 |
for (i = 0; i < group->member_name_len; i++) { |
1744 |
struct ip_address_entry *sentry = &group->member_name[i]; |
1745 |
if (sentry->is_ipv6 == dentry.is_ipv6 && memcmp(sentry->min, dentry.min, 16) <= 0 && memcmp(dentry.max, sentry->max, 16) <= 0) break; |
1746 |
} |
1747 |
if (i == group->member_name_len) continue; |
1748 |
} else { |
1749 |
/* IP address component. */ |
1750 |
struct ip_address_entry sentry; |
1751 |
if (parse_ip(sarg1.name, &sentry)) continue; |
1752 |
if (sentry.is_ipv6 != dentry.is_ipv6 || memcmp(dentry.min, sentry.min, 16) < 0 || memcmp(sentry.max, dentry.max, 16) < 0) continue; |
1753 |
} |
1754 |
} else { |
1755 |
/* An environemnt variable name component. */ |
1756 |
if (pathcmp(&sarg1, &darg1)) { |
1757 |
/* allow_env doesn't interpret leading @ as path_group. */ |
1758 |
if (darg1.is_patterned || !PathMatchesToPattern(&darg1, &sarg1)) continue; |
1759 |
} |
1760 |
} |
1761 |
|
1762 |
/* Compare rest words. */ |
1763 |
if (directive_index == 21 || directive_index == 22) { |
1764 |
if (pathcmp(&sarg2, &darg2)) { |
1765 |
const int may_use_pattern = !darg2.is_patterned; |
1766 |
if (darg2.name[0] == '@') continue; |
1767 |
if (sarg2.name[0] == '@') { |
1768 |
/* path_group component. */ |
1769 |
int i; |
1770 |
struct path_group_entry *group = FindPathGroup(sarg2.name + 1); |
1771 |
if (!group) continue; |
1772 |
for (i = 0; i < group->member_name_len; i++) { |
1773 |
const struct path_info *member_name = group->member_name[i]; |
1774 |
if (!pathcmp(member_name, &darg2)) break; |
1775 |
if (may_use_pattern && PathMatchesToPattern(&darg2, member_name)) break; |
1776 |
} |
1777 |
if (i == group->member_name_len) continue; |
1778 |
} else { |
1779 |
/* Pathname component. */ |
1780 |
if (!may_use_pattern || !PathMatchesToPattern(&darg2, &sarg2)) continue; |
1781 |
} |
1782 |
} |
1783 |
} else if (directive_index == 24) { |
1784 |
/* Basename component. */ |
1785 |
if (pathcmp(&sarg2, &darg2)) { |
1786 |
if (darg2.is_patterned || !PathMatchesToPattern(&darg2, &sarg2)) continue; |
1787 |
} |
1788 |
} else if (directive_index == 25) { |
1789 |
/* Domainname component. */ |
1790 |
char c; |
1791 |
if (strncmp(sarg2.name, darg2.name, sarg2.total_len)) continue; |
1792 |
c = darg2.name[sarg2.total_len]; |
1793 |
if (c && c != ' ') continue; |
1794 |
} else if (directive_index >= 26 && directive_index < 34) { |
1795 |
/* Port number component. */ |
1796 |
unsigned int smin, smax, dmin, dmax; |
1797 |
switch (sscanf(sarg2.name, "%u-%u", &smin, &smax)) { |
1798 |
case 1: |
1799 |
smax = smin; |
1800 |
case 2: |
1801 |
break; |
1802 |
default: |
1803 |
continue; |
1804 |
} |
1805 |
switch (sscanf(darg2.name, "%u-%u", &dmin, &dmax)) { |
1806 |
case 1: |
1807 |
dmax = dmin; |
1808 |
case 2: |
1809 |
break; |
1810 |
default: |
1811 |
continue; |
1812 |
} |
1813 |
if (smin > dmin || smax < dmax) continue; |
1814 |
} else { |
1815 |
/* This must be empty. */ |
1816 |
if (sarg2.total_len || darg2.total_len) continue; |
1817 |
} |
1818 |
generic_acl_list_selected[index] = 1; |
1819 |
} |
1820 |
put(); |
1821 |
free(cp); |
1822 |
ShowList(); |
1823 |
} |
1824 |
|
1825 |
static int GenericListLoop(void) { |
1826 |
static char *last_error = NULL; |
1827 |
static const int max_readline_history = 20; |
1828 |
static const char **readline_history = NULL; |
1829 |
static int readline_history_count = 0; |
1830 |
static char *search_buffer[MAXSCREEN]; |
1831 |
static int saved_current_y[MAXSCREEN]; |
1832 |
static int saved_current_item_index[MAXSCREEN]; |
1833 |
static int first = 1; |
1834 |
if (first) { |
1835 |
readline_history = malloc(max_readline_history * sizeof(const char *)); |
1836 |
memset(saved_current_y, 0, sizeof(saved_current_y)); |
1837 |
memset(saved_current_item_index, 0, sizeof(saved_current_item_index)); |
1838 |
memset(search_buffer, 0, sizeof(search_buffer)); |
1839 |
first = 0; |
1840 |
} |
1841 |
if (current_screen == SCREEN_SYSTEM_LIST) { |
1842 |
policy_file = SYSTEM_POLICY_FILE; |
1843 |
list_caption = "System Policy"; |
1844 |
} else if (current_screen == SCREEN_EXCEPTION_LIST) { |
1845 |
policy_file = EXCEPTION_POLICY_FILE; |
1846 |
list_caption = "Exception Policy"; |
1847 |
} else if (current_screen == SCREEN_ACL_LIST) { |
1848 |
policy_file = DOMAIN_POLICY_FILE; |
1849 |
list_caption = "Domain Policy"; |
1850 |
} else { |
1851 |
policy_file = DOMAIN_POLICY_FILE; |
1852 |
//list_caption = "Domain Transition"; |
1853 |
} |
1854 |
current_item_index[current_screen] = saved_current_item_index[current_screen]; |
1855 |
current_y[current_screen] = saved_current_y[current_screen]; |
1856 |
start: |
1857 |
if (current_screen == SCREEN_DOMAIN_LIST) { |
1858 |
ReadDomainAndExceptionPolicy(); |
1859 |
AdjustCursorPos(domain_list_count); |
1860 |
} else { |
1861 |
ReadGenericPolicy(); |
1862 |
AdjustCursorPos(generic_acl_list_count); |
1863 |
} |
1864 |
start2: |
1865 |
ShowList(); |
1866 |
if (last_error && current_screen == SCREEN_DOMAIN_LIST) { |
1867 |
mvprintw(1, 0, "ERROR: %s", last_error); clrtoeol(); refresh(); |
1868 |
free(last_error); last_error = NULL; |
1869 |
} |
1870 |
while (1) { |
1871 |
const int current = GetCurrent(); |
1872 |
const int c = getch2(); |
1873 |
saved_current_item_index[current_screen] = current_item_index[current_screen]; |
1874 |
saved_current_y[current_screen] = current_y[current_screen]; |
1875 |
if (c == 'q' || c == 'Q') return MAXSCREEN; |
1876 |
if ((c == '\r' || c == '\n') && current_screen == SCREEN_ACL_LIST) return SCREEN_DOMAIN_LIST; |
1877 |
if (c == '\t') { |
1878 |
if (current_screen == SCREEN_DOMAIN_LIST) return SCREEN_SYSTEM_LIST; |
1879 |
else if (current_screen == SCREEN_SYSTEM_LIST) return SCREEN_EXCEPTION_LIST; |
1880 |
else return SCREEN_DOMAIN_LIST; |
1881 |
} |
1882 |
if (c == ERR) continue; // Ignore invalid key. |
1883 |
switch(c) { |
1884 |
case KEY_RESIZE: |
1885 |
ResizeWindow(); |
1886 |
ShowList(); |
1887 |
break; |
1888 |
case KEY_UP: |
1889 |
UpArrowKey(); |
1890 |
break; |
1891 |
case KEY_DOWN: |
1892 |
DownArrowKey(); |
1893 |
break; |
1894 |
case KEY_PPAGE: |
1895 |
PageUpKey(); |
1896 |
break; |
1897 |
case KEY_NPAGE: |
1898 |
PageDownKey(); |
1899 |
break; |
1900 |
case ' ': |
1901 |
SelectItem(current); |
1902 |
break; |
1903 |
case 'c': |
1904 |
case 'C': |
1905 |
if (current >= 0) { |
1906 |
int index; |
1907 |
if (current_screen == SCREEN_DOMAIN_LIST) { |
1908 |
if (IsDeletedDomain(current) || IsInitializerSource(current)) break; |
1909 |
for (index = current; index < domain_list_count; index++) { |
1910 |
if (IsDeletedDomain(index) || IsInitializerSource(index)) continue; |
1911 |
domain_list_selected[index] = domain_list_selected[current]; |
1912 |
} |
1913 |
} else { |
1914 |
for (index = current; index < generic_acl_list_count; index++) { |
1915 |
generic_acl_list_selected[index] = generic_acl_list_selected[current]; |
1916 |
} |
1917 |
} |
1918 |
ShowList(); |
1919 |
} |
1920 |
break; |
1921 |
case 'f': |
1922 |
case 'F': |
1923 |
if (current >= 0) { |
1924 |
int index; |
1925 |
char *line; |
1926 |
input_path: |
1927 |
attrChange(A_BOLD, ON); // add color |
1928 |
line = simple_readline(window_height - 1, 0, "Search> ", readline_history, readline_history_count, 4000, 8); |
1929 |
attrChange(A_BOLD, OFF); // add color |
1930 |
if (line && *line) { |
1931 |
readline_history_count = simple_add_history(line, readline_history, readline_history_count, max_readline_history); |
1932 |
free(search_buffer[current_screen]); search_buffer[current_screen] = line; line = NULL; |
1933 |
for (index = 0; index < list_item_count[current_screen]; index++) { |
1934 |
const char *cp = (current_screen == SCREEN_DOMAIN_LIST) ? GetLastName(index) : generic_acl_list[index]; |
1935 |
if (!strstr(cp, search_buffer[current_screen])) continue; |
1936 |
SetCursorPos(index); |
1937 |
break; |
1938 |
} |
1939 |
} |
1940 |
free(line); |
1941 |
ShowList(); |
1942 |
} |
1943 |
break; |
1944 |
case 'p': |
1945 |
case 'P': |
1946 |
if (current >= 0) { |
1947 |
int index; |
1948 |
if (!search_buffer[current_screen]) goto input_path; |
1949 |
for (index = current - 1; index >= 0; index--) { |
1950 |
const char *cp = (current_screen == SCREEN_DOMAIN_LIST) ? GetLastName(index) : generic_acl_list[index]; |
1951 |
if (!strstr(cp, search_buffer[current_screen])) continue; |
1952 |
SetCursorPos(index); |
1953 |
ShowList(); |
1954 |
break; |
1955 |
} |
1956 |
} |
1957 |
break; |
1958 |
case 'n': |
1959 |
case 'N': |
1960 |
if (current >= 0) { |
1961 |
int index; |
1962 |
if (!search_buffer[current_screen]) goto input_path; |
1963 |
for (index = current + 1; index < list_item_count[current_screen]; index++) { |
1964 |
const char *cp = (current_screen == SCREEN_DOMAIN_LIST) ? GetLastName(index) : generic_acl_list[index]; |
1965 |
if (!strstr(cp, search_buffer[current_screen])) continue; |
1966 |
SetCursorPos(index); |
1967 |
ShowList(); |
1968 |
break; |
1969 |
} |
1970 |
} |
1971 |
break; |
1972 |
case 'd': |
1973 |
case 'D': |
1974 |
{ |
1975 |
int c; |
1976 |
move(1, 0); |
1977 |
colorChange(DISP_ERR, ON); // add color |
1978 |
if (current_screen == SCREEN_DOMAIN_LIST) { |
1979 |
if ((c = count(domain_list_selected, domain_list_count)) == 0 && (c = SelectItem(current)) == 0) printw("Select domain using Space key first."); |
1980 |
else printw("Delete selected domain%s? ('Y'es/'N'o)", c > 1 ? "s" : ""); |
1981 |
} else { |
1982 |
if ((c = count(generic_acl_list_selected, generic_acl_list_count)) == 0 && (c = SelectItem(current)) == 0) printw("Select entry using Space key first."); |
1983 |
else printw("Delete selected entr%s? ('Y'es/'N'o)", c > 1 ? "ies" : "y"); |
1984 |
} |
1985 |
colorChange(DISP_ERR, OFF); // add color |
1986 |
clrtoeol(); |
1987 |
refresh(); |
1988 |
if (!c) break; |
1989 |
do { |
1990 |
c = getch2(); |
1991 |
} while (!(c == 'Y' || c == 'y' || c == 'N' || c == 'n' || c == EOF)); |
1992 |
ResizeWindow(); |
1993 |
if (c == 'Y' || c == 'y') { |
1994 |
int index; |
1995 |
if (current_screen == SCREEN_DOMAIN_LIST) { |
1996 |
FILE *fp = open_write(DOMAIN_POLICY_FILE); |
1997 |
if (fp) { |
1998 |
for (index = 1; index < domain_list_count; index++) { |
1999 |
if (domain_list_selected[index]) fprintf(fp, "delete %s\n", DomainName(index)); |
2000 |
} |
2001 |
fclose(fp); |
2002 |
} |
2003 |
} else { |
2004 |
FILE *fp = open_write(policy_file); |
2005 |
if (fp) { |
2006 |
if (current_screen == SCREEN_ACL_LIST) fprintf(fp, "select %s\n", current_domain); |
2007 |
for (index = 0; index < generic_acl_list_count; index++) { |
2008 |
if (generic_acl_list_selected[index]) fprintf(fp, "delete %s\n", generic_acl_list[index]); |
2009 |
} |
2010 |
fclose(fp); |
2011 |
} |
2012 |
} |
2013 |
goto start; |
2014 |
} |
2015 |
ShowList(); |
2016 |
} |
2017 |
break; |
2018 |
case 'a': |
2019 |
case 'A': |
2020 |
{ |
2021 |
attrChange(A_BOLD, ON); // add color |
2022 |
char *line = simple_readline(window_height - 1, 0, "Enter new entry> ", readline_history, readline_history_count, 8192, 8); |
2023 |
attrChange(A_BOLD, OFF); // add color |
2024 |
if (line && *line) { |
2025 |
readline_history_count = simple_add_history(line, readline_history, readline_history_count, max_readline_history); |
2026 |
if (current_screen == SCREEN_DOMAIN_LIST && !IsCorrectDomain(line)) { |
2027 |
const int len = strlen(line) + 128; |
2028 |
if ((last_error = (char *) realloc(last_error, len)) == NULL) OutOfMemory(); |
2029 |
memset(last_error, 0, len); |
2030 |
snprintf(last_error, len - 1, "%s is a bad domainname.", line); |
2031 |
} else { |
2032 |
FILE *fp = open_write(policy_file); |
2033 |
if (fp) { |
2034 |
if (current_screen == SCREEN_ACL_LIST) fprintf(fp, "select %s\n", current_domain); |
2035 |
fprintf(fp, "%s\n", line); |
2036 |
fclose(fp); |
2037 |
} |
2038 |
} |
2039 |
} |
2040 |
free(line); |
2041 |
goto start; |
2042 |
} |
2043 |
break; |
2044 |
case '\r': |
2045 |
case '\n': |
2046 |
if (current_screen == SCREEN_DOMAIN_LIST) { |
2047 |
if (IsInitializerSource(current)) { |
2048 |
int redirect_index; |
2049 |
get(); |
2050 |
memset(shared_buffer, 0, shared_buffer_len); |
2051 |
snprintf(shared_buffer, shared_buffer_len - 1, ROOT_NAME "%s", strrchr(DomainName(current), ' ')); |
2052 |
redirect_index = FindDomain(shared_buffer, 0, 0); |
2053 |
put(); |
2054 |
if (redirect_index != EOF) { |
2055 |
current_item_index[current_screen] = redirect_index - current_y[current_screen]; |
2056 |
while (current_item_index[current_screen] < 0) { |
2057 |
current_item_index[current_screen]++; current_y[current_screen]--; |
2058 |
} |
2059 |
ShowList(); |
2060 |
} |
2061 |
} else if (!IsDeletedDomain(current)) { |
2062 |
free(current_domain); |
2063 |
if ((current_domain = strdup(DomainName(current))) == NULL) OutOfMemory(); |
2064 |
return SCREEN_ACL_LIST; |
2065 |
} |
2066 |
} |
2067 |
break; |
2068 |
case 's': |
2069 |
case 'S': |
2070 |
if (current_screen == SCREEN_DOMAIN_LIST) { |
2071 |
if (!count(domain_list_selected, domain_list_count) && !SelectItem(current)) { |
2072 |
mvprintw(1, 0, "Select domain using Space key first."); clrtoeol(); refresh(); |
2073 |
} else { |
2074 |
attrChange(A_BOLD, ON); // add color |
2075 |
char *line = simple_readline(window_height - 1, 0, "Enter profile number> ", NULL, 0, 8, 1); |
2076 |
attrChange(A_BOLD, OFF); // add color |
2077 |
if (line && *line) { |
2078 |
FILE *fp = open_write(DOMAIN_POLICY_FILE); |
2079 |
if (fp) { |
2080 |
int index; |
2081 |
for (index = 0; index < domain_list_count; index++) { |
2082 |
if (domain_list_selected[index]) fprintf(fp, "select %s\nuse_profile %s\n", DomainName(index), line); |
2083 |
} |
2084 |
fclose(fp); |
2085 |
} |
2086 |
} |
2087 |
free(line); |
2088 |
goto start; |
2089 |
} |
2090 |
} |
2091 |
break; |
2092 |
case 'r': |
2093 |
case 'R': |
2094 |
goto start; |
2095 |
case KEY_LEFT: |
2096 |
if (!max_eat_col[current_screen]) break; |
2097 |
max_eat_col[current_screen]--; |
2098 |
goto start2; |
2099 |
case KEY_RIGHT: |
2100 |
max_eat_col[current_screen]++; |
2101 |
goto start2; |
2102 |
case KEY_HOME: |
2103 |
max_eat_col[current_screen] = 0; |
2104 |
goto start2; |
2105 |
case KEY_END: |
2106 |
max_eat_col[current_screen] = max_col; |
2107 |
goto start2; |
2108 |
case KEY_IC: |
2109 |
if (current >= 0) readline_history_count = simple_add_history(current_screen == SCREEN_DOMAIN_LIST ? DomainName(current) : generic_acl_list[current], readline_history, readline_history_count, max_readline_history); |
2110 |
break; |
2111 |
case 'o': |
2112 |
case 'O': |
2113 |
if (current_screen == SCREEN_ACL_LIST) try_optimize(current); |
2114 |
break; |
2115 |
case '?': |
2116 |
{ |
2117 |
int c; |
2118 |
clear(); |
2119 |
printw("Commands available for this screen are:\n\n" |
2120 |
"Q/q Quit this editor.\n" |
2121 |
"R/r Refresh to the latest information.\n" |
2122 |
"F/f Find first.\n" |
2123 |
"N/n Find next.\n" |
2124 |
"P/p Find previous.\n" |
2125 |
"Tab Switch to next screen.\n" |
2126 |
"Insert Copy an entry at the cursor position to history buffer.\n" |
2127 |
"Space Invert selection state of an entry at the cursor position.\n" |
2128 |
"C/c Copy selection state of an entry at the cursor position to all entries below the cursor position.\n"); |
2129 |
if (current_screen == SCREEN_DOMAIN_LIST) { |
2130 |
printw("A/a Add a new domain.\n" |
2131 |
"Enter Edit ACLs of a domain at the cursor position.\n" |
2132 |
"D/d Delete selected domains.\n" |
2133 |
"S/s Set profile number of selected domains.\n"); |
2134 |
} else { |
2135 |
printw("A/a Add a new entry.\n" |
2136 |
"D/d Delete selected entries.\n"); |
2137 |
if (current_screen == SCREEN_ACL_LIST) printw("O/o Set selection state to other entries included in an entry at the cursor position.\n"); |
2138 |
} |
2139 |
printw("Arrow-keys and PageUp/PageDown/Home/End keys for scroll.\n\n" |
2140 |
"Press '?' to escape from this help.\n"); refresh(); |
2141 |
while ((c = getch2()) != '?' && c != EOF); |
2142 |
goto start; |
2143 |
} |
2144 |
break; |
2145 |
} |
2146 |
} |
2147 |
} |
2148 |
|
2149 |
static void policy_daemon(void) { |
2150 |
get(); |
2151 |
FindOrAssignNewDomain(ROOT_NAME, 0, 0); |
2152 |
while (1) { |
2153 |
static const struct path_info **exception_list = NULL, **system_list = NULL; |
2154 |
static int exception_list_count = 0, system_list_count = 0; |
2155 |
FILE *fp; |
2156 |
{ |
2157 |
struct msghdr msg; |
2158 |
struct iovec iov = { shared_buffer, shared_buffer_len - 1 }; |
2159 |
char cmsg_buf[CMSG_SPACE(sizeof(int))]; |
2160 |
struct cmsghdr *cmsg = (struct cmsghdr *) cmsg_buf; |
2161 |
memset(&msg, 0, sizeof(msg)); |
2162 |
msg.msg_iov = &iov; |
2163 |
msg.msg_iovlen = 1; |
2164 |
msg.msg_control = cmsg_buf; |
2165 |
msg.msg_controllen = sizeof(cmsg_buf); |
2166 |
memset(shared_buffer, 0, shared_buffer_len); |
2167 |
errno = 0; |
2168 |
if (recvmsg(persistent_fd, &msg, 0) > 0 && |
2169 |
(cmsg = CMSG_FIRSTHDR(&msg)) != NULL && |
2170 |
cmsg->cmsg_level == SOL_SOCKET && |
2171 |
cmsg->cmsg_type == SCM_RIGHTS && |
2172 |
cmsg->cmsg_len == CMSG_LEN(sizeof(int))) { |
2173 |
const int fd = * (int *) CMSG_DATA(cmsg); |
2174 |
if ((fp = fdopen(fd, "w+")) == NULL) { |
2175 |
close(fd); |
2176 |
continue; |
2177 |
} |
2178 |
} else { |
2179 |
break; |
2180 |
} |
2181 |
} |
2182 |
if (strncmp(shared_buffer, "POST ", 5) == 0) { |
2183 |
if (strcmp(shared_buffer + 5, "domain_policy") == 0) { |
2184 |
int index = EOF; |
2185 |
while (freadline(fp)) { |
2186 |
int is_delete = 0, is_select = 0; |
2187 |
if (strncmp(shared_buffer, "delete ", 7) == 0) { |
2188 |
is_delete = 1; |
2189 |
RemoveHeader(shared_buffer, 7); |
2190 |
} else if (strncmp(shared_buffer, "select ", 7) == 0) { |
2191 |
is_select = 1; |
2192 |
RemoveHeader(shared_buffer, 7); |
2193 |
} |
2194 |
if (IsDomainDef(shared_buffer)) { |
2195 |
if (is_delete) { |
2196 |
index = FindDomain(shared_buffer, 0, 0); |
2197 |
if (index > 0) DeleteDomain(index); |
2198 |
index = EOF; |
2199 |
} else if (is_select) { |
2200 |
index = FindDomain(shared_buffer, 0, 0); |
2201 |
} else { |
2202 |
index = FindOrAssignNewDomain(shared_buffer, 0, 0); |
2203 |
} |
2204 |
} else if (index >= 0 && shared_buffer[0]) { |
2205 |
unsigned int profile; |
2206 |
if (sscanf(shared_buffer, "use_profile %u", &profile) == 1) { |
2207 |
domain_list[index].profile = (unsigned char) profile; |
2208 |
} else if (is_delete) { |
2209 |
DelStringEntry(shared_buffer, index); |
2210 |
} else { |
2211 |
AddStringEntry(shared_buffer, index); |
2212 |
} |
2213 |
} |
2214 |
} |
2215 |
} else if (strcmp(shared_buffer + 5, "exception_policy") == 0) { |
2216 |
while (freadline(fp)) { |
2217 |
if (!shared_buffer[0]) continue; |
2218 |
if (strncmp(shared_buffer, "delete ", 7) == 0) { |
2219 |
int i; |
2220 |
struct path_info path; |
2221 |
RemoveHeader(shared_buffer, 7); |
2222 |
path.name = shared_buffer; |
2223 |
fill_path_info(&path); |
2224 |
for (i = 0; i < exception_list_count; i++) { |
2225 |
if (pathcmp(exception_list[i], &path)) continue; |
2226 |
for (exception_list_count--; i < exception_list_count; i++) exception_list[i] = exception_list[i + 1]; |
2227 |
break; |
2228 |
} |
2229 |
} else { |
2230 |
if ((exception_list = (const struct path_info **) realloc(exception_list, (exception_list_count + 1) * sizeof(const struct path_info *))) == NULL |
2231 |
|| (exception_list[exception_list_count++] = SaveName(shared_buffer)) == NULL) OutOfMemory(); |
2232 |
} |
2233 |
} |
2234 |
} else if (strcmp(shared_buffer + 5, "system_policy") == 0) { |
2235 |
while (freadline(fp)) { |
2236 |
if (!shared_buffer[0]) continue; |
2237 |
if (strncmp(shared_buffer, "delete ", 7) == 0) { |
2238 |
int i; |
2239 |
struct path_info path; |
2240 |
RemoveHeader(shared_buffer, 7); |
2241 |
path.name = shared_buffer; |
2242 |
fill_path_info(&path); |
2243 |
for (i = 0; i < system_list_count; i++) { |
2244 |
if (pathcmp(system_list[i], &path)) continue; |
2245 |
for (system_list_count--; i < system_list_count; i++) system_list[i] = system_list[i + 1]; |
2246 |
break; |
2247 |
} |
2248 |
} else { |
2249 |
if ((system_list = (const struct path_info **) realloc(system_list, (system_list_count + 1) * sizeof(struct path_info *))) == NULL |
2250 |
|| (system_list[system_list_count++] = SaveName(shared_buffer)) == NULL) OutOfMemory(); |
2251 |
} |
2252 |
} |
2253 |
} |
2254 |
} else if (strncmp(shared_buffer, "GET ", 4) == 0) { |
2255 |
if (strcmp(shared_buffer + 4, "domain_policy") == 0) { |
2256 |
int i, j; |
2257 |
for (i = 0; i < domain_list_count; i++) { |
2258 |
const struct path_info **string_ptr = domain_list[i].string_ptr; |
2259 |
const int string_count = domain_list[i].string_count; |
2260 |
fprintf(fp, "%s\nuse_profile %u\n\n", DomainName(i), domain_list[i].profile); |
2261 |
for (j = 0; j < string_count; j++) { |
2262 |
fprintf(fp, "%s\n", string_ptr[j]->name); |
2263 |
} |
2264 |
fprintf(fp, "\n"); |
2265 |
} |
2266 |
} else if (strcmp(shared_buffer + 4, "exception_policy") == 0) { |
2267 |
int i; |
2268 |
for (i = 0; i < exception_list_count; i++) fprintf(fp, "%s\n", exception_list[i]->name); |
2269 |
} else if (strcmp(shared_buffer + 4, "system_policy") == 0) { |
2270 |
int i; |
2271 |
for (i = 0; i < system_list_count; i++) fprintf(fp, "%s\n", system_list[i]->name); |
2272 |
} |
2273 |
} |
2274 |
fclose(fp); |
2275 |
} |
2276 |
put(); |
2277 |
_exit(0); |
2278 |
} |
2279 |
|
2280 |
int editpolicy_main(int argc, char *argv[]) { |
2281 |
memset(current_y, 0, sizeof(current_y)); |
2282 |
memset(current_item_index, 0, sizeof(current_item_index)); |
2283 |
memset(list_item_count, 0, sizeof(list_item_count)); |
2284 |
memset(max_eat_col, 0, sizeof(max_eat_col)); |
2285 |
if (argc > 1) { |
2286 |
if (strcmp(argv[1], "s") == 0) current_screen = SCREEN_SYSTEM_LIST; |
2287 |
else if (strcmp(argv[1], "e") == 0) current_screen = SCREEN_EXCEPTION_LIST; |
2288 |
else if (strcmp(argv[1], "d") == 0) current_screen = SCREEN_DOMAIN_LIST; |
2289 |
else { |
2290 |
printf("Usage: %s [s|e|d]\n", argv[0]); |
2291 |
return 1; |
2292 |
} |
2293 |
} |
2294 |
{ |
2295 |
char *cp = strrchr(argv[0], '/'); |
2296 |
if (!cp) cp = argv[0]; |
2297 |
else cp++; |
2298 |
if (strstr(cp, "editpolicy_offline")) offline_mode = 1; |
2299 |
} |
2300 |
if (offline_mode) { |
2301 |
int fd[2]; |
2302 |
if (chdir(disk_policy_dir)) { |
2303 |
printf("Directory %s doesn't exist.\n", disk_policy_dir); |
2304 |
return 1; |
2305 |
} |
2306 |
if (socketpair(PF_UNIX, SOCK_STREAM, 0, fd)) { |
2307 |
fprintf(stderr, "socketpair()\n"); |
2308 |
exit(1); |
2309 |
} |
2310 |
switch (fork()) { |
2311 |
case 0: |
2312 |
close(fd[0]); |
2313 |
persistent_fd = fd[1]; |
2314 |
policy_daemon(); |
2315 |
_exit(0); |
2316 |
case -1: |
2317 |
fprintf(stderr, "fork()\n"); |
2318 |
exit(1); |
2319 |
} |
2320 |
close(fd[1]); |
2321 |
persistent_fd = fd[0]; |
2322 |
{ |
2323 |
int fd, len; |
2324 |
FILE *fp; |
2325 |
get(); |
2326 |
if ((fd = open(disk_policy_system_policy, O_RDONLY)) != EOF) { |
2327 |
fp = open_write(SYSTEM_POLICY_FILE); |
2328 |
while ((len = read(fd, shared_buffer, shared_buffer_len)) > 0) fwrite(shared_buffer, len, 1, fp); |
2329 |
fclose(fp); close(fd); |
2330 |
} |
2331 |
if ((fd = open(disk_policy_exception_policy, O_RDONLY)) != EOF) { |
2332 |
fp = open_write(EXCEPTION_POLICY_FILE); |
2333 |
while ((len = read(fd, shared_buffer, shared_buffer_len)) > 0) fwrite(shared_buffer, len, 1, fp); |
2334 |
fclose(fp); close(fd); |
2335 |
} |
2336 |
if ((fd = open(disk_policy_domain_policy, O_RDONLY)) != EOF) { |
2337 |
fp = open_write(DOMAIN_POLICY_FILE); |
2338 |
while ((len = read(fd, shared_buffer, shared_buffer_len)) > 0) fwrite(shared_buffer, len, 1, fp); |
2339 |
fclose(fp); close(fd); |
2340 |
} |
2341 |
put(); |
2342 |
} |
2343 |
} else { |
2344 |
if (chdir(proc_policy_dir)) { |
2345 |
fprintf(stderr, "You can't use this editor for this kernel.\n"); |
2346 |
return 1; |
2347 |
} |
2348 |
{ |
2349 |
const int fd1 = open(SYSTEM_POLICY_FILE, O_RDWR), fd2 = open(EXCEPTION_POLICY_FILE, O_RDWR), fd3 = open(DOMAIN_POLICY_FILE, O_RDWR); |
2350 |
if ((fd1 != EOF && write(fd1, "", 0) != 0) || (fd2 != EOF && write(fd2, "", 0) != 0) || (fd3 != EOF && write(fd3, "", 0) != 0)) { |
2351 |
fprintf(stderr, "You need to register this program to %s to run this program.\n", proc_policy_manager); |
2352 |
return 1; |
2353 |
} |
2354 |
close(fd1); close(fd2); close(fd3); |
2355 |
} |
2356 |
} |
2357 |
initscr(); |
2358 |
ColorInit(); // add color |
2359 |
cbreak(); |
2360 |
noecho(); |
2361 |
nonl(); |
2362 |
intrflush(stdscr, FALSE); |
2363 |
keypad(stdscr, TRUE); |
2364 |
getmaxyx(stdscr, window_height, window_width); |
2365 |
while (current_screen < MAXSCREEN) { |
2366 |
if (!offline_mode) { |
2367 |
if (current_screen == SCREEN_DOMAIN_LIST && access(DOMAIN_POLICY_FILE, F_OK)) current_screen = SCREEN_SYSTEM_LIST; |
2368 |
else if (current_screen == SCREEN_SYSTEM_LIST && access(SYSTEM_POLICY_FILE, F_OK)) current_screen = SCREEN_EXCEPTION_LIST; |
2369 |
else if (current_screen == SCREEN_EXCEPTION_LIST && access(EXCEPTION_POLICY_FILE, F_OK)) { |
2370 |
current_screen = SCREEN_DOMAIN_LIST; |
2371 |
if (access(DOMAIN_POLICY_FILE, F_OK)) current_screen = SCREEN_SYSTEM_LIST; |
2372 |
} |
2373 |
} |
2374 |
ResizeWindow(); |
2375 |
current_screen = GenericListLoop(); |
2376 |
} |
2377 |
clear(); |
2378 |
move(0, 0); |
2379 |
refresh(); |
2380 |
endwin(); |
2381 |
if (offline_mode) { |
2382 |
int fd, len; |
2383 |
FILE *fp; |
2384 |
time_t now = time(NULL); |
2385 |
struct tm *tm = localtime(&now); |
2386 |
char filename[1024], buffer[1024]; |
2387 |
memset(filename, 0, sizeof(filename)); |
2388 |
snprintf(filename, sizeof(filename) - 1, "system_policy.%02d-%02d-%02d.%02d:%02d:%02d.conf", tm->tm_year % 100, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec); |
2389 |
if ((fd = open(filename, O_WRONLY | O_CREAT, 0600)) != EOF) { |
2390 |
if ((fp = open_read(SYSTEM_POLICY_FILE)) != NULL) { |
2391 |
while ((len = fread(buffer, 1, sizeof(buffer), fp)) > 0) write(fd, buffer, len); |
2392 |
close(fd); fclose(fp); |
2393 |
unlink(disk_policy_system_policy); |
2394 |
symlink(filename, "system_policy.conf"); |
2395 |
} |
2396 |
} |
2397 |
snprintf(filename, sizeof(filename) - 1, "exception_policy.%02d-%02d-%02d.%02d:%02d:%02d.conf", tm->tm_year % 100, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec); |
2398 |
if ((fd = open(filename, O_WRONLY | O_CREAT, 0600)) != EOF) { |
2399 |
if ((fp = open_read(EXCEPTION_POLICY_FILE)) != NULL) { |
2400 |
while ((len = fread(buffer, 1, sizeof(buffer), fp)) > 0) write(fd, buffer, len); |
2401 |
close(fd); fclose(fp); |
2402 |
unlink(disk_policy_exception_policy); |
2403 |
symlink(filename, "exception_policy.conf"); |
2404 |
} |
2405 |
} |
2406 |
snprintf(filename, sizeof(filename) - 1, "domain_policy.%02d-%02d-%02d.%02d:%02d:%02d.conf", tm->tm_year % 100, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec); |
2407 |
if ((fd = open(filename, O_WRONLY | O_CREAT, 0600)) != EOF) { |
2408 |
if ((fp = open_read(DOMAIN_POLICY_FILE)) != NULL) { |
2409 |
while ((len = fread(buffer, 1, sizeof(buffer), fp)) > 0) write(fd, buffer, len); |
2410 |
close(fd); fclose(fp); |
2411 |
unlink(disk_policy_domain_policy); |
2412 |
symlink(filename, "domain_policy.conf"); |
2413 |
} |
2414 |
} |
2415 |
} |
2416 |
return 0; |
2417 |
} |
2418 |
|
2419 |
/***** editpolicy end *****/ |