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>
18 #include <sys/types.h>
26 #include <afs/pioctl_nt.h>
27 #include <afs/kautils.h>
30 #include "cm_config.h"
33 #include "lanahelper.h"
35 /* Allocated in Windows Driver Kit */
36 #ifndef WNNC_NET_OPENAFS
37 #define WNNC_NET_OPENAFS 0x00390000
40 #include <WINNT\afsreg.h>
42 DWORD TraceOption = 0;
47 #define AFS_LOGON_EVENT_NAME TEXT("AFS Logon")
49 void DebugEvent0(char *a)
51 HANDLE h; char *ptbuf[1];
53 if (!Debug && !ISLOGONTRACE(TraceOption))
56 h = RegisterEventSource(NULL, AFS_LOGON_EVENT_NAME);
57 if (h != INVALID_HANDLE_VALUE) {
59 ReportEvent(h, EVENTLOG_INFORMATION_TYPE, 0, 1008, NULL, 1, 0, (const char **)ptbuf, NULL);
60 DeregisterEventSource(h);
65 void DebugEvent(char *b,...)
67 HANDLE h; char *ptbuf[1],buf[MAXBUF_+1];
70 if (!Debug && !ISLOGONTRACE(TraceOption))
73 h = RegisterEventSource(NULL, AFS_LOGON_EVENT_NAME);
74 if (h != INVALID_HANDLE_VALUE) {
76 StringCbVPrintf(buf, MAXBUF_+1,b,marker);
79 ReportEvent(h, EVENTLOG_INFORMATION_TYPE, 0, 1008, NULL, 1, 0, (const char **)ptbuf, NULL);
80 DeregisterEventSource(h);
85 static HANDLE hInitMutex = NULL;
86 static BOOL bInit = FALSE;
88 BOOLEAN APIENTRY DllEntryPoint(HANDLE dll, DWORD reason, PVOID reserved)
94 case DLL_PROCESS_ATTACH:
95 /* Initialization Mutex */
97 hInitMutex = CreateMutex(NULL, FALSE, NULL);
99 WSAStartup( MAKEWORD(2,2), &wsaData );
102 case DLL_PROCESS_DETACH:
104 CloseHandle(hInitMutex);
109 case DLL_THREAD_ATTACH:
110 case DLL_THREAD_DETACH:
112 /* Everything else succeeds but does nothing. */
119 void AfsLogonInit(void)
121 if ( bInit == FALSE ) {
122 if ( WaitForSingleObject( hInitMutex, INFINITE ) == WAIT_OBJECT_0 ) {
123 /* initAFSDirPath() initializes an array and sets a
124 * flag so that the initialization can only occur
125 * once. No cleanup will be done when the DLL is
126 * unloaded so the initialization will not be
127 * performed again on a subsequent reload
131 /* ka_Init initializes a number of error tables.
132 * and then calls ka_CellConfig() which grabs
133 * an afsconf_dir structure via afsconf_Open().
134 * Upon a second attempt to call ka_CellConfig()
135 * the structure will be released with afsconf_Close()
136 * and then re-opened. Could this corrupt memory?
138 * We only need this if we are not using KFW.
140 if (!KFW_is_available())
144 ReleaseMutex(hInitMutex);
148 CHAR *GenRandomName(CHAR *pbuf)
151 srand( (unsigned)time( NULL ) );
152 for (i=0;i<MAXRANDOMNAMELEN-1;i++)
153 pbuf[i]='a'+(rand() % 26);
154 pbuf[MAXRANDOMNAMELEN-1]=0;
158 BOOLEAN AFSWillAutoStart(void)
163 BOOLEAN result = FALSE;
164 LPQUERY_SERVICE_CONFIG pConfig = NULL;
168 /* Open services manager */
169 scm = OpenSCManager(NULL, NULL, GENERIC_READ);
170 if (!scm) return FALSE;
172 /* Open AFSD service */
173 svc = OpenService(scm, "TransarcAFSDaemon", SERVICE_QUERY_CONFIG);
177 /* Query AFSD service config, first just to get buffer size */
178 /* Expected to fail, so don't test return value */
179 (void) QueryServiceConfig(svc, NULL, 0, &BufSize);
180 status = GetLastError();
181 if (status != ERROR_INSUFFICIENT_BUFFER)
184 /* Allocate buffer */
185 pConfig = (LPQUERY_SERVICE_CONFIG)GlobalAlloc(GMEM_FIXED,BufSize);
189 /* Query AFSD service config, this time for real */
190 flag = QueryServiceConfig(svc, pConfig, BufSize, &BufSize);
194 /* Is it autostart? */
195 if (pConfig->dwStartType < SERVICE_DEMAND_START)
201 CloseServiceHandle(svc);
203 CloseServiceHandle(scm);
208 DWORD MapAuthError(DWORD code)
211 /* Unfortunately, returning WN_NO_NETWORK results in the MPR abandoning
212 * logon scripts for all credential managers, although they will still
213 * receive logon notifications. Since we don't want this, we return
214 * WN_SUCCESS. This is highly undesirable, but we also don't want to
215 * break other network providers.
219 return WN_NO_NETWORK; */
220 default: return WN_SUCCESS;
224 DWORD APIENTRY NPGetCaps(DWORD index)
229 * The purpose of this response is to let the system
230 * know which file system the network provider is associated with
231 * Microsoft issues these values starting from 1 with the exception
232 * of WNNC_CRED_MANAGER which is 0xFFFF. The provider type is
233 * stored in the hiword. Pick a value that is unused.
237 case WNNC_SPEC_VERSION:
238 return WNNC_SPEC_VERSION51;
241 /* Say we are already started, even though we might wait after we receive NPLogonNotify */
250 NetUserGetProfilePath( LPCWSTR Domain, LPCWSTR UserName, char * profilePath,
251 DWORD profilePathLen )
254 LPWSTR ServerName = NULL;
255 LPUSER_INFO_3 p3 = NULL;
257 NetGetAnyDCName(NULL, Domain, (LPBYTE *)&ServerName);
258 /* if NetGetAnyDCName fails, ServerName == NULL
259 * NetUserGetInfo will obtain local user information
261 code = NetUserGetInfo(ServerName, UserName, 3, (LPBYTE *)&p3);
262 if (code == NERR_Success)
264 code = NERR_UserNotFound;
266 if (p3->usri3_profile) {
267 DWORD len = lstrlenW(p3->usri3_profile);
269 /* Convert From Unicode to ANSI (UTF-8 for future) */
270 len = len < profilePathLen ? len : profilePathLen - 1;
271 WideCharToMultiByte(CP_UTF8, 0, p3->usri3_profile, len, profilePath, len, NULL, NULL);
272 profilePath[len] = '\0';
276 NetApiBufferFree(p3);
280 NetApiBufferFree(ServerName);
284 BOOL IsServiceRunning (void)
286 SERVICE_STATUS Status;
288 memset (&Status, 0x00, sizeof(Status));
289 Status.dwCurrentState = SERVICE_STOPPED;
291 if ((hManager = OpenSCManager (NULL, NULL, GENERIC_READ)) != NULL)
294 if ((hService = OpenService (hManager, TEXT("TransarcAFSDaemon"), GENERIC_READ)) != NULL)
296 QueryServiceStatus (hService, &Status);
297 CloseServiceHandle (hService);
300 CloseServiceHandle (hManager);
302 DebugEvent("AFS AfsLogon - Test Service Running Return Code[%x] ?Running[%d]",Status.dwCurrentState,(Status.dwCurrentState == SERVICE_RUNNING));
303 return (Status.dwCurrentState == SERVICE_RUNNING);
306 BOOL IsServiceStartPending (void)
308 SERVICE_STATUS Status;
310 memset (&Status, 0x00, sizeof(Status));
311 Status.dwCurrentState = SERVICE_STOPPED;
313 if ((hManager = OpenSCManager (NULL, NULL, GENERIC_READ)) != NULL)
316 if ((hService = OpenService (hManager, TEXT("TransarcAFSDaemon"), GENERIC_READ)) != NULL)
318 QueryServiceStatus (hService, &Status);
319 CloseServiceHandle (hService);
322 CloseServiceHandle (hManager);
324 DebugEvent("AFS AfsLogon - Test Service Start Pending Return Code[%x] ?Start Pending[%d]",Status.dwCurrentState,(Status.dwCurrentState == SERVICE_START_PENDING));
325 return (Status.dwCurrentState == SERVICE_START_PENDING);
328 BOOL StartTheService (void)
333 if ((hManager = OpenSCManager (NULL, NULL, GENERIC_READ|SERVICE_START)) != NULL)
336 if ((hService = OpenService (hManager, TEXT("TransarcAFSDaemon"), GENERIC_READ|SERVICE_START)) != NULL)
338 StartService (hService, 0, NULL);
339 gle = GetLastError();
340 CloseServiceHandle (hService);
342 gle = GetLastError();
344 CloseServiceHandle (hManager);
346 DebugEvent("AFS AfsLogon - Service Start Return Code[0x%x]",gle);
350 /* LOOKUPKEYCHAIN: macro to look up the value in the list of keys in order until it's found
351 v:variable to receive value (reference type)
353 d:default, in case the value isn't on any of the keys
355 #define LOOKUPKEYCHAIN(v,t,d,n) \
357 rv = ~ERROR_SUCCESS; \
360 dwSize = sizeof(v); \
361 rv = RegQueryValueEx(hkDom, n, 0, &dwType, (LPBYTE) &(v), &dwSize); \
362 if(rv == ERROR_SUCCESS || rv == ERROR_MORE_DATA) \
363 DebugEvent(#v " found in hkDom with type [%d]", dwType); \
365 if(hkDoms && ((rv != ERROR_SUCCESS && rv != ERROR_MORE_DATA) || dwType != t)) { \
366 dwSize = sizeof(v); \
367 rv = RegQueryValueEx(hkDoms, n, 0, &dwType, (LPBYTE) &(v), &dwSize); \
368 if(rv == ERROR_SUCCESS || rv == ERROR_MORE_DATA) \
369 DebugEvent(#v " found in hkDoms with type [%d]", dwType); \
371 if(hkNp && ((rv != ERROR_SUCCESS && rv != ERROR_MORE_DATA) || dwType != t)) { \
372 dwSize = sizeof(v); \
373 rv = RegQueryValueEx(hkNp, n, 0, &dwType, (LPBYTE) &(v), &dwSize); \
374 if(rv == ERROR_SUCCESS || rv == ERROR_MORE_DATA) \
375 DebugEvent(#v " found in hkNp with type [%d]", dwType); \
377 if((rv != ERROR_SUCCESS && rv != ERROR_MORE_DATA) || dwType != t) { \
379 DebugEvent0(#v " being set to default"); \
383 /* Get domain specific configuration info. We are returning void because if anything goes wrong
384 we just return defaults.
387 GetDomainLogonOptions( PLUID lpLogonId, char * username, char * domain, LogonOptions_t *opt ) {
388 HKEY hkParm = NULL; /* Service parameter */
389 HKEY hkNp = NULL; /* network provider key */
390 HKEY hkDoms = NULL; /* domains key */
391 HKEY hkDom = NULL; /* DOMAINS/domain key */
397 char computerName[MAX_COMPUTERNAME_LENGTH + 1]="";
398 char *effDomain = NULL;
400 memset(opt, 0, sizeof(LogonOptions_t));
402 DebugEvent("In GetDomainLogonOptions for user [%s] in domain [%s]", username, domain);
403 /* If the domain is the same as the Netbios computer name, we use the LOCALHOST domain name*/
404 opt->flags = LOGON_FLAG_REMOTE;
406 dwSize = MAX_COMPUTERNAME_LENGTH + 1;
407 if(GetComputerName(computerName, &dwSize)) {
408 if(!cm_stricmp_utf8(computerName, domain)) {
409 effDomain = "LOCALHOST";
410 opt->flags = LOGON_FLAG_LOCAL;
413 if (effDomain == NULL)
417 rv = RegOpenKeyEx( HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY, 0, KEY_READ, &hkParm );
418 if(rv != ERROR_SUCCESS) {
420 DebugEvent("GetDomainLogonOption: Can't open parms key [%d]", rv);
423 rv = RegOpenKeyEx( HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PROVIDER_SUBKEY, 0, KEY_READ, &hkNp );
424 if(rv != ERROR_SUCCESS) {
426 DebugEvent("GetDomainLogonOptions: Can't open NP key [%d]", rv);
430 rv = RegOpenKeyEx( hkNp, REG_CLIENT_DOMAINS_SUBKEY, 0, KEY_READ, &hkDoms );
431 if( rv != ERROR_SUCCESS ) {
433 DebugEvent("GetDomainLogonOptions: Can't open Domains key [%d]", rv);
437 if(hkDoms && effDomain) {
438 rv = RegOpenKeyEx( hkDoms, effDomain, 0, KEY_READ, &hkDom );
439 if( rv != ERROR_SUCCESS ) {
441 DebugEvent("GetDomainLogonOptions: Can't open domain key for [%s] [%d]", effDomain, rv);
442 /* If none of the domains match, we shouldn't use the domain key either */
447 DebugEvent0("Not opening domain key");
449 /* Each individual can either be specified on the domain key, the domains key or in the
450 net provider key. They fail over in that order. If none is found, we just use the
454 LOOKUPKEYCHAIN(opt->LogonOption, REG_DWORD, DEFAULT_LOGON_OPTION, REG_CLIENT_LOGON_OPTION_PARM);
456 /* FailLoginsSilently */
457 dwSize = sizeof(dwDummy);
458 rv = RegQueryValueEx(hkParm, REG_CLIENT_FAIL_SILENTLY_PARM, 0, &dwType, (LPBYTE) &dwDummy, &dwSize);
459 if (rv != ERROR_SUCCESS)
460 LOOKUPKEYCHAIN(dwDummy, REG_DWORD, DEFAULT_FAIL_SILENTLY, REG_CLIENT_FAIL_SILENTLY_PARM);
461 opt->failSilently = dwDummy ? 1 :0;
464 LOOKUPKEYCHAIN(opt->retryInterval, REG_DWORD, DEFAULT_RETRY_INTERVAL, REG_CLIENT_RETRY_INTERVAL_PARM);
467 LOOKUPKEYCHAIN(opt->sleepInterval, REG_DWORD, DEFAULT_SLEEP_INTERVAL, REG_CLIENT_SLEEP_INTERVAL_PARM);
469 if(!ISLOGONINTEGRATED(opt->LogonOption)) {
470 DebugEvent0("Integrated logon disabled");
471 goto cleanup; /* no need to lookup the logon script */
474 /* come up with SMB username */
475 if(ISHIGHSECURITY(opt->LogonOption)) {
476 DebugEvent0("High Security Mode active");
477 opt->smbName = malloc( MAXRANDOMNAMELEN );
478 if (opt->smbName == NULL)
480 GenRandomName(opt->smbName);
481 } else if (lpLogonId) {
482 /* username and domain for logon session is not necessarily the same as
483 username and domain passed into network provider. */
484 PSECURITY_LOGON_SESSION_DATA plsd=NULL;
485 char lsaUsername[MAX_USERNAME_LENGTH]="";
486 char lsaDomain[MAX_DOMAIN_LENGTH]="";
490 Status = LsaGetLogonSessionData(lpLogonId, &plsd);
491 if ( FAILED(Status) || plsd == NULL ) {
492 DebugEvent("LsaGetLogonSessionData failed [0x%x]", Status);
496 if (!UnicodeStringToANSI(plsd->UserName, lsaUsername, MAX_USERNAME_LENGTH))
499 if (!UnicodeStringToANSI(plsd->LogonDomain, lsaDomain, MAX_DOMAIN_LENGTH))
502 DebugEvent("PLSD username[%s] domain[%s]",lsaUsername,lsaDomain);
504 if(SUCCEEDED(StringCbLength(lsaUsername, MAX_USERNAME_LENGTH, &tlen)))
509 if(SUCCEEDED(StringCbLength(lsaDomain, MAX_DOMAIN_LENGTH, &tlen)))
516 opt->smbName = malloc(len);
517 if (opt->smbName == NULL)
520 StringCbCopy(opt->smbName, len, lsaDomain);
521 StringCbCat(opt->smbName, len, "\\");
522 StringCbCat(opt->smbName, len, lsaUsername);
524 strlwr(opt->smbName);
528 LsaFreeReturnBuffer(plsd);
530 if (opt->smbName == NULL) {
533 DebugEvent("Constructing username using [%s] and [%s]",
536 len = strlen(username) + strlen(domain) + 2;
538 opt->smbName = malloc(len);
539 if (opt->smbName == NULL)
542 StringCbCopy(opt->smbName, len, domain);
543 StringCbCat(opt->smbName, len, "\\");
544 StringCbCat(opt->smbName, len, username);
546 strlwr(opt->smbName);
549 DebugEvent0("Looking up logon script");
551 /* First find out where the key is */
556 rv = RegQueryValueExW(hkDom, REG_CLIENT_LOGON_SCRIPT_PARMW, 0, &dwType, NULL, &dwSize);
557 if(rv == ERROR_SUCCESS && (dwType == REG_SZ || dwType == REG_EXPAND_SZ)) {
559 DebugEvent0("Located logon script in hkDom");
562 rv = RegQueryValueExW(hkDoms, REG_CLIENT_LOGON_SCRIPT_PARMW, 0, &dwType, NULL, &dwSize);
563 if(rv == ERROR_SUCCESS && !hkTemp && (dwType == REG_SZ || dwType == REG_EXPAND_SZ)) {
565 DebugEvent0("Located logon script in hkDoms");
567 /* Note that the LogonScript in the NP key is only used if we are doing high security. */
568 else if(hkNp && ISHIGHSECURITY(opt->LogonOption)) {
569 rv = RegQueryValueExW(hkNp, REG_CLIENT_LOGON_SCRIPT_PARMW, 0, &dwType, NULL, &dwSize);
570 if(rv == ERROR_SUCCESS && !hkTemp && (dwType == REG_SZ || dwType == REG_EXPAND_SZ)) {
572 DebugEvent0("Located logon script in hkNp");
578 WCHAR *regscript = NULL;
579 WCHAR *regexscript = NULL;
580 WCHAR *regexuscript = NULL;
581 WCHAR *wuname = NULL;
586 StringCbLength(opt->smbName, MAX_USERNAME_LENGTH, &len);
589 wuname = malloc(len * sizeof(WCHAR));
591 goto doneLogonScript;
592 MultiByteToWideChar(CP_ACP,0,opt->smbName,-1,wuname,(int)(len*sizeof(WCHAR)));
594 DebugEvent("Username is set for [%S]", wuname);
596 /* dwSize still has the size of the required buffer in bytes. */
597 regscript = malloc(dwSize);
599 goto doneLogonScript;
600 rv = RegQueryValueExW(hkTemp, REG_CLIENT_LOGON_SCRIPT_PARMW, 0, &dwType, (LPBYTE) regscript, &dwSize);
601 if(rv != ERROR_SUCCESS) {/* what the ..? */
602 DebugEvent("Can't look up logon script rv [%d] size [%d] gle %d",rv, dwSize, GetLastError());
603 goto doneLogonScript;
606 DebugEvent("Found logon script [%S]", regscript);
608 if(dwType == REG_EXPAND_SZ) {
611 dwSize += MAX_PATH * sizeof(WCHAR); /* make room for environment expansion. */
612 regexscript = malloc(dwSize);
614 goto doneLogonScript;
615 dwReq = ExpandEnvironmentStringsW(regscript, regexscript, dwSize / sizeof(WCHAR));
617 regscript = regexscript;
619 if(dwReq > (dwSize / sizeof(WCHAR))) {
620 DebugEvent0("Overflow while expanding environment strings.");
621 goto doneLogonScript;
625 DebugEvent("After expanding env strings [%S]", regscript);
627 if(wcsstr(regscript, L"%s")) {
628 dwSize += (DWORD)(len * sizeof(WCHAR)); /* make room for username expansion */
629 regexuscript = (WCHAR *) LocalAlloc(LMEM_FIXED, dwSize);
631 goto doneLogonScript;
632 hr = StringCbPrintfW(regexuscript, dwSize, regscript, wuname);
634 regexuscript = (WCHAR *) LocalAlloc(LMEM_FIXED, dwSize);
636 goto doneLogonScript;
637 hr = StringCbCopyW(regexuscript, dwSize, regscript);
640 DebugEvent("After expanding username [%S]", regexuscript);
643 opt->logonScript = regexuscript;
645 LocalFree(regexuscript);
648 if(wuname) free(wuname);
649 if(regscript) free(regscript);
650 if(regexscript) free(regexscript);
653 DebugEvent0("Looking up TheseCells");
655 /* First find out where the key is */
660 rv = RegQueryValueEx(hkDom, REG_CLIENT_THESE_CELLS_PARM, 0, &dwType, NULL, &dwSize);
661 if (rv == ERROR_SUCCESS && dwType == REG_MULTI_SZ) {
663 DebugEvent("Located TheseCells in hkDom size %d", dwSize);
665 rv = RegQueryValueEx(hkDoms, REG_CLIENT_THESE_CELLS_PARM, 0, &dwType, NULL, &dwSize);
666 if (rv == ERROR_SUCCESS && !hkTemp && dwType == REG_MULTI_SZ) {
668 DebugEvent("Located TheseCells in hkDoms size %d", dwSize);
670 rv = RegQueryValueEx(hkNp, REG_CLIENT_THESE_CELLS_PARM, 0, &dwType, NULL, &dwSize);
671 if (rv == ERROR_SUCCESS && !hkTemp && dwType == REG_MULTI_SZ) {
673 DebugEvent("Located TheseCells in hkNp size %d", dwSize);
679 CHAR * thesecells = NULL, *p;
681 /* dwSize still has the size of the required buffer in bytes. */
682 thesecells = malloc(dwSize*2);
687 rv = RegQueryValueEx(hkTemp, REG_CLIENT_THESE_CELLS_PARM, 0, NULL, (LPBYTE) thesecells, &dwSize);
688 if(rv != ERROR_SUCCESS) {/* what the ..? */
689 DebugEvent("Can't look up TheseCells rv [%d] size [%d] gle [%d]",rv, dwSize, GetLastError());
693 /* TheseCells is a REG_MULTI_SZ */
694 if ( thesecells && thesecells[0]) {
695 for ( p=thesecells; *p; p += (strlen(p) + 1)) {
696 DebugEvent("Found TheseCells [%s]", p);
698 opt->theseCells = thesecells;
701 DebugEvent("TheseCells [REG_MULTI_SZ] not found");
705 if (thesecells) free(thesecells);
708 DebugEvent0("Looking up Realm");
710 /* First find out where the key is */
715 rv = RegQueryValueEx(hkDom, REG_CLIENT_REALM_PARM, 0, &dwType, NULL, &dwSize);
716 if (rv == ERROR_SUCCESS && dwType == REG_SZ) {
718 DebugEvent("Located Realm in hkDom size %d", dwSize);
720 rv = RegQueryValueEx(hkDoms, REG_CLIENT_REALM_PARM, 0, &dwType, NULL, &dwSize);
721 if (rv == ERROR_SUCCESS && !hkTemp && dwType == REG_SZ) {
723 DebugEvent("Located Realm in hkDoms size %d", dwSize);
725 rv = RegQueryValueEx(hkNp, REG_CLIENT_REALM_PARM, 0, &dwType, NULL, &dwSize);
726 if (rv == ERROR_SUCCESS && !hkTemp && dwType == REG_SZ) {
728 DebugEvent("Located Realm in hkNp size %d", dwSize);
736 /* dwSize still has the size of the required buffer in bytes. */
737 realm = malloc(dwSize*2);
742 rv = RegQueryValueEx(hkTemp, REG_CLIENT_REALM_PARM, 0, NULL, (LPBYTE) realm, &dwSize);
743 if(rv != ERROR_SUCCESS) {/* what the ..? */
744 DebugEvent("Can't look up Realm rv [%d] size [%d] gle [%d]",rv, dwSize, GetLastError());
748 DebugEvent("Found Realm [%s]", realm);
753 if (realm) free(realm);
757 if(hkNp) RegCloseKey(hkNp);
758 if(hkDom) RegCloseKey(hkDom);
759 if(hkDoms) RegCloseKey(hkDoms);
760 if(hkParm) RegCloseKey(hkParm);
763 #undef LOOKUPKEYCHAIN
765 /* Try to find out which cell the given path is in. We must retain
766 the contents of *cell in case of failure. *cell is assumed to be
767 at least cellLen chars */
768 DWORD GetFileCellName(char * path, char * cell, size_t cellLen) {
769 struct ViceIoctl blob;
770 char tcell[MAX_PATH];
774 blob.out_size = MAX_PATH;
777 code = pioctl(path, VIOC_FILE_CELL_NAME, &blob, 1);
780 strncpy(cell, tcell, cellLen);
781 cell[cellLen - 1] = '\0';
789 UnicodeStringToANSI(UNICODE_STRING uInputString, LPSTR lpszOutputString, int nOutStringLen)
793 GetCPInfo(CP_ACP, &CodePageInfo);
795 if (CodePageInfo.MaxCharSize > 1)
796 // Only supporting non-Unicode strings
799 if (uInputString.Buffer && ((LPBYTE) uInputString.Buffer)[1] == '\0')
801 // Looks like unicode, better translate it
802 // UNICODE_STRING specifies the length of the buffer string in Bytes not WCHARS
803 WideCharToMultiByte(CP_ACP, 0, (LPCWSTR) uInputString.Buffer, uInputString.Length/2,
804 lpszOutputString, nOutStringLen-1, NULL, NULL);
805 lpszOutputString[min(uInputString.Length/2,nOutStringLen-1)] = '\0';
809 lpszOutputString[0] = '\0';
811 } // UnicodeStringToANSI
813 DWORD APIENTRY NPLogonNotify(
815 LPCWSTR lpAuthentInfoType,
816 LPVOID lpAuthentInfo,
817 LPCWSTR lpPreviousAuthentInfoType,
818 LPVOID lpPreviousAuthentInfo,
819 LPWSTR lpStationName,
820 LPVOID StationHandle,
821 LPWSTR *lpLogonScript)
823 char uname[MAX_USERNAME_LENGTH]="";
824 char password[MAX_PASSWORD_LENGTH]="";
825 char logonDomain[MAX_DOMAIN_LENGTH]="";
826 char cell[256]="<non-integrated logon>";
827 char homePath[MAX_PATH]="";
828 char szLogonId[128] = "";
830 MSV1_0_INTERACTIVE_LOGON *IL;
832 DWORD code = 0, code2;
840 DWORD LSPtype, LSPsize;
843 HWND hwndOwner = (HWND)StationHandle;
845 BOOLEAN afsWillAutoStart;
847 BOOLEAN lowercased_name = TRUE;
849 LogonOptions_t opt; /* domain specific logon options */
853 /* Are we interactive? */
854 interactive = (wcsicmp(lpStationName, L"WinSta0") == 0);
856 #ifdef DISABLE_NON_INTERACTIVE
857 /* Do not do anything if the logon session is not interactive. */
862 (void) RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY,
863 0, KEY_QUERY_VALUE, &NPKey);
864 LSPsize=sizeof(TraceOption);
865 RegQueryValueEx(NPKey, REG_CLIENT_TRACE_OPTION_PARM, NULL,
866 &LSPtype, (LPBYTE)&TraceOption, &LSPsize);
870 (void) RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PROVIDER_SUBKEY,
871 0, KEY_QUERY_VALUE, &NPKey);
872 LSPsize=sizeof(Debug);
873 RegQueryValueEx(NPKey, REG_CLIENT_DEBUG_PARM, NULL,
874 &LSPtype, (LPBYTE)&Debug, &LSPsize);
878 DebugEvent("NPLogonNotify - LoginId(%d,%d)", lpLogonId->HighPart, lpLogonId->LowPart);
880 /* Make sure the AFS Libraries are initialized */
883 /* Initialize Logon Script to none */
886 /* MSV1_0_INTERACTIVE_LOGON and KERB_INTERACTIVE_LOGON are equivalent for
889 if ( wcsicmp(lpAuthentInfoType,L"MSV1_0:Interactive") &&
890 wcsicmp(lpAuthentInfoType,L"Kerberos:Interactive") )
892 DebugEvent("Unsupported Authentication Info Type: %S",
897 IL = (MSV1_0_INTERACTIVE_LOGON *) lpAuthentInfo;
899 /* Convert from Unicode to ANSI */
901 /*TODO: Use SecureZeroMemory to erase passwords */
902 if (!UnicodeStringToANSI(IL->UserName, uname, MAX_USERNAME_LENGTH) ||
903 !UnicodeStringToANSI(IL->Password, password, MAX_PASSWORD_LENGTH) ||
904 !UnicodeStringToANSI(IL->LogonDomainName, logonDomain, MAX_DOMAIN_LENGTH))
907 /* Make sure AD-DOMAINS sent from login that is sent to us is stripped */
908 ctemp = strchr(uname, '@');
912 if ( logonDomain[0] == '\0' )
913 StringCchCopy(logonDomain, MAX_DOMAIN_LENGTH, ctemp);
916 /* is the name all lowercase? */
917 for ( ctemp = uname; *ctemp ; ctemp++) {
918 if ( !islower(*ctemp) ) {
919 lowercased_name = FALSE;
928 GetDomainLogonOptions( lpLogonId, uname, logonDomain, &opt );
929 retryInterval = opt.retryInterval;
930 sleepInterval = opt.sleepInterval;
931 *lpLogonScript = opt.logonScript;
933 if (retryInterval < sleepInterval)
934 sleepInterval = retryInterval;
936 DebugEvent("Got logon script: [%S]", opt.logonScript);
938 afsWillAutoStart = AFSWillAutoStart();
940 DebugEvent("LogonOption[%x], Service AutoStart[%d]",
941 opt.LogonOption,afsWillAutoStart);
943 /* Check for zero length password if integrated logon*/
944 if ( ISLOGONINTEGRATED(opt.LogonOption) ) {
945 if ( password[0] == 0 ) {
946 DebugEvent0("Password is the empty string");
948 reason = "zero length password is illegal";
952 /* Get cell name if doing integrated logon.
953 We might overwrite this if we are logging into an AD realm and we find out that
954 the user's home dir is in some other cell. */
955 DebugEvent("About to call cm_GetRootCellName()");
956 code = cm_GetRootCellName(cell);
958 DebugEvent0("Unable to obtain Root Cell");
960 reason = "unknown cell";
962 DebugEvent("Default cell is %s", cell);
966 /* We get the user's home directory path, if applicable, though we can't lookup the
967 cell right away because the client service may not have started yet. This call
968 also sets the AD_REALM flag in opt.flags if applicable. */
969 if (ISREMOTE(opt.flags)) {
970 DebugEvent0("Is Remote");
971 GetAdHomePath(homePath,MAX_PATH,lpLogonId,&opt);
975 /* loop until AFS is started. */
976 if (afsWillAutoStart) {
978 * If the service is configured for auto start but hasn't started yet,
981 if (!(IsServiceRunning() || IsServiceStartPending()))
984 while ( IsServiceStartPending() ) {
988 while (IsServiceRunning() && code != KTC_NOCM && code != KTC_NOCMRPC && code != KTC_NOCELL) {
990 DebugEvent("while(autostart) LogonOption[%x], Service AutoStart[%d]",
991 opt.LogonOption,afsWillAutoStart);
993 if (ISADREALM(opt.flags)) {
994 code = GetFileCellName(homePath,cell,256);
996 DebugEvent("profile path [%s] is in cell [%s]",homePath,cell);
998 /* Don't bail out if GetFileCellName failed.
999 * The home dir may not be in AFS after all.
1004 /* if Integrated Logon */
1005 if (ISLOGONINTEGRATED(opt.LogonOption))
1007 if ( KFW_is_available() ) {
1008 SetEnvironmentVariable(DO_NOT_REGISTER_VARNAME, "");
1010 char * principal, *p;
1013 StringCchLength(opt.realm, MAX_DOMAIN_LENGTH, &tlen);
1015 StringCchLength(uname, MAX_USERNAME_LENGTH, &tlen);
1018 /* tlen is now the length of uname in characters */
1019 principal = (char *)malloc(len * sizeof(char));
1021 StringCchCopy(principal, len, uname);
1022 p = principal + tlen;
1024 StringCchCopy(p, len - tlen -1, opt.realm);
1025 code = KFW_AFS_get_cred(principal, cell, password, 0, opt.smbName, &reason);
1026 DebugEvent("KFW_AFS_get_cred uname=[%s] smbname=[%s] cell=[%s] code=[%d]",
1027 principal,opt.smbName,cell,code);
1031 code = KFW_AFS_get_cred(uname, cell, password, 0, opt.smbName, &reason);
1032 DebugEvent("KFW_AFS_get_cred uname=[%s] smbname=[%s] cell=[%s] code=[%d]",
1033 uname,opt.smbName,cell,code);
1035 SetEnvironmentVariable(DO_NOT_REGISTER_VARNAME, NULL);
1036 if (code == 0 && opt.theseCells) {
1037 char * principal, *p;
1040 StringCchLength(opt.realm ? opt.realm : cell, MAX_DOMAIN_LENGTH, &tlen);
1042 StringCchLength(uname, MAX_USERNAME_LENGTH, &tlen);
1045 /* tlen is now the length of uname in characters */
1046 principal = (char *)malloc(len * sizeof(char));
1048 StringCchCopy(principal, len, uname);
1049 p = principal + tlen;
1052 StringCchCopy(p, len - tlen -1, opt.realm);
1054 StringCchCopy(p, len - tlen - 1, cell);
1061 if ( cm_stricmp_utf8(p, cell) ) {
1062 SetEnvironmentVariable(DO_NOT_REGISTER_VARNAME, "");
1063 code2 = KFW_AFS_get_cred(principal, p, password, 0, opt.smbName, &reason);
1064 SetEnvironmentVariable(DO_NOT_REGISTER_VARNAME, NULL);
1065 DebugEvent("KFW_AFS_get_cred uname=[%s] smbname=[%s] cell=[%s] code=[%d]",
1066 principal,opt.smbName,p,code2);
1074 code = ka_UserAuthenticateGeneral2(KA_USERAUTH_VERSION+KA_USERAUTH_AUTHENT_LOGON,
1075 uname, "", cell, password, opt.smbName, 0, &pw_exp, 0,
1077 DebugEvent("AFS AfsLogon - (INTEGRATED only)ka_UserAuthenticateGeneral2 Code[%x] uname[%s] smbname=[%s] Cell[%s] PwExp=[%d] Reason=[%s]",
1078 code,uname,opt.smbName,cell,pw_exp,reason?reason:"");
1080 if ( code && code != KTC_NOCM && code != KTC_NOCMRPC && !lowercased_name ) {
1081 for ( ctemp = uname; *ctemp ; ctemp++) {
1082 *ctemp = tolower(*ctemp);
1084 lowercased_name = TRUE;
1088 /* is service started yet?*/
1090 /* If we've failed because the client isn't running yet and the
1091 * client is set to autostart (and therefore it makes sense for
1092 * us to wait for it to start) then sleep a while and try again.
1093 * If the error was something else, then give up. */
1094 if (code != KTC_NOCM && code != KTC_NOCMRPC)
1098 /*JUST check to see if its running*/
1099 if (IsServiceRunning())
1101 if (!IsServiceStartPending()) {
1103 reason = "AFS Service start failed";
1108 /* If the retry interval has expired and we still aren't
1109 * logged in, then just give up if we are not in interactive
1110 * mode or the failSilently flag is set, otherwise let the
1111 * user know we failed and give them a chance to try again. */
1112 if (retryInterval <= 0) {
1113 reason = "AFS not running";
1114 if (!interactive || opt.failSilently)
1116 flag = MessageBox(hwndOwner,
1117 "AFS is still starting. Retry?",
1119 MB_ICONQUESTION | MB_RETRYCANCEL);
1120 if (flag == IDCANCEL)
1123 /* Wait just a little while and try again */
1124 retryInterval = opt.retryInterval;
1128 Sleep(sleepInterval * 1000);
1129 retryInterval -= sleepInterval;
1132 DebugEvent0("while loop exited");
1134 /* remove any kerberos 5 tickets currently held by the SYSTEM account
1138 if (ISLOGONINTEGRATED(opt.LogonOption) && KFW_is_available()) {
1140 sprintf(szLogonId,"%d.%d",lpLogonId->HighPart, lpLogonId->LowPart);
1141 KFW_AFS_copy_cache_to_system_file(uname, szLogonId);
1143 KFW_AFS_destroy_tickets_for_principal(uname);
1151 StringCbPrintf(msg, sizeof(msg), "Integrated login failed: %s", reason);
1153 if (ISLOGONINTEGRATED(opt.LogonOption) && interactive && !opt.failSilently)
1154 MessageBox(hwndOwner, msg, "AFS Logon", MB_OK);
1156 h = RegisterEventSource(NULL, AFS_LOGON_EVENT_NAME);
1158 ReportEvent(h, EVENTLOG_WARNING_TYPE, 0, 1008, NULL,
1160 DeregisterEventSource(h);
1162 code = MapAuthError(code);
1165 if (ISLOGONINTEGRATED(opt.LogonOption) && (code!=0))
1168 LocalFree(*lpLogonScript);
1169 *lpLogonScript = NULL;
1170 if (!afsWillAutoStart) // its not running, so if not autostart or integrated logon then just skip
1175 if (opt.theseCells) free(opt.theseCells);
1176 if (opt.smbName) free(opt.smbName);
1177 if (opt.realm) free(opt.realm);
1179 DebugEvent("AFS AfsLogon - Exit","Return Code[%x]",code);
1183 DWORD APIENTRY NPPasswordChangeNotify(
1184 LPCWSTR lpAuthentInfoType,
1185 LPVOID lpAuthentInfo,
1186 LPCWSTR lpPreviousAuthentInfoType,
1187 LPVOID lpPreviousAuthentInfo,
1188 LPWSTR lpStationName,
1189 LPVOID StationHandle,
1192 BOOLEAN interactive;
1194 /* Are we interactive? */
1195 interactive = (wcsicmp(lpStationName, L"WinSta0") == 0);
1197 /* Do not do anything if the logon session is not interactive. */
1201 /* Make sure the AFS Libraries are initialized */
1204 DebugEvent0("AFS AfsLogon - NPPasswordChangeNotify");
1208 #include <userenv.h>
1210 #include <afs/vice.h>
1211 #include <afs/fs_utils.h>
1213 BOOL IsPathInAfs(const CHAR *strPath)
1216 struct ViceIoctl blob;
1220 blob.out_size = 2048;
1223 code = pioctl((LPTSTR)((LPCTSTR)strPath), VIOC_FILE_CELL_NAME, &blob, 1);
1230 typedef struct _WLX_NOTIFICATION_INFO {
1235 PWSTR WindowStation;
1238 PFNMSGECALLBACK pStatusCallback;
1239 } WLX_NOTIFICATION_INFO, *PWLX_NOTIFICATION_INFO;
1242 VOID AFS_Startup_Event( PWLX_NOTIFICATION_INFO pInfo )
1244 DWORD LSPtype, LSPsize;
1247 /* Make sure the AFS Libraries are initialized */
1250 (void) RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY,
1251 0, KEY_QUERY_VALUE, &NPKey);
1252 LSPsize=sizeof(TraceOption);
1253 RegQueryValueEx(NPKey, REG_CLIENT_TRACE_OPTION_PARM, NULL,
1254 &LSPtype, (LPBYTE)&TraceOption, &LSPsize);
1256 RegCloseKey (NPKey);
1257 DebugEvent0("AFS_Startup_Event");
1260 VOID AFS_Logoff_Event( PWLX_NOTIFICATION_INFO pInfo )
1263 TCHAR profileDir[1024] = TEXT("");
1265 PTOKEN_USER tokenUser = NULL;
1267 DWORD LSPtype, LSPsize;
1269 DWORD LogoffPreserveTokens = 0;
1272 /* Make sure the AFS Libraries are initialized */
1275 DebugEvent0("AFS_Logoff_Event - Start");
1277 (void) RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY,
1278 0, KEY_QUERY_VALUE, &NPKey);
1279 LSPsize=sizeof(LogoffPreserveTokens);
1280 RegQueryValueEx(NPKey, REG_CLIENT_LOGOFF_TOKENS_PARM, NULL,
1281 &LSPtype, (LPBYTE)&LogoffPreserveTokens, &LSPsize);
1282 RegCloseKey (NPKey);
1284 if (!LogoffPreserveTokens) {
1285 memset(&opt, 0, sizeof(LogonOptions_t));
1287 if (pInfo->UserName && pInfo->Domain) {
1288 char username[MAX_USERNAME_LENGTH] = "";
1289 char domain[MAX_DOMAIN_LENGTH] = "";
1292 StringCchLengthW(pInfo->UserName, MAX_USERNAME_LENGTH, &szlen);
1293 WideCharToMultiByte(CP_UTF8, 0, pInfo->UserName, szlen,
1294 username, sizeof(username), NULL, NULL);
1296 StringCchLengthW(pInfo->Domain, MAX_DOMAIN_LENGTH, &szlen);
1297 WideCharToMultiByte(CP_UTF8, 0, pInfo->Domain, szlen,
1298 domain, sizeof(domain), NULL, NULL);
1300 GetDomainLogonOptions(NULL, username, domain, &opt);
1303 if (ISREMOTE(opt.flags)) {
1304 if (!GetTokenInformation(pInfo->hToken, TokenUser, NULL, 0, &retLen))
1306 if ( GetLastError() == ERROR_INSUFFICIENT_BUFFER ) {
1307 tokenUser = (PTOKEN_USER) LocalAlloc(LPTR, retLen);
1309 if (!GetTokenInformation(pInfo->hToken, TokenUser, tokenUser, retLen, &retLen))
1311 DebugEvent("AFS_Logoff_Event - GetTokenInformation failed: GLE = %lX", GetLastError());
1316 /* We can't use pInfo->Domain for the domain since in the cross realm case
1317 * this is source domain and not the destination domain.
1319 if (tokenUser && QueryAdHomePathFromSid( profileDir, sizeof(profileDir), tokenUser->User.Sid, pInfo->Domain)) {
1320 WCHAR Domain[64]=L"";
1321 GetLocalShortDomain(Domain, sizeof(Domain));
1322 if (QueryAdHomePathFromSid( profileDir, sizeof(profileDir), tokenUser->User.Sid, Domain)) {
1323 if (NetUserGetProfilePath(pInfo->Domain, pInfo->UserName, profileDir, len))
1324 GetUserProfileDirectory(pInfo->hToken, profileDir, &len);
1328 if (strlen(profileDir)) {
1329 DebugEvent("AFS_Logoff_Event - Profile Directory: %s", profileDir);
1330 if (!IsPathInAfs(profileDir)) {
1331 if (code = ktc_ForgetAllTokens())
1332 DebugEvent("AFS_Logoff_Event - ForgetAllTokens failed [%lX]",code);
1334 DebugEvent0("AFS_Logoff_Event - ForgetAllTokens succeeded");
1336 DebugEvent0("AFS_Logoff_Event - Tokens left in place; profile in AFS");
1339 DebugEvent0("AFS_Logoff_Event - Unable to load profile");
1343 LocalFree(tokenUser);
1345 DebugEvent0("AFS_Logoff_Event - Local Logon");
1346 if (code = ktc_ForgetAllTokens())
1347 DebugEvent("AFS_Logoff_Event - ForgetAllTokens failed [%lX]",code);
1349 DebugEvent0("AFS_Logoff_Event - ForgetAllTokens succeeded");
1352 DebugEvent0("AFS_Logoff_Event - Preserving Tokens");
1355 DebugEvent0("AFS_Logoff_Event - End");
1358 VOID AFS_Logon_Event( PWLX_NOTIFICATION_INFO pInfo )
1360 TCHAR profileDir[1024] = TEXT("");
1362 PTOKEN_USER tokenUser = NULL;
1364 WCHAR szUserW[128] = L"";
1365 char szUserA[128] = "";
1366 char szClient[MAX_PATH];
1367 char szPath[MAX_PATH] = "";
1373 /* Make sure the AFS Libraries are initialized */
1376 DebugEvent0("AFS_Logon_Event - Start");
1378 DebugEvent("AFS_Logon_Event Process ID: %d",GetCurrentProcessId());
1380 memset(&opt, 0, sizeof(LogonOptions_t));
1382 if (pInfo->UserName && pInfo->Domain) {
1383 char username[MAX_USERNAME_LENGTH] = "";
1384 char domain[MAX_DOMAIN_LENGTH] = "";
1387 DebugEvent0("AFS_Logon_Event - pInfo UserName and Domain");
1389 StringCchLengthW(pInfo->UserName, MAX_USERNAME_LENGTH, &szlen);
1390 WideCharToMultiByte(CP_UTF8, 0, pInfo->UserName, szlen,
1391 username, sizeof(username), NULL, NULL);
1393 StringCchLengthW(pInfo->Domain, MAX_DOMAIN_LENGTH, &szlen);
1394 WideCharToMultiByte(CP_UTF8, 0, pInfo->Domain, szlen,
1395 domain, sizeof(domain), NULL, NULL);
1397 DebugEvent0("AFS_Logon_Event - Calling GetDomainLogonOptions");
1398 GetDomainLogonOptions(NULL, username, domain, &opt);
1400 if (!pInfo->UserName)
1401 DebugEvent0("AFS_Logon_Event - No pInfo->UserName");
1403 DebugEvent0("AFS_Logon_Event - No pInfo->Domain");
1406 DebugEvent("AFS_Logon_Event - opt.LogonOption = %lX opt.flags = %lX",
1407 opt.LogonOption, opt.flags);
1409 if (!ISLOGONINTEGRATED(opt.LogonOption) || !ISREMOTE(opt.flags)) {
1410 DebugEvent0("AFS_Logon_Event - Logon is not integrated or not remote");
1411 goto done_logon_event;
1414 DebugEvent0("AFS_Logon_Event - Calling GetTokenInformation");
1416 if (!GetTokenInformation(pInfo->hToken, TokenUser, NULL, 0, &retLen))
1418 if ( GetLastError() == ERROR_INSUFFICIENT_BUFFER ) {
1419 tokenUser = (PTOKEN_USER) LocalAlloc(LPTR, retLen);
1421 if (!GetTokenInformation(pInfo->hToken, TokenUser, tokenUser, retLen, &retLen))
1423 DebugEvent("AFS_Logon_Event - GetTokenInformation failed: GLE = %lX", GetLastError());
1428 /* We can't use pInfo->Domain for the domain since in the cross realm case
1429 * this is source domain and not the destination domain.
1431 if (tokenUser && QueryAdHomePathFromSid( profileDir, sizeof(profileDir), tokenUser->User.Sid, pInfo->Domain)) {
1432 WCHAR Domain[64]=L"";
1433 GetLocalShortDomain(Domain, sizeof(Domain));
1434 if (QueryAdHomePathFromSid( profileDir, sizeof(profileDir), tokenUser->User.Sid, Domain)) {
1435 if (NetUserGetProfilePath(pInfo->Domain, pInfo->UserName, profileDir, len))
1436 GetUserProfileDirectory(pInfo->hToken, profileDir, &len);
1440 if (strlen(profileDir)) {
1441 DebugEvent("AFS_Logon_Event - Profile Directory: %s", profileDir);
1443 DebugEvent0("AFS_Logon_Event - Unable to load profile");
1447 dwSize = sizeof(szUserA);
1448 if (!KFW_AFS_get_lsa_principal(szUserA, &dwSize)) {
1449 StringCbPrintfW(szUserW, sizeof(szUserW), L"%s\\%s", pInfo->Domain, pInfo->UserName);
1450 WideCharToMultiByte(CP_ACP, 0, szUserW, -1, szUserA, MAX_PATH, NULL, NULL);
1455 lana_GetNetbiosName(szClient, LANA_NETBIOS_NAME_FULL);
1456 StringCbPrintf(szPath, sizeof(szPath), "\\\\%s", szClient);
1458 DebugEvent("AFS_Logon_Event - Logon Name: %s", szUserA);
1460 memset (&nr, 0x00, sizeof(NETRESOURCE));
1461 nr.dwType=RESOURCETYPE_DISK;
1463 nr.lpRemoteName=szPath;
1464 res = WNetAddConnection2(&nr,NULL,szUserA,0);
1466 DebugEvent("AFS_Logon_Event - WNetAddConnection2(%s,%s) failed: 0x%X",
1467 szPath, szUserA,res);
1469 DebugEvent0("AFS_Logon_Event - WNetAddConnection2() succeeded");
1471 DebugEvent("AFS_Logon_Event - User name conversion failed: GLE = 0x%X",GetLastError());
1474 LocalFree(tokenUser);
1476 DebugEvent0("AFS_Logon_Event - End");
1480 GetSecurityLogonSessionData(HANDLE hToken, PSECURITY_LOGON_SESSION_DATA * ppSessionData)
1482 NTSTATUS Status = 0;
1483 TOKEN_STATISTICS Stats;
1489 *ppSessionData = NULL;
1491 Success = GetTokenInformation( hToken, TokenStatistics, &Stats, sizeof(TOKEN_STATISTICS), &ReqLen );
1495 Status = LsaGetLogonSessionData( &Stats.AuthenticationId, ppSessionData );
1496 if ( FAILED(Status) || !ppSessionData )
1502 VOID KFW_Logon_Event( PWLX_NOTIFICATION_INFO pInfo )
1505 WCHAR szUserW[128] = L"";
1506 char szUserA[128] = "";
1507 char szPath[MAX_PATH] = "";
1508 char szLogonId[128] = "";
1510 char filename[MAX_PATH] = "";
1511 char newfilename[MAX_PATH] = "";
1512 char commandline[MAX_PATH+256] = "";
1513 STARTUPINFO startupinfo;
1514 PROCESS_INFORMATION procinfo;
1515 HANDLE hf = INVALID_HANDLE_VALUE;
1517 LUID LogonId = {0, 0};
1518 PSECURITY_LOGON_SESSION_DATA pLogonSessionData = NULL;
1520 HKEY hKey1 = NULL, hKey2 = NULL;
1522 /* Make sure the KFW Libraries are initialized */
1525 DebugEvent0("KFW_Logon_Event - Start");
1527 GetSecurityLogonSessionData( pInfo->hToken, &pLogonSessionData );
1529 if ( pLogonSessionData ) {
1530 LogonId = pLogonSessionData->LogonId;
1531 DebugEvent("KFW_Logon_Event - LogonId(%d,%d)", LogonId.HighPart, LogonId.LowPart);
1533 sprintf(szLogonId,"%d.%d",LogonId.HighPart, LogonId.LowPart);
1534 LsaFreeReturnBuffer( pLogonSessionData );
1536 DebugEvent0("KFW_Logon_Event - Unable to determine LogonId");
1540 count = GetEnvironmentVariable("TEMP", filename, sizeof(filename));
1541 if ( count > sizeof(filename) || count == 0 ) {
1542 GetWindowsDirectory(filename, sizeof(filename));
1545 count = GetEnvironmentVariable("TEMP", filename, sizeof(filename));
1546 if ( count > sizeof(filename) || count == 0 ) {
1547 GetWindowsDirectory(filename, sizeof(filename));
1550 if ( strlen(filename) + strlen(szLogonId) + 2 > sizeof(filename) ) {
1551 DebugEvent0("KFW_Logon_Event - filename too long");
1555 strcat(filename, "\\");
1556 strcat(filename, szLogonId);
1558 hf = CreateFile(filename, FILE_ALL_ACCESS, 0, NULL, OPEN_EXISTING,
1559 FILE_ATTRIBUTE_NORMAL, NULL);
1560 if (hf == INVALID_HANDLE_VALUE) {
1561 DebugEvent0("KFW_Logon_Event - file cannot be opened");
1566 if (KFW_AFS_set_file_cache_dacl(filename, pInfo->hToken)) {
1567 DebugEvent0("KFW_Logon_Event - unable to set dacl");
1568 DeleteFile(filename);
1572 if (KFW_AFS_obtain_user_temp_directory(pInfo->hToken, newfilename, sizeof(newfilename))) {
1573 DebugEvent0("KFW_Logon_Event - unable to obtain temp directory");
1577 if ( strlen(newfilename) + strlen(szLogonId) + 2 > sizeof(newfilename) ) {
1578 DebugEvent0("KFW_Logon_Event - new filename too long");
1582 strcat(newfilename, "\\");
1583 strcat(newfilename, szLogonId);
1585 if (!MoveFileEx(filename, newfilename,
1586 MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH)) {
1587 DebugEvent("KFW_Logon_Event - MoveFileEx failed GLE = 0x%x", GetLastError());
1591 sprintf(commandline, "afscpcc.exe \"%s\"", newfilename);
1593 GetStartupInfo(&startupinfo);
1594 if (CreateProcessAsUser( pInfo->hToken,
1600 CREATE_NEW_PROCESS_GROUP | DETACHED_PROCESS,
1606 DebugEvent("KFW_Logon_Event - CommandLine %s", commandline);
1608 WaitForSingleObject(procinfo.hProcess, 30000);
1610 CloseHandle(procinfo.hThread);
1611 CloseHandle(procinfo.hProcess);
1613 DebugEvent0("KFW_Logon_Event - CreateProcessFailed");
1616 DeleteFile(filename);
1618 DebugEvent0("KFW_Logon_Event - End");