-: 0:Source:g_initialize.c -: 0:Graph:/var/tsitkova/Sources/v10/trunk/src/lib/gssapi/mechglue/g_initialize.so.gcno -: 0:Data:/var/tsitkova/Sources/v10/trunk/src/lib/gssapi/mechglue/g_initialize.so.gcda -: 0:Runs:1069 -: 0:Programs:1 -: 1:/* #pragma ident "@(#)g_initialize.c 1.36 05/02/02 SMI" */ -: 2: -: 3:/* -: 4: * Copyright 1996 by Sun Microsystems, Inc. -: 5: * -: 6: * Permission to use, copy, modify, distribute, and sell this software -: 7: * and its documentation for any purpose is hereby granted without fee, -: 8: * provided that the above copyright notice appears in all copies and -: 9: * that both that copyright notice and this permission notice appear in -: 10: * supporting documentation, and that the name of Sun Microsystems not be used -: 11: * in advertising or publicity pertaining to distribution of the software -: 12: * without specific, written prior permission. Sun Microsystems makes no -: 13: * representations about the suitability of this software for any -: 14: * purpose. It is provided "as is" without express or implied warranty. -: 15: * -: 16: * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, -: 17: * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO -: 18: * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR -: 19: * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF -: 20: * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR -: 21: * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -: 22: * PERFORMANCE OF THIS SOFTWARE. -: 23: */ -: 24: -: 25:/* -: 26: * This function will initialize the gssapi mechglue library -: 27: */ -: 28: -: 29:#include "mglueP.h" -: 30:#ifdef HAVE_STDLIB_H -: 31:#include -: 32:#endif -: 33:#ifdef HAVE_SYS_STAT_H -: 34:#include -: 35:#endif -: 36:#ifdef HAVE_SYS_PARAM_H -: 37:#include -: 38:#endif -: 39: -: 40:#include -: 41:#include -: 42:#include -: 43:#include -: 44: -: 45:#define M_DEFAULT "default" -: 46: -: 47:#include "k5-thread.h" -: 48:#include "k5-plugin.h" -: 49:#include "osconf.h" -: 50:#ifdef _GSS_STATIC_LINK -: 51:#include "gssapiP_krb5.h" -: 52:#include "gssapiP_spnego.h" -: 53:#endif -: 54: -: 55:#define MECH_SYM "gss_mech_initialize" -: 56: -: 57:#ifndef MECH_CONF -: 58:#define MECH_CONF "/etc/gss/mech" -: 59:#endif -: 60: -: 61:/* Local functions */ -: 62:static void addConfigEntry(const char *oidStr, const char *oid, const char *sharedLib, const char *kernMod, const char *modOptions); -: 63:static gss_mech_info searchMechList(gss_const_OID); -: 64:static void loadConfigFile(const char *); -: 65:#if defined(_WIN32) -: 66:#ifndef MECH_KEY -: 67:#define MECH_KEY "SOFTWARE\\gss\\mech" -: 68:#endif -: 69:static time_t getRegKeyModTime(HKEY hBaseKey, const char *keyPath); -: 70:static time_t getRegConfigModTime(const char *keyPath); -: 71:static void getRegKeyValue(HKEY key, const char *keyPath, const char *valueName, void **data, DWORD *dataLen); -: 72:static void loadConfigFromRegistry(HKEY keyBase, const char *keyPath); -: 73:#endif -: 74:static void updateMechList(void); -: 75:static void freeMechList(void); -: 76: -: 77:static OM_uint32 build_mechSet(void); -: 78:static void free_mechSet(void); -: 79: -: 80:/* -: 81: * list of mechanism libraries and their entry points. -: 82: * the list also maintains state of the mech libraries (loaded or not). -: 83: */ -: 84:static gss_mech_info g_mechList = NULL; -: 85:static gss_mech_info g_mechListTail = NULL; -: 86:static k5_mutex_t g_mechListLock = K5_MUTEX_PARTIAL_INITIALIZER; -: 87:static time_t g_confFileModTime = (time_t)0; -: 88: -: 89:static time_t g_mechSetTime = (time_t)0; -: 90:static gss_OID_set_desc g_mechSet = { 0, NULL }; -: 91:static k5_mutex_t g_mechSetLock = K5_MUTEX_PARTIAL_INITIALIZER; -: 92: 790: 93:MAKE_INIT_FUNCTION(gssint_mechglue_init); -: 94:MAKE_FINI_FUNCTION(gssint_mechglue_fini); -: 95: -: 96:int 790: 97:gssint_mechglue_init(void) -: 98:{ -: 99: int err; -: 100: -: 101:#ifdef SHOW_INITFINI_FUNCS -: 102: printf("gssint_mechglue_init\n"); -: 103:#endif -: 104: 790: 105: add_error_table(&et_ggss_error_table); -: 106: 790: 107: err = k5_mutex_finish_init(&g_mechSetLock); 790: 108: err = k5_mutex_finish_init(&g_mechListLock); -: 109: -: 110:#ifdef _GSS_STATIC_LINK 790: 111: err = gss_krb5int_lib_init(); 790: 112: err = gss_spnegoint_lib_init(); -: 113:#endif -: 114: 790: 115: err = gssint_mecherrmap_init(); 790: 116: return err; -: 117:} -: 118: -: 119:void #####: 120:gssint_mechglue_fini(void) -: 121:{ #####: 122: if (!INITIALIZER_RAN(gssint_mechglue_init) || PROGRAM_EXITING()) { -: 123:#ifdef SHOW_INITFINI_FUNCS -: 124: printf("gssint_mechglue_fini: skipping\n"); -: 125:#endif #####: 126: return; -: 127: } -: 128: -: 129:#ifdef SHOW_INITFINI_FUNCS -: 130: printf("gssint_mechglue_fini\n"); -: 131:#endif -: 132:#ifdef _GSS_STATIC_LINK #####: 133: gss_spnegoint_lib_fini(); #####: 134: gss_krb5int_lib_fini(); -: 135:#endif #####: 136: k5_mutex_destroy(&g_mechSetLock); #####: 137: k5_mutex_destroy(&g_mechListLock); #####: 138: free_mechSet(); #####: 139: freeMechList(); #####: 140: remove_error_table(&et_ggss_error_table); #####: 141: gssint_mecherrmap_destroy(); -: 142:} -: 143: -: 144:int 17027: 145:gssint_mechglue_initialize_library(void) -: 146:{ 17027: 147: return CALL_INIT_FUNCTION(gssint_mechglue_init); -: 148:} -: 149: -: 150:/* -: 151: * function used to reclaim the memory used by a gss_OID structure. -: 152: * This routine requires direct access to the mechList. -: 153: */ -: 154:OM_uint32 KRB5_CALLCONV 880: 155:gss_release_oid(minor_status, oid) -: 156:OM_uint32 *minor_status; -: 157:gss_OID *oid; -: 158:{ -: 159: OM_uint32 major; -: 160: gss_mech_info aMech; -: 161: 880: 162: if (minor_status == NULL) #####: 163: return (GSS_S_CALL_INACCESSIBLE_WRITE); -: 164: 880: 165: *minor_status = gssint_mechglue_initialize_library(); 880: 166: if (*minor_status != 0) #####: 167: return (GSS_S_FAILURE); -: 168: 880: 169: *minor_status = k5_mutex_lock(&g_mechListLock); 880: 170: if (*minor_status) #####: 171: return GSS_S_FAILURE; 880: 172: aMech = g_mechList; 5020: 173: while (aMech != NULL) { -: 174: -: 175: /* -: 176: * look through the loaded mechanism libraries for -: 177: * gss_internal_release_oid until one returns success. -: 178: * gss_internal_release_oid will only return success when -: 179: * the OID was recognized as an internal mechanism OID. if no -: 180: * mechanisms recognize the OID, then call the generic version. -: 181: */ 3488: 182: if (aMech->mech && aMech->mech->gss_internal_release_oid) { 2836: 183: major = aMech->mech->gss_internal_release_oid( -: 184: minor_status, oid); 2836: 185: if (major == GSS_S_COMPLETE) { 228: 186: k5_mutex_unlock(&g_mechListLock); 228: 187: return (GSS_S_COMPLETE); -: 188: } 2608: 189: map_error(minor_status, aMech->mech); -: 190: } 3260: 191: aMech = aMech->next; -: 192: } /* while */ 652: 193: k5_mutex_unlock(&g_mechListLock); -: 194: 652: 195: return (generic_gss_release_oid(minor_status, oid)); -: 196:} /* gss_release_oid */ -: 197: -: 198: -: 199:/* -: 200: * this function will return an oid set indicating available mechanisms. -: 201: * The set returned is based on configuration file entries and -: 202: * NOT on the loaded mechanisms. This function does not check if any -: 203: * of these can actually be loaded. -: 204: * This routine needs direct access to the mechanism list. -: 205: * To avoid reading the configuration file each call, we will save a -: 206: * a mech oid set, and only update it once the file has changed. -: 207: */ -: 208:OM_uint32 KRB5_CALLCONV 290: 209:gss_indicate_mechs(minorStatus, mechSet_out) -: 210:OM_uint32 *minorStatus; -: 211:gss_OID_set *mechSet_out; -: 212:{ -: 213: char *fileName; -: 214: struct stat fileInfo; -: 215: OM_uint32 status; -: 216: -: 217: /* Initialize outputs. */ -: 218: 290: 219: if (minorStatus != NULL) 290: 220: *minorStatus = 0; -: 221: 290: 222: if (mechSet_out != NULL) 290: 223: *mechSet_out = GSS_C_NO_OID_SET; -: 224: -: 225: /* Validate arguments. */ 290: 226: if (minorStatus == NULL || mechSet_out == NULL) #####: 227: return (GSS_S_CALL_INACCESSIBLE_WRITE); -: 228: 290: 229: *minorStatus = gssint_mechglue_initialize_library(); 290: 230: if (*minorStatus != 0) #####: 231: return (GSS_S_FAILURE); -: 232: 290: 233: fileName = MECH_CONF; -: 234: -: 235: /* -: 236: * If we have already computed the mechanisms supported and if it -: 237: * is still valid; make a copy and return to caller, -: 238: * otherwise build it first. -: 239: */ 290: 240: if ((stat(fileName, &fileInfo) == 0 && #####: 241: fileInfo.st_mtime > g_mechSetTime)) { -: 242: } /* if g_mechSet is out of date or not initialized */ 290: 243: if (build_mechSet()) #####: 244: return GSS_S_FAILURE; -: 245: -: 246: /* -: 247: * need to lock the g_mechSet in case someone tries to update it while -: 248: * I'm copying it. -: 249: */ 290: 250: *minorStatus = k5_mutex_lock(&g_mechSetLock); 290: 251: if (*minorStatus) { #####: 252: return GSS_S_FAILURE; -: 253: } -: 254: 290: 255: status = generic_gss_copy_oid_set(minorStatus, &g_mechSet, mechSet_out); 290: 256: (void) k5_mutex_unlock(&g_mechSetLock); 290: 257: return (status); -: 258:} /* gss_indicate_mechs */ -: 259: -: 260: -: 261:/* Call with g_mechSetLock held, or during final cleanup. */ -: 262:static void 290: 263:free_mechSet(void) -: 264:{ -: 265: unsigned int i; -: 266: 290: 267: if (g_mechSet.count != 0) { 1188: 268: for (i = 0; i < g_mechSet.count; i++) 990: 269: free(g_mechSet.elements[i].elements); 198: 270: free(g_mechSet.elements); 198: 271: g_mechSet.elements = NULL; 198: 272: g_mechSet.count = 0; -: 273: } 290: 274:} -: 275: -: 276:static OM_uint32 290: 277:build_mechSet(void) -: 278:{ -: 279: gss_mech_info mList; -: 280: size_t i; -: 281: size_t count; -: 282: gss_OID curItem; -: 283: -: 284: /* -: 285: * lock the mutex since we will be updating -: 286: * the mechList structure -: 287: * we need to keep the lock while we build the mechanism list -: 288: * since we are accessing parts of the mechList which could be -: 289: * modified. -: 290: */ 290: 291: if (k5_mutex_lock(&g_mechListLock) != 0) #####: 292: return GSS_S_FAILURE; -: 293: -: 294:#if 0 -: 295: /* -: 296: * this checks for the case when we need to re-construct the -: 297: * g_mechSet structure, but the mechanism list is upto date -: 298: * (because it has been read by someone calling -: 299: * gssint_get_mechanism) -: 300: */ -: 301: if (fileInfo.st_mtime > g_confFileModTime) -: 302: { -: 303: g_confFileModTime = fileInfo.st_mtime; -: 304: loadConfigFile(fileName); -: 305: } -: 306:#endif -: 307: 290: 308: updateMechList(); -: 309: -: 310: /* -: 311: * we need to lock the mech set so that no one else will -: 312: * try to read it as we are re-creating it -: 313: */ 290: 314: if (k5_mutex_lock(&g_mechSetLock) != 0) #####: 315: return GSS_S_FAILURE; -: 316: -: 317: /* if the oid list already exists we must free it first */ 290: 318: free_mechSet(); -: 319: -: 320: /* determine how many elements to have in the list */ 290: 321: mList = g_mechList; 290: 322: count = 0; 2030: 323: while (mList != NULL) { 1450: 324: count++; 1450: 325: mList = mList->next; -: 326: } -: 327: -: 328: /* this should always be true, but.... */ 290: 329: if (count > 0) { 290: 330: g_mechSet.elements = 290: 331: (gss_OID) calloc(count, sizeof (gss_OID_desc)); 290: 332: if (g_mechSet.elements == NULL) { #####: 333: (void) k5_mutex_unlock(&g_mechSetLock); #####: 334: (void) k5_mutex_unlock(&g_mechListLock); #####: 335: return (GSS_S_FAILURE); -: 336: } -: 337: 290: 338: (void) memset(g_mechSet.elements, 0, -: 339: count * sizeof (gss_OID_desc)); -: 340: -: 341: /* now copy each oid element */ 290: 342: g_mechSet.count = count; 290: 343: count = 0; 290: 344: mList = g_mechList; 2030: 345: while (mList != NULL) { 1450: 346: curItem = &(g_mechSet.elements[count]); 1450: 347: curItem->elements = (void*) 1450: 348: malloc(mList->mech_type->length); 1450: 349: if (curItem->elements == NULL) { -: 350: /* -: 351: * this is nasty - we must delete the -: 352: * part of the array already copied -: 353: */ #####: 354: for (i = 0; i < count; i++) { #####: 355: free(g_mechSet.elements[i]. -: 356: elements); -: 357: } #####: 358: free(g_mechSet.elements); #####: 359: g_mechSet.count = 0; #####: 360: g_mechSet.elements = NULL; #####: 361: (void) k5_mutex_unlock(&g_mechSetLock); #####: 362: (void) k5_mutex_unlock(&g_mechListLock); #####: 363: return (GSS_S_FAILURE); -: 364: } 1450: 365: g_OID_copy(curItem, mList->mech_type); 1450: 366: count++; 1450: 367: mList = mList->next; -: 368: } -: 369: } -: 370: -: 371:#if 0 -: 372: g_mechSetTime = fileInfo.st_mtime; -: 373:#endif 290: 374: (void) k5_mutex_unlock(&g_mechSetLock); 290: 375: (void) k5_mutex_unlock(&g_mechListLock); -: 376: 290: 377: return GSS_S_COMPLETE; -: 378:} -: 379: -: 380: -: 381:/* -: 382: * this function has been added for use by modules that need to -: 383: * know what (if any) optional parameters are supplied in the -: 384: * config file (MECH_CONF). -: 385: * It will return the option string for a specified mechanism. -: 386: * caller is responsible for freeing the memory -: 387: */ -: 388:char * 24: 389:gssint_get_modOptions(oid) -: 390:const gss_OID oid; -: 391:{ -: 392: gss_mech_info aMech; 24: 393: char *modOptions = NULL; -: 394: 24: 395: if (gssint_mechglue_initialize_library() != 0) #####: 396: return (NULL); -: 397: -: 398: /* make sure we have fresh data */ 24: 399: if (k5_mutex_lock(&g_mechListLock) != 0) #####: 400: return NULL; 24: 401: updateMechList(); -: 402: 48: 403: if ((aMech = searchMechList(oid)) == NULL || 24: 404: aMech->optionStr == NULL) { 24: 405: (void) k5_mutex_unlock(&g_mechListLock); 24: 406: return (NULL); -: 407: } -: 408: #####: 409: if (aMech->optionStr) #####: 410: modOptions = strdup(aMech->optionStr); #####: 411: (void) k5_mutex_unlock(&g_mechListLock); -: 412: #####: 413: return (modOptions); -: 414:} /* gssint_get_modOptions */ -: 415: -: 416:/* -: 417: * given a mechanism string return the mechanism oid -: 418: */ -: 419:OM_uint32 #####: 420:gssint_mech_to_oid(const char *mechStr, gss_OID* oid) -: 421:{ -: 422: gss_mech_info aMech; -: 423: #####: 424: if (oid == NULL) #####: 425: return (GSS_S_CALL_INACCESSIBLE_WRITE); -: 426: #####: 427: *oid = GSS_C_NULL_OID; -: 428: #####: 429: if (gssint_mechglue_initialize_library() != 0) #####: 430: return (GSS_S_FAILURE); -: 431: #####: 432: if ((mechStr == NULL) || (strlen(mechStr) == 0) || #####: 433: (strcasecmp(mechStr, M_DEFAULT) == 0)) #####: 434: return (GSS_S_COMPLETE); -: 435: -: 436: /* ensure we have fresh data */ #####: 437: if (k5_mutex_lock(&g_mechListLock) != 0) #####: 438: return GSS_S_FAILURE; #####: 439: updateMechList(); #####: 440: (void) k5_mutex_unlock(&g_mechListLock); -: 441: #####: 442: aMech = g_mechList; -: 443: -: 444: /* no lock required - only looking at fields that are not updated */ #####: 445: while (aMech != NULL) { #####: 446: if ((aMech->mechNameStr) && #####: 447: strcmp(aMech->mechNameStr, mechStr) == 0) { #####: 448: *oid = aMech->mech_type; #####: 449: return (GSS_S_COMPLETE); -: 450: } #####: 451: aMech = aMech->next; -: 452: } #####: 453: return (GSS_S_FAILURE); -: 454:} /* gssint_mech_to_oid */ -: 455: -: 456: -: 457:/* -: 458: * Given the mechanism oid, return the readable mechanism name -: 459: * associated with that oid from the mech config file -: 460: * (/etc/gss/mech). -: 461: */ -: 462:const char * #####: 463:gssint_oid_to_mech(const gss_OID oid) -: 464:{ -: 465: gss_mech_info aMech; -: 466: #####: 467: if (oid == GSS_C_NULL_OID) #####: 468: return (M_DEFAULT); -: 469: #####: 470: if (gssint_mechglue_initialize_library() != 0) #####: 471: return (NULL); -: 472: -: 473: /* ensure we have fresh data */ #####: 474: if (k5_mutex_lock(&g_mechListLock) != 0) #####: 475: return NULL; #####: 476: updateMechList(); #####: 477: aMech = searchMechList(oid); #####: 478: (void) k5_mutex_unlock(&g_mechListLock); -: 479: #####: 480: if (aMech == NULL) #####: 481: return (NULL); -: 482: #####: 483: return (aMech->mechNameStr); -: 484:} /* gssint_oid_to_mech */ -: 485: -: 486: -: 487:/* -: 488: * return a list of mechanism strings supported -: 489: * upon return the array is terminated with a NULL entry -: 490: */ -: 491:OM_uint32 #####: 492:gssint_get_mechanisms(char *mechArray[], int arrayLen) -: 493:{ -: 494: gss_mech_info aMech; -: 495: int i; -: 496: #####: 497: if (mechArray == NULL || arrayLen < 1) #####: 498: return (GSS_S_CALL_INACCESSIBLE_WRITE); -: 499: #####: 500: if (gssint_mechglue_initialize_library() != 0) #####: 501: return (GSS_S_FAILURE); -: 502: -: 503: /* ensure we have fresh data */ #####: 504: if (k5_mutex_lock(&g_mechListLock) != 0) #####: 505: return GSS_S_FAILURE; #####: 506: updateMechList(); #####: 507: (void) k5_mutex_unlock(&g_mechListLock); -: 508: #####: 509: aMech = g_mechList; -: 510: -: 511: /* no lock required - only looking at fields that are not updated */ #####: 512: for (i = 1; i < arrayLen; i++) { #####: 513: if (aMech != NULL) { #####: 514: *mechArray = aMech->mechNameStr; #####: 515: mechArray++; #####: 516: aMech = aMech->next; -: 517: } else #####: 518: break; -: 519: } #####: 520: *mechArray = NULL; #####: 521: return (GSS_S_COMPLETE); -: 522:} /* gss_get_mechanisms */ -: 523: -: 524:/* -: 525: * determines if the mechList needs to be updated from file -: 526: * and performs the update. -: 527: * this functions must be called with a lock of g_mechListLock -: 528: */ -: 529:static void 314: 530:updateMechList(void) -: 531:{ -: 532:#if defined(_WIN32) -: 533: time_t lastConfModTime = getRegConfigModTime(MECH_KEY); -: 534: if (g_confFileModTime < lastConfModTime) { -: 535: g_confFileModTime = lastConfModTime; -: 536: loadConfigFromRegistry(HKEY_CURRENT_USER, MECH_KEY); -: 537: loadConfigFromRegistry(HKEY_LOCAL_MACHINE, MECH_KEY); -: 538: } -: 539:#else /* _WIN32 */ -: 540: char *fileName; -: 541: struct stat fileInfo; -: 542: 314: 543: fileName = MECH_CONF; -: 544: -: 545: /* check if mechList needs updating */ 314: 546: if (stat(fileName, &fileInfo) == 0 && #####: 547: (fileInfo.st_mtime > g_confFileModTime)) { #####: 548: loadConfigFile(fileName); #####: 549: g_confFileModTime = fileInfo.st_mtime; -: 550: } -: 551:#if 0 -: 552: init_hardcoded(); -: 553:#endif -: 554:#endif /* !_WIN32 */ 314: 555:} /* updateMechList */ -: 556: -: 557:#ifdef _GSS_STATIC_LINK -: 558:static void #####: 559:releaseMechInfo(gss_mech_info *pCf) -: 560:{ -: 561: gss_mech_info cf; -: 562: OM_uint32 minor_status; -: 563: #####: 564: if (*pCf == NULL) { #####: 565: return; -: 566: } -: 567: #####: 568: cf = *pCf; -: 569: #####: 570: if (cf->kmodName != NULL) #####: 571: free(cf->kmodName); #####: 572: if (cf->uLibName != NULL) #####: 573: free(cf->uLibName); #####: 574: if (cf->mechNameStr != NULL) #####: 575: free(cf->mechNameStr); #####: 576: if (cf->optionStr != NULL) #####: 577: free(cf->optionStr); #####: 578: if (cf->mech_type != GSS_C_NO_OID && #####: 579: cf->mech_type != &cf->mech->mech_type) #####: 580: generic_gss_release_oid(&minor_status, &cf->mech_type); #####: 581: if (cf->mech != NULL) { #####: 582: memset(cf->mech, 0, sizeof(*cf->mech)); #####: 583: free(cf->mech); -: 584: } #####: 585: if (cf->mech_ext != NULL) { #####: 586: memset(cf->mech_ext, 0, sizeof(*cf->mech_ext)); #####: 587: free(cf->mech_ext); -: 588: } #####: 589: if (cf->dl_handle != NULL) #####: 590: krb5int_close_plugin(cf->dl_handle); -: 591: #####: 592: memset(cf, 0, sizeof(*cf)); #####: 593: free(cf); -: 594: #####: 595: *pCf = NULL; -: 596:} -: 597: -: 598:/* -: 599: * Register a mechanism. Called with g_mechListLock held. -: 600: */ -: 601:int 3950: 602:gssint_register_mechinfo(gss_mech_info template) -: 603:{ -: 604: gss_mech_info cf, new_cf; -: 605: 3950: 606: new_cf = calloc(1, sizeof(*new_cf)); 3950: 607: if (new_cf == NULL) { #####: 608: return ENOMEM; -: 609: } -: 610: 3950: 611: new_cf->dl_handle = template->dl_handle; -: 612: /* copy mech so we can rewrite canonical mechanism OID */ 3950: 613: new_cf->mech = (gss_mechanism)calloc(1, sizeof(struct gss_config)); 3950: 614: if (new_cf->mech == NULL) { #####: 615: releaseMechInfo(&new_cf); #####: 616: return ENOMEM; -: 617: } 3950: 618: *new_cf->mech = *template->mech; 3950: 619: if (template->mech_type != NULL) 3160: 620: new_cf->mech->mech_type = *(template->mech_type); 3950: 621: new_cf->mech_type = &new_cf->mech->mech_type; 3950: 622: new_cf->priority = template->priority; 3950: 623: new_cf->freeMech = 1; 3950: 624: new_cf->next = NULL; -: 625: 3950: 626: if (template->mech_ext != NULL) { 3950: 627: new_cf->mech_ext = (gss_mechanism_ext)calloc(1, -: 628: sizeof(struct gss_config_ext)); 3950: 629: if (new_cf->mech_ext == NULL) { #####: 630: releaseMechInfo(&new_cf); #####: 631: return ENOMEM; -: 632: } 3950: 633: *new_cf->mech_ext = *template->mech_ext; -: 634: } -: 635: 3950: 636: if (template->kmodName != NULL) { #####: 637: new_cf->kmodName = strdup(template->kmodName); #####: 638: if (new_cf->kmodName == NULL) { #####: 639: releaseMechInfo(&new_cf); #####: 640: return ENOMEM; -: 641: } -: 642: } 3950: 643: if (template->uLibName != NULL) { #####: 644: new_cf->uLibName = strdup(template->uLibName); #####: 645: if (new_cf->uLibName == NULL) { #####: 646: releaseMechInfo(&new_cf); #####: 647: return ENOMEM; -: 648: } -: 649: } 3950: 650: if (template->mechNameStr != NULL) { 3950: 651: new_cf->mechNameStr = strdup(template->mechNameStr); 3950: 652: if (new_cf->mechNameStr == NULL) { #####: 653: releaseMechInfo(&new_cf); #####: 654: return ENOMEM; -: 655: } -: 656: } 3950: 657: if (template->optionStr != NULL) { #####: 658: new_cf->optionStr = strdup(template->optionStr); #####: 659: if (new_cf->optionStr == NULL) { #####: 660: releaseMechInfo(&new_cf); #####: 661: return ENOMEM; -: 662: } -: 663: } 3950: 664: if (g_mechList == NULL) { 790: 665: g_mechList = new_cf; 790: 666: g_mechListTail = new_cf; 790: 667: return 0; 3160: 668: } else if (new_cf->priority < g_mechList->priority) { #####: 669: new_cf->next = g_mechList; #####: 670: g_mechList = new_cf; #####: 671: return 0; -: 672: } -: 673: 7900: 674: for (cf = g_mechList; cf != NULL; cf = cf->next) { 12640: 675: if (cf->next == NULL || 4740: 676: new_cf->priority < cf->next->priority) { 3160: 677: new_cf->next = cf->next; 3160: 678: cf->next = new_cf; 3160: 679: if (g_mechListTail == cf) { 3160: 680: g_mechListTail = new_cf; -: 681: } 3160: 682: break; -: 683: } -: 684: } -: 685: 3160: 686: return 0; -: 687:} -: 688:#endif /* _GSS_STATIC_LINK */ -: 689: -: 690:#define GSS_ADD_DYNAMIC_METHOD(_dl, _mech, _symbol) \ -: 691: do { \ -: 692: struct errinfo errinfo; \ -: 693: \ -: 694: memset(&errinfo, 0, sizeof(errinfo)); \ -: 695: if (krb5int_get_plugin_func(_dl, \ -: 696: #_symbol, \ -: 697: (void (**)())&(_mech)->_symbol, \ -: 698: &errinfo) || errinfo.code) \ -: 699: (_mech)->_symbol = NULL; \ -: 700: } while (0) -: 701: -: 702:/* -: 703: * If _symbol is undefined in the shared object but the shared object -: 704: * is linked against the mechanism glue, it's possible for dlsym() to -: 705: * return the mechanism glue implementation. Guard against that. -: 706: */ -: 707:#define GSS_ADD_DYNAMIC_METHOD_NOLOOP(_dl, _mech, _symbol) \ -: 708: do { \ -: 709: GSS_ADD_DYNAMIC_METHOD(_dl, _mech, _symbol); \ -: 710: if ((_mech)->_symbol == _symbol) \ -: 711: (_mech)->_symbol = NULL; \ -: 712: } while (0) -: 713: -: 714:static gss_mechanism #####: 715:build_dynamicMech(void *dl, const gss_OID mech_type) -: 716:{ -: 717: gss_mechanism mech; -: 718: #####: 719: mech = (gss_mechanism)calloc(1, sizeof(*mech)); #####: 720: if (mech == NULL) { #####: 721: return NULL; -: 722: } -: 723: #####: 724: GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_acquire_cred); #####: 725: GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_release_cred); #####: 726: GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_init_sec_context); #####: 727: GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_accept_sec_context); #####: 728: GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_process_context_token); #####: 729: GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_delete_sec_context); #####: 730: GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_context_time); #####: 731: GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_get_mic); #####: 732: GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_verify_mic); #####: 733: GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_wrap); #####: 734: GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_unwrap); #####: 735: GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_display_status); #####: 736: GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_indicate_mechs); #####: 737: GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_compare_name); #####: 738: GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_display_name); #####: 739: GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_import_name); #####: 740: GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_release_name); #####: 741: GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_inquire_cred); #####: 742: GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_add_cred); #####: 743: GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_export_sec_context); #####: 744: GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_import_sec_context); #####: 745: GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_inquire_cred_by_mech); #####: 746: GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_inquire_names_for_mech); #####: 747: GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_inquire_context); #####: 748: GSS_ADD_DYNAMIC_METHOD(dl, mech, gss_internal_release_oid); #####: 749: GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_wrap_size_limit); #####: 750: GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_localname); #####: 751: GSS_ADD_DYNAMIC_METHOD(dl, mech, gssspi_authorize_localname); #####: 752: GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_export_name); #####: 753: GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_duplicate_name); #####: 754: GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_store_cred); #####: 755: GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_inquire_sec_context_by_oid); #####: 756: GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_inquire_cred_by_oid); #####: 757: GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_set_sec_context_option); #####: 758: GSS_ADD_DYNAMIC_METHOD(dl, mech, gssspi_set_cred_option); #####: 759: GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gssspi_mech_invoke); #####: 760: GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_wrap_aead); #####: 761: GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_unwrap_aead); #####: 762: GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_wrap_iov); #####: 763: GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_unwrap_iov); #####: 764: GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_wrap_iov_length); #####: 765: GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_complete_auth_token); -: 766: /* Services4User (introduced in 1.8) */ #####: 767: GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_acquire_cred_impersonate_name); #####: 768: GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_add_cred_impersonate_name); -: 769: /* Naming extensions (introduced in 1.8) */ #####: 770: GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_display_name_ext); #####: 771: GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_inquire_name); #####: 772: GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_get_name_attribute); #####: 773: GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_set_name_attribute); #####: 774: GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_delete_name_attribute); #####: 775: GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_export_name_composite); #####: 776: GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_map_name_to_any); #####: 777: GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_release_any_name_mapping); -: 778: /* RFC 4401 (introduced in 1.8) */ #####: 779: GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_pseudo_random); -: 780: /* RFC 4178 (introduced in 1.8; gss_get_neg_mechs not implemented) */ #####: 781: GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_set_neg_mechs); -: 782: /* draft-ietf-sasl-gs2 */ #####: 783: GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_inquire_saslname_for_mech); #####: 784: GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_inquire_mech_for_saslname); -: 785: /* RFC 5587 */ #####: 786: GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_inquire_attrs_for_mech); -: 787: #####: 788: assert(mech_type != GSS_C_NO_OID); -: 789: #####: 790: mech->mech_type = *(mech_type); -: 791: #####: 792: return mech; -: 793:} -: 794: -: 795:static gss_mechanism_ext #####: 796:build_dynamicMechExt(void *dl, const gss_OID mech_type) -: 797:{ -: 798: gss_mechanism_ext mech_ext; -: 799: #####: 800: mech_ext = (gss_mechanism_ext)calloc(1, sizeof(*mech_ext)); #####: 801: if (mech_ext == NULL) { #####: 802: return NULL; -: 803: } -: 804: #####: 805: GSS_ADD_DYNAMIC_METHOD(dl, mech_ext, gssspi_acquire_cred_with_password); -: 806: #####: 807: return mech_ext; -: 808:} -: 809: -: 810:static void #####: 811:freeMechList(void) -: 812:{ -: 813: gss_mech_info cf, next_cf; -: 814: OM_uint32 minor; -: 815: #####: 816: for (cf = g_mechList; cf != NULL; cf = next_cf) { #####: 817: next_cf = cf->next; #####: 818: if (cf->kmodName != NULL) #####: 819: free(cf->kmodName); #####: 820: if (cf->uLibName != NULL) #####: 821: free(cf->uLibName); #####: 822: if (cf->mechNameStr != NULL) #####: 823: free(cf->mechNameStr); #####: 824: if (cf->optionStr != NULL) #####: 825: free(cf->optionStr); #####: 826: if (cf->mech_type != &cf->mech->mech_type) #####: 827: generic_gss_release_oid(&minor, &cf->mech_type); #####: 828: if (cf->mech != NULL && cf->freeMech) #####: 829: free(cf->mech); #####: 830: if (cf->mech_ext != NULL && cf->freeMech) #####: 831: free(cf->mech_ext); #####: 832: if (cf->dl_handle != NULL) #####: 833: (void) krb5int_close_plugin(cf->dl_handle); #####: 834: free(cf); -: 835: } #####: 836:} -: 837: -: 838:/* -: 839: * Register a mechanism. Called with g_mechListLock held. -: 840: */ -: 841: -: 842:/* -: 843: * given the mechanism type, return the mechanism structure -: 844: * containing the mechanism library entry points. -: 845: * will return NULL if mech type is not found -: 846: * This function will also trigger the loading of the mechanism -: 847: * module if it has not been already loaded. -: 848: */ -: 849:gss_mechanism 7702: 850:gssint_get_mechanism(gss_const_OID oid) -: 851:{ -: 852: gss_mech_info aMech; -: 853: gss_mechanism (*sym)(const gss_OID); -: 854: struct plugin_file_handle *dl; -: 855: struct errinfo errinfo; -: 856: 7702: 857: if (gssint_mechglue_initialize_library() != 0) #####: 858: return (NULL); -: 859: 7702: 860: if (k5_mutex_lock(&g_mechListLock) != 0) #####: 861: return NULL; -: 862: /* check if the mechanism is already loaded */ 7702: 863: if ((aMech = searchMechList(oid)) != NULL && aMech->mech) { 7702: 864: (void) k5_mutex_unlock(&g_mechListLock); 7702: 865: return (aMech->mech); -: 866: } -: 867: -: 868: /* -: 869: * might need to re-read the configuration file before loading -: 870: * the mechanism to ensure we have the latest info. -: 871: */ #####: 872: updateMechList(); -: 873: #####: 874: aMech = searchMechList(oid); -: 875: -: 876: /* is the mechanism present in the list ? */ #####: 877: if (aMech == NULL) { #####: 878: (void) k5_mutex_unlock(&g_mechListLock); #####: 879: return ((gss_mechanism)NULL); -: 880: } -: 881: -: 882: /* has another thread loaded the mech */ #####: 883: if (aMech->mech) { #####: 884: (void) k5_mutex_unlock(&g_mechListLock); #####: 885: return (aMech->mech); -: 886: } -: 887: #####: 888: memset(&errinfo, 0, sizeof(errinfo)); -: 889: #####: 890: if (krb5int_open_plugin(aMech->uLibName, &dl, &errinfo) != 0 || #####: 891: errinfo.code != 0) { -: 892:#if 0 -: 893: (void) syslog(LOG_INFO, "libgss dlopen(%s): %s\n", -: 894: aMech->uLibName, dlerror()); -: 895:#endif #####: 896: (void) k5_mutex_unlock(&g_mechListLock); #####: 897: return ((gss_mechanism)NULL); -: 898: } -: 899: #####: 900: if (krb5int_get_plugin_func(dl, MECH_SYM, (void (**)())&sym, -: 901: &errinfo) == 0) { -: 902: /* Call the symbol to get the mechanism table */ #####: 903: aMech->mech = (*sym)(aMech->mech_type); -: 904: } else { -: 905: /* Try dynamic dispatch table */ #####: 906: aMech->mech = build_dynamicMech(dl, aMech->mech_type); #####: 907: aMech->freeMech = 1; -: 908: } #####: 909: if (aMech->mech == NULL) { #####: 910: (void) krb5int_close_plugin(dl); -: 911:#if 0 -: 912: (void) syslog(LOG_INFO, "unable to initialize mechanism" -: 913: " library [%s]\n", aMech->uLibName); -: 914:#endif #####: 915: (void) k5_mutex_unlock(&g_mechListLock); #####: 916: return ((gss_mechanism)NULL); -: 917: } -: 918: #####: 919: aMech->dl_handle = dl; -: 920: #####: 921: (void) k5_mutex_unlock(&g_mechListLock); #####: 922: return (aMech->mech); -: 923:} /* gssint_get_mechanism */ -: 924: -: 925:gss_mechanism_ext 48: 926:gssint_get_mechanism_ext(oid) -: 927:const gss_OID oid; -: 928:{ -: 929: gss_mech_info aMech; -: 930: 48: 931: if (gssint_mechglue_initialize_library() != 0) #####: 932: return (NULL); -: 933: 48: 934: if (k5_mutex_lock(&g_mechListLock) != 0) #####: 935: return NULL; -: 936: /* check if the mechanism is already loaded */ 48: 937: if ((aMech = searchMechList(oid)) != NULL && aMech->mech_ext) { 48: 938: (void) k5_mutex_unlock(&g_mechListLock); 48: 939: return (aMech->mech_ext); -: 940: } -: 941: -: 942: /* -: 943: * might need to re-read the configuration file before loading -: 944: * the mechanism to ensure we have the latest info. -: 945: */ #####: 946: updateMechList(); -: 947: #####: 948: aMech = searchMechList(oid); -: 949: -: 950: /* is the mechanism present in the list ? */ #####: 951: if (aMech == NULL || aMech->dl_handle == NULL) { #####: 952: (void) k5_mutex_unlock(&g_mechListLock); #####: 953: return ((gss_mechanism_ext)NULL); -: 954: } -: 955: -: 956: /* has another thread loaded the mech */ #####: 957: if (aMech->mech_ext) { #####: 958: (void) k5_mutex_unlock(&g_mechListLock); #####: 959: return (aMech->mech_ext); -: 960: } -: 961: -: 962: /* Try dynamic dispatch table */ #####: 963: aMech->mech_ext = build_dynamicMechExt(aMech->dl_handle, -: 964: aMech->mech_type); #####: 965: if (aMech->mech_ext == NULL) { #####: 966: (void) k5_mutex_unlock(&g_mechListLock); #####: 967: return ((gss_mechanism_ext)NULL); -: 968: } -: 969: #####: 970: (void) k5_mutex_unlock(&g_mechListLock); #####: 971: return (aMech->mech_ext); -: 972:} /* gssint_get_mechanism_ext */ -: 973: -: 974:/* -: 975: * this routine is used for searching the list of mechanism data. -: 976: * -: 977: * this needs to be called with g_mechListLock held. -: 978: */ 7774: 979:static gss_mech_info searchMechList(gss_const_OID oid) -: 980:{ 7774: 981: gss_mech_info aMech = g_mechList; -: 982: -: 983: /* if oid is null -> then get default which is the first in the list */ 7774: 984: if (oid == GSS_C_NULL_OID) 38: 985: return (aMech); -: 986: 26134: 987: while (aMech != NULL) { 18398: 988: if (g_OID_equal(aMech->mech_type, oid)) 7736: 989: return (aMech); 10662: 990: aMech = aMech->next; -: 991: } -: 992: -: 993: /* none found */ #####: 994: return ((gss_mech_info) NULL); -: 995:} /* searchMechList */ -: 996: -: 997:/* -: 998: * loads the configuration file -: 999: * this is called while having a mutex lock on the mechanism list -: 1000: * entries for libraries that have been loaded can't be modified -: 1001: * mechNameStr and mech_type fields are not updated during updates -: 1002: */ #####: 1003:static void loadConfigFile(fileName) -: 1004:const char *fileName; -: 1005:{ -: 1006: char *sharedLib, *kernMod, *modOptions, *oid, *endp; -: 1007: char buffer[BUFSIZ], *oidStr; -: 1008: FILE *confFile; -: 1009: #####: 1010: if ((confFile = fopen(fileName, "r")) == NULL) { #####: 1011: return; -: 1012: } -: 1013: #####: 1014: (void) memset(buffer, 0, sizeof (buffer)); #####: 1015: while (fgets(buffer, BUFSIZ, confFile) != NULL) { -: 1016: -: 1017: /* ignore lines beginning with # */ #####: 1018: if (*buffer == '#') #####: 1019: continue; -: 1020: -: 1021: /* -: 1022: * find the first white-space character after -: 1023: * the mechanism name -: 1024: */ #####: 1025: oidStr = buffer; #####: 1026: for (endp = buffer; *endp && !isspace(*endp); endp++); -: 1027: -: 1028: /* Now find the first non-white-space character */ #####: 1029: if (*endp) { #####: 1030: *endp = '\0'; #####: 1031: endp++; #####: 1032: while (*endp && isspace(*endp)) #####: 1033: endp++; -: 1034: } -: 1035: -: 1036: /* -: 1037: * If that's all, then this is a corrupt entry. Skip it. -: 1038: */ #####: 1039: if (! *endp) #####: 1040: continue; -: 1041: -: 1042: /* Find the end of the oid and make sure it is NULL-ended */ #####: 1043: for (oid = endp; *endp && !isspace(*endp); endp++) -: 1044: ; -: 1045: #####: 1046: if (*endp) { #####: 1047: *endp = '\0'; #####: 1048: endp++; -: 1049: } -: 1050: -: 1051: /* Find the start of the shared lib name */ #####: 1052: for (sharedLib = endp; *sharedLib && isspace(*sharedLib); #####: 1053: sharedLib++) -: 1054: ; -: 1055: -: 1056: /* -: 1057: * Find the end of the shared lib name and make sure it is -: 1058: * NULL-terminated. -: 1059: */ #####: 1060: for (endp = sharedLib; *endp && !isspace(*endp); endp++) -: 1061: ; -: 1062: #####: 1063: if (*endp) { #####: 1064: *endp = '\0'; #####: 1065: endp++; -: 1066: } -: 1067: -: 1068: /* Find the start of the optional kernel module lib name */ #####: 1069: for (kernMod = endp; *kernMod && isspace(*kernMod); #####: 1070: kernMod++) -: 1071: ; -: 1072: -: 1073: /* -: 1074: * If this item starts with a bracket "[", then -: 1075: * it is not a kernel module, but is a list of -: 1076: * options for the user module to parse later. -: 1077: */ #####: 1078: if (*kernMod && *kernMod != '[') { -: 1079: /* -: 1080: * Find the end of the shared lib name and make sure -: 1081: * it is NULL-terminated. -: 1082: */ #####: 1083: for (endp = kernMod; *endp && !isspace(*endp); endp++) -: 1084: ; -: 1085: #####: 1086: if (*endp) { #####: 1087: *endp = '\0'; #####: 1088: endp++; -: 1089: } -: 1090: } else #####: 1091: kernMod = NULL; -: 1092: -: 1093: /* Find the start of the optional module options list */ #####: 1094: for (modOptions = endp; *modOptions && isspace(*modOptions); #####: 1095: modOptions++); -: 1096: #####: 1097: if (*modOptions == '[') { -: 1098: /* move past the opening bracket */ #####: 1099: for (modOptions = modOptions+1; #####: 1100: *modOptions && isspace(*modOptions); #####: 1101: modOptions++); -: 1102: -: 1103: /* Find the closing bracket */ #####: 1104: for (endp = modOptions; #####: 1105: *endp && *endp != ']'; endp++); -: 1106: #####: 1107: *endp = '\0'; -: 1108: } else { #####: 1109: modOptions = NULL; -: 1110: } -: 1111: #####: 1112: addConfigEntry(oidStr, oid, sharedLib, kernMod, modOptions); -: 1113: } /* while */ #####: 1114: (void) fclose(confFile); -: 1115:} /* loadConfigFile */ -: 1116: -: 1117:#if defined(_WIN32) -: 1118: -: 1119:static time_t -: 1120:filetimeToTimet(const FILETIME *ft) -: 1121:{ -: 1122: ULARGE_INTEGER ull; -: 1123: -: 1124: ull.LowPart = ft->dwLowDateTime; -: 1125: ull.HighPart = ft->dwHighDateTime; -: 1126: return (time_t)(ull.QuadPart / 10000000ULL - 11644473600ULL); -: 1127:} -: 1128: -: 1129:static time_t -: 1130:getRegConfigModTime(const char *keyPath) -: 1131:{ -: 1132: time_t currentUserModTime = getRegKeyModTime(HKEY_CURRENT_USER, -: 1133: keyPath); -: 1134: time_t localMachineModTime = getRegKeyModTime(HKEY_LOCAL_MACHINE, -: 1135: keyPath); -: 1136: -: 1137: return currentUserModTime > localMachineModTime ? currentUserModTime : -: 1138: localMachineModTime; -: 1139:} -: 1140: -: 1141:static time_t -: 1142:getRegKeyModTime(HKEY hBaseKey, const char *keyPath) -: 1143:{ -: 1144: HKEY hConfigKey; -: 1145: HRESULT rc; -: 1146: int iSubKey = 0; -: 1147: time_t modTime = 0, keyModTime; -: 1148: FILETIME keyLastWriteTime; -: 1149: char subKeyName[256]; -: 1150: -: 1151: if ((rc = RegOpenKeyEx(hBaseKey, keyPath, 0, KEY_ENUMERATE_SUB_KEYS, -: 1152: &hConfigKey)) != ERROR_SUCCESS) { -: 1153: /* TODO: log error message */ -: 1154: return 0; -: 1155: } -: 1156: do { -: 1157: int subKeyNameSize=sizeof(subKeyName)/sizeof(subKeyName[0]); -: 1158: if ((rc = RegEnumKeyEx(hConfigKey, iSubKey++, subKeyName, -: 1159: &subKeyNameSize, NULL, NULL, NULL, -: 1160: &keyLastWriteTime)) != ERROR_SUCCESS) { -: 1161: break; -: 1162: } -: 1163: keyModTime = filetimeToTimet(&keyLastWriteTime); -: 1164: if (modTime < keyModTime) { -: 1165: modTime = keyModTime; -: 1166: } -: 1167: } while (1); -: 1168: RegCloseKey(hConfigKey); -: 1169: return modTime; -: 1170:} -: 1171: -: 1172:static void -: 1173:getRegKeyValue(HKEY hKey, const char *keyPath, const char *valueName, -: 1174: void **data, DWORD* dataLen) -: 1175:{ -: 1176: DWORD sizeRequired=*dataLen; -: 1177: HRESULT hr; -: 1178: /* Get data length required */ -: 1179: if ((hr = RegGetValue(hKey, keyPath, valueName, RRF_RT_REG_SZ, NULL, -: 1180: NULL, &sizeRequired)) != ERROR_SUCCESS) { -: 1181: /* TODO: LOG registry error */ -: 1182: return; -: 1183: } -: 1184: /* adjust data buffer size if necessary */ -: 1185: if (*dataLen < sizeRequired) { -: 1186: *dataLen = sizeRequired; -: 1187: *data = realloc(*data, sizeRequired); -: 1188: if (!*data) { -: 1189: *dataLen = 0; -: 1190: /* TODO: LOG OOM ERROR! */ -: 1191: return; -: 1192: } -: 1193: } -: 1194: /* get data */ -: 1195: if ((hr = RegGetValue(hKey, keyPath, valueName, RRF_RT_REG_SZ, NULL, -: 1196: *data, &sizeRequired)) != ERROR_SUCCESS) { -: 1197: /* LOG registry error */ -: 1198: return; -: 1199: } -: 1200:} -: 1201: -: 1202:static void -: 1203:loadConfigFromRegistry(HKEY hBaseKey, const char *keyPath) -: 1204:{ -: 1205: HKEY hConfigKey; -: 1206: DWORD iSubKey, nSubKeys, maxSubKeyNameLen; -: 1207: char *oidStr = NULL, *oid = NULL, *sharedLib = NULL, *kernMod = NULL; -: 1208: char *modOptions = NULL; -: 1209: DWORD oidStrLen = 0, oidLen = 0, sharedLibLen = 0, kernModLen = 0; -: 1210: DWORD modOptionsLen = 0; -: 1211: HRESULT rc; -: 1212: -: 1213: if ((rc = RegOpenKeyEx(hBaseKey, keyPath, 0, -: 1214: KEY_ENUMERATE_SUB_KEYS|KEY_QUERY_VALUE, -: 1215: &hConfigKey)) != ERROR_SUCCESS) { -: 1216: /* TODO: log registry error */ -: 1217: return; -: 1218: } -: 1219: -: 1220: if ((rc = RegQueryInfoKey(hConfigKey, -: 1221: NULL, /* lpClass */ -: 1222: NULL, /* lpcClass */ -: 1223: NULL, /* lpReserved */ -: 1224: &nSubKeys, -: 1225: &maxSubKeyNameLen, -: 1226: NULL, /* lpcMaxClassLen */ -: 1227: NULL, /* lpcValues */ -: 1228: NULL, /* lpcMaxValueNameLen */ -: 1229: NULL, /* lpcMaxValueLen */ -: 1230: NULL, /* lpcbSecurityDescriptor */ -: 1231: NULL /* lpftLastWriteTime */ )) != ERROR_SUCCESS) { -: 1232: goto cleanup; -: 1233: } -: 1234: oidStr = malloc(++maxSubKeyNameLen); -: 1235: if (!oidStr) { -: 1236: goto cleanup; -: 1237: } -: 1238: for (iSubKey=0; iSubKeymech) { #####: 1311: generic_gss_release_oid(&minor, &mechOid); #####: 1312: return; -: 1313: } -: 1314: -: 1315: /* -: 1316: * If that's all, then this is a corrupt entry. Skip it. -: 1317: */ #####: 1318: if (! *sharedLib) { #####: 1319: generic_gss_release_oid(&minor, &mechOid); #####: 1320: return; -: 1321: } -: 1322:#if defined(_WIN32) -: 1323: sharedPath = sharedLib; -: 1324:#else #####: 1325: if (sharedLib[0] == '/') #####: 1326: snprintf(sharedPath, sizeof(sharedPath), "%s", sharedLib); -: 1327: else #####: 1328: snprintf(sharedPath, sizeof(sharedPath), "%s%s", -: 1329: MECH_LIB_PREFIX, sharedLib); -: 1330:#endif -: 1331: /* -: 1332: * are we creating a new mechanism entry or -: 1333: * just modifying existing (non loaded) mechanism entry -: 1334: */ #####: 1335: if (aMech) { -: 1336: /* -: 1337: * delete any old values and set new -: 1338: * mechNameStr and mech_type are not modified -: 1339: */ #####: 1340: if (aMech->kmodName) { #####: 1341: free(aMech->kmodName); #####: 1342: aMech->kmodName = NULL; -: 1343: } -: 1344: #####: 1345: if (aMech->optionStr) { #####: 1346: free(aMech->optionStr); #####: 1347: aMech->optionStr = NULL; -: 1348: } -: 1349: #####: 1350: if ((tmpStr = strdup(sharedPath)) != NULL) { #####: 1351: if (aMech->uLibName) #####: 1352: free(aMech->uLibName); #####: 1353: aMech->uLibName = tmpStr; -: 1354: } -: 1355: #####: 1356: if (kernMod) /* this is an optional parameter */ #####: 1357: aMech->kmodName = strdup(kernMod); -: 1358: #####: 1359: if (modOptions) /* optional module options */ #####: 1360: aMech->optionStr = strdup(modOptions); -: 1361: -: 1362: /* the oid is already set */ #####: 1363: generic_gss_release_oid(&minor, &mechOid); #####: 1364: return; -: 1365: } -: 1366: -: 1367: /* adding a new entry */ #####: 1368: aMech = calloc(1, sizeof (struct gss_mech_config)); #####: 1369: if (aMech == NULL) { #####: 1370: generic_gss_release_oid(&minor, &mechOid); #####: 1371: return; -: 1372: } #####: 1373: aMech->mech_type = mechOid; #####: 1374: aMech->uLibName = strdup(sharedPath); #####: 1375: aMech->mechNameStr = strdup(oidStr); #####: 1376: aMech->freeMech = 0; -: 1377: -: 1378: /* check if any memory allocations failed - bad news */ #####: 1379: if (aMech->uLibName == NULL || aMech->mechNameStr == NULL) { #####: 1380: if (aMech->uLibName) #####: 1381: free(aMech->uLibName); #####: 1382: if (aMech->mechNameStr) #####: 1383: free(aMech->mechNameStr); #####: 1384: generic_gss_release_oid(&minor, &mechOid); #####: 1385: free(aMech); #####: 1386: return; -: 1387: } #####: 1388: if (kernMod) /* this is an optional parameter */ #####: 1389: aMech->kmodName = strdup(kernMod); -: 1390: #####: 1391: if (modOptions) #####: 1392: aMech->optionStr = strdup(modOptions); -: 1393: /* -: 1394: * add the new entry to the end of the list - make sure -: 1395: * that only complete entries are added because other -: 1396: * threads might currently be searching the list. -: 1397: */ #####: 1398: tmp = g_mechListTail; #####: 1399: g_mechListTail = aMech; -: 1400: #####: 1401: if (tmp != NULL) #####: 1402: tmp->next = aMech; -: 1403: #####: 1404: if (g_mechList == NULL) #####: 1405: g_mechList = aMech; -: 1406:} -: 1407: