3 Copyright 2004 by the Massachusetts Institute of Technology
7 Permission to use, copy, modify, and distribute this software and its
8 documentation for any purpose and without fee is hereby granted,
9 provided that the above copyright notice appear in all copies and that
10 both that copyright notice and this permission notice appear in
11 supporting documentation, and that the name of the Massachusetts
12 Institute of Technology (M.I.T.) not be used in advertising or publicity
13 pertaining to distribution of the software without specific, written
16 M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
17 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
18 M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
19 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
20 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
21 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
27 //#pragma keyword("interface",on)
28 #define interface struct
29 #define SECURITY_WIN32
42 #define SEC_ERR_VALUE(v) if (status==v) return #v
44 char * _get_sec_err_text(SECURITY_STATUS status) {
45 SEC_ERR_VALUE(SEC_E_OK);
46 SEC_ERR_VALUE(SEC_I_CONTINUE_NEEDED);
47 SEC_ERR_VALUE(SEC_I_COMPLETE_NEEDED);
48 SEC_ERR_VALUE(SEC_I_COMPLETE_AND_CONTINUE);
49 SEC_ERR_VALUE(SEC_E_INCOMPLETE_MESSAGE);
50 SEC_ERR_VALUE(SEC_I_INCOMPLETE_CREDENTIALS);
51 SEC_ERR_VALUE(SEC_E_INVALID_HANDLE);
52 SEC_ERR_VALUE(SEC_E_TARGET_UNKNOWN);
53 SEC_ERR_VALUE(SEC_E_LOGON_DENIED);
54 SEC_ERR_VALUE(SEC_E_INTERNAL_ERROR);
55 SEC_ERR_VALUE(SEC_E_NO_CREDENTIALS);
56 SEC_ERR_VALUE(SEC_E_NO_AUTHENTICATING_AUTHORITY);
57 SEC_ERR_VALUE(SEC_E_INSUFFICIENT_MEMORY);
58 SEC_ERR_VALUE(SEC_E_INVALID_TOKEN);
59 SEC_ERR_VALUE(SEC_E_UNSUPPORTED_FUNCTION);
60 SEC_ERR_VALUE(SEC_E_WRONG_PRINCIPAL);
66 DWORD LogonSSP(PLUID lpLogonId, PCtxtHandle outCtx) {
68 SECURITY_STATUS status;
70 CtxtHandle ctxclient,ctxserver;
74 SecBufferDesc sdescc,sdescs;
75 SecBuffer stokc,stoks;
85 status = AcquireCredentialsHandle(
96 if (status != SEC_E_OK) {
97 DebugEvent("AcquireCredentialsHandle failed: %lX", status);
102 sdescc.pBuffers = &stokc;
103 sdescc.ulVersion = SECBUFFER_VERSION;
105 stokc.BufferType = SECBUFFER_TOKEN;
107 stokc.pvBuffer = NULL;
110 sdescs.pBuffers = &stoks;
111 sdescs.ulVersion = SECBUFFER_VERSION;
113 stoks.BufferType = SECBUFFER_TOKEN;
115 stoks.pvBuffer = NULL;
118 status = InitializeSecurityContext(
120 ((first)? NULL:&ctxclient),
122 ISC_REQ_DELEGATE | ISC_REQ_ALLOCATE_MEMORY,
124 SECURITY_NATIVE_DREP,
125 ((first)?NULL:&sdescs),
133 DebugEvent("InitializeSecurityContext returns status[%lX](%s)",status,_get_sec_err_text(status));
135 if (!first) FreeContextBuffer(stoks.pvBuffer);
137 if (status == SEC_I_COMPLETE_NEEDED || status == SEC_I_COMPLETE_AND_CONTINUE) {
138 CompleteAuthToken(&ctxclient, &sdescc);
141 if (status != SEC_I_CONTINUE_NEEDED && status != SEC_I_COMPLETE_AND_CONTINUE) {
145 if (!stokc.cbBuffer && !cont) {
146 DebugEvent("Breaking out after InitializeSecurityContext");
150 status = AcceptSecurityContext(
152 ((first)?NULL:&ctxserver),
154 ASC_REQ_DELEGATE | ASC_REQ_ALLOCATE_MEMORY,
155 SECURITY_NATIVE_DREP,
161 DebugEvent("AcceptSecurityContext returns status[%lX](%s)", status, _get_sec_err_text(status));
163 FreeContextBuffer(stokc.pvBuffer);
165 if (status == SEC_I_COMPLETE_NEEDED || status == SEC_I_COMPLETE_AND_CONTINUE) {
166 CompleteAuthToken(&ctxserver,&sdescs);
169 if (status == SEC_I_CONTINUE_NEEDED || status == SEC_I_COMPLETE_AND_CONTINUE) {
174 FreeContextBuffer(stoks.pvBuffer);
177 iters--; /* just in case, hard limit on loop */
178 } while (cont && iters);
180 if (sattrs & ASC_RET_DELEGATE) {
181 DebugEvent("Received delegate context");
185 DebugEvent("Didn't receive delegate context");
188 DeleteSecurityContext(&ctxserver);
191 DeleteSecurityContext(&ctxclient);
192 FreeCredentialsHandle(&creds);
197 DWORD QueryAdHomePathFromSid(char * homePath, size_t homePathLen, PSID psid, PWSTR domain) {
198 DWORD code = 1; /* default is failure */
202 WCHAR adsPath[MAX_PATH] = L"";
203 BOOL coInitialized = FALSE;
204 CHAR ansidomain[256], *a;
208 /* I trust this is an ASCII domain name */
209 for ( p=domain, a=ansidomain; *a = (CHAR)*p; p++, a++);
210 DebugEvent("Domain: %s", ansidomain);
212 if (ConvertSidToStringSidW(psid,&p)) {
213 IADsNameTranslate *pNto;
215 DebugEvent("Got SID string [%S]", p);
217 hr = CoInitialize(NULL);
219 coInitialized = TRUE;
221 hr = CoCreateInstance( CLSID_NameTranslate,
223 CLSCTX_INPROC_SERVER,
224 IID_IADsNameTranslate,
227 if (FAILED(hr)) { DebugEvent("Can't create nametranslate object"); }
229 hr = pNto->Init(ADS_NAME_INITTYPE_GC,L"");
231 DebugEvent("NameTranslate Init GC failed [%ld]", hr);
233 hr = pNto->Init(ADS_NAME_INITTYPE_DOMAIN,domain);
235 DebugEvent("NameTranslate Init Domain failed [%ld]", hr);
241 hr = pNto->Set(ADS_NAME_TYPE_SID_OR_SID_HISTORY_NAME, p);
242 if (FAILED(hr)) { DebugEvent("Can't set sid string"); }
246 hr = pNto->Get(ADS_NAME_TYPE_1779, &bstr);
248 hr = StringCchCopyW(adsPath, MAX_PATH, bstr);
250 DebugEvent("Overflow while copying ADS path");
264 DebugEvent("Can't convert sid to string");
268 WCHAR fAdsPath[MAX_PATH];
270 BSTR bstHomeDir = NULL;
272 hr = StringCchPrintfW(fAdsPath, MAX_PATH, L"LDAP://%s", adsPath);
274 DebugEvent("Can't format full adspath");
278 DebugEvent("Trying adsPath=[%S]", fAdsPath);
280 hr = ADsGetObject( fAdsPath, IID_IADsUser, (LPVOID *) &pAdsUser);
282 DebugEvent("Can't open IADs object");
286 hr = pAdsUser->get_Profile(&bstHomeDir);
288 DebugEvent("Can't get profile directory");
289 goto cleanup_homedir_section;
292 wcstombs(homePath, bstHomeDir, homePathLen);
294 DebugEvent("Got homepath [%s]", homePath);
296 SysFreeString(bstHomeDir);
300 cleanup_homedir_section:
311 /* Try to determine the user's AD home path. *homePath is assumed to be at least MAXPATH bytes.
312 If successful, opt.flags is updated with LOGON_FLAG_AD_REALM to indicate that we are dealing with
314 DWORD GetAdHomePath(char * homePath, size_t homePathLen, PLUID lpLogonId, LogonOptions_t * opt) {
317 SECURITY_STATUS status;
321 if (LogonSSP(lpLogonId,&ctx)) {
322 DebugEvent("Failed LogonSSP");
325 status = ImpersonateSecurityContext(&ctx);
326 if (status == SEC_E_OK) {
327 PSECURITY_LOGON_SESSION_DATA plsd;
330 rv = LsaGetLogonSessionData(lpLogonId, &plsd);
334 domain = (PWSTR)malloc(sizeof(WCHAR) * (plsd->LogonDomain.Length+1));
335 memcpy(domain, plsd->LogonDomain.Buffer, sizeof(WCHAR) * (plsd->LogonDomain.Length));
336 domain[plsd->LogonDomain.Length] = 0;
338 if (!QueryAdHomePathFromSid(homePath,homePathLen,plsd->Sid,domain)) {
339 DebugEvent("Returned home path [%s]",homePath);
340 opt->flags |= LOGON_FLAG_AD_REALM;
343 LsaFreeReturnBuffer(plsd);
345 DebugEvent("LsaGetLogonSessionData failed [%lX]", rv);
347 RevertSecurityContext(&ctx);
349 DebugEvent("Can't impersonate context [%lX]",status);
353 DeleteSecurityContext(&ctx);
358 BOOL GetLocalShortDomain(PWSTR Domain, DWORD cbDomain)
361 IADsADSystemInfo *pADsys;
362 BOOL coInitialized = FALSE;
365 hr = CoInitialize(NULL);
367 coInitialized = TRUE;
369 hr = CoCreateInstance(CLSID_ADSystemInfo,
371 CLSCTX_INPROC_SERVER,
372 IID_IADsADSystemInfo,
377 hr = pADsys->get_DomainShortName(&bstr);
379 hr = StringCbCopyW( Domain, cbDomain, bstr );