1 /*
   2  * kadmin/ldap_util/kdb5_ldap_list.c
   3  */
   4 
   5 /* Copyright (c) 2004-2005, Novell, Inc.
   6  * All rights reserved.
   7  *
   8  * Redistribution and use in source and binary forms, with or without
   9  * modification, are permitted provided that the following conditions are met:
  10  *
  11  *   * Redistributions of source code must retain the above copyright notice,
  12  *       this list of conditions and the following disclaimer.
  13  *   * Redistributions in binary form must reproduce the above copyright
  14  *       notice, this list of conditions and the following disclaimer in the
  15  *       documentation and/or other materials provided with the distribution.
  16  *   * The copyright holder's name is not used to endorse or promote products
  17  *       derived from this software without specific prior written permission.
  18  *
  19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  20  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  22  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  23  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  29  * POSSIBILITY OF SUCH DAMAGE.
  30  */
  31 
  32 /*
  33  * Miscellaneous functions for managing the string and integer lists
  34  */
  35 
  36 #include <k5-int.h>
  37 #include "kdb5_ldap_list.h"
  38 
  39 /*
  40  * Counts the number of entries in the given array of strings
  41  */
  42 int list_count_str_array(char **list)
  43 {
  44     int i = 0;
  45 
  46     if (list == NULL)
  47         return 0;
  48 
  49     for (i = 0; *list != NULL; list++) {
  50         i++;
  51     }
  52 
  53     return i;
  54 }
  55 
  56 
  57 /*
  58  * Counts the number of entries in the given array of integers
  59  */
  60 int list_count_int_array(int *list)
  61 {
  62     int i = 0;
  63 
  64     if (list == NULL)
  65         return 0;
  66 
  67     for (i = 0; *list != END_OF_LIST; list++) {
  68         i++;
  69     }
  70 
  71     return i;
  72 }
  73 
  74 
  75 /*
  76  * Frees the entries in a given list and not the list pointer
  77  */
  78 void krb5_free_list_entries(list)
  79     char **list;
  80 {
  81     if (list == NULL)
  82         return;
  83     for (; *list != NULL; list++) {
  84         free(*list);
  85         *list = NULL;
  86     }
  87 
  88     return;
  89 }
  90 
  91 
  92 /*
  93  * Tokenize the given string based on the delimiter provided
  94  * and return the result as a list
  95  */
  96 krb5_error_code
  97 krb5_parse_list(buffer, delimiter, list)
  98     char *buffer;
  99     char *delimiter;
 100     char **list;
 101 {
 102     char *str = NULL;
 103     char *token = NULL;
 104     char *ptrptr = NULL;
 105     char **plist = list;
 106     krb5_error_code retval = 0;
 107     int count = 0;
 108 
 109     if ((buffer == NULL) || (list == NULL) || (delimiter == NULL)) {
 110         return EINVAL;
 111     }
 112 
 113     str = strdup(buffer);
 114     if (str == NULL)
 115         return ENOMEM;
 116 
 117     token = strtok_r(str, delimiter, &ptrptr);
 118     for (count = 1; ((token != NULL) && (count < MAX_LIST_ENTRIES));
 119          plist++, count++) {
 120         *plist = strdup(token);
 121         if (*plist == NULL) {
 122             retval = ENOMEM;
 123             goto cleanup;
 124         }
 125         token = strtok_r(NULL, delimiter, &ptrptr);
 126     }
 127     *plist = NULL;
 128 
 129 cleanup:
 130     if (str) {
 131         free(str);
 132         str = NULL;
 133     }
 134     if (retval)
 135         krb5_free_list_entries(list);
 136 
 137     return retval;
 138 }
 139 
 140 
 141 int compare_int(m1, m2)
 142     const void *m1;
 143     const void *m2;
 144 {
 145     int mi1 = *(const int *)m1;
 146     int mi2 = *(const int *)m2;
 147 
 148     return (mi1 - mi2);
 149 }
 150 
 151 
 152 /*
 153  * Modifies the destination list to contain or not to contain the
 154  * entries present in the source list, depending on the mode
 155  * (ADD or DELETE).
 156  */
 157 void list_modify_str_array(destlist, sourcelist, mode)
 158     char ***destlist;
 159     const char **sourcelist;
 160     int mode;
 161 {
 162     char **dlist = NULL, **tmplist = NULL;
 163     const char **slist = NULL;
 164     int dcount = 0, scount = 0, copycount = 0;
 165 
 166     if ((destlist == NULL) || (*destlist == NULL) || (sourcelist == NULL))
 167         return;
 168 
 169     /* We need to add every entry present in the source list to
 170      * the destination list */
 171     if (mode == LIST_MODE_ADD) {
 172         /* Traverse throught the end of destlist for appending */
 173         for (dlist = *destlist, dcount = 0; *dlist != NULL;
 174              dlist++, dcount++) {
 175             ;   /* NULL statement */
 176         }
 177         /* Count the number of entries in the source list */
 178         for (slist = sourcelist, scount = 0; *slist != NULL;
 179              slist++, scount++) {
 180             ;   /* NULL statement */
 181         }
 182         /* Reset the slist pointer to the start of source list */
 183         slist = sourcelist;
 184 
 185         /* Now append the source list to the existing destlist */
 186         if ((dcount + scount) < MAX_LIST_ENTRIES)
 187             copycount = scount;
 188         else
 189             /* Leave the last entry for list terminator(=NULL) */
 190             copycount = (MAX_LIST_ENTRIES -1) - dcount;
 191 
 192         memcpy(dlist, slist, (sizeof(char *) * copycount));
 193         dlist += copycount;
 194         *dlist = NULL;
 195     } else if (mode == LIST_MODE_DELETE) {
 196         /* We need to delete every entry present in the source list
 197          * from the destination list */
 198         for (slist = sourcelist; *slist != NULL; slist++) {
 199             for (dlist = *destlist; *dlist != NULL; dlist++) {
 200                 /* DN is case insensitive string */
 201                 if (strcasecmp(*dlist, *slist) == 0) {
 202                     free(*dlist);
 203                     /* Advance the rest of the entries by one */
 204                     for (tmplist = dlist; *tmplist != NULL; tmplist++) {
 205                         *tmplist = *(tmplist+1);
 206                     }
 207                     break;
 208                 }
 209             }
 210         }
 211     }
 212 
 213     return;
 214 }
 215 
 216 
 217 /*
 218  * Modifies the destination list to contain or not to contain the
 219  * entries present in the source list, depending on the mode
 220  * (ADD or DELETE). where the list is array of integers.
 221  */
 222 int list_modify_int_array(destlist, sourcelist, mode)
 223     int *destlist;
 224     const int *sourcelist;
 225     int mode;
 226 {
 227     int *dlist = NULL, *tmplist = NULL;
 228     const int *slist = NULL;
 229     int dcount = 0, scount = 0, copycount = 0;
 230     int tcount = 0;
 231 
 232     if ((destlist == NULL) || (sourcelist == NULL))
 233         return 0;
 234 
 235     /* We need to add every entry present in the source list to the
 236      * destination list */
 237     if (mode == LIST_MODE_ADD) {
 238         /* Traverse throught the end of destlist for appending */
 239         for (dlist = destlist, dcount = 0; *dlist != END_OF_LIST;
 240              dlist++, dcount++)
 241             ;   /* NULL statement */
 242 
 243         /* Count the number of entries in the source list */
 244         for (slist = sourcelist, scount = 0; *slist != END_OF_LIST;
 245              slist++, scount++)
 246             ;   /* NULL statement */
 247 
 248         /* Reset the slist pointer to the start of source list */
 249         slist = sourcelist;
 250 
 251         /* Now append the source list to the existing destlist */
 252         if ((dcount + scount) < MAX_LIST_ENTRIES)
 253             copycount = scount;
 254         else
 255             /* Leave the last entry for list terminator(=NULL) */
 256             copycount = (MAX_LIST_ENTRIES -1) - dcount;
 257 
 258         memcpy(dlist, slist, (sizeof(int) * copycount));
 259         dlist += copycount;
 260         *dlist = END_OF_LIST;
 261         tcount = dcount + copycount;
 262     } else if (mode == LIST_MODE_DELETE) {
 263         /* We need to delete every entry present in the source list from
 264          * the destination list */
 265         for (slist = sourcelist; *slist != END_OF_LIST; slist++) {
 266             for (dlist = destlist; *dlist != END_OF_LIST; dlist++) {
 267                 if (*dlist == *slist) {
 268                     /* Advance the rest of the entries by one */
 269                     for (tmplist = dlist; *tmplist != END_OF_LIST; tmplist++) {
 270                         *tmplist = *(tmplist+1);
 271                     }
 272                     break;
 273                 }
 274             }
 275         }
 276         /* count the number of entries */
 277         for (dlist = destlist, tcount = 0; *dlist != END_OF_LIST; dlist++) {
 278             tcount++;
 279         }
 280     }
 281 
 282     return tcount;
 283 }
 284