r18379@cathode-dark-space: jaltman | 2006-07-24 02:58:23 -0400
ticket: new
subject: Windows Integrated Login Fixes for KFW 3.1
tags: pullup
component: windows
KFW integrated login was failing when the user is
not a power user or administrator. This was occurring
because the temporary file ccache was being created in
a directory the user could not read. While fixing this
it was noticed that the ACLs on the ccache were too broad.
Instead of applying a fix to the FILE: krb5_ccache
implementation it was decided that simply applying a new
set of ACLs (SYSTEM and "user" with no inheritance) to
the file immediately after the krb5_cc_initialize() call
would close the broadest security issues.
The file is initially created in the SYSTEM %TEMP% directory
with "SYSTEM" ACL only. Then it is moved to the user's %TEMP%
directory with "SYSTEM" and "user" ACLs. Finally, after
copying the credentials to the API: ccache, the file is deleted.
ticket: 4048
git-svn-id: svn://anonsvn.mit.edu/krb5/branches/krb5-1-5@18386
dc483132-0cff-0310-8789-
dd5450dbe970
-# Makefile for the KFW Network Provider
-#
-
-thisconfigdir=./..
-myfulldir=windows/nplogon
-mydir=.
-BUILDTOP=$(REL)..$(S)..
-DEFINES =
-LOCALINCLUDES = -I$(BUILDTOP) -I$(PISMERE)\athena\util\loadfuncs \
- -I$(PISMERE)\athena\auth\krb5\src\include\kerberosIV \
- -I$(PISMERE)\athena\auth\krb4\include \
- -I$(PISMERE)\athena\auth\leash\include
-PROG_LIBPATH=-L$(TOPLIBD) -L$(KRB5_LIBDIR)
-
-SYSLIBS = kernel32.lib user32.lib advapi32.lib wsock32.lib secur32.lib
-RFLAGS = $(LOCALINCLUDES)
-RCFLAGS = $(RFLAGS) -D_WIN32
-
-all-windows:: $(OUTPRE)kfwlogon.dll $(OUTPRE)kfwcpcc.exe
-
-$(OUTPRE)kfwlogon.res: kfwlogon.rc ..\version.rc
-
-$(OUTPRE)kfwcpcc.res: kfwcpcc.rc ..\version.rc
-
-$(OUTPRE)kfwlogon.dll: $(OUTPRE)kfwlogon.obj $(OUTPRE)kfwcommon.obj $(OUTPRE)kfwlogon.res
- link $(DLL_LINKOPTS) -out:$@ $(OUTPRE)kfwlogon.obj $(OUTPRE)kfwcommon.obj -entry:DllEntryPoint -def:kfwlogon.def $(SYSLIBS) $(KLIB) $(CLIB) $(SCLIB)
-
-$(OUTPRE)kfwcpcc.exe: $(OUTPRE)kfwcpcc.obj $(OUTPRE)kfwcommon.obj $(OUTPRE)kfwcpcc.res
- link $(EXE_LINKOPTS) -out:$@ $(OUTPRE)kfwcpcc.obj $(OUTPRE)kfwcommon.obj $(SYSLIBS) $(KLIB) $(CLIB) $(SCLIB)
-
-install::
- copy $(OUTPRE)kfwlogon.dll $(DESTDIR)
- copy $(OUTPRE)kfwcpcc.exe $(DESTDIR)
-
-clean::
- $(RM) $(OUTPRE)*.exe $(OUTPRE)*.dll $(OUTPRE)*.res
-
+# Makefile for the KFW Network Provider\r
+#\r
+\r
+thisconfigdir=./..\r
+myfulldir=windows/nplogon\r
+mydir=.\r
+BUILDTOP=$(REL)..$(S)..\r
+DEFINES = \r
+LOCALINCLUDES = -I$(BUILDTOP) -I$(PISMERE)\athena\util\loadfuncs \\r
+ -I$(PISMERE)\athena\auth\krb5\src\include\kerberosIV \\r
+ -I$(PISMERE)\athena\auth\krb4\include \\r
+ -I$(PISMERE)\athena\auth\leash\include\r
+PROG_LIBPATH=-L$(TOPLIBD) -L$(KRB5_LIBDIR)\r
+\r
+SYSLIBS = kernel32.lib user32.lib advapi32.lib wsock32.lib secur32.lib userenv.lib\r
+RFLAGS = $(LOCALINCLUDES)\r
+RCFLAGS = $(RFLAGS) -D_WIN32\r
+\r
+all-windows:: $(OUTPRE)kfwlogon.dll $(OUTPRE)kfwcpcc.exe\r
+\r
+$(OUTPRE)kfwlogon.res: kfwlogon.rc ..\version.rc\r
+\r
+$(OUTPRE)kfwcpcc.res: kfwcpcc.rc ..\version.rc\r
+\r
+$(OUTPRE)kfwlogon.dll: $(OUTPRE)kfwlogon.obj $(OUTPRE)kfwcommon.obj $(OUTPRE)kfwlogon.res\r
+ link $(DLL_LINKOPTS) -out:$@ $(OUTPRE)kfwlogon.obj $(OUTPRE)kfwcommon.obj -entry:DllEntryPoint -def:kfwlogon.def $(SYSLIBS) $(KLIB) $(CLIB)\r
+\r
+$(OUTPRE)kfwcpcc.exe: $(OUTPRE)kfwcpcc.obj $(OUTPRE)kfwcommon.obj $(OUTPRE)kfwcpcc.res\r
+ link $(EXE_LINKOPTS) -out:$@ $(OUTPRE)kfwcpcc.obj $(OUTPRE)kfwcommon.obj $(SYSLIBS) $(KLIB) $(CLIB)\r
+\r
+install::\r
+ copy $(OUTPRE)kfwlogon.dll $(DESTDIR)\r
+ copy $(OUTPRE)kfwcpcc.exe $(DESTDIR)\r
+\r
+clean::\r
+ $(RM) $(OUTPRE)*.exe $(OUTPRE)*.dll $(OUTPRE)*.res\r
+\r
\r
#include "kfwlogon.h"\r
#include <winbase.h>\r
+#include <Aclapi.h>\r
+#include <userenv.h>\r
+#include <Sddl.h>\r
\r
#include <io.h>\r
#include <sys/stat.h>\r
return(code);\r
}\r
\r
+int KFW_set_ccache_dacl(char *filename, HANDLE hUserToken)\r
+{\r
+ // SID_IDENTIFIER_AUTHORITY authority = SECURITY_NT_SID_AUTHORITY;\r
+ PSID pSystemSID = NULL;\r
+ DWORD SystemSIDlength, UserSIDlength;\r
+ PACL ccacheACL = NULL;\r
+ DWORD ccacheACLlength;\r
+ PTOKEN_USER pTokenUser = NULL;\r
+ DWORD retLen;\r
+ int ret = 0; \r
+\r
+ /* Get System SID */\r
+ ConvertStringSidToSid(SDDL_LOCAL_SYSTEM, &pSystemSID);\r
+\r
+ /* Create ACL */\r
+ SystemSIDlength = GetLengthSid(pSystemSID);\r
+ ccacheACLlength = sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE)\r
+ + SystemSIDlength - sizeof(DWORD);\r
+\r
+ if (hUserToken) {\r
+ if (!GetTokenInformation(hUserToken, TokenUser, NULL, 0, &retLen))\r
+ {\r
+ if ( GetLastError() == ERROR_INSUFFICIENT_BUFFER ) {\r
+ pTokenUser = (PTOKEN_USER) LocalAlloc(LPTR, retLen);\r
+\r
+ if (!GetTokenInformation(hUserToken, TokenUser, pTokenUser, retLen, &retLen))\r
+ {\r
+ DebugEvent("GetTokenInformation failed: GLE = %lX", GetLastError());\r
+ }\r
+ } \r
+ }\r
+\r
+ if (pTokenUser) {\r
+ UserSIDlength = GetLengthSid(pTokenUser->User.Sid);\r
+\r
+ ccacheACLlength += sizeof(ACCESS_ALLOWED_ACE) + UserSIDlength \r
+ - sizeof(DWORD);\r
+ }\r
+ }\r
+\r
+ ccacheACL = GlobalAlloc(GMEM_FIXED, ccacheACLlength);\r
+ InitializeAcl(ccacheACL, ccacheACLlength, ACL_REVISION);\r
+ AddAccessAllowedAceEx(ccacheACL, ACL_REVISION, 0,\r
+ STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL,\r
+ pSystemSID);\r
+ if (pTokenUser) {\r
+ AddAccessAllowedAceEx(ccacheACL, ACL_REVISION, 0,\r
+ STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL,\r
+ pTokenUser->User.Sid);\r
+ if (!SetNamedSecurityInfo( filename, SE_FILE_OBJECT,\r
+ DACL_SECURITY_INFORMATION | PROTECTED_DACL_SECURITY_INFORMATION,\r
+ NULL,\r
+ NULL, \r
+ ccacheACL,\r
+ NULL)) {\r
+ DebugEvent("SetNamedSecurityInfo DACL failed: GLE = 0x%lX", GetLastError());\r
+ ret = 1;\r
+ }\r
+ if (!SetNamedSecurityInfo( filename, SE_FILE_OBJECT,\r
+ OWNER_SECURITY_INFORMATION,\r
+ pTokenUser->User.Sid,\r
+ NULL, \r
+ NULL,\r
+ NULL)) {\r
+ DebugEvent("SetNamedSecurityInfo Owner failed: GLE = 0x%lX", GetLastError());\r
+ ret = 1;\r
+ }\r
+ } else {\r
+ if (!SetNamedSecurityInfo( filename, SE_FILE_OBJECT,\r
+ DACL_SECURITY_INFORMATION | PROTECTED_DACL_SECURITY_INFORMATION,\r
+ NULL,\r
+ NULL, \r
+ ccacheACL,\r
+ NULL)) {\r
+ DebugEvent("SetNamedSecurityInfo failed: GLE = 0x%lX", GetLastError());\r
+ ret = 1;\r
+ }\r
+ }\r
+\r
+ if (pSystemSID)\r
+ LocalFree(pSystemSID);\r
+ if (pTokenUser)\r
+ LocalFree(pTokenUser);\r
+ if (ccacheACL)\r
+ GlobalFree(ccacheACL);\r
+ return ret;\r
+}\r
+\r
+int KFW_obtain_user_temp_directory(HANDLE hUserToken, char *newfilename, int size)\r
+{\r
+ int retval = 0;\r
+ DWORD dwSize = size-1; /* leave room for nul */\r
+\r
+ *newfilename = '\0';\r
+\r
+ if ( !ExpandEnvironmentStringsForUser(hUserToken, "%TEMP%", newfilename, size) &&\r
+ !ExpandEnvironmentStringsForUser(hUserToken, "%TMP%", newfilename, size))\r
+ return 1;\r
+ return 0;\r
+}\r
+\r
void\r
KFW_copy_cache_to_system_file(char * user, char * szLogonId)\r
{\r
krb5_principal princ = 0;\r
krb5_ccache cc = 0;\r
krb5_ccache ncc = 0;\r
-\r
+ PSECURITY_ATTRIBUTES pSA = NULL;\r
+ \r
if (!pkrb5_init_context)\r
return;\r
\r
\r
strcat(cachename, filename);\r
\r
+ DebugEvent("KFW_Logon_Event - ccache %s", cachename);\r
+\r
DeleteFile(filename);\r
\r
code = pkrb5_init_context(&ctx);\r
code = pkrb5_cc_initialize(ctx, ncc, princ);\r
if (code) goto cleanup;\r
\r
+ KFW_set_ccache_dacl(filename, NULL);\r
+\r
code = pkrb5_cc_copy_creds(ctx,cc,ncc);\r
\r
cleanup:\r
}\r
\r
int\r
-KFW_copy_system_file_to_default_cache(char * filename)\r
+KFW_copy_file_cache_to_default_cache(char * filename)\r
{\r
char cachename[264] = "FILE:";\r
krb5_context ctx = 0;\r
if (code) ctx = 0;\r
\r
code = pkrb5_cc_resolve(ctx, cachename, &cc);\r
- if (code) goto cleanup;\r
+ if (code) {\r
+ DebugEvent0("kfwcpcc krb5_cc_resolve failed");\r
+ goto cleanup;\r
+ }\r
\r
code = pkrb5_cc_get_principal(ctx, cc, &princ);\r
- if (code) goto cleanup;\r
+ if (code) {\r
+ DebugEvent0("kfwcpcc krb5_cc_get_principal failed");\r
+ goto cleanup;\r
+ }\r
\r
code = pkrb5_cc_default(ctx, &ncc);\r
+ if (code) {\r
+ DebugEvent0("kfwcpcc krb5_cc_default failed");\r
+ goto cleanup;\r
+ }\r
if (!code) {\r
code = pkrb5_cc_initialize(ctx, ncc, princ);\r
\r
if (!code)\r
code = pkrb5_cc_copy_creds(ctx,cc,ncc);\r
+ if (code) {\r
+ DebugEvent0("kfwcpcc krb5_cc_copy_creds failed");\r
+ goto cleanup;\r
+ }\r
}\r
if ( ncc ) {\r
pkrb5_cc_close(ctx, ncc);\r
\r
KFW_initialize();\r
\r
- return KFW_copy_system_file_to_default_cache(argv[1]);\r
+ return KFW_copy_file_cache_to_default_cache(argv[1]);\r
}\r
\r
\r
/*\r
-Copyright 2005 by the Massachusetts Institute of Technology\r
+Copyright 2005,2006 by the Massachusetts Institute of Technology\r
\r
All rights reserved.\r
\r
char szLogonId[128] = "";\r
DWORD count;\r
char filename[256];\r
+ char newfilename[256];\r
char commandline[512];\r
STARTUPINFO startupinfo;\r
PROCESS_INFORMATION procinfo;\r
GetWindowsDirectory(filename, sizeof(filename));\r
}\r
\r
- if ( strlen(filename) + strlen(szLogonId) + 2 <= sizeof(filename) ) {\r
- strcat(filename, "\\");\r
- strcat(filename, szLogonId); \r
+ if ( strlen(filename) + strlen(szLogonId) + 2 > sizeof(filename) ) {\r
+ DebugEvent0("KFW_Logon_Event - filename too long");\r
+ return;\r
+ }\r
+\r
+ strcat(filename, "\\");\r
+ strcat(filename, szLogonId); \r
\r
- sprintf(commandline, "kfwcpcc.exe \"%s\"", filename);\r
+ KFW_set_ccache_dacl(filename, pInfo->hToken);\r
\r
- GetStartupInfo(&startupinfo);\r
- if (CreateProcessAsUser( pInfo->hToken,\r
+ KFW_obtain_user_temp_directory(pInfo->hToken, newfilename, sizeof(newfilename));\r
+\r
+ if ( strlen(newfilename) + strlen(szLogonId) + 2 > sizeof(newfilename) ) {\r
+ DebugEvent0("KFW_Logon_Event - new filename too long");\r
+ return;\r
+ }\r
+\r
+ strcat(newfilename, "\\");\r
+ strcat(newfilename, szLogonId); \r
+\r
+ if (!MoveFileEx(filename, newfilename, \r
+ MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH)) {\r
+ DebugEvent("KFW_Logon_Event - MoveFileEx failed GLE = 0x%x", GetLastError());\r
+ return;\r
+ }\r
+\r
+ sprintf(commandline, "kfwcpcc.exe \"%s\"", newfilename);\r
+\r
+ GetStartupInfo(&startupinfo);\r
+ if (CreateProcessAsUser( pInfo->hToken,\r
"kfwcpcc.exe",\r
commandline,\r
NULL,\r
NULL,\r
&startupinfo,\r
&procinfo)) \r
- {\r
- WaitForSingleObject(procinfo.hProcess, 30000);\r
+ {\r
+ DebugEvent("KFW_Logon_Event - CommandLine %s", commandline);\r
\r
- CloseHandle(procinfo.hThread);\r
- CloseHandle(procinfo.hProcess);\r
- }\r
+ WaitForSingleObject(procinfo.hProcess, 30000);\r
+\r
+ CloseHandle(procinfo.hThread);\r
+ CloseHandle(procinfo.hProcess);\r
+ } else {\r
+ DebugEvent0("KFW_Logon_Event - CreateProcessFailed");\r
}\r
\r
DeleteFile(filename);\r
/*\r
\r
-Copyright 2005 by the Massachusetts Institute of Technology\r
+Copyright 2005,2006 by the Massachusetts Institute of Technology\r
\r
All rights reserved.\r
\r
int KFW_get_cred( char * username, char * password, int lifetime, char ** reasonP );\r
void KFW_copy_cache_to_system_file(char * user, char * szLogonId);\r
int KFW_destroy_tickets_for_principal(char * user);\r
+int KFW_set_ccache_dacl(char *filename, HANDLE hUserToken);\r
+int KFW_obtain_user_temp_directory(HANDLE hUserToken, char *newfilename, int size);\r
\r
#ifdef __cplusplus\r
}\r