オープンソース・ソフトウェアの開発とダウンロード

Subversion リポジトリの参照

Contents of /trunk/1.6.x/ccs-tools/ccstools/ccstools.src/editpolicy.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 898 - (show annotations) (download) (as text)
Tue Jan 15 04:44:35 2008 UTC (16 years, 3 months ago) by kumaneko
File MIME type: text/x-csrc
File size: 83787 byte(s)


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 *****/

Back to OSDN">Back to OSDN
ViewVC Help
Powered by ViewVC 1.1.26