2 * Copyright (c) 2001-2004 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
25 #include <CoreFoundation/CoreFoundation.h>
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>
34 #include "remoteconf.h"
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
);
51 //----------------------------------------------------------------------
52 // open_dir_authorize_id
53 //----------------------------------------------------------------------
54 int open_dir_authorize_id(vchar_t
*id
, vchar_t
*group
)
58 tDirStatus dsResult
= eDSNoErr
;
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
;
67 if (id
== 0 || id
->l
< 1) {
68 plog(LLV_ERROR
, LOCATION
, NULL
, "invalid user name.\n");
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");
76 bcopy(id
->v
, user_name
, id
->l
);
77 *(user_name
+ id
->l
) = 0;
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");
85 bcopy(group
->v
, group_name
, group
->l
);
86 *(group_name
+ group
->l
) = 0;
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
);
102 authorized
= 1; // no group required - user record found
106 dsDeallocAttributeValueEntry(dirRef
, groupID
);
108 dsDeallocAttributeValueEntry(dirRef
, recordName
);
109 dsCloseDirNode(searchNodeRef
); // close the search node
111 dsCloseDirService(dirRef
);
116 plog(LLV_NOTIFY
, LOCATION
, NULL
, "User '%s' authorized for access\n", user_name
);
118 plog(LLV_NOTIFY
, LOCATION
, NULL
, "User '%s' not authorized for access\n", user_name
);
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
)
133 tDirStatus dsResult
= -1;
134 tDataBufferPtr searchNodeDataBufferPtr
= 0;
135 tDataListPtr searchNodeNameDataListPtr
= 0;
137 unsigned long outNodeCount
;
138 tContextData continueData
= 0;
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");
148 if ((searchNodeNameDataListPtr
= dsDataListAllocate(dirRef
)) == 0) {
149 plog(LLV_ERROR
, LOCATION
, NULL
, "Could not allocate tDataList\n");
153 // find authentication search node(s)
154 if ((dsResult
= dsFindDirNodes(dirRef
, searchNodeDataBufferPtr
, 0, eDSAuthenticationSearchNodeName
,
155 &outNodeCount
, &continueData
)) == eDSNoErr
) {
156 if (outNodeCount
!= 0) {
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
;
167 dsReleaseContinueData(dirRef
, continueData
);
171 if (searchNodeDataBufferPtr
)
172 dsDataBufferDeAllocate(dirRef
, searchNodeDataBufferPtr
);
173 if (searchNodeNameDataListPtr
)
174 dsDataListDeallocate(dirRef
, searchNodeNameDataListPtr
);
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
)
186 tDirStatus dsResult
= -1;
188 tDataBufferPtr userRcdDataBufferPtr
= 0;
189 tDataListPtr recordNameDataListPtr
= 0;
190 tDataListPtr recordTypeDataListPtr
= 0;
191 tDataListPtr attrTypeDataListPtr
= 0;
192 tContextData continueData
= 0;
194 unsigned long outRecordCount
;
195 int userRcdFound
= 0;
196 u_int32_t userRecordIndex
, attrIndex
;
200 if ((userRcdDataBufferPtr
= dsDataBufferAllocate(dirRef
, BUF_LEN
)) == 0) {
201 plog(LLV_ERROR
, LOCATION
, NULL
, "Could not allocate tDataBuffer\n");
204 if ((recordNameDataListPtr
= dsBuildListFromStrings(dirRef
, user_name
, 0)) == 0) {
205 plog(LLV_ERROR
, LOCATION
, NULL
, "Could not allocate tDataList\n");
208 if ((recordTypeDataListPtr
= dsBuildListFromStrings(dirRef
, kDSStdRecordTypeUsers
, 0)) == 0) {
209 plog(LLV_ERROR
, LOCATION
, NULL
, "Could not allocate tDataList\n");
212 if ((attrTypeDataListPtr
= dsBuildListFromStrings(dirRef
, kDSNAttrRecordName
, kDS1AttrDistinguishedName
, attr
, 0)) == 0) {
213 plog(LLV_ERROR
, LOCATION
, NULL
, "Could not allocate tDataList\n");
217 // find the user record(s), extracting the user name and requested attribute
219 dsResult
= dsGetRecordList(searchNodeRef
, userRcdDataBufferPtr
, recordNameDataListPtr
, eDSExact
,
220 recordTypeDataListPtr
, attrTypeDataListPtr
, 0, &outRecordCount
, &continueData
);
222 // if buffer too small - allocate a larger one
223 if (dsResult
== eDSBufferTooSmall
) {
224 u_int32_t size
= userRcdDataBufferPtr
->fBufferSize
* 2;
226 dsDataBufferDeAllocate(dirRef
, userRcdDataBufferPtr
);
227 if ((userRcdDataBufferPtr
= dsDataBufferAllocate(dirRef
, size
)) == 0) {
228 plog(LLV_ERROR
, LOCATION
, NULL
, "Could not allocate tDataBuffer\n");
233 } while (dsResult
== eDSBufferTooSmall
);
235 if (dsResult
== eDSNoErr
) {
236 // for each user record
237 for (userRecordIndex
= 1; (userRecordIndex
<= outRecordCount
) && (dsResult
== eDSNoErr
)
238 && (userRcdFound
== 0); userRecordIndex
++) {
240 tAttributeListRef attrListRef
;
241 tRecordEntryPtr userRcdEntryPtr
;
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
++) {
250 tAttributeValueListRef attrValueListRef
;
251 tAttributeEntryPtr attrInfoPtr
;
252 tAttributeValueEntryPtr attrValuePtr
;
254 if ((dsResult
= dsGetAttributeEntry(searchNodeRef
, userRcdDataBufferPtr
,
255 attrListRef
, attrIndex
, &attrValueListRef
, &attrInfoPtr
)) == eDSNoErr
) {
256 if ((dsResult
= dsGetAttributeValue(searchNodeRef
, userRcdDataBufferPtr
, 1,
257 attrValueListRef
, &attrValuePtr
)) == eDSNoErr
) {
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
))
264 if (!strcmp(attrInfoPtr
->fAttributeSignature
.fBufferData
, kDS1AttrDistinguishedName
)) {
265 if (!strcmp(attrValuePtr
->fAttributeValueData
.fBufferData
, user_name
))
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
273 dsDeallocAttributeValueEntry(dirRef
, attrValuePtr
);
275 dsCloseAttributeValueList(attrValueListRef
);
276 dsDeallocAttributeEntry(dirRef
, attrInfoPtr
);
279 // make sure we've processed both attributes and we have a match on user name
280 if(userRcdFound
== 0 || *attr_value
== 0) {
283 dsDeallocAttributeValueEntry(dirRef
, *attr_value
);
286 dsCloseAttributeList(attrListRef
);
287 dsDeallocRecordEntry(dirRef
, userRcdEntryPtr
);
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
);
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
)
315 tDirStatus dsResult
= -1;
317 tDataBufferPtr groupRcdDataBufferPtr
= 0;
318 tDataListPtr recordNameDataListPtr
= 0;
319 tDataListPtr recordTypeDataListPtr
= 0;
320 tDataListPtr attrTypeDataListPtr
= 0;
321 tContextData continueData
= 0;
323 unsigned long outRecordCount
;
324 u_int32_t attrIndex
, valueIndex
;
328 if ((groupRcdDataBufferPtr
= dsDataBufferAllocate(dirRef
, BUF_LEN
)) == 0) {
329 plog(LLV_ERROR
, LOCATION
, NULL
, "Could not allocate tDataBuffer\n");
332 if ((recordNameDataListPtr
= dsBuildListFromStrings(dirRef
, group_name
, 0)) == 0) {
333 plog(LLV_ERROR
, LOCATION
, NULL
, "Could not allocate tDataList\n");
336 if ((recordTypeDataListPtr
= dsBuildListFromStrings(dirRef
, kDSStdRecordTypeGroups
, 0)) == 0) {
337 plog(LLV_ERROR
, LOCATION
, NULL
, "Could not allocate tDataList\n");
340 if ((attrTypeDataListPtr
= dsBuildListFromStrings(dirRef
, kDS1AttrPrimaryGroupID
, kDSNAttrGroupMembership
, 0)) == 0) {
341 plog(LLV_ERROR
, LOCATION
, NULL
, "Could not allocate tDataList\n");
345 // find the group record, extracting the group ID and group membership attribute
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;
353 dsDataBufferDeAllocate(dirRef
, groupRcdDataBufferPtr
);
354 if ((groupRcdDataBufferPtr
= dsDataBufferAllocate(dirRef
, size
)) == 0) {
355 plog(LLV_ERROR
, LOCATION
, NULL
, "Could not allocate tDataBuffer\n");
360 } while (dsResult
== eDSBufferTooSmall
);
362 if (dsResult
== eDSNoErr
) {
364 tAttributeListRef attrListRef
;
365 tRecordEntryPtr groupRcdEntryPtr
;
367 // get the group record entry
368 if ((dsResult
= dsGetRecordEntry(searchNodeRef
, groupRcdDataBufferPtr
, 1, &attrListRef
, &groupRcdEntryPtr
)) == eDSNoErr
) {
370 // for each attribute
371 for (attrIndex
= 1; (attrIndex
<= groupRcdEntryPtr
->fRecordAttributeCount
) && (dsResult
== eDSNoErr
)
372 && (*authorized
== 0); attrIndex
++) {
374 tAttributeValueListRef attrValueListRef
;
375 tAttributeEntryPtr attrInfoPtr
;
376 tAttributeValueEntryPtr attrValuePtr
;
378 if ((dsResult
= dsGetAttributeEntry(searchNodeRef
, groupRcdDataBufferPtr
, attrListRef
,
379 attrIndex
, &attrValueListRef
, &attrInfoPtr
)) == eDSNoErr
) {
381 // group ID attribute ?
382 if (!strcmp(attrInfoPtr
->fAttributeSignature
.fBufferData
, kDS1AttrPrimaryGroupID
)) {
383 if ((dsResult
= dsGetAttributeValue(searchNodeRef
, groupRcdDataBufferPtr
, 1,
384 attrValueListRef
, &attrValuePtr
)) == eDSNoErr
) {
386 // check for match on primary group ID
387 if (!strcmp(attrValuePtr
->fAttributeValueData
.fBufferData
, userGID
))
389 dsDeallocAttributeValueEntry(dirRef
, attrValuePtr
);
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
++) {
396 if ((dsResult
= dsGetAttributeValue(searchNodeRef
, groupRcdDataBufferPtr
,
397 valueIndex
, attrValueListRef
, &attrValuePtr
)) == eDSNoErr
) {
398 if (!strcmp(attrValuePtr
->fAttributeValueData
.fBufferData
, user_name
))
400 dsDeallocAttributeValueEntry(dirRef
, attrValuePtr
);
404 dsCloseAttributeValueList(attrValueListRef
);
405 dsDeallocAttributeEntry(dirRef
, attrInfoPtr
);
408 dsCloseAttributeList(attrListRef
);
409 dsDeallocRecordEntry(dirRef
, groupRcdEntryPtr
);
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
);