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