LCOV - code coverage report
Current view: top level - util - util.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 478 613 78.0 %
Date: 2016-06-29 Functions: 30 33 90.9 %

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

Generated by: LCOV version 1.10