summaryrefslogtreecommitdiffstats
path: root/src/lib/win_glue.c
blob: 6dc9e101422e0cbbf7e3442df6d566bec17a1e65 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
/* 
 * WinSock support.
 *
 * Do the WinSock initialization call, keeping all the hair here.
 *
 * This routine is called by SOCKET_INITIALIZE in include/c-windows.h.
 * The code is pretty much copied from winsock.txt from winsock-1.1,
 * available from:
 * ftp://sunsite.unc.edu/pub/micro/pc-stuff/ms-windows/winsock/winsock-1.1
 *
 * Note: WSAStartup and WSACleanup is called here (and only here).
 * This assumes that under Windows, we only use this library via the
 * DLL.  Note that calls to WSAStartup and WSACleanup must be in
 * matched pairs.  If there is a missing WSACleanup call when a
 * program exits, under Lan Workplace, the name resolver will stop
 * working. 
 */

#ifdef KRB4
#include <kerberosIV/krb.h>
#endif
#define NEED_SOCKETS
#include "k5-int.h"

#ifndef NEED_WINSOCK
#if defined(KRB4) || defined(KRB5) || defined(GSSAPI)
#define NEED_WINSOCK 1
#endif
#endif

#ifdef KRB4
#include <kerberosIV/krb_err.h>
#endif
#ifdef KRB5
#include "krb5_err.h"
#include "kv5m_err.h"
#include "asn1_err.h"
#include "kdb5_err.h"
#include "profile.h"
#include "adm_err.h"
extern void krb5_stdcc_shutdown();
#endif
#ifdef GSSAPI
#include "gssapi/generic/gssapi_err_generic.h"
#include "gssapi/krb5/gssapi_err_krb5.h"
#endif


/*
 * #defines for MIT-specific time-based timebombs and/or version
 * server for the Kerberos DLL.
 */

#ifdef SAP_TIMEBOMB
#define TIMEBOMB 865141200	/* 1-Jun-97 */
#define TIMEBOMB_PRODUCT "SAPGUI"
#define TIMEBOMB_WARN  15
#define TIMEBOMB_INFO "  Please see the web page at:\nhttp://web.mit.edu/reeng/www/saphelp for more information"
#define TIMEBOMB_ERROR KRB5_APPL_EXPIRED
#endif

#ifdef KRB_TIMEBOMB
#define TIMEBOMB 865141200	/* 1-Jun-97 */
#define TIMEBOMB_PRODUCT "Kerberos V5"
#define TIMEBOMB_WARN 15
#define TIMEBOMB_INFO "  Please see the web page at:\nhttp://web.mit.edu/reeng/www/saphelp for more information"
#define TIMEBOMB_ERROR KRB5_LIB_EXPIRED
#endif

/*
 * #defines for using MIT's version server DLL
 */
#ifdef SAP_VERSERV
#define APP_TITLE "KRB5-SAP"
#define APP_VER "3.0f"
#define APP_INI "krb5sap.ini"
#define VERSERV_ERROR 	KRB5_APPL_EXPIRED
#endif

#ifdef VERSERV
#define WINDOWS
#include <ver.h>
#include <vs.h>
#include <v.h>


/*
 * This function will get the version resource information from the
 * application using the DLL.  This allows us to Version Serve
 * arbitrary third party applications.  If there is an error, or we
 * decide that we should not version check the calling application
 * then VSflag will be FALSE when the function returns.
 *
 * The buffers passed into this function must be at least
 * APPVERINFO_SIZE bytes long.
 */

#define APPVERINFO_SIZE 256

void GetCallingAppVerInfo( char *AppTitle, char *AppVer, char *AppIni,
			  BOOL *VSflag)
{
	char CallerFilename[_MAX_PATH];
	LONG FAR *lpLangInfo;
	DWORD hVersionInfoID, size;
	GLOBALHANDLE hVersionInfo;
	LPSTR lpVersionInfo;
	int dumint, retval;
	char *cp;
	char *revAppTitle;
	char szVerQ[90];
	LPBYTE locAppTitle;
	LPBYTE locAppVer;
	char locAppIni[_MAX_PATH];
#ifndef _WIN32
	WORD wStackSeg;
#endif /* !_WIN32 */

	/* first we need to get the calling module's filename */
#ifndef _WIN32
	_asm {
		mov wStackSeg, ss
	};
	retval = GetModuleFileName((HMODULE)wStackSeg, CallerFilename,
		_MAX_PATH);
#else
	/*
	 * Note: this may only work for single threaded applications,
	 * we'll live and learn ...
	 */
        retval = GetModuleFileName( NULL, CallerFilename, _MAX_PATH);
#endif

	if ( retval == 0 ) {
		VSflag = FALSE;
		return;
	}

	size = GetFileVersionInfoSize( CallerFilename, &hVersionInfoID);

	if( size == 0 ) {
		/*
		 * hey , I bet we don't have a version resource, let's
		 * punt
		 */
#if 0
		/* let's see what we have? (1813 means no resource) */
		size = GetLastError(); 		/*  WIN32 only */
#endif
		*VSflag = FALSE;
		return;
	}

	hVersionInfo = GlobalAlloc(GHND, size);
	lpVersionInfo = GlobalLock(hVersionInfo);

	retval = GetFileVersionInfo( CallerFilename, hVersionInfoID, size,
				    lpVersionInfo);

	retval = VerQueryValue(lpVersionInfo, "\\VarFileInfo\\Translation",
			       (LPSTR FAR *)&lpLangInfo, &dumint);
	wsprintf(szVerQ,
		 "\\StringFileInfo\\%04x%04x\\",
		 LOWORD(*lpLangInfo), HIWORD(*lpLangInfo));
	
	cp = szVerQ + lstrlen(szVerQ);

	lstrcpy(cp, "ProductName");


	/* try a localAppTitle and then a strcpy 4/2/97 */

	locAppTitle = 0;
	locAppVer = 0;

	retval = VerQueryValue(lpVersionInfo, szVerQ, &locAppTitle,
			       &dumint);

	lstrcpy(cp, "ProductVersion");


	retval = VerQueryValue(lpVersionInfo, szVerQ, &locAppVer,
			       &dumint);

	if (!locAppTitle || !locAppVer) {
	  	/* Punt, we don't have the right version resource records */
		*VSflag = FALSE;
		return;
	}

	/*
	 * We don't have a way to determine that INI file of the
	 * application at the moment so let's just use krb5.ini
	 */
	strncpy( locAppIni, KERBEROS_INI, sizeof(locAppIni) - 1 );
	locAppIni[ sizeof(locAppIni) - 1 ] = '\0';

	strncpy( AppTitle, locAppTitle, APPVERINFO_SIZE);
	AppTitle[APPVERINFO_SIZE - 1] = '\0';
	strncpy( AppVer, locAppVer, APPVERINFO_SIZE);
	AppVer[APPVERINFO_SIZE - 1] = '\0';
	strncpy( AppIni, locAppIni, APPVERINFO_SIZE);
	AppIni[APPVERINFO_SIZE - 1] = '\0';

	/*
	 * We also need to determine if we want to suppress version
	 * checking of this application.  Does the tail of the
	 * AppTitle end in a "-v" ?
	 */
	revAppTitle = _strrev( _strdup(AppTitle));
	if( revAppTitle[0] == 'v' || revAppTitle[0] == 'V'  &&
	   revAppTitle[1] == '-' ) {
		VSflag = FALSE;
	}
	return;
}


/*
 * Use the version server to give us some control on distribution and usage
 * We're going to test track as well
 */
static int CallVersionServer(app_title, app_version, app_ini, code_cover)
	char FAR *app_title;
	char FAR *app_version;
	char FAR *app_ini;
	char FAR *code_cover;
{
	VS_Request vrequest;
	VS_Status  vstatus;

	SetCursor(LoadCursor(NULL, IDC_WAIT));

	/*
	 * We should be able to pass in code_cover below, but things
	 * are breaking under Windows 16 for no good reason.
	 */
	vrequest = VSFormRequest((LPSTR) app_title, (LPSTR) app_version,
				 (LPSTR) app_ini,
				 NULL /* code_cover */, NULL,
				 V_CHECK_AND_LOG);

	SetCursor(LoadCursor(NULL, IDC_ARROW));
	/*
	 * If the user presses cancel when registering the test
	 * tracker, we'll let them continue.
	 */
	if (ReqStatus(vrequest) == V_E_CANCEL) {
		VSDestroyRequest(vrequest);
		return 0;
	}
	vstatus = VSProcessRequest(vrequest);
	/*
	 * Only complain periodically, if the test tracker isn't
	 * working... 
	 */
	if (v_complain(vstatus, app_ini)) {
		WinVSReportRequest(vrequest, NULL, 
				   "Version Server Status Report");
	}                                                         
	if (vstatus == V_REQUIRED) {
		SetCursor(LoadCursor(NULL, IDC_WAIT));
		VSDestroyRequest(vrequest);
		return( -1 );
	}
	VSDestroyRequest(vrequest);
	return (0);
}   
#endif

#ifdef TIMEBOMB
static krb5_error_code do_timebomb()
{
	char buf[1024];
	long timeleft;
	static first_time = 1;

	timeleft = TIMEBOMB - time(0);
	if (timeleft <= 0) {
		if (first_time) {
			sprintf(buf, "Your version of %s has expired.\n",
				TIMEBOMB_PRODUCT);
			buf[sizeof(buf) - 1] = '\0';
			strncat(buf, "Please upgrade it.", sizeof(buf) - 1 - strlen(buf));
#ifdef TIMEBOMB_INFO
			strncat(buf, TIMEBOMB_INFO, sizeof(buf) - 1 - strlen(buf));
#endif
			MessageBox(NULL, buf, "", MB_OK);
			first_time = 0;
		}
		return TIMEBOMB_ERROR;
	}
	timeleft = timeleft / ((long) 60*60*24);
	if (timeleft < TIMEBOMB_WARN) {
		if (first_time) {
			sprintf(buf, "Your version of %s will expire in %ld days.\n",
				TIMEBOMB_PRODUCT, timeleft);
			strncat(buf, "Please upgrade it soon.", sizeof(buf) - 1 - strlen(buf));
#ifdef TIMEBOMB_INFO
			strncat(buf, TIMEBOMB_INFO, sizeof(buf) - 1 - strlen(buf));
#endif
			MessageBox(NULL, buf, "", MB_OK);
			first_time = 0;
		}
	}
	return 0;
}
#endif

/*
 * This was originally called from LibMain; unfortunately, Windows 3.1
 * doesn't allow you to make messaging calls from LibMain.  So, we now
 * do the timebomb/version server stuff from krb5_init_context().
 */
krb5_error_code krb5_vercheck()
{
	static int verchecked = 0;
	if (verchecked)
		return 0;
#ifdef TIMEBOMB
	krb5_error_code retval = do_timebomb();
	if (retval)
		return retval;
#endif
#ifdef VERSERV
#if 0
	/* Check library ? */
	if (CallVersionServer(APP_TITLE, APP_VER, APP_INI, NULL))
		return KRB5_LIB_EXPIRED;
#endif
	{
#ifdef APP_TITLE
		if (CallVersionServer(APP_TITLE, APP_VER, APP_INI, NULL))
			return VERSERV_ERROR;
#else
		char AppTitle[APPVERINFO_SIZE];
		char AppVer[APPVERINFO_SIZE];
		char AppIni[APPVERINFO_SIZE];
		BOOL VSflag=TRUE;

		GetCallingAppVerInfo( AppTitle, AppVer, AppIni, &VSflag);

		if (VSflag) {
			if (CallVersionServer(AppTitle, AppVer, AppIni, NULL))
				return KRB5_APPL_EXPIRED;
		}
#endif
		
	}
#endif
        verchecked = 1;
	return 0;
}


static HINSTANCE hlibinstance;

HINSTANCE get_lib_instance()
{
    return hlibinstance;
}

#define DLL_STARTUP 0
#define DLL_SHUTDOWN 1

static int
control(int mode)
{
    void ((KRB5_CALLCONV *et_func)(struct error_table FAR *));
#ifdef NEED_WINSOCK
    WORD wVersionRequested;
    WSADATA wsaData;
    int err;
#endif

    switch(mode) {
    case DLL_STARTUP:
	et_func = add_error_table;

#ifdef NEED_WINSOCK
	wVersionRequested = 0x0101;		/* We need version 1.1 */
	if ((err = WSAStartup (wVersionRequested, &wsaData)))
	    return err;
	if (wVersionRequested != wsaData.wVersion) {
	    /* DLL couldn't support our version of the spec */
	    WSACleanup ();
	    return -104;			/* FIXME -- better error? */
	}
#endif
	break;

    case DLL_SHUTDOWN:
#ifdef KRB5
	krb5_stdcc_shutdown();
#endif
	et_func = remove_error_table;
#ifdef NEED_WINSOCK
	WSACleanup ();
#endif
	break;

    default:
	return -1;
    }

#ifdef KRB4
    (*et_func)(&et_krb_error_table);
#endif
#ifdef KRB5
    (*et_func)(&et_krb5_error_table);
    (*et_func)(&et_kv5m_error_table);
    (*et_func)(&et_kdb5_error_table);
    (*et_func)(&et_asn1_error_table);
    (*et_func)(&et_prof_error_table);
    (*et_func)(&et_kadm_error_table);
#endif
#ifdef GSSAPI
    (*et_func)(&et_k5g_error_table);
    (*et_func)(&et_ggss_error_table);
#endif

    return 0;
}

#ifdef _WIN32

BOOL WINAPI DllMain (HANDLE hModule, DWORD fdwReason, LPVOID lpReserved)
{
    switch (fdwReason)
    {
        case DLL_PROCESS_ATTACH:
	    hlibinstance = (HINSTANCE) hModule;
	    if (control(DLL_STARTUP))
		return FALSE;
	    break;

        case DLL_THREAD_ATTACH:
	    break;

        case DLL_THREAD_DETACH:
	    break;

        case DLL_PROCESS_DETACH:
	    if (control(DLL_SHUTDOWN))
		return FALSE;
	    break;

        default:
	    return FALSE;
    }
 
    return TRUE;   // successful DLL_PROCESS_ATTACH
}

#else

BOOL CALLBACK
LibMain (hInst, wDataSeg, cbHeap, CmdLine)
HINSTANCE hInst;
WORD wDataSeg;
WORD cbHeap;
LPSTR CmdLine;
{
    hlibinstance = hInst;
    if (control(DLL_STARTUP))
	return 0;
    else 
	return 1;
}

int CALLBACK __export
WEP(nParam)
	int nParam;
{
    if (control(DLL_SHUTDOWN))
	return 0;
    else
	return 1;
}

#endif