windows-logon-20050323
[openafs.git] / src / WINNT / afsd / afslogon.c
index afeede0..0e9788e 100644 (file)
@@ -14,7 +14,7 @@
 #include <sys/types.h>
 #include <fcntl.h>
 
-#include <winsock2.h> ]
+#include <winsock2.h>
 #include <lm.h>
 
 #include <afs/param.h>
@@ -27,6 +27,8 @@
 #include "krb.h"
 #include "afskfw.h"
 
+#include <WINNT\afsreg.h>
+
 DWORD TraceOption = 0;
 
 HANDLE hDLL;
@@ -197,19 +199,18 @@ DWORD APIENTRY NPGetCaps(DWORD index)
     }
 }       
 
-static NET_API_STATUS 
-NetUserGetProfilePath( LPCWSTR Domain, LPCWSTR UserName, char * profilePath, DWORD profilePathLen )
+NET_API_STATUS 
+NetUserGetProfilePath( LPCWSTR Domain, LPCWSTR UserName, char * profilePath, 
+                       DWORD profilePathLen )
 {
     NET_API_STATUS code;
     LPWSTR ServerName = NULL;
     LPUSER_INFO_3 p3 = NULL;
 
-    code = NetGetAnyDCName(NULL, Domain, (LPBYTE *)&ServerName);
-    if (code != NERR_Success)
-        return code;
-    if (ServerName == NULL)
-        return NERR_InvalidComputer;
-
+    NetGetAnyDCName(NULL, Domain, (LPBYTE *)&ServerName);
+    /* if NetGetAnyDCName fails, ServerName == NULL
+     * NetUserGetInfo will obtain local user information 
+     */
     code = NetUserGetInfo(ServerName, UserName, 3, (LPBYTE *)&p3);
     if (code == NERR_Success)
     {
@@ -217,19 +218,21 @@ NetUserGetProfilePath( LPCWSTR Domain, LPCWSTR UserName, char * profilePath, DWO
         if (p3) {
             if (p3->usri3_profile) {
                 DWORD len = lstrlenW(p3->usri3_profile);
-
-                /* Convert From Unicode to ASCII */
-                len = len < profilePathLen ? len : profilePathLen - 1;
-                CharToOemBuffW(p3->usri3_profile, profilePath, len);
-                profilePath[len] = '\0';
-                code = NERR_Success;
+                if (len > 0) {
+                    /* Convert From Unicode to ANSI (UTF-8 for future) */
+                    len = len < profilePathLen ? len : profilePathLen - 1;
+                    WideCharToMultiByte(CP_UTF8, 0, p3->usri3_profile, len, profilePath, len, NULL, NULL);
+                    profilePath[len] = '\0';
+                    code = NERR_Success;
+                }
             }
             NetApiBufferFree(p3);
         }
     }
-    NetApiBufferFree(ServerName);
+    if (ServerName) 
+        NetApiBufferFree(ServerName);
     return code;
-}       
+}
 
 BOOL IsServiceRunning (void)
 {
@@ -253,6 +256,28 @@ BOOL IsServiceRunning (void)
     return (Status.dwCurrentState == SERVICE_RUNNING);
 }   
 
+BOOL IsServiceStartPending (void)
+{
+    SERVICE_STATUS Status;
+    SC_HANDLE hManager;
+    memset (&Status, 0x00, sizeof(Status));
+    Status.dwCurrentState = SERVICE_STOPPED;
+
+    if ((hManager = OpenSCManager (NULL, NULL, GENERIC_READ)) != NULL)
+    {
+        SC_HANDLE hService;
+        if ((hService = OpenService (hManager, TEXT("TransarcAFSDaemon"), GENERIC_READ)) != NULL)
+        {
+            QueryServiceStatus (hService, &Status);
+            CloseServiceHandle (hService);
+        }
+
+        CloseServiceHandle (hManager);
+    }
+    DebugEvent("AFS AfsLogon - Test Service Start Pending","Return Code[%x] ?Start Pending[%d]",Status.dwCurrentState,(Status.dwCurrentState == SERVICE_START_PENDING));
+    return (Status.dwCurrentState == SERVICE_RUNNING);
+}   
+
 /* LOOKUPKEYCHAIN: macro to look up the value in the list of keys in order until it's found
    v:variable to receive value (reference type)
    t:type
@@ -300,6 +325,8 @@ GetDomainLogonOptions( PLUID lpLogonId, char * username, char * domain, LogonOpt
     char computerName[MAX_COMPUTERNAME_LENGTH + 1];
     char *effDomain;
 
+    memset(opt, 0, sizeof(LogonOptions_t));
+
     DebugEvent("In GetDomainLogonOptions for user [%s] in domain [%s]", username, domain);
     /* If the domain is the same as the Netbios computer name, we use the LOCALHOST domain name*/
     opt->flags = LOGON_FLAG_REMOTE;
@@ -316,13 +343,13 @@ GetDomainLogonOptions( PLUID lpLogonId, char * username, char * domain, LogonOpt
     } else
         effDomain = NULL;
 
-    rv = RegOpenKeyEx( HKEY_LOCAL_MACHINE, REG_CLIENT_PARMS_KEY, 0, KEY_READ, &hkParm );
+    rv = RegOpenKeyEx( HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY, 0, KEY_READ, &hkParm );
     if(rv != ERROR_SUCCESS) {
         hkParm = NULL;
         DebugEvent("GetDomainLogonOption: Can't open parms key [%d]", rv);
     }
 
-    rv = RegOpenKeyEx( HKEY_LOCAL_MACHINE, REG_CLIENT_PROVIDER_KEY, 0, KEY_READ, &hkNp );
+    rv = RegOpenKeyEx( HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PROVIDER_SUBKEY, 0, KEY_READ, &hkNp );
     if(rv != ERROR_SUCCESS) {
         hkNp = NULL;
         DebugEvent("GetDomainLogonOptions: Can't open NP key [%d]", rv);
@@ -510,6 +537,48 @@ GetDomainLogonOptions( PLUID lpLogonId, char * username, char * domain, LogonOpt
         if(regexscript) free(regexscript);
     }
 
+    DebugEvent("Looking up TheseCells");
+    /* Logon script */
+    /* First find out where the key is */
+    hkTemp = NULL;
+    rv = ~ERROR_SUCCESS;
+    dwType = 0;
+    if (hkDom)
+        rv = RegQueryValueEx(hkDom, REG_CLIENT_THESE_CELLS_PARM, 0, &dwType, NULL, &dwSize);
+    if (rv == ERROR_SUCCESS && dwType == REG_MULTI_SZ) {
+        hkTemp = hkDom;
+        DebugEvent("Located TheseCells in hkDom");
+    } else if (hkDoms)
+        rv = RegQueryValueEx(hkDoms, REG_CLIENT_THESE_CELLS_PARM, 0, &dwType, NULL, &dwSize);
+    if (rv == ERROR_SUCCESS && !hkTemp && dwType == REG_MULTI_SZ) {
+        hkTemp = hkDoms;
+        DebugEvent("Located TheseCells in hkDoms");
+    } else if (hkNp)
+        rv = RegQueryValueEx(hkNp, REG_CLIENT_THESE_CELLS_PARM, 0, &dwType, NULL, &dwSize);
+    if (rv == ERROR_SUCCESS && !hkTemp && dwType == REG_MULTI_SZ) {
+        hkTemp = hkNp;
+        DebugEvent("Located TheseCells in hkNp");
+    }
+
+    if (hkTemp) {
+        HRESULT hr;
+        size_t len;
+        CHAR * thesecells;
+
+        /* dwSize still has the size of the required buffer in bytes. */
+        thesecells = malloc(dwSize);
+        rv = RegQueryValueEx(hkTemp, REG_CLIENT_THESE_CELLS_PARM, 0, &dwType, (LPBYTE) thesecells, &dwSize);
+        if(rv != ERROR_SUCCESS) {/* what the ..? */
+            DebugEvent("Can't look up TheseCells [%d]",rv);
+            goto doneTheseCells;
+        }
+
+        DebugEvent("Found TheseCells [%s]", thesecells);
+        opt->theseCells = thesecells;
+
+      doneTheseCells:;
+    }
+
   cleanup:
     if(hkNp) RegCloseKey(hkNp);
     if(hkDom) RegCloseKey(hkDom);
@@ -562,8 +631,8 @@ UnicodeStringToANSI(UNICODE_STRING uInputString, LPSTR lpszOutputString, int nOu
         lpszOutputString[min(uInputString.Length/2,nOutStringLen-1)] = '\0';
         return TRUE;
     }
-       else
-               lpszOutputString[0] = '\0';
+    else
+        lpszOutputString[0] = '\0';
     return FALSE;
 }  // UnicodeStringToANSI
 
@@ -600,7 +669,7 @@ DWORD APIENTRY NPLogonNotify(
 
     BOOLEAN afsWillAutoStart;
 
-    BOOLEAN uppercased_name = TRUE;
+    BOOLEAN lowercased_name = TRUE;
 
     LogonOptions_t opt; /* domain specific logon options */
     int retryInterval;
@@ -631,15 +700,15 @@ DWORD APIENTRY NPLogonNotify(
     ctemp = strchr(uname, '@');
     if (ctemp) *ctemp = 0;
 
-    /* is the name all uppercase? */
+    /* is the name all lowercase? */
     for ( ctemp = uname; *ctemp ; ctemp++) {
-        if ( islower(*ctemp) ) {
-            uppercased_name = FALSE;
+        if ( !islower(*ctemp) ) {
+            lowercased_name = FALSE;
             break;
         }
     }
 
-    (void) RegOpenKeyEx(HKEY_LOCAL_MACHINE, REG_CLIENT_PARMS_KEY,
+    (void) RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY,
                          0, KEY_QUERY_VALUE, &NPKey);
     LSPsize=sizeof(TraceOption);
     RegQueryValueEx(NPKey, REG_CLIENT_TRACE_OPTION_PARM, NULL,
@@ -656,6 +725,9 @@ DWORD APIENTRY NPLogonNotify(
     sleepInterval = opt.sleepInterval;
     *lpLogonScript = opt.logonScript;
 
+    if (retryInterval < sleepInterval)
+        sleepInterval = retryInterval;
+
     DebugEvent("Got logon script: %S",opt.logonScript);
 
     afsWillAutoStart = AFSWillAutoStart();
@@ -689,7 +761,7 @@ DWORD APIENTRY NPLogonNotify(
         /* We get the user's home directory path, if applicable, though we can't lookup the
            cell right away because the client service may not have started yet. This call
            also sets the AD_REALM flag in opt.flags if applicable. */
-        if(ISREMOTE(opt.flags)) {
+        if (ISREMOTE(opt.flags)) {
             DebugEvent("Is Remote");
             GetAdHomePath(homePath,MAX_PATH,lpLogonId,&opt);
         }       
@@ -700,9 +772,9 @@ DWORD APIENTRY NPLogonNotify(
         DebugEvent("while(TRUE) LogonOption[%x], Service AutoStart[%d]",
                     opt.LogonOption,afsWillAutoStart);
 
-        if(ISADREALM(opt.flags)) {
+        if (ISADREALM(opt.flags)) {
             code = GetFileCellName(homePath,cell,256);
-            if(!code) {
+            if (!code) {
                 DebugEvent("profile path [%s] is in cell [%s]",homePath,cell);
             }
             /* Don't bail out if GetFileCellName failed.
@@ -717,42 +789,65 @@ DWORD APIENTRY NPLogonNotify(
             if ( KFW_is_available() ) {
                 code = KFW_AFS_get_cred(uname, cell, password, 0, opt.smbName, &reason);
                 DebugEvent("KFW_AFS_get_cred  uname=[%s] smbname=[%s] cell=[%s] code=[%d]",uname,opt.smbName,cell,code);
-            }
-            else {
+                if (code == 0 && opt.theseCells) { 
+                    char * principal, *p;
+
+                    principal = (char *)malloc(strlen(uname) + strlen(cell) + 2);
+                    if ( principal ) {
+                        strcpy(principal, uname);
+                        p = principal + strlen(uname);
+                        *p++ = '@';
+                        strcpy(p, cell);
+                        for ( ;*p; p++) {
+                            *p = toupper(*p);
+                        }
+
+                        p = opt.theseCells;
+                        while ( *p ) {
+                            code = KFW_AFS_get_cred(principal, p, 0, 0, opt.smbName, &reason);
+                            DebugEvent("KFW_AFS_get_cred  uname=[%s] smbname=[%s] cell=[%s] code=[%d]",
+                                        principal,opt.smbName,p,code);
+                            p += strlen(p) + 1;
+                        }
+                        
+                        free(principal);
+                    }
+                }
+            } else {
                 code = ka_UserAuthenticateGeneral2(KA_USERAUTH_VERSION+KA_USERAUTH_AUTHENT_LOGON,
                                                     uname, "", cell, password, opt.smbName, 0, &pw_exp, 0,
                                                     &reason);
-                DebugEvent("AFS AfsLogon - (INTEGRATED only)ka_UserAuthenticateGeneral2","Code[%x]",
-                            code);
+                DebugEvent("AFS AfsLogon - (INTEGRATED only)ka_UserAuthenticateGeneral2","Code[%x] uname[%s] Cell[%s]",
+                            code,uname,cell);
             }       
-            if ( code && code != KTC_NOCM && code != KTC_NOCMRPC && uppercased_name ) {
+            if ( code && code != KTC_NOCM && code != KTC_NOCMRPC && !lowercased_name ) {
                 for ( ctemp = uname; *ctemp ; ctemp++) {
                     *ctemp = tolower(*ctemp);
                 }
-                uppercased_name = FALSE;
-                continue;
+                lowercased_name = TRUE;
+                goto sleeping;
             }
+
+            /* is service started yet?*/
+
+            /* If we've failed because the client isn't running yet and the
+            * client is set to autostart (and therefore it makes sense for
+            * us to wait for it to start) then sleep a while and try again. 
+            * If the error was something else, then give up. */
+            if (code != KTC_NOCM && code != KTC_NOCMRPC || !afsWillAutoStart)
+                break;
         }
         else {  
             /*JUST check to see if its running*/
             if (IsServiceRunning())
                 break;
-            code = KTC_NOCM;
-            if (!afsWillAutoStart)
+            if (afsWillAutoStart && !IsServiceStartPending()) {
+                code = KTC_NOCMRPC;
+                reason = "AFS Service start failed";
                 break;
+            }
         }
 
-        /* is service started yet?*/
-        DebugEvent("AFS AfsLogon - ka_UserAuthenticateGeneral2","Code[%x] uname[%s] Cell[%s]",
-                    code,uname,cell);
-
-        /* If we've failed because the client isn't running yet and the
-         * client is set to autostart (and therefore it makes sense for
-         * us to wait for it to start) then sleep a while and try again. 
-         * If the error was something else, then give up. */
-        if (code != KTC_NOCM && code != KTC_NOCMRPC || !afsWillAutoStart)
-            break;
-
         /* If the retry interval has expired and we still aren't
          * logged in, then just give up if we are not in interactive
          * mode or the failSilently flag is set, otherwise let the
@@ -769,14 +864,11 @@ DWORD APIENTRY NPLogonNotify(
                 break;
 
             /* Wait just a little while and try again */
-            retryInterval = sleepInterval = DEFAULT_SLEEP_INTERVAL;
+            retryInterval = opt.retryInterval;
         }
 
-        if (retryInterval < sleepInterval)
-            sleepInterval = retryInterval;
-
+      sleeping:
         Sleep(sleepInterval * 1000);
-
         retryInterval -= sleepInterval;
     }
 
@@ -811,11 +903,11 @@ DWORD APIENTRY NPLogonNotify(
             *lpLogonScript = NULL;
             if (!afsWillAutoStart)     // its not running, so if not autostart or integrated logon then just skip
                 code = 0;
-
         }
     }
 
-    if(opt.smbName) free(opt.smbName);
+    if (opt.theseCells) free(opt.theseCells);
+    if (opt.smbName) free(opt.smbName);
 
     DebugEvent("AFS AfsLogon - Exit","Return Code[%x]",code);
     return code;
@@ -879,7 +971,7 @@ VOID AFS_Startup_Event( PWLX_NOTIFICATION_INFO pInfo )
     /* Make sure the AFS Libraries are initialized */
     AfsLogonInit();
 
-    (void) RegOpenKeyEx(HKEY_LOCAL_MACHINE, REG_CLIENT_PARMS_KEY,
+    (void) RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY,
                         0, KEY_QUERY_VALUE, &NPKey);
     LSPsize=sizeof(TraceOption);
     RegQueryValueEx(NPKey, REG_CLIENT_TRACE_OPTION_PARM, NULL,
@@ -892,8 +984,8 @@ VOID AFS_Startup_Event( PWLX_NOTIFICATION_INFO pInfo )
 VOID AFS_Logoff_Event( PWLX_NOTIFICATION_INFO pInfo )
 {
     DWORD code;
-    TCHAR profileDir[256] = TEXT("");
-    DWORD  len = 256;
+    TCHAR profileDir[1024] = TEXT("");
+    DWORD  len = 1024;
     PTOKEN_USER  tokenUser = NULL;
     DWORD  retLen;
     HANDLE hToken;
@@ -922,7 +1014,7 @@ VOID AFS_Logoff_Event( PWLX_NOTIFICATION_INFO pInfo )
         WCHAR Domain[64]=L"";
         GetLocalShortDomain(Domain, sizeof(Domain));
         if (QueryAdHomePathFromSid( profileDir, sizeof(profileDir), tokenUser->User.Sid, Domain)) {
-            if (NetUserGetProfilePath(pInfo->Domain, pInfo->UserName, profileDir, &len))
+            if (NetUserGetProfilePath(pInfo->Domain, pInfo->UserName, profileDir, len))
                 GetUserProfileDirectory(pInfo->hToken, profileDir, &len);
         }
     }