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