File: | /sssd/bdir/../src/util/util.c |
Location: | line 208, column 22 |
Description: | The left operand of '!=' is a garbage value |
1 | /* | |||
2 | Authors: | |||
3 | Simo Sorce <ssorce@redhat.com> | |||
4 | ||||
5 | Copyright (C) 2009 Red Hat | |||
6 | ||||
7 | This program is free software; you can redistribute it and/or modify | |||
8 | it under the terms of the GNU General Public License as published by | |||
9 | the Free Software Foundation; either version 3 of the License, or | |||
10 | (at your option) any later version. | |||
11 | ||||
12 | This program is distributed in the hope that it will be useful, | |||
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
15 | GNU General Public License for more details. | |||
16 | ||||
17 | You should have received a copy of the GNU General Public License | |||
18 | along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
19 | */ | |||
20 | ||||
21 | #include <ctype.h> | |||
22 | #include <netdb.h> | |||
23 | #include <poll.h> | |||
24 | #include <sys/socket.h> | |||
25 | #include <arpa/inet.h> | |||
26 | #include <talloc.h> | |||
27 | #include <dhash.h> | |||
28 | ||||
29 | #include "util/util.h" | |||
30 | #include "util/sss_utf8.h" | |||
31 | ||||
32 | int split_on_separator(TALLOC_CTX *mem_ctx, const char *str, | |||
33 | const char sep, bool_Bool trim, bool_Bool skip_empty, | |||
34 | char ***_list, int *size) | |||
35 | { | |||
36 | int ret; | |||
37 | const char *substr_end = str; | |||
38 | const char *substr_begin = str; | |||
39 | const char *sep_pos = NULL((void*)0); | |||
40 | size_t substr_len; | |||
41 | char **list = NULL((void*)0); | |||
42 | int num_strings = 0; | |||
43 | TALLOC_CTX *tmp_ctx = NULL((void*)0); | |||
44 | ||||
45 | if (str == NULL((void*)0) || *str == '\0' || _list == NULL((void*)0)) { | |||
46 | return EINVAL22; | |||
47 | } | |||
48 | ||||
49 | tmp_ctx = talloc_new(NULL)talloc_named_const(((void*)0), 0, "talloc_new: " "../src/util/util.c" ":" "49"); | |||
50 | if (tmp_ctx == NULL((void*)0)) { | |||
51 | return ENOMEM12; | |||
52 | } | |||
53 | ||||
54 | do { | |||
55 | substr_len = 0; | |||
56 | ||||
57 | /* If this is not the first substring, then move from the separator. */ | |||
58 | if (sep_pos != NULL((void*)0)) { | |||
59 | substr_end = sep_pos + 1; | |||
60 | substr_begin = sep_pos + 1; | |||
61 | } | |||
62 | ||||
63 | /* Find end of the first substring */ | |||
64 | while (*substr_end != sep && *substr_end != '\0') { | |||
65 | substr_end++; | |||
66 | substr_len++; | |||
67 | } | |||
68 | ||||
69 | sep_pos = substr_end; | |||
70 | ||||
71 | if (trim) { | |||
72 | /* Trim leading whitespace */ | |||
73 | while (isspace(*substr_begin)((*__ctype_b_loc ())[(int) ((*substr_begin))] & (unsigned short int) _ISspace) && substr_begin < substr_end) { | |||
74 | substr_begin++; | |||
75 | substr_len--; | |||
76 | } | |||
77 | ||||
78 | /* Trim trailing whitespace */ | |||
79 | while (substr_end - 1 > substr_begin && isspace(*(substr_end-1))((*__ctype_b_loc ())[(int) ((*(substr_end-1)))] & (unsigned short int) _ISspace)) { | |||
80 | substr_end--; | |||
81 | substr_len--; | |||
82 | } | |||
83 | } | |||
84 | ||||
85 | /* Copy the substring to the output list of strings */ | |||
86 | if (skip_empty == false0 || substr_len > 0) { | |||
87 | list = talloc_realloc(tmp_ctx, list, char*, num_strings + 2)(char* *)_talloc_realloc_array(tmp_ctx, list, sizeof(char*), num_strings + 2, "char*"); | |||
88 | if (list == NULL((void*)0)) { | |||
89 | ret = ENOMEM12; | |||
90 | goto done; | |||
91 | } | |||
92 | ||||
93 | /* empty string is stored for substr_len == 0 */ | |||
94 | list[num_strings] = talloc_strndup(list, substr_begin, substr_len); | |||
95 | if (list[num_strings] == NULL((void*)0)) { | |||
96 | ret = ENOMEM12; | |||
97 | goto done; | |||
98 | } | |||
99 | num_strings++; | |||
100 | } | |||
101 | ||||
102 | } while (*sep_pos != '\0'); | |||
103 | ||||
104 | if (list == NULL((void*)0)) { | |||
105 | /* No allocations were done, make space for the NULL */ | |||
106 | list = talloc(tmp_ctx, char *)(char * *)talloc_named_const(tmp_ctx, sizeof(char *), "char *" ); | |||
107 | if (list == NULL((void*)0)) { | |||
108 | ret = ENOMEM12; | |||
109 | goto done; | |||
110 | } | |||
111 | } | |||
112 | list[num_strings] = NULL((void*)0); | |||
113 | ||||
114 | if (size) { | |||
115 | *size = num_strings; | |||
116 | } | |||
117 | ||||
118 | *_list = talloc_steal(mem_ctx, list)({ __typeof__(list) __talloc_steal_ret = (__typeof__(list))_talloc_steal_loc ((mem_ctx),(list), "../src/util/util.c" ":" "118"); __talloc_steal_ret ; }); | |||
119 | ret = EOK0; | |||
120 | done: | |||
121 | talloc_free(tmp_ctx)_talloc_free(tmp_ctx, "../src/util/util.c" ":" "121"); | |||
122 | return ret; | |||
123 | } | |||
124 | ||||
125 | static void free_args(char **args) | |||
126 | { | |||
127 | int i; | |||
128 | ||||
129 | if (args) { | |||
130 | for (i = 0; args[i]; i++) free(args[i]); | |||
131 | free(args); | |||
132 | } | |||
133 | } | |||
134 | ||||
135 | /* parse a string into arguments. | |||
136 | * arguments are separated by a space | |||
137 | * '\' is an escape character and can be used only to escape | |||
138 | * itself or the white space. | |||
139 | */ | |||
140 | char **parse_args(const char *str) | |||
141 | { | |||
142 | const char *p; | |||
143 | char **ret, **r; | |||
144 | char *tmp; | |||
145 | int num; | |||
146 | int i; | |||
147 | bool_Bool e, w; | |||
148 | ||||
149 | tmp = malloc(strlen(str) + 1); | |||
150 | if (!tmp) return NULL((void*)0); | |||
| ||||
151 | ||||
152 | ret = NULL((void*)0); | |||
153 | num = 0; | |||
154 | i = 0; | |||
155 | e = false0; | |||
156 | w = false0; | |||
157 | p = str; | |||
158 | while (*p) { | |||
159 | if (*p == '\\') { | |||
160 | w = false0; | |||
161 | if (e) { | |||
162 | /* if we were already escaping, add a '\' literal */ | |||
163 | tmp[i] = '\\'; | |||
164 | i++; | |||
165 | e = false0; | |||
166 | } else { | |||
167 | /* otherwise just start escaping */ | |||
168 | e = true1; | |||
169 | } | |||
170 | } else if (isspace(*p)((*__ctype_b_loc ())[(int) ((*p))] & (unsigned short int) _ISspace)) { | |||
171 | if (e) { | |||
172 | /* Add escaped whitespace literally */ | |||
173 | tmp[i] = *p; | |||
174 | i++; | |||
175 | e = false0; | |||
176 | } else if (w == false0) { | |||
177 | /* If previous character was non-whitespace, arg break */ | |||
178 | tmp[i] = '\0'; | |||
179 | i++; | |||
180 | w = true1; | |||
181 | } | |||
182 | /* previous char was whitespace as well, skip it */ | |||
183 | } else { | |||
184 | w = false0; | |||
185 | if (e) { | |||
186 | /* Prepend escaped chars with a literal \ */ | |||
187 | tmp[i] = '\\'; | |||
188 | i++; | |||
189 | e = false0; | |||
190 | } | |||
191 | /* Copy character from the source string */ | |||
192 | tmp[i] = *p; | |||
193 | i++; | |||
194 | } | |||
195 | ||||
196 | p++; | |||
197 | ||||
198 | /* check if this was the last char */ | |||
199 | if (*p == '\0') { | |||
200 | if (e) { | |||
201 | tmp[i] = '\\'; | |||
202 | i++; | |||
203 | e = false0; | |||
204 | } | |||
205 | tmp[i] = '\0'; | |||
206 | i++; | |||
207 | } | |||
208 | if (tmp[i-1] != '\0' || strlen(tmp) == 0) { | |||
| ||||
209 | /* check next char and skip multiple spaces */ | |||
210 | continue; | |||
211 | } | |||
212 | ||||
213 | r = realloc(ret, (num + 2) * sizeof(char *)); | |||
214 | if (!r) goto fail; | |||
215 | ret = r; | |||
216 | ret[num+1] = NULL((void*)0); | |||
217 | ret[num] = strdup(tmp); | |||
218 | if (!ret[num]) goto fail; | |||
219 | num++; | |||
220 | i = 0; | |||
221 | } | |||
222 | ||||
223 | free(tmp); | |||
224 | return ret; | |||
225 | ||||
226 | fail: | |||
227 | free(tmp); | |||
228 | free_args(ret); | |||
229 | return NULL((void*)0); | |||
230 | } | |||
231 | ||||
232 | char **dup_string_list(TALLOC_CTX *memctx, const char **str_list) | |||
233 | { | |||
234 | int i = 0; | |||
235 | int j = 0; | |||
236 | char **dup_list; | |||
237 | ||||
238 | if (!str_list) { | |||
239 | return NULL((void*)0); | |||
240 | } | |||
241 | ||||
242 | /* Find the size of the list */ | |||
243 | while (str_list[i]) i++; | |||
244 | ||||
245 | dup_list = talloc_array(memctx, char *, i+1)(char * *)_talloc_array(memctx, sizeof(char *), i+1, "char *" ); | |||
246 | if (!dup_list) { | |||
247 | return NULL((void*)0); | |||
248 | } | |||
249 | ||||
250 | /* Copy the elements */ | |||
251 | for (j = 0; j < i; j++) { | |||
252 | dup_list[j] = talloc_strdup(dup_list, str_list[j]); | |||
253 | if (!dup_list[j]) { | |||
254 | talloc_free(dup_list)_talloc_free(dup_list, "../src/util/util.c" ":" "254"); | |||
255 | return NULL((void*)0); | |||
256 | } | |||
257 | } | |||
258 | ||||
259 | /* NULL-terminate the list */ | |||
260 | dup_list[i] = NULL((void*)0); | |||
261 | ||||
262 | return dup_list; | |||
263 | } | |||
264 | ||||
265 | /* Take two string lists (terminated on a NULL char*) | |||
266 | * and return up to three arrays of strings based on | |||
267 | * shared ownership. | |||
268 | * | |||
269 | * Pass NULL to any return type you don't care about | |||
270 | */ | |||
271 | errno_t diff_string_lists(TALLOC_CTX *memctx, | |||
272 | char **_list1, | |||
273 | char **_list2, | |||
274 | char ***_list1_only, | |||
275 | char ***_list2_only, | |||
276 | char ***_both_lists) | |||
277 | { | |||
278 | int error; | |||
279 | errno_t ret; | |||
280 | int i; | |||
281 | int i2 = 0; | |||
282 | int i12 = 0; | |||
283 | hash_table_t *table; | |||
284 | hash_key_t key; | |||
285 | hash_value_t value; | |||
286 | char **list1 = NULL((void*)0); | |||
287 | char **list2 = NULL((void*)0); | |||
288 | char **list1_only = NULL((void*)0); | |||
289 | char **list2_only = NULL((void*)0); | |||
290 | char **both_lists = NULL((void*)0); | |||
291 | unsigned long count; | |||
292 | hash_key_t *keys; | |||
293 | ||||
294 | TALLOC_CTX *tmp_ctx = talloc_new(memctx)talloc_named_const(memctx, 0, "talloc_new: " "../src/util/util.c" ":" "294"); | |||
295 | if (!tmp_ctx) { | |||
296 | return ENOMEM12; | |||
297 | } | |||
298 | ||||
299 | if (!_list1) { | |||
300 | list1 = talloc_array(tmp_ctx, char *, 1)(char * *)_talloc_array(tmp_ctx, sizeof(char *), 1, "char *"); | |||
301 | if (!list1) { | |||
302 | talloc_free(tmp_ctx)_talloc_free(tmp_ctx, "../src/util/util.c" ":" "302"); | |||
303 | return ENOMEM12; | |||
304 | } | |||
305 | list1[0] = NULL((void*)0); | |||
306 | } | |||
307 | else { | |||
308 | list1 = _list1; | |||
309 | } | |||
310 | ||||
311 | if (!_list2) { | |||
312 | list2 = talloc_array(tmp_ctx, char *, 1)(char * *)_talloc_array(tmp_ctx, sizeof(char *), 1, "char *"); | |||
313 | if (!list2) { | |||
314 | talloc_free(tmp_ctx)_talloc_free(tmp_ctx, "../src/util/util.c" ":" "314"); | |||
315 | return ENOMEM12; | |||
316 | } | |||
317 | list2[0] = NULL((void*)0); | |||
318 | } | |||
319 | else { | |||
320 | list2 = _list2; | |||
321 | } | |||
322 | ||||
323 | error = hash_create(10, &table, NULL((void*)0), NULL((void*)0)); | |||
324 | if (error != HASH_SUCCESS0) { | |||
325 | talloc_free(tmp_ctx)_talloc_free(tmp_ctx, "../src/util/util.c" ":" "325"); | |||
326 | return EIO5; | |||
327 | } | |||
328 | ||||
329 | key.type = HASH_KEY_STRING; | |||
330 | value.type = HASH_VALUE_UNDEF; | |||
331 | ||||
332 | /* Add all entries from list 1 into a hash table */ | |||
333 | i = 0; | |||
334 | while (list1[i]) { | |||
335 | key.str = talloc_strdup(tmp_ctx, list1[i]); | |||
336 | error = hash_enter(table, &key, &value); | |||
337 | if (error != HASH_SUCCESS0) { | |||
338 | ret = EIO5; | |||
339 | goto done; | |||
340 | } | |||
341 | i++; | |||
342 | } | |||
343 | ||||
344 | /* Iterate through list 2 and remove matching items */ | |||
345 | i = 0; | |||
346 | while (list2[i]) { | |||
347 | key.str = talloc_strdup(tmp_ctx, list2[i]); | |||
348 | error = hash_delete(table, &key); | |||
349 | if (error == HASH_SUCCESS0) { | |||
350 | if (_both_lists) { | |||
351 | /* String was present in both lists */ | |||
352 | i12++; | |||
353 | both_lists = talloc_realloc(tmp_ctx, both_lists, char *, i12+1)(char * *)_talloc_realloc_array(tmp_ctx, both_lists, sizeof(char *), i12+1, "char *"); | |||
354 | if (!both_lists) { | |||
355 | ret = ENOMEM12; | |||
356 | goto done; | |||
357 | } | |||
358 | both_lists[i12-1] = talloc_strdup(both_lists, list2[i]); | |||
359 | if (!both_lists[i12-1]) { | |||
360 | ret = ENOMEM12; | |||
361 | goto done; | |||
362 | } | |||
363 | ||||
364 | both_lists[i12] = NULL((void*)0); | |||
365 | } | |||
366 | } | |||
367 | else if (error == HASH_ERROR_KEY_NOT_FOUND(-2000 + 4)) { | |||
368 | if (_list2_only) { | |||
369 | /* String was present only in list2 */ | |||
370 | i2++; | |||
371 | list2_only = talloc_realloc(tmp_ctx, list2_only,(char * *)_talloc_realloc_array(tmp_ctx, list2_only, sizeof(char *), i2+1, "char *") | |||
372 | char *, i2+1)(char * *)_talloc_realloc_array(tmp_ctx, list2_only, sizeof(char *), i2+1, "char *"); | |||
373 | if (!list2_only) { | |||
374 | ret = ENOMEM12; | |||
375 | goto done; | |||
376 | } | |||
377 | list2_only[i2-1] = talloc_strdup(list2_only, list2[i]); | |||
378 | if (!list2_only[i2-1]) { | |||
379 | ret = ENOMEM12; | |||
380 | goto done; | |||
381 | } | |||
382 | ||||
383 | list2_only[i2] = NULL((void*)0); | |||
384 | } | |||
385 | } | |||
386 | else { | |||
387 | /* An error occurred */ | |||
388 | ret = EIO5; | |||
389 | goto done; | |||
390 | } | |||
391 | i++; | |||
392 | } | |||
393 | ||||
394 | /* Get the leftover entries in the hash table */ | |||
395 | if (_list1_only) { | |||
396 | error = hash_keys(table, &count, &keys); | |||
397 | if (error != HASH_SUCCESS0) { | |||
398 | ret = EIO5; | |||
399 | goto done; | |||
400 | } | |||
401 | ||||
402 | list1_only = talloc_array(tmp_ctx, char *, count+1)(char * *)_talloc_array(tmp_ctx, sizeof(char *), count+1, "char *" ); | |||
403 | if (!list1_only) { | |||
404 | ret = ENOMEM12; | |||
405 | goto done; | |||
406 | } | |||
407 | ||||
408 | for (i = 0; i < count; i++) { | |||
409 | list1_only[i] = talloc_strdup(list1_only, keys[i].str); | |||
410 | if (!list1_only[i]) { | |||
411 | ret = ENOMEM12; | |||
412 | goto done; | |||
413 | } | |||
414 | } | |||
415 | list1_only[count] = NULL((void*)0); | |||
416 | ||||
417 | free(keys); | |||
418 | ||||
419 | *_list1_only = talloc_steal(memctx, list1_only)({ __typeof__(list1_only) __talloc_steal_ret = (__typeof__(list1_only ))_talloc_steal_loc((memctx),(list1_only), "../src/util/util.c" ":" "419"); __talloc_steal_ret; }); | |||
420 | } | |||
421 | ||||
422 | if (_list2_only) { | |||
423 | if (list2_only) { | |||
424 | *_list2_only = talloc_steal(memctx, list2_only)({ __typeof__(list2_only) __talloc_steal_ret = (__typeof__(list2_only ))_talloc_steal_loc((memctx),(list2_only), "../src/util/util.c" ":" "424"); __talloc_steal_ret; }); | |||
425 | } | |||
426 | else { | |||
427 | *_list2_only = talloc_array(memctx, char *, 1)(char * *)_talloc_array(memctx, sizeof(char *), 1, "char *"); | |||
428 | if (!(*_list2_only)) { | |||
429 | ret = ENOMEM12; | |||
430 | goto done; | |||
431 | } | |||
432 | *_list2_only[0] = NULL((void*)0); | |||
433 | } | |||
434 | } | |||
435 | ||||
436 | if (_both_lists) { | |||
437 | if (both_lists) { | |||
438 | *_both_lists = talloc_steal(memctx, both_lists)({ __typeof__(both_lists) __talloc_steal_ret = (__typeof__(both_lists ))_talloc_steal_loc((memctx),(both_lists), "../src/util/util.c" ":" "438"); __talloc_steal_ret; }); | |||
439 | } | |||
440 | else { | |||
441 | *_both_lists = talloc_array(memctx, char *, 1)(char * *)_talloc_array(memctx, sizeof(char *), 1, "char *"); | |||
442 | if (!(*_both_lists)) { | |||
443 | ret = ENOMEM12; | |||
444 | goto done; | |||
445 | } | |||
446 | *_both_lists[0] = NULL((void*)0); | |||
447 | } | |||
448 | } | |||
449 | ||||
450 | ret = EOK0; | |||
451 | ||||
452 | done: | |||
453 | hash_destroy(table); | |||
454 | talloc_free(tmp_ctx)_talloc_free(tmp_ctx, "../src/util/util.c" ":" "454"); | |||
455 | return ret; | |||
456 | } | |||
457 | ||||
458 | static void *hash_talloc(const size_t size, void *pvt) | |||
459 | { | |||
460 | return talloc_size(pvt, size)talloc_named_const(pvt, size, "../src/util/util.c" ":" "460"); | |||
461 | } | |||
462 | ||||
463 | static void hash_talloc_free(void *ptr, void *pvt) | |||
464 | { | |||
465 | talloc_free(ptr)_talloc_free(ptr, "../src/util/util.c" ":" "465"); | |||
466 | } | |||
467 | ||||
468 | errno_t sss_hash_create_ex(TALLOC_CTX *mem_ctx, | |||
469 | unsigned long count, | |||
470 | hash_table_t **tbl, | |||
471 | unsigned int directory_bits, | |||
472 | unsigned int segment_bits, | |||
473 | unsigned long min_load_factor, | |||
474 | unsigned long max_load_factor, | |||
475 | hash_delete_callback *delete_callback, | |||
476 | void *delete_private_data) | |||
477 | { | |||
478 | errno_t ret; | |||
479 | hash_table_t *table; | |||
480 | int hret; | |||
481 | ||||
482 | TALLOC_CTX *internal_ctx; | |||
483 | internal_ctx = talloc_new(NULL)talloc_named_const(((void*)0), 0, "talloc_new: " "../src/util/util.c" ":" "483"); | |||
484 | if (!internal_ctx) { | |||
485 | return ENOMEM12; | |||
486 | } | |||
487 | ||||
488 | hret = hash_create_ex(count, &table, directory_bits, segment_bits, | |||
489 | min_load_factor, max_load_factor, | |||
490 | hash_talloc, hash_talloc_free, internal_ctx, | |||
491 | delete_callback, delete_private_data); | |||
492 | switch (hret) { | |||
493 | case HASH_SUCCESS0: | |||
494 | /* Steal the table pointer onto the mem_ctx, | |||
495 | * then make the internal_ctx a child of | |||
496 | * table. | |||
497 | * | |||
498 | * This way, we can clean up the values when | |||
499 | * we talloc_free() the table | |||
500 | */ | |||
501 | *tbl = talloc_steal(mem_ctx, table)({ __typeof__(table) __talloc_steal_ret = (__typeof__(table)) _talloc_steal_loc((mem_ctx),(table), "../src/util/util.c" ":" "501"); __talloc_steal_ret; }); | |||
502 | talloc_steal(table, internal_ctx)({ __typeof__(internal_ctx) __talloc_steal_ret = (__typeof__( internal_ctx))_talloc_steal_loc((table),(internal_ctx), "../src/util/util.c" ":" "502"); __talloc_steal_ret; }); | |||
503 | return EOK0; | |||
504 | ||||
505 | case HASH_ERROR_NO_MEMORY(-2000 + 3): | |||
506 | ret = ENOMEM12; | |||
507 | break; | |||
508 | default: | |||
509 | ret = EIO5; | |||
510 | } | |||
511 | ||||
512 | DEBUG(SSSDBG_FATAL_FAILURE, "Could not create hash table: [%d][%s]\n",do { int __debug_macro_level = 0x0010; if ((debug_level & (__debug_macro_level) || (debug_level == 0 && (__debug_macro_level & (0x0010 | 0x0020))))) { debug_fn("../src/util/util.c", 513, __FUNCTION__, __debug_macro_level, "Could not create hash table: [%d][%s]\n" , hret, hash_error_string(hret)); } } while (0) | |||
513 | hret, hash_error_string(hret))do { int __debug_macro_level = 0x0010; if ((debug_level & (__debug_macro_level) || (debug_level == 0 && (__debug_macro_level & (0x0010 | 0x0020))))) { debug_fn("../src/util/util.c", 513, __FUNCTION__, __debug_macro_level, "Could not create hash table: [%d][%s]\n" , hret, hash_error_string(hret)); } } while (0); | |||
514 | ||||
515 | talloc_free(internal_ctx)_talloc_free(internal_ctx, "../src/util/util.c" ":" "515"); | |||
516 | return ret; | |||
517 | } | |||
518 | ||||
519 | errno_t sss_hash_create(TALLOC_CTX *mem_ctx, unsigned long count, | |||
520 | hash_table_t **tbl) | |||
521 | { | |||
522 | return sss_hash_create_ex(mem_ctx, count, tbl, 0, 0, 0, 0, NULL((void*)0), NULL((void*)0)); | |||
523 | } | |||
524 | ||||
525 | errno_t sss_filter_sanitize(TALLOC_CTX *mem_ctx, | |||
526 | const char *input, | |||
527 | char **sanitized) | |||
528 | { | |||
529 | char *output; | |||
530 | size_t i = 0; | |||
531 | size_t j = 0; | |||
532 | ||||
533 | /* Assume the worst-case. We'll resize it later, once */ | |||
534 | output = talloc_array(mem_ctx, char, strlen(input) * 3 + 1)(char *)_talloc_array(mem_ctx, sizeof(char), strlen(input) * 3 + 1, "char"); | |||
535 | if (!output) { | |||
536 | return ENOMEM12; | |||
537 | } | |||
538 | ||||
539 | while (input[i]) { | |||
540 | switch(input[i]) { | |||
541 | case '\t': | |||
542 | output[j++] = '\\'; | |||
543 | output[j++] = '0'; | |||
544 | output[j++] = '9'; | |||
545 | break; | |||
546 | case ' ': | |||
547 | output[j++] = '\\'; | |||
548 | output[j++] = '2'; | |||
549 | output[j++] = '0'; | |||
550 | break; | |||
551 | case '*': | |||
552 | output[j++] = '\\'; | |||
553 | output[j++] = '2'; | |||
554 | output[j++] = 'a'; | |||
555 | break; | |||
556 | case '(': | |||
557 | output[j++] = '\\'; | |||
558 | output[j++] = '2'; | |||
559 | output[j++] = '8'; | |||
560 | break; | |||
561 | case ')': | |||
562 | output[j++] = '\\'; | |||
563 | output[j++] = '2'; | |||
564 | output[j++] = '9'; | |||
565 | break; | |||
566 | case '\\': | |||
567 | output[j++] = '\\'; | |||
568 | output[j++] = '5'; | |||
569 | output[j++] = 'c'; | |||
570 | break; | |||
571 | default: | |||
572 | output[j++] = input[i]; | |||
573 | } | |||
574 | ||||
575 | i++; | |||
576 | } | |||
577 | output[j] = '\0'; | |||
578 | *sanitized = talloc_realloc(mem_ctx, output, char, j+1)(char *)_talloc_realloc_array(mem_ctx, output, sizeof(char), j +1, "char"); | |||
579 | if (!*sanitized) { | |||
580 | talloc_free(output)_talloc_free(output, "../src/util/util.c" ":" "580"); | |||
581 | return ENOMEM12; | |||
582 | } | |||
583 | ||||
584 | return EOK0; | |||
585 | } | |||
586 | ||||
587 | char * | |||
588 | sss_escape_ip_address(TALLOC_CTX *mem_ctx, int family, const char *addr) | |||
589 | { | |||
590 | return family == AF_INET610 ? talloc_asprintf(mem_ctx, "[%s]", addr) : | |||
591 | talloc_strdup(mem_ctx, addr); | |||
592 | } | |||
593 | ||||
594 | /* out->len includes terminating '\0' */ | |||
595 | void to_sized_string(struct sized_string *out, const char *in) | |||
596 | { | |||
597 | out->str = in; | |||
598 | if (out->str) { | |||
599 | out->len = strlen(out->str) + 1; | |||
600 | } else { | |||
601 | out->len = 0; | |||
602 | } | |||
603 | } | |||
604 | ||||
605 | /* This function only removes first and last | |||
606 | * character if the first character was '['. | |||
607 | * | |||
608 | * NOTE: This means, that ipv6addr must NOT be followed | |||
609 | * by port number. | |||
610 | */ | |||
611 | errno_t | |||
612 | remove_ipv6_brackets(char *ipv6addr) | |||
613 | { | |||
614 | size_t len; | |||
615 | ||||
616 | if (ipv6addr && ipv6addr[0] == '[') { | |||
617 | len = strlen(ipv6addr); | |||
618 | if (len < 3) { | |||
619 | return EINVAL22; | |||
620 | } | |||
621 | ||||
622 | memmove(ipv6addr, &ipv6addr[1], len - 2); | |||
623 | ipv6addr[len -2] = '\0'; | |||
624 | } | |||
625 | ||||
626 | return EOK0; | |||
627 | } | |||
628 | ||||
629 | errno_t add_string_to_list(TALLOC_CTX *mem_ctx, const char *string, | |||
630 | char ***list_p) | |||
631 | { | |||
632 | size_t c; | |||
633 | char **old_list = NULL((void*)0); | |||
634 | char **new_list = NULL((void*)0); | |||
635 | ||||
636 | if (string == NULL((void*)0) || list_p == NULL((void*)0)) { | |||
637 | DEBUG(SSSDBG_OP_FAILURE, "Missing string or list.\n")do { int __debug_macro_level = 0x0040; if ((debug_level & (__debug_macro_level) || (debug_level == 0 && (__debug_macro_level & (0x0010 | 0x0020))))) { debug_fn("../src/util/util.c", 637, __FUNCTION__, __debug_macro_level, "Missing string or list.\n" ); } } while (0); | |||
638 | return EINVAL22; | |||
639 | } | |||
640 | ||||
641 | old_list = *list_p; | |||
642 | ||||
643 | if (old_list == NULL((void*)0)) { | |||
644 | /* If the input is a NULL list a new one is created with the new | |||
645 | * string and the terminating NULL element. */ | |||
646 | c = 0; | |||
647 | new_list = talloc_array(mem_ctx, char *, 2)(char * *)_talloc_array(mem_ctx, sizeof(char *), 2, "char *"); | |||
648 | } else { | |||
649 | for (c = 0; old_list[c] != NULL((void*)0); c++); | |||
650 | /* Allocate one extra space for the new service and one for | |||
651 | * the terminating NULL | |||
652 | */ | |||
653 | new_list = talloc_realloc(mem_ctx, old_list, char *, c + 2)(char * *)_talloc_realloc_array(mem_ctx, old_list, sizeof(char *), c + 2, "char *"); | |||
654 | } | |||
655 | ||||
656 | if (new_list == NULL((void*)0)) { | |||
657 | DEBUG(SSSDBG_OP_FAILURE, "talloc_array/talloc_realloc failed.\n")do { int __debug_macro_level = 0x0040; if ((debug_level & (__debug_macro_level) || (debug_level == 0 && (__debug_macro_level & (0x0010 | 0x0020))))) { debug_fn("../src/util/util.c", 657, __FUNCTION__, __debug_macro_level, "talloc_array/talloc_realloc failed.\n" ); } } while (0); | |||
658 | return ENOMEM12; | |||
659 | } | |||
660 | ||||
661 | new_list[c] = talloc_strdup(new_list, string); | |||
662 | if (new_list[c] == NULL((void*)0)) { | |||
663 | DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n")do { int __debug_macro_level = 0x0040; if ((debug_level & (__debug_macro_level) || (debug_level == 0 && (__debug_macro_level & (0x0010 | 0x0020))))) { debug_fn("../src/util/util.c", 663, __FUNCTION__, __debug_macro_level, "talloc_strdup failed.\n" ); } } while (0); | |||
664 | talloc_free(new_list)_talloc_free(new_list, "../src/util/util.c" ":" "664"); | |||
665 | return ENOMEM12; | |||
666 | } | |||
667 | ||||
668 | new_list[c + 1] = NULL((void*)0); | |||
669 | ||||
670 | *list_p = new_list; | |||
671 | ||||
672 | return EOK0; | |||
673 | } | |||
674 | ||||
675 | bool_Bool string_in_list(const char *string, char **list, bool_Bool case_sensitive) | |||
676 | { | |||
677 | size_t c; | |||
678 | int(*compare)(const char *s1, const char *s2); | |||
679 | ||||
680 | if (string == NULL((void*)0) || list == NULL((void*)0) || *list == NULL((void*)0)) { | |||
681 | return false0; | |||
682 | } | |||
683 | ||||
684 | compare = case_sensitive ? strcmp : strcasecmp; | |||
685 | ||||
686 | for (c = 0; list[c] != NULL((void*)0); c++) { | |||
687 | if (compare(string, list[c]) == 0) { | |||
688 | return true1; | |||
689 | } | |||
690 | } | |||
691 | ||||
692 | return false0; | |||
693 | } | |||
694 | ||||
695 | void safezero(void *data, size_t size) | |||
696 | { | |||
697 | volatile uint8_t *p = data; | |||
698 | ||||
699 | while (size--) { | |||
700 | *p++ = 0; | |||
701 | } | |||
702 | } | |||
703 | ||||
704 | int domain_to_basedn(TALLOC_CTX *memctx, const char *domain, char **basedn) | |||
705 | { | |||
706 | const char *s; | |||
707 | char *dn; | |||
708 | char *p; | |||
709 | int l; | |||
710 | ||||
711 | if (!domain || !basedn) { | |||
712 | return EINVAL22; | |||
713 | } | |||
714 | ||||
715 | s = domain; | |||
716 | dn = talloc_strdup(memctx, "dc="); | |||
717 | ||||
718 | while ((p = strchr(s, '.'))) { | |||
719 | l = p - s; | |||
720 | dn = talloc_asprintf_append_buffer(dn, "%.*s,dc=", l, s); | |||
721 | if (!dn) { | |||
722 | return ENOMEM12; | |||
723 | } | |||
724 | s = p + 1; | |||
725 | } | |||
726 | dn = talloc_strdup_append_buffer(dn, s); | |||
727 | if (!dn) { | |||
728 | return ENOMEM12; | |||
729 | } | |||
730 | ||||
731 | for (p=dn; *p; ++p) { | |||
732 | *p = tolower(*p); | |||
733 | } | |||
734 | ||||
735 | *basedn = dn; | |||
736 | return EOK0; | |||
737 | } | |||
738 | ||||
739 | bool_Bool is_host_in_domain(const char *host, const char *domain) | |||
740 | { | |||
741 | int diff = strlen(host) - strlen(domain); | |||
742 | ||||
743 | if (diff == 0 && strcmp(host, domain) == 0) { | |||
744 | return true1; | |||
745 | } | |||
746 | ||||
747 | if (diff > 0 && strcmp(host + diff, domain) == 0 && host[diff - 1] == '.') { | |||
748 | return true1; | |||
749 | } | |||
750 | ||||
751 | return false0; | |||
752 | } | |||
753 | ||||
754 | /* addr is in network order for both IPv4 and IPv6 versions */ | |||
755 | bool_Bool check_ipv4_addr(struct in_addr *addr, uint8_t flags) | |||
756 | { | |||
757 | char straddr[INET_ADDRSTRLEN16]; | |||
758 | ||||
759 | if (inet_ntop(AF_INET2, addr, straddr, INET_ADDRSTRLEN16) == NULL((void*)0)) { | |||
760 | DEBUG(SSSDBG_MINOR_FAILURE,do { int __debug_macro_level = 0x0080; if ((debug_level & (__debug_macro_level) || (debug_level == 0 && (__debug_macro_level & (0x0010 | 0x0020))))) { debug_fn("../src/util/util.c", 761, __FUNCTION__, __debug_macro_level, "inet_ntop failed, won't log IP addresses\n" ); } } while (0) | |||
761 | "inet_ntop failed, won't log IP addresses\n")do { int __debug_macro_level = 0x0080; if ((debug_level & (__debug_macro_level) || (debug_level == 0 && (__debug_macro_level & (0x0010 | 0x0020))))) { debug_fn("../src/util/util.c", 761, __FUNCTION__, __debug_macro_level, "inet_ntop failed, won't log IP addresses\n" ); } } while (0); | |||
762 | snprintf(straddr, INET_ADDRSTRLEN16, "unknown"); | |||
763 | } | |||
764 | ||||
765 | if ((flags & SSS_NO_MULTICAST0x04) && IN_MULTICAST(ntohl(addr->s_addr))((((in_addr_t)(ntohl(addr->s_addr))) & 0xf0000000) == 0xe0000000 )) { | |||
766 | DEBUG(SSSDBG_FUNC_DATA, "Multicast IPv4 address %s\n", straddr)do { int __debug_macro_level = 0x0200; if ((debug_level & (__debug_macro_level) || (debug_level == 0 && (__debug_macro_level & (0x0010 | 0x0020))))) { debug_fn("../src/util/util.c", 766, __FUNCTION__, __debug_macro_level, "Multicast IPv4 address %s\n" , straddr); } } while (0); | |||
767 | return false0; | |||
768 | } else if ((flags & SSS_NO_LOOPBACK0x02) | |||
769 | && inet_netof(*addr) == IN_LOOPBACKNET127) { | |||
770 | DEBUG(SSSDBG_FUNC_DATA, "Loopback IPv4 address %s\n", straddr)do { int __debug_macro_level = 0x0200; if ((debug_level & (__debug_macro_level) || (debug_level == 0 && (__debug_macro_level & (0x0010 | 0x0020))))) { debug_fn("../src/util/util.c", 770, __FUNCTION__, __debug_macro_level, "Loopback IPv4 address %s\n" , straddr); } } while (0); | |||
771 | return false0; | |||
772 | } else if ((flags & SSS_NO_LINKLOCAL0x01) | |||
773 | && (addr->s_addr & htonl(0xffff0000)) == htonl(0xa9fe0000)) { | |||
774 | /* 169.254.0.0/16 */ | |||
775 | DEBUG(SSSDBG_FUNC_DATA, "Link-local IPv4 address %s\n", straddr)do { int __debug_macro_level = 0x0200; if ((debug_level & (__debug_macro_level) || (debug_level == 0 && (__debug_macro_level & (0x0010 | 0x0020))))) { debug_fn("../src/util/util.c", 775, __FUNCTION__, __debug_macro_level, "Link-local IPv4 address %s\n" , straddr); } } while (0); | |||
776 | return false0; | |||
777 | } else if ((flags & SSS_NO_BROADCAST0x08) | |||
778 | && addr->s_addr == htonl(INADDR_BROADCAST((in_addr_t) 0xffffffff))) { | |||
779 | DEBUG(SSSDBG_FUNC_DATA, "Broadcast IPv4 address %s\n", straddr)do { int __debug_macro_level = 0x0200; if ((debug_level & (__debug_macro_level) || (debug_level == 0 && (__debug_macro_level & (0x0010 | 0x0020))))) { debug_fn("../src/util/util.c", 779, __FUNCTION__, __debug_macro_level, "Broadcast IPv4 address %s\n" , straddr); } } while (0); | |||
780 | return false0; | |||
781 | } | |||
782 | ||||
783 | return true1; | |||
784 | } | |||
785 | ||||
786 | bool_Bool check_ipv6_addr(struct in6_addr *addr, uint8_t flags) | |||
787 | { | |||
788 | char straddr[INET6_ADDRSTRLEN46]; | |||
789 | ||||
790 | if (inet_ntop(AF_INET610, addr, straddr, INET6_ADDRSTRLEN46) == NULL((void*)0)) { | |||
791 | DEBUG(SSSDBG_MINOR_FAILURE,do { int __debug_macro_level = 0x0080; if ((debug_level & (__debug_macro_level) || (debug_level == 0 && (__debug_macro_level & (0x0010 | 0x0020))))) { debug_fn("../src/util/util.c", 792, __FUNCTION__, __debug_macro_level, "inet_ntop failed, won't log IP addresses\n" ); } } while (0) | |||
792 | "inet_ntop failed, won't log IP addresses\n")do { int __debug_macro_level = 0x0080; if ((debug_level & (__debug_macro_level) || (debug_level == 0 && (__debug_macro_level & (0x0010 | 0x0020))))) { debug_fn("../src/util/util.c", 792, __FUNCTION__, __debug_macro_level, "inet_ntop failed, won't log IP addresses\n" ); } } while (0); | |||
793 | snprintf(straddr, INET6_ADDRSTRLEN46, "unknown"); | |||
794 | } | |||
795 | ||||
796 | if ((flags & SSS_NO_LINKLOCAL0x01) && IN6_IS_ADDR_LINKLOCAL(addr)(__extension__ ({ const struct in6_addr *__a = (const struct in6_addr *) (addr); (__a->__in6_u.__u6_addr32[0] & htonl (0xffc00000 )) == htonl (0xfe800000); }))) { | |||
797 | DEBUG(SSSDBG_FUNC_DATA, "Link local IPv6 address %s\n", straddr)do { int __debug_macro_level = 0x0200; if ((debug_level & (__debug_macro_level) || (debug_level == 0 && (__debug_macro_level & (0x0010 | 0x0020))))) { debug_fn("../src/util/util.c", 797, __FUNCTION__, __debug_macro_level, "Link local IPv6 address %s\n" , straddr); } } while (0); | |||
798 | return false0; | |||
799 | } else if ((flags & SSS_NO_LOOPBACK0x02) && IN6_IS_ADDR_LOOPBACK(addr)(__extension__ ({ const struct in6_addr *__a = (const struct in6_addr *) (addr); __a->__in6_u.__u6_addr32[0] == 0 && __a ->__in6_u.__u6_addr32[1] == 0 && __a->__in6_u.__u6_addr32 [2] == 0 && __a->__in6_u.__u6_addr32[3] == htonl ( 1); }))) { | |||
800 | DEBUG(SSSDBG_FUNC_DATA, "Loopback IPv6 address %s\n", straddr)do { int __debug_macro_level = 0x0200; if ((debug_level & (__debug_macro_level) || (debug_level == 0 && (__debug_macro_level & (0x0010 | 0x0020))))) { debug_fn("../src/util/util.c", 800, __FUNCTION__, __debug_macro_level, "Loopback IPv6 address %s\n" , straddr); } } while (0); | |||
801 | return false0; | |||
802 | } else if ((flags & SSS_NO_MULTICAST0x04) && IN6_IS_ADDR_MULTICAST(addr)(((const uint8_t *) (addr))[0] == 0xff)) { | |||
803 | DEBUG(SSSDBG_FUNC_DATA, "Multicast IPv6 address %s\n", straddr)do { int __debug_macro_level = 0x0200; if ((debug_level & (__debug_macro_level) || (debug_level == 0 && (__debug_macro_level & (0x0010 | 0x0020))))) { debug_fn("../src/util/util.c", 803, __FUNCTION__, __debug_macro_level, "Multicast IPv6 address %s\n" , straddr); } } while (0); | |||
804 | return false0; | |||
805 | } | |||
806 | ||||
807 | return true1; | |||
808 | } | |||
809 | ||||
810 | const char * const * get_known_services(void) | |||
811 | { | |||
812 | static const char *svc[] = {"nss", "pam", "sudo", "autofs", | |||
813 | "ssh", "pac", "ifp", NULL((void*)0) }; | |||
814 | ||||
815 | return svc; | |||
816 | } |