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
32 #if (_WIN32_WINNT < 0x0500)
33 #error _WIN32_WINNT < 0x0500
45 #define SEC_ERR_VALUE(v) if (status==v) return #v
47 char * _get_sec_err_text(SECURITY_STATUS status) {
48 SEC_ERR_VALUE(SEC_E_OK);
49 SEC_ERR_VALUE(SEC_I_CONTINUE_NEEDED);
50 SEC_ERR_VALUE(SEC_I_COMPLETE_NEEDED);
51 SEC_ERR_VALUE(SEC_I_COMPLETE_AND_CONTINUE);
52 SEC_ERR_VALUE(SEC_E_INCOMPLETE_MESSAGE);
53 SEC_ERR_VALUE(SEC_I_INCOMPLETE_CREDENTIALS);
54 SEC_ERR_VALUE(SEC_E_INVALID_HANDLE);
55 SEC_ERR_VALUE(SEC_E_TARGET_UNKNOWN);
56 SEC_ERR_VALUE(SEC_E_LOGON_DENIED);
57 SEC_ERR_VALUE(SEC_E_INTERNAL_ERROR);
58 SEC_ERR_VALUE(SEC_E_NO_CREDENTIALS);
59 SEC_ERR_VALUE(SEC_E_NO_AUTHENTICATING_AUTHORITY);
60 SEC_ERR_VALUE(SEC_E_INSUFFICIENT_MEMORY);
61 SEC_ERR_VALUE(SEC_E_INVALID_TOKEN);
62 SEC_ERR_VALUE(SEC_E_UNSUPPORTED_FUNCTION);
63 SEC_ERR_VALUE(SEC_E_WRONG_PRINCIPAL);
69 DWORD LogonSSP(PLUID lpLogonId, PCtxtHandle outCtx) {
71 SECURITY_STATUS status;
73 CtxtHandle ctxclient,ctxserver;
77 SecBufferDesc sdescc,sdescs;
78 SecBuffer stokc,stoks;
88 status = AcquireCredentialsHandle(
99 if (status != SEC_E_OK) {
100 DebugEvent("AcquireCredentialsHandle failed: %lX", status);
105 sdescc.pBuffers = &stokc;
106 sdescc.ulVersion = SECBUFFER_VERSION;
108 stokc.BufferType = SECBUFFER_TOKEN;
110 stokc.pvBuffer = NULL;
113 sdescs.pBuffers = &stoks;
114 sdescs.ulVersion = SECBUFFER_VERSION;
116 stoks.BufferType = SECBUFFER_TOKEN;
118 stoks.pvBuffer = NULL;
121 status = InitializeSecurityContext(
123 ((first)? NULL:&ctxclient),
125 ISC_REQ_DELEGATE | ISC_REQ_ALLOCATE_MEMORY,
127 SECURITY_NATIVE_DREP,
128 ((first)?NULL:&sdescs),
136 DebugEvent("InitializeSecurityContext returns status[%lX](%s)",status,_get_sec_err_text(status));
138 if (!first) FreeContextBuffer(stoks.pvBuffer);
140 if (status == SEC_I_COMPLETE_NEEDED || status == SEC_I_COMPLETE_AND_CONTINUE) {
141 CompleteAuthToken(&ctxclient, &sdescc);
144 if (status != SEC_I_CONTINUE_NEEDED && status != SEC_I_COMPLETE_AND_CONTINUE) {
148 if (!stokc.cbBuffer && !cont) {
149 DebugEvent("Breaking out after InitializeSecurityContext");
153 status = AcceptSecurityContext(
155 ((first)?NULL:&ctxserver),
157 ASC_REQ_DELEGATE | ASC_REQ_ALLOCATE_MEMORY,
158 SECURITY_NATIVE_DREP,
164 DebugEvent("AcceptSecurityContext returns status[%lX](%s)", status, _get_sec_err_text(status));
166 FreeContextBuffer(stokc.pvBuffer);
168 if (status == SEC_I_COMPLETE_NEEDED || status == SEC_I_COMPLETE_AND_CONTINUE) {
169 CompleteAuthToken(&ctxserver,&sdescs);
172 if (status == SEC_I_CONTINUE_NEEDED || status == SEC_I_COMPLETE_AND_CONTINUE) {
177 FreeContextBuffer(stoks.pvBuffer);
180 iters--; /* just in case, hard limit on loop */
181 } while (cont && iters);
183 if (sattrs & ASC_RET_DELEGATE) {
184 DebugEvent("Received delegate context");
188 DebugEvent("Didn't receive delegate context");
191 DeleteSecurityContext(&ctxserver);
194 DeleteSecurityContext(&ctxclient);
195 FreeCredentialsHandle(&creds);
200 DWORD QueryAdHomePathFromSid(char * homePath, size_t homePathLen, PSID psid, PWSTR domain) {
201 DWORD code = 1; /* default is failure */
205 WCHAR adsPath[MAX_PATH] = L"";
206 BOOL coInitialized = FALSE;
207 CHAR ansidomain[256], *a;
211 /* I trust this is an ASCII domain name */
212 for ( p=domain, a=ansidomain; *a = (CHAR)*p; p++, a++);
213 DebugEvent("Domain: %s", ansidomain);
215 if (ConvertSidToStringSidW(psid,&p)) {
216 IADsNameTranslate *pNto;
218 DebugEvent("Got SID string [%S]", p);
220 hr = CoInitialize(NULL);
222 coInitialized = TRUE;
224 hr = CoCreateInstance( CLSID_NameTranslate,
226 CLSCTX_INPROC_SERVER,
227 IID_IADsNameTranslate,
230 if (FAILED(hr)) { DebugEvent("Can't create nametranslate object"); }
232 hr = pNto->Init(ADS_NAME_INITTYPE_GC,L"");
234 DebugEvent("NameTranslate Init GC failed [%ld]", hr);
236 hr = pNto->Init(ADS_NAME_INITTYPE_DOMAIN,domain);
238 DebugEvent("NameTranslate Init Domain failed [%ld]", hr);
244 hr = pNto->Set(ADS_NAME_TYPE_SID_OR_SID_HISTORY_NAME, p);
245 if (FAILED(hr)) { DebugEvent("Can't set sid string"); }
249 hr = pNto->Get(ADS_NAME_TYPE_1779, &bstr);
251 hr = StringCchCopyW(adsPath, MAX_PATH, bstr);
253 DebugEvent("Overflow while copying ADS path");
267 DebugEvent("Can't convert sid to string");
271 WCHAR fAdsPath[MAX_PATH];
273 BSTR bstHomeDir = NULL;
275 hr = StringCchPrintfW(fAdsPath, MAX_PATH, L"LDAP://%s", adsPath);
277 DebugEvent("Can't format full adspath");
281 DebugEvent("Trying adsPath=[%S]", fAdsPath);
283 hr = ADsGetObject( fAdsPath, IID_IADsUser, (LPVOID *) &pAdsUser);
285 DebugEvent("Can't open IADs object");
289 hr = pAdsUser->get_Profile(&bstHomeDir);
291 DebugEvent("Can't get profile directory");
292 goto cleanup_homedir_section;
295 wcstombs(homePath, bstHomeDir, homePathLen);
297 DebugEvent("Got homepath [%s]", homePath);
299 SysFreeString(bstHomeDir);
303 cleanup_homedir_section:
314 /* Try to determine the user's AD home path. *homePath is assumed to be at least MAXPATH bytes.
315 If successful, opt.flags is updated with LOGON_FLAG_AD_REALM to indicate that we are dealing with
317 DWORD GetAdHomePath(char * homePath, size_t homePathLen, PLUID lpLogonId, LogonOptions_t * opt) {
320 SECURITY_STATUS status;
324 if (LogonSSP(lpLogonId,&ctx)) {
325 DebugEvent("Failed LogonSSP");
328 status = ImpersonateSecurityContext(&ctx);
329 if (status == SEC_E_OK) {
330 PSECURITY_LOGON_SESSION_DATA plsd;
333 rv = LsaGetLogonSessionData(lpLogonId, &plsd);
337 domain = (PWSTR)malloc(sizeof(WCHAR) * (plsd->LogonDomain.Length+1));
338 memcpy(domain, plsd->LogonDomain.Buffer, sizeof(WCHAR) * (plsd->LogonDomain.Length));
339 domain[plsd->LogonDomain.Length] = 0;
341 if (!QueryAdHomePathFromSid(homePath,homePathLen,plsd->Sid,domain)) {
342 DebugEvent("Returned home path [%s]",homePath);
343 opt->flags |= LOGON_FLAG_AD_REALM;
346 LsaFreeReturnBuffer(plsd);
348 DebugEvent("LsaGetLogonSessionData failed [%lX]", rv);
350 RevertSecurityContext(&ctx);
352 DebugEvent("Can't impersonate context [%lX]",status);
356 DeleteSecurityContext(&ctx);
361 BOOL GetLocalShortDomain(PWSTR Domain, DWORD cbDomain)
364 IADsADSystemInfo *pADsys;
365 BOOL coInitialized = FALSE;
368 hr = CoInitialize(NULL);
370 coInitialized = TRUE;
372 hr = CoCreateInstance(CLSID_ADSystemInfo,
374 CLSCTX_INPROC_SERVER,
375 IID_IADsADSystemInfo,
380 hr = pADsys->get_DomainShortName(&bstr);
382 hr = StringCbCopyW( Domain, cbDomain, bstr );