From b4b61821081d809bb3a737f9e23964f4f99b3c58 Mon Sep 17 00:00:00 2001 From: Jeffrey Altman Date: Tue, 7 Apr 2009 15:05:30 +0000 Subject: [PATCH] windows-smb-registry-config-20090407 LICENSE MIT Move configureBackConnectionHostNames() to smb_StartListeners() so that when the NetbiosName changes while the service is running the new values can be set. Add configureExtendedSMBSessionTimeouts() which configures new SMB functionality added in a Win2003 post-SP2 hot fix. --- src/WINNT/afsd/afsd_init.c | 166 +------------------------- src/WINNT/afsd/smb.c | 290 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 295 insertions(+), 161 deletions(-) diff --git a/src/WINNT/afsd/afsd_init.c b/src/WINNT/afsd/afsd_init.c index ec603a2..032e589 100644 --- a/src/WINNT/afsd/afsd_init.c +++ b/src/WINNT/afsd/afsd_init.c @@ -86,8 +86,8 @@ char cm_HostName[200]; long cm_HostAddr; unsigned short cm_callbackport = CM_DEFAULT_CALLBACKPORT; -char cm_NetbiosName[MAX_NB_NAME_LENGTH] = ""; -clientchar_t cm_NetbiosNameC[MAX_NB_NAME_LENGTH] = _C(""); +char cm_NetbiosName[MAX_NB_NAME_LENGTH] = "NOT.YET.SET"; +clientchar_t cm_NetbiosNameC[MAX_NB_NAME_LENGTH] = _C("NOT.YET.SET"); char cm_CachePath[MAX_PATH]; DWORD cm_ValidateCache = 1; @@ -240,159 +240,6 @@ 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 - * - * Starting in Longhorn Beta 1, an entry in the BackConnectionHostNames value will - * force Windows to use the loopback authentication mechanism for the specified - * services. - */ - HKEY hkLsa; - HKEY hkMSV10; - HKEY hkClient; - DWORD dwType; - DWORD dwSize, dwAllocSize; - DWORD dwValue; - PBYTE pHostNames = NULL, pName = NULL; - 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, &dwAllocSize) == ERROR_SUCCESS) && - (dwType == REG_MULTI_SZ)) - { - dwAllocSize += 1 /* in case the source string is not nul terminated */ - + strlen(cm_NetbiosName) + 2; - pHostNames = malloc(dwAllocSize); - dwSize = dwAllocSize; - if (RegQueryValueEx( hkMSV10, "BackConnectionHostNames", 0, &dwType, - pHostNames, &dwSize) == ERROR_SUCCESS) - { - for (pName = pHostNames; - (pName - pHostNames < (int) dwSize) && *pName ; - pName += strlen(pName) + 1) - { - if ( !stricmp(pName, cm_NetbiosName) ) { - bNameFound = TRUE; - break; - } - } - } - } - - if ( !bNameFound ) { - size_t size = strlen(cm_NetbiosName) + 2; - if ( !pHostNames ) { - pHostNames = malloc(size); - pName = pHostNames; - } - StringCbCopyA(pName, size, cm_NetbiosName); - pName += size - 1; - *pName = '\0'; /* add a second nul terminator */ - - dwType = REG_MULTI_SZ; - dwSize = pName - pHostNames + 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, (LPBYTE)&dwValue, &dwSize) != ERROR_SUCCESS || - dwValue == 0 ) { - dwType = REG_DWORD; - dwSize = sizeof(DWORD); - dwValue = 1; - RegSetValueEx( hkLsa, "DisableLoopbackCheck", 0, dwType, (LPBYTE)&dwValue, dwSize); - - if (RegCreateKeyEx( HKEY_LOCAL_MACHINE, - AFSREG_CLT_OPENAFS_SUBKEY, - 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, (LPBYTE)&dwValue, dwSize); - RegCloseKey(hkClient); - } - RegCloseKey(hkLsa); - } - } - } else { - if (RegCreateKeyEx( HKEY_LOCAL_MACHINE, - AFSREG_CLT_OPENAFS_SUBKEY, - 0, - NULL, - REG_OPTION_NON_VOLATILE, - KEY_READ|KEY_WRITE, - NULL, - &hkClient, - NULL) == ERROR_SUCCESS) { - - dwSize = sizeof(DWORD); - if ( RegQueryValueEx( hkClient, "RemoveDisableLoopbackCheck", 0, &dwType, (LPBYTE)&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); - } - - if (pHostNames) - free(pHostNames); -} - - static void afsd_InitServerPreferences(void) { HKEY hkPrefs = 0; @@ -900,15 +747,15 @@ int afsd_InitCM(char **reasonP) (LPBYTE) cm_mountRootC, &cm_mountRootCLen); if (code == ERROR_SUCCESS) { afsi_log("Mount root %S", cm_mountRootC); - cm_mountRootCLen = cm_ClientStrLen(cm_mountRootC); + cm_mountRootCLen = (DWORD)cm_ClientStrLen(cm_mountRootC); } else { cm_ClientStrCpy(cm_mountRootC, lengthof(cm_mountRootC), _C("/afs")); - cm_mountRootCLen = cm_ClientStrLen(cm_mountRootC); + cm_mountRootCLen = (DWORD)cm_ClientStrLen(cm_mountRootC); /* Don't log */ } cm_ClientStringToFsString(cm_mountRootC, -1, cm_mountRoot, lengthof(cm_mountRoot)); - cm_mountRootLen = cm_FsStrLen(cm_mountRoot); + cm_mountRootLen = (DWORD)cm_FsStrLen(cm_mountRoot); dummyLen = sizeof(buf); code = RegQueryValueEx(parmKey, "CachePath", NULL, ®Type, @@ -1327,9 +1174,6 @@ int afsd_InitCM(char **reasonP) cm_initParams.setTime = 0; cm_initParams.memCache = 1; - /* Ensure the AFS Netbios Name is registered to allow loopback access */ - configureBackConnectionHostNames(); - /* init user daemon, and other packages */ cm_InitUser(); diff --git a/src/WINNT/afsd/smb.c b/src/WINNT/afsd/smb.c index 357df62..6d34102 100644 --- a/src/WINNT/afsd/smb.c +++ b/src/WINNT/afsd/smb.c @@ -9409,6 +9409,290 @@ exit_thread: } 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 + * + * Starting in Longhorn Beta 1, an entry in the BackConnectionHostNames value will + * force Windows to use the loopback authentication mechanism for the specified + * services. + */ + HKEY hkLsa; + HKEY hkMSV10; + HKEY hkClient; + DWORD dwType; + DWORD dwSize, dwAllocSize; + DWORD dwValue; + PBYTE pHostNames = NULL, pName = NULL; + BOOL bNameFound = FALSE; + + /* BackConnectionHostNames and DisableLoopbackCheck */ + 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, &dwAllocSize) == ERROR_SUCCESS) && + (dwType == REG_MULTI_SZ)) + { + dwAllocSize += 1 /* in case the source string is not nul terminated */ + + (DWORD)strlen(cm_NetbiosName) + 2; + pHostNames = malloc(dwAllocSize); + dwSize = dwAllocSize; + if (RegQueryValueEx( hkMSV10, "BackConnectionHostNames", 0, &dwType, + pHostNames, &dwSize) == ERROR_SUCCESS) + { + for (pName = pHostNames; + (pName - pHostNames < (int) dwSize) && *pName ; + pName += strlen(pName) + 1) + { + if ( !stricmp(pName, cm_NetbiosName) ) { + bNameFound = TRUE; + break; + } + } + } + } + + if ( !bNameFound ) { + size_t size = strlen(cm_NetbiosName) + 2; + if ( !pHostNames ) { + pHostNames = malloc(size); + pName = pHostNames; + } + StringCbCopyA(pName, size, cm_NetbiosName); + pName += size - 1; + *pName = '\0'; /* add a second nul terminator */ + + dwType = REG_MULTI_SZ; + dwSize = (DWORD)(pName - pHostNames + 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, (LPBYTE)&dwValue, &dwSize) != ERROR_SUCCESS || + dwValue == 0 ) { + dwType = REG_DWORD; + dwSize = sizeof(DWORD); + dwValue = 1; + RegSetValueEx( hkLsa, "DisableLoopbackCheck", 0, dwType, (LPBYTE)&dwValue, dwSize); + + if (RegCreateKeyEx( HKEY_LOCAL_MACHINE, + AFSREG_CLT_OPENAFS_SUBKEY, + 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, (LPBYTE)&dwValue, dwSize); + RegCloseKey(hkClient); + } + RegCloseKey(hkLsa); + } + } + } else { + if (RegCreateKeyEx( HKEY_LOCAL_MACHINE, + AFSREG_CLT_OPENAFS_SUBKEY, + 0, + NULL, + REG_OPTION_NON_VOLATILE, + KEY_READ|KEY_WRITE, + NULL, + &hkClient, + NULL) == ERROR_SUCCESS) { + + dwSize = sizeof(DWORD); + if ( RegQueryValueEx( hkClient, "RemoveDisableLoopbackCheck", 0, &dwType, (LPBYTE)&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); + } + } + + if (pHostNames) { + free(pHostNames); + pHostNames = NULL; + } + + RegCloseKey(hkMSV10); + } +} + + +static void +configureExtendedSMBSessionTimeouts(void) +{ + /* + * In a Hot Fix to Windows 2003 SP2, the smb redirector was given the following + * new functionality: + * + * [HKLM\SYSTEM\CurrentControlSet\Services\LanManWorkstation\Parameters] + * "ReconnectableServers" REG_MULTI_SZ + * "ExtendedSessTimeout" REG_DWORD (seconds) + * "ServersWithExtendedSessTimeout" REG_MULTI_SZ + * + * These values can be used to prevent the smb redirector from timing out + * smb connection to the afs smb server prematurely. + */ + HKEY hkLanMan; + DWORD dwType; + DWORD dwSize, dwAllocSize; + DWORD dwValue; + PBYTE pHostNames = NULL, pName = NULL; + BOOL bNameFound = FALSE; + + if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE, + "SYSTEM\\CurrentControlSet\\Services\\LanManWorkstation\\Parameters", + 0, + KEY_READ|KEY_WRITE, + &hkLanMan) == ERROR_SUCCESS ) + { + if ((RegQueryValueEx( hkLanMan, "ReconnectableServers", 0, + &dwType, NULL, &dwAllocSize) == ERROR_SUCCESS) && + (dwType == REG_MULTI_SZ)) + { + dwAllocSize += 1 /* in case the source string is not nul terminated */ + + (DWORD)strlen(cm_NetbiosName) + 2; + pHostNames = malloc(dwAllocSize); + dwSize = dwAllocSize; + if (RegQueryValueEx( hkLanMan, "ReconnectableServers", 0, &dwType, + pHostNames, &dwSize) == ERROR_SUCCESS) + { + for (pName = pHostNames; + (pName - pHostNames < (int) dwSize) && *pName ; + pName += strlen(pName) + 1) + { + if ( !stricmp(pName, cm_NetbiosName) ) { + bNameFound = TRUE; + break; + } + } + } + } + + if ( !bNameFound ) { + size_t size = strlen(cm_NetbiosName) + 2; + if ( !pHostNames ) { + pHostNames = malloc(size); + pName = pHostNames; + } + StringCbCopyA(pName, size, cm_NetbiosName); + pName += size - 1; + *pName = '\0'; /* add a second nul terminator */ + + dwType = REG_MULTI_SZ; + dwSize = (DWORD)(pName - pHostNames + 1); + RegSetValueEx( hkLanMan, "ReconnectableServers", 0, dwType, pHostNames, dwSize); + } + + if (pHostNames) { + free(pHostNames); + pHostNames = NULL; + } + + if ((RegQueryValueEx( hkLanMan, "ServersWithExtendedSessTimeout", 0, + &dwType, NULL, &dwAllocSize) == ERROR_SUCCESS) && + (dwType == REG_MULTI_SZ)) + { + dwAllocSize += 1 /* in case the source string is not nul terminated */ + + (DWORD)strlen(cm_NetbiosName) + 2; + pHostNames = malloc(dwAllocSize); + dwSize = dwAllocSize; + if (RegQueryValueEx( hkLanMan, "ServersWithExtendedSessTimeout", 0, &dwType, + pHostNames, &dwSize) == ERROR_SUCCESS) + { + for (pName = pHostNames; + (pName - pHostNames < (int) dwSize) && *pName ; + pName += strlen(pName) + 1) + { + if ( !stricmp(pName, cm_NetbiosName) ) { + bNameFound = TRUE; + break; + } + } + } + } + + if ( !bNameFound ) { + size_t size = strlen(cm_NetbiosName) + 2; + if ( !pHostNames ) { + pHostNames = malloc(size); + pName = pHostNames; + } + StringCbCopyA(pName, size, cm_NetbiosName); + pName += size - 1; + *pName = '\0'; /* add a second nul terminator */ + + dwType = REG_MULTI_SZ; + dwSize = (DWORD)(pName - pHostNames + 1); + RegSetValueEx( hkLanMan, "ServersWithExtendedSessTimeout", 0, dwType, pHostNames, dwSize); + } + + if (pHostNames) { + free(pHostNames); + pHostNames = NULL; + } + + if ((RegQueryValueEx( hkLanMan, "ExtendedSessTimeout", 0, + &dwType, (LPBYTE)&dwValue, &dwAllocSize) != ERROR_SUCCESS) || + (dwType != REG_DWORD)) + { + dwType = REG_DWORD; + dwSize = sizeof(dwValue); + dwValue = 600; /* 10 minutes */ + RegSetValueEx( hkLanMan, "ExtendedSessTimeout", 0, dwType, (const BYTE *)&dwValue, dwSize); + } + RegCloseKey(hkLanMan); + } +} + +static void smb_LanAdapterChangeThread(void *param) { /* @@ -9702,6 +9986,12 @@ void smb_StartListeners(int locked) } afsi_log("smb_StartListeners"); + /* Ensure the AFS Netbios Name is registered to allow loopback access */ + configureBackConnectionHostNames(); + + /* Configure Extended SMB Session Timeouts */ + configureExtendedSMBSessionTimeouts(); + smb_ListenerState = SMB_LISTENER_STARTED; cm_VolStatus_Network_Started(cm_NetbiosName #ifdef _WIN64 -- 1.9.4