/[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 1158 - (show annotations) (download) (as text)
Fri Nov 20 14:04:55 2009 UTC (12 years, 2 months ago) by aramv
File MIME type: text/x-chdr
File size: 19534 byte(s)
Added code to specify allowed policies and clean those not allowed
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 /* tries to link all policy rules to a plugin in the plugin manager */
315 EES_RC link_rules_to_plugins(policy_t* policies){
316 policy_t *temp_policy = policies;
317 rule_t *temp_rule = NULL;
318 var_t *temp_var = NULL;
319
320 while(temp_policy){
321 temp_rule = temp_policy->rules;
322 while(temp_rule){
323 temp_var = get_variable_by_name(temp_rule->state);
324 temp_rule->plugin = get_plugin(temp_var->value);
325 temp_rule = temp_rule->next;
326 }
327 temp_policy = temp_policy->next;
328 }
329 return EES_SUCCESS;
330 }
331
332 /* iterates the policies and removes those that are not explicitly named in the passed array of strings */
333 policy_t* reduce_policy_tree(policy_t* policies, int number_of_policies, char* names_of_policies[]){
334 int i, policy_should_be_removed;
335 policy_t *temp_policy = policies;
336 while(temp_policy){
337 policy_should_be_removed = 1;
338 printf("Checking policy: %s\n", temp_policy->name);
339 for(i = 0; i < number_of_policies; i++){
340 if(strcmp(temp_policy->name, names_of_policies[i]) == 0){
341 /* if the policy is in the named list, we can continue to the next plugin */
342 printf("Allowed policy: %s\n", names_of_policies[i]);
343 policy_should_be_removed = 0;
344 break;
345 }
346 }
347
348 if(policy_should_be_removed){
349 printf("Removing not-allowed policy: %s\n", temp_policy->name);
350 remove_policy_by_name(temp_policy->name);
351 }
352 /* Move to next policy */
353 temp_policy = temp_policy->next;
354 }
355 return policies;
356 }
357
358 /*! concatenates two strings */
359 record_t* concat_strings(record_t* r1, record_t* r2){
360 record_t* new_record;
361 /*eef_log(LOG_DEBUG, "Concating: %s with %s\n", r1->string, r2->string);*/
362 if((new_record = malloc(sizeof(record_t)))){
363 if((new_record->string =
364 calloc(1, sizeof(char)*(strlen(r1->string) + strlen(r2->string)+1)))){
365 strncat(new_record->string, r1->string, strlen(r1->string));
366 strncat(new_record->string, r2->string, strlen(r2->string));
367 free(r1->string);
368 free(r1);
369 free(r2->string);
370 free(r2);
371 return new_record;
372 }
373 }
374 return NULL;
375 }
376
377 /*! concatenates two strings with a space in between */
378 record_t* concat_strings_with_space(record_t *r1, record_t* r2){
379 record_t *r;
380 /*eef_log(LOG_DEBUG, "Concating: %s with %s with spaces\n", r1->string, r2->string);*/
381 if((r = malloc(sizeof(record_t)))){
382 r->string = calloc(1,(sizeof(char)*(strlen(r1->string)+strlen(r2->string)+2)));
383 strncat(r->string, r1->string, strlen(r1->string));
384 strncat(r->string, " ", 1);
385 strncat(r->string, r2->string, strlen(r2->string));
386 free(r1->string);
387 free(r1);
388 free(r2->string);
389 free(r2);
390 return r;
391 }
392 return NULL;
393 }
394
395 /*! logs errors encountered during parsing */
396 int yyerror(char* string){
397 eef_log(LOG_ERR, "Parse error: %s at line %i in config file %s", string, lineno, config_file_s);
398 return 0;
399 }
400
401 /*! get variable from list */
402 var_t* get_variable_by_name(char* name){
403 for(current_variable = variables_list; current_variable != NULL; current_variable = current_variable->next){
404 if(!strncmp(name, current_variable->name, strlen(current_variable->name))){
405 return current_variable;
406 }
407 }
408 return NULL;
409 }
410
411 /*! Removes a policy from the list of policies */
412 void remove_policy(record_t* policy){
413 policy_t *temp_policy = policies_list, *next_policy = NULL;
414 eef_log(LOG_DEBUG, "Deleted policy: %s\n", policy->string);
415
416 while(temp_policy){
417 if(strcmp(temp_policy->name, policy->string) == 0){
418 /* target policy was found */
419 next_policy = temp_policy->next;
420
421 /* Clean policy fields */
422 clean_rules_list(temp_policy->rules);
423 free(temp_policy->name);
424 free(temp_policy);
425 }
426
427 /* Move to next policy */
428 temp_policy = next_policy;
429 }
430
431 free(policy->string);
432 free(policy);
433 return;
434 }
435
436 /*! Removes a policy from the list of policies */
437 void remove_policy_by_name(char* policy){
438 policy_t *temp_policy = policies_list, *next_policy = NULL;
439 eef_log(LOG_DEBUG, "Deleted policy: %s\n", policy);
440
441 while(temp_policy){
442 if(strcmp(temp_policy->name, policy) == 0){
443 /* target policy was found */
444 next_policy = temp_policy->next;
445
446 /* Clean policy fields */
447 clean_rules_list(temp_policy->rules);
448 free(temp_policy->name);
449 free(temp_policy);
450 }
451
452 /* Move to next policy */
453 temp_policy = next_policy;
454 }
455 return;
456 }
457
458 /*! converts a string to an array of strings by splitting it at each \t delimiter
459 - overwrites the second argument with a pointer to the number of elements in the array */
460 char** _var_to_argv(char* value, int *argc){
461 char *start_of_arg = NULL, *copy_of_value = NULL, **argv = NULL;
462 char *delimiters = " \t";
463 size_t size_of_arg = 0, size_of_array, i = 0;
464 char *str_ptr;
465 copy_of_value = strdup(value);
466 size_of_array = (sizeof(char)*(strlen(copy_of_value)+1));
467 if((argv = calloc(1, size_of_array)) != NULL){
468 start_of_arg = strtok_r(copy_of_value, delimiters, &str_ptr);
469 while(start_of_arg != NULL){
470 size_of_arg = (sizeof(char)*(strlen(start_of_arg)+1));
471 if((argv[i] = calloc(1, size_of_arg))){
472 memcpy(argv[i], start_of_arg, size_of_arg);
473 start_of_arg = strtok_r(NULL, delimiters, &str_ptr);
474 i++;
475 }
476 }
477 }
478 free(copy_of_value);
479 if(i < ARG_MAX){
480 *argc = i;
481 } else {
482 *argc = ARG_MAX;
483 }
484 return argv;
485 }
486
487 /*! returns pdl path found in parsed config file */
488 const char* get_pdl_path(){
489 return _pdl_path;
490 }
491
492 /*! Iterates list of policies and the rules they contain and tries to let the plugin manager prepare plugin structs*/
493 EES_RC add_prepared_plugins(){
494 char** argv;
495 int argc;
496 EES_RC plugin_initialized_ok = EES_SUCCESS;
497 var_t *temp_var = variables_list;
498
499 while((temp_var != NULL) && (plugin_initialized_ok == EES_SUCCESS)){
500 argv = _var_to_argv(temp_var->value, &argc);
501
502 /* this is a callout to the plug-in manager, which adds a struct describing a single plug-in to its list */
503 plugin_initialized_ok = add_prepared_plugin(argc, argv);
504
505 /* Move to next variable */
506 temp_var = temp_var->next;
507 }
508
509 return plugin_initialized_ok;
510 }
511
512 /*! Iterates the list of var_t structures and tries to free them */
513 EES_RC clean_variables_list(){
514 current_variable = variables_list;
515 while(current_variable){
516 free(current_variable->name);
517 free(current_variable->value);
518
519 /* Move to next variable */
520 variables_list_last = current_variable;
521 current_variable = current_variable->next;
522
523 /* Clean last variable struct */
524 free(variables_list_last);
525 }
526 return EES_SUCCESS;
527 }
528
529 /*! Iterates the list of rule_t structures starting with the passed rule and tries to free them and their true/false branches */
530 EES_RC clean_rules_list(rule_t* top_rule){
531 rule_t* temp_rule = top_rule;
532 rule_t* last_rule;
533 while(temp_rule){
534 /* Clean rules in true branch */
535 if(temp_rule->true_branch){
536 clean_rules_list(temp_rule->true_branch);
537 }
538
539 /* Clean rules in false branch */
540 if(temp_rule->false_branch){
541 clean_rules_list(temp_rule->false_branch);
542 }
543
544 /* Clean rule state */
545 free(temp_rule->state);
546
547 /* Move to next rule */
548 last_rule = temp_rule;
549 temp_rule = temp_rule->next;
550
551 /* Clean rule struct */
552 free(last_rule);
553 }
554 return EES_SUCCESS;
555 }
556
557 void free_args(int argc, char** argv){
558 for(; argc > 0; argc--){
559 free(argv[argc-1]);
560 }
561 free(argv);
562 }
563
564 /*! Iterates the list of policy_t structures and tries to free them and their rules */
565 EES_RC clean_policies_list(){
566 policy_t *temp_policy = policies_list, *last_policy = NULL;
567 while(temp_policy){
568 /* Clean policy fields */
569 clean_rules_list(temp_policy->rules);
570 free(temp_policy->name);
571
572 /* Move to next policy */
573 last_policy = temp_policy;
574 temp_policy = temp_policy->next;
575 free(last_policy);
576 }
577 return EES_SUCCESS;
578 }
579
580 /*! Terminates the parser and tries to free all used memory */
581 EES_RC pdl_term(){
582 clean_variables_list();
583 clean_policies_list();
584 free(_pdl_path);
585
586 if(config_file_fp != NULL){
587 /* 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 */
588 #if HAVE_YYLEX_DESTROY /* macro set by configure script */
589 yylex_destroy();
590 #else
591 /*eef_log(LOG_WARNING, "Lex function yylex_destroy() not available - possibly unable to free allocated memory for evaluation manager\n");*/
592 #if HAVE_FLEX
593 delete_lex_buffer(); /* this function is defined in pdl_lex.l */
594 /*eef_log(LOG_INFO, "Managed to free allocated memory for evaluation manager\n"); */
595 #else
596 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");
597 #endif
598 #endif
599
600 if((fclose(config_file_fp)==0) ){
601 return EES_SUCCESS;
602 }
603 }
604 return EES_FAILURE;
605 }
606
607 /*! TODO */
608 EES_RC allow_rules(int val){
609 /*printf("Allowed rule: %i\n", val);*/
610 return EES_SUCCESS;
611 }
612
613 /*! TODO */
614 EES_RC allowed_policy_rule(const char* label){
615 /*printf("Allowed policy rule: %s\n", label);*/
616 return EES_SUCCESS;
617 }

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