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

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