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