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