1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate /* 30*7c478bd9Sstevel@tonic-gate * This file contains functions to initialize the gssapi library and 31*7c478bd9Sstevel@tonic-gate * load mechanism libraries. 32*7c478bd9Sstevel@tonic-gate * 33*7c478bd9Sstevel@tonic-gate * It also contain functions requiring direct access to the mechanism's 34*7c478bd9Sstevel@tonic-gate * list (gss_inidicate_mechs and gss_release_oid) as well as support 35*7c478bd9Sstevel@tonic-gate * functions which translate the mechanism strings to oids and vise versa. 36*7c478bd9Sstevel@tonic-gate * 37*7c478bd9Sstevel@tonic-gate * The mechanism libraries are loaded on demand. This is triggered 38*7c478bd9Sstevel@tonic-gate * through the get_mechanism function call. 39*7c478bd9Sstevel@tonic-gate * 40*7c478bd9Sstevel@tonic-gate * Updates to the mechList are performed with the following restrictions: 41*7c478bd9Sstevel@tonic-gate * - once a library is loaded, none of the fields are updated 42*7c478bd9Sstevel@tonic-gate * - existing entiries for non-loaded mechs, will have the 43*7c478bd9Sstevel@tonic-gate * library and kernel module names updated only 44*7c478bd9Sstevel@tonic-gate * (i.e. the mech oid and mech name will not be updated) 45*7c478bd9Sstevel@tonic-gate */ 46*7c478bd9Sstevel@tonic-gate 47*7c478bd9Sstevel@tonic-gate #include <mechglueP.h> 48*7c478bd9Sstevel@tonic-gate #include <stdio.h> 49*7c478bd9Sstevel@tonic-gate #include <syslog.h> 50*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 51*7c478bd9Sstevel@tonic-gate #include <string.h> 52*7c478bd9Sstevel@tonic-gate #include <sys/stat.h> 53*7c478bd9Sstevel@tonic-gate #include <ctype.h> 54*7c478bd9Sstevel@tonic-gate #include <errno.h> 55*7c478bd9Sstevel@tonic-gate #include <synch.h> 56*7c478bd9Sstevel@tonic-gate #include <dlfcn.h> 57*7c478bd9Sstevel@tonic-gate #include <libintl.h> 58*7c478bd9Sstevel@tonic-gate 59*7c478bd9Sstevel@tonic-gate 60*7c478bd9Sstevel@tonic-gate #ifndef TEXT_DOMAIN 61*7c478bd9Sstevel@tonic-gate #error TEXT_DOMAIN not defined 62*7c478bd9Sstevel@tonic-gate #endif 63*7c478bd9Sstevel@tonic-gate 64*7c478bd9Sstevel@tonic-gate #define MECH_CONF "/etc/gss/mech" 65*7c478bd9Sstevel@tonic-gate 66*7c478bd9Sstevel@tonic-gate #define MECH_LIB_PREFIX1 "/usr/lib/" 67*7c478bd9Sstevel@tonic-gate 68*7c478bd9Sstevel@tonic-gate /* 69*7c478bd9Sstevel@tonic-gate * This #ifdef mess figures out if we are to be compiled into 70*7c478bd9Sstevel@tonic-gate * a sparcv9/lp64 binary for the purposes of figuring the absolute location 71*7c478bd9Sstevel@tonic-gate * of gss-api mechanism modules. 72*7c478bd9Sstevel@tonic-gate */ 73*7c478bd9Sstevel@tonic-gate #ifdef _LP64 74*7c478bd9Sstevel@tonic-gate 75*7c478bd9Sstevel@tonic-gate #ifdef __sparc 76*7c478bd9Sstevel@tonic-gate 77*7c478bd9Sstevel@tonic-gate #define MECH_LIB_PREFIX2 "sparcv9/" 78*7c478bd9Sstevel@tonic-gate 79*7c478bd9Sstevel@tonic-gate #elif defined(__amd64) 80*7c478bd9Sstevel@tonic-gate 81*7c478bd9Sstevel@tonic-gate #define MECH_LIB_PREFIX2 "amd64/" 82*7c478bd9Sstevel@tonic-gate 83*7c478bd9Sstevel@tonic-gate #else /* __sparc */ 84*7c478bd9Sstevel@tonic-gate 85*7c478bd9Sstevel@tonic-gate you need to define where under /usr the LP64 libraries live for this platform 86*7c478bd9Sstevel@tonic-gate 87*7c478bd9Sstevel@tonic-gate #endif /* __sparc */ 88*7c478bd9Sstevel@tonic-gate 89*7c478bd9Sstevel@tonic-gate #else /* _LP64 */ 90*7c478bd9Sstevel@tonic-gate 91*7c478bd9Sstevel@tonic-gate #define MECH_LIB_PREFIX2 "" 92*7c478bd9Sstevel@tonic-gate 93*7c478bd9Sstevel@tonic-gate #endif /* _LP64 */ 94*7c478bd9Sstevel@tonic-gate 95*7c478bd9Sstevel@tonic-gate #define MECH_LIB_DIR "gss/" 96*7c478bd9Sstevel@tonic-gate 97*7c478bd9Sstevel@tonic-gate #define MECH_LIB_PREFIX MECH_LIB_PREFIX1 MECH_LIB_PREFIX2 MECH_LIB_DIR 98*7c478bd9Sstevel@tonic-gate 99*7c478bd9Sstevel@tonic-gate 100*7c478bd9Sstevel@tonic-gate #ifndef MECH_SYM 101*7c478bd9Sstevel@tonic-gate #define MECH_SYM "gss_mech_initialize" 102*7c478bd9Sstevel@tonic-gate #endif 103*7c478bd9Sstevel@tonic-gate 104*7c478bd9Sstevel@tonic-gate #define M_DEFAULT "default" 105*7c478bd9Sstevel@tonic-gate 106*7c478bd9Sstevel@tonic-gate /* Local functions */ 107*7c478bd9Sstevel@tonic-gate static gss_mech_info searchMechList(const gss_OID); 108*7c478bd9Sstevel@tonic-gate static void loadConfigFile(const char *); 109*7c478bd9Sstevel@tonic-gate static void updateMechList(void); 110*7c478bd9Sstevel@tonic-gate 111*7c478bd9Sstevel@tonic-gate 112*7c478bd9Sstevel@tonic-gate /* 113*7c478bd9Sstevel@tonic-gate * list of mechanism libraries and their entry points. 114*7c478bd9Sstevel@tonic-gate * the list also maintains state of the mech libraries (loaded or not). 115*7c478bd9Sstevel@tonic-gate */ 116*7c478bd9Sstevel@tonic-gate static gss_mech_info g_mechList = NULL; 117*7c478bd9Sstevel@tonic-gate static gss_mech_info g_mechListTail = NULL; 118*7c478bd9Sstevel@tonic-gate static mutex_t g_mechListLock; 119*7c478bd9Sstevel@tonic-gate static time_t g_confFileModTime = (time_t)0; 120*7c478bd9Sstevel@tonic-gate 121*7c478bd9Sstevel@tonic-gate /* 122*7c478bd9Sstevel@tonic-gate * function used to reclaim the memory used by a gss_OID structure. 123*7c478bd9Sstevel@tonic-gate * This routine requires direct access to the mechList. 124*7c478bd9Sstevel@tonic-gate */ 125*7c478bd9Sstevel@tonic-gate OM_uint32 126*7c478bd9Sstevel@tonic-gate gss_release_oid(minor_status, oid) 127*7c478bd9Sstevel@tonic-gate OM_uint32 *minor_status; 128*7c478bd9Sstevel@tonic-gate gss_OID *oid; 129*7c478bd9Sstevel@tonic-gate { 130*7c478bd9Sstevel@tonic-gate OM_uint32 major; 131*7c478bd9Sstevel@tonic-gate gss_mech_info aMech = g_mechList; 132*7c478bd9Sstevel@tonic-gate 133*7c478bd9Sstevel@tonic-gate if (minor_status == NULL) 134*7c478bd9Sstevel@tonic-gate return (GSS_S_CALL_INACCESSIBLE_WRITE); 135*7c478bd9Sstevel@tonic-gate 136*7c478bd9Sstevel@tonic-gate *minor_status = 0; 137*7c478bd9Sstevel@tonic-gate 138*7c478bd9Sstevel@tonic-gate while (aMech != NULL) { 139*7c478bd9Sstevel@tonic-gate 140*7c478bd9Sstevel@tonic-gate /* 141*7c478bd9Sstevel@tonic-gate * look through the loaded mechanism libraries for 142*7c478bd9Sstevel@tonic-gate * gss_internal_release_oid until one returns success. 143*7c478bd9Sstevel@tonic-gate * gss_internal_release_oid will only return success when 144*7c478bd9Sstevel@tonic-gate * the OID was recognized as an internal mechanism OID. if no 145*7c478bd9Sstevel@tonic-gate * mechanisms recognize the OID, then call the generic version. 146*7c478bd9Sstevel@tonic-gate */ 147*7c478bd9Sstevel@tonic-gate 148*7c478bd9Sstevel@tonic-gate /* 149*7c478bd9Sstevel@tonic-gate * we can walk the mechanism list without a mutex, because we 150*7c478bd9Sstevel@tonic-gate * are only looking at fields which once read will never change. 151*7c478bd9Sstevel@tonic-gate * Mechanism entries are always added to the end, and as 152*7c478bd9Sstevel@tonic-gate * complete entries. 153*7c478bd9Sstevel@tonic-gate */ 154*7c478bd9Sstevel@tonic-gate if (aMech->mech && aMech->mech->gss_internal_release_oid) { 155*7c478bd9Sstevel@tonic-gate major = aMech->mech->gss_internal_release_oid( 156*7c478bd9Sstevel@tonic-gate aMech->mech->context, 157*7c478bd9Sstevel@tonic-gate minor_status, oid); 158*7c478bd9Sstevel@tonic-gate if (major == GSS_S_COMPLETE) 159*7c478bd9Sstevel@tonic-gate return (GSS_S_COMPLETE); 160*7c478bd9Sstevel@tonic-gate } 161*7c478bd9Sstevel@tonic-gate aMech = aMech->next; 162*7c478bd9Sstevel@tonic-gate } /* while */ 163*7c478bd9Sstevel@tonic-gate 164*7c478bd9Sstevel@tonic-gate return (generic_gss_release_oid(minor_status, oid)); 165*7c478bd9Sstevel@tonic-gate } /* gss_release_oid */ 166*7c478bd9Sstevel@tonic-gate 167*7c478bd9Sstevel@tonic-gate 168*7c478bd9Sstevel@tonic-gate /* 169*7c478bd9Sstevel@tonic-gate * this function will return an oid set indicating available mechanisms. 170*7c478bd9Sstevel@tonic-gate * The set returned is based on configuration file entries and 171*7c478bd9Sstevel@tonic-gate * NOT on the loaded mechanisms. This function does not check if any 172*7c478bd9Sstevel@tonic-gate * of these can actually be loaded. 173*7c478bd9Sstevel@tonic-gate * This routine needs direct access to the mechanism list. 174*7c478bd9Sstevel@tonic-gate * To avoid reading the configuration file each call, we will save a 175*7c478bd9Sstevel@tonic-gate * a mech oid set, and only update it once the file has changed. 176*7c478bd9Sstevel@tonic-gate */ 177*7c478bd9Sstevel@tonic-gate static time_t g_mechSetTime = (time_t)0; 178*7c478bd9Sstevel@tonic-gate static gss_OID_set_desc g_mechSet = { 0, NULL }; 179*7c478bd9Sstevel@tonic-gate static mutex_t g_mechSetLock; 180*7c478bd9Sstevel@tonic-gate 181*7c478bd9Sstevel@tonic-gate 182*7c478bd9Sstevel@tonic-gate OM_uint32 183*7c478bd9Sstevel@tonic-gate gss_indicate_mechs(minorStatus, mechSet) 184*7c478bd9Sstevel@tonic-gate OM_uint32 *minorStatus; 185*7c478bd9Sstevel@tonic-gate gss_OID_set *mechSet; 186*7c478bd9Sstevel@tonic-gate { 187*7c478bd9Sstevel@tonic-gate gss_mech_info mList; 188*7c478bd9Sstevel@tonic-gate char *fileName; 189*7c478bd9Sstevel@tonic-gate struct stat fileInfo; 190*7c478bd9Sstevel@tonic-gate int count, i, j; 191*7c478bd9Sstevel@tonic-gate gss_OID curItem; 192*7c478bd9Sstevel@tonic-gate 193*7c478bd9Sstevel@tonic-gate if (!minorStatus) 194*7c478bd9Sstevel@tonic-gate return (GSS_S_CALL_INACCESSIBLE_WRITE); 195*7c478bd9Sstevel@tonic-gate 196*7c478bd9Sstevel@tonic-gate *minorStatus = 0; 197*7c478bd9Sstevel@tonic-gate 198*7c478bd9Sstevel@tonic-gate 199*7c478bd9Sstevel@tonic-gate /* check output parameter */ 200*7c478bd9Sstevel@tonic-gate if (mechSet == NULL) 201*7c478bd9Sstevel@tonic-gate return (GSS_S_CALL_INACCESSIBLE_WRITE); 202*7c478bd9Sstevel@tonic-gate 203*7c478bd9Sstevel@tonic-gate fileName = MECH_CONF; 204*7c478bd9Sstevel@tonic-gate 205*7c478bd9Sstevel@tonic-gate /* 206*7c478bd9Sstevel@tonic-gate * If we have already computed the mechanisms supported and if it 207*7c478bd9Sstevel@tonic-gate * is still valid; make a copy and return to caller, 208*7c478bd9Sstevel@tonic-gate * otherwise build it first. 209*7c478bd9Sstevel@tonic-gate */ 210*7c478bd9Sstevel@tonic-gate if ((stat(fileName, &fileInfo) == 0 && 211*7c478bd9Sstevel@tonic-gate fileInfo.st_mtime > g_mechSetTime)) { 212*7c478bd9Sstevel@tonic-gate /* 213*7c478bd9Sstevel@tonic-gate * lock the mutex since we will be updating 214*7c478bd9Sstevel@tonic-gate * the mechList structure 215*7c478bd9Sstevel@tonic-gate * we need to keep the lock while we build the mechanism list 216*7c478bd9Sstevel@tonic-gate * since we are accessing parts of the mechList which could be 217*7c478bd9Sstevel@tonic-gate * modified. 218*7c478bd9Sstevel@tonic-gate */ 219*7c478bd9Sstevel@tonic-gate (void) mutex_lock(&g_mechListLock); 220*7c478bd9Sstevel@tonic-gate 221*7c478bd9Sstevel@tonic-gate /* 222*7c478bd9Sstevel@tonic-gate * this checks for the case when we need to re-construct the 223*7c478bd9Sstevel@tonic-gate * g_mechSet structure, but the mechanism list is upto date 224*7c478bd9Sstevel@tonic-gate * (because it has been read by someone calling 225*7c478bd9Sstevel@tonic-gate * __gss_get_mechanism) 226*7c478bd9Sstevel@tonic-gate */ 227*7c478bd9Sstevel@tonic-gate if (fileInfo.st_mtime > g_confFileModTime) 228*7c478bd9Sstevel@tonic-gate { 229*7c478bd9Sstevel@tonic-gate g_confFileModTime = fileInfo.st_mtime; 230*7c478bd9Sstevel@tonic-gate loadConfigFile(fileName); 231*7c478bd9Sstevel@tonic-gate } 232*7c478bd9Sstevel@tonic-gate 233*7c478bd9Sstevel@tonic-gate /* 234*7c478bd9Sstevel@tonic-gate * we need to lock the mech set so that no one else will 235*7c478bd9Sstevel@tonic-gate * try to read it as we are re-creating it 236*7c478bd9Sstevel@tonic-gate */ 237*7c478bd9Sstevel@tonic-gate (void) mutex_lock(&g_mechSetLock); 238*7c478bd9Sstevel@tonic-gate 239*7c478bd9Sstevel@tonic-gate /* if the oid list already exists we must free it first */ 240*7c478bd9Sstevel@tonic-gate if (g_mechSet.count != 0) { 241*7c478bd9Sstevel@tonic-gate for (i = 0; i < g_mechSet.count; i++) 242*7c478bd9Sstevel@tonic-gate free(g_mechSet.elements[i].elements); 243*7c478bd9Sstevel@tonic-gate free(g_mechSet.elements); 244*7c478bd9Sstevel@tonic-gate g_mechSet.elements = NULL; 245*7c478bd9Sstevel@tonic-gate g_mechSet.count = 0; 246*7c478bd9Sstevel@tonic-gate } 247*7c478bd9Sstevel@tonic-gate 248*7c478bd9Sstevel@tonic-gate /* determine how many elements to have in the list */ 249*7c478bd9Sstevel@tonic-gate mList = g_mechList; 250*7c478bd9Sstevel@tonic-gate count = 0; 251*7c478bd9Sstevel@tonic-gate while (mList != NULL) { 252*7c478bd9Sstevel@tonic-gate count++; 253*7c478bd9Sstevel@tonic-gate mList = mList->next; 254*7c478bd9Sstevel@tonic-gate } 255*7c478bd9Sstevel@tonic-gate 256*7c478bd9Sstevel@tonic-gate /* this should always be true, but.... */ 257*7c478bd9Sstevel@tonic-gate if (count > 0) { 258*7c478bd9Sstevel@tonic-gate g_mechSet.elements = 259*7c478bd9Sstevel@tonic-gate (gss_OID) calloc(count, sizeof (gss_OID_desc)); 260*7c478bd9Sstevel@tonic-gate if (g_mechSet.elements == NULL) { 261*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&g_mechSetLock); 262*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&g_mechListLock); 263*7c478bd9Sstevel@tonic-gate return (GSS_S_FAILURE); 264*7c478bd9Sstevel@tonic-gate } 265*7c478bd9Sstevel@tonic-gate 266*7c478bd9Sstevel@tonic-gate (void) memset(g_mechSet.elements, 0, 267*7c478bd9Sstevel@tonic-gate count * sizeof (gss_OID_desc)); 268*7c478bd9Sstevel@tonic-gate 269*7c478bd9Sstevel@tonic-gate /* now copy each oid element */ 270*7c478bd9Sstevel@tonic-gate g_mechSet.count = count; 271*7c478bd9Sstevel@tonic-gate count = 0; 272*7c478bd9Sstevel@tonic-gate mList = g_mechList; 273*7c478bd9Sstevel@tonic-gate while (mList != NULL) { 274*7c478bd9Sstevel@tonic-gate curItem = &(g_mechSet.elements[count]); 275*7c478bd9Sstevel@tonic-gate curItem->elements = (void*) 276*7c478bd9Sstevel@tonic-gate malloc(mList->mech_type->length); 277*7c478bd9Sstevel@tonic-gate if (curItem->elements == NULL) { 278*7c478bd9Sstevel@tonic-gate /* 279*7c478bd9Sstevel@tonic-gate * this is nasty - we must delete the 280*7c478bd9Sstevel@tonic-gate * part of the array already copied 281*7c478bd9Sstevel@tonic-gate */ 282*7c478bd9Sstevel@tonic-gate for (i = 0; i < count; i++) { 283*7c478bd9Sstevel@tonic-gate free(g_mechSet.elements[i]. 284*7c478bd9Sstevel@tonic-gate elements); 285*7c478bd9Sstevel@tonic-gate } 286*7c478bd9Sstevel@tonic-gate free(g_mechSet.elements); 287*7c478bd9Sstevel@tonic-gate g_mechSet.count = 0; 288*7c478bd9Sstevel@tonic-gate g_mechSet.elements = NULL; 289*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&g_mechSetLock); 290*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&g_mechListLock); 291*7c478bd9Sstevel@tonic-gate return (GSS_S_FAILURE); 292*7c478bd9Sstevel@tonic-gate } 293*7c478bd9Sstevel@tonic-gate g_OID_copy(curItem, mList->mech_type); 294*7c478bd9Sstevel@tonic-gate count++; 295*7c478bd9Sstevel@tonic-gate mList = mList->next; 296*7c478bd9Sstevel@tonic-gate } 297*7c478bd9Sstevel@tonic-gate } 298*7c478bd9Sstevel@tonic-gate 299*7c478bd9Sstevel@tonic-gate g_mechSetTime = fileInfo.st_mtime; 300*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&g_mechSetLock); 301*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&g_mechListLock); 302*7c478bd9Sstevel@tonic-gate } /* if g_mechSet is out of date or not initialized */ 303*7c478bd9Sstevel@tonic-gate 304*7c478bd9Sstevel@tonic-gate /* 305*7c478bd9Sstevel@tonic-gate * the mech set is created and it is up to date 306*7c478bd9Sstevel@tonic-gate * so just copy it to caller 307*7c478bd9Sstevel@tonic-gate */ 308*7c478bd9Sstevel@tonic-gate if ((*mechSet = 309*7c478bd9Sstevel@tonic-gate (gss_OID_set) malloc(sizeof (gss_OID_set_desc))) == NULL) 310*7c478bd9Sstevel@tonic-gate { 311*7c478bd9Sstevel@tonic-gate return (GSS_S_FAILURE); 312*7c478bd9Sstevel@tonic-gate } 313*7c478bd9Sstevel@tonic-gate 314*7c478bd9Sstevel@tonic-gate /* 315*7c478bd9Sstevel@tonic-gate * need to lock the g_mechSet in case someone tries to update it while 316*7c478bd9Sstevel@tonic-gate * I'm copying it. 317*7c478bd9Sstevel@tonic-gate */ 318*7c478bd9Sstevel@tonic-gate (void) mutex_lock(&g_mechSetLock); 319*7c478bd9Sstevel@tonic-gate 320*7c478bd9Sstevel@tonic-gate /* allocate space for the oid structures */ 321*7c478bd9Sstevel@tonic-gate if (((*mechSet)->elements = 322*7c478bd9Sstevel@tonic-gate (void*) calloc(g_mechSet.count, sizeof (gss_OID_desc))) 323*7c478bd9Sstevel@tonic-gate == NULL) 324*7c478bd9Sstevel@tonic-gate { 325*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&g_mechSetLock); 326*7c478bd9Sstevel@tonic-gate free(*mechSet); 327*7c478bd9Sstevel@tonic-gate *mechSet = NULL; 328*7c478bd9Sstevel@tonic-gate return (GSS_S_FAILURE); 329*7c478bd9Sstevel@tonic-gate } 330*7c478bd9Sstevel@tonic-gate 331*7c478bd9Sstevel@tonic-gate /* now copy the oid structures */ 332*7c478bd9Sstevel@tonic-gate (void) memcpy((*mechSet)->elements, g_mechSet.elements, 333*7c478bd9Sstevel@tonic-gate g_mechSet.count * sizeof (gss_OID_desc)); 334*7c478bd9Sstevel@tonic-gate 335*7c478bd9Sstevel@tonic-gate (*mechSet)->count = g_mechSet.count; 336*7c478bd9Sstevel@tonic-gate 337*7c478bd9Sstevel@tonic-gate /* still need to copy each of the oid elements arrays */ 338*7c478bd9Sstevel@tonic-gate for (i = 0; i < (*mechSet)->count; i++) { 339*7c478bd9Sstevel@tonic-gate curItem = &((*mechSet)->elements[i]); 340*7c478bd9Sstevel@tonic-gate curItem->elements = 341*7c478bd9Sstevel@tonic-gate (void *) malloc(g_mechSet.elements[i].length); 342*7c478bd9Sstevel@tonic-gate if (curItem->elements == NULL) { 343*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&g_mechSetLock); 344*7c478bd9Sstevel@tonic-gate /* 345*7c478bd9Sstevel@tonic-gate * must still free the allocated elements for 346*7c478bd9Sstevel@tonic-gate * each allocated gss_OID_desc 347*7c478bd9Sstevel@tonic-gate */ 348*7c478bd9Sstevel@tonic-gate for (j = 0; j < i; j++) { 349*7c478bd9Sstevel@tonic-gate free((*mechSet)->elements[j].elements); 350*7c478bd9Sstevel@tonic-gate } 351*7c478bd9Sstevel@tonic-gate free((*mechSet)->elements); 352*7c478bd9Sstevel@tonic-gate free(mechSet); 353*7c478bd9Sstevel@tonic-gate *mechSet = NULL; 354*7c478bd9Sstevel@tonic-gate return (GSS_S_FAILURE); 355*7c478bd9Sstevel@tonic-gate } 356*7c478bd9Sstevel@tonic-gate g_OID_copy(curItem, &g_mechSet.elements[i]); 357*7c478bd9Sstevel@tonic-gate } 358*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&g_mechSetLock); 359*7c478bd9Sstevel@tonic-gate return (GSS_S_COMPLETE); 360*7c478bd9Sstevel@tonic-gate } /* gss_indicate_mechs */ 361*7c478bd9Sstevel@tonic-gate 362*7c478bd9Sstevel@tonic-gate /* 363*7c478bd9Sstevel@tonic-gate * this function has been added for use by modules that need to 364*7c478bd9Sstevel@tonic-gate * know what (if any) optional parameters are supplied in the 365*7c478bd9Sstevel@tonic-gate * config file (MECH_CONF). 366*7c478bd9Sstevel@tonic-gate * It will return the option string for a specified mechanism. 367*7c478bd9Sstevel@tonic-gate * caller is responsible for freeing the memory 368*7c478bd9Sstevel@tonic-gate */ 369*7c478bd9Sstevel@tonic-gate char * 370*7c478bd9Sstevel@tonic-gate __gss_get_modOptions(oid) 371*7c478bd9Sstevel@tonic-gate const gss_OID oid; 372*7c478bd9Sstevel@tonic-gate { 373*7c478bd9Sstevel@tonic-gate gss_mech_info aMech; 374*7c478bd9Sstevel@tonic-gate char *modOptions = NULL; 375*7c478bd9Sstevel@tonic-gate 376*7c478bd9Sstevel@tonic-gate /* make sure we have fresh data */ 377*7c478bd9Sstevel@tonic-gate (void) mutex_lock(&g_mechListLock); 378*7c478bd9Sstevel@tonic-gate updateMechList(); 379*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&g_mechListLock); 380*7c478bd9Sstevel@tonic-gate 381*7c478bd9Sstevel@tonic-gate /* searching the list does not require a lock */ 382*7c478bd9Sstevel@tonic-gate if ((aMech = searchMechList(oid)) == NULL || 383*7c478bd9Sstevel@tonic-gate aMech->optionStr == NULL) { 384*7c478bd9Sstevel@tonic-gate return (NULL); 385*7c478bd9Sstevel@tonic-gate } 386*7c478bd9Sstevel@tonic-gate 387*7c478bd9Sstevel@tonic-gate /* 388*7c478bd9Sstevel@tonic-gate * need to obtain a lock on this structure in case someone else 389*7c478bd9Sstevel@tonic-gate * will try to update it during the copy 390*7c478bd9Sstevel@tonic-gate */ 391*7c478bd9Sstevel@tonic-gate (void) mutex_lock(&g_mechListLock); 392*7c478bd9Sstevel@tonic-gate if (aMech->optionStr) 393*7c478bd9Sstevel@tonic-gate modOptions = strdup(aMech->optionStr); 394*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&g_mechListLock); 395*7c478bd9Sstevel@tonic-gate 396*7c478bd9Sstevel@tonic-gate return (modOptions); 397*7c478bd9Sstevel@tonic-gate } /* __gss_get_modOptions */ 398*7c478bd9Sstevel@tonic-gate 399*7c478bd9Sstevel@tonic-gate /* 400*7c478bd9Sstevel@tonic-gate * this function has been added for use by gssd. 401*7c478bd9Sstevel@tonic-gate * It will return the kernel module name for a specified mechanism. 402*7c478bd9Sstevel@tonic-gate * caller is responsible for freeing the memory 403*7c478bd9Sstevel@tonic-gate */ 404*7c478bd9Sstevel@tonic-gate char * 405*7c478bd9Sstevel@tonic-gate __gss_get_kmodName(oid) 406*7c478bd9Sstevel@tonic-gate const gss_OID oid; 407*7c478bd9Sstevel@tonic-gate { 408*7c478bd9Sstevel@tonic-gate gss_mech_info aMech; 409*7c478bd9Sstevel@tonic-gate char *kmodName = NULL; 410*7c478bd9Sstevel@tonic-gate 411*7c478bd9Sstevel@tonic-gate /* make sure we have fresh data */ 412*7c478bd9Sstevel@tonic-gate (void) mutex_lock(&g_mechListLock); 413*7c478bd9Sstevel@tonic-gate updateMechList(); 414*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&g_mechListLock); 415*7c478bd9Sstevel@tonic-gate 416*7c478bd9Sstevel@tonic-gate /* searching the list does not require a lock */ 417*7c478bd9Sstevel@tonic-gate if ((aMech = searchMechList(oid)) == NULL || aMech->kmodName == NULL) { 418*7c478bd9Sstevel@tonic-gate return (NULL); 419*7c478bd9Sstevel@tonic-gate } 420*7c478bd9Sstevel@tonic-gate 421*7c478bd9Sstevel@tonic-gate /* 422*7c478bd9Sstevel@tonic-gate * need to obtain a lock on this structure in case someone else 423*7c478bd9Sstevel@tonic-gate * will try to update it during the copy 424*7c478bd9Sstevel@tonic-gate */ 425*7c478bd9Sstevel@tonic-gate (void) mutex_lock(&g_mechListLock); 426*7c478bd9Sstevel@tonic-gate if (aMech->kmodName) 427*7c478bd9Sstevel@tonic-gate kmodName = strdup(aMech->kmodName); 428*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&g_mechListLock); 429*7c478bd9Sstevel@tonic-gate 430*7c478bd9Sstevel@tonic-gate return (kmodName); 431*7c478bd9Sstevel@tonic-gate } /* __gss_get_kmodName */ 432*7c478bd9Sstevel@tonic-gate 433*7c478bd9Sstevel@tonic-gate 434*7c478bd9Sstevel@tonic-gate /* 435*7c478bd9Sstevel@tonic-gate * given a mechanism string return the mechanism oid 436*7c478bd9Sstevel@tonic-gate */ 437*7c478bd9Sstevel@tonic-gate OM_uint32 438*7c478bd9Sstevel@tonic-gate __gss_mech_to_oid(const char *mechStr, gss_OID* oid) 439*7c478bd9Sstevel@tonic-gate { 440*7c478bd9Sstevel@tonic-gate gss_mech_info aMech; 441*7c478bd9Sstevel@tonic-gate 442*7c478bd9Sstevel@tonic-gate if (oid == NULL) 443*7c478bd9Sstevel@tonic-gate return (GSS_S_CALL_INACCESSIBLE_WRITE); 444*7c478bd9Sstevel@tonic-gate 445*7c478bd9Sstevel@tonic-gate *oid = GSS_C_NULL_OID; 446*7c478bd9Sstevel@tonic-gate 447*7c478bd9Sstevel@tonic-gate if ((mechStr == NULL) || (strlen(mechStr) == 0) || 448*7c478bd9Sstevel@tonic-gate (strcasecmp(mechStr, M_DEFAULT) == 0)) 449*7c478bd9Sstevel@tonic-gate return (GSS_S_COMPLETE); 450*7c478bd9Sstevel@tonic-gate 451*7c478bd9Sstevel@tonic-gate /* ensure we have fresh data */ 452*7c478bd9Sstevel@tonic-gate (void) mutex_lock(&g_mechListLock); 453*7c478bd9Sstevel@tonic-gate updateMechList(); 454*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&g_mechListLock); 455*7c478bd9Sstevel@tonic-gate 456*7c478bd9Sstevel@tonic-gate aMech = g_mechList; 457*7c478bd9Sstevel@tonic-gate 458*7c478bd9Sstevel@tonic-gate /* no lock required - only looking at fields that are not updated */ 459*7c478bd9Sstevel@tonic-gate while (aMech != NULL) { 460*7c478bd9Sstevel@tonic-gate if ((aMech->mechNameStr) && 461*7c478bd9Sstevel@tonic-gate strcmp(aMech->mechNameStr, mechStr) == 0) { 462*7c478bd9Sstevel@tonic-gate *oid = aMech->mech_type; 463*7c478bd9Sstevel@tonic-gate return (GSS_S_COMPLETE); 464*7c478bd9Sstevel@tonic-gate } 465*7c478bd9Sstevel@tonic-gate aMech = aMech->next; 466*7c478bd9Sstevel@tonic-gate } 467*7c478bd9Sstevel@tonic-gate return (GSS_S_FAILURE); 468*7c478bd9Sstevel@tonic-gate } /* __gss_mech_to_oid */ 469*7c478bd9Sstevel@tonic-gate 470*7c478bd9Sstevel@tonic-gate 471*7c478bd9Sstevel@tonic-gate /* 472*7c478bd9Sstevel@tonic-gate * Given the mechanism oid, return the readable mechanism name 473*7c478bd9Sstevel@tonic-gate * associated with that oid from the mech config file 474*7c478bd9Sstevel@tonic-gate * (/etc/gss/mech). 475*7c478bd9Sstevel@tonic-gate */ 476*7c478bd9Sstevel@tonic-gate const char * 477*7c478bd9Sstevel@tonic-gate __gss_oid_to_mech(const gss_OID oid) 478*7c478bd9Sstevel@tonic-gate { 479*7c478bd9Sstevel@tonic-gate gss_mech_info aMech; 480*7c478bd9Sstevel@tonic-gate 481*7c478bd9Sstevel@tonic-gate if (oid == GSS_C_NULL_OID) 482*7c478bd9Sstevel@tonic-gate return (M_DEFAULT); 483*7c478bd9Sstevel@tonic-gate 484*7c478bd9Sstevel@tonic-gate /* ensure we have fresh data */ 485*7c478bd9Sstevel@tonic-gate (void) mutex_lock(&g_mechListLock); 486*7c478bd9Sstevel@tonic-gate updateMechList(); 487*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&g_mechListLock); 488*7c478bd9Sstevel@tonic-gate 489*7c478bd9Sstevel@tonic-gate if ((aMech = searchMechList(oid)) == NULL) 490*7c478bd9Sstevel@tonic-gate return (NULL); 491*7c478bd9Sstevel@tonic-gate 492*7c478bd9Sstevel@tonic-gate return (aMech->mechNameStr); 493*7c478bd9Sstevel@tonic-gate } /* __gss_oid_to_mech */ 494*7c478bd9Sstevel@tonic-gate 495*7c478bd9Sstevel@tonic-gate 496*7c478bd9Sstevel@tonic-gate /* 497*7c478bd9Sstevel@tonic-gate * return a list of mechanism strings supported 498*7c478bd9Sstevel@tonic-gate * upon return the array is terminated with a NULL entry 499*7c478bd9Sstevel@tonic-gate */ 500*7c478bd9Sstevel@tonic-gate OM_uint32 501*7c478bd9Sstevel@tonic-gate __gss_get_mechanisms(char *mechArray[], int arrayLen) 502*7c478bd9Sstevel@tonic-gate { 503*7c478bd9Sstevel@tonic-gate gss_mech_info aMech; 504*7c478bd9Sstevel@tonic-gate int i; 505*7c478bd9Sstevel@tonic-gate 506*7c478bd9Sstevel@tonic-gate if (mechArray == NULL || arrayLen < 1) 507*7c478bd9Sstevel@tonic-gate return (GSS_S_CALL_INACCESSIBLE_WRITE); 508*7c478bd9Sstevel@tonic-gate 509*7c478bd9Sstevel@tonic-gate /* ensure we have fresh data */ 510*7c478bd9Sstevel@tonic-gate (void) mutex_lock(&g_mechListLock); 511*7c478bd9Sstevel@tonic-gate updateMechList(); 512*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&g_mechListLock); 513*7c478bd9Sstevel@tonic-gate 514*7c478bd9Sstevel@tonic-gate aMech = g_mechList; 515*7c478bd9Sstevel@tonic-gate 516*7c478bd9Sstevel@tonic-gate /* no lock required - only looking at fields that are not updated */ 517*7c478bd9Sstevel@tonic-gate for (i = 1; i < arrayLen; i++) { 518*7c478bd9Sstevel@tonic-gate if (aMech != NULL) { 519*7c478bd9Sstevel@tonic-gate *mechArray = aMech->mechNameStr; 520*7c478bd9Sstevel@tonic-gate mechArray++; 521*7c478bd9Sstevel@tonic-gate aMech = aMech->next; 522*7c478bd9Sstevel@tonic-gate } else 523*7c478bd9Sstevel@tonic-gate break; 524*7c478bd9Sstevel@tonic-gate } 525*7c478bd9Sstevel@tonic-gate *mechArray = NULL; 526*7c478bd9Sstevel@tonic-gate return (GSS_S_COMPLETE); 527*7c478bd9Sstevel@tonic-gate } /* gss_get_mechanisms */ 528*7c478bd9Sstevel@tonic-gate 529*7c478bd9Sstevel@tonic-gate 530*7c478bd9Sstevel@tonic-gate /* 531*7c478bd9Sstevel@tonic-gate * determines if the mechList needs to be updated from file 532*7c478bd9Sstevel@tonic-gate * and performs the update. 533*7c478bd9Sstevel@tonic-gate * this functions must be called with a lock of g_mechListLock 534*7c478bd9Sstevel@tonic-gate */ 535*7c478bd9Sstevel@tonic-gate static void 536*7c478bd9Sstevel@tonic-gate updateMechList(void) 537*7c478bd9Sstevel@tonic-gate { 538*7c478bd9Sstevel@tonic-gate char *fileName; 539*7c478bd9Sstevel@tonic-gate struct stat fileInfo; 540*7c478bd9Sstevel@tonic-gate 541*7c478bd9Sstevel@tonic-gate fileName = MECH_CONF; 542*7c478bd9Sstevel@tonic-gate 543*7c478bd9Sstevel@tonic-gate /* check if mechList needs updating */ 544*7c478bd9Sstevel@tonic-gate if (stat(fileName, &fileInfo) == 0 && 545*7c478bd9Sstevel@tonic-gate (fileInfo.st_mtime > g_confFileModTime)) { 546*7c478bd9Sstevel@tonic-gate loadConfigFile(fileName); 547*7c478bd9Sstevel@tonic-gate g_confFileModTime = fileInfo.st_mtime; 548*7c478bd9Sstevel@tonic-gate } 549*7c478bd9Sstevel@tonic-gate } /* updateMechList */ 550*7c478bd9Sstevel@tonic-gate 551*7c478bd9Sstevel@tonic-gate 552*7c478bd9Sstevel@tonic-gate /* 553*7c478bd9Sstevel@tonic-gate * given the mechanism type, return the mechanism structure 554*7c478bd9Sstevel@tonic-gate * containing the mechanism library entry points. 555*7c478bd9Sstevel@tonic-gate * will return NULL if mech type is not found 556*7c478bd9Sstevel@tonic-gate * This function will also trigger the loading of the mechanism 557*7c478bd9Sstevel@tonic-gate * module if it has not been already loaded. 558*7c478bd9Sstevel@tonic-gate */ 559*7c478bd9Sstevel@tonic-gate gss_mechanism 560*7c478bd9Sstevel@tonic-gate __gss_get_mechanism(oid) 561*7c478bd9Sstevel@tonic-gate const gss_OID oid; 562*7c478bd9Sstevel@tonic-gate { 563*7c478bd9Sstevel@tonic-gate gss_mech_info aMech; 564*7c478bd9Sstevel@tonic-gate gss_mechanism (*sym)(const gss_OID); 565*7c478bd9Sstevel@tonic-gate void *dl; 566*7c478bd9Sstevel@tonic-gate 567*7c478bd9Sstevel@tonic-gate /* check if the mechanism is already loaded */ 568*7c478bd9Sstevel@tonic-gate if ((aMech = searchMechList(oid)) != NULL && aMech->mech) { 569*7c478bd9Sstevel@tonic-gate return (aMech->mech); 570*7c478bd9Sstevel@tonic-gate } 571*7c478bd9Sstevel@tonic-gate 572*7c478bd9Sstevel@tonic-gate /* 573*7c478bd9Sstevel@tonic-gate * might need to re-read the configuration file before loading 574*7c478bd9Sstevel@tonic-gate * the mechanism to ensure we have the latest info. 575*7c478bd9Sstevel@tonic-gate */ 576*7c478bd9Sstevel@tonic-gate (void) mutex_lock(&g_mechListLock); 577*7c478bd9Sstevel@tonic-gate updateMechList(); 578*7c478bd9Sstevel@tonic-gate 579*7c478bd9Sstevel@tonic-gate aMech = searchMechList(oid); 580*7c478bd9Sstevel@tonic-gate 581*7c478bd9Sstevel@tonic-gate /* is the mechanism present in the list ? */ 582*7c478bd9Sstevel@tonic-gate if (aMech == NULL) { 583*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&g_mechListLock); 584*7c478bd9Sstevel@tonic-gate return ((gss_mechanism)NULL); 585*7c478bd9Sstevel@tonic-gate } 586*7c478bd9Sstevel@tonic-gate 587*7c478bd9Sstevel@tonic-gate /* has another thread loaded the mech */ 588*7c478bd9Sstevel@tonic-gate if (aMech->mech) { 589*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&g_mechListLock); 590*7c478bd9Sstevel@tonic-gate return (aMech->mech); 591*7c478bd9Sstevel@tonic-gate } 592*7c478bd9Sstevel@tonic-gate 593*7c478bd9Sstevel@tonic-gate /* we found the mechanism, but it is not loaded */ 594*7c478bd9Sstevel@tonic-gate if ((dl = dlopen(aMech->uLibName, RTLD_NOW)) == NULL) { 595*7c478bd9Sstevel@tonic-gate (void) syslog(LOG_INFO, "libgss dlopen(%s): %s\n", 596*7c478bd9Sstevel@tonic-gate aMech->uLibName, dlerror()); 597*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&g_mechListLock); 598*7c478bd9Sstevel@tonic-gate return ((gss_mechanism)NULL); 599*7c478bd9Sstevel@tonic-gate } 600*7c478bd9Sstevel@tonic-gate 601*7c478bd9Sstevel@tonic-gate if ((sym = (gss_mechanism (*)(const gss_OID))dlsym(dl, MECH_SYM)) 602*7c478bd9Sstevel@tonic-gate == NULL) { 603*7c478bd9Sstevel@tonic-gate (void) dlclose(dl); 604*7c478bd9Sstevel@tonic-gate (void) syslog(LOG_INFO, "unable to initialize mechanism" 605*7c478bd9Sstevel@tonic-gate " library [%s]\n", aMech->uLibName); 606*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&g_mechListLock); 607*7c478bd9Sstevel@tonic-gate return ((gss_mechanism)NULL); 608*7c478bd9Sstevel@tonic-gate } 609*7c478bd9Sstevel@tonic-gate 610*7c478bd9Sstevel@tonic-gate /* Call the symbol to get the mechanism table */ 611*7c478bd9Sstevel@tonic-gate aMech->mech = (*sym)(aMech->mech_type); 612*7c478bd9Sstevel@tonic-gate 613*7c478bd9Sstevel@tonic-gate if (aMech->mech == NULL) { 614*7c478bd9Sstevel@tonic-gate (void) dlclose(dl); 615*7c478bd9Sstevel@tonic-gate (void) syslog(LOG_INFO, "unable to initialize mechanism" 616*7c478bd9Sstevel@tonic-gate " library [%s]\n", aMech->uLibName); 617*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&g_mechListLock); 618*7c478bd9Sstevel@tonic-gate return ((gss_mechanism)NULL); 619*7c478bd9Sstevel@tonic-gate } 620*7c478bd9Sstevel@tonic-gate 621*7c478bd9Sstevel@tonic-gate aMech->dl_handle = dl; 622*7c478bd9Sstevel@tonic-gate 623*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&g_mechListLock); 624*7c478bd9Sstevel@tonic-gate return (aMech->mech); 625*7c478bd9Sstevel@tonic-gate } /* __gss_get_mechanism */ 626*7c478bd9Sstevel@tonic-gate 627*7c478bd9Sstevel@tonic-gate gss_mechanism_ext 628*7c478bd9Sstevel@tonic-gate __gss_get_mechanism_ext(oid) 629*7c478bd9Sstevel@tonic-gate const gss_OID oid; 630*7c478bd9Sstevel@tonic-gate { 631*7c478bd9Sstevel@tonic-gate gss_mech_info aMech; 632*7c478bd9Sstevel@tonic-gate gss_mechanism_ext mech_ext; 633*7c478bd9Sstevel@tonic-gate 634*7c478bd9Sstevel@tonic-gate /* check if the mechanism is already loaded */ 635*7c478bd9Sstevel@tonic-gate if ((aMech = searchMechList(oid)) != NULL && aMech->mech_ext != NULL) 636*7c478bd9Sstevel@tonic-gate return (aMech->mech_ext); 637*7c478bd9Sstevel@tonic-gate 638*7c478bd9Sstevel@tonic-gate if (__gss_get_mechanism(oid) == NULL) 639*7c478bd9Sstevel@tonic-gate return (NULL); 640*7c478bd9Sstevel@tonic-gate 641*7c478bd9Sstevel@tonic-gate if (aMech->dl_handle == NULL) 642*7c478bd9Sstevel@tonic-gate return (NULL); 643*7c478bd9Sstevel@tonic-gate 644*7c478bd9Sstevel@tonic-gate /* Load the gss_config_ext struct for this mech */ 645*7c478bd9Sstevel@tonic-gate 646*7c478bd9Sstevel@tonic-gate mech_ext = (gss_mechanism_ext)malloc(sizeof (struct gss_config_ext)); 647*7c478bd9Sstevel@tonic-gate 648*7c478bd9Sstevel@tonic-gate if (mech_ext == NULL) 649*7c478bd9Sstevel@tonic-gate return (NULL); 650*7c478bd9Sstevel@tonic-gate 651*7c478bd9Sstevel@tonic-gate /* 652*7c478bd9Sstevel@tonic-gate * dlsym() the mech's 'method' functions for the extended APIs 653*7c478bd9Sstevel@tonic-gate * 654*7c478bd9Sstevel@tonic-gate * NOTE: Until the void *context argument is removed from the 655*7c478bd9Sstevel@tonic-gate * SPI method functions' signatures it will be necessary to have 656*7c478bd9Sstevel@tonic-gate * different function pointer typedefs and function names for 657*7c478bd9Sstevel@tonic-gate * the SPI methods than for the API. When this argument is 658*7c478bd9Sstevel@tonic-gate * removed it will be possible to rename gss_*_sfct to gss_*_fct 659*7c478bd9Sstevel@tonic-gate * and and gssspi_* to gss_*. 660*7c478bd9Sstevel@tonic-gate */ 661*7c478bd9Sstevel@tonic-gate mech_ext->gss_acquire_cred_with_password = 662*7c478bd9Sstevel@tonic-gate (gss_acquire_cred_with_password_sfct)dlsym(aMech->dl_handle, 663*7c478bd9Sstevel@tonic-gate "gssspi_acquire_cred_with_password"); 664*7c478bd9Sstevel@tonic-gate 665*7c478bd9Sstevel@tonic-gate /* Set aMech->mech_ext */ 666*7c478bd9Sstevel@tonic-gate (void) mutex_lock(&g_mechListLock); 667*7c478bd9Sstevel@tonic-gate 668*7c478bd9Sstevel@tonic-gate if (aMech->mech_ext == NULL) 669*7c478bd9Sstevel@tonic-gate aMech->mech_ext = mech_ext; 670*7c478bd9Sstevel@tonic-gate else 671*7c478bd9Sstevel@tonic-gate free(mech_ext); /* we raced and lost; don't leak */ 672*7c478bd9Sstevel@tonic-gate 673*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&g_mechListLock); 674*7c478bd9Sstevel@tonic-gate 675*7c478bd9Sstevel@tonic-gate return (aMech->mech_ext); 676*7c478bd9Sstevel@tonic-gate 677*7c478bd9Sstevel@tonic-gate } /* __gss_get_mechanism_ext */ 678*7c478bd9Sstevel@tonic-gate 679*7c478bd9Sstevel@tonic-gate 680*7c478bd9Sstevel@tonic-gate /* 681*7c478bd9Sstevel@tonic-gate * this routine is used for searching the list of mechanism data. 682*7c478bd9Sstevel@tonic-gate * it needs not be mutex protected because we only add new structures 683*7c478bd9Sstevel@tonic-gate * from the end and they are fully initialized before being added. 684*7c478bd9Sstevel@tonic-gate */ 685*7c478bd9Sstevel@tonic-gate static gss_mech_info searchMechList(oid) 686*7c478bd9Sstevel@tonic-gate const gss_OID oid; 687*7c478bd9Sstevel@tonic-gate { 688*7c478bd9Sstevel@tonic-gate gss_mech_info aMech = g_mechList; 689*7c478bd9Sstevel@tonic-gate 690*7c478bd9Sstevel@tonic-gate /* if oid is null -> then get default which is the first in the list */ 691*7c478bd9Sstevel@tonic-gate if (oid == GSS_C_NULL_OID) 692*7c478bd9Sstevel@tonic-gate return (aMech); 693*7c478bd9Sstevel@tonic-gate 694*7c478bd9Sstevel@tonic-gate while (aMech != NULL) { 695*7c478bd9Sstevel@tonic-gate if (g_OID_equal(aMech->mech_type, oid)) 696*7c478bd9Sstevel@tonic-gate return (aMech); 697*7c478bd9Sstevel@tonic-gate aMech = aMech->next; 698*7c478bd9Sstevel@tonic-gate } 699*7c478bd9Sstevel@tonic-gate 700*7c478bd9Sstevel@tonic-gate /* none found */ 701*7c478bd9Sstevel@tonic-gate return ((gss_mech_info) NULL); 702*7c478bd9Sstevel@tonic-gate } /* searchMechList */ 703*7c478bd9Sstevel@tonic-gate 704*7c478bd9Sstevel@tonic-gate 705*7c478bd9Sstevel@tonic-gate /* 706*7c478bd9Sstevel@tonic-gate * loads the configuration file 707*7c478bd9Sstevel@tonic-gate * this is called while having a mutex lock on the mechanism list 708*7c478bd9Sstevel@tonic-gate * entries for libraries that have been loaded can't be modified 709*7c478bd9Sstevel@tonic-gate * mechNameStr and mech_type fields are not updated during updates 710*7c478bd9Sstevel@tonic-gate */ 711*7c478bd9Sstevel@tonic-gate static void loadConfigFile(fileName) 712*7c478bd9Sstevel@tonic-gate const char *fileName; 713*7c478bd9Sstevel@tonic-gate { 714*7c478bd9Sstevel@tonic-gate char buffer[BUFSIZ], *oidStr, *oid, *sharedLib, *kernMod, *endp; 715*7c478bd9Sstevel@tonic-gate char *modOptions; 716*7c478bd9Sstevel@tonic-gate char sharedPath[sizeof (MECH_LIB_PREFIX) + BUFSIZ]; 717*7c478bd9Sstevel@tonic-gate char *tmpStr; 718*7c478bd9Sstevel@tonic-gate FILE *confFile; 719*7c478bd9Sstevel@tonic-gate gss_OID mechOid; 720*7c478bd9Sstevel@tonic-gate gss_mech_info aMech, tmp; 721*7c478bd9Sstevel@tonic-gate OM_uint32 minor; 722*7c478bd9Sstevel@tonic-gate gss_buffer_desc oidBuf; 723*7c478bd9Sstevel@tonic-gate 724*7c478bd9Sstevel@tonic-gate if ((confFile = fopen(fileName, "r")) == NULL) { 725*7c478bd9Sstevel@tonic-gate return; 726*7c478bd9Sstevel@tonic-gate } 727*7c478bd9Sstevel@tonic-gate 728*7c478bd9Sstevel@tonic-gate (void) memset(buffer, 0, sizeof (buffer)); 729*7c478bd9Sstevel@tonic-gate while (fgets(buffer, BUFSIZ, confFile) != NULL) { 730*7c478bd9Sstevel@tonic-gate 731*7c478bd9Sstevel@tonic-gate /* ignore lines beginning with # */ 732*7c478bd9Sstevel@tonic-gate if (*buffer == '#') 733*7c478bd9Sstevel@tonic-gate continue; 734*7c478bd9Sstevel@tonic-gate 735*7c478bd9Sstevel@tonic-gate /* 736*7c478bd9Sstevel@tonic-gate * find the first white-space character after 737*7c478bd9Sstevel@tonic-gate * the mechanism name 738*7c478bd9Sstevel@tonic-gate */ 739*7c478bd9Sstevel@tonic-gate oidStr = buffer; 740*7c478bd9Sstevel@tonic-gate for (oid = buffer; *oid && !isspace(*oid); oid++); 741*7c478bd9Sstevel@tonic-gate 742*7c478bd9Sstevel@tonic-gate /* Now find the first non-white-space character */ 743*7c478bd9Sstevel@tonic-gate if (*oid) { 744*7c478bd9Sstevel@tonic-gate *oid = '\0'; 745*7c478bd9Sstevel@tonic-gate oid++; 746*7c478bd9Sstevel@tonic-gate while (*oid && isspace(*oid)) 747*7c478bd9Sstevel@tonic-gate oid++; 748*7c478bd9Sstevel@tonic-gate } 749*7c478bd9Sstevel@tonic-gate 750*7c478bd9Sstevel@tonic-gate /* 751*7c478bd9Sstevel@tonic-gate * If that's all, then this is a corrupt entry. Skip it. 752*7c478bd9Sstevel@tonic-gate */ 753*7c478bd9Sstevel@tonic-gate if (! *oid) 754*7c478bd9Sstevel@tonic-gate continue; 755*7c478bd9Sstevel@tonic-gate 756*7c478bd9Sstevel@tonic-gate /* Find the end of the oid and make sure it is NULL-ended */ 757*7c478bd9Sstevel@tonic-gate for (endp = oid; *endp && !isspace(*endp); endp++) 758*7c478bd9Sstevel@tonic-gate ; 759*7c478bd9Sstevel@tonic-gate 760*7c478bd9Sstevel@tonic-gate if (*endp) { 761*7c478bd9Sstevel@tonic-gate *endp = '\0'; 762*7c478bd9Sstevel@tonic-gate } 763*7c478bd9Sstevel@tonic-gate 764*7c478bd9Sstevel@tonic-gate /* 765*7c478bd9Sstevel@tonic-gate * check if an entry for this oid already exists 766*7c478bd9Sstevel@tonic-gate * if it does, and the library is already loaded then 767*7c478bd9Sstevel@tonic-gate * we can't modify it, so skip it 768*7c478bd9Sstevel@tonic-gate */ 769*7c478bd9Sstevel@tonic-gate oidBuf.value = (void *)oid; 770*7c478bd9Sstevel@tonic-gate oidBuf.length = strlen(oid); 771*7c478bd9Sstevel@tonic-gate if (generic_gss_str_to_oid(&minor, &oidBuf, &mechOid) 772*7c478bd9Sstevel@tonic-gate != GSS_S_COMPLETE) { 773*7c478bd9Sstevel@tonic-gate (void) syslog(LOG_INFO, "invalid mechanism oid" 774*7c478bd9Sstevel@tonic-gate " [%s] in configuration file", oid); 775*7c478bd9Sstevel@tonic-gate continue; 776*7c478bd9Sstevel@tonic-gate } 777*7c478bd9Sstevel@tonic-gate 778*7c478bd9Sstevel@tonic-gate aMech = searchMechList(mechOid); 779*7c478bd9Sstevel@tonic-gate if (aMech && aMech->mech) { 780*7c478bd9Sstevel@tonic-gate free(mechOid->elements); 781*7c478bd9Sstevel@tonic-gate free(mechOid); 782*7c478bd9Sstevel@tonic-gate continue; 783*7c478bd9Sstevel@tonic-gate } 784*7c478bd9Sstevel@tonic-gate 785*7c478bd9Sstevel@tonic-gate /* Find the start of the shared lib name */ 786*7c478bd9Sstevel@tonic-gate for (sharedLib = endp+1; *sharedLib && isspace(*sharedLib); 787*7c478bd9Sstevel@tonic-gate sharedLib++) 788*7c478bd9Sstevel@tonic-gate ; 789*7c478bd9Sstevel@tonic-gate 790*7c478bd9Sstevel@tonic-gate /* 791*7c478bd9Sstevel@tonic-gate * If that's all, then this is a corrupt entry. Skip it. 792*7c478bd9Sstevel@tonic-gate */ 793*7c478bd9Sstevel@tonic-gate if (! *sharedLib) { 794*7c478bd9Sstevel@tonic-gate free(mechOid->elements); 795*7c478bd9Sstevel@tonic-gate free(mechOid); 796*7c478bd9Sstevel@tonic-gate continue; 797*7c478bd9Sstevel@tonic-gate } 798*7c478bd9Sstevel@tonic-gate 799*7c478bd9Sstevel@tonic-gate /* 800*7c478bd9Sstevel@tonic-gate * Find the end of the shared lib name and make sure it is 801*7c478bd9Sstevel@tonic-gate * NULL-terminated. 802*7c478bd9Sstevel@tonic-gate */ 803*7c478bd9Sstevel@tonic-gate for (endp = sharedLib; *endp && !isspace(*endp); endp++) 804*7c478bd9Sstevel@tonic-gate ; 805*7c478bd9Sstevel@tonic-gate 806*7c478bd9Sstevel@tonic-gate if (*endp) { 807*7c478bd9Sstevel@tonic-gate *endp = '\0'; 808*7c478bd9Sstevel@tonic-gate } 809*7c478bd9Sstevel@tonic-gate 810*7c478bd9Sstevel@tonic-gate /* Find the start of the optional kernel module lib name */ 811*7c478bd9Sstevel@tonic-gate for (kernMod = endp+1; *kernMod && isspace(*kernMod); 812*7c478bd9Sstevel@tonic-gate kernMod++) 813*7c478bd9Sstevel@tonic-gate ; 814*7c478bd9Sstevel@tonic-gate 815*7c478bd9Sstevel@tonic-gate /* 816*7c478bd9Sstevel@tonic-gate * If this item starts with a bracket "[", then 817*7c478bd9Sstevel@tonic-gate * it is not a kernel module, but is a list of 818*7c478bd9Sstevel@tonic-gate * options for the user module to parse later. 819*7c478bd9Sstevel@tonic-gate */ 820*7c478bd9Sstevel@tonic-gate if (*kernMod && *kernMod != '[') { 821*7c478bd9Sstevel@tonic-gate /* 822*7c478bd9Sstevel@tonic-gate * Find the end of the shared lib name and make sure 823*7c478bd9Sstevel@tonic-gate * it is NULL-terminated. 824*7c478bd9Sstevel@tonic-gate */ 825*7c478bd9Sstevel@tonic-gate for (endp = kernMod; *endp && !isspace(*endp); endp++) 826*7c478bd9Sstevel@tonic-gate ; 827*7c478bd9Sstevel@tonic-gate 828*7c478bd9Sstevel@tonic-gate if (*endp) { 829*7c478bd9Sstevel@tonic-gate *endp = '\0'; 830*7c478bd9Sstevel@tonic-gate } 831*7c478bd9Sstevel@tonic-gate } else 832*7c478bd9Sstevel@tonic-gate kernMod = NULL; 833*7c478bd9Sstevel@tonic-gate 834*7c478bd9Sstevel@tonic-gate /* Find the start of the optional module options list */ 835*7c478bd9Sstevel@tonic-gate for (modOptions = endp+1; *modOptions && isspace(*modOptions); 836*7c478bd9Sstevel@tonic-gate modOptions++); 837*7c478bd9Sstevel@tonic-gate 838*7c478bd9Sstevel@tonic-gate if (*modOptions == '[') { 839*7c478bd9Sstevel@tonic-gate /* move past the opening bracket */ 840*7c478bd9Sstevel@tonic-gate for (modOptions = modOptions+1; 841*7c478bd9Sstevel@tonic-gate *modOptions && isspace(*modOptions); 842*7c478bd9Sstevel@tonic-gate modOptions++); 843*7c478bd9Sstevel@tonic-gate 844*7c478bd9Sstevel@tonic-gate /* Find the closing bracket */ 845*7c478bd9Sstevel@tonic-gate for (endp = modOptions; 846*7c478bd9Sstevel@tonic-gate *endp && *endp != ']'; endp++); 847*7c478bd9Sstevel@tonic-gate 848*7c478bd9Sstevel@tonic-gate if (endp) 849*7c478bd9Sstevel@tonic-gate *endp = '\0'; 850*7c478bd9Sstevel@tonic-gate 851*7c478bd9Sstevel@tonic-gate } else { 852*7c478bd9Sstevel@tonic-gate modOptions = NULL; 853*7c478bd9Sstevel@tonic-gate } 854*7c478bd9Sstevel@tonic-gate 855*7c478bd9Sstevel@tonic-gate (void) strcpy(sharedPath, MECH_LIB_PREFIX); 856*7c478bd9Sstevel@tonic-gate (void) strcat(sharedPath, sharedLib); 857*7c478bd9Sstevel@tonic-gate 858*7c478bd9Sstevel@tonic-gate /* 859*7c478bd9Sstevel@tonic-gate * are we creating a new mechanism entry or 860*7c478bd9Sstevel@tonic-gate * just modifying existing (non loaded) mechanism entry 861*7c478bd9Sstevel@tonic-gate */ 862*7c478bd9Sstevel@tonic-gate if (aMech) { 863*7c478bd9Sstevel@tonic-gate /* 864*7c478bd9Sstevel@tonic-gate * delete any old values and set new 865*7c478bd9Sstevel@tonic-gate * mechNameStr and mech_type are not modified 866*7c478bd9Sstevel@tonic-gate */ 867*7c478bd9Sstevel@tonic-gate if (aMech->kmodName) { 868*7c478bd9Sstevel@tonic-gate free(aMech->kmodName); 869*7c478bd9Sstevel@tonic-gate aMech->kmodName = NULL; 870*7c478bd9Sstevel@tonic-gate } 871*7c478bd9Sstevel@tonic-gate 872*7c478bd9Sstevel@tonic-gate if (aMech->optionStr) { 873*7c478bd9Sstevel@tonic-gate free(aMech->optionStr); 874*7c478bd9Sstevel@tonic-gate aMech->optionStr = NULL; 875*7c478bd9Sstevel@tonic-gate } 876*7c478bd9Sstevel@tonic-gate 877*7c478bd9Sstevel@tonic-gate if ((tmpStr = strdup(sharedPath)) != NULL) { 878*7c478bd9Sstevel@tonic-gate if (aMech->uLibName) 879*7c478bd9Sstevel@tonic-gate free(aMech->uLibName); 880*7c478bd9Sstevel@tonic-gate aMech->uLibName = tmpStr; 881*7c478bd9Sstevel@tonic-gate } 882*7c478bd9Sstevel@tonic-gate 883*7c478bd9Sstevel@tonic-gate if (kernMod) /* this is an optional parameter */ 884*7c478bd9Sstevel@tonic-gate aMech->kmodName = strdup(kernMod); 885*7c478bd9Sstevel@tonic-gate 886*7c478bd9Sstevel@tonic-gate if (modOptions) /* optional module options */ 887*7c478bd9Sstevel@tonic-gate aMech->optionStr = strdup(modOptions); 888*7c478bd9Sstevel@tonic-gate 889*7c478bd9Sstevel@tonic-gate /* the oid is already set */ 890*7c478bd9Sstevel@tonic-gate free(mechOid->elements); 891*7c478bd9Sstevel@tonic-gate free(mechOid); 892*7c478bd9Sstevel@tonic-gate continue; 893*7c478bd9Sstevel@tonic-gate } 894*7c478bd9Sstevel@tonic-gate 895*7c478bd9Sstevel@tonic-gate /* adding a new entry */ 896*7c478bd9Sstevel@tonic-gate aMech = malloc(sizeof (struct gss_mech_config)); 897*7c478bd9Sstevel@tonic-gate if (aMech == NULL) { 898*7c478bd9Sstevel@tonic-gate free(mechOid->elements); 899*7c478bd9Sstevel@tonic-gate free(mechOid); 900*7c478bd9Sstevel@tonic-gate continue; 901*7c478bd9Sstevel@tonic-gate } 902*7c478bd9Sstevel@tonic-gate (void) memset(aMech, 0, sizeof (struct gss_mech_config)); 903*7c478bd9Sstevel@tonic-gate aMech->mech_type = mechOid; 904*7c478bd9Sstevel@tonic-gate aMech->uLibName = strdup(sharedPath); 905*7c478bd9Sstevel@tonic-gate aMech->mechNameStr = strdup(oidStr); 906*7c478bd9Sstevel@tonic-gate 907*7c478bd9Sstevel@tonic-gate /* check if any memory allocations failed - bad news */ 908*7c478bd9Sstevel@tonic-gate if (aMech->uLibName == NULL || aMech->mechNameStr == NULL) { 909*7c478bd9Sstevel@tonic-gate if (aMech->uLibName) 910*7c478bd9Sstevel@tonic-gate free(aMech->uLibName); 911*7c478bd9Sstevel@tonic-gate if (aMech->mechNameStr) 912*7c478bd9Sstevel@tonic-gate free(aMech->mechNameStr); 913*7c478bd9Sstevel@tonic-gate free(mechOid->elements); 914*7c478bd9Sstevel@tonic-gate free(mechOid); 915*7c478bd9Sstevel@tonic-gate free(aMech); 916*7c478bd9Sstevel@tonic-gate continue; 917*7c478bd9Sstevel@tonic-gate } 918*7c478bd9Sstevel@tonic-gate if (kernMod) /* this is an optional parameter */ 919*7c478bd9Sstevel@tonic-gate aMech->kmodName = strdup(kernMod); 920*7c478bd9Sstevel@tonic-gate 921*7c478bd9Sstevel@tonic-gate if (modOptions) 922*7c478bd9Sstevel@tonic-gate aMech->optionStr = strdup(modOptions); 923*7c478bd9Sstevel@tonic-gate /* 924*7c478bd9Sstevel@tonic-gate * add the new entry to the end of the list - make sure 925*7c478bd9Sstevel@tonic-gate * that only complete entries are added because other 926*7c478bd9Sstevel@tonic-gate * threads might currently be searching the list. 927*7c478bd9Sstevel@tonic-gate */ 928*7c478bd9Sstevel@tonic-gate tmp = g_mechListTail; 929*7c478bd9Sstevel@tonic-gate g_mechListTail = aMech; 930*7c478bd9Sstevel@tonic-gate 931*7c478bd9Sstevel@tonic-gate if (tmp != NULL) 932*7c478bd9Sstevel@tonic-gate tmp->next = aMech; 933*7c478bd9Sstevel@tonic-gate 934*7c478bd9Sstevel@tonic-gate if (g_mechList == NULL) 935*7c478bd9Sstevel@tonic-gate g_mechList = aMech; 936*7c478bd9Sstevel@tonic-gate } /* while */ 937*7c478bd9Sstevel@tonic-gate (void) fclose(confFile); 938*7c478bd9Sstevel@tonic-gate } /* loadConfigFile */ 939