VirtualBox

source: vbox/trunk/src/VBox/HostServices/auth/directoryservice/directoryservice.cpp@ 34214

最後變更 在這個檔案從34214是 33185,由 vboxsync 提交於 14 年 前

generalized and moved auth modules

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Id Revision
檔案大小: 13.3 KB
 
1/** @file
2 *
3 * VBox Remote Desktop Protocol:
4 * External Authentication Library:
5 * Mac OS X Authentication. This is based on
6 * http://developer.apple.com/mac/library/samplecode/CryptNoMore/
7 */
8
9/*
10 * Copyright (C) 2009-2010 Oracle Corporation
11 *
12 * This file is part of VirtualBox Open Source Edition (OSE), as
13 * available from http://www.alldomusa.eu.org. This file is free software;
14 * you can redistribute it and/or modify it under the terms of the GNU
15 * General Public License (GPL) as published by the Free Software
16 * Foundation, in version 2 as it comes in the "COPYING" file of the
17 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
18 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
19 */
20
21#include <iprt/cdefs.h>
22#include <iprt/assert.h>
23
24#include <VBox/VRDPAuth.h>
25
26#include <DirectoryService/DirectoryService.h>
27
28/* Globals */
29static const size_t s_cBufferSize = 32 * 1024;
30
31tDirStatus defaultSearchNodePath(tDirReference pDirRef, tDataListPtr *pdsNodePath)
32{
33 tDirStatus dsErr = eDSNoErr;
34 /* Create a buffer for the resulting nodes */
35 tDataBufferPtr pTmpBuf = NULL;
36 pTmpBuf = dsDataBufferAllocate(pDirRef, s_cBufferSize);
37 if (pTmpBuf)
38 {
39 /* Try to find the default search node for local names */
40 UInt32 cNodes;
41 tContextData pCtx = NULL;
42 dsErr = dsFindDirNodes(pDirRef, pTmpBuf, NULL, eDSLocalNodeNames, &cNodes, &pCtx);
43 /* Any nodes found? */
44 if ( dsErr == eDSNoErr
45 && cNodes >= 1)
46 /* The first path of the node list is what we looking for. */
47 dsErr = dsGetDirNodeName(pDirRef, pTmpBuf, 1, pdsNodePath);
48 else
49 dsErr = eDSNodeNotFound;
50
51 if (pCtx)
52 dsReleaseContinueData(pDirRef, pCtx);
53 dsDataBufferDeAllocate(pDirRef, pTmpBuf);
54 }
55 else
56 dsErr = eDSAllocationFailed;
57
58 return dsErr;
59}
60
61tDirStatus userAuthInfo(tDirReference pDirRef, tDirNodeReference pNodeRef, const char *pszUsername, tDataListPtr *ppAuthNodeListOut)
62{
63 tDirStatus dsErr = eDSNoErr;
64 tDirStatus dsCleanErr = eDSNoErr;
65 /* Create a buffer for the resulting authentication info */
66 tDataBufferPtr pTmpBuf = dsDataBufferAllocate(pDirRef, s_cBufferSize);
67 if (pTmpBuf)
68 {
69 /* Create the necessary lists for kDSNAttrMetaNodeLocation and kDSNAttrRecordName. */
70 tDataListPtr pRecordType = dsBuildListFromStrings(pDirRef, kDSStdRecordTypeUsers, NULL);
71 tDataListPtr pRecordName = dsBuildListFromStrings(pDirRef, pszUsername, NULL);
72 tDataListPtr pRequestedAttributes = dsBuildListFromStrings(pDirRef, kDSNAttrMetaNodeLocation, kDSNAttrRecordName, NULL);
73 if (!( pRecordType == NULL
74 || pRecordName == NULL
75 || pRequestedAttributes == NULL))
76 {
77 /* Now search for the first matching record */
78 UInt32 cRecords = 1;
79 tContextData pCtx = NULL;
80 dsErr = dsGetRecordList(pNodeRef,
81 pTmpBuf,
82 pRecordName,
83 eDSExact,
84 pRecordType,
85 pRequestedAttributes,
86 false,
87 &cRecords,
88 &pCtx);
89 if ( dsErr == eDSNoErr
90 && cRecords >= 1)
91 {
92 /* Process the first found record. Look at any attribute one by one. */
93 tAttributeListRef pRecAttrListRef = NULL;
94 tRecordEntryPtr pRecEntry = NULL;
95 tDataListPtr pAuthNodeList = NULL;
96 dsErr = dsGetRecordEntry(pNodeRef, pTmpBuf, 1, &pRecAttrListRef, &pRecEntry);
97 if (dsErr == eDSNoErr)
98 {
99 for (size_t i = 1; i <= pRecEntry->fRecordAttributeCount; ++i)
100 {
101 tAttributeValueListRef pAttrValueListRef = NULL;
102 tAttributeEntryPtr pAttrEntry = NULL;
103 /* Get the information for this attribute. */
104 dsErr = dsGetAttributeEntry(pNodeRef, pTmpBuf, pRecAttrListRef, i,
105 &pAttrValueListRef, &pAttrEntry);
106 if (dsErr == eDSNoErr)
107 {
108 tAttributeValueEntryPtr pValueEntry = NULL;
109 /* Has any value? */
110 if (pAttrEntry->fAttributeValueCount > 0)
111 {
112 dsErr = dsGetAttributeValue(pNodeRef, pTmpBuf, 1, pAttrValueListRef, &pValueEntry);
113 if (dsErr == eDSNoErr)
114 {
115 /* Check for kDSNAttrMetaNodeLocation */
116 if (strcmp(pAttrEntry->fAttributeSignature.fBufferData, kDSNAttrMetaNodeLocation) == 0)
117 {
118 /* Convert the meta location attribute to a path node list */
119 pAuthNodeList = dsBuildFromPath(pDirRef,
120 pValueEntry->fAttributeValueData.fBufferData,
121 "/");
122 if (pAuthNodeList == NULL)
123 dsErr = eDSAllocationFailed;
124 }
125 }
126 }
127
128 if (pValueEntry != NULL)
129 dsDeallocAttributeValueEntry(pDirRef, pValueEntry);
130 if (pAttrValueListRef)
131 dsCloseAttributeValueList(pAttrValueListRef);
132 if (pAttrEntry != NULL)
133 dsDeallocAttributeEntry(pDirRef, pAttrEntry);
134
135 if (dsErr != eDSNoErr)
136 break;
137 }
138 }
139 }
140 /* Copy the results */
141 if (dsErr == eDSNoErr)
142 {
143 if (pAuthNodeList != NULL)
144 {
145 /* Copy out results. */
146 *ppAuthNodeListOut = pAuthNodeList;
147 pAuthNodeList = NULL;
148 }
149 else
150 dsErr = eDSAttributeNotFound;
151 }
152
153 if (pAuthNodeList != NULL)
154 {
155 dsCleanErr = dsDataListDeallocate(pDirRef, pAuthNodeList);
156 if (dsCleanErr == eDSNoErr)
157 free(pAuthNodeList);
158 }
159 if (pRecAttrListRef)
160 dsCloseAttributeList(pRecAttrListRef);
161 if (pRecEntry != NULL)
162 dsDeallocRecordEntry(pDirRef, pRecEntry);
163 }
164 else
165 dsErr = eDSRecordNotFound;
166 if (pCtx)
167 dsReleaseContinueData(pDirRef, pCtx);
168 }
169 else
170 dsErr = eDSAllocationFailed;
171 if (pRequestedAttributes != NULL)
172 {
173 dsCleanErr = dsDataListDeallocate(pDirRef, pRequestedAttributes);
174 if (dsCleanErr == eDSNoErr)
175 free(pRequestedAttributes);
176 }
177 if (pRecordName != NULL)
178 {
179 dsCleanErr = dsDataListDeallocate(pDirRef, pRecordName);
180 if (dsCleanErr == eDSNoErr)
181 free(pRecordName);
182 }
183 if (pRecordType != NULL)
184 {
185 dsCleanErr = dsDataListDeallocate(pDirRef, pRecordType);
186 if (dsCleanErr == eDSNoErr)
187 free(pRecordType);
188 }
189 dsDataBufferDeAllocate(pDirRef, pTmpBuf);
190 }
191 else
192 dsErr = eDSAllocationFailed;
193
194 return dsErr;
195}
196
197tDirStatus authWithNode(tDirReference pDirRef, tDataListPtr pAuthNodeList, const char *pszUsername, const char *pszPassword)
198{
199 tDirStatus dsErr = eDSNoErr;
200 /* Open the authentication node. */
201 tDirNodeReference pAuthNodeRef = NULL;
202 dsErr = dsOpenDirNode(pDirRef, pAuthNodeList, &pAuthNodeRef);
203 if (dsErr == eDSNoErr)
204 {
205 /* How like we to authenticate! */
206 tDataNodePtr pAuthMethod = dsDataNodeAllocateString(pDirRef, kDSStdAuthNodeNativeClearTextOK);
207 if (pAuthMethod)
208 {
209 /* Create the memory holding the authentication data. The data
210 * structure consists of 4 byte length of the username + zero byte,
211 * the username itself, a 4 byte length of the password & the
212 * password itself + zero byte. */
213 tDataBufferPtr pAuthOutBuf = dsDataBufferAllocate(pDirRef, s_cBufferSize);
214 if (pAuthOutBuf)
215 {
216 size_t cUserName = strlen(pszUsername) + 1;
217 size_t cPassword = strlen(pszPassword) + 1;
218 unsigned long cLen = 0;
219 tDataBufferPtr pAuthInBuf = dsDataBufferAllocate(pDirRef, sizeof(cLen) + cUserName + sizeof(cLen) + cPassword);
220 if (pAuthInBuf)
221 {
222 /* Move the data into the buffer. */
223 pAuthInBuf->fBufferLength = 0;
224 /* Length of the username */
225 cLen = cUserName;
226 memcpy(&pAuthInBuf->fBufferData[pAuthInBuf->fBufferLength], &cLen, sizeof(cLen));
227 pAuthInBuf->fBufferLength += sizeof(cLen);
228 /* The username itself */
229 memcpy(&pAuthInBuf->fBufferData[pAuthInBuf->fBufferLength], pszUsername, cUserName);
230 pAuthInBuf->fBufferLength += cUserName;
231 /* Length of the password */
232 cLen = cPassword;
233 memcpy(&pAuthInBuf->fBufferData[pAuthInBuf->fBufferLength], &cLen, sizeof(cLen));
234 pAuthInBuf->fBufferLength += sizeof(cLen);
235 /* The password itself */
236 memcpy(&pAuthInBuf->fBufferData[pAuthInBuf->fBufferLength], pszPassword, cPassword);
237 pAuthInBuf->fBufferLength += cPassword;
238 /* Now authenticate */
239 dsErr = dsDoDirNodeAuth(pAuthNodeRef, pAuthMethod, true, pAuthInBuf, pAuthOutBuf, NULL);
240 /* Clean up. */
241 dsDataBufferDeAllocate(pDirRef, pAuthInBuf);
242 }
243 else
244 dsErr = eDSAllocationFailed;
245 dsDataBufferDeAllocate(pDirRef, pAuthOutBuf);
246 }
247 else
248 dsErr = eDSAllocationFailed;
249 dsDataNodeDeAllocate(pDirRef, pAuthMethod);
250 }
251 else
252 dsErr = eDSAllocationFailed;
253 dsCloseDirNode(pAuthNodeRef);
254 }
255
256 return dsErr;
257}
258
259RT_C_DECLS_BEGIN
260DECLEXPORT(VRDPAuthResult) VRDPAUTHCALL VRDPAuth(PVRDPAUTHUUID pUuid,
261 VRDPAuthGuestJudgement guestJudgement,
262 const char *pszUser,
263 const char *pszPassword,
264 const char *pszDomain)
265{
266 /* Validate input */
267 AssertPtrReturn(pszUser, VRDPAuthAccessDenied);
268 AssertPtrReturn(pszPassword, VRDPAuthAccessDenied);
269
270 /* Result to a default value */
271 VRDPAuthResult result = VRDPAuthAccessDenied;
272
273 tDirStatus dsErr = eDSNoErr;
274 tDirStatus dsCleanErr = eDSNoErr;
275 tDirReference pDirRef = NULL;
276 /* Connect to the Directory Service. */
277 dsErr = dsOpenDirService(&pDirRef);
278 if (dsErr == eDSNoErr)
279 {
280 /* Fetch the default search node */
281 tDataListPtr pSearchNodeList = NULL;
282 dsErr = defaultSearchNodePath(pDirRef, &pSearchNodeList);
283 if (dsErr == eDSNoErr)
284 {
285 /* Open the default search node */
286 tDirNodeReference pSearchNodeRef = NULL;
287 dsErr = dsOpenDirNode(pDirRef, pSearchNodeList, &pSearchNodeRef);
288 if (dsErr == eDSNoErr)
289 {
290 /* Search for the user info, fetch the authentication node &
291 * the authentication user name. This allows the client to
292 * specify a long user name even if the name which is used to
293 * authenticate has the short form. */
294 tDataListPtr pAuthNodeList = NULL;
295 dsErr = userAuthInfo(pDirRef, pSearchNodeRef, pszUser, &pAuthNodeList);
296 if (dsErr == eDSNoErr)
297 {
298 /* Open the authentication node and do the authentication. */
299 dsErr = authWithNode(pDirRef, pAuthNodeList, pszUser, pszPassword);
300 if (dsErr == eDSNoErr)
301 result = VRDPAuthAccessGranted;
302 dsCleanErr = dsDataListDeallocate(pDirRef, pAuthNodeList);
303 if (dsCleanErr == eDSNoErr)
304 free(pAuthNodeList);
305 }
306 dsCloseDirNode(pSearchNodeRef);
307 }
308 dsCleanErr = dsDataListDeallocate(pDirRef, pSearchNodeList);
309 if (dsCleanErr == eDSNoErr)
310 free(pSearchNodeList);
311 }
312 dsCloseDirService(pDirRef);
313 }
314
315 return result;
316}
317RT_C_DECLS_END
318
319static PVRDPAUTHENTRY gpfnAuthEntry = VRDPAuth;
320
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette