2 * Copyright (c) 2001-2004 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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.
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
20 * @APPLE_LICENSE_HEADER_END@
24 #include <CoreFoundation/CoreFoundation.h>
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>
33 #include "remoteconf.h"
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
);
50 //----------------------------------------------------------------------
51 // open_dir_authorize_id
52 //----------------------------------------------------------------------
53 int open_dir_authorize_id(vchar_t
*id
, vchar_t
*group
)
57 tDirStatus dsResult
= eDSNoErr
;
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
;
66 if (id
== 0 || id
->l
< 1) {
67 plog(LLV_ERROR
, LOCATION
, NULL
, "invalid user name.\n");
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");
75 bcopy(id
->v
, user_name
, id
->l
);
76 *(user_name
+ id
->l
) = 0;
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");
84 bcopy(group
->v
, group_name
, group
->l
);
85 *(group_name
+ group
->l
) = 0;
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
);
101 authorized
= 1; // no group required - user record found
105 dsDeallocAttributeValueEntry(dirRef
, groupID
);
107 dsDeallocAttributeValueEntry(dirRef
, recordName
);
108 dsCloseDirNode(searchNodeRef
); // close the search node
110 dsCloseDirService(dirRef
);
115 plog(LLV_NOTIFY
, LOCATION
, NULL
, "User '%s' authorized for access\n", user_name
);
117 plog(LLV_NOTIFY
, LOCATION
, NULL
, "User '%s' not authorized for access\n", user_name
);
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
)
132 tDirStatus dsResult
= -1;
133 tDataBufferPtr searchNodeDataBufferPtr
= 0;
134 tDataListPtr searchNodeNameDataListPtr
= 0;
136 unsigned long outNodeCount
;
137 tContextData continueData
= 0;
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");
147 if ((searchNodeNameDataListPtr
= dsDataListAllocate(dirRef
)) == 0) {
148 plog(LLV_ERROR
, LOCATION
, NULL
, "Could not allocate tDataList\n");
152 // find authentication search node(s)
153 if ((dsResult
= dsFindDirNodes(dirRef
, searchNodeDataBufferPtr
, 0, eDSAuthenticationSearchNodeName
,
154 &outNodeCount
, &continueData
)) == eDSNoErr
) {
155 if (outNodeCount
!= 0) {
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
;
166 dsReleaseContinueData(dirRef
, continueData
);
170 if (searchNodeDataBufferPtr
)
171 dsDataBufferDeAllocate(dirRef
, searchNodeDataBufferPtr
);
172 if (searchNodeNameDataListPtr
)
173 dsDataListDeallocate(dirRef
, searchNodeNameDataListPtr
);
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
)
185 tDirStatus dsResult
= -1;
187 tDataBufferPtr userRcdDataBufferPtr
= 0;
188 tDataListPtr recordNameDataListPtr
= 0;
189 tDataListPtr recordTypeDataListPtr
= 0;
190 tDataListPtr attrTypeDataListPtr
= 0;
191 tContextData continueData
= 0;
193 unsigned long outRecordCount
;
194 int userRcdFound
= 0;
195 u_int32_t userRecordIndex
, attrIndex
;
199 if ((userRcdDataBufferPtr
= dsDataBufferAllocate(dirRef
, BUF_LEN
)) == 0) {
200 plog(LLV_ERROR
, LOCATION
, NULL
, "Could not allocate tDataBuffer\n");
203 if ((recordNameDataListPtr
= dsBuildListFromStrings(dirRef
, user_name
, 0)) == 0) {
204 plog(LLV_ERROR
, LOCATION
, NULL
, "Could not allocate tDataList\n");
207 if ((recordTypeDataListPtr
= dsBuildListFromStrings(dirRef
, kDSStdRecordTypeUsers
, 0)) == 0) {
208 plog(LLV_ERROR
, LOCATION
, NULL
, "Could not allocate tDataList\n");
211 if ((attrTypeDataListPtr
= dsBuildListFromStrings(dirRef
, kDSNAttrRecordName
, kDS1AttrDistinguishedName
, attr
, 0)) == 0) {
212 plog(LLV_ERROR
, LOCATION
, NULL
, "Could not allocate tDataList\n");
216 // find the user record(s), extracting the user name and requested attribute
218 dsResult
= dsGetRecordList(searchNodeRef
, userRcdDataBufferPtr
, recordNameDataListPtr
, eDSExact
,
219 recordTypeDataListPtr
, attrTypeDataListPtr
, 0, &outRecordCount
, &continueData
);
221 // if buffer too small - allocate a larger one
222 if (dsResult
== eDSBufferTooSmall
) {
223 u_int32_t size
= userRcdDataBufferPtr
->fBufferSize
* 2;
225 dsDataBufferDeAllocate(dirRef
, userRcdDataBufferPtr
);
226 if ((userRcdDataBufferPtr
= dsDataBufferAllocate(dirRef
, size
)) == 0) {
227 plog(LLV_ERROR
, LOCATION
, NULL
, "Could not allocate tDataBuffer\n");
232 } while (dsResult
== eDSBufferTooSmall
);
234 if (dsResult
== eDSNoErr
) {
235 // for each user record
236 for (userRecordIndex
= 1; (userRecordIndex
<= outRecordCount
) && (dsResult
== eDSNoErr
)
237 && (userRcdFound
== 0); userRecordIndex
++) {
239 tAttributeListRef attrListRef
;
240 tRecordEntryPtr userRcdEntryPtr
;
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
++) {
249 tAttributeValueListRef attrValueListRef
;
250 tAttributeEntryPtr attrInfoPtr
;
251 tAttributeValueEntryPtr attrValuePtr
;
253 if ((dsResult
= dsGetAttributeEntry(searchNodeRef
, userRcdDataBufferPtr
,
254 attrListRef
, attrIndex
, &attrValueListRef
, &attrInfoPtr
)) == eDSNoErr
) {
255 if ((dsResult
= dsGetAttributeValue(searchNodeRef
, userRcdDataBufferPtr
, 1,
256 attrValueListRef
, &attrValuePtr
)) == eDSNoErr
) {
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
))
263 if (!strcmp(attrInfoPtr
->fAttributeSignature
.fBufferData
, kDS1AttrDistinguishedName
)) {
264 if (!strcmp(attrValuePtr
->fAttributeValueData
.fBufferData
, user_name
))
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
272 dsDeallocAttributeValueEntry(dirRef
, attrValuePtr
);
274 dsCloseAttributeValueList(attrValueListRef
);
275 dsDeallocAttributeEntry(dirRef
, attrInfoPtr
);
278 // make sure we've processed both attributes and we have a match on user name
279 if(userRcdFound
== 0 || *attr_value
== 0) {
282 dsDeallocAttributeValueEntry(dirRef
, *attr_value
);
285 dsCloseAttributeList(attrListRef
);
286 dsDeallocRecordEntry(dirRef
, userRcdEntryPtr
);
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
);
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
)
314 tDirStatus dsResult
= -1;
316 tDataBufferPtr groupRcdDataBufferPtr
= 0;
317 tDataListPtr recordNameDataListPtr
= 0;
318 tDataListPtr recordTypeDataListPtr
= 0;
319 tDataListPtr attrTypeDataListPtr
= 0;
320 tContextData continueData
= 0;
322 unsigned long outRecordCount
;
323 u_int32_t attrIndex
, valueIndex
;
327 if ((groupRcdDataBufferPtr
= dsDataBufferAllocate(dirRef
, BUF_LEN
)) == 0) {
328 plog(LLV_ERROR
, LOCATION
, NULL
, "Could not allocate tDataBuffer\n");
331 if ((recordNameDataListPtr
= dsBuildListFromStrings(dirRef
, group_name
, 0)) == 0) {
332 plog(LLV_ERROR
, LOCATION
, NULL
, "Could not allocate tDataList\n");
335 if ((recordTypeDataListPtr
= dsBuildListFromStrings(dirRef
, kDSStdRecordTypeGroups
, 0)) == 0) {
336 plog(LLV_ERROR
, LOCATION
, NULL
, "Could not allocate tDataList\n");
339 if ((attrTypeDataListPtr
= dsBuildListFromStrings(dirRef
, kDS1AttrPrimaryGroupID
, kDSNAttrGroupMembership
, 0)) == 0) {
340 plog(LLV_ERROR
, LOCATION
, NULL
, "Could not allocate tDataList\n");
344 // find the group record, extracting the group ID and group membership attribute
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;
352 dsDataBufferDeAllocate(dirRef
, groupRcdDataBufferPtr
);
353 if ((groupRcdDataBufferPtr
= dsDataBufferAllocate(dirRef
, size
)) == 0) {
354 plog(LLV_ERROR
, LOCATION
, NULL
, "Could not allocate tDataBuffer\n");
359 } while (dsResult
== eDSBufferTooSmall
);
361 if (dsResult
== eDSNoErr
) {
363 tAttributeListRef attrListRef
;
364 tRecordEntryPtr groupRcdEntryPtr
;
366 // get the group record entry
367 if ((dsResult
= dsGetRecordEntry(searchNodeRef
, groupRcdDataBufferPtr
, 1, &attrListRef
, &groupRcdEntryPtr
)) == eDSNoErr
) {
369 // for each attribute
370 for (attrIndex
= 1; (attrIndex
<= groupRcdEntryPtr
->fRecordAttributeCount
) && (dsResult
== eDSNoErr
)
371 && (*authorized
== 0); attrIndex
++) {
373 tAttributeValueListRef attrValueListRef
;
374 tAttributeEntryPtr attrInfoPtr
;
375 tAttributeValueEntryPtr attrValuePtr
;
377 if ((dsResult
= dsGetAttributeEntry(searchNodeRef
, groupRcdDataBufferPtr
, attrListRef
,
378 attrIndex
, &attrValueListRef
, &attrInfoPtr
)) == eDSNoErr
) {
380 // group ID attribute ?
381 if (!strcmp(attrInfoPtr
->fAttributeSignature
.fBufferData
, kDS1AttrPrimaryGroupID
)) {
382 if ((dsResult
= dsGetAttributeValue(searchNodeRef
, groupRcdDataBufferPtr
, 1,
383 attrValueListRef
, &attrValuePtr
)) == eDSNoErr
) {
385 // check for match on primary group ID
386 if (!strcmp(attrValuePtr
->fAttributeValueData
.fBufferData
, userGID
))
388 dsDeallocAttributeValueEntry(dirRef
, attrValuePtr
);
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
++) {
395 if ((dsResult
= dsGetAttributeValue(searchNodeRef
, groupRcdDataBufferPtr
,
396 valueIndex
, attrValueListRef
, &attrValuePtr
)) == eDSNoErr
) {
397 if (!strcmp(attrValuePtr
->fAttributeValueData
.fBufferData
, user_name
))
399 dsDeallocAttributeValueEntry(dirRef
, attrValuePtr
);
403 dsCloseAttributeValueList(attrValueListRef
);
404 dsDeallocAttributeEntry(dirRef
, attrInfoPtr
);
407 dsCloseAttributeList(attrListRef
);
408 dsDeallocRecordEntry(dirRef
, groupRcdEntryPtr
);
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
);