Print this page
1668 CVE 2011-3508 (ldap format string issues)
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/lib/nsswitch/ldap/common/ldap_utils.c
+++ new/usr/src/lib/nsswitch/ldap/common/ldap_utils.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License, Version 1.0 only
6 6 * (the "License"). You may not use this file except in compliance
7 7 * with the License.
8 8 *
9 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 10 * or http://www.opensolaris.org/os/licensing.
11 11 * See the License for the specific language governing permissions
12 12 * and limitations under the License.
13 13 *
14 14 * When distributing Covered Code, include this CDDL HEADER in each
|
↓ open down ↓ |
14 lines elided |
↑ open up ↑ |
15 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 16 * If applicable, add the following below this CDDL HEADER, with the
17 17 * fields enclosed by brackets "[]" replaced with your own identifying
18 18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 19 *
20 20 * CDDL HEADER END
21 21 */
22 22 /*
23 23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
24 24 * Use is subject to license terms.
25 + * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
25 26 */
26 27
27 -#pragma ident "%Z%%M% %I% %E% SMI"
28 -
29 28 #include <sys/systeminfo.h>
30 29 #include "ldap_common.h"
31 30
32 31
33 32 #ifdef DEBUG
34 33 /*
35 34 * Debugging routine for printing the value of a result
36 35 * structure
37 36 */
38 37 int
39 38 printresult(ns_ldap_result_t *result)
40 39 {
41 40 int i, j, k;
42 41 ns_ldap_entry_t *curEntry;
43 42
44 43 printf("--------------------------------------\n");
45 44 printf("entries_count %d\n", result->entries_count);
46 45 curEntry = result->entry;
47 46 for (i = 0; i < result->entries_count; i++) {
48 47 printf("entry %d has attr_count = %d \n",
49 48 i, curEntry->attr_count);
50 49 for (j = 0; j < curEntry->attr_count; j++) {
51 50 printf("entry %d has attr_pair[%d] = %s \n",
52 51 i, j, curEntry->attr_pair[j]->attrname);
53 52 for (k = 0;
54 53 (k < curEntry->attr_pair[j]->value_count) &&
55 54 (curEntry->attr_pair[j]->attrvalue[k]);
56 55 k++)
57 56 printf("entry %d has "
58 57 "attr_pair[%d]->attrvalue[%d] = %s \n",
59 58 i, j, k,
60 59 curEntry->attr_pair[j]->attrvalue[k]);
61 60 }
62 61 printf("\n--------------------------------------\n");
63 62 curEntry = curEntry->next;
64 63 }
65 64 return (1);
66 65 }
67 66 #endif
68 67
69 68
70 69 /*
71 70 *
72 71 */
73 72
74 73 ns_ldap_attr_t *
75 74 getattr(ns_ldap_result_t *result, int i)
76 75 {
77 76 ns_ldap_entry_t *entry;
78 77
79 78 #ifdef DEBUG
80 79 (void) fprintf(stdout, "\n[ldap_utils.c: getattr]\n");
81 80 #endif /* DEBUG */
82 81
83 82 if (result != NULL) {
84 83 entry = result->entry;
85 84 } else {
86 85 return (NULL);
87 86 }
88 87 if (result->entries_count == 0) {
89 88 return (NULL);
90 89 } else {
91 90 return (entry->attr_pair[i]);
92 91 }
93 92 }
94 93
95 94 /*
96 95 * _get_domain_name() passes the dn one level up from cdn, e.g.,
97 96 * a pointer pointing to "ou= ..." for the cdn's listed below:
98 97 * dn: cn=hostname+ipHostNumber="109.34.54.76", ou= ...
99 98 * dn: echo+IpServiceProtocol=udp, ou= ...
100 99 * to __ns_ldap_dn2domain() to retrieve the domain name associated
101 100 * with cdn.
102 101 */
103 102
104 103 char *
105 104 _get_domain_name(char *cdn)
106 105 {
107 106 char **rdns;
108 107 char *pdn, *domain = NULL;
109 108 int nrdns;
110 109 int len = 0;
111 110 const ns_cred_t *cred = NULL;
112 111 ns_ldap_error_t *error;
113 112
114 113 /* break the cdn into its components */
115 114 rdns = ldap_explode_dn(cdn, 0);
116 115 if (rdns == NULL || *rdns == NULL)
117 116 return (NULL);
118 117
119 118 /* construct parent dn */
120 119 for (nrdns = 1; rdns[nrdns]; nrdns++)
121 120 len += strlen(rdns[nrdns]) + 1;
122 121 if (len == 0)
123 122 len = strlen(rdns[0]);
124 123 pdn = (char *)malloc(len + 1);
125 124 if (pdn == NULL) {
126 125 ldap_value_free(rdns);
127 126 return (NULL);
128 127 }
129 128
130 129 *pdn = '\0';
131 130 if (nrdns == 1)
132 131 (void) strcat(pdn, rdns[0]);
133 132 else {
134 133 for (nrdns = 1; rdns[nrdns]; nrdns++) {
135 134 (void) strcat(pdn, rdns[nrdns]);
136 135 (void) strcat(pdn, ",");
137 136 }
138 137 /* remove the last ',' */
139 138 pdn[strlen(pdn) - 1] = '\0';
140 139 }
141 140 /* get domain name */
142 141 (void) __ns_ldap_dn2domain(pdn, &domain, cred, &error);
143 142
144 143 ldap_value_free(rdns);
145 144 free(pdn);
146 145 return (domain);
147 146 }
148 147
149 148
150 149 /*
151 150 * "109.34.54.76" -> 109.34.54.76
152 151 */
153 152
154 153 const char *
155 154 _strip_quotes(char *ipaddress)
156 155 {
157 156 char *cp = (char *)NULL;
158 157
159 158 /* look for first " */
160 159 if ((cp = strchr(ipaddress, '"')) == NULL)
161 160 return ((char *)ipaddress);
162 161 ipaddress++;
163 162 /* look for last " */
164 163 if ((cp = strchr(ipaddress, '"')) == NULL)
165 164 return ((char *)ipaddress);
166 165 *cp++ = '\0';
167 166
168 167 return (ipaddress);
169 168 }
170 169
171 170
172 171 /*
173 172 * This is a copy of a routine in libnsl/nss/netdir_inet.c. It is
174 173 * here because /etc/lib/nss_ldap.so.1 cannot call routines in
175 174 * libnsl. Care should be taken to keep the two copies in sync.
176 175 */
177 176
178 177 int
179 178 __nss2herrno(nss_status_t nsstat)
180 179 {
181 180 switch (nsstat) {
182 181 case NSS_SUCCESS:
183 182 return (0);
184 183 case NSS_NOTFOUND:
185 184 return (HOST_NOT_FOUND);
186 185 case NSS_TRYAGAIN:
187 186 return (TRY_AGAIN);
188 187 case NSS_UNAVAIL:
189 188 default: /* keep gcc happy */
190 189 return (NO_RECOVERY);
191 190 }
192 191 /* NOTREACHED */
193 192 }
194 193
195 194 /*
196 195 * This is a generic filter call back function for
197 196 * merging the filter from service search descriptor with
198 197 * an existing search filter. This routine expects userdata
199 198 * contain a format string with a single %s in it, and will
200 199 * use the format string with sprintf() to insert the SSD filter.
201 200 *
202 201 * This routine is passed to the __ns_ldap_list() or
203 202 * __ns_ldap_firstEntry() APIs as the filter call back
204 203 * together with the userdata. For example,
205 204 * the gethostbyname processing may call __ns_ldap_list() with
206 205 * "(&(objectClass=ipHost)(cn=sys1))" as filter, this function
207 206 * as the filter call back, and "(&(%s)(cn=sys1))" as the
|
↓ open down ↓ |
169 lines elided |
↑ open up ↑ |
208 207 * userdata, this routine will in turn gets call to produce
209 208 * "(&(department=sds)(cn=sys1))" as the real search
210 209 * filter, if the input SSD contains a filter "department=sds".
211 210 */
212 211 int
213 212 _merge_SSD_filter(const ns_ldap_search_desc_t *desc,
214 213 char **realfilter,
215 214 const void *userdata)
216 215 {
217 216 int len;
217 + char *checker;
218 218
219 219 #ifdef DEBUG
220 220 (void) fprintf(stdout, "\n[ldap_utils.c: _merge_SSD_filter]\n");
221 221 #endif /* DEBUG */
222 222
223 223 /* sanity check */
224 224 if (realfilter == NULL)
225 225 return (NS_LDAP_INVALID_PARAM);
226 226 *realfilter = NULL;
227 227
228 - if (desc == NULL || desc->filter == NULL ||
229 - userdata == NULL)
228 + if (desc == NULL || desc->filter == NULL || userdata == NULL)
230 229 return (NS_LDAP_INVALID_PARAM);
231 230
231 + /* Parameter check. We only want one %s here, otherwise bail. */
232 + len = 0; /* Reuse 'len' as "Number of %s hits"... */
233 + checker = (char *)userdata;
234 + do {
235 + checker = strchr(checker, '%');
236 + if (checker != NULL) {
237 + if (len > 0 || *(checker + 1) != 's')
238 + return (NS_LDAP_INVALID_PARAM);
239 + len++; /* Got our %s. */
240 + checker += 2;
241 + } else if (len != 1)
242 + return (NS_LDAP_INVALID_PARAM);
243 + } while (checker != NULL);
244 +
232 245 #ifdef DEBUG
233 246 (void) fprintf(stdout, "\n[userdata: %s]\n", (char *)userdata);
234 247 (void) fprintf(stdout, "\n[SSD filter: %s]\n", desc->filter);
235 248 #endif /* DEBUG */
236 249
237 250 len = strlen(userdata) + strlen(desc->filter) + 1;
238 251
239 252 *realfilter = (char *)malloc(len);
240 253 if (*realfilter == NULL)
241 254 return (NS_LDAP_MEMORY);
242 255
243 - (void) sprintf(*realfilter, (char *)userdata,
244 - desc->filter);
256 + (void) sprintf(*realfilter, (char *)userdata, desc->filter);
245 257
246 258 #ifdef DEBUG
247 259 (void) fprintf(stdout, "\n[new filter: %s]\n", *realfilter);
248 260 #endif /* DEBUG */
249 261
250 262 return (NS_LDAP_SUCCESS);
251 263 }
252 264
253 265 static char
254 266 hex_char(int n)
255 267 {
256 268 return ("0123456789abcdef"[n & 0xf]);
257 269 }
258 270
259 271 int
260 272 _ldap_filter_name(char *filter_name, const char *name, int filter_name_size)
261 273 {
262 274 char *end = filter_name + filter_name_size;
263 275 char c;
264 276
265 277 for (; *name; name++) {
266 278 c = *name;
267 279 switch (c) {
268 280 case '*':
269 281 case '(':
270 282 case ')':
271 283 case '\\':
272 284 if (end <= filter_name + 3)
273 285 return (-1);
274 286 *filter_name++ = '\\';
275 287 *filter_name++ = hex_char(c >> 4);
276 288 *filter_name++ = hex_char(c & 0xf);
277 289 break;
278 290 default:
279 291 if (end <= filter_name + 1)
280 292 return (-1);
281 293 *filter_name++ = c;
282 294 break;
283 295 }
284 296 }
285 297 if (end <= filter_name)
286 298 return (-1);
287 299 *filter_name = '\0';
288 300 return (0);
289 301 }
|
↓ open down ↓ |
35 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX