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) {
198 DWORD code = 1; /* default is failure */
202 WCHAR adsPath[MAX_PATH] = L"";
203 BOOL coInitialized = FALSE;
207 if(ConvertSidToStringSidW(psid,&p)) {
208 IADsNameTranslate *pNto;
210 DebugEvent("Got SID string [%S]", p);
212 hr = CoInitialize(NULL);
214 coInitialized = TRUE;
216 hr = CoCreateInstance( CLSID_NameTranslate,
218 CLSCTX_INPROC_SERVER,
219 IID_IADsNameTranslate,
222 if(FAILED(hr)) { DebugEvent("Can't create nametranslate object"); }
224 hr = pNto->Init(ADS_NAME_INITTYPE_GC,L""); //,clientUpn/*IL->UserName.Buffer*/,IL->LogonDomainName.Buffer,IL->Password.Buffer);
226 DebugEvent("NameTranslate Init failed [%ld]", hr);
229 hr = pNto->Set(ADS_NAME_TYPE_SID_OR_SID_HISTORY_NAME, p);
230 if(FAILED(hr)) { DebugEvent("Can't set sid string"); }
234 hr = pNto->Get(ADS_NAME_TYPE_1779, &bstr);
235 wcscpy(adsPath, bstr);
246 DebugEvent("Can't convert sid to string");
250 WCHAR fAdsPath[MAX_PATH];
252 BSTR bstHomeDir = NULL;
254 hr = StringCchPrintfW(fAdsPath, MAX_PATH, L"LDAP://%s", adsPath);
256 DebugEvent("Can't format full adspath");
260 DebugEvent("Trying adsPath=[%S]", fAdsPath);
262 hr = ADsGetObject( fAdsPath, IID_IADsUser, (LPVOID *) &pAdsUser);
264 DebugEvent("Can't open IADs object");
268 hr = pAdsUser->get_Profile(&bstHomeDir);
270 DebugEvent("Can't get profile directory");
271 goto cleanup_homedir_section;
274 wcstombs(homePath, bstHomeDir, homePathLen);
276 DebugEvent("Got homepath [%s]", homePath);
278 SysFreeString(bstHomeDir);
282 cleanup_homedir_section:
293 /* Try to determine the user's AD home path. *homePath is assumed to be at least MAXPATH bytes.
294 If successful, opt.flags is updated with LOGON_FLAG_AD_REALM to indicate that we are dealing with
296 DWORD GetAdHomePath(char * homePath, size_t homePathLen, PLUID lpLogonId, LogonOptions_t * opt) {
299 SECURITY_STATUS status;
303 if(LogonSSP(lpLogonId,&ctx)) {
304 DebugEvent("Failed LogonSSP");
307 status = ImpersonateSecurityContext(&ctx);
308 if(status == SEC_E_OK) {
309 PSECURITY_LOGON_SESSION_DATA plsd;
312 rv = LsaGetLogonSessionData(lpLogonId, &plsd);
314 if(!QueryAdHomePathFromSid(homePath,homePathLen,plsd->Sid)) {
315 DebugEvent("Returned home path [%s]",homePath);
316 opt->flags |= LOGON_FLAG_AD_REALM;
318 LsaFreeReturnBuffer(plsd);
320 DebugEvent("LsaGetLogonSessionData failed [%lX]", rv);
322 RevertSecurityContext(&ctx);
324 DebugEvent("Can't impersonate context [%lX]",status);
328 DeleteSecurityContext(&ctx);