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

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