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
14 #include <sys/types.h>
20 #include <afs/param.h>
22 #include <afs/pioctl_nt.h>
23 #include <afs/kautils.h>
26 #include "cm_config.h"
30 DWORD TraceOption = 0;
35 #define AFS_LOGON_EVENT_NAME TEXT("AFS Logon")
37 void DebugEvent0(char *a)
39 HANDLE h; char *ptbuf[1];
40 if (!ISLOGONTRACE(TraceOption))
42 h = RegisterEventSource(NULL, AFS_LOGON_EVENT_NAME);
44 ReportEvent(h, EVENTLOG_INFORMATION_TYPE, 0, 0, NULL, 1, 0, (const char **)ptbuf, NULL);
45 DeregisterEventSource(h);
49 void DebugEvent(char *b,...)
51 HANDLE h; char *ptbuf[1],buf[MAXBUF_+1];
54 if (!ISLOGONTRACE(TraceOption))
57 h = RegisterEventSource(NULL, AFS_LOGON_EVENT_NAME);
59 StringCbVPrintf(buf, MAXBUF_+1,b,marker);
62 ReportEvent(h, EVENTLOG_INFORMATION_TYPE, 0, 0, NULL, 1, 0, (const char **)ptbuf, NULL);
63 DeregisterEventSource(h);
67 static HANDLE hInitMutex = NULL;
68 static BOOL bInit = FALSE;
70 BOOLEAN APIENTRY DllEntryPoint(HANDLE dll, DWORD reason, PVOID reserved)
74 case DLL_PROCESS_ATTACH:
75 /* Initialization Mutex */
76 hInitMutex = CreateMutex(NULL, FALSE, NULL);
79 case DLL_PROCESS_DETACH:
80 CloseHandle(hInitMutex);
83 case DLL_THREAD_ATTACH:
84 case DLL_THREAD_DETACH:
86 /* Everything else succeeds but does nothing. */
93 void AfsLogonInit(void)
95 if ( bInit == FALSE ) {
96 if ( WaitForSingleObject( hInitMutex, INFINITE ) == WAIT_OBJECT_0 ) {
97 if ( bInit == FALSE ) {
103 ReleaseMutex(hInitMutex);
108 CHAR *GenRandomName(CHAR *pbuf)
111 srand( (unsigned)time( NULL ) );
112 for (i=0;i<MAXRANDOMNAMELEN-1;i++)
113 pbuf[i]='a'+(rand() % 26);
114 pbuf[MAXRANDOMNAMELEN-1]=0;
118 BOOLEAN AFSWillAutoStart(void)
123 BOOLEAN result = FALSE;
124 LPQUERY_SERVICE_CONFIG pConfig = NULL;
128 /* Open services manager */
129 scm = OpenSCManager(NULL, NULL, GENERIC_READ);
130 if (!scm) return FALSE;
132 /* Open AFSD service */
133 svc = OpenService(scm, "TransarcAFSDaemon", SERVICE_QUERY_CONFIG);
137 /* Query AFSD service config, first just to get buffer size */
138 /* Expected to fail, so don't test return value */
139 (void) QueryServiceConfig(svc, NULL, 0, &BufSize);
140 status = GetLastError();
141 if (status != ERROR_INSUFFICIENT_BUFFER)
144 /* Allocate buffer */
145 pConfig = (LPQUERY_SERVICE_CONFIG)GlobalAlloc(GMEM_FIXED,BufSize);
149 /* Query AFSD service config, this time for real */
150 flag = QueryServiceConfig(svc, pConfig, BufSize, &BufSize);
154 /* Is it autostart? */
155 if (pConfig->dwStartType < SERVICE_DEMAND_START)
161 CloseServiceHandle(svc);
163 CloseServiceHandle(scm);
168 DWORD MapAuthError(DWORD code)
171 /* Unfortunately, returning WN_NO_NETWORK results in the MPR abandoning
172 * logon scripts for all credential managers, although they will still
173 * receive logon notifications. Since we don't want this, we return
174 * WN_SUCCESS. This is highly undesirable, but we also don't want to
175 * break other network providers.
179 return WN_NO_NETWORK; */
180 default: return WN_SUCCESS;
184 DWORD APIENTRY NPGetCaps(DWORD index)
188 /* Don't have our own type; use somebody else's. */
189 return WNNC_NET_SUN_PC_NFS;
192 /* Say we are already started, even though we might wait after we receive NPLogonNotify */
201 NetUserGetProfilePath( LPCWSTR Domain, LPCWSTR UserName, char * profilePath,
202 DWORD profilePathLen )
205 LPWSTR ServerName = NULL;
206 LPUSER_INFO_3 p3 = NULL;
208 NetGetAnyDCName(NULL, Domain, (LPBYTE *)&ServerName);
209 /* if NetGetAnyDCName fails, ServerName == NULL
210 * NetUserGetInfo will obtain local user information
212 code = NetUserGetInfo(ServerName, UserName, 3, (LPBYTE *)&p3);
213 if (code == NERR_Success)
215 code = NERR_UserNotFound;
217 if (p3->usri3_profile) {
218 DWORD len = lstrlenW(p3->usri3_profile);
220 /* Convert From Unicode to ANSI (UTF-8 for future) */
221 len = len < profilePathLen ? len : profilePathLen - 1;
222 WideCharToMultiByte(CP_UTF8, 0, p3->usri3_profile, len, profilePath, len, NULL, NULL);
223 profilePath[len] = '\0';
227 NetApiBufferFree(p3);
231 NetApiBufferFree(ServerName);
235 BOOL IsServiceRunning (void)
237 SERVICE_STATUS Status;
239 memset (&Status, 0x00, sizeof(Status));
240 Status.dwCurrentState = SERVICE_STOPPED;
242 if ((hManager = OpenSCManager (NULL, NULL, GENERIC_READ)) != NULL)
245 if ((hService = OpenService (hManager, TEXT("TransarcAFSDaemon"), GENERIC_READ)) != NULL)
247 QueryServiceStatus (hService, &Status);
248 CloseServiceHandle (hService);
251 CloseServiceHandle (hManager);
253 DebugEvent("AFS AfsLogon - Test Service Running","Return Code[%x] ?Running[%d]",Status.dwCurrentState,(Status.dwCurrentState == SERVICE_RUNNING));
254 return (Status.dwCurrentState == SERVICE_RUNNING);
257 /* LOOKUPKEYCHAIN: macro to look up the value in the list of keys in order until it's found
258 v:variable to receive value (reference type)
260 d:default, in case the value isn't on any of the keys
262 #define LOOKUPKEYCHAIN(v,t,d,n) \
264 rv = ~ERROR_SUCCESS; \
267 dwSize = sizeof(v); \
268 rv = RegQueryValueEx(hkDom, n, 0, &dwType, (LPBYTE) &(v), &dwSize); \
269 if(rv == ERROR_SUCCESS) DebugEvent(#v " found in hkDom with type [%d]", dwType); \
271 if(hkDoms && (rv != ERROR_SUCCESS || dwType != t)) { \
272 dwSize = sizeof(v); \
273 rv = RegQueryValueEx(hkDoms, n, 0, &dwType, (LPBYTE) &(v), &dwSize); \
274 if(rv == ERROR_SUCCESS) DebugEvent(#v " found in hkDoms with type [%d]", dwType); \
276 if(hkNp && (rv != ERROR_SUCCESS || dwType != t)) { \
277 dwSize = sizeof(v); \
278 rv = RegQueryValueEx(hkNp, n, 0, &dwType, (LPBYTE) &(v), &dwSize); \
279 if(rv == ERROR_SUCCESS) DebugEvent(#v " found in hkNp with type [%d]", dwType); \
281 if(rv != ERROR_SUCCESS || dwType != t) { \
283 DebugEvent(#v " being set to default"); \
287 /* Get domain specific configuration info. We are returning void because if anything goes wrong
288 we just return defaults.
291 GetDomainLogonOptions( PLUID lpLogonId, char * username, char * domain, LogonOptions_t *opt ) {
292 HKEY hkParm = NULL; /* Service parameter */
293 HKEY hkNp = NULL; /* network provider key */
294 HKEY hkDoms = NULL; /* domains key */
295 HKEY hkDom = NULL; /* DOMAINS/domain key */
301 char computerName[MAX_COMPUTERNAME_LENGTH + 1];
304 DebugEvent("In GetDomainLogonOptions for user [%s] in domain [%s]", username, domain);
305 /* If the domain is the same as the Netbios computer name, we use the LOCALHOST domain name*/
306 opt->flags = LOGON_FLAG_REMOTE;
308 dwSize = MAX_COMPUTERNAME_LENGTH;
309 if(GetComputerName(computerName, &dwSize)) {
310 if(!stricmp(computerName, domain)) {
311 effDomain = "LOCALHOST";
312 opt->flags = LOGON_FLAG_LOCAL;
320 rv = RegOpenKeyEx( HKEY_LOCAL_MACHINE, REG_CLIENT_PARMS_KEY, 0, KEY_READ, &hkParm );
321 if(rv != ERROR_SUCCESS) {
323 DebugEvent("GetDomainLogonOption: Can't open parms key [%d]", rv);
326 rv = RegOpenKeyEx( HKEY_LOCAL_MACHINE, REG_CLIENT_PROVIDER_KEY, 0, KEY_READ, &hkNp );
327 if(rv != ERROR_SUCCESS) {
329 DebugEvent("GetDomainLogonOptions: Can't open NP key [%d]", rv);
333 rv = RegOpenKeyEx( hkNp, REG_CLIENT_DOMAINS_SUBKEY, 0, KEY_READ, &hkDoms );
334 if( rv != ERROR_SUCCESS ) {
336 DebugEvent("GetDomainLogonOptions: Can't open Domains key [%d]", rv);
340 if(hkDoms && effDomain) {
341 rv = RegOpenKeyEx( hkDoms, effDomain, 0, KEY_READ, &hkDom );
342 if( rv != ERROR_SUCCESS ) {
344 DebugEvent("GetDomainLogonOptions: Can't open domain key for [%s] [%d]", effDomain, rv);
345 /* If none of the domains match, we shouldn't use the domain key either */
350 DebugEvent("Not opening domain key for [%s]", effDomain);
352 /* Each individual can either be specified on the domain key, the domains key or in the
353 net provider key. They fail over in that order. If none is found, we just use the
357 LOOKUPKEYCHAIN(opt->LogonOption, REG_DWORD, DEFAULT_LOGON_OPTION, REG_CLIENT_LOGON_OPTION_PARM);
359 /* FailLoginsSilently */
360 dwSize = sizeof(dwDummy);
361 rv = RegQueryValueEx(hkParm, REG_CLIENT_FAIL_SILENTLY_PARM, 0, &dwType, (LPBYTE) &dwDummy, &dwSize);
362 if (rv != ERROR_SUCCESS)
363 LOOKUPKEYCHAIN(dwDummy, REG_DWORD, DEFAULT_FAIL_SILENTLY, REG_CLIENT_FAIL_SILENTLY_PARM);
364 opt->failSilently = !!dwDummy;
367 LOOKUPKEYCHAIN(opt->retryInterval, REG_DWORD, DEFAULT_RETRY_INTERVAL, REG_CLIENT_RETRY_INTERVAL_PARM);
370 LOOKUPKEYCHAIN(opt->sleepInterval, REG_DWORD, DEFAULT_SLEEP_INTERVAL, REG_CLIENT_SLEEP_INTERVAL_PARM);
372 opt->logonScript = NULL;
375 if(!ISLOGONINTEGRATED(opt->LogonOption)) {
376 goto cleanup; /* no need to lookup the logon script */
379 /* come up with SMB username */
380 if(ISHIGHSECURITY(opt->LogonOption)) {
381 opt->smbName = malloc( MAXRANDOMNAMELEN );
382 GenRandomName(opt->smbName);
384 /* username and domain for logon session is not necessarily the same as
385 username and domain passed into network provider. */
386 PSECURITY_LOGON_SESSION_DATA plsd;
387 char lsaUsername[MAX_USERNAME_LENGTH];
388 char lsaDomain[MAX_DOMAIN_LENGTH];
391 LsaGetLogonSessionData(lpLogonId, &plsd);
393 UnicodeStringToANSI(plsd->UserName, lsaUsername, MAX_USERNAME_LENGTH);
394 UnicodeStringToANSI(plsd->LogonDomain, lsaDomain, MAX_DOMAIN_LENGTH);
396 DebugEvent("PLSD username[%s] domain[%s]",lsaUsername,lsaDomain);
398 if(SUCCEEDED(StringCbLength(lsaUsername, MAX_USERNAME_LENGTH, &tlen)))
403 if(SUCCEEDED(StringCbLength(lsaDomain, MAX_DOMAIN_LENGTH, &tlen)))
410 opt->smbName = malloc(len);
412 StringCbCopy(opt->smbName, len, lsaDomain);
413 StringCbCat(opt->smbName, len, "\\");
414 StringCbCat(opt->smbName, len, lsaUsername);
416 strlwr(opt->smbName);
419 LsaFreeReturnBuffer(plsd);
422 DebugEvent("Looking up logon script");
424 /* First find out where the key is */
429 rv = RegQueryValueExW(hkDom, REG_CLIENT_LOGON_SCRIPT_PARMW, 0, &dwType, NULL, &dwSize);
430 if(rv == ERROR_SUCCESS && (dwType == REG_SZ || dwType == REG_EXPAND_SZ)) {
432 DebugEvent("Located logon script in hkDom");
435 rv = RegQueryValueExW(hkDoms, REG_CLIENT_LOGON_SCRIPT_PARMW, 0, &dwType, NULL, &dwSize);
436 if(rv == ERROR_SUCCESS && !hkTemp && (dwType == REG_SZ || dwType == REG_EXPAND_SZ)) {
438 DebugEvent("Located logon script in hkDoms");
440 /* Note that the LogonScript in the NP key is only used if we are doing high security. */
441 else if(hkNp && ISHIGHSECURITY(opt->LogonOption))
442 rv = RegQueryValueExW(hkNp, REG_CLIENT_LOGON_SCRIPT_PARMW, 0, &dwType, NULL, &dwSize);
443 if(rv == ERROR_SUCCESS && !hkTemp && (dwType == REG_SZ || dwType == REG_EXPAND_SZ)) {
445 DebugEvent("Located logon script in hkNp");
449 WCHAR *regscript = NULL;
450 WCHAR *regexscript = NULL;
451 WCHAR *regexuscript = NULL;
452 WCHAR *wuname = NULL;
457 StringCbLength(opt->smbName, MAX_USERNAME_LENGTH, &len);
460 wuname = malloc(len * sizeof(WCHAR));
461 MultiByteToWideChar(CP_ACP,0,opt->smbName,-1,wuname,len*sizeof(WCHAR));
463 DebugEvent("Username is set for [%S]", wuname);
465 /* dwSize still has the size of the required buffer in bytes. */
466 regscript = malloc(dwSize);
467 rv = RegQueryValueExW(hkTemp, REG_CLIENT_LOGON_SCRIPT_PARMW, 0, &dwType, (LPBYTE) regscript, &dwSize);
468 if(rv != ERROR_SUCCESS) {/* what the ..? */
469 DebugEvent("Can't look up logon script [%d]",rv);
470 goto doneLogonScript;
473 DebugEvent("Found logon script [%S]", regscript);
475 if(dwType == REG_EXPAND_SZ) {
478 dwSize += MAX_PATH * sizeof(WCHAR); /* make room for environment expansion. */
479 regexscript = malloc(dwSize);
480 dwReq = ExpandEnvironmentStringsW(regscript, regexscript, dwSize / sizeof(WCHAR));
482 regscript = regexscript;
484 if(dwReq > (dwSize / sizeof(WCHAR))) {
485 DebugEvent("Overflow while expanding environment strings.");
486 goto doneLogonScript;
490 DebugEvent("After expanding env strings [%S]", regscript);
492 if(wcsstr(regscript, L"%s")) {
493 dwSize += len * sizeof(WCHAR); /* make room for username expansion */
494 regexuscript = (WCHAR *) LocalAlloc(LMEM_FIXED, dwSize);
495 hr = StringCbPrintfW(regexuscript, dwSize, regscript, wuname);
497 regexuscript = (WCHAR *) LocalAlloc(LMEM_FIXED, dwSize);
498 hr = StringCbCopyW(regexuscript, dwSize, regscript);
501 DebugEvent("After expanding username [%S]", regexuscript);
504 opt->logonScript = regexuscript;
506 LocalFree(regexuscript);
509 if(wuname) free(wuname);
510 if(regscript) free(regscript);
511 if(regexscript) free(regexscript);
515 if(hkNp) RegCloseKey(hkNp);
516 if(hkDom) RegCloseKey(hkDom);
517 if(hkDoms) RegCloseKey(hkDoms);
518 if(hkParm) RegCloseKey(hkParm);
521 #undef LOOKUPKEYCHAIN
523 /* Try to find out which cell the given path is in. We must retain
524 the contents of *cell in case of failure. *cell is assumed to be
525 at least cellLen chars */
526 DWORD GetFileCellName(char * path, char * cell, size_t cellLen) {
527 struct ViceIoctl blob;
528 char tcell[MAX_PATH];
532 blob.out_size = MAX_PATH;
535 code = pioctl(path, VIOC_FILE_CELL_NAME, &blob, 1);
538 strncpy(cell, tcell, cellLen);
539 cell[cellLen - 1] = '\0';
547 UnicodeStringToANSI(UNICODE_STRING uInputString, LPSTR lpszOutputString, int nOutStringLen)
551 GetCPInfo(CP_ACP, &CodePageInfo);
553 if (uInputString.Buffer && ((LPBYTE) uInputString.Buffer)[1] == '\0')
555 // Looks like unicode, better translate it
556 // UNICODE_STRING specifies the length of the buffer string in Bytes not WCHARS
557 WideCharToMultiByte(CP_ACP, 0, (LPCWSTR) uInputString.Buffer, uInputString.Length/2,
558 lpszOutputString, nOutStringLen-1, NULL, NULL);
559 lpszOutputString[min(uInputString.Length/2,nOutStringLen-1)] = '\0';
563 lpszOutputString[0] = '\0';
566 } // UnicodeStringToANSI
568 DWORD APIENTRY NPLogonNotify(
570 LPCWSTR lpAuthentInfoType,
571 LPVOID lpAuthentInfo,
572 LPCWSTR lpPreviousAuthentInfoType,
573 LPVOID lpPreviousAuthentInfo,
574 LPWSTR lpStationName,
575 LPVOID StationHandle,
576 LPWSTR *lpLogonScript)
578 char uname[MAX_USERNAME_LENGTH]="";
579 char password[MAX_PASSWORD_LENGTH]="";
580 char logonDomain[MAX_DOMAIN_LENGTH]="";
581 char cell[256]="<non-integrated logon>";
582 char homePath[MAX_PATH]="";
584 MSV1_0_INTERACTIVE_LOGON *IL;
594 DWORD LSPtype, LSPsize;
597 HWND hwndOwner = (HWND)StationHandle;
599 BOOLEAN afsWillAutoStart;
601 BOOLEAN uppercased_name = TRUE;
603 LogonOptions_t opt; /* domain specific logon options */
607 /* Make sure the AFS Libraries are initialized */
610 /* Initialize Logon Script to none */
613 /* TODO: We should check the value of lpAuthentInfoType before assuming that it is
614 MSV1_0_INTERACTIVE_LOGON though for our purposes KERB_INTERACTIVE_LOGON is
615 co-incidentally equivalent. */
616 IL = (MSV1_0_INTERACTIVE_LOGON *) lpAuthentInfo;
618 /* Are we interactive? */
619 interactive = (wcscmp(lpStationName, L"WinSta0") == 0);
621 /* Convert from Unicode to ANSI */
623 /*TODO: Use SecureZeroMemory to erase passwords */
624 UnicodeStringToANSI(IL->UserName, uname, MAX_USERNAME_LENGTH);
625 UnicodeStringToANSI(IL->Password, password, MAX_PASSWORD_LENGTH);
626 UnicodeStringToANSI(IL->LogonDomainName, logonDomain, MAX_DOMAIN_LENGTH);
628 /* Make sure AD-DOMANS sent from login that is sent to us is striped */
629 ctemp = strchr(uname, '@');
630 if (ctemp) *ctemp = 0;
632 /* is the name all uppercase? */
633 for ( ctemp = uname; *ctemp ; ctemp++) {
634 if ( islower(*ctemp) ) {
635 uppercased_name = FALSE;
640 (void) RegOpenKeyEx(HKEY_LOCAL_MACHINE, REG_CLIENT_PARMS_KEY,
641 0, KEY_QUERY_VALUE, &NPKey);
642 LSPsize=sizeof(TraceOption);
643 RegQueryValueEx(NPKey, REG_CLIENT_TRACE_OPTION_PARM, NULL,
644 &LSPtype, (LPBYTE)&TraceOption, &LSPsize);
652 GetDomainLogonOptions( lpLogonId, uname, logonDomain, &opt );
653 retryInterval = opt.retryInterval;
654 sleepInterval = opt.sleepInterval;
655 *lpLogonScript = opt.logonScript;
657 DebugEvent("Got logon script: %S",opt.logonScript);
659 afsWillAutoStart = AFSWillAutoStart();
661 DebugEvent("LogonOption[%x], Service AutoStart[%d]",
662 opt.LogonOption,afsWillAutoStart);
664 /* Check for zero length password if integrated logon*/
665 if ( ISLOGONINTEGRATED(opt.LogonOption) ) {
666 if ( password[0] == 0 ) {
667 DebugEvent("Password is the empty string");
669 reason = "zero length password is illegal";
673 /* Get cell name if doing integrated logon.
674 We might overwrite this if we are logging into an AD realm and we find out that
675 the user's home dir is in some other cell. */
676 DebugEvent("About to call cm_GetRootCellName(%s)",cell);
677 code = cm_GetRootCellName(cell);
679 DebugEvent("Unable to obtain Root Cell");
681 reason = "unknown cell";
684 DebugEvent("Cell is %s",cell);
687 /* We get the user's home directory path, if applicable, though we can't lookup the
688 cell right away because the client service may not have started yet. This call
689 also sets the AD_REALM flag in opt.flags if applicable. */
690 if(ISREMOTE(opt.flags)) {
691 DebugEvent("Is Remote");
692 GetAdHomePath(homePath,MAX_PATH,lpLogonId,&opt);
696 /* loop until AFS is started. */
698 DebugEvent("while(TRUE) LogonOption[%x], Service AutoStart[%d]",
699 opt.LogonOption,afsWillAutoStart);
701 if(ISADREALM(opt.flags)) {
702 code = GetFileCellName(homePath,cell,256);
704 DebugEvent("profile path [%s] is in cell [%s]",homePath,cell);
706 /* Don't bail out if GetFileCellName failed.
707 * The home dir may not be in AFS after all.
712 /* if Integrated Logon */
713 if (ISLOGONINTEGRATED(opt.LogonOption))
715 if ( KFW_is_available() ) {
716 code = KFW_AFS_get_cred(uname, cell, password, 0, opt.smbName, &reason);
717 DebugEvent("KFW_AFS_get_cred uname=[%s] smbname=[%s] cell=[%s] code=[%d]",uname,opt.smbName,cell,code);
720 code = ka_UserAuthenticateGeneral2(KA_USERAUTH_VERSION+KA_USERAUTH_AUTHENT_LOGON,
721 uname, "", cell, password, opt.smbName, 0, &pw_exp, 0,
723 DebugEvent("AFS AfsLogon - (INTEGRATED only)ka_UserAuthenticateGeneral2","Code[%x]",
726 if ( code && code != KTC_NOCM && code != KTC_NOCMRPC && uppercased_name ) {
727 for ( ctemp = uname; *ctemp ; ctemp++) {
728 *ctemp = tolower(*ctemp);
730 uppercased_name = FALSE;
735 /*JUST check to see if its running*/
736 if (IsServiceRunning())
739 if (!afsWillAutoStart)
743 /* is service started yet?*/
744 DebugEvent("AFS AfsLogon - ka_UserAuthenticateGeneral2","Code[%x] uname[%s] Cell[%s]",
747 /* If we've failed because the client isn't running yet and the
748 * client is set to autostart (and therefore it makes sense for
749 * us to wait for it to start) then sleep a while and try again.
750 * If the error was something else, then give up. */
751 if (code != KTC_NOCM && code != KTC_NOCMRPC || !afsWillAutoStart)
754 /* If the retry interval has expired and we still aren't
755 * logged in, then just give up if we are not in interactive
756 * mode or the failSilently flag is set, otherwise let the
757 * user know we failed and give them a chance to try again. */
758 if (retryInterval <= 0) {
759 reason = "AFS not running";
760 if (!interactive || opt.failSilently)
762 flag = MessageBox(hwndOwner,
763 "AFS is still starting. Retry?",
765 MB_ICONQUESTION | MB_RETRYCANCEL);
766 if (flag == IDCANCEL)
769 /* Wait just a little while and try again */
770 retryInterval = sleepInterval = DEFAULT_SLEEP_INTERVAL;
773 if (retryInterval < sleepInterval)
774 sleepInterval = retryInterval;
776 Sleep(sleepInterval * 1000);
778 retryInterval -= sleepInterval;
781 DebugEvent("while loop exited");
782 /* remove any kerberos 5 tickets currently held by the SYSTEM account */
783 if ( KFW_is_available() )
784 KFW_AFS_destroy_tickets_for_cell(cell);
791 StringCbPrintf(msg, sizeof(msg), "Integrated login failed: %s", reason);
793 if (ISLOGONINTEGRATED(opt.LogonOption) && interactive && !opt.failSilently)
794 MessageBox(hwndOwner, msg, "AFS Logon", MB_OK);
796 h = RegisterEventSource(NULL, AFS_LOGON_EVENT_NAME);
798 ReportEvent(h, EVENTLOG_WARNING_TYPE, 0, 1008, NULL,
800 DeregisterEventSource(h);
802 code = MapAuthError(code);
805 if (ISLOGONINTEGRATED(opt.LogonOption) && (code!=0))
808 LocalFree(*lpLogonScript);
809 *lpLogonScript = NULL;
810 if (!afsWillAutoStart) // its not running, so if not autostart or integrated logon then just skip
816 if(opt.smbName) free(opt.smbName);
818 DebugEvent("AFS AfsLogon - Exit","Return Code[%x]",code);
822 DWORD APIENTRY NPPasswordChangeNotify(
823 LPCWSTR lpAuthentInfoType,
824 LPVOID lpAuthentInfo,
825 LPCWSTR lpPreviousAuthentInfoType,
826 LPVOID lpPreviousAuthentInfo,
827 LPWSTR lpStationName,
828 LPVOID StationHandle,
831 /* Make sure the AFS Libraries are initialized */
834 DebugEvent0("AFS AfsLogon - NPPasswordChangeNotify");
840 #include <afs/vice.h>
841 #include <afs/fs_utils.h>
843 BOOL IsPathInAfs(const CHAR *strPath)
846 struct ViceIoctl blob;
850 blob.out_size = 2048;
853 code = pioctl((LPTSTR)((LPCTSTR)strPath), VIOC_FILE_CELL_NAME, &blob, 1);
860 typedef struct _WLX_NOTIFICATION_INFO {
868 PFNMSGECALLBACK pStatusCallback;
869 } WLX_NOTIFICATION_INFO, *PWLX_NOTIFICATION_INFO;
872 VOID AFS_Startup_Event( PWLX_NOTIFICATION_INFO pInfo )
874 DWORD LSPtype, LSPsize;
877 /* Make sure the AFS Libraries are initialized */
880 (void) RegOpenKeyEx(HKEY_LOCAL_MACHINE, REG_CLIENT_PARMS_KEY,
881 0, KEY_QUERY_VALUE, &NPKey);
882 LSPsize=sizeof(TraceOption);
883 RegQueryValueEx(NPKey, REG_CLIENT_TRACE_OPTION_PARM, NULL,
884 &LSPtype, (LPBYTE)&TraceOption, &LSPsize);
887 DebugEvent0("AFS_Startup_Event");
890 VOID AFS_Logoff_Event( PWLX_NOTIFICATION_INFO pInfo )
893 TCHAR profileDir[1024] = TEXT("");
895 PTOKEN_USER tokenUser = NULL;
899 /* Make sure the AFS Libraries are initialized */
902 DebugEvent0("AFS_Logoff_Event - Starting");
904 if (!GetTokenInformation(pInfo->hToken, TokenUser, NULL, 0, &retLen))
906 if ( GetLastError() == ERROR_INSUFFICIENT_BUFFER ) {
907 tokenUser = (PTOKEN_USER) LocalAlloc(LPTR, retLen);
909 if (!GetTokenInformation(pInfo->hToken, TokenUser, tokenUser, retLen, &retLen))
911 DebugEvent("GetTokenInformation failed: GLE = %lX", GetLastError());
916 /* We can't use pInfo->Domain for the domain since in the cross realm case
917 * this is source domain and not the destination domain.
919 if (QueryAdHomePathFromSid( profileDir, sizeof(profileDir), tokenUser->User.Sid, pInfo->Domain)) {
920 WCHAR Domain[64]=L"";
921 GetLocalShortDomain(Domain, sizeof(Domain));
922 if (QueryAdHomePathFromSid( profileDir, sizeof(profileDir), tokenUser->User.Sid, Domain)) {
923 if (NetUserGetProfilePath(pInfo->Domain, pInfo->UserName, profileDir, len))
924 GetUserProfileDirectory(pInfo->hToken, profileDir, &len);
928 if (strlen(profileDir)) {
929 DebugEvent("Profile Directory: %s", profileDir);
930 if (!IsPathInAfs(profileDir)) {
931 if (code = ktc_ForgetAllTokens())
932 DebugEvent("AFS_Logoff_Event - ForgetAllTokens failed [%lX]",code);
934 DebugEvent0("AFS_Logoff_Event - ForgetAllTokens succeeded");
936 DebugEvent0("AFS_Logoff_Event - Tokens left in place; profile in AFS");
939 DebugEvent0("AFS_Logoff_Event - Unable to load profile");
943 LocalFree(tokenUser);