From 15487b4acc9a44157f5a8329aba35a694fd4815a Mon Sep 17 00:00:00 2001 From: Jeffrey Altman Date: Thu, 28 Apr 2005 13:11:38 +0000 Subject: [PATCH] STABLE14-windows-multi-domain-forest-fix-20050428 Add the ability to obtain the "Kerberos" principal used for logon to the machine in order to establish a connection to the smb server that utilizes the username for which locally cached credentials are available. --- src/sys/NTMakefile | 1 + src/sys/pioctl_nt.c | 256 ++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 246 insertions(+), 11 deletions(-) diff --git a/src/sys/NTMakefile b/src/sys/NTMakefile index a7dec7094..1d8d7bdac 100644 --- a/src/sys/NTMakefile +++ b/src/sys/NTMakefile @@ -5,6 +5,7 @@ # License. For details, see the LICENSE file in the top-level source # directory or online at http://www.openafs.org/dl/license10.html +AFSDEV_AUXCDEFINES = $(AFSDEV_AUXCDEFINES) -I..\WINNT\kfw\inc\loadfuncs -I..\WINNT\kfw\inc\krb5 RELDIR=sys !INCLUDE ..\config\NTMakefile.$(SYS_NAME) !INCLUDE ..\config\NTMakefile.version diff --git a/src/sys/pioctl_nt.c b/src/sys/pioctl_nt.c index 06bdbbb01..05c150999 100644 --- a/src/sys/pioctl_nt.c +++ b/src/sys/pioctl_nt.c @@ -43,6 +43,9 @@ RCSID #include #include +#include +#include + static char AFSConfigKeyName[] = AFSREG_CLT_SVC_PARAM_SUBKEY; #define FS_IOCTLREQUEST_MAXSIZE 8192 @@ -123,6 +126,177 @@ IoctlDebug(void) return debug; } + +// krb5 functions +DECL_FUNC_PTR(krb5_cc_default_name); +DECL_FUNC_PTR(krb5_cc_set_default_name); +DECL_FUNC_PTR(krb5_get_default_config_files); +DECL_FUNC_PTR(krb5_free_config_files); +DECL_FUNC_PTR(krb5_free_context); +DECL_FUNC_PTR(krb5_get_default_realm); +DECL_FUNC_PTR(krb5_free_default_realm); +DECL_FUNC_PTR(krb5_init_context); +DECL_FUNC_PTR(krb5_cc_default); +DECL_FUNC_PTR(krb5_parse_name); +DECL_FUNC_PTR(krb5_free_principal); +DECL_FUNC_PTR(krb5_cc_close); +DECL_FUNC_PTR(krb5_cc_get_principal); +DECL_FUNC_PTR(krb5_build_principal); +DECL_FUNC_PTR(krb5_c_random_make_octets); +DECL_FUNC_PTR(krb5_get_init_creds_password); +DECL_FUNC_PTR(krb5_free_cred_contents); +DECL_FUNC_PTR(krb5_cc_resolve); +DECL_FUNC_PTR(krb5_unparse_name); +DECL_FUNC_PTR(krb5_free_unparsed_name); + +FUNC_INFO krb5_fi[] = { + MAKE_FUNC_INFO(krb5_cc_default_name), + MAKE_FUNC_INFO(krb5_cc_set_default_name), + MAKE_FUNC_INFO(krb5_get_default_config_files), + MAKE_FUNC_INFO(krb5_free_config_files), + MAKE_FUNC_INFO(krb5_free_context), + MAKE_FUNC_INFO(krb5_get_default_realm), + MAKE_FUNC_INFO(krb5_free_default_realm), + MAKE_FUNC_INFO(krb5_init_context), + MAKE_FUNC_INFO(krb5_cc_default), + MAKE_FUNC_INFO(krb5_parse_name), + MAKE_FUNC_INFO(krb5_free_principal), + MAKE_FUNC_INFO(krb5_cc_close), + MAKE_FUNC_INFO(krb5_cc_get_principal), + MAKE_FUNC_INFO(krb5_build_principal), + MAKE_FUNC_INFO(krb5_c_random_make_octets), + MAKE_FUNC_INFO(krb5_get_init_creds_password), + MAKE_FUNC_INFO(krb5_free_cred_contents), + MAKE_FUNC_INFO(krb5_cc_resolve), + MAKE_FUNC_INFO(krb5_unparse_name), + MAKE_FUNC_INFO(krb5_free_unparsed_name), + END_FUNC_INFO +}; + +static int +LoadFuncs( + const char* dll_name, + FUNC_INFO fi[], + HINSTANCE* ph, // [out, optional] - DLL handle + int* pindex, // [out, optional] - index of last func loaded (-1 if none) + int cleanup, // cleanup function pointers and unload on error + int go_on, // continue loading even if some functions cannot be loaded + int silent // do not pop-up a system dialog if DLL cannot be loaded + ) +{ + HINSTANCE h; + int i, n, last_i; + int error = 0; + UINT em; + + if (ph) *ph = 0; + if (pindex) *pindex = -1; + + for (n = 0; fi[n].func_ptr_var; n++) + *(fi[n].func_ptr_var) = 0; + + if (silent) + em = SetErrorMode(SEM_FAILCRITICALERRORS); + h = LoadLibrary(dll_name); + if (silent) + SetErrorMode(em); + + if (!h) + return 0; + + last_i = -1; + for (i = 0; (go_on || !error) && (i < n); i++) + { + void* p = (void*)GetProcAddress(h, fi[i].func_name); + if (!p) + error = 1; + else + { + last_i = i; + *(fi[i].func_ptr_var) = p; + } + } + if (pindex) *pindex = last_i; + if (error && cleanup && !go_on) { + for (i = 0; i < n; i++) { + *(fi[i].func_ptr_var) = 0; + } + FreeLibrary(h); + return 0; + } + if (ph) *ph = h; + if (error) return 0; + return 1; +} + +#define KERB5DLL "krb5_32.dll" +static BOOL +IsKrb5Available() +{ + static HINSTANCE hKrb5DLL = 0; + + if ( hKrb5DLL ) + return TRUE; + + hKrb5DLL = LoadLibrary(KERB5DLL); + if (hKrb5DLL) { + if (!LoadFuncs(KERB5DLL, krb5_fi, 0, 0, 1, 0, 0)) + { + FreeLibrary(hKrb5DLL); + hKrb5DLL = 0; + return FALSE; + } + } + return TRUE; +} + +static BOOL +GetLSAPrincipalName(char * szUser, DWORD *dwSize) +{ + krb5_context ctx = 0; + krb5_error_code code; + krb5_ccache mslsa_ccache=0; + krb5_principal princ = 0; + char * pname = 0; + BOOL success = 0; + + if (!IsKrb5Available()) + return FALSE; + + if (code = pkrb5_init_context(&ctx)) + goto cleanup; + + if (code = pkrb5_cc_resolve(ctx, "MSLSA:", &mslsa_ccache)) + goto cleanup; + + if (code = pkrb5_cc_get_principal(ctx, mslsa_ccache, &princ)) + goto cleanup; + + if (code = pkrb5_unparse_name(ctx, princ, &pname)) + goto cleanup; + + if ( strlen(pname) < *dwSize ) { + strncpy(szUser, pname, *dwSize); + szUser[*dwSize-1] = '\0'; + success = 1; + } + *dwSize = strlen(pname); + + cleanup: + if (pname) + pkrb5_free_unparsed_name(ctx, pname); + + if (princ) + pkrb5_free_principal(ctx, princ); + + if (mslsa_ccache) + pkrb5_cc_close(ctx, mslsa_ccache); + + if (ctx) + pkrb5_free_context(ctx); + return success; +} + static long GetIoctlHandle(char *fileNamep, HANDLE * handlep) { @@ -213,14 +387,10 @@ GetIoctlHandle(char *fileNamep, HANDLE * handlep) (va_list *) NULL ) ) { - fprintf(stderr,"pioctl CreateFile(%s) failed: 0x%8X\r\n\t[%s]\r\n", + fprintf(stderr,"pioctl CreateFile(%s) failed: 0x%X\r\n\t[%s]\r\n", tbuffer,gle,buf); } } -#ifdef COMMENT - if (gle != ERROR_DOWNGRADE_DETECTED) - return -1; -#endif lana_GetNetbiosName(szClient, LANA_NETBIOS_NAME_FULL); @@ -234,7 +404,69 @@ GetIoctlHandle(char *fileNamep, HANDLE * handlep) if ( szUser[0] ) { if ( ioctlDebug ) - fprintf(stderr, "pioctl logon user: [%s]\r\n",szUser); + fprintf(stderr, "pioctl Explorer logon user: [%s]\r\n",szUser); + + sprintf(szPath, "\\\\%s", szClient); + memset (&nr, 0x00, sizeof(NETRESOURCE)); + nr.dwType=RESOURCETYPE_DISK; + nr.lpLocalName=0; + nr.lpRemoteName=szPath; + res = WNetAddConnection2(&nr,NULL,szUser,0); + if (res) { + if ( ioctlDebug ) { + fprintf(stderr, "pioctl WNetAddConnection2(%s,%s) failed: 0x%X\r\n", + szPath,szUser,res); + } + gonext = 1; + } + + sprintf(szPath, "\\\\%s\\all", szClient); + res = WNetAddConnection2(&nr,NULL,szUser,0); + if (res) { + if ( ioctlDebug ) { + fprintf(stderr, "pioctl WNetAddConnection2(%s,%s) failed: 0x%X\r\n", + szPath,szUser,res); + } + gonext = 1; + } + + if (gonext) + goto try_lsa_principal; + + fh = CreateFile(tbuffer, GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, + FILE_FLAG_WRITE_THROUGH, NULL); + fflush(stdout); + if (fh == INVALID_HANDLE_VALUE) { + gle = GetLastError(); + if (gle && ioctlDebug ) { + char buf[4096]; + + if ( FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, + NULL, + gle, + MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US), + buf, + 4096, + (va_list *) NULL + ) ) + { + fprintf(stderr,"pioctl CreateFile(%s) failed: 0x%X\r\n\t[%s]\r\n", + tbuffer,gle,buf); + } + } + } + } + } + + try_lsa_principal: + if (fh == INVALID_HANDLE_VALUE) { + int gonext = 0; + + dwSize = sizeof(szUser); + if (GetLSAPrincipalName(szUser, &dwSize)) { + if ( ioctlDebug ) + fprintf(stderr, "pioctl LSA Principal logon user: [%s]\r\n",szUser); sprintf(szPath, "\\\\%s", szClient); memset (&nr, 0x00, sizeof(NETRESOURCE)); @@ -261,7 +493,7 @@ GetIoctlHandle(char *fileNamep, HANDLE * handlep) } if (gonext) - goto next_attempt; + goto try_sam_compat; fh = CreateFile(tbuffer, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, @@ -281,7 +513,7 @@ GetIoctlHandle(char *fileNamep, HANDLE * handlep) (va_list *) NULL ) ) { - fprintf(stderr,"pioctl CreateFile(%s) failed: 0x%8X\r\n\t[%s]\r\n", + fprintf(stderr,"pioctl CreateFile(%s) failed: 0x%X\r\n\t[%s]\r\n", tbuffer,gle,buf); } } @@ -289,11 +521,12 @@ GetIoctlHandle(char *fileNamep, HANDLE * handlep) } } - next_attempt: + try_sam_compat: if ( fh == INVALID_HANDLE_VALUE ) { + dwSize = sizeof(szUser); if (GetUserNameEx(NameSamCompatible, szUser, &dwSize)) { if ( ioctlDebug ) - fprintf(stderr, "pioctl logon user: [%s]\r\n",szUser); + fprintf(stderr, "pioctl SamCompatible logon user: [%s]\r\n",szUser); sprintf(szPath, "\\\\%s", szClient); memset (&nr, 0x00, sizeof(NETRESOURCE)); @@ -336,13 +569,14 @@ GetIoctlHandle(char *fileNamep, HANDLE * handlep) (va_list *) NULL ) ) { - fprintf(stderr,"pioctl CreateFile(%s) failed: 0x%8X\r\n\t[%s]\r\n", + fprintf(stderr,"pioctl CreateFile(%s) failed: 0x%X\r\n\t[%s]\r\n", tbuffer,gle,buf); } } return -1; } } else { + fprintf(stderr, "GetUserNameEx(NameSamCompatible) failed: 0x%X\r\n", GetLastError()); return -1; } } -- 2.39.5