From 17584782a4d76facf5a89a3eeeebfcc23582b3e8 Mon Sep 17 00:00:00 2001 From: Jeffrey Altman Date: Mon, 25 Jun 2012 23:06:30 -0400 Subject: [PATCH] Windows: afslogon expand short domain names Depending on how the user specifies the domain name during login, NPLogonNotify may be given a short or a full domain or kerberos realm name. If the name is the short name, attempt to expand it automatically if there is no 'realm' configured for the short domain name. This patchset relies upon data in the local registry instead of using an API such as NameTranslate in order to avoid network queries to the domain controller that might not be reachable. Change-Id: Ib2cd08bca5223fa847a462520074bb758191539d Reviewed-on: http://gerrit.openafs.org/7650 Tested-by: BuildBot Reviewed-by: Jeffrey Altman Tested-by: Jeffrey Altman --- src/WINNT/afsd/afslogon.c | 103 +++++++++++++++++++++++++++++++++++++- 1 file changed, 102 insertions(+), 1 deletion(-) diff --git a/src/WINNT/afsd/afslogon.c b/src/WINNT/afsd/afslogon.c index 52b9a3f5f6..d3e3821bb5 100644 --- a/src/WINNT/afsd/afslogon.c +++ b/src/WINNT/afsd/afslogon.c @@ -366,6 +366,86 @@ BOOL StartTheService (void) return (gle == 0); } +char * +FindFullDomainName(const char *short_domain) +{ + /* + * Possible sources of domain or realm information: + * + * HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Group Policy\History + * MachineDomain REG_SZ + * + * HKLM\SYSTEM\CurrentControlSet\Control\Lsa\CachedMachineNames + * NameUserPrincipal REG_SZ MACHINE$@DOMAIN + * + * HKLM\SYSTEM\CurrentControlSet\Control\Lsa\Kerberos\Domains\ + */ + + LONG rv; + HKEY hk = NULL; + DWORD dwType; + DWORD dwSize; + char * domain; + size_t short_domain_len; + + if (short_domain == NULL) + return NULL; + + short_domain_len = strlen(short_domain); + + /* First look for this machine's Active Directory domain */ + rv = RegOpenKeyEx( HKEY_LOCAL_MACHINE, + "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Group Policy\\History", + 0, KEY_READ, &hk); + if (rv == ERROR_SUCCESS) { + dwType = 0; + dwSize = 0; + rv = RegQueryValueEx(hk, "MachineDomain", 0, &dwType, NULL, &dwSize); + if (rv == ERROR_SUCCESS && dwType == REG_SZ) { + domain = malloc(dwSize + 1); + if (domain) { + dwSize += 1; + rv = RegQueryValueEx(hk, "MachineDomain", 0, &dwType, domain, &dwSize); + if (rv == ERROR_SUCCESS && dwType == REG_SZ) { + domain[dwSize-1] = '\0'; + if (strncmp(short_domain, domain, strlen(short_domain)) == 0 && + domain[short_domain_len] == '.') + { + RegCloseKey(hk); + return domain; + } + } + free(domain); + } + } + RegCloseKey(hk); + } + + /* Then check the list of configured Kerberos realms, if any */ + rv = RegOpenKeyEx( HKEY_LOCAL_MACHINE, + "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Group Policy\\History", + 0, KEY_READ, &hk); + if (rv == ERROR_SUCCESS) { + DWORD index, cch; + char name[256]; + + for (index=0; rv==ERROR_SUCCESS; index++) { + cch = sizeof(name); + rv = RegEnumKeyEx(hk, index, name, &cch, NULL, NULL, NULL, NULL); + if (rv == ERROR_SUCCESS && + strncmp(short_domain, name, strlen(short_domain)) == 0 && + name[short_domain_len] == '.') { + domain = strdup(name); + RegCloseKey(hk); + return domain; + } + } + RegCloseKey(hk); + } + + return NULL; +} + /* * 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). @@ -829,8 +909,29 @@ GetDomainLogonOptions( PLUID lpLogonId, BOOLEAN bKerberos, doneRealm: if (realm) free(realm); } else { - if ( !ISREMOTE(opt->flags) ) + /* + * If no realm was found and the logon domain is not a valid + * realm name (aka LOCALHOST or domain short name, attempt + * to identify the full domain name or use the krb5 default + * realm. + * + * Possible sources of domain or realm information: + * + * HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Group Policy\History + * MachineDomain REG_SZ + * + * HKLM\SYSTEM\CurrentControlSet\Control\Lsa\CachedMachineNames + * NameUserPrincipal REG_SZ MACHINE$@DOMAIN + * + * HKLM\SYSTEM\CurrentControlSet\Control\Lsa\Kerberos\Domains\ + */ + if ( !ISREMOTE(opt->flags)) { opt->realm = KFW_get_default_realm(); + } else if ( strchr(domain, '.') == NULL) { + opt->realm = FindFullDomainName(domain); + if (opt->realm == NULL) + opt->realm = KFW_get_default_realm(); + } } /* Obtain the username mapping (if any) */