]> git.saurik.com Git - apple/ipsec.git/blob - ipsec-tools/racoon/open_dir.c
ipsec-34.0.1.tar.gz
[apple/ipsec.git] / ipsec-tools / racoon / open_dir.c
1 /*
2 * Copyright (c) 2001-2004 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
11 *
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
18 * under the License.
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22
23
24 #include <CoreFoundation/CoreFoundation.h>
25
26 #include <DirectoryService/DirServices.h>
27 #include <DirectoryService/DirServicesUtils.h>
28 #include <DirectoryService/DirServicesConst.h>
29 #include <CoreFoundation/CFString.h>
30 #include <SystemConfiguration/SystemConfiguration.h>
31
32 #include "vmbuf.h"
33 #include "remoteconf.h"
34 #include "plog.h"
35 #include "misc.h"
36 #include "gcmalloc.h"
37 #include "open_dir.h"
38
39 #define BUF_LEN 1024
40
41
42 static tDirStatus open_dir_get_search_node_ref(tDirReference dirRef, unsigned long index,
43 tDirNodeReference *searchNodeRef, unsigned long *count);
44 static tDirStatus open_dir_get_user_attr(tDirReference dirRef, tDirNodeReference searchNodeRef, char *user_name,
45 char *attr, tAttributeValueEntryPtr *attr_value);
46 static tDirStatus open_dir_check_group_membership(tDirReference dirRef, tDirNodeReference searchNodeRef,
47 char *group_name, char *user_name, char *userGID, int *authorized);
48
49
50 //----------------------------------------------------------------------
51 // open_dir_authorize_id
52 //----------------------------------------------------------------------
53 int open_dir_authorize_id(vchar_t *id, vchar_t *group)
54 {
55
56 tDirReference dirRef;
57 tDirStatus dsResult = eDSNoErr;
58 int authorized = 0;
59 tDirNodeReference searchNodeRef;
60 tAttributeValueEntryPtr groupID = NULL;
61 tAttributeValueEntryPtr recordName = NULL;
62 unsigned long searchNodeCount;
63 char* user_name = NULL;
64 char* group_name = NULL;
65
66 if (id == 0 || id->l < 1) {
67 plog(LLV_ERROR, LOCATION, NULL, "invalid user name.\n");
68 goto end;
69 }
70 user_name = racoon_malloc(id->l + 1);
71 if (user_name == NULL) {
72 plog(LLV_ERROR, LOCATION, NULL, "out of memory - unable to allocate space for user name.\n");
73 goto end;
74 }
75 bcopy(id->v, user_name, id->l);
76 *(user_name + id->l) = 0;
77
78 if (group && group->l > 0) {
79 group_name = racoon_malloc(group->l + 1);
80 if (group_name == NULL) {
81 plog(LLV_NOTIFY, LOCATION, NULL, "out of memeory - unable to allocate space for group name.\n");
82 goto end;
83 }
84 bcopy(group->v, group_name, group->l);
85 *(group_name + group->l) = 0;
86 }
87
88 if ((dsResult = dsOpenDirService(&dirRef)) == eDSNoErr) {
89 // get the search node ref
90 if ((dsResult = open_dir_get_search_node_ref(dirRef, 1, &searchNodeRef, &searchNodeCount)) == eDSNoErr) {
91 // get the user's primary group ID
92 if (dsResult = open_dir_get_user_attr(dirRef, searchNodeRef, user_name, kDSNAttrRecordName, &recordName) == eDSNoErr) {
93 if (recordName != 0) {
94 if (group_name != 0) {
95 if ((dsResult = open_dir_get_user_attr(dirRef, searchNodeRef, user_name, kDS1AttrPrimaryGroupID, &groupID)) == eDSNoErr) {
96 // check if user is member of the group
97 dsResult = open_dir_check_group_membership(dirRef, searchNodeRef, group_name,
98 recordName->fAttributeValueData.fBufferData, groupID->fAttributeValueData.fBufferData, &authorized);
99 }
100 } else
101 authorized = 1; // no group required - user record found
102 }
103 }
104 if (groupID)
105 dsDeallocAttributeValueEntry(dirRef, groupID);
106 if (recordName)
107 dsDeallocAttributeValueEntry(dirRef, recordName);
108 dsCloseDirNode(searchNodeRef); // close the search node
109 }
110 dsCloseDirService(dirRef);
111 }
112
113 end:
114 if (authorized)
115 plog(LLV_NOTIFY, LOCATION, NULL, "User '%s' authorized for access\n", user_name);
116 else
117 plog(LLV_NOTIFY, LOCATION, NULL, "User '%s' not authorized for access\n", user_name);
118 if (user_name)
119 free(user_name);
120 if (group_name)
121 free(group_name);
122 return authorized;
123 }
124
125
126 //----------------------------------------------------------------------
127 // open_dir_get_search_node_ref
128 //----------------------------------------------------------------------
129 static tDirStatus open_dir_get_search_node_ref(tDirReference dirRef, unsigned long index,
130 tDirNodeReference *searchNodeRef, unsigned long *count)
131 {
132 tDirStatus dsResult = -1;
133 tDataBufferPtr searchNodeDataBufferPtr = 0;
134 tDataListPtr searchNodeNameDataListPtr = 0;
135
136 unsigned long outNodeCount;
137 tContextData continueData = 0;
138
139 *searchNodeRef = 0;
140 *count = 0;
141
142 // allocate required buffers and data lists
143 if ((searchNodeDataBufferPtr = dsDataBufferAllocate(dirRef, BUF_LEN)) == 0) {
144 plog(LLV_ERROR, LOCATION, NULL, "Could not allocate tDataBuffer\n");
145 goto cleanup;
146 }
147 if ((searchNodeNameDataListPtr = dsDataListAllocate(dirRef)) == 0) {
148 plog(LLV_ERROR, LOCATION, NULL, "Could not allocate tDataList\n");
149 goto cleanup;
150 }
151
152 // find authentication search node(s)
153 if ((dsResult = dsFindDirNodes(dirRef, searchNodeDataBufferPtr, 0, eDSAuthenticationSearchNodeName,
154 &outNodeCount, &continueData)) == eDSNoErr) {
155 if (outNodeCount != 0) {
156
157 // get the seach node name and open the node
158 if ((dsResult = dsGetDirNodeName(dirRef, searchNodeDataBufferPtr, index,
159 &searchNodeNameDataListPtr)) == eDSNoErr) {
160 if ((dsResult = dsOpenDirNode(dirRef, searchNodeNameDataListPtr, searchNodeRef)) == eDSNoErr) {
161 *count = outNodeCount;
162 }
163 }
164 }
165 if (continueData)
166 dsReleaseContinueData(dirRef, continueData);
167 }
168
169 cleanup:
170 if (searchNodeDataBufferPtr)
171 dsDataBufferDeAllocate(dirRef, searchNodeDataBufferPtr);
172 if (searchNodeNameDataListPtr)
173 dsDataListDeallocate(dirRef, searchNodeNameDataListPtr);
174
175 return dsResult;
176 }
177
178 //----------------------------------------------------------------------
179 // open_dir_get_user_attr
180 //----------------------------------------------------------------------
181 static tDirStatus open_dir_get_user_attr(tDirReference dirRef, tDirNodeReference searchNodeRef, char *user_name,
182 char *attr, tAttributeValueEntryPtr *attr_value)
183 {
184
185 tDirStatus dsResult = -1;
186
187 tDataBufferPtr userRcdDataBufferPtr = 0;
188 tDataListPtr recordNameDataListPtr = 0;
189 tDataListPtr recordTypeDataListPtr = 0;
190 tDataListPtr attrTypeDataListPtr = 0;
191 tContextData continueData = 0;
192
193 unsigned long outRecordCount;
194 int userRcdFound = 0;
195 u_int32_t userRecordIndex, attrIndex;
196
197 *attr_value = 0;
198
199 if ((userRcdDataBufferPtr = dsDataBufferAllocate(dirRef, BUF_LEN)) == 0) {
200 plog(LLV_ERROR, LOCATION, NULL, "Could not allocate tDataBuffer\n");
201 goto cleanup;
202 }
203 if ((recordNameDataListPtr = dsBuildListFromStrings(dirRef, user_name, 0)) == 0) {
204 plog(LLV_ERROR, LOCATION, NULL, "Could not allocate tDataList\n");
205 goto cleanup;
206 }
207 if ((recordTypeDataListPtr = dsBuildListFromStrings(dirRef, kDSStdRecordTypeUsers, 0)) == 0) {
208 plog(LLV_ERROR, LOCATION, NULL, "Could not allocate tDataList\n");
209 goto cleanup;
210 }
211 if ((attrTypeDataListPtr = dsBuildListFromStrings(dirRef, kDSNAttrRecordName, kDS1AttrDistinguishedName, attr, 0)) == 0) {
212 plog(LLV_ERROR, LOCATION, NULL, "Could not allocate tDataList\n");
213 goto cleanup;
214 }
215
216 // find the user record(s), extracting the user name and requested attribute
217 do {
218 dsResult = dsGetRecordList(searchNodeRef, userRcdDataBufferPtr, recordNameDataListPtr, eDSExact,
219 recordTypeDataListPtr, attrTypeDataListPtr, 0, &outRecordCount, &continueData);
220
221 // if buffer too small - allocate a larger one
222 if (dsResult == eDSBufferTooSmall) {
223 u_int32_t size = userRcdDataBufferPtr->fBufferSize * 2;
224
225 dsDataBufferDeAllocate(dirRef, userRcdDataBufferPtr);
226 if ((userRcdDataBufferPtr = dsDataBufferAllocate(dirRef, size)) == 0) {
227 plog(LLV_ERROR, LOCATION, NULL, "Could not allocate tDataBuffer\n");
228 dsResult = -1;
229 goto cleanup;
230 }
231 }
232 } while (dsResult == eDSBufferTooSmall);
233
234 if (dsResult == eDSNoErr) {
235 // for each user record
236 for (userRecordIndex = 1; (userRecordIndex <= outRecordCount) && (dsResult == eDSNoErr)
237 && (userRcdFound == 0); userRecordIndex++) {
238
239 tAttributeListRef attrListRef;
240 tRecordEntryPtr userRcdEntryPtr;
241
242 // get the user record entry from the data buffer
243 if ((dsResult = dsGetRecordEntry(searchNodeRef, userRcdDataBufferPtr, userRecordIndex,
244 &attrListRef, &userRcdEntryPtr)) == eDSNoErr) {
245 // for each attribute
246 for (attrIndex = 1; (attrIndex <= userRcdEntryPtr->fRecordAttributeCount)
247 && (dsResult == eDSNoErr); attrIndex++) {
248
249 tAttributeValueListRef attrValueListRef;
250 tAttributeEntryPtr attrInfoPtr;
251 tAttributeValueEntryPtr attrValuePtr;
252
253 if ((dsResult = dsGetAttributeEntry(searchNodeRef, userRcdDataBufferPtr,
254 attrListRef, attrIndex, &attrValueListRef, &attrInfoPtr)) == eDSNoErr) {
255 if ((dsResult = dsGetAttributeValue(searchNodeRef, userRcdDataBufferPtr, 1,
256 attrValueListRef, &attrValuePtr)) == eDSNoErr) {
257
258 // check for user record name or attribute searching for
259 if (!strcmp(attrInfoPtr->fAttributeSignature.fBufferData, kDSNAttrRecordName)) {
260 if (!strcmp(attrValuePtr->fAttributeValueData.fBufferData, user_name))
261 userRcdFound = 1;
262 }
263 if (!strcmp(attrInfoPtr->fAttributeSignature.fBufferData, kDS1AttrDistinguishedName)) {
264 if (!strcmp(attrValuePtr->fAttributeValueData.fBufferData, user_name))
265 userRcdFound = 1;
266 }
267 if (!strcmp(attrInfoPtr->fAttributeSignature.fBufferData, attr)) {
268 *attr_value = attrValuePtr; // return the attribute value
269 attrValuePtr = 0; // set to zero so we don't deallocate it
270 }
271 if (attrValuePtr)
272 dsDeallocAttributeValueEntry(dirRef, attrValuePtr);
273 }
274 dsCloseAttributeValueList(attrValueListRef);
275 dsDeallocAttributeEntry(dirRef, attrInfoPtr);
276 }
277 }
278 // make sure we've processed both attributes and we have a match on user name
279 if(userRcdFound == 0 || *attr_value == 0) {
280 userRcdFound = 0;
281 if (*attr_value)
282 dsDeallocAttributeValueEntry(dirRef, *attr_value);
283 *attr_value = 0;
284 }
285 dsCloseAttributeList(attrListRef);
286 dsDeallocRecordEntry(dirRef, userRcdEntryPtr);
287 }
288 }
289 }
290
291 cleanup:
292 if (continueData)
293 dsReleaseContinueData(searchNodeRef, continueData);
294 if (userRcdDataBufferPtr)
295 dsDataBufferDeAllocate(dirRef, userRcdDataBufferPtr);
296 if (recordNameDataListPtr)
297 dsDataListDeallocate(dirRef, recordNameDataListPtr);
298 if (recordTypeDataListPtr)
299 dsDataListDeallocate(dirRef, recordTypeDataListPtr);
300 if (attrTypeDataListPtr)
301 dsDataListDeallocate(dirRef, attrTypeDataListPtr);
302
303 return dsResult;
304
305 }
306
307
308 //----------------------------------------------------------------------
309 // open_dir_check_group_membership
310 //----------------------------------------------------------------------
311 static tDirStatus open_dir_check_group_membership(tDirReference dirRef, tDirNodeReference searchNodeRef,
312 char *group_name, char *user_name, char *userGID, int *authorized)
313 {
314 tDirStatus dsResult = -1;
315
316 tDataBufferPtr groupRcdDataBufferPtr = 0;
317 tDataListPtr recordNameDataListPtr = 0;
318 tDataListPtr recordTypeDataListPtr = 0;
319 tDataListPtr attrTypeDataListPtr = 0;
320 tContextData continueData = 0;
321
322 unsigned long outRecordCount;
323 u_int32_t attrIndex, valueIndex;
324
325 *authorized = 0;
326
327 if ((groupRcdDataBufferPtr = dsDataBufferAllocate(dirRef, BUF_LEN)) == 0) {
328 plog(LLV_ERROR, LOCATION, NULL, "Could not allocate tDataBuffer\n");
329 goto cleanup;
330 }
331 if ((recordNameDataListPtr = dsBuildListFromStrings(dirRef, group_name, 0)) == 0) {
332 plog(LLV_ERROR, LOCATION, NULL, "Could not allocate tDataList\n");
333 goto cleanup;
334 }
335 if ((recordTypeDataListPtr = dsBuildListFromStrings(dirRef, kDSStdRecordTypeGroups, 0)) == 0) {
336 plog(LLV_ERROR, LOCATION, NULL, "Could not allocate tDataList\n");
337 goto cleanup;
338 }
339 if ((attrTypeDataListPtr = dsBuildListFromStrings(dirRef, kDS1AttrPrimaryGroupID, kDSNAttrGroupMembership, 0)) == 0) {
340 plog(LLV_ERROR, LOCATION, NULL, "Could not allocate tDataList\n");
341 goto cleanup;
342 }
343
344 // find the group record, extracting the group ID and group membership attribute
345 do {
346 dsResult = dsGetRecordList(searchNodeRef, groupRcdDataBufferPtr, recordNameDataListPtr, eDSExact,
347 recordTypeDataListPtr, attrTypeDataListPtr, 0, &outRecordCount, &continueData);
348 // if buffer too small - allocate a larger one
349 if (dsResult == eDSBufferTooSmall) {
350 u_int32_t size = groupRcdDataBufferPtr->fBufferSize * 2;
351
352 dsDataBufferDeAllocate(dirRef, groupRcdDataBufferPtr);
353 if ((groupRcdDataBufferPtr = dsDataBufferAllocate(dirRef, size)) == 0) {
354 plog(LLV_ERROR, LOCATION, NULL, "Could not allocate tDataBuffer\n");
355 dsResult = -1;
356 goto cleanup;
357 }
358 }
359 } while (dsResult == eDSBufferTooSmall);
360
361 if (dsResult == eDSNoErr) {
362
363 tAttributeListRef attrListRef;
364 tRecordEntryPtr groupRcdEntryPtr;
365
366 // get the group record entry
367 if ((dsResult = dsGetRecordEntry(searchNodeRef, groupRcdDataBufferPtr, 1, &attrListRef, &groupRcdEntryPtr)) == eDSNoErr) {
368
369 // for each attribute
370 for (attrIndex = 1; (attrIndex <= groupRcdEntryPtr->fRecordAttributeCount) && (dsResult == eDSNoErr)
371 && (*authorized == 0); attrIndex++) {
372
373 tAttributeValueListRef attrValueListRef;
374 tAttributeEntryPtr attrInfoPtr;
375 tAttributeValueEntryPtr attrValuePtr;
376
377 if ((dsResult = dsGetAttributeEntry(searchNodeRef, groupRcdDataBufferPtr, attrListRef,
378 attrIndex, &attrValueListRef, &attrInfoPtr)) == eDSNoErr) {
379
380 // group ID attribute ?
381 if (!strcmp(attrInfoPtr->fAttributeSignature.fBufferData, kDS1AttrPrimaryGroupID)) {
382 if ((dsResult = dsGetAttributeValue(searchNodeRef, groupRcdDataBufferPtr, 1,
383 attrValueListRef, &attrValuePtr)) == eDSNoErr) {
384
385 // check for match on primary group ID
386 if (!strcmp(attrValuePtr->fAttributeValueData.fBufferData, userGID))
387 *authorized = 1;
388 dsDeallocAttributeValueEntry(dirRef, attrValuePtr);
389 }
390 } else if (!strcmp(attrInfoPtr->fAttributeSignature.fBufferData, kDSNAttrGroupMembership)) {
391 // for each value check for user's name in the group
392 for (valueIndex = 1; (valueIndex <= attrInfoPtr->fAttributeValueCount)
393 && (dsResult == eDSNoErr) && (*authorized == 0); valueIndex++) {
394
395 if ((dsResult = dsGetAttributeValue(searchNodeRef, groupRcdDataBufferPtr,
396 valueIndex, attrValueListRef, &attrValuePtr)) == eDSNoErr) {
397 if (!strcmp(attrValuePtr->fAttributeValueData.fBufferData, user_name))
398 *authorized = 1;
399 dsDeallocAttributeValueEntry(dirRef, attrValuePtr);
400 }
401 }
402 }
403 dsCloseAttributeValueList(attrValueListRef);
404 dsDeallocAttributeEntry(dirRef, attrInfoPtr);
405 }
406 }
407 dsCloseAttributeList(attrListRef);
408 dsDeallocRecordEntry(dirRef, groupRcdEntryPtr);
409 }
410 }
411
412 cleanup:
413 if (continueData)
414 dsReleaseContinueData(searchNodeRef, continueData);
415 if (groupRcdDataBufferPtr)
416 dsDataBufferDeAllocate(dirRef, groupRcdDataBufferPtr);
417 if (recordNameDataListPtr)
418 dsDataListDeallocate(dirRef, recordNameDataListPtr);
419 if (recordTypeDataListPtr)
420 dsDataListDeallocate(dirRef, recordTypeDataListPtr);
421 if (attrTypeDataListPtr)
422 dsDataListDeallocate(dirRef, attrTypeDataListPtr);
423
424 return dsResult;
425 }
426