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