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(NULL,"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(NULL,"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(NULL,"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(NULL,"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(NULL,"Received delegate context");
185 DebugEvent(NULL,"Didn't receive delegate context");
188 DeleteSecurityContext(&ctxserver);
192 DeleteSecurityContext(&ctxclient);
194 FreeCredentialsHandle(&creds);
199 DWORD QueryAdHomePath(char * homePath, size_t homePathLen, PLUID lpLogonId) {
200 DWORD code = 1; /* default is failure */
202 PSECURITY_LOGON_SESSION_DATA plsd;
208 WCHAR adsPath[MAX_PATH] = L"";
209 BOOL coInitialized = FALSE;
213 rv = LsaGetLogonSessionData(lpLogonId, &plsd);
215 if(ConvertSidToStringSidW(plsd->Sid,&p)) {
216 IADsNameTranslate *pNto;
218 DebugEvent(NULL, "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(NULL,"Can't create nametranslate object"); }
232 hr = pNto->Init(ADS_NAME_INITTYPE_GC,L""); //,clientUpn/*IL->UserName.Buffer*/,IL->LogonDomainName.Buffer,IL->Password.Buffer);
234 DebugEvent(NULL,"NameTranslate Init failed [%ld]", hr);
237 hr = pNto->Set(ADS_NAME_TYPE_SID_OR_SID_HISTORY_NAME, p);
238 if(FAILED(hr)) { DebugEvent(NULL,"Can't set sid string"); }
242 hr = pNto->Get(ADS_NAME_TYPE_1779, &bstr);
243 wcscpy(adsPath, bstr);
254 DebugEvent(NULL, "Can't convert sid to string");
257 LsaFreeReturnBuffer(plsd);
259 DebugEvent(NULL, "LsaGetLogonSessionData failed");
263 WCHAR fAdsPath[MAX_PATH];
265 BSTR bstHomeDir = NULL;
267 hr = StringCchPrintfW(fAdsPath, MAX_PATH, L"LDAP://%s", adsPath);
269 DebugEvent(NULL, "Can't format full adspath");
273 DebugEvent(NULL, "Trying adsPath=[%S]", fAdsPath);
275 hr = ADsGetObject( fAdsPath, IID_IADsUser, (LPVOID *) &pAdsUser);
277 DebugEvent(NULL, "Can't open IADs object");
281 hr = pAdsUser->get_Profile(&bstHomeDir);
283 DebugEvent(NULL, "Can't get profile directory");
284 goto cleanup_homedir_section;
287 wcstombs(homePath, bstHomeDir, homePathLen);
289 DebugEvent(NULL, "Got homepath [%s]", homePath);
291 SysFreeString(bstHomeDir);
295 cleanup_homedir_section:
306 /* Try to determine the user's AD home path. *homePath is assumed to be at least MAXPATH bytes.
307 If successful, opt.flags is updated with LOGON_FLAG_AD_REALM to indicate that we are dealing with
309 DWORD GetAdHomePath(char * homePath, size_t homePathLen, PLUID lpLogonId, LogonOptions_t * opt) {
312 SECURITY_STATUS status;
316 if(LogonSSP(lpLogonId,&ctx))
319 status = ImpersonateSecurityContext(&ctx);
320 if(status == SEC_E_OK) {
321 if(!QueryAdHomePath(homePath,homePathLen,lpLogonId)) {
322 DebugEvent(NULL,"Returned home path [%s]",homePath);
323 opt->flags |= LOGON_FLAG_AD_REALM;
325 RevertSecurityContext(&ctx);
327 DebugEvent(NULL,"Can't impersonate context [%lX]",status);
331 DeleteSecurityContext(&ctx);