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 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 */ 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 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 */ 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 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 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 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 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 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