2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
10 #include <afsconfig.h>
11 #include <afs/param.h>
16 #include <sys/types.h>
21 #define SECURITY_WIN32
30 #include <afs/pioctl_nt.h>
31 #include <afs/kautils.h>
34 #include "cm_config.h"
37 #include "lanahelper.h"
39 /* Allocated in Windows Driver Kit */
40 #ifndef WNNC_NET_OPENAFS
41 #define WNNC_NET_OPENAFS 0x00390000
44 #include <WINNT\afsreg.h>
46 DWORD TraceOption = 0;
51 #define AFS_LOGON_EVENT_NAME TEXT("AFS Logon")
53 void DebugEvent0(char *a)
55 HANDLE h; char *ptbuf[1];
57 if (!Debug && !ISLOGONTRACE(TraceOption))
62 OutputDebugString("\r\n");
65 h = RegisterEventSource(NULL, AFS_LOGON_EVENT_NAME);
66 if (h != INVALID_HANDLE_VALUE) {
68 ReportEvent(h, EVENTLOG_INFORMATION_TYPE, 0, 1008, NULL, 1, 0, (const char **)ptbuf, NULL);
69 DeregisterEventSource(h);
74 void DebugEvent(char *b,...)
77 char *ptbuf[1], buf[MAXBUF_+1];
80 if (!Debug && !ISLOGONTRACE(TraceOption))
84 StringCbVPrintf(buf, MAXBUF_+1,b,marker);
88 OutputDebugString(buf);
89 OutputDebugString("\r\n");
92 h = RegisterEventSource(NULL, AFS_LOGON_EVENT_NAME);
93 if (h != INVALID_HANDLE_VALUE) {
95 ReportEvent(h, EVENTLOG_INFORMATION_TYPE, 0, 1008, NULL, 1, 0, (const char **)ptbuf, NULL);
96 DeregisterEventSource(h);
101 static HANDLE hInitMutex = NULL;
102 static BOOL bInit = FALSE;
104 BOOLEAN APIENTRY DllEntryPoint(HANDLE dll, DWORD reason, PVOID reserved)
110 case DLL_PROCESS_ATTACH:
111 /* Initialization Mutex */
113 hInitMutex = CreateMutex(NULL, FALSE, NULL);
115 WSAStartup( MAKEWORD(2,2), &wsaData );
118 case DLL_PROCESS_DETACH:
120 CloseHandle(hInitMutex);
125 case DLL_THREAD_ATTACH:
126 case DLL_THREAD_DETACH:
128 /* Everything else succeeds but does nothing. */
135 void AfsLogonInit(void)
137 if ( bInit == FALSE ) {
138 if ( WaitForSingleObject( hInitMutex, INFINITE ) == WAIT_OBJECT_0 ) {
139 /* initAFSDirPath() initializes an array and sets a
140 * flag so that the initialization can only occur
141 * once. No cleanup will be done when the DLL is
142 * unloaded so the initialization will not be
143 * performed again on a subsequent reload
147 /* ka_Init initializes a number of error tables.
148 * and then calls ka_CellConfig() which grabs
149 * an afsconf_dir structure via afsconf_Open().
150 * Upon a second attempt to call ka_CellConfig()
151 * the structure will be released with afsconf_Close()
152 * and then re-opened. Could this corrupt memory?
154 * We only need this if we are not using KFW.
156 if (!KFW_is_available())
160 ReleaseMutex(hInitMutex);
164 CHAR *GenRandomName(CHAR *pbuf)
167 srand( (unsigned)time( NULL ) );
168 for (i=0;i<MAXRANDOMNAMELEN-1;i++)
169 pbuf[i]='a'+(rand() % 26);
170 pbuf[MAXRANDOMNAMELEN-1]=0;
174 BOOLEAN AFSWillAutoStart(void)
179 BOOLEAN result = FALSE;
180 LPQUERY_SERVICE_CONFIG pConfig = NULL;
184 /* Open services manager */
185 scm = OpenSCManager(NULL, NULL, GENERIC_READ);
186 if (!scm) return FALSE;
188 /* Open AFSD service */
189 svc = OpenService(scm, "TransarcAFSDaemon", SERVICE_QUERY_CONFIG);
193 /* Query AFSD service config, first just to get buffer size */
194 /* Expected to fail, so don't test return value */
195 (void) QueryServiceConfig(svc, NULL, 0, &BufSize);
196 status = GetLastError();
197 if (status != ERROR_INSUFFICIENT_BUFFER)
200 /* Allocate buffer */
201 pConfig = (LPQUERY_SERVICE_CONFIG)GlobalAlloc(GMEM_FIXED,BufSize);
205 /* Query AFSD service config, this time for real */
206 flag = QueryServiceConfig(svc, pConfig, BufSize, &BufSize);
210 /* Is it autostart? */
211 if (pConfig->dwStartType < SERVICE_DEMAND_START)
217 CloseServiceHandle(svc);
219 CloseServiceHandle(scm);
224 DWORD MapAuthError(DWORD code)
227 /* Unfortunately, returning WN_NO_NETWORK results in the MPR abandoning
228 * logon scripts for all credential managers, although they will still
229 * receive logon notifications.
231 * Instead return WN_NET_ERROR (ERROR_UNEXP_NET_ERR) to indicate a
232 * problem with this network.
243 DWORD APIENTRY NPGetCaps(DWORD index)
248 * The purpose of this response is to let the system
249 * know which file system the network provider is associated with
250 * Microsoft issues these values starting from 1 with the exception
251 * of WNNC_CRED_MANAGER which is 0xFFFF. The provider type is
252 * stored in the hiword. Pick a value that is unused.
256 case WNNC_SPEC_VERSION:
257 return WNNC_SPEC_VERSION51;
260 /* Say we are already started, even though we might wait after we receive NPLogonNotify */
269 NetUserGetProfilePath( LPCWSTR Domain, LPCWSTR UserName, char * profilePath,
270 DWORD profilePathLen )
273 LPWSTR ServerName = NULL;
274 LPUSER_INFO_3 p3 = NULL;
276 NetGetAnyDCName(NULL, Domain, (LPBYTE *)&ServerName);
277 /* if NetGetAnyDCName fails, ServerName == NULL
278 * NetUserGetInfo will obtain local user information
280 code = NetUserGetInfo(ServerName, UserName, 3, (LPBYTE *)&p3);
281 if (code == NERR_Success)
283 code = NERR_UserNotFound;
285 if (p3->usri3_profile) {
286 DWORD len = lstrlenW(p3->usri3_profile);
288 /* Convert From Unicode to ANSI (UTF-8 for future) */
289 len = len < profilePathLen ? len : profilePathLen - 1;
290 WideCharToMultiByte(CP_UTF8, 0, p3->usri3_profile, len, profilePath, len, NULL, NULL);
291 profilePath[len] = '\0';
295 NetApiBufferFree(p3);
299 NetApiBufferFree(ServerName);
303 BOOL IsServiceRunning (void)
305 SERVICE_STATUS Status;
307 memset (&Status, 0x00, sizeof(Status));
308 Status.dwCurrentState = SERVICE_STOPPED;
310 if ((hManager = OpenSCManager (NULL, NULL, GENERIC_READ)) != NULL)
313 if ((hService = OpenService (hManager, TEXT("TransarcAFSDaemon"), GENERIC_READ)) != NULL)
315 QueryServiceStatus (hService, &Status);
316 CloseServiceHandle (hService);
319 CloseServiceHandle (hManager);
321 DebugEvent("AFS AfsLogon - Test Service Running Return Code[%x] ?Running[%d]",Status.dwCurrentState,(Status.dwCurrentState == SERVICE_RUNNING));
322 return (Status.dwCurrentState == SERVICE_RUNNING);
325 BOOL IsServiceStartPending (void)
327 SERVICE_STATUS Status;
329 memset (&Status, 0x00, sizeof(Status));
330 Status.dwCurrentState = SERVICE_STOPPED;
332 if ((hManager = OpenSCManager (NULL, NULL, GENERIC_READ)) != NULL)
335 if ((hService = OpenService (hManager, TEXT("TransarcAFSDaemon"), GENERIC_READ)) != NULL)
337 QueryServiceStatus (hService, &Status);
338 CloseServiceHandle (hService);
341 CloseServiceHandle (hManager);
343 DebugEvent("AFS AfsLogon - Test Service Start Pending Return Code[%x] ?Start Pending[%d]",Status.dwCurrentState,(Status.dwCurrentState == SERVICE_START_PENDING));
344 return (Status.dwCurrentState == SERVICE_START_PENDING);
347 BOOL StartTheService (void)
352 if ((hManager = OpenSCManager (NULL, NULL, GENERIC_READ|SERVICE_START)) != NULL)
355 if ((hService = OpenService (hManager, TEXT("TransarcAFSDaemon"), GENERIC_READ|SERVICE_START)) != NULL)
357 StartService (hService, 0, NULL);
358 gle = GetLastError();
359 CloseServiceHandle (hService);
361 gle = GetLastError();
363 CloseServiceHandle (hManager);
365 DebugEvent("AFS AfsLogon - Service Start Return Code[0x%x]",gle);
370 * LOOKUPKEYCHAIN: macro to look up the value in the list of keys in order until it's found
371 * v:variable to receive value (reference type).
373 * d:default, in case the value isn't on any of the keys
376 #define LOOKUPKEYCHAIN(v,t,d,n) \
378 rv = ~ERROR_SUCCESS; \
381 dwSize = sizeof(v); \
382 rv = RegQueryValueEx(hkUserMap, n, 0, &dwType, (LPBYTE) &(v), &dwSize); \
383 if(rv == ERROR_SUCCESS || rv == ERROR_MORE_DATA) \
384 DebugEvent(#v " found in hkUserMap with type [%d]", dwType); \
386 if(hkDom && ((rv != ERROR_SUCCESS && rv != ERROR_MORE_DATA) || dwType != t)) { \
387 dwSize = sizeof(v); \
388 rv = RegQueryValueEx(hkDom, n, 0, &dwType, (LPBYTE) &(v), &dwSize); \
389 if(rv == ERROR_SUCCESS || rv == ERROR_MORE_DATA) \
390 DebugEvent(#v " found in hkDom with type [%d]", dwType); \
392 if(hkDoms && ((rv != ERROR_SUCCESS && rv != ERROR_MORE_DATA) || dwType != t)) { \
393 dwSize = sizeof(v); \
394 rv = RegQueryValueEx(hkDoms, n, 0, &dwType, (LPBYTE) &(v), &dwSize); \
395 if(rv == ERROR_SUCCESS || rv == ERROR_MORE_DATA) \
396 DebugEvent(#v " found in hkDoms with type [%d]", dwType); \
398 if(hkNp && ((rv != ERROR_SUCCESS && rv != ERROR_MORE_DATA) || dwType != t)) { \
399 dwSize = sizeof(v); \
400 rv = RegQueryValueEx(hkNp, n, 0, &dwType, (LPBYTE) &(v), &dwSize); \
401 if(rv == ERROR_SUCCESS || rv == ERROR_MORE_DATA) \
402 DebugEvent(#v " found in hkNp with type [%d]", dwType); \
404 if((rv != ERROR_SUCCESS && rv != ERROR_MORE_DATA) || dwType != t) { \
406 DebugEvent0(#v " being set to default"); \
412 * FINDKEYCHAIN1: macro to find the value in the list of keys in order until it's found.
413 * Sets hkTemp variable to the key the value is found in.
417 #define FINDKEYCHAIN1(t,n) \
420 rv = ~ERROR_SUCCESS; \
424 rv = RegQueryValueEx(hkUserMap, n, 0, &dwType, NULL, &dwSize); \
425 if((rv == ERROR_SUCCESS || rv == ERROR_MORE_DATA) && dwType == t) { \
426 DebugEvent(#n " found in hkUserMap with type [%d]", dwType); \
427 hkTemp = hkUserMap; \
430 if(hkDom && ((rv != ERROR_SUCCESS && rv != ERROR_MORE_DATA) || dwType != t)) { \
432 rv = RegQueryValueEx(hkDom, n, 0, &dwType, NULL, &dwSize); \
433 if((rv == ERROR_SUCCESS || rv == ERROR_MORE_DATA) && dwType == t) { \
434 DebugEvent(#n " found in hkDom with type [%d]", dwType); \
438 if(hkDoms && ((rv != ERROR_SUCCESS && rv != ERROR_MORE_DATA) || dwType != t)) { \
440 rv = RegQueryValueEx(hkDoms, n, 0, &dwType, NULL, &dwSize); \
441 if((rv == ERROR_SUCCESS || rv == ERROR_MORE_DATA) && dwType == t) { \
442 DebugEvent(#n " found in hkDoms with type [%d]", dwType); \
446 if(hkNp && ((rv != ERROR_SUCCESS && rv != ERROR_MORE_DATA) || dwType != t)) { \
448 rv = RegQueryValueEx(hkNp, n, 0, &dwType, NULL, &dwSize); \
449 if((rv == ERROR_SUCCESS || rv == ERROR_MORE_DATA) && dwType == t) { \
450 DebugEvent(#n " found in hkNp with type [%d]", dwType); \
454 if((rv != ERROR_SUCCESS && rv != ERROR_MORE_DATA) || dwType != t) { \
455 DebugEvent0(#n " not found"); \
460 * FINDKEYCHAIN2: macro to find the value in the list of keys in order until it's found.
461 * Sets hkTemp variable to the key the value is found in.
466 #define FINDKEYCHAIN2(t1,t2,n) \
469 rv = ~ERROR_SUCCESS; \
473 rv = RegQueryValueEx(hkUserMap, n, 0, &dwType, NULL, &dwSize); \
474 if((rv == ERROR_SUCCESS || rv == ERROR_MORE_DATA) && (dwType == t1 || dwType == t2)) { \
475 DebugEvent(#n " found in hkUserMap with type [%d]", dwType); \
476 hkTemp = hkUserMap; \
479 if(hkDom && ((rv != ERROR_SUCCESS && rv != ERROR_MORE_DATA) || (dwType != t1 && dwType != t2))) { \
481 rv = RegQueryValueEx(hkDom, n, 0, &dwType, NULL, &dwSize); \
482 if((rv == ERROR_SUCCESS || rv == ERROR_MORE_DATA) && (dwType == t1 || dwType == t2)) {\
483 DebugEvent(#n " found in hkDom with type [%d]", dwType); \
487 if(hkDoms && ((rv != ERROR_SUCCESS && rv != ERROR_MORE_DATA) || (dwType != t1 && dwType != t2))) { \
489 rv = RegQueryValueEx(hkDoms, n, 0, &dwType, NULL, &dwSize); \
490 if((rv == ERROR_SUCCESS || rv == ERROR_MORE_DATA) && (dwType == t1 || dwType == t2)) { \
491 DebugEvent(#n " found in hkDoms with type [%d]", dwType); \
495 if(hkNp && ((rv != ERROR_SUCCESS && rv != ERROR_MORE_DATA) || (dwType != t1 && dwType != t2))) { \
497 rv = RegQueryValueEx(hkNp, n, 0, &dwType, NULL, &dwSize); \
498 if((rv == ERROR_SUCCESS || rv == ERROR_MORE_DATA) && (dwType == t1 || dwType == t2)) { \
499 DebugEvent(#n " found in hkNp with type [%d]", dwType); \
503 if((rv != ERROR_SUCCESS && rv != ERROR_MORE_DATA) || (dwType != t1 && dwType != t2)) { \
504 DebugEvent0(#n " not found"); \
510 * Get domain specific configuration info. We return void
511 * because if anything goes wrong we just return defaults.
514 GetDomainLogonOptions( PLUID lpLogonId, BOOLEAN bKerberos,
515 char * username, char * domain, LogonOptions_t *opt ) {
516 HKEY hkParm = NULL; /* Service parameter */
517 HKEY hkNp = NULL; /* network provider key */
518 HKEY hkDoms = NULL; /* domains key */
519 HKEY hkDom = NULL; /* DOMAINS/domain key */
520 HKEY hkUserMap = NULL; /* User mapping key */
526 char computerName[MAX_COMPUTERNAME_LENGTH + 1]="";
527 char *effDomain = NULL;
529 memset(opt, 0, sizeof(LogonOptions_t));
530 DebugEvent("In GetDomainLogonOptions for user [%s] in domain [%s]", username, domain);
532 /* If the domain is the same as the Netbios computer name, we use the LOCALHOST domain name. */
533 opt->flags = LOGON_FLAG_REMOTE;
535 dwSize = MAX_COMPUTERNAME_LENGTH + 1;
536 if(GetComputerName(computerName, &dwSize)) {
537 if(!cm_stricmp_utf8(computerName, domain)) {
538 effDomain = "LOCALHOST";
539 opt->flags = LOGON_FLAG_LOCAL;
542 if (effDomain == NULL)
546 rv = RegOpenKeyEx( HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY, 0, KEY_READ, &hkParm );
547 if(rv != ERROR_SUCCESS) {
549 DebugEvent("GetDomainLogonOption: Can't open parms key [%d]", rv);
552 rv = RegOpenKeyEx( HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PROVIDER_SUBKEY, 0, KEY_READ, &hkNp );
553 if(rv != ERROR_SUCCESS) {
555 DebugEvent("GetDomainLogonOptions: Can't open NP key [%d]", rv);
559 rv = RegOpenKeyEx( hkNp, REG_CLIENT_DOMAINS_SUBKEY, 0, KEY_READ, &hkDoms );
560 if( rv != ERROR_SUCCESS ) {
562 DebugEvent("GetDomainLogonOptions: Can't open Domains key [%d]", rv);
566 if(hkDoms && effDomain) {
567 rv = RegOpenKeyEx( hkDoms, effDomain, 0, KEY_READ, &hkDom );
568 if( rv != ERROR_SUCCESS ) {
570 DebugEvent("GetDomainLogonOptions: Can't open domain key for [%s] [%d]", effDomain, rv);
572 /* If none of the domains match, we shouldn't use the domain key either */
576 rv = RegOpenKeyEx( hkDom, username, 0, KEY_READ, &hkUserMap);
577 if ( rv != ERROR_SUCCESS ) {
579 DebugEvent("GetDomainLogonOptions: Can't open usermap key for [%s]@[%s] [%d]",
580 username, effDomain, rv);
584 DebugEvent0("Not opening domain key");
588 * Most individual values can be specified on the user mapping key, the domain key,
589 * the domains key or in the net provider key. They fail over in that order.
590 * If none is found, we just use the defaults.
594 LOOKUPKEYCHAIN(opt->LogonOption, REG_DWORD, DEFAULT_LOGON_OPTION, REG_CLIENT_LOGON_OPTION_PARM);
596 /* FailLoginsSilently */
597 dwSize = sizeof(dwDummy);
598 rv = RegQueryValueEx(hkParm, REG_CLIENT_FAIL_SILENTLY_PARM, 0, &dwType, (LPBYTE) &dwDummy, &dwSize);
599 if (rv != ERROR_SUCCESS)
600 LOOKUPKEYCHAIN(dwDummy, REG_DWORD, DEFAULT_FAIL_SILENTLY, REG_CLIENT_FAIL_SILENTLY_PARM);
601 opt->failSilently = dwDummy ? 1 :0;
604 LOOKUPKEYCHAIN(opt->retryInterval, REG_DWORD, DEFAULT_RETRY_INTERVAL, REG_CLIENT_RETRY_INTERVAL_PARM);
607 LOOKUPKEYCHAIN(opt->sleepInterval, REG_DWORD, DEFAULT_SLEEP_INTERVAL, REG_CLIENT_SLEEP_INTERVAL_PARM);
609 if(!ISLOGONINTEGRATED(opt->LogonOption)) {
610 DebugEvent0("Integrated logon disabled");
611 goto cleanup; /* no need to lookup the logon script */
614 /* come up with SMB username */
616 /* username and domain for logon session is not necessarily the same as
617 username and domain passed into network provider. */
618 PSECURITY_LOGON_SESSION_DATA plsd=NULL;
619 char lsaUsername[MAX_USERNAME_LENGTH]="";
620 char lsaDomain[MAX_DOMAIN_LENGTH]="";
624 Status = LsaGetLogonSessionData(lpLogonId, &plsd);
625 if ( FAILED(Status) || plsd == NULL ) {
626 DebugEvent("LsaGetLogonSessionData failed [0x%x]", Status);
630 if (!UnicodeStringToANSI(plsd->UserName, lsaUsername, MAX_USERNAME_LENGTH))
633 if (!UnicodeStringToANSI(plsd->LogonDomain, lsaDomain, MAX_DOMAIN_LENGTH))
636 DebugEvent("PLSD username[%s] domain[%s]",lsaUsername,lsaDomain);
638 if(SUCCEEDED(StringCbLength(lsaUsername, MAX_USERNAME_LENGTH, &tlen)))
643 if(SUCCEEDED(StringCbLength(lsaDomain, MAX_DOMAIN_LENGTH, &tlen)))
650 opt->smbName = malloc(len);
651 if (opt->smbName == NULL)
654 StringCbCopy(opt->smbName, len, lsaDomain);
655 StringCbCat(opt->smbName, len, "\\");
656 StringCbCat(opt->smbName, len, lsaUsername);
658 strlwr(opt->smbName);
662 LsaFreeReturnBuffer(plsd);
665 if (opt->smbName == NULL) {
668 DebugEvent("Constructing username using [%s] and [%s]",
671 len = strlen(username) + strlen(domain) + 2;
673 opt->smbName = malloc(len);
674 if (opt->smbName == NULL)
677 StringCbCopy(opt->smbName, len, domain);
678 StringCbCat(opt->smbName, len, "\\");
679 StringCbCat(opt->smbName, len, username);
681 strlwr(opt->smbName);
684 DebugEvent0("Looking up logon script");
686 /* First find out where the key is */
687 FINDKEYCHAIN2(REG_SZ, REG_EXPAND_SZ, REG_CLIENT_LOGON_SCRIPT_PARM);
688 /* Note that the LogonScript in the NP key not used. */
693 WCHAR *regscript = NULL;
694 WCHAR *regexscript = NULL;
695 WCHAR *regexuscript = NULL;
696 WCHAR *wuname = NULL;
701 StringCbLength(opt->smbName, MAX_USERNAME_LENGTH, &len);
704 wuname = malloc(len * sizeof(WCHAR));
706 goto doneLogonScript;
707 MultiByteToWideChar(CP_ACP,0,opt->smbName,-1,wuname,(int)(len*sizeof(WCHAR)));
709 DebugEvent("Username is set for [%S]", wuname);
711 /* dwSize still has the size of the required buffer in bytes. */
712 regscript = malloc(dwSize);
714 goto doneLogonScript;
715 rv = RegQueryValueExW(hkTemp, REG_CLIENT_LOGON_SCRIPT_PARMW, 0, &dwType, (LPBYTE) regscript, &dwSize);
716 if(rv != ERROR_SUCCESS) {/* what the ..? */
717 DebugEvent("Can't look up logon script rv [%d] size [%d] gle %d",rv, dwSize, GetLastError());
718 goto doneLogonScript;
721 DebugEvent("Found logon script [%S]", regscript);
723 if(dwType == REG_EXPAND_SZ) {
726 dwSize += MAX_PATH * sizeof(WCHAR); /* make room for environment expansion. */
727 regexscript = malloc(dwSize);
729 goto doneLogonScript;
730 dwReq = ExpandEnvironmentStringsW(regscript, regexscript, dwSize / sizeof(WCHAR));
732 regscript = regexscript;
734 if(dwReq > (dwSize / sizeof(WCHAR))) {
735 DebugEvent0("Overflow while expanding environment strings.");
736 goto doneLogonScript;
740 DebugEvent("After expanding env strings [%S]", regscript);
742 if(wcsstr(regscript, L"%s")) {
743 dwSize += (DWORD)(len * sizeof(WCHAR)); /* make room for username expansion */
744 regexuscript = (WCHAR *) LocalAlloc(LMEM_FIXED, dwSize);
746 goto doneLogonScript;
747 hr = StringCbPrintfW(regexuscript, dwSize, regscript, wuname);
749 regexuscript = (WCHAR *) LocalAlloc(LMEM_FIXED, dwSize);
751 goto doneLogonScript;
752 hr = StringCbCopyW(regexuscript, dwSize, regscript);
755 DebugEvent("After expanding username [%S]", regexuscript);
758 opt->logonScript = regexuscript;
760 LocalFree(regexuscript);
763 if(wuname) free(wuname);
764 if(regscript) free(regscript);
765 if(regexscript) free(regexscript);
768 DebugEvent0("Looking up TheseCells");
770 /* First find out where the key is */
771 FINDKEYCHAIN1(REG_MULTI_SZ, REG_CLIENT_THESE_CELLS_PARM);
774 CHAR * thesecells = NULL, *p;
776 /* dwSize still has the size of the required buffer in bytes. */
777 thesecells = malloc(dwSize*2);
782 rv = RegQueryValueEx(hkTemp, REG_CLIENT_THESE_CELLS_PARM, 0, NULL, (LPBYTE) thesecells, &dwSize);
783 if(rv != ERROR_SUCCESS) {/* what the ..? */
784 DebugEvent("Can't look up TheseCells rv [%d] size [%d] gle [%d]",rv, dwSize, GetLastError());
788 /* TheseCells is a REG_MULTI_SZ */
789 if ( thesecells && thesecells[0]) {
790 for ( p=thesecells; *p; p += (strlen(p) + 1)) {
791 DebugEvent("Found TheseCells [%s]", p);
793 opt->theseCells = thesecells;
796 DebugEvent("TheseCells [REG_MULTI_SZ] not found");
800 if (thesecells) free(thesecells);
803 DebugEvent0("Looking up Realm");
805 /* First find out where the key is */
806 FINDKEYCHAIN1(REG_SZ, REG_CLIENT_REALM_PARM);
811 /* dwSize still has the size of the required buffer in bytes. */
812 realm = malloc(dwSize*2);
817 rv = RegQueryValueEx(hkTemp, REG_CLIENT_REALM_PARM, 0, NULL, (LPBYTE) realm, &dwSize);
818 if(rv != ERROR_SUCCESS) {/* what the ..? */
819 DebugEvent("Can't look up Realm rv [%d] size [%d] gle [%d]",rv, dwSize, GetLastError());
823 DebugEvent("Found Realm [%s]", realm);
824 if (strcmp(realm, domain)) {
830 if (realm) free(realm);
832 if ( !ISREMOTE(opt->flags) )
833 opt->realm = KFW_get_default_realm();
836 /* Obtain the username mapping (if any) */
842 rv = RegQueryValueEx(hkUserMap, REG_CLIENT_USERNAME_PARM, 0, &dwType, NULL, &dwSize);
843 if((rv == ERROR_SUCCESS || rv == ERROR_MORE_DATA) && dwType == REG_SZ) {
844 CHAR * usermap = NULL;
846 /* dwSize still has the size of the required buffer in bytes. */
847 usermap = malloc(dwSize*2);
852 rv = RegQueryValueEx(hkTemp, REG_CLIENT_USERNAME_PARM, 0, NULL, (LPBYTE) usermap, &dwSize);
853 if(rv != ERROR_SUCCESS) {/* what the ..? */
854 DebugEvent("Can't look up Username rv [%d] size [%d] gle [%d]", rv, dwSize, GetLastError());
858 DebugEvent("Found Username [%s]", usermap);
859 if (strcmp(usermap, username)) {
860 opt->username = usermap;
865 if (usermap) free(usermap);
869 /* Determine if the username@realm is the LSA Kerberos principal (if any) */
870 if (!opt->username && !opt->realm && bKerberos) {
871 opt->flags |= LOGON_FLAG_LSA;
875 if(hkNp) RegCloseKey(hkNp);
876 if(hkDom) RegCloseKey(hkDom);
877 if(hkDoms) RegCloseKey(hkDoms);
878 if(hkUserMap) RegCloseKey(hkUserMap);
879 if(hkParm) RegCloseKey(hkParm);
882 #undef LOOKUPKEYCHAIN
886 /* Try to find out which cell the given path is in. We must retain
887 the contents of *cell in case of failure. *cell is assumed to be
888 at least cellLen chars */
889 DWORD GetFileCellName(char * path, char * cell, size_t cellLen) {
890 struct ViceIoctl blob;
891 char tcell[MAX_PATH];
895 blob.out_size = MAX_PATH;
898 code = pioctl(path, VIOC_FILE_CELL_NAME, &blob, 1);
901 strncpy(cell, tcell, cellLen);
902 cell[cellLen - 1] = '\0';
910 UnicodeStringToANSI(UNICODE_STRING uInputString, LPSTR lpszOutputString, int nOutStringLen)
914 GetCPInfo(CP_ACP, &CodePageInfo);
916 if (CodePageInfo.MaxCharSize > 1)
917 // Only supporting non-Unicode strings
920 if (uInputString.Buffer && ((LPBYTE) uInputString.Buffer)[1] == '\0')
922 // Looks like unicode, better translate it
923 // UNICODE_STRING specifies the length of the buffer string in Bytes not WCHARS
924 WideCharToMultiByte(CP_ACP, 0, (LPCWSTR) uInputString.Buffer, uInputString.Length/2,
925 lpszOutputString, nOutStringLen-1, NULL, NULL);
926 lpszOutputString[min(uInputString.Length/2,nOutStringLen-1)] = '\0';
930 lpszOutputString[0] = '\0';
932 } // UnicodeStringToANSI
935 ObtainTokens( PLUID lpLogonId,
936 LogonOptions_t *pOpt,
945 CtxtHandle LogonContext;
948 LogonSSP(lpLogonId, &LogonContext);
949 ImpersonateSecurityContext(&LogonContext);
951 if ( KFW_is_available() ) {
952 char * principal, *p;
955 SetEnvironmentVariable(DO_NOT_REGISTER_VARNAME, "");
957 if (ISLSA(pOpt->flags)) {
958 KFW_import_windows_lsa();
961 StringCchLength(pOpt->realm ? pOpt->realm : realm, MAX_DOMAIN_LENGTH, &tlen);
963 StringCchLength(uname, MAX_USERNAME_LENGTH, &tlen);
966 /* tlen is now the length of uname in characters */
967 principal = (char *)malloc(len * sizeof(char));
969 StringCchCopy(principal, len, uname);
970 p = principal + tlen;
972 StringCchCopy(p, len - tlen -1, pOpt->realm ? pOpt->realm : realm);
973 code = KFW_AFS_get_cred(principal, cell, password, 0, pOpt->smbName, preason);
974 DebugEvent("KFW_AFS_get_cred uname=[%s] smbname=[%s] cell=[%s] code=[%d]",
975 principal, pOpt->smbName, cell, code);
977 if (code == 0 && pOpt->theseCells) {
978 p = pOpt->theseCells;
980 if ( cm_stricmp_utf8(p, cell) ) {
981 SetEnvironmentVariable(DO_NOT_REGISTER_VARNAME, "");
982 code2 = KFW_AFS_get_cred(principal, p, password, 0, pOpt->smbName, preason);
983 SetEnvironmentVariable(DO_NOT_REGISTER_VARNAME, NULL);
984 DebugEvent("KFW_AFS_get_cred uname=[%s] smbname=[%s] cell=[%s] code=[%d]",
985 principal, pOpt->smbName, p, code2);
993 SetEnvironmentVariable(DO_NOT_REGISTER_VARNAME, NULL);
996 code = ka_UserAuthenticateGeneral2(KA_USERAUTH_VERSION+KA_USERAUTH_AUTHENT_LOGON,
997 uname, "", cell, password, pOpt->smbName, 0, &pw_exp, 0,
999 DebugEvent("AFS AfsLogon - (INTEGRATED only)ka_UserAuthenticateGeneral2 Code[%x] uname[%s] smbname=[%s] Cell[%s] PwExp=[%d] Reason=[%s]",
1000 code, uname, pOpt->smbName, cell, pw_exp, *preason ? *preason : "");
1003 RevertSecurityContext(&LogonContext);
1004 DeleteSecurityContext(&LogonContext);
1012 LPCWSTR lpAuthentInfoType,
1013 LPVOID lpAuthentInfo,
1014 LPCWSTR lpPreviousAuthentInfoType,
1015 LPVOID lpPreviousAuthentInfo,
1016 LPWSTR lpStationName,
1017 LPVOID StationHandle,
1018 LPWSTR *lpLogonScript)
1020 char uname[MAX_USERNAME_LENGTH]="";
1021 char password[MAX_PASSWORD_LENGTH]="";
1022 char logonDomain[MAX_DOMAIN_LENGTH]="";
1023 char cell[256]="<non-integrated logon>";
1024 char homePath[MAX_PATH]="";
1025 char szLogonId[128] = "";
1027 MSV1_0_INTERACTIVE_LOGON *IL;
1034 BOOLEAN interactive;
1035 BOOLEAN domainKerberos = FALSE;
1037 DWORD LSPtype, LSPsize;
1040 HWND hwndOwner = (HWND)StationHandle;
1042 BOOLEAN afsWillAutoStart;
1044 BOOLEAN lowercased_name = TRUE;
1046 LogonOptions_t opt; /* domain specific logon options */
1050 /* Are we interactive? */
1051 interactive = (wcsicmp(lpStationName, L"WinSta0") == 0);
1053 #ifdef DISABLE_NON_INTERACTIVE
1054 /* Do not do anything if the logon session is not interactive. */
1059 (void) RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY,
1060 0, KEY_QUERY_VALUE, &NPKey);
1061 LSPsize=sizeof(TraceOption);
1062 RegQueryValueEx(NPKey, REG_CLIENT_TRACE_OPTION_PARM, NULL,
1063 &LSPtype, (LPBYTE)&TraceOption, &LSPsize);
1065 RegCloseKey (NPKey);
1067 (void) RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PROVIDER_SUBKEY,
1068 0, KEY_QUERY_VALUE, &NPKey);
1069 LSPsize=sizeof(Debug);
1070 RegQueryValueEx(NPKey, REG_CLIENT_DEBUG_PARM, NULL,
1071 &LSPtype, (LPBYTE)&Debug, &LSPsize);
1073 RegCloseKey (NPKey);
1075 DebugEvent("NPLogonNotify - LoginId(%d,%d)", lpLogonId->HighPart, lpLogonId->LowPart);
1077 /* Make sure the AFS Libraries are initialized */
1080 /* Initialize Logon Script to none */
1081 *lpLogonScript=NULL;
1083 /* MSV1_0_INTERACTIVE_LOGON and KERB_INTERACTIVE_LOGON are equivalent for
1086 domainKerberos = !wcsicmp(lpAuthentInfoType,L"Kerberos:Interactive");
1088 if ( wcsicmp(lpAuthentInfoType,L"MSV1_0:Interactive") &&
1091 DebugEvent("Unsupported Authentication Info Type: %S",
1096 IL = (MSV1_0_INTERACTIVE_LOGON *) lpAuthentInfo;
1098 /* Convert from Unicode to ANSI */
1100 if (!UnicodeStringToANSI(IL->UserName, uname, MAX_USERNAME_LENGTH) ||
1101 !UnicodeStringToANSI(IL->LogonDomainName, logonDomain, MAX_DOMAIN_LENGTH) ||
1102 !UnicodeStringToANSI(IL->Password, password, MAX_PASSWORD_LENGTH))
1106 * The AD logon domain can be provided in the IL->LogonDomainName field
1107 * or as part of the IL->UserName field or both. If the IL->UserName
1108 * field contains a domain:
1109 * a) if there is no IL->LogonDomainName, use it as the domain
1110 * b) strip it from the username as we may combined the name with
1111 * another realm based upon our configuration
1113 ctemp = strchr(uname, '@');
1115 DebugEvent("Username contains a realm: %s", uname);
1118 StringCchCopy(logonDomain, MAX_DOMAIN_LENGTH, ctemp);
1124 GetDomainLogonOptions( lpLogonId, domainKerberos, uname, logonDomain, &opt);
1126 retryInterval = opt.retryInterval;
1127 sleepInterval = opt.sleepInterval;
1128 *lpLogonScript = opt.logonScript;
1130 if (retryInterval < sleepInterval)
1131 sleepInterval = retryInterval;
1133 DebugEvent("Got logon script: [%S]", opt.logonScript);
1135 afsWillAutoStart = AFSWillAutoStart();
1137 DebugEvent("LogonOption[%x], Service AutoStart[%d]",
1138 opt.LogonOption,afsWillAutoStart);
1140 /* Check for zero length password if integrated logon*/
1141 if ( ISLOGONINTEGRATED(opt.LogonOption) ) {
1142 if ( password[0] == 0 ) {
1143 DebugEvent0("Password is the empty string");
1145 reason = "zero length password is illegal";
1149 /* Get cell name if doing integrated logon.
1150 We might overwrite this if we are logging into an AD realm and we find out that
1151 the user's home dir is in some other cell. */
1152 DebugEvent0("About to call cm_GetRootCellName()");
1153 code = cm_GetRootCellName(cell);
1155 DebugEvent0("Unable to obtain Root Cell");
1157 reason = "unknown cell";
1159 DebugEvent("Default cell is %s", cell);
1163 /* We get the user's home directory path, if applicable, though we can't lookup the
1164 cell right away because the client service may not have started yet. This call
1165 also sets the AD_REALM flag in opt.flags if applicable. */
1166 if (ISREMOTE(opt.flags)) {
1167 DebugEvent0("Is Remote");
1168 GetAdHomePath(homePath,MAX_PATH,lpLogonId,&opt);
1172 AFSCreatePAG(lpLogonId);
1174 if (afsWillAutoStart) {
1176 * If the service is configured for auto start but hasn't started yet,
1179 if (!(IsServiceRunning() || IsServiceStartPending()))
1182 /* loop until AFS is started or fails. */
1183 while ( IsServiceStartPending() ) {
1187 while (IsServiceRunning() && code != KTC_NOCM && code != KTC_NOCMRPC && code != KTC_NOCELL) {
1188 DebugEvent("while(autostart) LogonOption[%x], Service AutoStart[%d]",
1189 opt.LogonOption,afsWillAutoStart);
1191 if (ISADREALM(opt.flags)) {
1192 code = GetFileCellName(homePath,cell,256);
1194 DebugEvent("profile path [%s] is in cell [%s]",homePath,cell);
1197 * Don't bail out if GetFileCellName failed.
1198 * The home dir may not be in AFS after all.
1203 /* if Integrated Logon */
1204 if (ISLOGONINTEGRATED(opt.LogonOption))
1206 code = ObtainTokens( lpLogonId, &opt, opt.username ? opt.username : uname,
1207 opt.realm ? opt.realm : logonDomain, cell, password, &reason);
1208 if ( code && code != KTC_NOCM && code != KTC_NOCMRPC && !lowercased_name && !opt.username) {
1209 for ( ctemp = uname; *ctemp ; ctemp++) {
1210 *ctemp = tolower(*ctemp);
1212 lowercased_name = TRUE;
1216 /* is service started yet?*/
1218 /* If we've failed because the client isn't running yet and the
1219 * client is set to autostart (and therefore it makes sense for
1220 * us to wait for it to start) then sleep a while and try again.
1221 * If the error was something else, then give up. */
1222 if (code != KTC_NOCM && code != KTC_NOCMRPC)
1226 /*JUST check to see if its running*/
1227 if (IsServiceRunning())
1229 if (!IsServiceStartPending()) {
1231 reason = "AFS Service start failed";
1236 /* If the retry interval has expired and we still aren't
1237 * logged in, then just give up if we are not in interactive
1238 * mode or the failSilently flag is set, otherwise let the
1239 * user know we failed and give them a chance to try again. */
1240 if (retryInterval <= 0) {
1241 reason = "AFS not running";
1242 if (!interactive || opt.failSilently)
1244 flag = MessageBox(hwndOwner,
1245 "AFS is still starting. Retry?",
1247 MB_ICONQUESTION | MB_RETRYCANCEL);
1248 if (flag == IDCANCEL)
1251 /* Wait just a little while and try again */
1252 retryInterval = opt.retryInterval;
1256 Sleep(sleepInterval * 1000);
1257 retryInterval -= sleepInterval;
1259 DebugEvent0("while loop exited");
1262 /* remove any kerberos 5 tickets currently held by the SYSTEM account
1266 if (ISLOGONINTEGRATED(opt.LogonOption) && KFW_is_available()) {
1267 CtxtHandle LogonContext;
1269 LogonSSP(lpLogonId, &LogonContext);
1270 ImpersonateSecurityContext(&LogonContext);
1273 sprintf(szLogonId,"%d.%d",lpLogonId->HighPart, lpLogonId->LowPart);
1274 DebugEvent("copying cache for %s %s", uname, szLogonId);
1275 KFW_AFS_copy_cache_to_system_file(uname, szLogonId);
1277 DebugEvent("Destroying tickets for %s", uname);
1278 KFW_AFS_destroy_tickets_for_principal(uname);
1280 RevertSecurityContext(&LogonContext);
1281 DeleteSecurityContext(&LogonContext);
1289 DebugEvent("Integrated login failed: %s", reason);
1291 StringCbPrintf(msg, sizeof(msg), "Integrated login failed: %s", reason);
1293 if (ISLOGONINTEGRATED(opt.LogonOption) && interactive && !opt.failSilently)
1294 MessageBox(hwndOwner, msg, "AFS Logon", MB_OK|MB_ICONWARNING|MB_SYSTEMMODAL);
1296 h = RegisterEventSource(NULL, AFS_LOGON_EVENT_NAME);
1298 ReportEvent(h, EVENTLOG_WARNING_TYPE, 0, 1008, NULL,
1300 DeregisterEventSource(h);
1302 code = MapAuthError(code);
1305 if (ISLOGONINTEGRATED(opt.LogonOption) && (code!=0))
1308 LocalFree(*lpLogonScript);
1309 *lpLogonScript = NULL;
1310 if (!afsWillAutoStart) // its not running, so if not autostart or integrated logon then just skip
1315 if (opt.theseCells) free(opt.theseCells);
1316 if (opt.smbName) free(opt.smbName);
1317 if (opt.realm) free(opt.realm);
1319 SecureZeroMemory(password, sizeof(password));
1321 DebugEvent("AFS AfsLogon - Exit","Return Code[%x]",code);
1325 DWORD APIENTRY NPPasswordChangeNotify(
1326 LPCWSTR lpAuthentInfoType,
1327 LPVOID lpAuthentInfo,
1328 LPCWSTR lpPreviousAuthentInfoType,
1329 LPVOID lpPreviousAuthentInfo,
1330 LPWSTR lpStationName,
1331 LPVOID StationHandle,
1334 BOOLEAN interactive;
1336 /* Are we interactive? */
1337 interactive = (wcsicmp(lpStationName, L"WinSta0") == 0);
1339 /* Do not do anything if the logon session is not interactive. */
1343 /* Make sure the AFS Libraries are initialized */
1346 DebugEvent0("AFS AfsLogon - NPPasswordChangeNotify");
1350 #include <userenv.h>
1352 #include <afs/vice.h>
1353 #include <afs/fs_utils.h>
1355 BOOL IsPathInAfs(const CHAR *strPath)
1358 struct ViceIoctl blob;
1362 blob.out_size = 2048;
1365 code = pioctl((LPTSTR)((LPCTSTR)strPath), VIOC_FILE_CELL_NAME, &blob, 1);
1372 typedef struct _WLX_NOTIFICATION_INFO {
1377 PWSTR WindowStation;
1380 PFNMSGECALLBACK pStatusCallback;
1381 } WLX_NOTIFICATION_INFO, *PWLX_NOTIFICATION_INFO;
1384 VOID AFS_Startup_Event( PWLX_NOTIFICATION_INFO pInfo )
1386 DWORD LSPtype, LSPsize;
1389 /* Make sure the AFS Libraries are initialized */
1392 (void) RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY,
1393 0, KEY_QUERY_VALUE, &NPKey);
1394 LSPsize=sizeof(TraceOption);
1395 RegQueryValueEx(NPKey, REG_CLIENT_TRACE_OPTION_PARM, NULL,
1396 &LSPtype, (LPBYTE)&TraceOption, &LSPsize);
1398 RegCloseKey (NPKey);
1400 (void) RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PROVIDER_SUBKEY,
1401 0, KEY_QUERY_VALUE, &NPKey);
1402 LSPsize=sizeof(Debug);
1403 RegQueryValueEx(NPKey, REG_CLIENT_DEBUG_PARM, NULL,
1404 &LSPtype, (LPBYTE)&Debug, &LSPsize);
1406 RegCloseKey (NPKey);
1407 DebugEvent0("AFS_Startup_Event");
1410 VOID AFS_Logoff_Event( PWLX_NOTIFICATION_INFO pInfo )
1413 TCHAR profileDir[1024] = TEXT("");
1415 PTOKEN_USER tokenUser = NULL;
1417 DWORD LSPtype, LSPsize;
1419 DWORD LogoffPreserveTokens = 0;
1422 /* Make sure the AFS Libraries are initialized */
1425 DebugEvent0("AFS_Logoff_Event - Start");
1427 (void) RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY,
1428 0, KEY_QUERY_VALUE, &NPKey);
1429 LSPsize=sizeof(LogoffPreserveTokens);
1430 RegQueryValueEx(NPKey, REG_CLIENT_LOGOFF_TOKENS_PARM, NULL,
1431 &LSPtype, (LPBYTE)&LogoffPreserveTokens, &LSPsize);
1432 RegCloseKey (NPKey);
1434 if (!LogoffPreserveTokens) {
1435 memset(&opt, 0, sizeof(LogonOptions_t));
1437 if (pInfo->UserName && pInfo->Domain) {
1438 char username[MAX_USERNAME_LENGTH] = "";
1439 char domain[MAX_DOMAIN_LENGTH] = "";
1442 StringCchLengthW(pInfo->UserName, MAX_USERNAME_LENGTH, &szlen);
1443 WideCharToMultiByte(CP_UTF8, 0, pInfo->UserName, (int)szlen,
1444 username, sizeof(username), NULL, NULL);
1446 StringCchLengthW(pInfo->Domain, MAX_DOMAIN_LENGTH, &szlen);
1447 WideCharToMultiByte(CP_UTF8, 0, pInfo->Domain, (int)szlen,
1448 domain, sizeof(domain), NULL, NULL);
1450 GetDomainLogonOptions(NULL, FALSE, username, domain, &opt);
1453 if (ISREMOTE(opt.flags)) {
1454 if (!GetTokenInformation(pInfo->hToken, TokenUser, NULL, 0, &retLen))
1456 if ( GetLastError() == ERROR_INSUFFICIENT_BUFFER ) {
1457 tokenUser = (PTOKEN_USER) LocalAlloc(LPTR, retLen);
1459 if (!GetTokenInformation(pInfo->hToken, TokenUser, tokenUser, retLen, &retLen))
1461 DebugEvent("AFS_Logoff_Event - GetTokenInformation failed: GLE = %lX", GetLastError());
1466 /* We can't use pInfo->Domain for the domain since in the cross realm case
1467 * this is source domain and not the destination domain.
1469 if (tokenUser && QueryAdHomePathFromSid( profileDir, sizeof(profileDir), tokenUser->User.Sid, pInfo->Domain)) {
1470 WCHAR Domain[64]=L"";
1471 GetLocalShortDomain(Domain, sizeof(Domain));
1472 if (QueryAdHomePathFromSid( profileDir, sizeof(profileDir), tokenUser->User.Sid, Domain)) {
1473 if (NetUserGetProfilePath(pInfo->Domain, pInfo->UserName, profileDir, len))
1474 GetUserProfileDirectory(pInfo->hToken, profileDir, &len);
1478 if (strlen(profileDir)) {
1479 DebugEvent("AFS_Logoff_Event - Profile Directory: %s", profileDir);
1480 if (!IsPathInAfs(profileDir)) {
1481 if (code = ktc_ForgetAllTokens())
1482 DebugEvent("AFS_Logoff_Event - ForgetAllTokens failed [%lX]",code);
1484 DebugEvent0("AFS_Logoff_Event - ForgetAllTokens succeeded");
1486 DebugEvent0("AFS_Logoff_Event - Tokens left in place; profile in AFS");
1489 DebugEvent0("AFS_Logoff_Event - Unable to load profile");
1493 LocalFree(tokenUser);
1495 DebugEvent0("AFS_Logoff_Event - Local Logon");
1496 if (code = ktc_ForgetAllTokens())
1497 DebugEvent("AFS_Logoff_Event - ForgetAllTokens failed [%lX]",code);
1499 DebugEvent0("AFS_Logoff_Event - ForgetAllTokens succeeded");
1502 DebugEvent0("AFS_Logoff_Event - Preserving Tokens");
1505 DebugEvent0("AFS_Logoff_Event - End");
1508 VOID AFS_Logon_Event( PWLX_NOTIFICATION_INFO pInfo )
1510 TCHAR profileDir[1024] = TEXT("");
1512 PTOKEN_USER tokenUser = NULL;
1514 WCHAR szUserW[128] = L"";
1515 char szUserA[128] = "";
1516 char szClient[MAX_PATH];
1517 char szPath[MAX_PATH] = "";
1523 /* Make sure the AFS Libraries are initialized */
1526 DebugEvent0("AFS_Logon_Event - Start");
1528 DebugEvent("AFS_Logon_Event Process ID: %d",GetCurrentProcessId());
1530 memset(&opt, 0, sizeof(LogonOptions_t));
1532 if (pInfo->UserName && pInfo->Domain) {
1533 char username[MAX_USERNAME_LENGTH] = "";
1534 char domain[MAX_DOMAIN_LENGTH] = "";
1537 DebugEvent0("AFS_Logon_Event - pInfo UserName and Domain");
1539 StringCchLengthW(pInfo->UserName, MAX_USERNAME_LENGTH, &szlen);
1540 WideCharToMultiByte(CP_UTF8, 0, pInfo->UserName, (int)szlen,
1541 username, sizeof(username), NULL, NULL);
1543 StringCchLengthW(pInfo->Domain, MAX_DOMAIN_LENGTH, &szlen);
1544 WideCharToMultiByte(CP_UTF8, 0, pInfo->Domain, (int)szlen,
1545 domain, sizeof(domain), NULL, NULL);
1547 DebugEvent0("AFS_Logon_Event - Calling GetDomainLogonOptions");
1548 GetDomainLogonOptions(NULL, FALSE, username, domain, &opt);
1550 if (!pInfo->UserName)
1551 DebugEvent0("AFS_Logon_Event - No pInfo->UserName");
1553 DebugEvent0("AFS_Logon_Event - No pInfo->Domain");
1556 DebugEvent("AFS_Logon_Event - opt.LogonOption = %lX opt.flags = %lX",
1557 opt.LogonOption, opt.flags);
1559 if (!ISLOGONINTEGRATED(opt.LogonOption) || !ISREMOTE(opt.flags)) {
1560 DebugEvent0("AFS_Logon_Event - Logon is not integrated or not remote");
1561 goto done_logon_event;
1564 DebugEvent0("AFS_Logon_Event - Calling GetTokenInformation");
1566 if (!GetTokenInformation(pInfo->hToken, TokenUser, NULL, 0, &retLen))
1568 if ( GetLastError() == ERROR_INSUFFICIENT_BUFFER ) {
1569 tokenUser = (PTOKEN_USER) LocalAlloc(LPTR, retLen);
1571 if (!GetTokenInformation(pInfo->hToken, TokenUser, tokenUser, retLen, &retLen))
1573 DebugEvent("AFS_Logon_Event - GetTokenInformation failed: GLE = %lX", GetLastError());
1578 /* We can't use pInfo->Domain for the domain since in the cross realm case
1579 * this is source domain and not the destination domain.
1581 if (tokenUser && QueryAdHomePathFromSid( profileDir, sizeof(profileDir), tokenUser->User.Sid, pInfo->Domain)) {
1582 WCHAR Domain[64]=L"";
1583 GetLocalShortDomain(Domain, sizeof(Domain));
1584 if (QueryAdHomePathFromSid( profileDir, sizeof(profileDir), tokenUser->User.Sid, Domain)) {
1585 if (NetUserGetProfilePath(pInfo->Domain, pInfo->UserName, profileDir, len))
1586 GetUserProfileDirectory(pInfo->hToken, profileDir, &len);
1590 if (strlen(profileDir)) {
1591 DebugEvent("AFS_Logon_Event - Profile Directory: %s", profileDir);
1593 DebugEvent0("AFS_Logon_Event - Unable to load profile");
1597 dwSize = sizeof(szUserA);
1598 if (!KFW_AFS_get_lsa_principal(szUserA, &dwSize)) {
1599 StringCbPrintfW(szUserW, sizeof(szUserW), L"%s\\%s", pInfo->Domain, pInfo->UserName);
1600 WideCharToMultiByte(CP_ACP, 0, szUserW, -1, szUserA, MAX_PATH, NULL, NULL);
1605 lana_GetNetbiosName(szClient, LANA_NETBIOS_NAME_FULL);
1606 StringCbPrintf(szPath, sizeof(szPath), "\\\\%s", szClient);
1608 DebugEvent("AFS_Logon_Event - Logon Name: %s", szUserA);
1610 memset (&nr, 0x00, sizeof(NETRESOURCE));
1611 nr.dwType=RESOURCETYPE_DISK;
1613 nr.lpRemoteName=szPath;
1614 res = WNetAddConnection2(&nr,NULL,szUserA,0);
1616 DebugEvent("AFS_Logon_Event - WNetAddConnection2(%s,%s) failed: 0x%X",
1617 szPath, szUserA,res);
1619 DebugEvent0("AFS_Logon_Event - WNetAddConnection2() succeeded");
1621 DebugEvent("AFS_Logon_Event - User name conversion failed: GLE = 0x%X",GetLastError());
1624 LocalFree(tokenUser);
1626 DebugEvent0("AFS_Logon_Event - End");
1630 GetSecurityLogonSessionData(HANDLE hToken, PSECURITY_LOGON_SESSION_DATA * ppSessionData)
1632 NTSTATUS Status = 0;
1633 TOKEN_STATISTICS Stats;
1639 *ppSessionData = NULL;
1641 Success = GetTokenInformation( hToken, TokenStatistics, &Stats, sizeof(TOKEN_STATISTICS), &ReqLen );
1645 Status = LsaGetLogonSessionData( &Stats.AuthenticationId, ppSessionData );
1646 if ( FAILED(Status) || !ppSessionData )
1652 VOID KFW_Logon_Event( PWLX_NOTIFICATION_INFO pInfo )
1655 WCHAR szUserW[128] = L"";
1656 char szUserA[128] = "";
1657 char szPath[MAX_PATH] = "";
1658 char szLogonId[128] = "";
1660 char filename[MAX_PATH] = "";
1661 char newfilename[MAX_PATH] = "";
1662 char commandline[MAX_PATH+256] = "";
1663 STARTUPINFO startupinfo;
1664 PROCESS_INFORMATION procinfo;
1665 HANDLE hf = INVALID_HANDLE_VALUE;
1667 LUID LogonId = {0, 0};
1668 PSECURITY_LOGON_SESSION_DATA pLogonSessionData = NULL;
1670 HKEY hKey1 = NULL, hKey2 = NULL;
1672 /* Make sure the KFW Libraries are initialized */
1675 DebugEvent0("KFW_Logon_Event - Start");
1677 GetSecurityLogonSessionData( pInfo->hToken, &pLogonSessionData );
1679 if ( pLogonSessionData ) {
1680 LogonId = pLogonSessionData->LogonId;
1681 DebugEvent("KFW_Logon_Event - LogonId(%d,%d)", LogonId.HighPart, LogonId.LowPart);
1683 sprintf(szLogonId,"%d.%d",LogonId.HighPart, LogonId.LowPart);
1684 LsaFreeReturnBuffer( pLogonSessionData );
1686 DebugEvent0("KFW_Logon_Event - Unable to determine LogonId");
1690 count = GetEnvironmentVariable("TEMP", filename, sizeof(filename));
1691 if ( count > sizeof(filename) || count == 0 ) {
1692 GetWindowsDirectory(filename, sizeof(filename));
1695 count = GetEnvironmentVariable("TEMP", filename, sizeof(filename));
1696 if ( count > sizeof(filename) || count == 0 ) {
1697 GetWindowsDirectory(filename, sizeof(filename));
1700 if ( strlen(filename) + strlen(szLogonId) + 2 > sizeof(filename) ) {
1701 DebugEvent0("KFW_Logon_Event - filename too long");
1705 strcat(filename, "\\");
1706 strcat(filename, szLogonId);
1708 hf = CreateFile(filename, FILE_ALL_ACCESS, 0, NULL, OPEN_EXISTING,
1709 FILE_ATTRIBUTE_NORMAL, NULL);
1710 if (hf == INVALID_HANDLE_VALUE) {
1711 DebugEvent0("KFW_Logon_Event - file cannot be opened");
1716 if (KFW_AFS_set_file_cache_dacl(filename, pInfo->hToken)) {
1717 DebugEvent0("KFW_Logon_Event - unable to set dacl");
1718 DeleteFile(filename);
1722 if (KFW_AFS_obtain_user_temp_directory(pInfo->hToken, newfilename, sizeof(newfilename))) {
1723 DebugEvent0("KFW_Logon_Event - unable to obtain temp directory");
1727 if ( strlen(newfilename) + strlen(szLogonId) + 2 > sizeof(newfilename) ) {
1728 DebugEvent0("KFW_Logon_Event - new filename too long");
1732 strcat(newfilename, "\\");
1733 strcat(newfilename, szLogonId);
1735 if (!MoveFileEx(filename, newfilename,
1736 MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH)) {
1737 DebugEvent("KFW_Logon_Event - MoveFileEx failed GLE = 0x%x", GetLastError());
1741 sprintf(commandline, "afscpcc.exe \"%s\"", newfilename);
1743 GetStartupInfo(&startupinfo);
1744 if (CreateProcessAsUser( pInfo->hToken,
1750 CREATE_NEW_PROCESS_GROUP | DETACHED_PROCESS,
1756 DebugEvent("KFW_Logon_Event - CommandLine %s", commandline);
1758 WaitForSingleObject(procinfo.hProcess, 30000);
1760 CloseHandle(procinfo.hThread);
1761 CloseHandle(procinfo.hProcess);
1763 DebugEvent0("KFW_Logon_Event - CreateProcessFailed");
1766 DeleteFile(filename);
1768 DebugEvent0("KFW_Logon_Event - End");