1 |
#include <stdlib.h> |
2 |
#include <string.h> |
3 |
#include <ctype.h> |
4 |
|
5 |
#include "gridmapdir.h" |
6 |
#include "fileutil.h" |
7 |
|
8 |
#define WHITESPACE_CHARS " \t\n" |
9 |
#define QUOTING_CHARS "\"" |
10 |
#define ESCAPING_CHARS "\\" |
11 |
#define COMMENT_CHARS "#" |
12 |
#define WILD_CHARS '*' |
13 |
#define DIGIT_CHARS "0123456789" |
14 |
#define USERID_SEP_CHARS "," |
15 |
#define USERID_TERMINATOR_CHARS USERID_SEP_CHARS WHITESPACE_CHARS |
16 |
#define NUL '\0' |
17 |
#define USERID_CHUNK_SIZE 4 |
18 |
|
19 |
|
20 |
/****************************************************************************** |
21 |
Function: gridmap_parse_line |
22 |
Description: |
23 |
Given a line from the gridmap file, parse it returning |
24 |
a gridmap_line_t structure. line is modified during parsing. |
25 |
|
26 |
The format of the line is expected to be: |
27 |
|
28 |
<DN> <userid>[,<userid>[,<userid>...]] |
29 |
|
30 |
Leading and trailing whitespace is ignored. |
31 |
|
32 |
userids must only have a comma between them, no whitespace. |
33 |
|
34 |
Anything after the userids is ignored. |
35 |
|
36 |
Anything after an unescaped comment character is ignored. |
37 |
|
38 |
Parameters: |
39 |
line, a pointer to the line from the file (NUL-terminated string) |
40 |
|
41 |
gline, a pointer to a pointer that will be set to point at |
42 |
the gridmap_line_t structure containing the line information. |
43 |
If the line contains no content, gline will be set to NULL. |
44 |
|
45 |
Returns: |
46 |
0 on success, non-zero on error. |
47 |
|
48 |
******************************************************************************/ |
49 |
static int gridmap_parse_line(char * line, gridmap_line_t ** gline); |
50 |
static int xdigit_to_value(char xdigit); |
51 |
static int gridmap_parse_globusid(const char * unparsed, char ** pparsed); |
52 |
static void gridmap_free_gridmap_line(gridmap_line_t *gline); |
53 |
static int match_dn(const char * dn, const char * match, unsigned short matching_type); |
54 |
|
55 |
static int match_dn(const char * match, const char * to_match, unsigned short matching_type) { |
56 |
if ( (matching_type&MATCH_WILD_CHARS) == MATCH_WILD_CHARS ){ |
57 |
return fnmatch(match, to_match, 0); |
58 |
} else { |
59 |
return strcmp(match, to_match); |
60 |
} |
61 |
} |
62 |
|
63 |
gridmap_line_t * find_mapping(const gridmap_list_t * list, const char * to_match, unsigned short matching_type) { |
64 |
const gridmap_list_t * current = list; |
65 |
while (current != NULL){ |
66 |
if (match_dn(current->line->match,to_match,matching_type) == 0) |
67 |
return current->line; |
68 |
current = current->next; |
69 |
if (current == list) |
70 |
break; |
71 |
} |
72 |
return NULL; |
73 |
} |
74 |
|
75 |
void gridmap_list_free(gridmap_list_t * list){ |
76 |
gridmap_list_t * current = list; |
77 |
gridmap_list_t * working = NULL; |
78 |
while (current != NULL){ |
79 |
working = current; |
80 |
current = current->next; |
81 |
|
82 |
gridmap_free_gridmap_line(working->line); |
83 |
free(working); |
84 |
} |
85 |
} |
86 |
|
87 |
int parse_gridmapfile(const char * image_map_file, gridmap_list_t ** list){ |
88 |
gridmap_list_t * result = NULL; |
89 |
gridmap_list_t * resultlast = NULL; |
90 |
gridmap_list_t * resultnew = NULL; |
91 |
gridmap_line_t * gline = NULL; |
92 |
char * contents = NULL; |
93 |
char * linestart = NULL; |
94 |
char * lineend = NULL; |
95 |
int eof = 0; |
96 |
int read; |
97 |
|
98 |
read = cgul_read_config(image_map_file, &contents, getuid(), getgid()); |
99 |
if (read != 0){ |
100 |
// EEF_log(LOG_ERR,"Unable to safely open the image map file '%s', reason: %d (for an explenation of the reason look in cgul/fileutil/fileutil.h)",image_map_file,read); |
101 |
goto failure; |
102 |
} |
103 |
|
104 |
linestart = contents; |
105 |
while (eof == 0){ |
106 |
lineend = linestart; |
107 |
while (*lineend != '\n'){ |
108 |
if (*lineend == '\0'){ |
109 |
eof = 1; |
110 |
break; |
111 |
} |
112 |
lineend++; |
113 |
} |
114 |
*lineend = '\0'; |
115 |
|
116 |
read = gridmap_parse_line(linestart, &gline); |
117 |
linestart = lineend+1; |
118 |
|
119 |
/* error which is unrecoverable only will result in a non 0 value */ |
120 |
if (read != 0) { |
121 |
goto failure; |
122 |
} |
123 |
|
124 |
/* line consisting of comment or whitespaces only */ |
125 |
if (gline == NULL) |
126 |
continue; |
127 |
|
128 |
resultnew = calloc(1,sizeof(gridmap_list_t)); |
129 |
resultnew->line = gline; |
130 |
|
131 |
if (result == NULL){ |
132 |
resultlast = result = resultnew; |
133 |
} else { |
134 |
resultlast->next = resultnew; |
135 |
resultlast = resultnew; |
136 |
} |
137 |
/* be sure to point the last result to the actual last result in the list */ |
138 |
while (resultlast->next != NULL) |
139 |
resultlast = resultlast->next; |
140 |
|
141 |
gline = NULL; |
142 |
resultnew = NULL; |
143 |
} |
144 |
|
145 |
*list = result; |
146 |
|
147 |
return 0; |
148 |
failure: |
149 |
gridmap_free_gridmap_line(gline); |
150 |
gline = NULL; |
151 |
|
152 |
free(contents); |
153 |
contents = NULL; |
154 |
|
155 |
gridmap_list_free(result); |
156 |
result = NULL; |
157 |
resultlast = NULL; |
158 |
|
159 |
return -1; |
160 |
} |
161 |
|
162 |
static int gridmap_parse_line(char * line, gridmap_line_t ** gline) { |
163 |
charlist_t * mappings = NULL; |
164 |
charlist_t * mappingsnew = NULL; |
165 |
char * dn_end; |
166 |
char * parsed_dn = NULL; |
167 |
gridmap_line_t * gline_tmp = NULL; |
168 |
|
169 |
|
170 |
/* Check arguments */ |
171 |
if ((line == NULL) || (gline == NULL)) |
172 |
goto error; |
173 |
|
174 |
/* Skip over leading whitespace */ |
175 |
line += strspn(line, WHITESPACE_CHARS); |
176 |
|
177 |
/* Check for comment at start of line and ignore line if present */ |
178 |
if (strchr(COMMENT_CHARS, *line) != NULL) { |
179 |
/* Ignore line, return NULL gline */ |
180 |
*gline = NULL; |
181 |
return 0; |
182 |
} |
183 |
|
184 |
/* Check for empty line */ |
185 |
if (*line == NUL) { |
186 |
/* Empty line, return NULL gline. */ |
187 |
*gline = NULL; |
188 |
return 0; |
189 |
} |
190 |
|
191 |
/* Is DN quoted? */ |
192 |
if (strchr(QUOTING_CHARS, *line) != NULL) { |
193 |
/* |
194 |
* Yes, skip over opening quote and look for unescaped |
195 |
* closing double quote |
196 |
*/ |
197 |
line++; |
198 |
dn_end = line; |
199 |
while (strchr(QUOTING_CHARS, *dn_end) == NULL){ |
200 |
if (strchr(ESCAPING_CHARS, *dn_end) != NULL) |
201 |
dn_end++; |
202 |
if (*dn_end == 0) |
203 |
goto error; |
204 |
dn_end++; |
205 |
} |
206 |
} else { |
207 |
/* No, just find next whitespace */ |
208 |
dn_end = line + strcspn(line, WHITESPACE_CHARS); |
209 |
|
210 |
if (*dn_end == NUL) |
211 |
goto error; /* Nothing after DN */ |
212 |
} |
213 |
|
214 |
/* NUL terminate DN and parse */ |
215 |
*dn_end = NUL; |
216 |
|
217 |
if (gridmap_parse_globusid(line, &parsed_dn) != 0) |
218 |
return -1; |
219 |
|
220 |
/* Skip over closing delim and any whitespace after DN */ |
221 |
line = dn_end + 1; |
222 |
line += strspn(line, WHITESPACE_CHARS); |
223 |
|
224 |
/* Parse list of unix user ID seperated by USERID_SEP_CHARS */ |
225 |
while ((*line != NUL) && (strchr(WHITESPACE_CHARS, *line) == NULL)) { |
226 |
int mapping_len; |
227 |
char * mapping; |
228 |
|
229 |
/* Find end of this userid */ |
230 |
mapping_len = strcspn(line, USERID_TERMINATOR_CHARS); |
231 |
|
232 |
mapping = strndup(line,mapping_len); |
233 |
if (mapping == NULL) |
234 |
goto error; |
235 |
|
236 |
mappingsnew = charlist_add_char_ptr_own(mappings, mapping); |
237 |
/* test for the memory beeing available */ |
238 |
if (mappingsnew == NULL){ |
239 |
/* free the local char ptr */ |
240 |
free(mapping); |
241 |
|
242 |
goto error; |
243 |
} |
244 |
|
245 |
mappings = mappingsnew; |
246 |
|
247 |
line += mapping_len; |
248 |
|
249 |
/* If we're on a seperator character, skip over it */ |
250 |
if (strchr(USERID_SEP_CHARS, *line) != NULL) |
251 |
line++; |
252 |
} |
253 |
|
254 |
/* |
255 |
* There might be more stuff on the line, but we're ignoring |
256 |
* it for now. |
257 |
*/ |
258 |
|
259 |
/* Ok, build our gridmap_line_t structure */ |
260 |
gline_tmp = malloc(sizeof(*gline_tmp)); |
261 |
|
262 |
if (gline_tmp == NULL) |
263 |
goto error; |
264 |
|
265 |
gline_tmp->match = parsed_dn; |
266 |
gline_tmp->mappings = mappings; |
267 |
|
268 |
*gline = gline_tmp; |
269 |
|
270 |
return 0; |
271 |
|
272 |
error: |
273 |
free(parsed_dn); |
274 |
parsed_dn = NULL; |
275 |
|
276 |
charlist_free(mappings); |
277 |
|
278 |
free(gline_tmp); |
279 |
|
280 |
return -1; |
281 |
|
282 |
} /* gridmap_parse_line() */ |
283 |
|
284 |
/****************************************************************************** |
285 |
Function: gridmap_parse_globusid |
286 |
Description: |
287 |
Given a pointer to a string containing the globusid from the |
288 |
gridmap file, return a pointer to a string containing the |
289 |
parsed from of the id. |
290 |
|
291 |
Specifically handle backslashed characters - e.g. '\\', |
292 |
'\x4a' or '\37'. |
293 |
|
294 |
Parameters: |
295 |
unparsed, pointer to unparsed string |
296 |
|
297 |
pparsed, pointer to pointer that should be set to point at |
298 |
allocated parsed string |
299 |
|
300 |
Returns: |
301 |
0 on success |
302 |
non-zero on error. |
303 |
|
304 |
******************************************************************************/ |
305 |
static int gridmap_parse_globusid(const char * unparsed, char ** pparsed) { |
306 |
int escaped = 0; /* Is the current character escaped? (Previous char was backslash) */ |
307 |
char * buffer = NULL; /* Buffer we are putting resulting name into */ |
308 |
int buffer_len = 0; /* Buffer's length in bytes */ |
309 |
int buffer_index = 0; /* And our current position in buffer */ |
310 |
char unparsed_char; /* Character we're currently looking at */ |
311 |
|
312 |
|
313 |
/* Check input parameters for legality */ |
314 |
if ((unparsed == NULL) || (pparsed == NULL)) |
315 |
return -1; |
316 |
|
317 |
buffer_len = strlen(unparsed); |
318 |
buffer = malloc(buffer_len); |
319 |
if (buffer == NULL) |
320 |
return -1; |
321 |
|
322 |
/* Walk through the name, parsing as we go */ |
323 |
while ((unparsed_char = *(unparsed++)) != NUL){ |
324 |
/* Unescaped backslash */ |
325 |
if (strchr(ESCAPING_CHARS, unparsed_char) && !escaped) { |
326 |
escaped = 1; |
327 |
continue; |
328 |
} |
329 |
|
330 |
/* Escaped hex character - e.g. '\xfe' */ |
331 |
if ((unparsed_char == 'x') && escaped) { |
332 |
if (isxdigit(*unparsed) && isxdigit(*(unparsed + 1))) { |
333 |
/* Set unparsed_char to value represented by hex value */ |
334 |
unparsed_char = (xdigit_to_value(*unparsed) << 4) + xdigit_to_value(*(unparsed + 1)); |
335 |
unparsed += 2; |
336 |
} |
337 |
/* else just fall through */ |
338 |
} |
339 |
|
340 |
/* |
341 |
* Ok, we now have the character in unparsed_char to be appended |
342 |
* to our output string. |
343 |
* |
344 |
* First, make sure we have enough room in our output buffer. |
345 |
*/ |
346 |
if ((buffer_index + 1 /* for NUL */) >= buffer_len) { |
347 |
/* Grow buffer */ |
348 |
char *tmp_buffer; |
349 |
buffer_len *= 2; |
350 |
tmp_buffer = realloc(buffer, buffer_len); |
351 |
if (tmp_buffer == NULL) { |
352 |
free(buffer); |
353 |
return -1; |
354 |
} |
355 |
buffer = tmp_buffer; |
356 |
} |
357 |
|
358 |
buffer[buffer_index++] = unparsed_char; |
359 |
buffer[buffer_index] = NUL; |
360 |
|
361 |
escaped = 0; |
362 |
} |
363 |
|
364 |
/* XXX What if escaped == 1 here? */ |
365 |
/* Success */ |
366 |
|
367 |
*pparsed = buffer; |
368 |
|
369 |
return 0; |
370 |
|
371 |
} /* gridmap_parse_globusid() */ |
372 |
|
373 |
/****************************************************************************** |
374 |
Function: xdigit_to_value |
375 |
Description: |
376 |
Convert a ascii character representing a hexadecimal digit |
377 |
into a integer. |
378 |
|
379 |
Parameters: |
380 |
xdigit, character contain the hex digit. |
381 |
|
382 |
Returns: |
383 |
value contained in xdigit, or -1 on error. |
384 |
|
385 |
******************************************************************************/ |
386 |
|
387 |
static int xdigit_to_value(char xdigit) { |
388 |
if ((xdigit >= '0') && (xdigit <= '9')) |
389 |
return (xdigit - '0'); |
390 |
if ((xdigit >= 'a') && (xdigit <= 'f')) |
391 |
return (xdigit - 'a' + 0xa); |
392 |
if ((xdigit >= 'A') && (xdigit <= 'F')) |
393 |
return (xdigit - 'A' + 0xa); |
394 |
/* Illegal digit */ |
395 |
return -1; |
396 |
} /* xdigit_to_value() */ |
397 |
|
398 |
/****************************************************************************** |
399 |
Function: gridmap_free_gridmap_line |
400 |
Description: |
401 |
Frees all memory allocated to a gridmap_line_t structure. |
402 |
|
403 |
Parameters: |
404 |
gline, pointer to structure to be freed. |
405 |
|
406 |
Returns: |
407 |
Nothing. |
408 |
******************************************************************************/ |
409 |
static void gridmap_free_gridmap_line(gridmap_line_t *gline) { |
410 |
if (gline == NULL) |
411 |
return; |
412 |
|
413 |
free(gline->match); |
414 |
gline->match = NULL; |
415 |
|
416 |
charlist_free(gline->mappings); |
417 |
gline->mappings = NULL; |
418 |
|
419 |
free(gline); |
420 |
} /* gridmap_free_gridmap_line() */ |
421 |
|
422 |
void charlist_free(charlist_t * list){ |
423 |
charlist_t * current = list; |
424 |
charlist_t * working; |
425 |
while (current != NULL){ |
426 |
working = current; |
427 |
current = current->next; |
428 |
|
429 |
/* clean the element */ |
430 |
free(working->value); |
431 |
free(working); |
432 |
working = NULL; |
433 |
|
434 |
if (current == list) |
435 |
/* it accidantly is circular so break out of it as I already cleaned it up */ |
436 |
break; |
437 |
} |
438 |
} |
439 |
|
440 |
charlist_t * charlist_add_char_ptr_own(charlist_t * list, const char * str){ |
441 |
charlist_t * working = list; |
442 |
charlist_t * last = NULL; |
443 |
if (working == NULL){ |
444 |
last = working = calloc(1,sizeof(charlist_t)); |
445 |
} else { |
446 |
last = working; |
447 |
while (last->next != NULL){ |
448 |
/* it is a circular list, now you found the last one */ |
449 |
if (last->next == working) |
450 |
break; |
451 |
last = last->next; |
452 |
} |
453 |
last->next = calloc(1,sizeof(charlist_t)); |
454 |
last = last->next; |
455 |
} |
456 |
|
457 |
if (last == NULL) |
458 |
return NULL; |
459 |
|
460 |
last->value = str; |
461 |
return working; |
462 |
} |
463 |
|
464 |
charlist_t * charlist_add_char_ptr_owned(charlist_t * list, const char * str) { |
465 |
char * mystr = strdup(str); |
466 |
if (mystr == NULL) |
467 |
return NULL; |
468 |
return charlist_add_char_ptr_own(list, mystr); |
469 |
} |
470 |
|
471 |
int main(int argc, char* argv[]){ |
472 |
char* gridmapfile = "/home/aczid/workspace/grid-mw-security/ees/examples/example_gridmapfile.txt"; |
473 |
|
474 |
} |