/[pdpsoft]/trunk/grid-mw-security/ees/src/eval_man/pdl.c
ViewVC logotype

Contents of /trunk/grid-mw-security/ees/src/eval_man/pdl.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1146 - (show annotations) (download) (as text)
Thu Nov 19 16:35:31 2009 UTC (12 years, 2 months ago) by aramv
File MIME type: text/x-chdr
File size: 21064 byte(s)
Cleaned up tree building/printing code
1 #include "pdl.h"
2
3 /* Lex/Yacc stuff */
4 extern FILE * yyin;
5 extern unsigned int lineno;
6 extern int yyparse(void);
7 extern int yylex(void);
8
9 /* Lex/Yacc cleanup functions */
10 extern void delete_lex_buffer(void);
11 #if HAVE_YYLEX_DESTROY
12 extern int yylex_destroy(void);
13 #endif
14
15 /* internal data */
16 static const char* config_file_s;
17 FILE* config_file_fp;
18 static char* _pdl_path;
19
20 var_t* variables_list;
21 var_t* variables_list_last;
22 var_t* current_variable;
23
24 rule_t* rules_list;
25 rule_t* rules_list_last;
26 rule_t* current_rule;
27
28 policy_t* policies_list;
29 policy_t* policies_list_last;
30 policy_t* current_policy;
31
32 /*! initializes the parsing of the configuration file */
33 EES_RC pdl_init(const char* config_file_name){
34 eef_plugindl_t* temp_plugin = NULL;
35 config_file_s = config_file_name;
36
37 if((config_file_fp = fopen(config_file_s,"r")) != NULL){
38 yyin = config_file_fp;
39 yyparse();
40 /*print_policies();*/
41 if(add_plugins() == EES_SUCCESS){
42 /* this is a callout to the plugin manager, which calls dlopen(), dlsym() and the plugin's initialize function */
43 if(initialize_plugins() == EES_SUCCESS){
44 temp_plugin = build_plugin_tree(policies_list);
45 print_plugin_tree_recursive(temp_plugin, 0);
46 return EES_SUCCESS;
47 } else {
48 eef_log(LOG_ERR, "Failed to initialize plug-ins from policy config file %s\n", config_file_s);
49 }
50 } else {
51 eef_log(LOG_ERR, "Failed to load plug-ins from policy config file %s\n", config_file_s);
52 }
53 } else {
54 eef_log(LOG_ERR, "Failed to open policy config file %s", config_file_s);
55 }
56 return EES_FAILURE;
57 }
58
59 /* TODO the retrieving of plugins could really be more efficient - it should be possible to only store argv[0] in the string-based policy tree */
60 /* builds a tree of eef_plugindl_t structs, which hold pointers to initialized plugins retrieved from the plugin manager */
61 eef_plugindl_t* build_plugin_tree(policy_t* policies){
62 policy_t *temp_policy = policies;
63 eef_plugindl_t *temp_plugin_rules = NULL , *temp_plugin_rules_last = NULL, *plugin_tree = NULL, *plugin_tree_last = NULL, *temp_plugin_node = NULL;
64 rule_t *temp_rule = NULL;
65 char** argv;
66 int argc;
67
68 while(temp_policy){
69 temp_rule = temp_policy->rules;
70 while(temp_rule){
71 /* find plug-in described by rule */
72 argv = _var_to_argv(get_variable_by_name(temp_rule->state)->value, &argc);
73 temp_plugin_node = get_plugin(argv[0]);
74 free_args(argc, argv);
75
76 /* link branch pointers to plugin */
77 if(temp_plugin_node){
78 if(temp_rule->true_branch){
79 argv = _var_to_argv(get_variable_by_name(temp_rule->true_branch->state)->value, &argc);
80 temp_plugin_node->true_branch = get_plugin(argv[0]);
81 free_args(argc, argv);
82 }
83
84 if(temp_rule->false_branch){
85 argv = _var_to_argv(get_variable_by_name(temp_rule->false_branch->state)->value, &argc);
86 temp_plugin_node->false_branch = get_plugin(argv[0]);
87 free_args(argc, argv);
88 }
89 }
90
91 /* append rule plugin to list of rules */
92 if(temp_plugin_rules){
93 temp_plugin_rules_last->next = temp_plugin_node;
94 } else {
95 temp_plugin_rules = temp_plugin_node;
96 }
97 temp_plugin_rules_last = temp_plugin_node;
98
99 /* iterate to next rule */
100 temp_rule = temp_rule->next;
101 }
102
103 /* at this point the tree describing a single policy with branches of rules has been created */
104
105 /* append rule plugin tree (policy) to the list of policies */
106 if(plugin_tree){
107 plugin_tree_last->next_policy = temp_plugin_rules;
108 } else {
109 plugin_tree = temp_plugin_rules;
110 }
111 plugin_tree_last = temp_plugin_rules;
112
113 /* start a new rules tree for the next policy */
114 temp_plugin_rules = NULL;
115
116 /* iterate to next policy */
117 temp_policy = temp_policy->next;
118
119 }
120 return plugin_tree;
121 }
122
123 void free_args(int argc, char** argv){
124 for(; argc > 0; argc--){
125 free(argv[argc-1]);
126 }
127 free(argv);
128 }
129
130 void print_plugin_tree_recursive(eef_plugindl_t* plugin_tree, int depth){
131 int num_policy = 1;
132
133 while(plugin_tree){
134 if(depth==0){
135 printf("Policy %i\n", num_policy);
136 }
137
138 indent_stdout(depth);
139 printf("rule %s\n", plugin_tree->pluginname);
140 indent_stdout(depth);
141 printf("-------------------------\n");
142
143 if(plugin_tree->true_branch){
144 indent_stdout(depth+1);
145 printf("True: ");
146 print_plugin_tree_recursive(plugin_tree->true_branch, depth+1);
147 }
148
149 if(plugin_tree->false_branch){
150 indent_stdout(depth+1);
151 printf("False: ");
152 print_plugin_tree_recursive(plugin_tree->false_branch, depth+1);
153 }
154 printf("\n");
155
156 /* code to break from the loop */
157 if(depth==0){
158 /* top level plugin - a policy */
159 num_policy++;
160 /* iterate to next policy */
161 plugin_tree = plugin_tree->next_policy;
162 } else {
163 /* prevent recursive printing of everything below top level plugins */
164 plugin_tree = NULL;
165 }
166 }
167
168 return;
169
170 }
171
172 void indent_stdout(depth){
173 int depth_cache;
174 for(depth_cache = depth; depth_cache > 0; depth_cache--){
175 printf(" ");
176 }
177 return;
178 }
179
180 /*! sets the path to modules directory */
181 void set_pdl_path(record_t* path){
182 size_t path_size = 0;
183 size_t string_size = (sizeof(char) * (strlen(path->string)+2)); /* size of string + extra slash + null byte */
184 _pdl_path = "";
185
186 /*struct stat sb;*/
187 /*if stat(MODUL*/
188
189 if(string_size < FILENAME_MAX){
190 path_size = string_size;
191 } else {
192 path_size = FILENAME_MAX;
193 }
194
195 if((_pdl_path = calloc(1, path_size))){
196 strncpy(_pdl_path, path->string, path_size);
197 strncat(_pdl_path, "/", 1);
198 }
199
200 eef_log(LOG_DEBUG, "Found a new modules path: %s\n", _pdl_path);
201
202 free(path->string);
203 free(path);
204 }
205
206 /*! Handles a variable representing a plug-in; creates a structure containing its values and adds it to the list of var_t structs variables_list */
207 void add_variable(record_t* name, record_t* value){
208 eef_log(LOG_DEBUG, "Added variable name: %s\n", name->string);
209 eef_log(LOG_DEBUG, "Added variable value: %s\n", value->string);
210
211 /* allocate struct and populate fields */
212 if((current_variable = calloc(1,sizeof(var_t)))){
213 current_variable->name = strdup(name->string);
214 current_variable->value = strdup(value->string);
215 current_variable->lineno = name->lineno;
216 current_variable->next = NULL;
217 } else {
218 eef_log(LOG_ERR, "Out of memory!");
219 }
220
221 /* append to the end of the list */
222 if(variables_list){
223 variables_list_last->next = current_variable;
224 } else {
225 variables_list = current_variable;
226 }
227 variables_list_last = current_variable;
228
229 /* clean up */
230 free(name->string);
231 free(name);
232 free(value->string);
233 free(value);
234 }
235
236 /* TODO I think this function is a bit of a kludge and could probably be rewritten to be more efficient and more legible - I think it might do too much, so extracting some functions might help */
237 /*! Appends a rule to the global rules_list, which is to be added to a policy when add_policy is called
238 Will return an error when:
239 - adding the rule to the list will create a recursion in the tree of rules
240 - an unknown variable is referenced
241 */
242 rule_t* add_rule(record_t* state, record_t* true_branch, record_t* false_branch){
243 rule_t *new_rule = NULL, *new_false_branch = NULL, *new_true_branch = NULL, *recursive_rule = NULL;
244 var_t *temp_var = NULL;
245 char *unknown_var_format_string = "Unknown variable %s at line %i in config file %s";
246
247 if((new_rule = find_state(rules_list, state->string))){
248 eef_log(LOG_WARNING, "State %s at line %i is already in use at line %i.\n", state->string, state->lineno, new_rule->lineno);
249 } else {
250 /*find variables for rule */
251 temp_var = get_variable_by_name(state->string);
252 if(temp_var == NULL){
253 /* Errorous state - variable referenced in rule not previously defined */
254 eef_log(LOG_ERR, unknown_var_format_string, state->string, state->lineno, config_file_s);
255 }
256 if(temp_var != NULL){
257 if((new_rule = calloc(1, sizeof(rule_t)))){
258 /* populate fields of current state */
259 new_rule->state = strdup(state->string);
260 new_rule->lineno = state->lineno;
261
262 /* populate fields of branches */
263 if(false_branch){
264 temp_var = get_variable_by_name(false_branch->string);
265 if(temp_var == NULL){
266 /* Errorous state - variable referenced in rule not previously defined */
267 eef_log(LOG_ERR, unknown_var_format_string, false_branch->string, false_branch->lineno, config_file_s);
268 return NULL;
269 }
270 if((new_false_branch = calloc(1, sizeof(rule_t)))){
271 new_false_branch->state = strdup(false_branch->string);
272 new_false_branch->lineno = false_branch->lineno;
273 new_rule->false_branch = new_false_branch;
274 }
275 }
276
277 if(true_branch){
278 temp_var = get_variable_by_name(true_branch->string);
279 if(temp_var == NULL){
280 /* Errorous state - variable referenced in rule not previously defined */
281 eef_log(LOG_ERR, unknown_var_format_string, true_branch->string, true_branch->lineno, config_file_s);
282 return NULL;
283 }
284 if((new_true_branch = calloc(1, sizeof(rule_t)))){
285 new_true_branch->state = strdup(true_branch->string);
286 new_true_branch->lineno = true_branch->lineno;
287 new_rule->true_branch = new_true_branch;
288 }
289 }
290
291 /* check for recursion */
292 if((recursive_rule = check_for_recursion(rules_list, new_rule))){
293 eef_log(LOG_WARNING, "Rule %s at line %i leads to recursion into state %s", new_rule->state, new_rule->lineno, recursive_rule->state);
294 } else {
295 /* add new rule at the end of the rules list */
296 if(rules_list){
297 rules_list_last->next = new_rule;
298 } else {
299 rules_list = new_rule;
300 }
301 rules_list_last = new_rule;
302 /*eef_log(LOG_DEBUG, "Added a new rule: %s\n", new_rule->state);*/
303 }
304
305 } else {
306 eef_log(LOG_ERR, "Out of memory!");
307 }
308 }
309 }
310
311 /* clean up */
312 if(state != NULL){
313 free(state->string);
314 free(state);
315 }
316 if(true_branch != NULL){
317 free(true_branch->string);
318 free(true_branch);
319 }
320 if(false_branch != NULL){
321 free(false_branch->string);
322 free(false_branch);
323 }
324
325 return new_rule;
326 }
327
328 /* Tries to find a recursion in the list of rules by iterating through all the tree branches. When the same rule is encountered in the current list a recursion has been found */
329 rule_t* check_for_recursion(rule_t* rule_l, rule_t* rule_r){
330 rule_t* temp_rule = rule_l;
331
332 /* right hand rule leads to its own recursive state */
333 /* still need to find a way to reuse the code from the while loop to do this check */
334 if(rule_r){
335 if(rule_r->true_branch){
336 if(strcmp(rule_r->state, rule_r->true_branch->state) == 0){
337 return rule_r->true_branch;
338 }
339 }
340
341 if(rule_r->false_branch){
342 if(strcmp(rule_r->state, rule_r->false_branch->state) == 0){
343 return rule_r->false_branch;
344 }
345 }
346 }
347
348 /* iterate list of rules */
349 while(temp_rule){
350 if((temp_rule != NULL) && (rule_r != NULL)){
351 /* left hand and right hand state are equal */
352 if(strcmp(temp_rule->state, rule_r->state) == 0){
353 return rule_r;
354 }
355
356 /* start state and true branch of right hand rule are equal */
357 if(rule_r->true_branch){
358 if(strcmp(temp_rule->state, rule_r->true_branch->state) == 0){
359 return rule_r->true_branch;
360 }
361 }
362
363 /* start state and false branch of right hand side are equal */
364 if(rule_r->false_branch){
365 if(strcmp(temp_rule->state, rule_r->false_branch->state) == 0){
366 return rule_r->false_branch;
367 }
368 }
369 }
370
371 /* move to next rule */
372 temp_rule = temp_rule->next;
373 }
374 return NULL;
375 }
376
377 /*! Tries to find specified state in the rules_list */
378 rule_t* find_state(rule_t* rule, const char* state){
379 if(!rule || !state){
380 return NULL;
381 }
382
383 /* iterate while the rule isn't associated with the given state */
384 while(rule && strcmp(state, rule->state)){
385 rule = rule->next;
386 }
387 return rule;
388 }
389
390 /*! Adds a new policy_t structure to the policies_list which will hold the current rules_list. rules_list is nulled after creating a policy so a new list can be created for the next policy */
391 void add_policy(record_t* policy, rule_t* top_rule){
392 policy_t* new_policy = NULL;
393 /*eef_log(LOG_DEBUG, "Found a new policy: %s\n", policy->string);*/
394
395 if((new_policy = calloc(1, sizeof(policy_t)))){
396 new_policy->name = strdup(policy->string);
397 new_policy->lineno = policy->lineno;
398 new_policy->rules = top_rule;
399 }
400
401 /* append to the end of the list */
402 if(policies_list){
403 policies_list_last->next = new_policy;
404 } else {
405 policies_list = new_policy;
406 }
407 policies_list_last = new_policy;
408
409 rules_list = NULL;
410
411 free(policy->string);
412 free(policy);
413 }
414
415
416 void print_policies(){
417 rule_t* temp_rule = NULL;
418 policy_t* temp_policy = policies_list;
419
420 while(temp_policy){
421 temp_rule = temp_policy->rules;
422 eef_log(LOG_DEBUG, "Policy: %s\n", temp_policy->name);
423 while(temp_rule){
424 eef_log(LOG_DEBUG, " | Rule %s\n", temp_rule->state);
425 eef_log(LOG_DEBUG, " -------------------------\n");
426 if(temp_rule->true_branch){
427 eef_log(LOG_DEBUG, " True branch: %s\n", temp_rule->true_branch->state);
428 }
429 /*if(temp_rule->true_branch && temp_rule->false_branch){*/
430 /*}*/
431 if(temp_rule->false_branch){
432 eef_log(LOG_DEBUG, " False branch: %s\n", temp_rule->false_branch->state);
433 }
434 eef_log(LOG_DEBUG, "\n");
435 temp_rule = temp_rule->next;
436 }
437 temp_policy = temp_policy->next;
438 }
439 }
440
441 /*! concatenates two strings */
442 record_t* concat_strings(record_t* r1, record_t* r2){
443 record_t* new_record;
444 /*eef_log(LOG_DEBUG, "Concating: %s with %s\n", r1->string, r2->string);*/
445 if((new_record = malloc(sizeof(record_t)))){
446 if((new_record->string =
447 calloc(1, sizeof(char)*(strlen(r1->string) + strlen(r2->string)+1)))){
448 strncat(new_record->string, r1->string, strlen(r1->string));
449 strncat(new_record->string, r2->string, strlen(r2->string));
450 free(r1->string);
451 free(r1);
452 free(r2->string);
453 free(r2);
454 return new_record;
455 }
456 }
457 return NULL;
458 }
459
460 /*! concatenates two strings with a space in between */
461 record_t* concat_strings_with_space(record_t *r1, record_t* r2){
462 record_t *r;
463 /*eef_log(LOG_DEBUG, "Concating: %s with %s with spaces\n", r1->string, r2->string);*/
464 if((r = malloc(sizeof(record_t)))){
465 r->string = calloc(1,(sizeof(char)*(strlen(r1->string)+strlen(r2->string)+2)));
466 strncat(r->string, r1->string, strlen(r1->string));
467 strncat(r->string, " ", 1);
468 strncat(r->string, r2->string, strlen(r2->string));
469 free(r1->string);
470 free(r1);
471 free(r2->string);
472 free(r2);
473 return r;
474 }
475 return NULL;
476 }
477
478 /*! logs errors encountered during parsing */
479 int yyerror(char* string){
480 eef_log(LOG_ERR, "Parse error: %s at line %i in config file %s", string, lineno, config_file_s);
481 return 0;
482 }
483
484 /*! get variable from list */
485 var_t* get_variable_by_name(char* name){
486 for(current_variable = variables_list; current_variable != NULL; current_variable = current_variable->next){
487 if(!strncmp(name, current_variable->name, strlen(current_variable->name))){
488 return current_variable;
489 }
490 }
491 return NULL;
492 }
493
494 /*TODO*/
495 /*! Removes a policy from the list of policies */
496 void remove_policy(record_t* policy){
497 eef_log(LOG_DEBUG, "Deleted policy: %s\n", policy->string);
498 free(policy->string);
499 free(policy);
500 }
501
502 /*! converts a string to an array of strings by splitting it at each \t delimiter
503 - overwrites the second argument with a pointer to the number of elements in the array */
504 char** _var_to_argv(char* value, int *argc){
505 char *start_of_arg = NULL, *copy_of_value = NULL, **argv = NULL;
506 char *delimiters = " \t";
507 size_t size_of_arg = 0, size_of_array, i = 0;
508 char *str_ptr;
509 copy_of_value = strdup(value);
510 size_of_array = (sizeof(char)*(strlen(copy_of_value)+1));
511 if((argv = calloc(1, size_of_array)) != NULL){
512 start_of_arg = strtok_r(copy_of_value, delimiters, &str_ptr);
513 while(start_of_arg != NULL){
514 size_of_arg = (sizeof(char)*(strlen(start_of_arg)+1));
515 if((argv[i] = calloc(1, size_of_arg))){
516 memcpy(argv[i], start_of_arg, size_of_arg);
517 start_of_arg = strtok_r(NULL, delimiters, &str_ptr);
518 i++;
519 }
520 }
521 }
522 free(copy_of_value);
523 if(i < ARG_MAX){
524 *argc = i;
525 } else {
526 *argc = ARG_MAX;
527 }
528 return argv;
529 }
530
531 /*! returns pdl path found in parsed config file */
532 const char* get_pdl_path(){
533 return _pdl_path;
534 }
535
536 /*! Iterates list of policies and the rules they contain and tries to add the specified plug-ins to the plugin manager */
537 EES_RC add_plugins(){
538 char** argv;
539 int argc;
540 EES_RC plugin_initialized_ok = EES_SUCCESS;
541 /*policy_t *temp_policy = policies_list, *last_policy = NULL;*/
542 /*rule_t *temp_rule = NULL;*/
543 var_t *temp_var = variables_list;
544
545 while((temp_var != NULL) && (plugin_initialized_ok == EES_SUCCESS)){
546 /*printf("Var: %s\n", temp_var->name);*/
547 /*printf("Plug-in: %s\n", temp_var->value);*/
548 argv = _var_to_argv(temp_var->value, &argc);
549
550 /* this is a callout to the plug-in manager, which adds a single plug-in to its list */
551 plugin_initialized_ok = add_plugin(argc, argv);
552
553 /* Move to next variable */
554 temp_var = temp_var->next;
555 }
556
557 return plugin_initialized_ok;
558 }
559
560 /*! Iterates the list of var_t structures and tries to free them */
561 EES_RC clean_variables_list(){
562 current_variable = variables_list;
563 while(current_variable){
564 free(current_variable->name);
565 free(current_variable->value);
566
567 /* Move to next variable */
568 variables_list_last = current_variable;
569 current_variable = current_variable->next;
570
571 /* Clean last variable struct */
572 free(variables_list_last);
573 }
574 return EES_SUCCESS;
575 }
576
577 /*! Iterates the list of rule_t structures starting with the passed rule and tries to free them and their true/false branches */
578 EES_RC clean_rules_list(rule_t* top_rule){
579 rule_t* temp_rule = top_rule;
580 rule_t* last_rule;
581 while(temp_rule){
582 /* Clean rules in true branch */
583 if(temp_rule->true_branch){
584 clean_rules_list(temp_rule->true_branch);
585 }
586
587 /* Clean rules in false branch */
588 if(temp_rule->false_branch){
589 clean_rules_list(temp_rule->false_branch);
590 }
591
592 /* Clean rule state */
593 free(temp_rule->state);
594
595 /* Move to next rule */
596 last_rule = temp_rule;
597 temp_rule = temp_rule->next;
598
599 /* Clean rule struct */
600 free(last_rule);
601 }
602 return EES_SUCCESS;
603 }
604
605 /*! Iterates the list of policy_t structures and tries to free them and their rules */
606 EES_RC clean_policies_list(){
607 policy_t *temp_policy = policies_list, *last_policy = NULL;
608 while(temp_policy){
609 /* Clean policy fields */
610 clean_rules_list(temp_policy->rules);
611 free(temp_policy->name);
612
613 /* Move to next policy */
614 last_policy = temp_policy;
615 temp_policy = temp_policy->next;
616 free(last_policy);
617 }
618 return EES_SUCCESS;
619 }
620
621 /*! Terminates the parser and tries to free all used memory */
622 EES_RC pdl_term(){
623 clean_variables_list();
624 clean_policies_list();
625 free(_pdl_path);
626
627 if(config_file_fp != NULL){
628 /* This is the preferred way of cleaning up various flex versions - See: http://flex.sourceforge.net/manual/Memory-leak-_002d-16386-bytes-allocated-by-malloc_002e.html#Memory-leak-_002d-16386-bytes-allocated-by-malloc_002e */
629 #if HAVE_YYLEX_DESTROY /* macro set by configure script */
630 yylex_destroy();
631 #else
632 /*eef_log(LOG_WARNING, "Lex function yylex_destroy() not available - possibly unable to free allocated memory for evaluation manager\n");*/
633 #if HAVE_FLEX
634 delete_lex_buffer(); /* this function is defined in pdl_lex.l */
635 /*eef_log(LOG_INFO, "Managed to free allocated memory for evaluation manager\n"); */
636 #else
637 eef_log(LOG_WARNING, "Lex functions yylex_destroy() and yy_delete_buffer() are both not available - unable to free allocated memory for evaluation manager\n");
638 #endif
639 #endif
640
641 if((fclose(config_file_fp)==0) ){
642 return EES_SUCCESS;
643 }
644 }
645 return EES_FAILURE;
646 }
647
648 /*! TODO */
649 EES_RC allow_rules(int val){
650 /*printf("Allowed rules: %i\n", val);*/
651 return EES_SUCCESS;
652 }
653
654 /*! TODO */
655 EES_RC allowed_policy_rule(const char* label){
656 /*printf("Allowed policy rule: %s\n", label);*/
657 return EES_SUCCESS;
658 }

grid.support@nikhef.nl
ViewVC Help
Powered by ViewVC 1.1.28