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 #include <afsconfig.h>
28 #include <afs/param.h>
32 //#pragma keyword("interface",on)
33 //#define interface struct
34 #define SECURITY_WIN32
35 #if (_WIN32_WINNT < 0x0500)
36 #error _WIN32_WINNT < 0x0500
51 #include "..\afsrdr\common\AFSUserDefines.h"
52 #include "..\afsrdr\common\AFSUserIoctl.h"
53 #include "..\afsrdr\common\AFSUserStructs.h"
54 #include "..\afsrdr\common\AFSProvider.h"
56 #define SEC_ERR_VALUE(v) if (status==v) return #v
58 char * _get_sec_err_text(SECURITY_STATUS status) {
59 SEC_ERR_VALUE(SEC_E_OK);
60 SEC_ERR_VALUE(SEC_I_CONTINUE_NEEDED);
61 SEC_ERR_VALUE(SEC_I_COMPLETE_NEEDED);
62 SEC_ERR_VALUE(SEC_I_COMPLETE_AND_CONTINUE);
63 SEC_ERR_VALUE(SEC_E_INCOMPLETE_MESSAGE);
64 SEC_ERR_VALUE(SEC_I_INCOMPLETE_CREDENTIALS);
65 SEC_ERR_VALUE(SEC_E_INVALID_HANDLE);
66 SEC_ERR_VALUE(SEC_E_TARGET_UNKNOWN);
67 SEC_ERR_VALUE(SEC_E_LOGON_DENIED);
68 SEC_ERR_VALUE(SEC_E_INTERNAL_ERROR);
69 SEC_ERR_VALUE(SEC_E_NO_CREDENTIALS);
70 SEC_ERR_VALUE(SEC_E_NO_AUTHENTICATING_AUTHORITY);
71 SEC_ERR_VALUE(SEC_E_INSUFFICIENT_MEMORY);
72 SEC_ERR_VALUE(SEC_E_INVALID_TOKEN);
73 SEC_ERR_VALUE(SEC_E_UNSUPPORTED_FUNCTION);
74 SEC_ERR_VALUE(SEC_E_WRONG_PRINCIPAL);
81 LogonSSP(PLUID lpLogonId, PCtxtHandle outCtx) {
83 SECURITY_STATUS status;
85 CtxtHandle ctxclient,ctxserver;
89 SecBufferDesc sdescc,sdescs;
90 SecBuffer stokc,stoks;
100 status = AcquireCredentialsHandle( NULL,
110 if (status != SEC_E_OK) {
111 DebugEvent("AcquireCredentialsHandle failed: %lX", status);
116 sdescc.pBuffers = &stokc;
117 sdescc.ulVersion = SECBUFFER_VERSION;
119 stokc.BufferType = SECBUFFER_TOKEN;
121 stokc.pvBuffer = NULL;
124 sdescs.pBuffers = &stoks;
125 sdescs.ulVersion = SECBUFFER_VERSION;
127 stoks.BufferType = SECBUFFER_TOKEN;
129 stoks.pvBuffer = NULL;
132 status = InitializeSecurityContext( &creds,
133 ((first)? NULL:&ctxclient),
135 ISC_REQ_DELEGATE | ISC_REQ_ALLOCATE_MEMORY,
137 SECURITY_NATIVE_DREP,
138 ((first)?NULL:&sdescs),
146 DebugEvent("InitializeSecurityContext returns status[%lX](%s)",status,_get_sec_err_text(status));
148 if (!first) FreeContextBuffer(stoks.pvBuffer);
150 if (status == SEC_I_COMPLETE_NEEDED || status == SEC_I_COMPLETE_AND_CONTINUE) {
151 CompleteAuthToken(&ctxclient, &sdescc);
154 if (status != SEC_I_CONTINUE_NEEDED && status != SEC_I_COMPLETE_AND_CONTINUE) {
158 if (!stokc.cbBuffer && !cont) {
159 DebugEvent("Breaking out after InitializeSecurityContext");
163 status = AcceptSecurityContext( &creds,
164 ((first)?NULL:&ctxserver),
166 ASC_REQ_DELEGATE | ASC_REQ_ALLOCATE_MEMORY,
167 SECURITY_NATIVE_DREP,
173 DebugEvent("AcceptSecurityContext returns status[%lX](%s)", status, _get_sec_err_text(status));
175 FreeContextBuffer(stokc.pvBuffer);
177 if (status == SEC_I_COMPLETE_NEEDED || status == SEC_I_COMPLETE_AND_CONTINUE) {
178 CompleteAuthToken(&ctxserver,&sdescs);
181 if (status == SEC_I_CONTINUE_NEEDED || status == SEC_I_COMPLETE_AND_CONTINUE) {
186 FreeContextBuffer(stoks.pvBuffer);
189 iters--; /* just in case, hard limit on loop */
190 } while (cont && iters);
192 if (sattrs & ASC_RET_DELEGATE) {
193 DebugEvent("Received delegate context");
197 DebugEvent("Didn't receive delegate context");
200 DeleteSecurityContext(&ctxserver);
203 DeleteSecurityContext(&ctxclient);
204 FreeCredentialsHandle(&creds);
210 QueryAdHomePathFromSid(char * homePath, size_t homePathLen, PSID psid, PWSTR domain) {
211 DWORD code = 1; /* default is failure */
215 WCHAR adsPath[MAX_PATH] = L"";
216 BOOL coInitialized = FALSE;
217 CHAR ansidomain[256], *a;
221 /* I trust this is an ASCII domain name */
222 for ( p=domain, a=ansidomain; *a = (CHAR)*p; p++, a++);
223 DebugEvent("Domain: %s", ansidomain);
225 if (ConvertSidToStringSidW(psid,&p)) {
226 IADsNameTranslate *pNto;
228 DebugEvent("Got SID string [%S]", p);
230 hr = CoInitialize(NULL);
232 coInitialized = TRUE;
234 hr = CoCreateInstance( CLSID_NameTranslate,
236 CLSCTX_INPROC_SERVER,
237 IID_IADsNameTranslate,
241 DebugEvent("Can't create nametranslate object");
244 hr = pNto->Init(ADS_NAME_INITTYPE_GC,L"");
246 DebugEvent("NameTranslate Init GC failed [%ld]", hr);
248 hr = pNto->Init(ADS_NAME_INITTYPE_DOMAIN,domain);
250 DebugEvent("NameTranslate Init Domain failed [%ld]", hr);
256 hr = pNto->Set(ADS_NAME_TYPE_SID_OR_SID_HISTORY_NAME, p);
258 DebugEvent("Can't set sid string");
263 hr = pNto->Get(ADS_NAME_TYPE_1779, &bstr);
265 hr = StringCchCopyW(adsPath, MAX_PATH, bstr);
267 DebugEvent("Overflow while copying ADS path");
280 DebugEvent("Can't convert sid to string");
284 WCHAR fAdsPath[MAX_PATH];
286 BSTR bstHomeDir = NULL;
288 hr = StringCchPrintfW(fAdsPath, MAX_PATH, L"LDAP://%s", adsPath);
290 DebugEvent("Can't format full adspath");
294 DebugEvent("Trying adsPath=[%S]", fAdsPath);
296 hr = ADsGetObject( fAdsPath, IID_IADsUser, (LPVOID *) &pAdsUser);
298 DebugEvent("Can't open IADs object");
302 hr = pAdsUser->get_Profile(&bstHomeDir);
304 DebugEvent("Can't get profile directory");
305 goto cleanup_homedir_section;
308 wcstombs(homePath, bstHomeDir, homePathLen);
310 DebugEvent("Got homepath [%s]", homePath);
312 SysFreeString(bstHomeDir);
316 cleanup_homedir_section:
327 /* Try to determine the user's AD home path. *homePath is assumed to be at least MAXPATH bytes.
328 If successful, opt.flags is updated with LOGON_FLAG_AD_REALM to indicate that we are dealing with
331 GetAdHomePath(char * homePath, size_t homePathLen, PLUID lpLogonId, LogonOptions_t * opt) {
334 SECURITY_STATUS status;
338 if (LogonSSP(lpLogonId,&ctx)) {
339 DebugEvent("Failed LogonSSP");
343 status = ImpersonateSecurityContext(&ctx);
344 if (status == SEC_E_OK) {
345 PSECURITY_LOGON_SESSION_DATA plsd;
348 rv = LsaGetLogonSessionData(lpLogonId, &plsd);
352 domain = (PWSTR)malloc(sizeof(WCHAR) * (plsd->LogonDomain.Length+1));
353 memcpy(domain, plsd->LogonDomain.Buffer, sizeof(WCHAR) * (plsd->LogonDomain.Length));
354 domain[plsd->LogonDomain.Length] = 0;
356 if (!QueryAdHomePathFromSid(homePath,homePathLen,plsd->Sid,domain)) {
357 DebugEvent("Returned home path [%s]",homePath);
358 opt->flags |= LOGON_FLAG_AD_REALM;
361 LsaFreeReturnBuffer(plsd);
363 DebugEvent("LsaGetLogonSessionData failed [%lX]", rv);
365 RevertSecurityContext(&ctx);
367 DebugEvent("Can't impersonate context [%lX]",status);
371 DeleteSecurityContext(&ctx);
376 GetLocalShortDomain(PWSTR Domain, DWORD cbDomain)
379 IADsADSystemInfo *pADsys;
380 BOOL coInitialized = FALSE;
383 hr = CoInitialize(NULL);
385 coInitialized = TRUE;
387 hr = CoCreateInstance( CLSID_ADSystemInfo,
389 CLSCTX_INPROC_SERVER,
390 IID_IADsADSystemInfo,
395 hr = pADsys->get_DomainShortName(&bstr);
397 hr = StringCbCopyW( Domain, cbDomain, bstr );
415 HANDLE hControlDevice = NULL;
417 hControlDevice = CreateFileW( AFS_SYMLINK_W,
418 GENERIC_READ | GENERIC_WRITE,
419 FILE_SHARE_READ | FILE_SHARE_WRITE,
425 if( hControlDevice == INVALID_HANDLE_VALUE)
427 hControlDevice = NULL;
428 DebugEvent("OpenRedirector Failed to open control device error: %d",
432 return hControlDevice;
436 AFSCreatePAG(PLUID lpLogonId)
438 BOOLEAN bRet = FALSE;
439 HANDLE hControlDevice = NULL;
440 DWORD dwCopyBytes = 0;
441 AFSAuthGroupRequestCB *pAuthGroup = NULL;
442 WCHAR * pwchSIDString = NULL;
444 SECURITY_STATUS status;
445 PSECURITY_LOGON_SESSION_DATA plsd = NULL;
447 BOOLEAN bImpersonated = FALSE;
450 unsigned char *pchGUID = NULL;
453 if (LogonSSP(lpLogonId, &ctx)) {
454 DebugEvent("AFSCreatePAG unable to obtain LogonSSP context");
458 status = ImpersonateSecurityContext(&ctx);
459 if (status == SEC_E_OK)
461 bImpersonated = TRUE;
463 rv = LsaGetLogonSessionData(lpLogonId, &plsd);
466 if( !ConvertSidToStringSidW( plsd->Sid,
469 DebugEvent("AFSCreatePAG Failed to convert sid to string Error %08X", GetLastError());
473 pAuthGroup = (AFSAuthGroupRequestCB *)LocalAlloc( LPTR, 0x1000);
475 if( pAuthGroup == NULL)
477 DebugEvent0("AFSCreatePAG Failed auth group allocation");
481 memset( pAuthGroup, 0, 0x1000);
483 pAuthGroup->SIDLength = (USHORT) (wcslen( pwchSIDString) * sizeof( WCHAR));
484 pAuthGroup->SessionId = plsd->Session;
486 memcpy( pAuthGroup->SIDString,
488 pAuthGroup->SIDLength);
490 RevertSecurityContext(&ctx);
492 bImpersonated = FALSE;
494 hControlDevice = OpenRedirector();
496 if( hControlDevice == NULL)
498 DebugEvent0("AFSCreatePAG Failed to open redirector");
502 bRet = DeviceIoControl( hControlDevice,
503 IOCTL_AFS_AUTHGROUP_SID_QUERY,
513 DebugEvent("AFSCreatePAG Failed IOCTL_AFS_AUTHGROUP_SID_QUERY Error 0x%08X", GetLastError());
517 if( UuidToString( (UUID *)&stAuthGroup,
518 &pchGUID) == RPC_S_OK)
520 DebugEvent("AFSCreatePAG Initial AuthGroup %s\n", pchGUID);
521 RpcStringFree( &pchGUID);
525 DebugEvent0("AFSCreatePAG Failed to convert GUID to string\n");
529 ImpersonateSecurityContext(&ctx); bImpersonated = TRUE;
531 bRet = DeviceIoControl( hControlDevice,
532 IOCTL_AFS_AUTHGROUP_SID_QUERY,
542 DebugEvent("AFSCreatePAG Failed IOCTL_AFS_AUTHGROUP_SID_QUERY Impersonation Error 0x%08X", GetLastError());
546 if( UuidToString( (UUID *)&stAuthGroup,
547 &pchGUID) == RPC_S_OK)
549 DebugEvent("AFSCreatePAG Initial Impersonation AuthGroup %s\n", pchGUID);
550 RpcStringFree( &pchGUID);
554 DebugEvent0("AFSCreatePAG Failed to convert GUID to string\n");
558 RevertSecurityContext(&ctx); bImpersonated = FALSE;
561 bRet = DeviceIoControl( hControlDevice,
562 IOCTL_AFS_AUTHGROUP_LOGON_CREATE,
564 sizeof( AFSAuthGroupRequestCB) + pAuthGroup->SIDLength - 1,
572 DebugEvent("AFSCreatePAG Failed IOCTL_AFS_AUTHGROUP_SID_CREATE Error 0x%08X", GetLastError());
576 bRet = DeviceIoControl( hControlDevice,
577 IOCTL_AFS_AUTHGROUP_SID_QUERY,
587 DebugEvent("AFSCreatePAG Failed IOCTL_AFS_AUTHGROUP_SID_QUERY Error 0x%08X", GetLastError());
591 if( UuidToString( (UUID *)&stAuthGroup,
592 &pchGUID) == RPC_S_OK)
594 DebugEvent("AFSCreatePAG New AuthGroup %s\n", pchGUID);
595 RpcStringFree( &pchGUID);
599 DebugEvent0("AFSCreatePAG Failed to convert GUID to string\n");
604 ImpersonateSecurityContext(&ctx);
606 bRet = DeviceIoControl( hControlDevice,
607 IOCTL_AFS_AUTHGROUP_SID_QUERY,
617 DebugEvent("AFSCreatePAG Failed IOCTL_AFS_AUTHGROUP_SID_QUERY Impersonation Error 0x%08X", GetLastError());
621 if( UuidToString( (UUID *)&stAuthGroup,
622 &pchGUID) == RPC_S_OK)
624 DebugEvent("AFSCreatePAG New Impersonation AuthGroup %s\n", pchGUID);
625 RpcStringFree( &pchGUID);
629 DebugEvent0("AFSCreatePAG Failed to convert GUID to string\n");
633 RevertSecurityContext(&ctx);
637 DebugEvent("AFSCreatePAG LsaGetLogonSessionData failed [%lX]", rv);
643 DebugEvent("AFSCreatePAG cannot impersonate context [%lX]", status);
650 RevertSecurityContext(&ctx);
652 DeleteSecurityContext(&ctx);
655 LsaFreeReturnBuffer(plsd);
657 if ( hControlDevice != NULL)
658 CloseHandle( hControlDevice);
660 if( pwchSIDString != NULL)
661 LocalFree( pwchSIDString);