xref: /freebsd/crypto/krb5/src/windows/kfwlogon/kfwlogon.c (revision 7f2fe78b9dd5f51c821d771b63d2e096f6fd49e9)
1*7f2fe78bSCy Schubert /*
2*7f2fe78bSCy Schubert Copyright 2005,2006 by the Massachusetts Institute of Technology
3*7f2fe78bSCy Schubert Copyright 2007 by Secure Endpoints Inc.
4*7f2fe78bSCy Schubert 
5*7f2fe78bSCy Schubert All rights reserved.
6*7f2fe78bSCy Schubert 
7*7f2fe78bSCy Schubert Permission to use, copy, modify, and distribute this software and its
8*7f2fe78bSCy Schubert documentation for any purpose and without fee is hereby granted,
9*7f2fe78bSCy Schubert provided that the above copyright notice appear in all copies and that
10*7f2fe78bSCy Schubert both that copyright notice and this permission notice appear in
11*7f2fe78bSCy Schubert supporting documentation, and that the name of the Massachusetts
12*7f2fe78bSCy Schubert Institute of Technology (M.I.T.) not be used in advertising or publicity
13*7f2fe78bSCy Schubert pertaining to distribution of the software without specific, written
14*7f2fe78bSCy Schubert prior permission.
15*7f2fe78bSCy Schubert 
16*7f2fe78bSCy Schubert M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
17*7f2fe78bSCy Schubert ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
18*7f2fe78bSCy Schubert M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
19*7f2fe78bSCy Schubert ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
20*7f2fe78bSCy Schubert WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
21*7f2fe78bSCy Schubert ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
22*7f2fe78bSCy Schubert SOFTWARE.
23*7f2fe78bSCy Schubert 
24*7f2fe78bSCy Schubert */
25*7f2fe78bSCy Schubert 
26*7f2fe78bSCy Schubert #include "kfwlogon.h"
27*7f2fe78bSCy Schubert 
28*7f2fe78bSCy Schubert #include <io.h>
29*7f2fe78bSCy Schubert #include <stdio.h>
30*7f2fe78bSCy Schubert #include <sys/stat.h>
31*7f2fe78bSCy Schubert #include <sys/types.h>
32*7f2fe78bSCy Schubert #include <fcntl.h>
33*7f2fe78bSCy Schubert 
34*7f2fe78bSCy Schubert #include <winsock2.h>
35*7f2fe78bSCy Schubert #include <lm.h>
36*7f2fe78bSCy Schubert #include <nb30.h>
37*7f2fe78bSCy Schubert 
38*7f2fe78bSCy Schubert static HANDLE hDLL;
39*7f2fe78bSCy Schubert 
40*7f2fe78bSCy Schubert static HANDLE hInitMutex = NULL;
41*7f2fe78bSCy Schubert static BOOL bInit = FALSE;
42*7f2fe78bSCy Schubert 
43*7f2fe78bSCy Schubert 
DllEntryPoint(HANDLE dll,DWORD reason,PVOID reserved)44*7f2fe78bSCy Schubert BOOLEAN APIENTRY DllEntryPoint(HANDLE dll, DWORD reason, PVOID reserved)
45*7f2fe78bSCy Schubert {
46*7f2fe78bSCy Schubert     hDLL = dll;
47*7f2fe78bSCy Schubert     switch (reason) {
48*7f2fe78bSCy Schubert     case DLL_PROCESS_ATTACH:
49*7f2fe78bSCy Schubert         /* Initialization Mutex */
50*7f2fe78bSCy Schubert         hInitMutex = CreateMutex(NULL, FALSE, NULL);
51*7f2fe78bSCy Schubert         break;
52*7f2fe78bSCy Schubert 
53*7f2fe78bSCy Schubert     case DLL_PROCESS_DETACH:
54*7f2fe78bSCy Schubert         CloseHandle(hInitMutex);
55*7f2fe78bSCy Schubert         break;
56*7f2fe78bSCy Schubert 
57*7f2fe78bSCy Schubert     case DLL_THREAD_ATTACH:
58*7f2fe78bSCy Schubert     case DLL_THREAD_DETACH:
59*7f2fe78bSCy Schubert     default:
60*7f2fe78bSCy Schubert         /* Everything else succeeds but does nothing. */
61*7f2fe78bSCy Schubert         break;
62*7f2fe78bSCy Schubert     }
63*7f2fe78bSCy Schubert 
64*7f2fe78bSCy Schubert     return TRUE;
65*7f2fe78bSCy Schubert }
66*7f2fe78bSCy Schubert 
NPGetCaps(DWORD index)67*7f2fe78bSCy Schubert DWORD APIENTRY NPGetCaps(DWORD index)
68*7f2fe78bSCy Schubert {
69*7f2fe78bSCy Schubert     switch (index) {
70*7f2fe78bSCy Schubert     case WNNC_NET_TYPE:
71*7f2fe78bSCy Schubert         /* We aren't a file system; We don't have our own type; use somebody else's. */
72*7f2fe78bSCy Schubert         return WNNC_NET_SUN_PC_NFS;
73*7f2fe78bSCy Schubert     case WNNC_START:
74*7f2fe78bSCy Schubert         /* Say we are already started, even though we might wait after we receive NPLogonNotify */
75*7f2fe78bSCy Schubert         return 1;
76*7f2fe78bSCy Schubert 
77*7f2fe78bSCy Schubert     default:
78*7f2fe78bSCy Schubert         return 0;
79*7f2fe78bSCy Schubert     }
80*7f2fe78bSCy Schubert }
81*7f2fe78bSCy Schubert 
82*7f2fe78bSCy Schubert 
83*7f2fe78bSCy Schubert static BOOL
84*7f2fe78bSCy Schubert WINAPI
UnicodeStringToANSI(UNICODE_STRING uInputString,LPSTR lpszOutputString,int nOutStringLen)85*7f2fe78bSCy Schubert UnicodeStringToANSI(UNICODE_STRING uInputString, LPSTR lpszOutputString, int nOutStringLen)
86*7f2fe78bSCy Schubert {
87*7f2fe78bSCy Schubert     CPINFO CodePageInfo;
88*7f2fe78bSCy Schubert 
89*7f2fe78bSCy Schubert     GetCPInfo(CP_ACP, &CodePageInfo);
90*7f2fe78bSCy Schubert 
91*7f2fe78bSCy Schubert     if (CodePageInfo.MaxCharSize > 1)
92*7f2fe78bSCy Schubert         // Only supporting non-Unicode strings
93*7f2fe78bSCy Schubert         return FALSE;
94*7f2fe78bSCy Schubert 
95*7f2fe78bSCy Schubert     if (uInputString.Buffer && ((LPBYTE) uInputString.Buffer)[1] == '\0')
96*7f2fe78bSCy Schubert     {
97*7f2fe78bSCy Schubert         // Looks like unicode, better translate it
98*7f2fe78bSCy Schubert         // UNICODE_STRING specifies the length of the buffer string in Bytes not WCHARS
99*7f2fe78bSCy Schubert         WideCharToMultiByte(CP_ACP, 0, (LPCWSTR) uInputString.Buffer, uInputString.Length/2,
100*7f2fe78bSCy Schubert                             lpszOutputString, nOutStringLen-1, NULL, NULL);
101*7f2fe78bSCy Schubert         lpszOutputString[min(uInputString.Length/2,nOutStringLen-1)] = '\0';
102*7f2fe78bSCy Schubert         return TRUE;
103*7f2fe78bSCy Schubert     }
104*7f2fe78bSCy Schubert 
105*7f2fe78bSCy Schubert     lpszOutputString[0] = '\0';
106*7f2fe78bSCy Schubert     return FALSE;
107*7f2fe78bSCy Schubert }  // UnicodeStringToANSI
108*7f2fe78bSCy Schubert 
109*7f2fe78bSCy Schubert 
110*7f2fe78bSCy Schubert static BOOL
is_windows_vista(void)111*7f2fe78bSCy Schubert is_windows_vista(void)
112*7f2fe78bSCy Schubert {
113*7f2fe78bSCy Schubert    static BOOL fChecked = FALSE;
114*7f2fe78bSCy Schubert    static BOOL fIsWinVista = FALSE;
115*7f2fe78bSCy Schubert 
116*7f2fe78bSCy Schubert    if (!fChecked)
117*7f2fe78bSCy Schubert    {
118*7f2fe78bSCy Schubert        OSVERSIONINFO Version;
119*7f2fe78bSCy Schubert 
120*7f2fe78bSCy Schubert        memset (&Version, 0x00, sizeof(Version));
121*7f2fe78bSCy Schubert        Version.dwOSVersionInfoSize = sizeof(Version);
122*7f2fe78bSCy Schubert 
123*7f2fe78bSCy Schubert        if (GetVersionEx (&Version))
124*7f2fe78bSCy Schubert        {
125*7f2fe78bSCy Schubert            if (Version.dwPlatformId == VER_PLATFORM_WIN32_NT &&
126*7f2fe78bSCy Schubert                Version.dwMajorVersion >= 6)
127*7f2fe78bSCy Schubert                fIsWinVista = TRUE;
128*7f2fe78bSCy Schubert        }
129*7f2fe78bSCy Schubert        fChecked = TRUE;
130*7f2fe78bSCy Schubert    }
131*7f2fe78bSCy Schubert 
132*7f2fe78bSCy Schubert    return fIsWinVista;
133*7f2fe78bSCy Schubert }
134*7f2fe78bSCy Schubert 
135*7f2fe78bSCy Schubert 
136*7f2fe78bSCy Schubert /* Construct a Logon Script that will cause the LogonEventHandler to be executed
137*7f2fe78bSCy Schubert  * under in the logon session
138*7f2fe78bSCy Schubert  */
139*7f2fe78bSCy Schubert 
140*7f2fe78bSCy Schubert #define RUNDLL32_CMDLINE "rundll32.exe kfwlogon.dll,LogonEventHandler "
141*7f2fe78bSCy Schubert VOID
ConfigureLogonScript(LPWSTR * lpLogonScript,char * filename)142*7f2fe78bSCy Schubert ConfigureLogonScript(LPWSTR *lpLogonScript, char * filename) {
143*7f2fe78bSCy Schubert     DWORD dwLogonScriptLen;
144*7f2fe78bSCy Schubert     LPWSTR lpScript;
145*7f2fe78bSCy Schubert     LPSTR lpTemp;
146*7f2fe78bSCy Schubert 
147*7f2fe78bSCy Schubert     if (!lpLogonScript)
148*7f2fe78bSCy Schubert 	return;
149*7f2fe78bSCy Schubert     *lpLogonScript = NULL;
150*7f2fe78bSCy Schubert 
151*7f2fe78bSCy Schubert     if (!filename)
152*7f2fe78bSCy Schubert 	return;
153*7f2fe78bSCy Schubert 
154*7f2fe78bSCy Schubert     dwLogonScriptLen = strlen(RUNDLL32_CMDLINE) + strlen(filename) + 2;
155*7f2fe78bSCy Schubert     lpTemp = (LPSTR) malloc(dwLogonScriptLen);
156*7f2fe78bSCy Schubert     if (!lpTemp)
157*7f2fe78bSCy Schubert 	return;
158*7f2fe78bSCy Schubert 
159*7f2fe78bSCy Schubert     _snprintf(lpTemp, dwLogonScriptLen, "%s%s", RUNDLL32_CMDLINE, filename);
160*7f2fe78bSCy Schubert 
161*7f2fe78bSCy Schubert     SetLastError(0);
162*7f2fe78bSCy Schubert     dwLogonScriptLen = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, lpTemp, -1, NULL, 0);
163*7f2fe78bSCy Schubert     DebugEvent("ConfigureLogonScript %s requires %d bytes gle=0x%x", lpTemp, dwLogonScriptLen, GetLastError());
164*7f2fe78bSCy Schubert 
165*7f2fe78bSCy Schubert     lpScript = LocalAlloc(LMEM_ZEROINIT, dwLogonScriptLen * 2);
166*7f2fe78bSCy Schubert     if (lpScript) {
167*7f2fe78bSCy Schubert 	if (MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, lpTemp, -1, lpScript, 2 * dwLogonScriptLen))
168*7f2fe78bSCy Schubert 	    *lpLogonScript = lpScript;
169*7f2fe78bSCy Schubert 	else {
170*7f2fe78bSCy Schubert 	    DebugEvent("ConfigureLogonScript - MultiByteToWideChar failed gle = 0x%x", GetLastError());
171*7f2fe78bSCy Schubert 	    LocalFree(lpScript);
172*7f2fe78bSCy Schubert 	}
173*7f2fe78bSCy Schubert     } else {
174*7f2fe78bSCy Schubert 	DebugEvent("LocalAlloc failed gle=0x%x", GetLastError());
175*7f2fe78bSCy Schubert     }
176*7f2fe78bSCy Schubert     free(lpTemp);
177*7f2fe78bSCy Schubert }
178*7f2fe78bSCy Schubert 
179*7f2fe78bSCy Schubert 
NPLogonNotify(PLUID lpLogonId,LPCWSTR lpAuthentInfoType,LPVOID lpAuthentInfo,LPCWSTR lpPreviousAuthentInfoType,LPVOID lpPreviousAuthentInfo,LPWSTR lpStationName,LPVOID StationHandle,LPWSTR * lpLogonScript)180*7f2fe78bSCy Schubert DWORD APIENTRY NPLogonNotify(
181*7f2fe78bSCy Schubert 	PLUID lpLogonId,
182*7f2fe78bSCy Schubert 	LPCWSTR lpAuthentInfoType,
183*7f2fe78bSCy Schubert 	LPVOID lpAuthentInfo,
184*7f2fe78bSCy Schubert 	LPCWSTR lpPreviousAuthentInfoType,
185*7f2fe78bSCy Schubert 	LPVOID lpPreviousAuthentInfo,
186*7f2fe78bSCy Schubert 	LPWSTR lpStationName,
187*7f2fe78bSCy Schubert 	LPVOID StationHandle,
188*7f2fe78bSCy Schubert 	LPWSTR *lpLogonScript)
189*7f2fe78bSCy Schubert {
190*7f2fe78bSCy Schubert     char uname[MAX_USERNAME_LENGTH+1]="";
191*7f2fe78bSCy Schubert     char password[MAX_PASSWORD_LENGTH+1]="";
192*7f2fe78bSCy Schubert     char logonDomain[MAX_DOMAIN_LENGTH+1]="";
193*7f2fe78bSCy Schubert 
194*7f2fe78bSCy Schubert     MSV1_0_INTERACTIVE_LOGON *IL;
195*7f2fe78bSCy Schubert 
196*7f2fe78bSCy Schubert     DWORD code = 0;
197*7f2fe78bSCy Schubert 
198*7f2fe78bSCy Schubert     char *reason;
199*7f2fe78bSCy Schubert     char *ctemp;
200*7f2fe78bSCy Schubert 
201*7f2fe78bSCy Schubert     BOOLEAN interactive = TRUE;
202*7f2fe78bSCy Schubert     HWND hwndOwner = (HWND)StationHandle;
203*7f2fe78bSCy Schubert     BOOLEAN lowercased_name = TRUE;
204*7f2fe78bSCy Schubert 
205*7f2fe78bSCy Schubert     /* Can we load KFW binaries? */
206*7f2fe78bSCy Schubert     if ( !KFW_is_available() )
207*7f2fe78bSCy Schubert         return 0;
208*7f2fe78bSCy Schubert 
209*7f2fe78bSCy Schubert     DebugEvent0("NPLogonNotify start");
210*7f2fe78bSCy Schubert 
211*7f2fe78bSCy Schubert     /* Remote Desktop / Terminal Server connections to existing sessions
212*7f2fe78bSCy Schubert      * are interactive logons.  Unfortunately, because the session already
213*7f2fe78bSCy Schubert      * exists the logon script does not get executed and this prevents
214*7f2fe78bSCy Schubert      * us from being able to execute the rundll32 entrypoint
215*7f2fe78bSCy Schubert      * LogonEventHandlerA which would process the credential cache this
216*7f2fe78bSCy Schubert      * routine will produce.  Therefore, we must cleanup orphaned cache
217*7f2fe78bSCy Schubert      * files from this routine.  We will take care of it before doing
218*7f2fe78bSCy Schubert      * anything else.
219*7f2fe78bSCy Schubert      */
220*7f2fe78bSCy Schubert     KFW_cleanup_orphaned_caches();
221*7f2fe78bSCy Schubert 
222*7f2fe78bSCy Schubert     /* Are we interactive? */
223*7f2fe78bSCy Schubert     if (lpStationName)
224*7f2fe78bSCy Schubert         interactive = (wcsicmp(lpStationName, L"WinSta0") == 0);
225*7f2fe78bSCy Schubert 
226*7f2fe78bSCy Schubert     if ( !interactive ) {
227*7f2fe78bSCy Schubert 	char station[64]="station";
228*7f2fe78bSCy Schubert         DWORD rv;
229*7f2fe78bSCy Schubert 
230*7f2fe78bSCy Schubert         SetLastError(0);
231*7f2fe78bSCy Schubert 	rv = WideCharToMultiByte(CP_UTF8, 0, lpStationName, -1,
232*7f2fe78bSCy Schubert 			    station, sizeof(station), NULL, NULL);
233*7f2fe78bSCy Schubert         DebugEvent("Skipping NPLogonNotify- LoginId(%d,%d) - Interactive(%d:%s) - gle %d",
234*7f2fe78bSCy Schubert                     lpLogonId->HighPart, lpLogonId->LowPart, interactive, rv != 0 ? station : "failure", GetLastError());
235*7f2fe78bSCy Schubert         return 0;
236*7f2fe78bSCy Schubert     } else
237*7f2fe78bSCy Schubert         DebugEvent("NPLogonNotify - LoginId(%d,%d)", lpLogonId->HighPart, lpLogonId->LowPart);
238*7f2fe78bSCy Schubert 
239*7f2fe78bSCy Schubert     /* Initialize Logon Script to none */
240*7f2fe78bSCy Schubert     *lpLogonScript=NULL;
241*7f2fe78bSCy Schubert 
242*7f2fe78bSCy Schubert     /* MSV1_0_INTERACTIVE_LOGON and KERB_INTERACTIVE_LOGON are equivalent for
243*7f2fe78bSCy Schubert      * our purposes */
244*7f2fe78bSCy Schubert 
245*7f2fe78bSCy Schubert     if ( wcsicmp(lpAuthentInfoType,L"MSV1_0:Interactive") &&
246*7f2fe78bSCy Schubert          wcsicmp(lpAuthentInfoType,L"Kerberos:Interactive") )
247*7f2fe78bSCy Schubert     {
248*7f2fe78bSCy Schubert 	char msg[64];
249*7f2fe78bSCy Schubert 	WideCharToMultiByte(CP_ACP, 0, lpAuthentInfoType, -1,
250*7f2fe78bSCy Schubert 			    msg, sizeof(msg), NULL, NULL);
251*7f2fe78bSCy Schubert 	msg[sizeof(msg)-1]='\0';
252*7f2fe78bSCy Schubert         DebugEvent("NPLogonNotify - Unsupported Authentication Info Type: %s", msg);
253*7f2fe78bSCy Schubert         return 0;
254*7f2fe78bSCy Schubert     }
255*7f2fe78bSCy Schubert 
256*7f2fe78bSCy Schubert     IL = (MSV1_0_INTERACTIVE_LOGON *) lpAuthentInfo;
257*7f2fe78bSCy Schubert 
258*7f2fe78bSCy Schubert     /* Convert from Unicode to ANSI */
259*7f2fe78bSCy Schubert 
260*7f2fe78bSCy Schubert     /*TODO: Use SecureZeroMemory to erase passwords */
261*7f2fe78bSCy Schubert     if (!UnicodeStringToANSI(IL->UserName, uname, MAX_USERNAME_LENGTH) ||
262*7f2fe78bSCy Schubert 	!UnicodeStringToANSI(IL->Password, password, MAX_PASSWORD_LENGTH) ||
263*7f2fe78bSCy Schubert 	!UnicodeStringToANSI(IL->LogonDomainName, logonDomain, MAX_DOMAIN_LENGTH))
264*7f2fe78bSCy Schubert 	return 0;
265*7f2fe78bSCy Schubert 
266*7f2fe78bSCy Schubert     /* Make sure AD-DOMAINS sent from login that is sent to us is stripped */
267*7f2fe78bSCy Schubert     ctemp = strchr(uname, '@');
268*7f2fe78bSCy Schubert     if (ctemp) *ctemp = 0;
269*7f2fe78bSCy Schubert 
270*7f2fe78bSCy Schubert     /* is the name all lowercase? */
271*7f2fe78bSCy Schubert     for ( ctemp = uname; *ctemp ; ctemp++) {
272*7f2fe78bSCy Schubert         if ( !islower(*ctemp) ) {
273*7f2fe78bSCy Schubert             lowercased_name = FALSE;
274*7f2fe78bSCy Schubert             break;
275*7f2fe78bSCy Schubert         }
276*7f2fe78bSCy Schubert     }
277*7f2fe78bSCy Schubert 
278*7f2fe78bSCy Schubert     code = KFW_get_cred(uname, password, 0, &reason);
279*7f2fe78bSCy Schubert     DebugEvent("NPLogonNotify - KFW_get_cred  uname=[%s] code=[%d]",uname, code);
280*7f2fe78bSCy Schubert 
281*7f2fe78bSCy Schubert     /* remove any kerberos 5 tickets currently held by the SYSTEM account
282*7f2fe78bSCy Schubert      * for this user
283*7f2fe78bSCy Schubert      */
284*7f2fe78bSCy Schubert     if (!code) {
285*7f2fe78bSCy Schubert 	char filename[MAX_PATH+1] = "";
286*7f2fe78bSCy Schubert 	char acctname[MAX_USERNAME_LENGTH+MAX_DOMAIN_LENGTH+3]="";
287*7f2fe78bSCy Schubert 	PSID pUserSid = NULL;
288*7f2fe78bSCy Schubert 	LPTSTR pReferencedDomainName = NULL;
289*7f2fe78bSCy Schubert 	DWORD dwSidLen = 0, dwDomainLen = 0, count;
290*7f2fe78bSCy Schubert 	SID_NAME_USE eUse;
291*7f2fe78bSCy Schubert 
292*7f2fe78bSCy Schubert 	if (_snprintf(acctname, sizeof(acctname), "%s\\%s", logonDomain, uname) < 0) {
293*7f2fe78bSCy Schubert 	    code = -1;
294*7f2fe78bSCy Schubert 	    goto cleanup;
295*7f2fe78bSCy Schubert 	}
296*7f2fe78bSCy Schubert 
297*7f2fe78bSCy Schubert 	count = GetTempPath(sizeof(filename), filename);
298*7f2fe78bSCy Schubert         if (count == 0 || count > (sizeof(filename)-1)) {
299*7f2fe78bSCy Schubert             code = -1;
300*7f2fe78bSCy Schubert             goto cleanup;
301*7f2fe78bSCy Schubert         }
302*7f2fe78bSCy Schubert 
303*7f2fe78bSCy Schubert 	if (_snprintf(filename, sizeof(filename), "%s\\kfwlogon-%x.%x",
304*7f2fe78bSCy Schubert 		       filename, lpLogonId->HighPart, lpLogonId->LowPart) < 0)
305*7f2fe78bSCy Schubert 	{
306*7f2fe78bSCy Schubert 	    code = -1;
307*7f2fe78bSCy Schubert 	    goto cleanup;
308*7f2fe78bSCy Schubert 	}
309*7f2fe78bSCy Schubert 
310*7f2fe78bSCy Schubert 	KFW_copy_cache_to_system_file(uname, filename);
311*7f2fe78bSCy Schubert 
312*7f2fe78bSCy Schubert 	/* Need to determine the SID */
313*7f2fe78bSCy Schubert 
314*7f2fe78bSCy Schubert 	/* First get the size of the required buffers */
315*7f2fe78bSCy Schubert 	LookupAccountName (NULL,
316*7f2fe78bSCy Schubert 			   acctname,
317*7f2fe78bSCy Schubert 			   pUserSid,
318*7f2fe78bSCy Schubert 			   &dwSidLen,
319*7f2fe78bSCy Schubert 			   pReferencedDomainName,
320*7f2fe78bSCy Schubert 			   &dwDomainLen,
321*7f2fe78bSCy Schubert 			   &eUse);
322*7f2fe78bSCy Schubert 	if(dwSidLen){
323*7f2fe78bSCy Schubert 	    pUserSid = (PSID) malloc (dwSidLen);
324*7f2fe78bSCy Schubert 	    memset(pUserSid,0,dwSidLen);
325*7f2fe78bSCy Schubert 	}
326*7f2fe78bSCy Schubert 
327*7f2fe78bSCy Schubert 	if(dwDomainLen){
328*7f2fe78bSCy Schubert 	    pReferencedDomainName = (LPTSTR) malloc (dwDomainLen * sizeof(TCHAR));
329*7f2fe78bSCy Schubert 	    memset(pReferencedDomainName,0,dwDomainLen * sizeof(TCHAR));
330*7f2fe78bSCy Schubert 	}
331*7f2fe78bSCy Schubert 
332*7f2fe78bSCy Schubert 	//Now get the SID and the domain name
333*7f2fe78bSCy Schubert 	if (pUserSid && LookupAccountName( NULL,
334*7f2fe78bSCy Schubert 					   acctname,
335*7f2fe78bSCy Schubert 					   pUserSid,
336*7f2fe78bSCy Schubert 					   &dwSidLen,
337*7f2fe78bSCy Schubert 					   pReferencedDomainName,
338*7f2fe78bSCy Schubert 					   &dwDomainLen,
339*7f2fe78bSCy Schubert 					   &eUse))
340*7f2fe78bSCy Schubert 	{
341*7f2fe78bSCy Schubert 	    DebugEvent("LookupAccountName obtained user %s sid in domain %s", acctname, pReferencedDomainName);
342*7f2fe78bSCy Schubert 	    code = KFW_set_ccache_dacl_with_user_sid(filename, pUserSid);
343*7f2fe78bSCy Schubert 
344*7f2fe78bSCy Schubert #ifdef USE_WINLOGON_EVENT
345*7f2fe78bSCy Schubert 	    /* If we are on Vista, setup a LogonScript
346*7f2fe78bSCy Schubert 	     * that will execute the LogonEventHandler entry point via rundll32.exe
347*7f2fe78bSCy Schubert 	     */
348*7f2fe78bSCy Schubert 	    if (is_windows_vista()) {
349*7f2fe78bSCy Schubert 		ConfigureLogonScript(lpLogonScript, filename);
350*7f2fe78bSCy Schubert 		if (*lpLogonScript)
351*7f2fe78bSCy Schubert 		    DebugEvent0("LogonScript assigned");
352*7f2fe78bSCy Schubert 		else
353*7f2fe78bSCy Schubert 		    DebugEvent0("No Logon Script");
354*7f2fe78bSCy Schubert 	    }
355*7f2fe78bSCy Schubert #else
356*7f2fe78bSCy Schubert 	    ConfigureLogonScript(lpLogonScript, filename);
357*7f2fe78bSCy Schubert 	    if (*lpLogonScript)
358*7f2fe78bSCy Schubert 		    DebugEvent0("LogonScript assigned");
359*7f2fe78bSCy Schubert 	    else
360*7f2fe78bSCy Schubert 		    DebugEvent0("No Logon Script");
361*7f2fe78bSCy Schubert #endif
362*7f2fe78bSCy Schubert 	} else {
363*7f2fe78bSCy Schubert 	    DebugEvent0("LookupAccountName failed");
364*7f2fe78bSCy Schubert 	    DeleteFile(filename);
365*7f2fe78bSCy Schubert 	    code = -1;
366*7f2fe78bSCy Schubert 	}
367*7f2fe78bSCy Schubert 
368*7f2fe78bSCy Schubert       cleanup:
369*7f2fe78bSCy Schubert 	if (pUserSid)
370*7f2fe78bSCy Schubert 	    free(pUserSid);
371*7f2fe78bSCy Schubert 	if (pReferencedDomainName)
372*7f2fe78bSCy Schubert 	    free(pReferencedDomainName);
373*7f2fe78bSCy Schubert     }
374*7f2fe78bSCy Schubert 
375*7f2fe78bSCy Schubert     KFW_destroy_tickets_for_principal(uname);
376*7f2fe78bSCy Schubert 
377*7f2fe78bSCy Schubert     if (code) {
378*7f2fe78bSCy Schubert         char msg[128];
379*7f2fe78bSCy Schubert         HANDLE h;
380*7f2fe78bSCy Schubert         char *ptbuf[1];
381*7f2fe78bSCy Schubert 
382*7f2fe78bSCy Schubert         StringCbPrintf(msg, sizeof(msg), "Kerberos ticket acquisition failed: %s", reason);
383*7f2fe78bSCy Schubert 
384*7f2fe78bSCy Schubert         h = RegisterEventSource(NULL, KFW_LOGON_EVENT_NAME);
385*7f2fe78bSCy Schubert         ptbuf[0] = msg;
386*7f2fe78bSCy Schubert         ReportEvent(h, EVENTLOG_WARNING_TYPE, 0, 1008, NULL, 1, 0, ptbuf, NULL);
387*7f2fe78bSCy Schubert         DeregisterEventSource(h);
388*7f2fe78bSCy Schubert         SetLastError(code);
389*7f2fe78bSCy Schubert     }
390*7f2fe78bSCy Schubert 
391*7f2fe78bSCy Schubert     if (code)
392*7f2fe78bSCy Schubert 	DebugEvent0("NPLogonNotify failure");
393*7f2fe78bSCy Schubert     else
394*7f2fe78bSCy Schubert 	DebugEvent0("NPLogonNotify success");
395*7f2fe78bSCy Schubert 
396*7f2fe78bSCy Schubert     return code;
397*7f2fe78bSCy Schubert }
398*7f2fe78bSCy Schubert 
399*7f2fe78bSCy Schubert 
NPPasswordChangeNotify(LPCWSTR lpAuthentInfoType,LPVOID lpAuthentInfo,LPCWSTR lpPreviousAuthentInfoType,LPVOID lpPreviousAuthentInfo,LPWSTR lpStationName,LPVOID StationHandle,DWORD dwChangeInfo)400*7f2fe78bSCy Schubert DWORD APIENTRY NPPasswordChangeNotify(
401*7f2fe78bSCy Schubert 	LPCWSTR lpAuthentInfoType,
402*7f2fe78bSCy Schubert 	LPVOID lpAuthentInfo,
403*7f2fe78bSCy Schubert 	LPCWSTR lpPreviousAuthentInfoType,
404*7f2fe78bSCy Schubert 	LPVOID lpPreviousAuthentInfo,
405*7f2fe78bSCy Schubert 	LPWSTR lpStationName,
406*7f2fe78bSCy Schubert 	LPVOID StationHandle,
407*7f2fe78bSCy Schubert 	DWORD dwChangeInfo)
408*7f2fe78bSCy Schubert {
409*7f2fe78bSCy Schubert     return 0;
410*7f2fe78bSCy Schubert }
411*7f2fe78bSCy Schubert 
412*7f2fe78bSCy Schubert #include <userenv.h>
413*7f2fe78bSCy Schubert #include <Winwlx.h>
414*7f2fe78bSCy Schubert 
415*7f2fe78bSCy Schubert #ifdef COMMENT
416*7f2fe78bSCy Schubert typedef struct _WLX_NOTIFICATION_INFO {
417*7f2fe78bSCy Schubert     ULONG Size;
418*7f2fe78bSCy Schubert     ULONG Flags;
419*7f2fe78bSCy Schubert     PWSTR UserName;
420*7f2fe78bSCy Schubert     PWSTR Domain;
421*7f2fe78bSCy Schubert     PWSTR WindowStation;
422*7f2fe78bSCy Schubert     HANDLE hToken;
423*7f2fe78bSCy Schubert     HDESK hDesktop;
424*7f2fe78bSCy Schubert     PFNMSGECALLBACK pStatusCallback;
425*7f2fe78bSCy Schubert } WLX_NOTIFICATION_INFO, *PWLX_NOTIFICATION_INFO;
426*7f2fe78bSCy Schubert #endif
427*7f2fe78bSCy Schubert 
KFW_Startup_Event(PWLX_NOTIFICATION_INFO pInfo)428*7f2fe78bSCy Schubert VOID KFW_Startup_Event( PWLX_NOTIFICATION_INFO pInfo )
429*7f2fe78bSCy Schubert {
430*7f2fe78bSCy Schubert     DebugEvent0("KFW_Startup_Event");
431*7f2fe78bSCy Schubert }
432*7f2fe78bSCy Schubert 
433*7f2fe78bSCy Schubert static BOOL
GetSecurityLogonSessionData(HANDLE hToken,PSECURITY_LOGON_SESSION_DATA * ppSessionData)434*7f2fe78bSCy Schubert GetSecurityLogonSessionData(HANDLE hToken, PSECURITY_LOGON_SESSION_DATA * ppSessionData)
435*7f2fe78bSCy Schubert {
436*7f2fe78bSCy Schubert     NTSTATUS Status = 0;
437*7f2fe78bSCy Schubert     TOKEN_STATISTICS Stats;
438*7f2fe78bSCy Schubert     DWORD   ReqLen;
439*7f2fe78bSCy Schubert     BOOL    Success;
440*7f2fe78bSCy Schubert 
441*7f2fe78bSCy Schubert     if (!ppSessionData)
442*7f2fe78bSCy Schubert         return FALSE;
443*7f2fe78bSCy Schubert     *ppSessionData = NULL;
444*7f2fe78bSCy Schubert 
445*7f2fe78bSCy Schubert 
446*7f2fe78bSCy Schubert     Success = GetTokenInformation( hToken, TokenStatistics, &Stats, sizeof(TOKEN_STATISTICS), &ReqLen );
447*7f2fe78bSCy Schubert     if ( !Success )
448*7f2fe78bSCy Schubert         return FALSE;
449*7f2fe78bSCy Schubert 
450*7f2fe78bSCy Schubert     Status = LsaGetLogonSessionData( &Stats.AuthenticationId, ppSessionData );
451*7f2fe78bSCy Schubert     if ( FAILED(Status) || !ppSessionData )
452*7f2fe78bSCy Schubert         return FALSE;
453*7f2fe78bSCy Schubert 
454*7f2fe78bSCy Schubert     return TRUE;
455*7f2fe78bSCy Schubert }
456*7f2fe78bSCy Schubert 
KFW_Logon_Event(PWLX_NOTIFICATION_INFO pInfo)457*7f2fe78bSCy Schubert VOID KFW_Logon_Event( PWLX_NOTIFICATION_INFO pInfo )
458*7f2fe78bSCy Schubert {
459*7f2fe78bSCy Schubert #ifdef USE_WINLOGON_EVENT
460*7f2fe78bSCy Schubert     WCHAR szUserW[128] = L"";
461*7f2fe78bSCy Schubert     char  szUserA[128] = "";
462*7f2fe78bSCy Schubert     char szPath[MAX_PATH] = "";
463*7f2fe78bSCy Schubert     char szLogonId[128] = "";
464*7f2fe78bSCy Schubert     DWORD count;
465*7f2fe78bSCy Schubert     char filename[MAX_PATH] = "";
466*7f2fe78bSCy Schubert     char newfilename[MAX_PATH] = "";
467*7f2fe78bSCy Schubert     char commandline[MAX_PATH+256] = "";
468*7f2fe78bSCy Schubert     STARTUPINFO startupinfo;
469*7f2fe78bSCy Schubert     PROCESS_INFORMATION procinfo;
470*7f2fe78bSCy Schubert     HANDLE hf = NULL;
471*7f2fe78bSCy Schubert 
472*7f2fe78bSCy Schubert     LUID LogonId = {0, 0};
473*7f2fe78bSCy Schubert     PSECURITY_LOGON_SESSION_DATA pLogonSessionData = NULL;
474*7f2fe78bSCy Schubert 
475*7f2fe78bSCy Schubert     HKEY hKey1 = NULL, hKey2 = NULL;
476*7f2fe78bSCy Schubert 
477*7f2fe78bSCy Schubert     DebugEvent0("KFW_Logon_Event - Start");
478*7f2fe78bSCy Schubert 
479*7f2fe78bSCy Schubert     GetSecurityLogonSessionData( pInfo->hToken, &pLogonSessionData );
480*7f2fe78bSCy Schubert 
481*7f2fe78bSCy Schubert     if ( pLogonSessionData ) {
482*7f2fe78bSCy Schubert         LogonId = pLogonSessionData->LogonId;
483*7f2fe78bSCy Schubert         DebugEvent("KFW_Logon_Event - LogonId(%d,%d)", LogonId.HighPart, LogonId.LowPart);
484*7f2fe78bSCy Schubert 
485*7f2fe78bSCy Schubert         _snprintf(szLogonId, sizeof(szLogonId), "kfwlogon-%d.%d",LogonId.HighPart, LogonId.LowPart);
486*7f2fe78bSCy Schubert         LsaFreeReturnBuffer( pLogonSessionData );
487*7f2fe78bSCy Schubert     } else {
488*7f2fe78bSCy Schubert         DebugEvent0("KFW_Logon_Event - Unable to determine LogonId");
489*7f2fe78bSCy Schubert         return;
490*7f2fe78bSCy Schubert     }
491*7f2fe78bSCy Schubert 
492*7f2fe78bSCy Schubert     count = GetEnvironmentVariable("TEMP", filename, sizeof(filename));
493*7f2fe78bSCy Schubert     if ( count > sizeof(filename) || count == 0 ) {
494*7f2fe78bSCy Schubert         GetWindowsDirectory(filename, sizeof(filename));
495*7f2fe78bSCy Schubert     }
496*7f2fe78bSCy Schubert 
497*7f2fe78bSCy Schubert     if ( strlen(filename) + strlen(szLogonId) + 2 > sizeof(filename) ) {
498*7f2fe78bSCy Schubert         DebugEvent0("KFW_Logon_Event - filename too long");
499*7f2fe78bSCy Schubert 	return;
500*7f2fe78bSCy Schubert     }
501*7f2fe78bSCy Schubert 
502*7f2fe78bSCy Schubert     strcat(filename, "\\");
503*7f2fe78bSCy Schubert     strcat(filename, szLogonId);
504*7f2fe78bSCy Schubert 
505*7f2fe78bSCy Schubert     hf = CreateFile(filename, FILE_ALL_ACCESS, 0, NULL, OPEN_EXISTING,
506*7f2fe78bSCy Schubert 		    FILE_ATTRIBUTE_NORMAL, NULL);
507*7f2fe78bSCy Schubert     if (hf == INVALID_HANDLE_VALUE) {
508*7f2fe78bSCy Schubert         DebugEvent0("KFW_Logon_Event - file cannot be opened");
509*7f2fe78bSCy Schubert 	return;
510*7f2fe78bSCy Schubert     }
511*7f2fe78bSCy Schubert     CloseHandle(hf);
512*7f2fe78bSCy Schubert 
513*7f2fe78bSCy Schubert     if (KFW_set_ccache_dacl(filename, pInfo->hToken)) {
514*7f2fe78bSCy Schubert         DebugEvent0("KFW_Logon_Event - unable to set dacl");
515*7f2fe78bSCy Schubert 	DeleteFile(filename);
516*7f2fe78bSCy Schubert 	return;
517*7f2fe78bSCy Schubert     }
518*7f2fe78bSCy Schubert 
519*7f2fe78bSCy Schubert     if (KFW_obtain_user_temp_directory(pInfo->hToken, newfilename, sizeof(newfilename))) {
520*7f2fe78bSCy Schubert         DebugEvent0("KFW_Logon_Event - unable to obtain temp directory");
521*7f2fe78bSCy Schubert 	return;
522*7f2fe78bSCy Schubert     }
523*7f2fe78bSCy Schubert 
524*7f2fe78bSCy Schubert     if ( strlen(newfilename) + strlen(szLogonId) + 2 > sizeof(newfilename) ) {
525*7f2fe78bSCy Schubert         DebugEvent0("KFW_Logon_Event - new filename too long");
526*7f2fe78bSCy Schubert 	return;
527*7f2fe78bSCy Schubert     }
528*7f2fe78bSCy Schubert 
529*7f2fe78bSCy Schubert     strcat(newfilename, "\\");
530*7f2fe78bSCy Schubert     strcat(newfilename, szLogonId);
531*7f2fe78bSCy Schubert 
532*7f2fe78bSCy Schubert     if (!MoveFileEx(filename, newfilename,
533*7f2fe78bSCy Schubert 		     MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH)) {
534*7f2fe78bSCy Schubert         DebugEvent("KFW_Logon_Event - MoveFileEx failed GLE = 0x%x", GetLastError());
535*7f2fe78bSCy Schubert 	return;
536*7f2fe78bSCy Schubert     }
537*7f2fe78bSCy Schubert 
538*7f2fe78bSCy Schubert     _snprintf(commandline, sizeof(commandline), "kfwcpcc.exe \"%s\"", newfilename);
539*7f2fe78bSCy Schubert 
540*7f2fe78bSCy Schubert     GetStartupInfo(&startupinfo);
541*7f2fe78bSCy Schubert     if (CreateProcessAsUser( pInfo->hToken,
542*7f2fe78bSCy Schubert                              "kfwcpcc.exe",
543*7f2fe78bSCy Schubert                              commandline,
544*7f2fe78bSCy Schubert                              NULL,
545*7f2fe78bSCy Schubert                              NULL,
546*7f2fe78bSCy Schubert                              FALSE,
547*7f2fe78bSCy Schubert                              CREATE_NEW_PROCESS_GROUP | DETACHED_PROCESS,
548*7f2fe78bSCy Schubert                              NULL,
549*7f2fe78bSCy Schubert                              NULL,
550*7f2fe78bSCy Schubert                              &startupinfo,
551*7f2fe78bSCy Schubert                              &procinfo))
552*7f2fe78bSCy Schubert     {
553*7f2fe78bSCy Schubert 	DebugEvent("KFW_Logon_Event - CommandLine %s", commandline);
554*7f2fe78bSCy Schubert 
555*7f2fe78bSCy Schubert 	WaitForSingleObject(procinfo.hProcess, 30000);
556*7f2fe78bSCy Schubert 
557*7f2fe78bSCy Schubert 	CloseHandle(procinfo.hThread);
558*7f2fe78bSCy Schubert 	CloseHandle(procinfo.hProcess);
559*7f2fe78bSCy Schubert     } else {
560*7f2fe78bSCy Schubert 	DebugEvent0("KFW_Logon_Event - CreateProcessFailed");
561*7f2fe78bSCy Schubert     }
562*7f2fe78bSCy Schubert 
563*7f2fe78bSCy Schubert     DeleteFile(newfilename);
564*7f2fe78bSCy Schubert 
565*7f2fe78bSCy Schubert     DebugEvent0("KFW_Logon_Event - End");
566*7f2fe78bSCy Schubert #endif /* USE_WINLOGON_EVENT */
567*7f2fe78bSCy Schubert }
568*7f2fe78bSCy Schubert 
569*7f2fe78bSCy Schubert 
570*7f2fe78bSCy Schubert /* Documentation on the use of RunDll32 entrypoints can be found
571*7f2fe78bSCy Schubert  * at https://support.microsoft.com/kb/164787
572*7f2fe78bSCy Schubert  */
573*7f2fe78bSCy Schubert void CALLBACK
LogonEventHandlerA(HWND hwnd,HINSTANCE hinst,LPSTR lpszCmdLine,int nCmdShow)574*7f2fe78bSCy Schubert LogonEventHandlerA(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow)
575*7f2fe78bSCy Schubert {
576*7f2fe78bSCy Schubert     HANDLE hf = NULL;
577*7f2fe78bSCy Schubert     char commandline[MAX_PATH+256] = "";
578*7f2fe78bSCy Schubert     STARTUPINFO startupinfo;
579*7f2fe78bSCy Schubert     PROCESS_INFORMATION procinfo;
580*7f2fe78bSCy Schubert 
581*7f2fe78bSCy Schubert     DebugEvent0("LogonEventHandler - Start");
582*7f2fe78bSCy Schubert 
583*7f2fe78bSCy Schubert     /* Validate lpszCmdLine as a file */
584*7f2fe78bSCy Schubert     hf = CreateFile(lpszCmdLine, GENERIC_READ | DELETE, 0, NULL, OPEN_EXISTING,
585*7f2fe78bSCy Schubert 		    FILE_ATTRIBUTE_NORMAL, NULL);
586*7f2fe78bSCy Schubert     if (hf == INVALID_HANDLE_VALUE) {
587*7f2fe78bSCy Schubert         DebugEvent("LogonEventHandler - \"%s\" cannot be opened", lpszCmdLine);
588*7f2fe78bSCy Schubert 	return;
589*7f2fe78bSCy Schubert     }
590*7f2fe78bSCy Schubert     CloseHandle(hf);
591*7f2fe78bSCy Schubert 
592*7f2fe78bSCy Schubert 
593*7f2fe78bSCy Schubert     _snprintf(commandline, sizeof(commandline), "kfwcpcc.exe \"%s\"", lpszCmdLine);
594*7f2fe78bSCy Schubert 
595*7f2fe78bSCy Schubert     GetStartupInfo(&startupinfo);
596*7f2fe78bSCy Schubert     SetLastError(0);
597*7f2fe78bSCy Schubert     if (CreateProcess( NULL,
598*7f2fe78bSCy Schubert 		       commandline,
599*7f2fe78bSCy Schubert 		       NULL,
600*7f2fe78bSCy Schubert 		       NULL,
601*7f2fe78bSCy Schubert 		       FALSE,
602*7f2fe78bSCy Schubert 		       CREATE_NEW_PROCESS_GROUP | DETACHED_PROCESS,
603*7f2fe78bSCy Schubert 		       NULL,
604*7f2fe78bSCy Schubert 		       NULL,
605*7f2fe78bSCy Schubert 		       &startupinfo,
606*7f2fe78bSCy Schubert 		       &procinfo))
607*7f2fe78bSCy Schubert     {
608*7f2fe78bSCy Schubert 	DebugEvent("KFW_Logon_Event - CommandLine %s", commandline);
609*7f2fe78bSCy Schubert 
610*7f2fe78bSCy Schubert 	WaitForSingleObject(procinfo.hProcess, 30000);
611*7f2fe78bSCy Schubert 
612*7f2fe78bSCy Schubert 	CloseHandle(procinfo.hThread);
613*7f2fe78bSCy Schubert 	CloseHandle(procinfo.hProcess);
614*7f2fe78bSCy Schubert     } else {
615*7f2fe78bSCy Schubert 	DebugEvent("KFW_Logon_Event - CreateProcessFailed \"%s\" GLE 0x%x",
616*7f2fe78bSCy Schubert                      commandline, GetLastError());
617*7f2fe78bSCy Schubert         DebugEvent("KFW_Logon_Event PATH %s", getenv("PATH"));
618*7f2fe78bSCy Schubert     }
619*7f2fe78bSCy Schubert 
620*7f2fe78bSCy Schubert     DeleteFile(lpszCmdLine);
621*7f2fe78bSCy Schubert 
622*7f2fe78bSCy Schubert     DebugEvent0("KFW_Logon_Event - End");
623*7f2fe78bSCy Schubert }
624