Windows Integrated Login Fixes for KFW 3.1
authorJeffrey Altman <jaltman@secure-endpoints.com>
Mon, 24 Jul 2006 06:58:23 +0000 (06:58 +0000)
committerJeffrey Altman <jaltman@secure-endpoints.com>
Mon, 24 Jul 2006 06:58:23 +0000 (06:58 +0000)
    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: new
tags: pullup
component: windows

git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@18379 dc483132-0cff-0310-8789-dd5450dbe970

src/windows/kfwlogon/Makefile.in
src/windows/kfwlogon/kfwcommon.c
src/windows/kfwlogon/kfwcpcc.c
src/windows/kfwlogon/kfwlogon.c
src/windows/kfwlogon/kfwlogon.h

index 0b3879c591c0c76b18aa1d44bb4d276762015d5b..03fc6e7e4c3805b1694eae9592645b2914a93260 100644 (file)
@@ -1,37 +1,37 @@
-# 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
index 251e1436b7033d8ab72756403c0093ed642cd72e..a4263c83821fb4ba16ac1e4d5c9a8ac75eb65666 100644 (file)
@@ -24,6 +24,9 @@ SOFTWARE.
 \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
@@ -758,6 +761,107 @@ KFW_get_cred( char * username,
     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
@@ -769,7 +873,8 @@ KFW_copy_cache_to_system_file(char * user, char * szLogonId)
     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
@@ -789,6 +894,8 @@ KFW_copy_cache_to_system_file(char * user, char * szLogonId)
 \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
@@ -806,6 +913,8 @@ KFW_copy_cache_to_system_file(char * user, char * szLogonId)
     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
@@ -827,7 +936,7 @@ KFW_copy_cache_to_system_file(char * user, char * szLogonId)
 }\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
@@ -849,17 +958,31 @@ KFW_copy_system_file_to_default_cache(char * filename)
     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
index 4dbace9696220dfcb39466770866a4c759fd0a1a..c3485c02d024d0019fef9d196bba40bb24e46751 100644 (file)
@@ -33,7 +33,7 @@ int main(int argc, char *argv[])
 \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
index eddf273412baf29128e2f4d943f70ec15f9a1f24..e815f73e00411832e764568aa9d3cd2aba458089 100644 (file)
@@ -1,5 +1,5 @@
 /*\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
@@ -292,6 +292,7 @@ VOID KFW_Logon_Event( PWLX_NOTIFICATION_INFO pInfo )
     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
@@ -321,14 +322,36 @@ VOID KFW_Logon_Event( PWLX_NOTIFICATION_INFO pInfo )
         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
@@ -339,12 +362,15 @@ VOID KFW_Logon_Event( PWLX_NOTIFICATION_INFO pInfo )
                              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
index 34c8cc70c830f36f5c92011d2060f4114741451a..d3fa6709d648997945cbae9a55080e8d8e7d80cd 100644 (file)
@@ -1,6 +1,6 @@
 /*\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
@@ -194,6 +194,8 @@ int KFW_is_available(void);
 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