From 91d38b93566734734f559a84c38a09e5c7d530c0 Mon Sep 17 00:00:00 2001 From: Jeffrey Altman Date: Sat, 18 Feb 2012 19:57:25 -0500 Subject: [PATCH] Windows: Dereg Lanman and Lsa reg values for afsredir If the machine has been upgraded from an AFS SMB Server to the AFS Redirector, the registry will have leftover configuration for the "AFS" netbios name in the Lsa BackConnectionHostNames value and the LanmanWorkstation ReconnectableServers and ServersWithExtendedSessTimeout values. These values are not useful with the AFS Redirector since \\AFS is owned by afsredir.sys and not the SMB redirector. Remove the "AFS" netbios name from these values when afsd_service.exe has started in redirector mode. Change-Id: If8c100d3569595645c041ac58fedb1c835f9129f Reviewed-on: http://gerrit.openafs.org/6737 Tested-by: BuildBot Reviewed-by: Jeffrey Altman Tested-by: Jeffrey Altman --- src/WINNT/afsd/afsd_init.c | 17 ++ src/WINNT/afsd/smb.c | 340 +++++++++++++++++++++++++++---------- src/WINNT/afsd/smb.h | 2 + 3 files changed, 272 insertions(+), 87 deletions(-) diff --git a/src/WINNT/afsd/afsd_init.c b/src/WINNT/afsd/afsd_init.c index e6d9da2da..b3760459a 100644 --- a/src/WINNT/afsd/afsd_init.c +++ b/src/WINNT/afsd/afsd_init.c @@ -860,6 +860,17 @@ afsd_InitCM(char **reasonP) smb_LogoffTransferTimeout = ltto; afsi_log("Logoff token transfer timeout %d seconds", ltto); + dummyLen = sizeof(cm_NetbiosName); + code = RegQueryValueEx(parmKey, "NetbiosName", NULL, NULL, + (LPBYTE) cm_NetbiosName, &dummyLen); + if (code == ERROR_SUCCESS) + afsi_log("NetbiosName %s", cm_NetbiosName); + else { + cm_FsStrCpy(cm_NetbiosName, lengthof(cm_NetbiosName), "AFS"); + afsi_log("Default NetbiosName AFS"); + } + cm_Utf8ToClientString(cm_NetbiosName, -1, cm_NetbiosNameC, MAX_NB_NAME_LENGTH); + dummyLen = sizeof(cm_rootVolumeName); code = RegQueryValueEx(parmKey, "RootVolume", NULL, NULL, (LPBYTE) cm_rootVolumeName, &dummyLen); @@ -1585,6 +1596,12 @@ int afsd_InitSMB(char **reasonP, void *aMBfunc) smb_Init(afsd_logp, smb_UseV3, numSvThreads, aMBfunc); afsi_log("smb_Init complete"); } else { + smb_configureBackConnectionHostNames(FALSE); + + if (msftSMBRedirectorSupportsExtendedTimeouts()) { + afsi_log("Microsoft SMB Redirector supports Extended Timeouts"); + smb_configureExtendedSMBSessionTimeouts(FALSE); + } afsi_log("smb_Init skipped"); } diff --git a/src/WINNT/afsd/smb.c b/src/WINNT/afsd/smb.c index 2b7df2206..8c8045a0b 100644 --- a/src/WINNT/afsd/smb.c +++ b/src/WINNT/afsd/smb.c @@ -10002,8 +10002,8 @@ exit_thread: return; } -static void -configureBackConnectionHostNames(void) +void +smb_configureBackConnectionHostNames(int bEnable) { /* 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. @@ -10044,10 +10044,31 @@ configureBackConnectionHostNames(void) DWORD dwSize, dwAllocSize; DWORD dwValue; PBYTE pHostNames = NULL, pName = NULL; + PBYTE pOrigNames = NULL, pOrig = NULL; BOOL bNameFound = FALSE; + DWORD dwLoopbackCheckDisabled; + DWORD dwszBackConnectionHostNames; + size_t nbsize = strlen(cm_NetbiosName) + 2; + size_t len; static BOOL bLoopbackCheckDisabled = FALSE; - /* BackConnectionHostNames and DisableLoopbackCheck */ + /* DisableLoopbackCheck */ + 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)&dwLoopbackCheckDisabled, &dwSize) != ERROR_SUCCESS) + { + dwLoopbackCheckDisabled = 0; + } + } else { + hkLsa = INVALID_HANDLE_VALUE; + } + + /* BackConnectionHostNames */ if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Control\\Lsa\\MSV1_0", 0, @@ -10061,12 +10082,12 @@ configureBackConnectionHostNames(void) dwAllocSize += 1 /* in case the source string is not nul terminated */ + (DWORD)strlen(cm_NetbiosName) + 2; pHostNames = malloc(dwAllocSize); - dwSize = dwAllocSize; + dwszBackConnectionHostNames = dwAllocSize; if (RegQueryValueEx( hkMSV10, "BackConnectionHostNames", 0, &dwType, - pHostNames, &dwSize) == ERROR_SUCCESS) + pHostNames, &dwszBackConnectionHostNames) == ERROR_SUCCESS) { for (pName = pHostNames; - (pName - pHostNames < (int) dwSize) && *pName ; + (pName - pHostNames < (int) dwszBackConnectionHostNames) && *pName ; pName += strlen(pName) + 1) { if ( !stricmp(pName, cm_NetbiosName) ) { @@ -10077,33 +10098,27 @@ configureBackConnectionHostNames(void) } } - 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 */ + if ( bEnable ) { + 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); + 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 ) { + if ( hkLsa != INVALID_HANDLE_VALUE && !dwLoopbackCheckDisabled) + { dwType = REG_DWORD; dwSize = sizeof(DWORD); - dwValue = 1; - RegSetValueEx( hkLsa, "DisableLoopbackCheck", 0, dwType, (LPBYTE)&dwValue, dwSize); + dwLoopbackCheckDisabled = 1; + RegSetValueEx( hkLsa, "DisableLoopbackCheck", 0, dwType, (LPBYTE)&dwLoopbackCheckDisabled, dwSize); if (RegCreateKeyEx( HKEY_LOCAL_MACHINE, AFSREG_CLT_OPENAFS_SUBKEY, @@ -10122,36 +10137,83 @@ configureBackConnectionHostNames(void) bLoopbackCheckDisabled = TRUE; RegCloseKey(hkClient); } - RegCloseKey(hkLsa); } + } else if (!bLoopbackCheckDisabled && hkLsa != INVALID_HANDLE_VALUE) { + 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 ) { + RegDeleteValue(hkLsa, "DisableLoopbackCheck"); + } + } + RegDeleteValue(hkClient, "RemoveDisableLoopbackCheck"); + RegCloseKey(hkClient); } - } else if (!bLoopbackCheckDisabled) { - 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 ) - { + } else { + /* + * Disable SMB. Start by removing the DisableLoopbackCheck value if present. + */ + if (hkLsa != INVALID_HANDLE_VALUE) { + 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 ) { RegDeleteValue(hkLsa, "DisableLoopbackCheck"); - RegCloseKey(hkLsa); } } RegDeleteValue(hkClient, "RemoveDisableLoopbackCheck"); RegCloseKey(hkClient); } + + /* Then remove our NetbiosName from the BackConnectionHostNames list */ + if ( bNameFound ) { + /* + * we found our name so if the size of the value is smaller + * or equal to the length of our name alone, we are done. + */ + if ( dwszBackConnectionHostNames <= nbsize ) { + RegDeleteValue( hkMSV10, "BackConnectionHostNames"); + } else { + pOrigNames = pHostNames; + pHostNames = malloc(dwAllocSize); + + pOrig = pOrigNames; + pName = pHostNames; + while (pOrig - pOrigNames < dwszBackConnectionHostNames) { + len = strlen(pOrig); + if ( stricmp(pOrig, cm_NetbiosName)) { + /* not our name */ + StringCbCopyA(pName, dwAllocSize - (pName - pHostNames), pOrig); + pName += len + 1; + } + pOrig += len + 1; + } + *pName = '\0'; /* add a second nul terminator */ + pName++; + + dwType = REG_MULTI_SZ; + dwSize = (DWORD)(pName - pHostNames + 1); + RegSetValueEx( hkMSV10, "BackConnectionHostNames", 0, dwType, pHostNames, dwSize); + } + } } if (pHostNames) { @@ -10159,19 +10221,28 @@ configureBackConnectionHostNames(void) pHostNames = NULL; } + if (pOrigNames) { + free(pOrigNames); + pOrigNames = NULL; + } + RegCloseKey(hkMSV10); } + + if ( hkLsa != INVALID_HANDLE_VALUE ) { + RegCloseKey(hkLsa); + } } -static void -configureExtendedSMBSessionTimeouts(void) +void +smb_configureExtendedSMBSessionTimeouts(int bEnable) { /* * In a Hot Fix to Windows 2003 SP2, the smb redirector was given the following * new functionality: * - * [HKLM\SYSTEM\CurrentControlSet\Services\LanManWorkstation\Parameters] + * [HKLM\SYSTEM\CurrentControlSet\Services\LanmanWorkstation\Parameters] * "ReconnectableServers" REG_MULTI_SZ * "ExtendedSessTimeout" REG_DWORD (seconds) * "ServersWithExtendedSessTimeout" REG_MULTI_SZ @@ -10179,32 +10250,36 @@ configureExtendedSMBSessionTimeouts(void) * These values can be used to prevent the smb redirector from timing out * smb connection to the afs smb server prematurely. */ - HKEY hkLanMan; + HKEY hkLanman; DWORD dwType; DWORD dwSize, dwAllocSize; DWORD dwValue; - PBYTE pHostNames = NULL, pName = NULL; + PBYTE pHostNames = NULL, pOrigNames = NULL, pName = NULL, pOrig = NULL; BOOL bNameFound = FALSE; + DWORD dwszReconnectableServers; + DWORD dwszServersWithExtendedSessTimeout; + size_t nbsize = strlen(cm_NetbiosName) + 2; + size_t len; if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE, - "SYSTEM\\CurrentControlSet\\Services\\LanManWorkstation\\Parameters", + "SYSTEM\\CurrentControlSet\\Services\\LanmanWorkstation\\Parameters", 0, KEY_READ|KEY_WRITE, - &hkLanMan) == ERROR_SUCCESS ) + &hkLanman) == ERROR_SUCCESS ) { - if ((RegQueryValueEx( hkLanMan, "ReconnectableServers", 0, + 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) + dwszReconnectableServers = dwAllocSize; + if (RegQueryValueEx( hkLanman, "ReconnectableServers", 0, &dwType, + pHostNames, &dwszReconnectableServers) == ERROR_SUCCESS) { for (pName = pHostNames; - (pName - pHostNames < (int) dwSize) && *pName ; + (pName - pHostNames < (int) dwszReconnectableServers) && *pName ; pName += strlen(pName) + 1) { if ( !stricmp(pName, cm_NetbiosName) ) { @@ -10215,19 +10290,58 @@ configureExtendedSMBSessionTimeouts(void) } } - if ( !bNameFound ) { - size_t size = strlen(cm_NetbiosName) + 2; + /* + * If our name was not found and we are enabling SMB, + * add our name to the current value. + */ + if ( bEnable && !bNameFound ) { if ( !pHostNames ) { - pHostNames = malloc(size); + pHostNames = malloc(nbsize); pName = pHostNames; } - StringCbCopyA(pName, size, cm_NetbiosName); - pName += size - 1; + StringCbCopyA(pName, nbsize, cm_NetbiosName); + pName += nbsize - 1; *pName = '\0'; /* add a second nul terminator */ dwType = REG_MULTI_SZ; dwSize = (DWORD)(pName - pHostNames + 1); - RegSetValueEx( hkLanMan, "ReconnectableServers", 0, dwType, pHostNames, dwSize); + RegSetValueEx( hkLanman, "ReconnectableServers", 0, dwType, pHostNames, dwSize); + } + + /* + * If our name was found and we are disabling SMB, + * remove our name from the list and update the value. + * If our name is the only entry, remove the value. + */ + if ( !bEnable && bNameFound ) { + /* + * we found our name so if the size of the value is smaller + * or equal to the length of our name alone, we are done. + */ + if ( dwszReconnectableServers <= nbsize ) { + RegDeleteValue( hkLanman, "ReconnectableServers"); + } else { + pOrigNames = pHostNames; + pHostNames = malloc(dwAllocSize); + + pOrig = pOrigNames; + pName = pHostNames; + while (pOrig - pOrigNames