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  */
list_count_str_array(char ** list)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  */
list_count_int_array(int * list)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  */
krb5_free_list_entries(list)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
krb5_parse_list(buffer,delimiter,list)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 
compare_int(m1,m2)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  */
list_modify_str_array(destlist,sourcelist,mode)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  */
list_modify_int_array(destlist,sourcelist,mode)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 
285