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