xref: /freebsd/crypto/krb5/src/lib/win_glue.c (revision 7f2fe78b9dd5f51c821d771b63d2e096f6fd49e9)
1 #include "k5-int.h"
2 
3 #ifdef KRB5
4 #include "krb5_err.h"
5 #include "kv5m_err.h"
6 #include "asn1_err.h"
7 #include "kdb5_err.h"
8 #include "profile.h"
9 extern void krb5_stdcc_shutdown();
10 #endif
11 #ifdef GSSAPI
12 #include "gssapi/generic/gssapi_err_generic.h"
13 #include "gssapi/krb5/gssapi_err_krb5.h"
14 #endif
15 
16 
17 /*
18  * #defines for MIT-specific time-based timebombs and/or version
19  * server for the Kerberos DLL.
20  */
21 
22 #ifdef SAP_TIMEBOMB
23 #define TIMEBOMB 865141200	/* 1-Jun-97 */
24 #define TIMEBOMB_PRODUCT "SAPGUI"
25 #define TIMEBOMB_WARN  15
26 #define TIMEBOMB_INFO "  Please see the web page at:\nhttp://web.mit.edu/reeng/www/saphelp for more information"
27 #define TIMEBOMB_ERROR KRB5_APPL_EXPIRED
28 #endif
29 
30 #ifdef KRB_TIMEBOMB
31 #define TIMEBOMB 865141200	/* 1-Jun-97 */
32 #define TIMEBOMB_PRODUCT "Kerberos V5"
33 #define TIMEBOMB_WARN 15
34 #define TIMEBOMB_INFO "  Please see the web page at:\nhttp://web.mit.edu/reeng/www/saphelp for more information"
35 #define TIMEBOMB_ERROR KRB5_LIB_EXPIRED
36 #endif
37 
38 /*
39  * #defines for using MIT's version server DLL
40  */
41 #ifdef SAP_VERSERV
42 #define APP_TITLE "KRB5-SAP"
43 #define APP_VER "3.0f"
44 #define APP_INI "krb5sap.ini"
45 #define VERSERV_ERROR 	KRB5_APPL_EXPIRED
46 #endif
47 
48 #ifdef VERSERV
49 #define WINDOWS
50 #include <ver.h>
51 #include <vs.h>
52 #include <v.h>
53 
54 
55 /*
56  * This function will get the version resource information from the
57  * application using the DLL.  This allows us to Version Serve
58  * arbitrary third party applications.  If there is an error, or we
59  * decide that we should not version check the calling application
60  * then VSflag will be FALSE when the function returns.
61  *
62  * The buffers passed into this function must be at least
63  * APPVERINFO_SIZE bytes long.
64  */
65 
66 #define APPVERINFO_SIZE 256
67 
GetCallingAppVerInfo(char * AppTitle,char * AppVer,char * AppIni,BOOL * VSflag)68 void GetCallingAppVerInfo( char *AppTitle, char *AppVer, char *AppIni,
69 			  BOOL *VSflag)
70 {
71 	char CallerFilename[_MAX_PATH];
72 	LONG *lpLangInfo;
73 	DWORD hVersionInfoID, size;
74 	GLOBALHANDLE hVersionInfo;
75 	LPSTR lpVersionInfo;
76 	int dumint, retval;
77 	char *cp;
78 	char *revAppTitle;
79 	char szVerQ[90];
80 	LPBYTE locAppTitle;
81 	LPBYTE locAppVer;
82 	char locAppIni[_MAX_PATH];
83 #ifndef _WIN32
84 	WORD wStackSeg;
85 #endif /* !_WIN32 */
86 
87 	/* first we need to get the calling module's filename */
88 #ifndef _WIN32
89 	_asm {
90 		mov wStackSeg, ss
91 	};
92 	retval = GetModuleFileName((HMODULE)wStackSeg, CallerFilename,
93 		_MAX_PATH);
94 #else
95 	/*
96 	 * Note: this may only work for single threaded applications,
97 	 * we'll live and learn ...
98 	 */
99         retval = GetModuleFileName( NULL, CallerFilename, _MAX_PATH);
100 #endif
101 
102 	if ( retval == 0 ) {
103 		VSflag = FALSE;
104 		return;
105 	}
106 
107 	size = GetFileVersionInfoSize( CallerFilename, &hVersionInfoID);
108 
109 	if( size == 0 ) {
110 		/*
111 		 * hey , I bet we don't have a version resource, let's
112 		 * punt
113 		 */
114 		*VSflag = FALSE;
115 		return;
116 	}
117 
118 	hVersionInfo = GlobalAlloc(GHND, size);
119 	lpVersionInfo = GlobalLock(hVersionInfo);
120 
121 	retval = GetFileVersionInfo( CallerFilename, hVersionInfoID, size,
122 				    lpVersionInfo);
123 
124 	retval = VerQueryValue(lpVersionInfo, "\\VarFileInfo\\Translation",
125 			       (LPSTR *)&lpLangInfo, &dumint);
126 	wsprintf(szVerQ,
127 		 "\\StringFileInfo\\%04x%04x\\",
128 		 LOWORD(*lpLangInfo), HIWORD(*lpLangInfo));
129 
130 	cp = szVerQ + lstrlen(szVerQ);
131 
132 	lstrcpy(cp, "ProductName");
133 
134 
135 	/* try a localAppTitle and then a strcpy 4/2/97 */
136 
137 	locAppTitle = 0;
138 	locAppVer = 0;
139 
140 	retval = VerQueryValue(lpVersionInfo, szVerQ, &locAppTitle,
141 			       &dumint);
142 
143 	lstrcpy(cp, "ProductVersion");
144 
145 
146 	retval = VerQueryValue(lpVersionInfo, szVerQ, &locAppVer,
147 			       &dumint);
148 
149 	if (!locAppTitle || !locAppVer) {
150 	  	/* Punt, we don't have the right version resource records */
151 		*VSflag = FALSE;
152 		return;
153 	}
154 
155 	/*
156 	 * We don't have a way to determine that INI file of the
157 	 * application at the moment so let's just use krb5.ini
158 	 */
159 	strncpy( locAppIni, KERBEROS_INI, sizeof(locAppIni) - 1 );
160 	locAppIni[ sizeof(locAppIni) - 1 ] = '\0';
161 
162 	strncpy( AppTitle, locAppTitle, APPVERINFO_SIZE);
163 	AppTitle[APPVERINFO_SIZE - 1] = '\0';
164 	strncpy( AppVer, locAppVer, APPVERINFO_SIZE);
165 	AppVer[APPVERINFO_SIZE - 1] = '\0';
166 	strncpy( AppIni, locAppIni, APPVERINFO_SIZE);
167 	AppIni[APPVERINFO_SIZE - 1] = '\0';
168 
169 	/*
170 	 * We also need to determine if we want to suppress version
171 	 * checking of this application.  Does the tail of the
172 	 * AppTitle end in a "-v" ?
173 	 */
174 	revAppTitle = _strrev( _strdup(AppTitle));
175 	if( revAppTitle[0] == 'v' || revAppTitle[0] == 'V'  &&
176 	   revAppTitle[1] == '-' ) {
177 		VSflag = FALSE;
178 	}
179 	return;
180 }
181 
182 
183 /*
184  * Use the version server to give us some control on distribution and usage
185  * We're going to test track as well
186  */
CallVersionServer(app_title,app_version,app_ini,code_cover)187 static int CallVersionServer(app_title, app_version, app_ini, code_cover)
188 	char *app_title;
189 	char *app_version;
190 	char *app_ini;
191 	char *code_cover;
192 {
193 	VS_Request vrequest;
194 	VS_Status  vstatus;
195 
196 	SetCursor(LoadCursor(NULL, IDC_WAIT));
197 
198 	/*
199 	 * We should be able to pass in code_cover below, but things
200 	 * are breaking under Windows 16 for no good reason.
201 	 */
202 	vrequest = VSFormRequest((LPSTR) app_title, (LPSTR) app_version,
203 				 (LPSTR) app_ini,
204 				 NULL /* code_cover */, NULL,
205 				 V_CHECK_AND_LOG);
206 
207 	SetCursor(LoadCursor(NULL, IDC_ARROW));
208 	/*
209 	 * If the user presses cancel when registering the test
210 	 * tracker, we'll let them continue.
211 	 */
212 	if (ReqStatus(vrequest) == V_E_CANCEL) {
213 		VSDestroyRequest(vrequest);
214 		return 0;
215 	}
216 	vstatus = VSProcessRequest(vrequest);
217 	/*
218 	 * Only complain periodically, if the test tracker isn't
219 	 * working...
220 	 */
221 	if (v_complain(vstatus, app_ini)) {
222 		WinVSReportRequest(vrequest, NULL,
223 				   "Version Server Status Report");
224 	}
225 	if (vstatus == V_REQUIRED) {
226 		SetCursor(LoadCursor(NULL, IDC_WAIT));
227 		VSDestroyRequest(vrequest);
228 		return( -1 );
229 	}
230 	VSDestroyRequest(vrequest);
231 	return (0);
232 }
233 #endif
234 
235 #ifdef TIMEBOMB
do_timebomb()236 static krb5_error_code do_timebomb()
237 {
238 	char buf[1024];
239 	long timeleft;
240 	static first_time = 1;
241 
242 	timeleft = TIMEBOMB - time(0);
243 	if (timeleft <= 0) {
244 		if (first_time) {
245 			sprintf(buf, "Your version of %s has expired.\n",
246 				TIMEBOMB_PRODUCT);
247 			buf[sizeof(buf) - 1] = '\0';
248 			strncat(buf, "Please upgrade it.", sizeof(buf) - 1 - strlen(buf));
249 #ifdef TIMEBOMB_INFO
250 			strncat(buf, TIMEBOMB_INFO, sizeof(buf) - 1 - strlen(buf));
251 #endif
252 			MessageBox(NULL, buf, "", MB_OK);
253 			first_time = 0;
254 		}
255 		return TIMEBOMB_ERROR;
256 	}
257 	timeleft = timeleft / ((long) 60*60*24);
258 	if (timeleft < TIMEBOMB_WARN) {
259 		if (first_time) {
260 			sprintf(buf, "Your version of %s will expire in %ld days.\n",
261 				TIMEBOMB_PRODUCT, timeleft);
262 			strncat(buf, "Please upgrade it soon.", sizeof(buf) - 1 - strlen(buf));
263 #ifdef TIMEBOMB_INFO
264 			strncat(buf, TIMEBOMB_INFO, sizeof(buf) - 1 - strlen(buf));
265 #endif
266 			MessageBox(NULL, buf, "", MB_OK);
267 			first_time = 0;
268 		}
269 	}
270 	return 0;
271 }
272 #endif
273 
274 /*
275  * This was originally called from LibMain; unfortunately, Windows 3.1
276  * doesn't allow you to make messaging calls from LibMain.  So, we now
277  * do the timebomb/version server stuff from krb5_init_context().
278  */
krb5_vercheck()279 krb5_error_code krb5_vercheck()
280 {
281 	static int verchecked = 0;
282 	if (verchecked)
283 		return 0;
284 #ifdef TIMEBOMB
285 	krb5_error_code retval = do_timebomb();
286 	if (retval)
287 		return retval;
288 #endif
289 #ifdef VERSERV
290 	{
291 #ifdef APP_TITLE
292 		if (CallVersionServer(APP_TITLE, APP_VER, APP_INI, NULL))
293 			return VERSERV_ERROR;
294 #else
295 		char AppTitle[APPVERINFO_SIZE];
296 		char AppVer[APPVERINFO_SIZE];
297 		char AppIni[APPVERINFO_SIZE];
298 		BOOL VSflag=TRUE;
299 
300 		GetCallingAppVerInfo( AppTitle, AppVer, AppIni, &VSflag);
301 
302 		if (VSflag) {
303 			if (CallVersionServer(AppTitle, AppVer, AppIni, NULL))
304 				return KRB5_APPL_EXPIRED;
305 		}
306 #endif
307 
308 	}
309 #endif
310         verchecked = 1;
311 	return 0;
312 }
313 
314 
315 static HINSTANCE hlibinstance;
316 
get_lib_instance()317 HINSTANCE get_lib_instance()
318 {
319     return hlibinstance;
320 }
321 
322 #define DLL_STARTUP 0
323 #define DLL_SHUTDOWN 1
324 
325 static int
control(int mode)326 control(int mode)
327 {
328     switch(mode) {
329     case DLL_STARTUP:
330 	break;
331 
332     case DLL_SHUTDOWN:
333 #ifdef KRB5
334 	krb5_stdcc_shutdown();
335 #endif
336 	break;
337 
338 #if defined(ENABLE_THREADS) && defined(SUPPORTLIB)
339     case DLL_THREAD_DETACH:
340 	krb5int_thread_detach_hook();
341 	return 0;
342 #endif
343 
344     default:
345 	return -1;
346     }
347 
348 #if defined KRB5
349     switch (mode) {
350     case DLL_STARTUP:
351 	profile_library_initializer__auxinit();
352 	krb5int_lib_init__auxinit();
353 	break;
354     case DLL_SHUTDOWN:
355 	krb5int_lib_fini();
356 	profile_library_finalizer();
357 	break;
358     }
359 #elif defined GSSAPI
360     switch (mode) {
361     case DLL_STARTUP:
362 	gssint_mechglue_init__auxinit();
363 	break;
364     case DLL_SHUTDOWN:
365 	gssint_mechglue_fini();
366 	break;
367     }
368 #elif defined COMERR
369     switch (mode) {
370     case DLL_STARTUP:
371 	com_err_initialize__auxinit();
372 	break;
373     case DLL_SHUTDOWN:
374 	com_err_terminate();
375 	break;
376     }
377 #elif defined PROFILELIB
378     switch (mode) {
379     case DLL_STARTUP:
380 	profile_library_initializer__auxinit();
381 	break;
382     case DLL_SHUTDOWN:
383 	profile_library_finalizer();
384 	break;
385     }
386 #elif defined SUPPORTLIB
387     switch (mode) {
388     case DLL_STARTUP:
389       krb5int_thread_support_init__auxinit();
390       break;
391     case DLL_SHUTDOWN:
392       krb5int_thread_support_fini();
393       break;
394     }
395 #else
396 # error "Don't know the init/fini functions for this library."
397 #endif
398 
399     return 0;
400 }
401 
402 #ifdef _WIN32
403 
DllMain(HANDLE hModule,DWORD fdwReason,LPVOID lpReserved)404 BOOL WINAPI DllMain (HANDLE hModule, DWORD fdwReason, LPVOID lpReserved)
405 {
406     switch (fdwReason)
407     {
408         case DLL_PROCESS_ATTACH:
409 	    hlibinstance = (HINSTANCE) hModule;
410 	    if (control(DLL_STARTUP))
411 		return FALSE;
412 	    break;
413 
414         case DLL_THREAD_ATTACH:
415 	    break;
416 
417         case DLL_THREAD_DETACH:
418 	    if (control(DLL_THREAD_DETACH))
419 		return FALSE;
420 	    break;
421 
422         case DLL_PROCESS_DETACH:
423 	    if (control(DLL_SHUTDOWN))
424 		return FALSE;
425 	    break;
426 
427         default:
428 	    return FALSE;
429     }
430 
431     return TRUE;   // successful DLL_PROCESS_ATTACH
432 }
433 
434 #else
435 
436 BOOL CALLBACK
LibMain(hInst,wDataSeg,cbHeap,CmdLine)437 LibMain (hInst, wDataSeg, cbHeap, CmdLine)
438 HINSTANCE hInst;
439 WORD wDataSeg;
440 WORD cbHeap;
441 LPSTR CmdLine;
442 {
443     hlibinstance = hInst;
444     if (control(DLL_STARTUP))
445 	return 0;
446     else
447 	return 1;
448 }
449 
450 int CALLBACK __export
WEP(nParam)451 WEP(nParam)
452 	int nParam;
453 {
454     if (control(DLL_SHUTDOWN))
455 	return 0;
456     else
457 	return 1;
458 }
459 
460 #endif
461