sssd  2.2.3
About: SSSD provides a set of daemons to manage access to remote directories and authentication mechanisms such as LDAP, Kerberos or FreeIPA. It provides also an NSS and PAM interface toward the system.
  Fossies Dox: sssd-2.2.3.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

util.c
Go to the documentation of this file.
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 "config.h"
22 #include <ctype.h>
23 #include <netdb.h>
24 #include <poll.h>
25 #include <sys/types.h>
26 #include <sys/socket.h>
27 #include <arpa/inet.h>
28 #include <fcntl.h>
29 #include <talloc.h>
30 #include <dhash.h>
31 #include <time.h>
32 
33 #include "util/util.h"
34 #include "util/sss_utf8.h"
35 
38 
39 static void free_args(char **args)
40 {
41  int i;
42 
43  if (args) {
44  for (i = 0; args[i]; i++) free(args[i]);
45  free(args);
46  }
47 }
48 
49 /* parse a string into arguments.
50  * arguments are separated by a space
51  * '\' is an escape character and can be used only to escape
52  * itself or the white space.
53  */
54 char **parse_args(const char *str)
55 {
56  const char *p;
57  char **ret, **r;
58  char *tmp;
59  int num;
60  int i;
61  bool e, w;
62 
63  tmp = malloc(strlen(str) + 1);
64  if (!tmp) return NULL;
65 
66  ret = NULL;
67  num = 0;
68  i = 0;
69  e = false;
70  /* skip leading whitespaces */
71  w = true;
72  p = str;
73  while (*p) {
74  if (*p == '\\') {
75  w = false;
76  if (e) {
77  /* if we were already escaping, add a '\' literal */
78  tmp[i] = '\\';
79  i++;
80  e = false;
81  } else {
82  /* otherwise just start escaping */
83  e = true;
84  }
85  } else if (isspace(*p)) {
86  if (e) {
87  /* Add escaped whitespace literally */
88  tmp[i] = *p;
89  i++;
90  e = false;
91  } else if (w == false) {
92  /* If previous character was non-whitespace, arg break */
93  tmp[i] = '\0';
94  i++;
95  w = true;
96  }
97  /* previous char was whitespace as well, skip it */
98  } else {
99  w = false;
100  if (e) {
101  /* Prepend escaped chars with a literal \ */
102  tmp[i] = '\\';
103  i++;
104  e = false;
105  }
106  /* Copy character from the source string */
107  tmp[i] = *p;
108  i++;
109  }
110 
111  p++;
112 
113  /* check if this was the last char */
114  if (*p == '\0') {
115  if (e) {
116  tmp[i] = '\\';
117  i++;
118  e = false;
119  }
120  tmp[i] = '\0';
121  i++;
122  }
123 
124  /* save token to result array */
125  if (i > 1 && tmp[i-1] == '\0') {
126  r = realloc(ret, (num + 2) * sizeof(char *));
127  if (!r) goto fail;
128  ret = r;
129  ret[num+1] = NULL;
130  ret[num] = strdup(tmp);
131  if (!ret[num]) goto fail;
132  num++;
133  i = 0;
134  }
135  }
136 
137  free(tmp);
138  return ret;
139 
140 fail:
141  free(tmp);
142  free_args(ret);
143  return NULL;
144 }
145 
146 const char **dup_string_list(TALLOC_CTX *memctx, const char **str_list)
147 {
148  int i = 0;
149  int j = 0;
150  const char **dup_list;
151 
152  if (!str_list) {
153  return NULL;
154  }
155 
156  /* Find the size of the list */
157  while (str_list[i]) i++;
158 
159  dup_list = talloc_array(memctx, const char *, i+1);
160  if (!dup_list) {
161  return NULL;
162  }
163 
164  /* Copy the elements */
165  for (j = 0; j < i; j++) {
166  dup_list[j] = talloc_strdup(dup_list, str_list[j]);
167  if (!dup_list[j]) {
168  talloc_free(dup_list);
169  return NULL;
170  }
171  }
172 
173  /* NULL-terminate the list */
174  dup_list[i] = NULL;
175 
176  return dup_list;
177 }
178 
179 /* Take two string lists (terminated on a NULL char*)
180  * and return up to three arrays of strings based on
181  * shared ownership.
182  *
183  * Pass NULL to any return type you don't care about
184  */
185 errno_t diff_string_lists(TALLOC_CTX *memctx,
186  char **_list1,
187  char **_list2,
188  char ***_list1_only,
189  char ***_list2_only,
190  char ***_both_lists)
191 {
192  int error;
193  errno_t ret;
194  int i;
195  int i2 = 0;
196  int i12 = 0;
197  hash_table_t *table;
198  hash_key_t key;
199  hash_value_t value;
200  char **list1 = NULL;
201  char **list2 = NULL;
202  char **list1_only = NULL;
203  char **list2_only = NULL;
204  char **both_lists = NULL;
205  unsigned long count;
206  hash_key_t *keys;
207 
208  TALLOC_CTX *tmp_ctx = talloc_new(memctx);
209  if (!tmp_ctx) {
210  return ENOMEM;
211  }
212 
213  if (!_list1) {
214  list1 = talloc_array(tmp_ctx, char *, 1);
215  if (!list1) {
216  talloc_free(tmp_ctx);
217  return ENOMEM;
218  }
219  list1[0] = NULL;
220  }
221  else {
222  list1 = _list1;
223  }
224 
225  if (!_list2) {
226  list2 = talloc_array(tmp_ctx, char *, 1);
227  if (!list2) {
228  talloc_free(tmp_ctx);
229  return ENOMEM;
230  }
231  list2[0] = NULL;
232  }
233  else {
234  list2 = _list2;
235  }
236 
237  error = hash_create(10, &table, NULL, NULL);
238  if (error != HASH_SUCCESS) {
239  talloc_free(tmp_ctx);
240  return EIO;
241  }
242 
243  key.type = HASH_KEY_STRING;
244  value.type = HASH_VALUE_UNDEF;
245 
246  /* Add all entries from list 1 into a hash table */
247  i = 0;
248  while (list1[i]) {
249  key.str = talloc_strdup(tmp_ctx, list1[i]);
250  error = hash_enter(table, &key, &value);
251  if (error != HASH_SUCCESS) {
252  ret = EIO;
253  goto done;
254  }
255  i++;
256  }
257 
258  /* Iterate through list 2 and remove matching items */
259  i = 0;
260  while (list2[i]) {
261  key.str = talloc_strdup(tmp_ctx, list2[i]);
262  error = hash_delete(table, &key);
263  if (error == HASH_SUCCESS) {
264  if (_both_lists) {
265  /* String was present in both lists */
266  i12++;
267  both_lists = talloc_realloc(tmp_ctx, both_lists, char *, i12+1);
268  if (!both_lists) {
269  ret = ENOMEM;
270  goto done;
271  }
272  both_lists[i12-1] = talloc_strdup(both_lists, list2[i]);
273  if (!both_lists[i12-1]) {
274  ret = ENOMEM;
275  goto done;
276  }
277 
278  both_lists[i12] = NULL;
279  }
280  }
281  else if (error == HASH_ERROR_KEY_NOT_FOUND) {
282  if (_list2_only) {
283  /* String was present only in list2 */
284  i2++;
285  list2_only = talloc_realloc(tmp_ctx, list2_only,
286  char *, i2+1);
287  if (!list2_only) {
288  ret = ENOMEM;
289  goto done;
290  }
291  list2_only[i2-1] = talloc_strdup(list2_only, list2[i]);
292  if (!list2_only[i2-1]) {
293  ret = ENOMEM;
294  goto done;
295  }
296 
297  list2_only[i2] = NULL;
298  }
299  }
300  else {
301  /* An error occurred */
302  ret = EIO;
303  goto done;
304  }
305  i++;
306  }
307 
308  /* Get the leftover entries in the hash table */
309  if (_list1_only) {
310  error = hash_keys(table, &count, &keys);
311  if (error != HASH_SUCCESS) {
312  ret = EIO;
313  goto done;
314  }
315 
316  list1_only = talloc_array(tmp_ctx, char *, count+1);
317  if (!list1_only) {
318  ret = ENOMEM;
319  goto done;
320  }
321 
322  for (i = 0; i < count; i++) {
323  list1_only[i] = talloc_strdup(list1_only, keys[i].str);
324  if (!list1_only[i]) {
325  ret = ENOMEM;
326  goto done;
327  }
328  }
329  list1_only[count] = NULL;
330 
331  free(keys);
332 
333  *_list1_only = talloc_steal(memctx, list1_only);
334  }
335 
336  if (_list2_only) {
337  if (list2_only) {
338  *_list2_only = talloc_steal(memctx, list2_only);
339  }
340  else {
341  *_list2_only = talloc_array(memctx, char *, 1);
342  if (!(*_list2_only)) {
343  ret = ENOMEM;
344  goto done;
345  }
346  *_list2_only[0] = NULL;
347  }
348  }
349 
350  if (_both_lists) {
351  if (both_lists) {
352  *_both_lists = talloc_steal(memctx, both_lists);
353  }
354  else {
355  *_both_lists = talloc_array(memctx, char *, 1);
356  if (!(*_both_lists)) {
357  ret = ENOMEM;
358  goto done;
359  }
360  *_both_lists[0] = NULL;
361  }
362  }
363 
364  ret = EOK;
365 
366 done:
367  hash_destroy(table);
368  talloc_free(tmp_ctx);
369  return ret;
370 }
371 
372 static void *hash_talloc(const size_t size, void *pvt)
373 {
374  return talloc_size(pvt, size);
375 }
376 
377 static void hash_talloc_free(void *ptr, void *pvt)
378 {
379  talloc_free(ptr);
380 }
381 
382 errno_t sss_hash_create_ex(TALLOC_CTX *mem_ctx,
383  unsigned long count,
384  hash_table_t **tbl,
385  unsigned int directory_bits,
386  unsigned int segment_bits,
387  unsigned long min_load_factor,
388  unsigned long max_load_factor,
389  hash_delete_callback *delete_callback,
390  void *delete_private_data)
391 {
392  errno_t ret;
393  hash_table_t *table;
394  int hret;
395 
396  TALLOC_CTX *internal_ctx;
397  internal_ctx = talloc_new(NULL);
398  if (!internal_ctx) {
399  return ENOMEM;
400  }
401 
402  hret = hash_create_ex(count, &table, directory_bits, segment_bits,
403  min_load_factor, max_load_factor,
404  hash_talloc, hash_talloc_free, internal_ctx,
405  delete_callback, delete_private_data);
406  switch (hret) {
407  case HASH_SUCCESS:
408  /* Steal the table pointer onto the mem_ctx,
409  * then make the internal_ctx a child of
410  * table.
411  *
412  * This way, we can clean up the values when
413  * we talloc_free() the table
414  */
415  *tbl = talloc_steal(mem_ctx, table);
416  talloc_steal(table, internal_ctx);
417  return EOK;
418 
419  case HASH_ERROR_NO_MEMORY:
420  ret = ENOMEM;
421  break;
422  default:
423  ret = EIO;
424  }
425 
426  DEBUG(SSSDBG_FATAL_FAILURE, "Could not create hash table: [%d][%s]\n",
427  hret, hash_error_string(hret));
428 
429  talloc_free(internal_ctx);
430  return ret;
431 }
432 
433 errno_t sss_hash_create(TALLOC_CTX *mem_ctx, unsigned long count,
434  hash_table_t **tbl)
435 {
436  return sss_hash_create_ex(mem_ctx, count, tbl, 0, 0, 0, 0, NULL, NULL);
437 }
438 
439 errno_t sss_filter_sanitize_ex(TALLOC_CTX *mem_ctx,
440  const char *input,
441  char **sanitized,
442  const char *ignore)
443 {
444  char *output;
445  size_t i = 0;
446  size_t j = 0;
447  char *allowed;
448 
449  /* Assume the worst-case. We'll resize it later, once */
450  output = talloc_array(mem_ctx, char, strlen(input) * 3 + 1);
451  if (!output) {
452  return ENOMEM;
453  }
454 
455  while (input[i]) {
456  /* Even though this character might have a special meaning, if it's
457  * explicitly allowed, just copy it and move on
458  */
459  if (ignore == NULL) {
460  allowed = NULL;
461  } else {
462  allowed = strchr(ignore, input[i]);
463  }
464  if (allowed) {
465  output[j++] = input[i++];
466  continue;
467  }
468 
469  switch(input[i]) {
470  case '\t':
471  output[j++] = '\\';
472  output[j++] = '0';
473  output[j++] = '9';
474  break;
475  case ' ':
476  output[j++] = '\\';
477  output[j++] = '2';
478  output[j++] = '0';
479  break;
480  case '*':
481  output[j++] = '\\';
482  output[j++] = '2';
483  output[j++] = 'a';
484  break;
485  case '(':
486  output[j++] = '\\';
487  output[j++] = '2';
488  output[j++] = '8';
489  break;
490  case ')':
491  output[j++] = '\\';
492  output[j++] = '2';
493  output[j++] = '9';
494  break;
495  case '\\':
496  output[j++] = '\\';
497  output[j++] = '5';
498  output[j++] = 'c';
499  break;
500  case '\r':
501  output[j++] = '\\';
502  output[j++] = '0';
503  output[j++] = 'd';
504  break;
505  case '\n':
506  output[j++] = '\\';
507  output[j++] = '0';
508  output[j++] = 'a';
509  break;
510  default:
511  output[j++] = input[i];
512  }
513 
514  i++;
515  }
516  output[j] = '\0';
517  *sanitized = talloc_realloc(mem_ctx, output, char, j+1);
518  if (!*sanitized) {
519  talloc_free(output);
520  return ENOMEM;
521  }
522 
523  return EOK;
524 }
525 
526 errno_t sss_filter_sanitize(TALLOC_CTX *mem_ctx,
527  const char *input,
528  char **sanitized)
529 {
530  return sss_filter_sanitize_ex(mem_ctx, input, sanitized, NULL);
531 }
532 
533 char *
534 sss_escape_ip_address(TALLOC_CTX *mem_ctx, int family, const char *addr)
535 {
536  return family == AF_INET6 ? talloc_asprintf(mem_ctx, "[%s]", addr) :
537  talloc_strdup(mem_ctx, addr);
538 }
539 
540 /* out->len includes terminating '\0' */
541 void to_sized_string(struct sized_string *out, const char *in)
542 {
543  out->str = in;
544  if (out->str) {
545  out->len = strlen(out->str) + 1;
546  } else {
547  out->len = 0;
548  }
549 }
550 
551 /* This function only removes first and last
552  * character if the first character was '['.
553  *
554  * NOTE: This means, that ipv6addr must NOT be followed
555  * by port number.
556  */
557 errno_t
558 remove_ipv6_brackets(char *ipv6addr)
559 {
560  size_t len;
561 
562  if (ipv6addr && ipv6addr[0] == '[') {
563  len = strlen(ipv6addr);
564  if (len < 3) {
565  return EINVAL;
566  }
567 
568  memmove(ipv6addr, &ipv6addr[1], len - 2);
569  ipv6addr[len -2] = '\0';
570  }
571 
572  return EOK;
573 }
574 
575 errno_t add_string_to_list(TALLOC_CTX *mem_ctx, const char *string,
576  char ***list_p)
577 {
578  size_t c;
579  char **old_list = NULL;
580  char **new_list = NULL;
581 
582  if (string == NULL || list_p == NULL) {
583  DEBUG(SSSDBG_OP_FAILURE, "Missing string or list.\n");
584  return EINVAL;
585  }
586 
587  old_list = *list_p;
588 
589  if (old_list == NULL) {
590  /* If the input is a NULL list a new one is created with the new
591  * string and the terminating NULL element. */
592  c = 0;
593  new_list = talloc_array(mem_ctx, char *, 2);
594  } else {
595  for (c = 0; old_list[c] != NULL; c++);
596  /* Allocate one extra space for the new service and one for
597  * the terminating NULL
598  */
599  new_list = talloc_realloc(mem_ctx, old_list, char *, c + 2);
600  }
601 
602  if (new_list == NULL) {
603  DEBUG(SSSDBG_OP_FAILURE, "talloc_array/talloc_realloc failed.\n");
604  return ENOMEM;
605  }
606 
607  new_list[c] = talloc_strdup(new_list, string);
608  if (new_list[c] == NULL) {
609  DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n");
610  talloc_free(new_list);
611  return ENOMEM;
612  }
613 
614  new_list[c + 1] = NULL;
615 
616  *list_p = new_list;
617 
618  return EOK;
619 }
620 
621 int domain_to_basedn(TALLOC_CTX *memctx, const char *domain, char **basedn)
622 {
623  const char *s;
624  char *dn;
625  char *p;
626  int l;
627 
628  if (!domain || !basedn) {
629  return EINVAL;
630  }
631 
632  s = domain;
633  dn = talloc_strdup(memctx, "dc=");
634 
635  while ((p = strchr(s, '.'))) {
636  l = p - s;
637  dn = talloc_asprintf_append_buffer(dn, "%.*s,dc=", l, s);
638  if (!dn) {
639  return ENOMEM;
640  }
641  s = p + 1;
642  }
643  dn = talloc_strdup_append_buffer(dn, s);
644  if (!dn) {
645  return ENOMEM;
646  }
647 
648  for (p=dn; *p; ++p) {
649  *p = tolower(*p);
650  }
651 
652  *basedn = dn;
653  return EOK;
654 }
655 
656 bool is_host_in_domain(const char *host, const char *domain)
657 {
658  int diff = strlen(host) - strlen(domain);
659 
660  if (diff == 0 && strcmp(host, domain) == 0) {
661  return true;
662  }
663 
664  if (diff > 0 && strcmp(host + diff, domain) == 0 && host[diff - 1] == '.') {
665  return true;
666  }
667 
668  return false;
669 }
670 
671 /* addr is in network order for both IPv4 and IPv6 versions */
672 bool check_ipv4_addr(struct in_addr *addr, uint8_t flags)
673 {
674  char straddr[INET_ADDRSTRLEN];
675 
676  if (inet_ntop(AF_INET, addr, straddr, INET_ADDRSTRLEN) == NULL) {
678  "inet_ntop failed, won't log IP addresses\n");
679  snprintf(straddr, INET_ADDRSTRLEN, "unknown");
680  }
681 
682  if ((flags & SSS_NO_MULTICAST) && IN_MULTICAST(ntohl(addr->s_addr))) {
683  DEBUG(SSSDBG_FUNC_DATA, "Multicast IPv4 address %s\n", straddr);
684  return false;
685  } else if ((flags & SSS_NO_LOOPBACK)
686  && inet_netof(*addr) == IN_LOOPBACKNET) {
687  DEBUG(SSSDBG_FUNC_DATA, "Loopback IPv4 address %s\n", straddr);
688  return false;
689  } else if ((flags & SSS_NO_LINKLOCAL)
690  && (addr->s_addr & htonl(0xffff0000)) == htonl(0xa9fe0000)) {
691  /* 169.254.0.0/16 */
692  DEBUG(SSSDBG_FUNC_DATA, "Link-local IPv4 address %s\n", straddr);
693  return false;
694  } else if ((flags & SSS_NO_BROADCAST)
695  && addr->s_addr == htonl(INADDR_BROADCAST)) {
696  DEBUG(SSSDBG_FUNC_DATA, "Broadcast IPv4 address %s\n", straddr);
697  return false;
698  }
699 
700  return true;
701 }
702 
703 bool check_ipv6_addr(struct in6_addr *addr, uint8_t flags)
704 {
705  char straddr[INET6_ADDRSTRLEN];
706 
707  if (inet_ntop(AF_INET6, addr, straddr, INET6_ADDRSTRLEN) == NULL) {
709  "inet_ntop failed, won't log IP addresses\n");
710  snprintf(straddr, INET6_ADDRSTRLEN, "unknown");
711  }
712 
713  if ((flags & SSS_NO_LINKLOCAL) && IN6_IS_ADDR_LINKLOCAL(addr)) {
714  DEBUG(SSSDBG_FUNC_DATA, "Link local IPv6 address %s\n", straddr);
715  return false;
716  } else if ((flags & SSS_NO_LOOPBACK) && IN6_IS_ADDR_LOOPBACK(addr)) {
717  DEBUG(SSSDBG_FUNC_DATA, "Loopback IPv6 address %s\n", straddr);
718  return false;
719  } else if ((flags & SSS_NO_MULTICAST) && IN6_IS_ADDR_MULTICAST(addr)) {
720  DEBUG(SSSDBG_FUNC_DATA, "Multicast IPv6 address %s\n", straddr);
721  return false;
722  }
723 
724  return true;
725 }
726 
727 const char * const * get_known_services(void)
728 {
729  static const char *svc[] = {"nss", "pam", "sudo", "autofs",
730  "ssh", "pac", "ifp", NULL };
731 
732  return svc;
733 }
734 
735 errno_t add_strings_lists(TALLOC_CTX *mem_ctx, const char **l1, const char **l2,
736  bool copy_strings, char ***_new_list)
737 {
738  size_t c;
739  size_t l1_count = 0;
740  size_t l2_count = 0;
741  size_t new_count = 0;
742  char **new;
743  int ret;
744 
745  if (l1 != NULL) {
746  for (l1_count = 0; l1[l1_count] != NULL; l1_count++);
747  }
748 
749  if (l2 != NULL) {
750  for (l2_count = 0; l2[l2_count] != NULL; l2_count++);
751  }
752 
753  new_count = l1_count + l2_count;
754 
755  new = talloc_array(mem_ctx, char *, new_count + 1);
756  if (new == NULL) {
757  DEBUG(SSSDBG_OP_FAILURE, "talloc_array failed.\n");
758  return ENOMEM;
759  }
760  new [new_count] = NULL;
761 
762  if (copy_strings) {
763  for(c = 0; c < l1_count; c++) {
764  new[c] = talloc_strdup(new, l1[c]);
765  if (new[c] == NULL) {
766  DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n");
767  ret = ENOMEM;
768  goto done;
769  }
770  }
771  for(c = 0; c < l2_count; c++) {
772  new[l1_count + c] = talloc_strdup(new, l2[c]);
773  if (new[l1_count + c] == NULL) {
774  DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n");
775  ret = ENOMEM;
776  goto done;
777  }
778  }
779  } else {
780  if (l1 != NULL) {
781  memcpy(new, l1, sizeof(char *) * l1_count);
782  }
783 
784  if (l2 != NULL) {
785  memcpy(&new[l1_count], l2, sizeof(char *) * l2_count);
786  }
787  }
788 
789  *_new_list = new;
790  ret = EOK;
791 
792 done:
793  if (ret != EOK) {
794  talloc_free(new);
795  }
796 
797  return ret;
798 }
799 
800 /* Set the nonblocking flag to the fd */
802 {
803  int flags;
804  int ret;
805 
806  flags = fcntl(fd, F_GETFL, 0);
807  if (flags == -1) {
808  ret = errno;
810  "F_GETFL failed [%d][%s].\n", ret, strerror(ret));
811  return ret;
812  }
813 
814  if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) {
815  ret = errno;
817  "F_SETFL failed [%d][%s].\n", ret, strerror(ret));
818  return ret;
819  }
820 
821  return EOK;
822 }
823 
824 /* Convert GeneralizedTime (http://en.wikipedia.org/wiki/GeneralizedTime)
825  * to unix time (seconds since epoch). Use UTC time zone.
826  */
827 errno_t sss_utc_to_time_t(const char *str, const char *format, time_t *_unix_time)
828 {
829  char *end;
830  struct tm tm;
831  size_t len;
832  time_t ut;
833 
834  if (str == NULL) {
835  return EINVAL;
836  }
837 
838  len = strlen(str);
839  if (str[len-1] != 'Z') {
841  "%s does not seem to be in UTZ time zone.\n", str);
843  }
844 
845  memset(&tm, 0, sizeof(tm));
846 
847  end = strptime(str, format, &tm);
848  /* not all characters from format were matched */
849  if (end == NULL) {
851  "String [%s] failed to match format [%s].\n", str, format);
852  return EINVAL;
853  }
854 
855  /* str is 'longer' than format */
856  if (*end != '\0') {
858  "String [%s] is longer than format [%s].\n", str, format);
859  return EINVAL;
860  }
861 
862  ut = mktime(&tm);
863  if (ut == -1) {
865  "mktime failed to convert [%s].\n", str);
866  return EINVAL;
867  }
868 
869  tzset();
870  ut -= timezone;
871  *_unix_time = ut;
872  return EOK;
873 }
874 
876  const char *filename;
877 };
878 
879 static int unlink_dbg(const char *filename)
880 {
881  errno_t ret;
882 
883  ret = unlink(filename);
884  if (ret != 0) {
885  ret = errno;
886  if (ret == ENOENT) {
888  "File already removed: [%s]\n", filename);
889  return 0;
890  } else {
892  "Cannot remove temporary file [%s] %d [%s]\n",
893  filename, ret, strerror(ret));
894  return -1;
895  }
896  }
897 
898  return 0;
899 }
900 
901 static int unique_filename_destructor(void *memptr)
902 {
903  struct tmpfile_watch *tw = talloc_get_type(memptr, struct tmpfile_watch);
904 
905  if (tw == NULL || tw->filename == NULL) {
906  DEBUG(SSSDBG_CRIT_FAILURE, "BUG: Wrong private pointer\n");
907  return -1;
908  }
909 
910  DEBUG(SSSDBG_TRACE_INTERNAL, "Unlinking [%s]\n", tw->filename);
911 
912  return unlink_dbg(tw->filename);
913 }
914 
915 static struct tmpfile_watch *tmpfile_watch_set(TALLOC_CTX *owner,
916  const char *filename)
917 {
918  struct tmpfile_watch *tw = NULL;
919 
920  tw = talloc_zero(owner, struct tmpfile_watch);
921  if (tw == NULL) {
922  return NULL;
923  }
924 
925  tw->filename = talloc_strdup(tw, filename);
926  if (tw->filename == NULL) {
927  talloc_free(tw);
928  return NULL;
929  }
930 
931  talloc_set_destructor((TALLOC_CTX *) tw,
933  return tw;
934 }
935 
936 int sss_unique_file_ex(TALLOC_CTX *owner,
937  char *path_tmpl,
938  mode_t file_umask,
939  errno_t *_err)
940 {
941  size_t tmpl_len;
942  errno_t ret;
943  int fd = -1;
944  mode_t old_umask;
945  struct tmpfile_watch *tw = NULL;
946 
947  tmpl_len = strlen(path_tmpl);
948  if (tmpl_len < 6 || strcmp(path_tmpl + (tmpl_len - 6), "XXXXXX") != 0) {
950  "Template too short or doesn't end with XXXXXX!\n");
951  ret = EINVAL;
952  goto done;
953  }
954 
955  old_umask = umask(file_umask);
956  fd = mkstemp(path_tmpl);
957  umask(old_umask);
958  if (fd == -1) {
959  ret = errno;
961  "mkstemp(\"%s\") failed [%d]: %s!\n",
962  path_tmpl, ret, strerror(ret));
963  goto done;
964  }
965 
966  if (owner != NULL) {
967  tw = tmpfile_watch_set(owner, path_tmpl);
968  if (tw == NULL) {
969  unlink_dbg(path_tmpl);
970  ret = ENOMEM;
971  goto done;
972  }
973  }
974 
975  ret = EOK;
976 done:
977  if (_err) {
978  *_err = ret;
979  }
980  return fd;
981 }
982 
983 int sss_unique_file(TALLOC_CTX *owner,
984  char *path_tmpl,
985  errno_t *_err)
986 {
987  return sss_unique_file_ex(owner, path_tmpl, SSS_DFL_UMASK, _err);
988 }
989 
990 errno_t sss_unique_filename(TALLOC_CTX *owner, char *path_tmpl)
991 {
992  int fd;
993  errno_t ret;
994 
995  fd = sss_unique_file(owner, path_tmpl, &ret);
996  /* We only care about a unique file name */
997  if (fd >= 0) {
998  close(fd);
999  }
1000 
1001  return ret;
1002 }
1003 
1004 bool is_user_or_group_name(const char *sudo_user_value)
1005 {
1006  if (sudo_user_value == NULL) {
1007  return false;
1008  }
1009 
1010  /* See man sudoers.ldap for explanation */
1011  if (strcmp(sudo_user_value, "ALL") == 0) {
1012  return false;
1013  }
1014 
1015  switch (sudo_user_value[0]) {
1016  case '#': /* user id */
1017  case '+': /* netgroup */
1018  case '\0': /* empty value */
1019  return false;
1020  }
1021 
1022  if (sudo_user_value[0] == '%') {
1023  switch (sudo_user_value[1]) {
1024  case '#': /* POSIX group ID */
1025  case ':': /* non-POSIX group */
1026  case '\0': /* empty value */
1027  return false;
1028  }
1029  }
1030 
1031  /* Now it's either a username or a groupname */
1032  return true;
1033 }
1034 
1036 {
1037 #ifdef HAVE_SYSTEMD
1038  return !!socket_activated;
1039 #else
1040  return false;
1041 #endif
1042 }
1043 
1045 {
1046 #ifdef HAVE_SYSTEMD
1047  return !!dbus_activated;
1048 #else
1049  return false;
1050 #endif
1051 }
1052 
1054 {
1055 #ifdef BUILD_LOCAL_PROVIDER
1056  return true;
1057 #else
1058  return false;
1059 #endif
1060 }
1061 
1062 int sss_rand(void)
1063 {
1064  static bool srand_done = false;
1065 
1066  /* Coverity might complain here: "DC.WEAK_CRYPTO (CWE-327)"
1067  * It is safe to ignore as this helper function is *NOT* intended
1068  * to be used in security relevant context.
1069  */
1070  if (!srand_done) {
1071  srand(time(NULL) * getpid());
1072  srand_done = true;
1073  }
1074  return rand();
1075 }
SSSDBG_TRACE_INTERNAL
#define SSSDBG_TRACE_INTERNAL
Definition: debug.h:82
get_known_services
const char *const * get_known_services(void)
Definition: util.c:727
EOK
#define EOK
Definition: hbac_evaluator.c:40
output
Definition: sss_nss_idmap.c:43
is_host_in_domain
bool is_host_in_domain(const char *host, const char *domain)
Definition: util.c:656
SSS_NO_MULTICAST
#define SSS_NO_MULTICAST
Definition: util.h:359
tmpfile_watch
Definition: util.c:875
is_dbus_activated
bool is_dbus_activated(void)
Definition: util.c:1044
sss_unique_file_ex
int sss_unique_file_ex(TALLOC_CTX *owner, char *path_tmpl, mode_t file_umask, errno_t *_err)
Definition: util.c:936
sss_rand
int sss_rand(void)
Definition: util.c:1062
to_sized_string
void to_sized_string(struct sized_string *out, const char *in)
Definition: util.c:541
tmpfile_watch_set
static struct tmpfile_watch * tmpfile_watch_set(TALLOC_CTX *owner, const char *filename)
Definition: util.c:915
sized_string::str
const char * str
Definition: util.h:521
diff_string_lists
errno_t diff_string_lists(TALLOC_CTX *memctx, char **_list1, char **_list2, char ***_list1_only, char ***_list2_only, char ***_both_lists)
Definition: util.c:185
add_strings_lists
errno_t add_strings_lists(TALLOC_CTX *mem_ctx, const char **l1, const char **l2, bool copy_strings, char ***_new_list)
Add two list of strings.
Definition: util.c:735
SSS_DFL_UMASK
#define SSS_DFL_UMASK
Default secure umask.
Definition: util.h:61
DEBUG
#define DEBUG(level, format,...)
macro to generate debug messages
Definition: debug.h:123
sss_hash_create_ex
errno_t sss_hash_create_ex(TALLOC_CTX *mem_ctx, unsigned long count, hash_table_t **tbl, unsigned int directory_bits, unsigned int segment_bits, unsigned long min_load_factor, unsigned long max_load_factor, hash_delete_callback *delete_callback, void *delete_private_data)
Definition: util.c:382
add_string_to_list
errno_t add_string_to_list(TALLOC_CTX *mem_ctx, const char *string, char ***list_p)
Definition: util.c:575
SSSDBG_FUNC_DATA
#define SSSDBG_FUNC_DATA
Definition: debug.h:79
ERR_TIMESPEC_NOT_SUPPORTED
@ ERR_TIMESPEC_NOT_SUPPORTED
Definition: util_errors.h:103
SSS_NO_LINKLOCAL
#define SSS_NO_LINKLOCAL
Definition: util.h:357
errno_t
int errno_t
Definition: hbac_evaluator.c:36
sss_unique_filename
errno_t sss_unique_filename(TALLOC_CTX *owner, char *path_tmpl)
Definition: util.c:990
sss_filter_sanitize
errno_t sss_filter_sanitize(TALLOC_CTX *mem_ctx, const char *input, char **sanitized)
Definition: util.c:526
SSSDBG_FATAL_FAILURE
#define SSSDBG_FATAL_FAILURE
Definition: debug.h:74
sized_string
Definition: util.h:520
domain_to_basedn
int domain_to_basedn(TALLOC_CTX *memctx, const char *domain, char **basedn)
Definition: util.c:621
is_socket_activated
bool is_socket_activated(void)
Definition: util.c:1035
dup_string_list
const char ** dup_string_list(TALLOC_CTX *memctx, const char **str_list)
Definition: util.c:146
remove_ipv6_brackets
errno_t remove_ipv6_brackets(char *ipv6addr)
Definition: util.c:558
hash_talloc_free
static void hash_talloc_free(void *ptr, void *pvt)
Definition: util.c:377
sss_utc_to_time_t
errno_t sss_utc_to_time_t(const char *str, const char *format, time_t *_unix_time)
Definition: util.c:827
sss_fd_nonblocking
errno_t sss_fd_nonblocking(int fd)
set file descriptor as nonblocking
Definition: util.c:801
SSSDConfigTest.error
int error
Definition: SSSDConfigTest.py:2129
sized_string::len
size_t len
Definition: util.h:522
dbus_activated
int dbus_activated
Definition: util.c:37
sss_utf8.h
free_args
static void free_args(char **args)
Definition: util.c:39
socket_activated
int socket_activated
Definition: util.c:36
check_ipv4_addr
bool check_ipv4_addr(struct in_addr *addr, uint8_t flags)
Definition: util.c:672
SSSDBG_MINOR_FAILURE
#define SSSDBG_MINOR_FAILURE
Definition: debug.h:77
unlink_dbg
static int unlink_dbg(const char *filename)
Definition: util.c:879
parse_args
char ** parse_args(const char *str)
Definition: util.c:54
SSS_NO_BROADCAST
#define SSS_NO_BROADCAST
Definition: util.h:360
local_provider_is_built
bool local_provider_is_built(void)
Definition: util.c:1053
SSS_NO_LOOPBACK
#define SSS_NO_LOOPBACK
Definition: util.h:358
SSSDBG_CRIT_FAILURE
#define SSSDBG_CRIT_FAILURE
Definition: debug.h:75
sss_unique_file
int sss_unique_file(TALLOC_CTX *owner, char *path_tmpl, errno_t *_err)
Definition: util.c:983
unique_filename_destructor
static int unique_filename_destructor(void *memptr)
Definition: util.c:901
NULL
#define NULL
Definition: util.h:67
SSSDBG_OP_FAILURE
#define SSSDBG_OP_FAILURE
Definition: debug.h:76
is_user_or_group_name
bool is_user_or_group_name(const char *sudo_user_value)
Definition: util.c:1004
tmpfile_watch::filename
const char * filename
Definition: util.c:876
util.h
sss_hash_create
errno_t sss_hash_create(TALLOC_CTX *mem_ctx, unsigned long count, hash_table_t **tbl)
Definition: util.c:433
check_ipv6_addr
bool check_ipv6_addr(struct in6_addr *addr, uint8_t flags)
Definition: util.c:703
hash_talloc
static void * hash_talloc(const size_t size, void *pvt)
Definition: util.c:372
input
Definition: sss_nss_idmap.c:38
ret
errno_t ret
Definition: sbus_errors.c:31
sss_escape_ip_address
char * sss_escape_ip_address(TALLOC_CTX *mem_ctx, int family, const char *addr)
Definition: util.c:534
sss_filter_sanitize_ex
errno_t sss_filter_sanitize_ex(TALLOC_CTX *mem_ctx, const char *input, char **sanitized, const char *ignore)
Definition: util.c:439