Windows: NPLogonNotify provide password in all cases
[openafs.git] / src / WINNT / afsd / afslogon.c
index be5876e..e2c89c0 100644 (file)
@@ -1,12 +1,16 @@
 /*
  * Copyright 2000, International Business Machines Corporation and others.
  * All Rights Reserved.
- * 
+ *
  * This software has been released under the terms of the IBM Public
  * License.  For details, see the LICENSE file in the top-level source
  * directory or online at http://www.openafs.org/dl/license10.html
  */
 
+#include <afsconfig.h>
+#include <afs/param.h>
+#include <roken.h>
+
 #include "afslogon.h"
 
 #include <io.h>
@@ -18,7 +22,6 @@
 #include <lm.h>
 #include <nb30.h>
 
-#include <afs/param.h>
 #include <afs/stds.h>
 #include <afs/pioctl_nt.h>
 #include <afs/kautils.h>
@@ -42,13 +45,13 @@ HANDLE hDLL;
 
 #define AFS_LOGON_EVENT_NAME TEXT("AFS Logon")
 
-void DebugEvent0(char *a) 
+void DebugEvent0(char *a)
 {
     HANDLE h; char *ptbuf[1];
-    
+
     if (!ISLOGONTRACE(TraceOption))
         return;
-    
+
     h = RegisterEventSource(NULL, AFS_LOGON_EVENT_NAME);
     if (h != INVALID_HANDLE_VALUE) {
         ptbuf[0] = a;
@@ -58,7 +61,7 @@ void DebugEvent0(char *a)
 }
 
 #define MAXBUF_ 512
-void DebugEvent(char *b,...) 
+void DebugEvent(char *b,...)
 {
     HANDLE h; char *ptbuf[1],buf[MAXBUF_+1];
     va_list marker;
@@ -116,21 +119,21 @@ void AfsLogonInit(void)
 {
     if ( bInit == FALSE ) {
         if ( WaitForSingleObject( hInitMutex, INFINITE ) == WAIT_OBJECT_0 ) {
-           /* initAFSDirPath() initializes an array and sets a 
+           /* initAFSDirPath() initializes an array and sets a
             * flag so that the initialization can only occur
-            * once.  No cleanup will be done when the DLL is 
-            * unloaded so the initialization will not be 
+            * once.  No cleanup will be done when the DLL is
+            * unloaded so the initialization will not be
             * performed again on a subsequent reload
             */
            initAFSDirPath();
 
            /* ka_Init initializes a number of error tables.
-            * and then calls ka_CellConfig() which grabs 
+            * and then calls ka_CellConfig() which grabs
             * an afsconf_dir structure via afsconf_Open().
             * Upon a second attempt to call ka_CellConfig()
             * the structure will be released with afsconf_Close()
             * and then re-opened.  Could this corrupt memory?
-            * 
+            *
             * We only need this if we are not using KFW.
             */
            if (!KFW_is_available())
@@ -231,10 +234,10 @@ DWORD APIENTRY NPGetCaps(DWORD index)
     default:
         return 0;
     }
-}       
+}
 
-NET_API_STATUS 
-NetUserGetProfilePath( LPCWSTR Domain, LPCWSTR UserName, char * profilePath, 
+NET_API_STATUS
+NetUserGetProfilePath( LPCWSTR Domain, LPCWSTR UserName, char * profilePath,
                        DWORD profilePathLen )
 {
     NET_API_STATUS code;
@@ -243,7 +246,7 @@ NetUserGetProfilePath( LPCWSTR Domain, LPCWSTR UserName, char * profilePath,
 
     NetGetAnyDCName(NULL, Domain, (LPBYTE *)&ServerName);
     /* if NetGetAnyDCName fails, ServerName == NULL
-     * NetUserGetInfo will obtain local user information 
+     * NetUserGetInfo will obtain local user information
      */
     code = NetUserGetInfo(ServerName, UserName, 3, (LPBYTE *)&p3);
     if (code == NERR_Success)
@@ -263,7 +266,7 @@ NetUserGetProfilePath( LPCWSTR Domain, LPCWSTR UserName, char * profilePath,
             NetApiBufferFree(p3);
         }
     }
-    if (ServerName) 
+    if (ServerName)
         NetApiBufferFree(ServerName);
     return code;
 }
@@ -288,7 +291,7 @@ BOOL IsServiceRunning (void)
     }
     DebugEvent("AFS AfsLogon - Test Service Running Return Code[%x] ?Running[%d]",Status.dwCurrentState,(Status.dwCurrentState == SERVICE_RUNNING));
     return (Status.dwCurrentState == SERVICE_RUNNING);
-}   
+}
 
 BOOL IsServiceStartPending (void)
 {
@@ -310,7 +313,7 @@ BOOL IsServiceStartPending (void)
     }
     DebugEvent("AFS AfsLogon - Test Service Start Pending Return Code[%x] ?Start Pending[%d]",Status.dwCurrentState,(Status.dwCurrentState == SERVICE_START_PENDING));
     return (Status.dwCurrentState == SERVICE_START_PENDING);
-}   
+}
 
 /* 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)
@@ -348,7 +351,7 @@ BOOL IsServiceStartPending (void)
 /* Get domain specific configuration info.  We are returning void because if anything goes wrong
    we just return defaults.
  */
-void 
+void
 GetDomainLogonOptions( PLUID lpLogonId, char * username, char * domain, LogonOptions_t *opt ) {
     HKEY hkParm = NULL; /* Service parameter */
     HKEY hkNp = NULL;   /* network provider key */
@@ -412,7 +415,7 @@ GetDomainLogonOptions( PLUID lpLogonId, char * username, char * domain, LogonOpt
         DebugEvent0("Not opening domain key");
 
     /* Each individual can either be specified on the domain key, the domains key or in the
-       net provider key.  They fail over in that order.  If none is found, we just use the 
+       net provider key.  They fail over in that order.  If none is found, we just use the
        defaults. */
 
     /* LogonOption */
@@ -457,7 +460,7 @@ GetDomainLogonOptions( PLUID lpLogonId, char * username, char * domain, LogonOpt
             DebugEvent("LsaGetLogonSessionData failed [0x%x]", Status);
             goto bad_strings;
         }
-        
+
         if (!UnicodeStringToANSI(plsd->UserName, lsaUsername, MAX_USERNAME_LENGTH))
             goto bad_strings;
 
@@ -497,7 +500,7 @@ GetDomainLogonOptions( PLUID lpLogonId, char * username, char * domain, LogonOpt
 
         DebugEvent("Constructing username using [%s] and [%s]",
                    username, domain);
+
         len = strlen(username) + strlen(domain) + 2;
 
         opt->smbName = malloc(len);
@@ -641,7 +644,7 @@ GetDomainLogonOptions( PLUID lpLogonId, char * username, char * domain, LogonOpt
     }
 
     if (hkTemp) {
-        CHAR * thesecells = NULL;
+        CHAR * thesecells = NULL, *p;
 
         /* dwSize still has the size of the required buffer in bytes. */
         thesecells = malloc(dwSize*2);
@@ -655,9 +658,16 @@ GetDomainLogonOptions( PLUID lpLogonId, char * username, char * domain, LogonOpt
             goto doneTheseCells;
         }
 
-        DebugEvent("Found TheseCells [%s]", thesecells);
-        opt->theseCells = thesecells;
-        thesecells = NULL;
+        /* TheseCells is a REG_MULTI_SZ */
+        if ( thesecells && thesecells[0]) {
+            for ( p=thesecells; *p; p += (strlen(p) + 1)) {
+                DebugEvent("Found TheseCells [%s]", p);
+            }
+            opt->theseCells = thesecells;
+            thesecells = NULL;
+        } else {
+            DebugEvent("TheseCells [REG_MULTI_SZ] not found");
+        }
 
       doneTheseCells:
         if (thesecells) free(thesecells);
@@ -716,7 +726,7 @@ GetDomainLogonOptions( PLUID lpLogonId, char * username, char * domain, LogonOpt
     if(hkDom) RegCloseKey(hkDom);
     if(hkDoms) RegCloseKey(hkDoms);
     if(hkParm) RegCloseKey(hkParm);
-}       
+}
 
 #undef LOOKUPKEYCHAIN
 
@@ -739,7 +749,7 @@ DWORD GetFileCellName(char * path, char * cell, size_t cellLen) {
         cell[cellLen - 1] = '\0';
     }
     return code;
-}       
+}
 
 
 static BOOL
@@ -753,7 +763,7 @@ UnicodeStringToANSI(UNICODE_STRING uInputString, LPSTR lpszOutputString, int nOu
     if (CodePageInfo.MaxCharSize > 1)
         // Only supporting non-Unicode strings
         return FALSE;
-    
+
     if (uInputString.Buffer && ((LPBYTE) uInputString.Buffer)[1] == '\0')
     {
         // Looks like unicode, better translate it
@@ -763,7 +773,7 @@ UnicodeStringToANSI(UNICODE_STRING uInputString, LPSTR lpszOutputString, int nOu
         lpszOutputString[min(uInputString.Length/2,nOutStringLen-1)] = '\0';
         return TRUE;
     }
-      
+
     lpszOutputString[0] = '\0';
     return FALSE;
 }  // UnicodeStringToANSI
@@ -832,11 +842,11 @@ DWORD APIENTRY NPLogonNotify(
 
     /* Initialize Logon Script to none */
     *lpLogonScript=NULL;
-    
+
     /* MSV1_0_INTERACTIVE_LOGON and KERB_INTERACTIVE_LOGON are equivalent for
      * our purposes */
 
-    if ( wcsicmp(lpAuthentInfoType,L"MSV1_0:Interactive") && 
+    if ( wcsicmp(lpAuthentInfoType,L"MSV1_0:Interactive") &&
          wcsicmp(lpAuthentInfoType,L"Kerberos:Interactive") )
     {
         DebugEvent("Unsupported Authentication Info Type: %S",
@@ -854,7 +864,7 @@ DWORD APIENTRY NPLogonNotify(
         !UnicodeStringToANSI(IL->LogonDomainName, logonDomain, MAX_DOMAIN_LENGTH))
        return 0;
 
-    /* Make sure AD-DOMAINS sent from login that is sent to us is striped */
+    /* Make sure AD-DOMAINS sent from login that is sent to us is stripped */
     ctemp = strchr(uname, '@');
     if (ctemp) {
         *ctemp = 0;
@@ -883,13 +893,13 @@ DWORD APIENTRY NPLogonNotify(
     if (retryInterval < sleepInterval)
         sleepInterval = retryInterval;
 
-    DebugEvent("Got logon script: %S",opt.logonScript);
+    DebugEvent("Got logon script: [%S]", opt.logonScript);
 
     afsWillAutoStart = AFSWillAutoStart();
 
     DebugEvent("LogonOption[%x], Service AutoStart[%d]",
                 opt.LogonOption,afsWillAutoStart);
-    
+
     /* Check for zero length password if integrated logon*/
     if ( ISLOGONINTEGRATED(opt.LogonOption) )  {
         if ( password[0] == 0 ) {
@@ -899,19 +909,19 @@ DWORD APIENTRY NPLogonNotify(
             code=0;
         }
 
-        /* Get cell name if doing integrated logon.  
+        /* Get cell name if doing integrated logon.
            We might overwrite this if we are logging into an AD realm and we find out that
            the user's home dir is in some other cell. */
-        DebugEvent("About to call cm_GetRootCellName(%s)",cell);
+        DebugEvent("About to call cm_GetRootCellName()");
         code = cm_GetRootCellName(cell);
-        if (code < 0) { 
+        if (code < 0) {
             DebugEvent0("Unable to obtain Root Cell");
             code = KTC_NOCELL;
             reason = "unknown cell";
             code=0;
         } else {
-            DebugEvent("Cell is %s",cell);
-        }       
+            DebugEvent("Default cell is %s", cell);
+        }
 
         /* 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
@@ -934,14 +944,14 @@ DWORD APIENTRY NPLogonNotify(
                    DebugEvent("profile path [%s] is in cell [%s]",homePath,cell);
                }
                /* Don't bail out if GetFileCellName failed.
-                * The home dir may not be in AFS after all. 
+                * The home dir may not be in AFS after all.
                 */
            } else
                code=0;
-               
+
            /* if Integrated Logon  */
            if (ISLOGONINTEGRATED(opt.LogonOption))
-           {                   
+           {
                if ( KFW_is_available() ) {
                    SetEnvironmentVariable(DO_NOT_REGISTER_VARNAME, "");
                     if (opt.realm) {
@@ -971,7 +981,7 @@ DWORD APIENTRY NPLogonNotify(
                                     uname,opt.smbName,cell,code);
                     }
                    SetEnvironmentVariable(DO_NOT_REGISTER_VARNAME, NULL);
-                   if (code == 0 && opt.theseCells) { 
+                   if (code == 0 && opt.theseCells) {
                        char * principal, *p;
                        size_t len, tlen;
 
@@ -998,7 +1008,7 @@ DWORD APIENTRY NPLogonNotify(
                            while ( *p ) {
                                 if ( cm_stricmp_utf8(p, cell) ) {
                                     SetEnvironmentVariable(DO_NOT_REGISTER_VARNAME, "");
-                                    code2 = KFW_AFS_get_cred(principal, p, 0, 0, opt.smbName, &reason);
+                                    code2 = KFW_AFS_get_cred(principal, p, password, 0, opt.smbName, &reason);
                                     SetEnvironmentVariable(DO_NOT_REGISTER_VARNAME, NULL);
                                     DebugEvent("KFW_AFS_get_cred  uname=[%s] smbname=[%s] cell=[%s] code=[%d]",
                                                principal,opt.smbName,p,code2);
@@ -1014,7 +1024,7 @@ DWORD APIENTRY NPLogonNotify(
                                                        &reason);
                    DebugEvent("AFS AfsLogon - (INTEGRATED only)ka_UserAuthenticateGeneral2 Code[%x] uname[%s] smbname=[%s] Cell[%s] PwExp=[%d] Reason=[%s]",
                                code,uname,opt.smbName,cell,pw_exp,reason?reason:"");
-               }       
+               }
                if ( code && code != KTC_NOCM && code != KTC_NOCMRPC && !lowercased_name ) {
                    for ( ctemp = uname; *ctemp ; ctemp++) {
                        *ctemp = tolower(*ctemp);
@@ -1027,12 +1037,12 @@ DWORD APIENTRY NPLogonNotify(
 
                /* 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. 
+                * 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)
                    break;
            }
-           else {  
+           else {
                /*JUST check to see if its running*/
                if (IsServiceRunning())
                    break;
@@ -1070,7 +1080,7 @@ DWORD APIENTRY NPLogonNotify(
     DebugEvent0("while loop exited");
 
     /* remove any kerberos 5 tickets currently held by the SYSTEM account
-     * for this user 
+     * for this user
      */
 
     if (ISLOGONINTEGRATED(opt.LogonOption) && KFW_is_available()) {
@@ -1096,7 +1106,7 @@ DWORD APIENTRY NPLogonNotify(
        ReportEvent(h, EVENTLOG_WARNING_TYPE, 0, 1008, NULL,
                     1, 0, ptbuf, NULL);
        DeregisterEventSource(h);
-           
+
         code = MapAuthError(code);
         SetLastError(code);
 
@@ -1116,7 +1126,7 @@ DWORD APIENTRY NPLogonNotify(
 
     DebugEvent("AFS AfsLogon - Exit","Return Code[%x]",code);
     return code;
-}       
+}
 
 DWORD APIENTRY NPPasswordChangeNotify(
        LPCWSTR lpAuthentInfoType,
@@ -1165,14 +1175,14 @@ BOOL IsPathInAfs(const CHAR *strPath)
 }
 
 #ifdef COMMENT
-typedef struct _WLX_NOTIFICATION_INFO {  
-    ULONG Size;  
-    ULONG Flags;  
-    PWSTR UserName;  
-    PWSTR Domain;  
-    PWSTR WindowStation;  
-    HANDLE hToken;  
-    HDESK hDesktop;  
+typedef struct _WLX_NOTIFICATION_INFO {
+    ULONG Size;
+    ULONG Flags;
+    PWSTR UserName;
+    PWSTR Domain;
+    PWSTR WindowStation;
+    HANDLE hToken;
+    HDESK hDesktop;
     PFNMSGECALLBACK pStatusCallback;
 } WLX_NOTIFICATION_INFO, *PWLX_NOTIFICATION_INFO;
 #endif
@@ -1251,7 +1261,7 @@ VOID AFS_Logoff_Event( PWLX_NOTIFICATION_INFO pInfo )
                }
            }
 
-           /* We can't use pInfo->Domain for the domain since in the cross realm case 
+           /* We can't use pInfo->Domain for the domain since in the cross realm case
             * this is source domain and not the destination domain.
             */
            if (tokenUser && QueryAdHomePathFromSid( profileDir, sizeof(profileDir), tokenUser->User.Sid, pInfo->Domain)) {
@@ -1291,7 +1301,7 @@ VOID AFS_Logoff_Event( PWLX_NOTIFICATION_INFO pInfo )
     }
 
     DebugEvent0("AFS_Logoff_Event - End");
-}   
+}
 
 VOID AFS_Logon_Event( PWLX_NOTIFICATION_INFO pInfo )
 {
@@ -1327,7 +1337,7 @@ VOID AFS_Logon_Event( PWLX_NOTIFICATION_INFO pInfo )
         StringCchLengthW(pInfo->UserName, MAX_USERNAME_LENGTH, &szlen);
         WideCharToMultiByte(CP_UTF8, 0, pInfo->UserName, szlen,
                             username, sizeof(username), NULL, NULL);
-        
+
         StringCchLengthW(pInfo->Domain, MAX_DOMAIN_LENGTH, &szlen);
         WideCharToMultiByte(CP_UTF8, 0, pInfo->Domain, szlen,
                             domain, sizeof(domain), NULL, NULL);
@@ -1341,7 +1351,7 @@ VOID AFS_Logon_Event( PWLX_NOTIFICATION_INFO pInfo )
            DebugEvent0("AFS_Logon_Event - No pInfo->Domain");
     }
 
-    DebugEvent("AFS_Logon_Event - opt.LogonOption = %lX opt.flags = %lX", 
+    DebugEvent("AFS_Logon_Event - opt.LogonOption = %lX opt.flags = %lX",
                opt.LogonOption, opt.flags);
 
     if (!ISLOGONINTEGRATED(opt.LogonOption) || !ISREMOTE(opt.flags)) {
@@ -1363,7 +1373,7 @@ VOID AFS_Logon_Event( PWLX_NOTIFICATION_INFO pInfo )
         }
     }
 
-    /* We can't use pInfo->Domain for the domain since in the cross realm case 
+    /* We can't use pInfo->Domain for the domain since in the cross realm case
      * this is source domain and not the destination domain.
      */
     if (tokenUser && QueryAdHomePathFromSid( profileDir, sizeof(profileDir), tokenUser->User.Sid, pInfo->Domain)) {
@@ -1374,7 +1384,7 @@ VOID AFS_Logon_Event( PWLX_NOTIFICATION_INFO pInfo )
                 GetUserProfileDirectory(pInfo->hToken, profileDir, &len);
         }
     }
-    
+
     if (strlen(profileDir)) {
         DebugEvent("AFS_Logon_Event - Profile Directory: %s", profileDir);
     } else {
@@ -1405,7 +1415,7 @@ VOID AFS_Logon_Event( PWLX_NOTIFICATION_INFO pInfo )
                         szPath, szUserA,res);
         else
             DebugEvent0("AFS_Logon_Event - WNetAddConnection2() succeeded");
-    } else 
+    } else
         DebugEvent("AFS_Logon_Event - User name conversion failed: GLE = 0x%X",GetLastError());
 
     if ( tokenUser )
@@ -1491,22 +1501,22 @@ VOID KFW_Logon_Event( PWLX_NOTIFICATION_INFO pInfo )
     }
 
     strcat(filename, "\\");
-    strcat(filename, szLogonId);    
+    strcat(filename, szLogonId);
 
-    hf = CreateFile(filename, FILE_ALL_ACCESS, 0, NULL, OPEN_EXISTING, 
+    hf = CreateFile(filename, FILE_ALL_ACCESS, 0, NULL, OPEN_EXISTING,
                     FILE_ATTRIBUTE_NORMAL, NULL);
     if (hf == INVALID_HANDLE_VALUE) {
        DebugEvent0("KFW_Logon_Event - file cannot be opened");
        return;
     }
     CloseHandle(hf);
+
     if (KFW_AFS_set_file_cache_dacl(filename, pInfo->hToken)) {
        DebugEvent0("KFW_Logon_Event - unable to set dacl");
        DeleteFile(filename);
        return;
     }
+
     if (KFW_AFS_obtain_user_temp_directory(pInfo->hToken, newfilename, sizeof(newfilename))) {
        DebugEvent0("KFW_Logon_Event - unable to obtain temp directory");
        return;
@@ -1518,9 +1528,9 @@ VOID KFW_Logon_Event( PWLX_NOTIFICATION_INFO pInfo )
     }
 
     strcat(newfilename, "\\");
-    strcat(newfilename, szLogonId);    
+    strcat(newfilename, szLogonId);
 
-    if (!MoveFileEx(filename, newfilename, 
+    if (!MoveFileEx(filename, newfilename,
                     MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH)) {
         DebugEvent("KFW_Logon_Event - MoveFileEx failed GLE = 0x%x", GetLastError());
        return;
@@ -1539,7 +1549,7 @@ VOID KFW_Logon_Event( PWLX_NOTIFICATION_INFO pInfo )
                              NULL,
                              NULL,
                              &startupinfo,
-                             &procinfo)) 
+                             &procinfo))
     {
        DebugEvent("KFW_Logon_Event - CommandLine %s", commandline);