misc-post-1366-20040804
[openafs.git] / src / WINNT / afsd / afsd_init.c
index c23efe6..96cccf0 100644 (file)
@@ -17,6 +17,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <winsock2.h>
+#include <strsafe.h>
 
 #include <osi.h>
 #include "afsd.h"
@@ -28,6 +29,7 @@
 #include "smb.h"
 #include "cm_rpc.h"
 #include "lanahelper.h"
+#include "afsicf.h"
 
 extern int RXAFSCB_ExecuteRequest(struct rx_call *z_call);
 extern int RXSTATS_ExecuteRequest(struct rx_call *z_call);
@@ -78,6 +80,12 @@ BOOL reportSessionStartups = FALSE;
 
 cm_initparams_v1 cm_initParams;
 
+char *cm_sysName = 0;
+int   cm_sysNameCount = 0;
+char *cm_sysNameList[MAXNUMSYSNAMES];
+
+DWORD TraceOption = 0;
+
 /*
  * AFSD Initialization Log
  *
@@ -107,25 +115,48 @@ afsi_start()
        char t[100], u[100], *p, *path;
        int zilch;
        int code;
+    DWORD dwLow, dwHigh;
+       HKEY parmKey;
+       DWORD dummyLen;
+    DWORD maxLogSize = 100 * 1024;
 
        afsi_file = INVALID_HANDLE_VALUE;
     if (getenv("TEMP"))
     {
-        strcpy(wd, getenv("TEMP"));
+        StringCbCopyA(wd, sizeof(wd), getenv("TEMP"));
     }
     else
     {
         code = GetWindowsDirectory(wd, sizeof(wd));
         if (code == 0) return;
     }
-       strcat(wd, "\\afsd_init.log");
+       StringCbCatA(wd, sizeof(wd), "\\afsd_init.log");
        GetTimeFormat(LOCALE_SYSTEM_DEFAULT, 0, NULL, NULL, t, sizeof(t));
        afsi_file = CreateFile(wd, GENERIC_WRITE, FILE_SHARE_READ, NULL,
                            OPEN_ALWAYS, FILE_FLAG_WRITE_THROUGH, NULL);
+
+    code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSConfigKeyName,
+                         0, KEY_QUERY_VALUE, &parmKey);
+       if (code == ERROR_SUCCESS) {
+        dummyLen = sizeof(maxLogSize);
+        code = RegQueryValueEx(parmKey, "MaxLogSize", NULL, NULL,
+                                (BYTE *) &maxLogSize, &dummyLen);
+        RegCloseKey (parmKey);
+       }
+
+    if (maxLogSize) {
+        dwLow = GetFileSize( afsi_file, &dwHigh );
+        if ( dwHigh > 0 || dwLow >= maxLogSize ) {
+            CloseHandle(afsi_file);
+            afsi_file = CreateFile( wd, GENERIC_WRITE, FILE_SHARE_READ, NULL,
+                                    CREATE_ALWAYS, FILE_FLAG_WRITE_THROUGH, NULL);
+        }
+    }
+
     SetFilePointer(afsi_file, 0, NULL, FILE_END);
        GetTimeFormat(LOCALE_SYSTEM_DEFAULT, 0, NULL, NULL, u, sizeof(u));
-       strcat(t, ": Create log file\n");
-       strcat(u, ": Created log file\n");
+       StringCbCatA(t, sizeof(t), ": Create log file\n");
+       StringCbCatA(u, sizeof(u), ": Created log file\n");
        WriteFile(afsi_file, t, strlen(t), &zilch, NULL);
        WriteFile(afsi_file, u, strlen(u), &zilch, NULL);
     p = "PATH=";
@@ -140,16 +171,16 @@ static int afsi_log_useTimestamp = 1;
 void
 afsi_log(char *pattern, ...)
 {
-       char s[100], t[100], d[100], u[300];
+       char s[256], t[100], d[100], u[512];
        int zilch;
        va_list ap;
        va_start(ap, pattern);
 
-       vsprintf(s, pattern, ap);
+       StringCbVPrintfA(s, sizeof(s), pattern, ap);
     if ( afsi_log_useTimestamp ) {
         GetTimeFormat(LOCALE_SYSTEM_DEFAULT, 0, NULL, NULL, t, sizeof(t));
                GetDateFormat(LOCALE_SYSTEM_DEFAULT, 0, NULL, NULL, d, sizeof(d));
-               sprintf(u, "%s %s: %s\n", d, t, s);
+               StringCbPrintfA(u, sizeof(u), "%s %s: %s\n", d, t, s);
         if (afsi_file != INVALID_HANDLE_VALUE)
             WriteFile(afsi_file, u, strlen(u), &zilch, NULL);
 #ifdef NOTSERVICE
@@ -175,7 +206,7 @@ void afsd_ForceTrace(BOOL flush)
         return;
 
        len = GetTempPath(sizeof(buf)-10, buf);
-       strcpy(&buf[len], "/afsd.log");
+       StringCbCopyA(&buf[len], sizeof(buf)-len, "/afsd.log");
        handle = CreateFile(buf, GENERIC_WRITE, FILE_SHARE_READ,
                            NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
        if (handle == INVALID_HANDLE_VALUE) {
@@ -188,6 +219,141 @@ void afsd_ForceTrace(BOOL flush)
        CloseHandle(handle);
 }
 
+static void
+configureBackConnectionHostNames(void)
+{
+    /* On Windows XP SP2, Windows 2003 SP1, and all future Windows operating systems
+     * there is a restriction on the use of SMB authentication on loopback connections.
+     * There are two work arounds available:
+     * 
+     *   (1) We can disable the check for matching host names.  This does not
+     *   require a reboot:
+     *   [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa]
+     *     "DisableLoopbackCheck"=dword:00000001
+     *
+     *   (2) We can add the AFS SMB/CIFS service name to an approved list.  This
+     *   does require a reboot:
+     *   [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa\MSV1_0]
+     *     "BackConnectionHostNames"=multi-sz
+     *
+     * The algorithm will be:
+     *   (1) Check to see if cm_NetbiosName exists in the BackConnectionHostNames list
+     *   (2a) If not, add it to the list.  (This will not take effect until the next reboot.)
+     *   (2b1)    and check to see if DisableLoopbackCheck is set.
+     *   (2b2)    If not set, set the DisableLoopbackCheck value to 0x1 
+     *   (2b3)                and create HKLM\SOFTWARE\OpenAFS\Client  UnsetDisableLoopbackCheck
+     *   (2c) else If cm_NetbiosName exists in the BackConnectionHostNames list,
+     *             check for the UnsetDisableLoopbackCheck value.  
+     *             If set, set the DisableLoopbackCheck flag to 0x0 
+     *             and delete the UnsetDisableLoopbackCheck value
+     */
+    HKEY hkLsa;
+    HKEY hkMSV10;
+    HKEY hkClient;
+    DWORD dwType;
+    DWORD dwSize;
+    DWORD dwValue;
+    PBYTE pHostNames = NULL, pName;
+    BOOL  bNameFound = FALSE;   
+
+    if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE, 
+                       "SYSTEM\\CurrentControlSet\\Control\\Lsa\\MSV1_0",
+                       0,
+                       KEY_READ|KEY_WRITE,
+                       &hkMSV10) == ERROR_SUCCESS )
+    {
+        if (RegQueryValueEx( hkMSV10, "BackConnectionHostNames", 0, &dwType, NULL, &dwSize) == ERROR_SUCCESS) {
+            pHostNames = malloc(dwSize + strlen(cm_NetbiosName) + 1);
+            RegQueryValueEx( hkMSV10, "BackConnectionHostNames", 0, &dwType, pHostNames, &dwSize);
+
+            for (pName = pHostNames; *pName ; pName += strlen(pName) + 1)
+            {
+                if ( !stricmp(pName, cm_NetbiosName) ) {
+                    bNameFound = TRUE;
+                    break;
+                }   
+            }
+        }
+             
+        if ( !bNameFound ) {
+            if ( !pHostNames ) {
+                pName = pHostNames = malloc(strlen(cm_NetbiosName) + 2);
+                dwSize = 1;
+            }
+            strcpy(pName, cm_NetbiosName);
+            pName += strlen(cm_NetbiosName) + 1;
+            *pName = '\0';  /* add a second nul terminator */
+
+            dwType = REG_MULTI_SZ;
+            dwSize += strlen(cm_NetbiosName) + 1;
+            RegSetValueEx( hkMSV10, "BackConnectionHostNames", 0, dwType, pHostNames, dwSize);
+
+            if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE, 
+                               "SYSTEM\\CurrentControlSet\\Control\\Lsa",
+                               0,
+                               KEY_READ|KEY_WRITE,
+                               &hkLsa) == ERROR_SUCCESS )
+            {
+                dwSize = sizeof(DWORD);
+                if ( RegQueryValueEx( hkLsa, "DisableLoopbackCheck", 0, &dwType, &dwValue, &dwSize) != ERROR_SUCCESS ||
+                     dwValue == 0 ) {
+                    dwType = REG_DWORD;
+                    dwSize = sizeof(DWORD);
+                    dwValue = 1;
+                    RegSetValueEx( hkLsa, "DisableLoopbackCheck", 0, dwType, &dwValue, dwSize);
+
+                    if (RegCreateKeyEx( HKEY_LOCAL_MACHINE, 
+                                        "SOFTWARE\\OpenAFS\\Client",
+                                        0,
+                                        NULL,
+                                        REG_OPTION_NON_VOLATILE,
+                                        KEY_READ|KEY_WRITE,
+                                        NULL,
+                                        &hkClient,
+                                        NULL) == ERROR_SUCCESS) {
+
+                        dwType = REG_DWORD;
+                        dwSize = sizeof(DWORD);
+                        dwValue = 1;
+                        RegSetValueEx( hkClient, "RemoveDisableLoopbackCheck", 0, dwType, &dwValue, dwSize);
+                        RegCloseKey(hkClient);
+                    }
+                    RegCloseKey(hkLsa);
+                }
+            }
+        } else {
+            if (RegCreateKeyEx( HKEY_LOCAL_MACHINE, 
+                                "SOFTWARE\\OpenAFS\\Client",
+                                0,
+                                NULL,
+                                REG_OPTION_NON_VOLATILE,
+                                KEY_READ|KEY_WRITE,
+                                NULL,
+                                &hkClient,
+                                NULL) == ERROR_SUCCESS) {
+
+                dwSize = sizeof(DWORD);
+                if ( RegQueryValueEx( hkClient, "RemoveDisableLoopbackCheck", 0, &dwType, &dwValue, &dwSize) == ERROR_SUCCESS &&
+                     dwValue == 1 ) {
+                    if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE, 
+                                       "SYSTEM\\CurrentControlSet\\Control\\Lsa",
+                                       0,
+                                       KEY_READ|KEY_WRITE,
+                                       &hkLsa) == ERROR_SUCCESS )
+                    {
+                        RegDeleteValue(hkLsa, "DisableLoopbackCheck");
+                        RegCloseKey(hkLsa);
+                    }
+                }
+                RegDeleteValue(hkClient, "RemoveDisableLoopbackCheck");
+                RegCloseKey(hkClient);
+            }
+        }
+        RegCloseKey(hkMSV10);
+    }
+}
+
+
 /*
  * AFSD Initialization
  */
@@ -200,8 +366,10 @@ int afsd_InitCM(char **reasonP)
        long logChunkSize;
        long stats;
        long traceBufSize;
+    long maxcpus;
        long ltt, ltto;
     long rx_mtu, rx_nojumbo;
+    long virtualCache;
        char rootCellName[256];
        struct rx_service *serverp;
        static struct rx_securityClass *nullServerSecurityClassp;
@@ -210,10 +378,12 @@ int afsd_InitCM(char **reasonP)
        char buf[200];
        HKEY parmKey;
        DWORD dummyLen;
+    DWORD regType;
        long code;
        /*int freelanceEnabled;*/
        WSADATA WSAjunk;
     lana_number_t lanaNum;
+    int i;
 
        WSAStartup(0x0101, &WSAjunk);
 
@@ -246,12 +416,53 @@ int afsd_InitCM(char **reasonP)
                FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM
                                | FORMAT_MESSAGE_ALLOCATE_BUFFER,
                              NULL, code, 0, (LPTSTR)&msgBuf, 0, NULL);
-               sprintf(buf,
+               StringCbPrintfA(buf, sizeof(buf),
                        "Failure in configuration while opening Registry: %s",
                        msgBuf);
                osi_panic(buf, __FILE__, __LINE__);
        }
 
+    dummyLen = sizeof(maxcpus);
+       code = RegQueryValueEx(parmKey, "MaxCPUs", NULL, NULL,
+                               (BYTE *) &maxcpus, &dummyLen);
+       if (code == ERROR_SUCCESS) {
+        HANDLE hProcess;
+        DWORD_PTR processAffinityMask, systemAffinityMask;
+
+        hProcess = OpenProcess(PROCESS_QUERY_INFORMATION|PROCESS_SET_INFORMATION,
+                               FALSE, GetCurrentProcessId());
+        if ( hProcess != NULL &&
+             GetProcessAffinityMask(hProcess, &processAffinityMask, &systemAffinityMask) )
+        {
+            int i, n, bits;
+            DWORD_PTR mask, newAffinityMask;
+
+#if defined(_WIN64)
+            bits = 64;
+#else
+            bits = 32;
+#endif
+            for ( i=0, n=0, mask=1, newAffinityMask=0; i<bits && n<maxcpus; i++ ) {
+                if ( processAffinityMask & mask ) {
+                    newAffinityMask |= mask;
+                    n++;
+                }
+                mask *= 2;
+            }
+
+            SetProcessAffinityMask(hProcess, newAffinityMask);
+            CloseHandle(hProcess);
+            afsi_log("CPU Restrictions set to %d cpu(s); %d cpu(s) available", maxcpus, n);
+        } else {
+            afsi_log("CPU Restrictions set to %d cpu(s); unable to access process information", maxcpus);
+        }
+    }
+
+       dummyLen = sizeof(TraceOption);
+       code = RegQueryValueEx(parmKey, "TraceOption", NULL, NULL,
+                               (BYTE *) &TraceOption, &dummyLen);
+    afsi_log("Event Log Tracing = %lX", TraceOption);
+
        dummyLen = sizeof(traceBufSize);
        code = RegQueryValueEx(parmKey, "TraceBufferSize", NULL, NULL,
                                (BYTE *) &traceBufSize, &dummyLen);
@@ -337,6 +548,7 @@ int afsd_InitCM(char **reasonP)
                afsi_log("Logoff token transfer on by default");
        }
     smb_LogoffTokenTransfer = ltt;
+    afsi_log("Logoff token transfer is currently ignored");
 
        if (ltt) {
                dummyLen = sizeof(ltto);
@@ -353,6 +565,7 @@ int afsd_InitCM(char **reasonP)
         ltto = 0;
     }
     smb_LogoffTransferTimeout = ltto;
+    afsi_log("Default logoff token is currently ignored");
 
        dummyLen = sizeof(cm_rootVolumeName);
        code = RegQueryValueEx(parmKey, "RootVolume", NULL, NULL,
@@ -360,34 +573,53 @@ int afsd_InitCM(char **reasonP)
        if (code == ERROR_SUCCESS)
                afsi_log("Root volume %s", cm_rootVolumeName);
        else {
-               strcpy(cm_rootVolumeName, "root.afs");
+               StringCbCopyA(cm_rootVolumeName, sizeof(cm_rootVolumeName), "root.afs");
                afsi_log("Default root volume name root.afs");
        }
 
        cm_mountRootLen = sizeof(cm_mountRoot);
-       code = RegQueryValueEx(parmKey, "Mountroot", NULL, NULL,
+       code = RegQueryValueEx(parmKey, "MountRoot", NULL, NULL,
                                cm_mountRoot, &cm_mountRootLen);
        if (code == ERROR_SUCCESS) {
                afsi_log("Mount root %s", cm_mountRoot);
                cm_mountRootLen = strlen(cm_mountRoot);
        } else {
-               strcpy(cm_mountRoot, "/afs");
+               StringCbCopyA(cm_mountRoot, sizeof(cm_mountRoot), "/afs");
                cm_mountRootLen = 4;
                /* Don't log */
        }
 
-       dummyLen = sizeof(cm_CachePath);
-       code = RegQueryValueEx(parmKey, "CachePath", NULL, NULL,
-                               cm_CachePath, &dummyLen);
-       if (code == ERROR_SUCCESS)
+       dummyLen = sizeof(buf);
+       code = RegQueryValueEx(parmKey, "CachePath", NULL, &regType,
+                               buf, &dummyLen);
+    if (code == ERROR_SUCCESS && buf[0]) {
+        if(regType == REG_EXPAND_SZ) {
+            dummyLen = ExpandEnvironmentStrings(buf, cm_CachePath, sizeof(cm_CachePath));
+            if(dummyLen > sizeof(cm_CachePath)) {
+                afsi_log("Cache path [%s] longer than %d after expanding env strings", buf, sizeof(cm_CachePath));
+                osi_panic("CachePath too long", __FILE__, __LINE__);
+            }
+        } else {
+            StringCbCopyA(cm_CachePath, sizeof(cm_CachePath), buf);
+        }
                afsi_log("Cache path %s", cm_CachePath);
-       else {
+    } else {
                GetWindowsDirectory(cm_CachePath, sizeof(cm_CachePath));
                cm_CachePath[2] = 0;    /* get drive letter only */
-               strcat(cm_CachePath, "\\AFSCache");
+               StringCbCatA(cm_CachePath, sizeof(cm_CachePath), "\\AFSCache");
                afsi_log("Default cache path %s", cm_CachePath);
        }
 
+    dummyLen = sizeof(virtualCache);
+    code = RegQueryValueEx(parmKey, "NonPersistentCaching", NULL, NULL,
+        &virtualCache, &dummyLen);
+    if (code == ERROR_SUCCESS && virtualCache) {
+        buf_cacheType = CM_BUF_CACHETYPE_VIRTUAL;
+    } else {
+        buf_cacheType = CM_BUF_CACHETYPE_FILE;
+    }
+    afsi_log("Cache type is %s", ((buf_cacheType == CM_BUF_CACHETYPE_FILE)?"FILE":"VIRTUAL"));
+
        dummyLen = sizeof(traceOnPanic);
        code = RegQueryValueEx(parmKey, "TrapOnPanic", NULL, NULL,
                                (BYTE *) &traceOnPanic, &dummyLen);
@@ -410,15 +642,22 @@ int afsd_InitCM(char **reasonP)
                /* Don't log */
        }
 
-       dummyLen = sizeof(cm_sysName);
+    for ( i=0; i < MAXNUMSYSNAMES; i++ ) {
+        cm_sysNameList[i] = osi_Alloc(MAXSYSNAME);
+        cm_sysNameList[i][0] = '\0';
+    }
+    cm_sysName = cm_sysNameList[0];
+
+       dummyLen = MAXSYSNAME;
        code = RegQueryValueEx(parmKey, "SysName", NULL, NULL,
                                cm_sysName, &dummyLen);
        if (code == ERROR_SUCCESS)
                afsi_log("Sys name %s", cm_sysName);
        else {
-               strcat(cm_sysName, "i386_nt40");
+               StringCbCopyA(cm_sysName, MAXSYSNAME, "i386_nt40");
                afsi_log("Default sys name %s", cm_sysName);
        }
+    cm_sysNameCount = 1;
 
        dummyLen = sizeof(cryptall);
        code = RegQueryValueEx(parmKey, "SecurityLevel", NULL, NULL,
@@ -500,6 +739,16 @@ int afsd_InitCM(char **reasonP)
     }
     afsi_log("Maximum number of VCs per server is %d", smb_maxVCPerServer);
 
+       dummyLen = sizeof(smb_authType);
+       code = RegQueryValueEx(parmKey, "SMBAuthType", NULL, NULL,
+               (BYTE *) &smb_authType, &dummyLen);
+
+       if (code != ERROR_SUCCESS || 
+        (smb_authType != SMB_AUTH_EXTENDED && smb_authType != SMB_AUTH_NTLM && smb_authType != SMB_AUTH_NONE)) {
+               smb_authType = SMB_AUTH_EXTENDED; /* default is to use extended authentication */
+       }
+       afsi_log("SMB authentication type is %s", ((smb_authType == SMB_AUTH_NONE)?"NONE":((smb_authType == SMB_AUTH_EXTENDED)?"EXTENDED":"NTLM")));
+
     dummyLen = sizeof(rx_nojumbo);
     code = RegQueryValueEx(parmKey, "RxNoJumbo", NULL, NULL,
                            (BYTE *) &rx_nojumbo, &dummyLen);
@@ -545,7 +794,7 @@ int afsd_InitCM(char **reasonP)
         afsi_log("Using >%s< as SMB server name", cm_NetbiosName);
     } else {
         /* something went horribly wrong.  We can't proceed without a netbios name */
-        sprintf(buf,"Netbios name could not be determined: %li", code);
+        StringCbPrintfA(buf,sizeof(buf),"Netbios name could not be determined: %li", code);
         osi_panic(buf, __FILE__, __LINE__);
     }
 
@@ -594,25 +843,10 @@ int afsd_InitCM(char **reasonP)
     }
 
     /* Open Microsoft Firewall to allow in port 7001 */
-    {
-        HKEY hk;
-        DWORD dwDisp;
-        TCHAR* value = TEXT("7001:UDP:*:Enabled:AFS Cache Manager Callback");
-        if (RegCreateKeyEx (HKEY_LOCAL_MACHINE, 
-                            "SYSTEM\\CurrentControlSet\\Services\\SharedAccess\\Parameters\\FirewallPolicy\\DomainProfile\\GloballyOpenP", 
-                            0, TEXT("container"), 0, KEY_SET_VALUE, NULL, &hk, &dwDisp) == ERROR_SUCCESS)
-        {
-            RegSetValueEx (hk, TEXT("7001:UDP"), 0, REG_SZ, (PBYTE)value, sizeof(TCHAR) * (1+lstrlen(value)));
-            RegCloseKey (hk);
-        }
-        if (RegCreateKeyEx (HKEY_LOCAL_MACHINE, 
-                            "SYSTEM\\CurrentControlSet\\Services\\SharedAccess\\Parameters\\FirewallPolicy\\StandardProfile\\GloballyOpenP", 
-                            0, TEXT("container"), 0, KEY_SET_VALUE, NULL, &hk, &dwDisp) == ERROR_SUCCESS)
-        {
-            RegSetValueEx (hk, TEXT("7001:UDP"), 0, REG_SZ, (PBYTE)value, sizeof(TCHAR) * (1+lstrlen(value)));
-            RegCloseKey (hk);
-        }
-    }
+    icf_CheckAndAddAFSPorts(AFS_PORTSET_CLIENT);
+
+    /* Ensure the AFS Netbios Name is registered to allow loopback access */
+    configureBackConnectionHostNames();
 
        /* initialize RX, and tell it to listen to port 7001, which is used for
      * callback RPC messages.
@@ -726,6 +960,7 @@ int afsd_InitDaemons(char **reasonP)
        /* this should really be in an init daemon from here on down */
 
     if (!cm_freelanceEnabled) {
+               osi_Log0(afsd_logp, "Loading Root Volume from cell");
         code = cm_GetVolumeByName(cm_rootCellp, cm_rootVolumeName, cm_rootUserp,
                                   &req, CM_FLAG_CREATE, &cm_rootVolumep);
         afsi_log("cm_GetVolumeByName code %x root vol %x", code,