4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
28 * This module contains the interfaces for the NIS+ security mechanisms.
37 #include <netconfig.h>
38 #include <sys/types.h>
44 #include <rpcsvc/nis_dhext.h>
51 #define NIS_SEC_CF_MAX_LINELEN 512
53 /* the min number of fields allowable per line */
54 #define NIS_SEC_CF_MIN_FIELDS 5
55 /* the max number of fields processed per line */
56 #define NIS_SEC_CF_MAX_FIELDS 7
58 /* field "Not Applicable" char */
59 #define NIS_SEC_CF_NA_CHAR '-'
60 #define NIS_SEC_CF_NA_CMP(a) ((a)[0] == NIS_SEC_CF_NA_CHAR && (a)[1] == '\0')
63 static const char *cf_entry_type_mech_str
= "mech";
64 static const char *cf_mech_des_str
= NIS_SEC_CF_DES_ALIAS
;
65 static const char *cf_mech_dh1920_str
= "dh192-0";
67 static const char *cf_secserv_default_str
= "default";
68 static const char *cf_secserv_none_str
= "none";
69 static const char *cf_secserv_integrity_str
= "integrity";
70 static const char *cf_secserv_privacy_str
= "privacy";
72 static mutex_t nis_sec_cf_lock
= DEFAULTMUTEX
;
78 * This is currently a private NIS+ interface but at some point in the future
79 * can be broken out and made available to other apps that need to access
83 #define MF_MAX_LINELEN 256
84 #define MF_MAX_FLDLEN MAXDHNAME
86 /* mech file entry type */
91 /* the 4th field is not used by user land apps */
94 static const char mech_file
[] = "/etc/gss/mech";
95 static const int mech_file_flds_max
= 3;
96 static const int mech_file_flds_min
= 3;
97 static mutex_t mech_file_lock
= DEFAULTMUTEX
;
98 static const char dh_str
[] = "diffie_hellman";
101 #define MECH_LIB_PREFIX1 "/usr/lib/"
105 #define MECH_LIB_PREFIX2 "64/"
109 #define MECH_LIB_PREFIX2 ""
113 #define MECH_LIB_DIR "gss/"
115 #define MECH_LIB_PREFIX MECH_LIB_PREFIX1 MECH_LIB_PREFIX2 MECH_LIB_DIR
119 list_free_all(void (*free_ent
)(), void **mpp
)
131 list_append_ent(void *ent
, void **list
, uint_t cnt
, void (*free_ent
)())
135 if (!(new_l
= reallocarray(list
, cnt
+ 1, sizeof (*list
)))) {
136 list_free_all(free_ent
, list
);
139 *(new_l
+ cnt
- 1) = ent
;
140 *(new_l
+ cnt
) = NULL
;
146 list_copy(void *(*cp_ent
)(), void **mpp
)
156 for (tpp
= mpp
; *tpp
; tpp
++)
161 if (!(tpp_h
= calloc(diff
+ 1, sizeof (*mpp
))))
164 for (tpp
= tpp_h
; *mpp
; mpp
++) {
165 if (!(tp
= (*cp_ent
)(*mpp
))) {
182 if (fgets(line
, NIS_SEC_CF_MAX_LINELEN
, fd
) == NULL
)
184 cp
= index(line
, '\n');
191 nextfield(char **cpp
, char *op
, int n
)
198 while (*cp
== ' ' || *cp
== '\t')
200 if (*cp
== '\0' || *cp
== '#')
203 max
= (intptr_t)op
+ n
;
204 while (*cp
&& *cp
!= ' ' && *cp
!= '\t' && *cp
!= '#' &&
209 if ((intptr_t)dst
>= max
)
210 /* not much else to do but move past current field */
211 while (*cp
&& *cp
!= ' ' && *cp
!= '\t' && *cp
!= '#')
220 static rpc_gss_service_t
221 str_to_secserv_t(const char *s
)
225 if (strncmp(cf_secserv_none_str
, s
,
226 strlen(cf_secserv_none_str
)) == 0)
227 return (rpc_gss_svc_none
);
228 if (strncmp(cf_secserv_integrity_str
, s
,
229 strlen(cf_secserv_integrity_str
)) == 0)
230 return (rpc_gss_svc_integrity
);
231 if (strncmp(cf_secserv_privacy_str
, s
,
232 strlen(cf_secserv_privacy_str
)) == 0)
233 return (rpc_gss_svc_privacy
);
236 return (rpc_gss_svc_default
);
240 * Return TRUE if all the chars up to the NUL are of the digit type.
244 isnumberstr(const char *s
)
255 * Free security file mechanism entry.
258 sf_free_mech_ent(mechanism_t
*mp
)
269 free_fields(char **cpp
, int cnt
)
275 for (; cnt
> 0; cnt
--, tpp
++)
285 * Generic parse-linestr-of-config-file routine. Arg linep is ptr
286 * (which will be modified) to the input string . Arg minflds is the
287 * minimum number of fields expected. Arg maxflds is the max number
288 * of fields that will be parsed. Arg bufsiz is the max len of each
289 * field that will be copied to the return area.
291 * If there are less fields in the entry than the max number,
292 * the remainding ptrs will be 0.
294 * Returns a ptr to an array of ptrs to strings on success else
297 * The caller must free the storage (of a successful return only).
300 parse_line(char *linep
, int minflds
, int maxflds
, int bufsiz
)
302 char **fpp
= calloc(maxflds
, sizeof (linep
));
310 if (!(cp
= malloc(bufsiz
))) {
315 for (i
= 0; i
< maxflds
; i
++, tpp
++) {
317 if (!nextfield(&linep
, cp
, bufsiz
)) {
325 if (!(tp
= strdup(cp
))) {
338 * Return a ptr to a mechanism entry read from a line of the sec conf file.
339 * Return NULL on EOF or error.
341 * An alias field of "des" (case not sig) will override any settings
342 * in the keylen or algtype fields like so:
348 get_secfile_ent(FILE *fptr
)
352 char **flds
; /* line fields */
353 const int num_flds_min
= NIS_SEC_CF_MIN_FIELDS
;
354 const int num_flds_max
= NIS_SEC_CF_MAX_FIELDS
;
355 char line
[NIS_SEC_CF_MAX_LINELEN
+ 1 ] = {0};
356 const int line_len
= NIS_SEC_CF_MAX_LINELEN
+ 1;
359 * NIS+ security conf file layout
361 * mech <GSS_mechanism_name> <Mech_bit_size> <Mech_alg_type>
362 * <Alias> <GSS_quality_of_protection> <GSS_sec_svc>
364 * QOP and sec_svc are optional.
366 const int mn_offset
= 1; /* mechname */
367 const int kl_offset
= 2; /* key length */
368 const int at_offset
= 3; /* alg type */
369 const int al_offset
= 4; /* mech alias */
370 const int qp_offset
= 5; /* qop */
371 const int ss_offset
= 6; /* security svc */
374 while (((cp
= nextline(fptr
, line
)) != NULL
) &&
375 (*cp
== '#' || *cp
== '\0'))
380 if (!(flds
= parse_line(cp
, num_flds_min
, num_flds_max
,
384 if (strncmp(cf_entry_type_mech_str
, *flds
,
385 strlen(cf_entry_type_mech_str
))) {
386 free_fields(flds
, num_flds_max
);
390 if (!(m
= malloc(sizeof (mechanism_t
)))) {
391 free_fields(flds
, num_flds_max
);
396 m
->mechname
= NIS_SEC_CF_NA_CMP(*(flds
+ mn_offset
)) ? NULL
397 : strdup(*(flds
+ mn_offset
));
399 /* mechanism alias */
400 m
->alias
= NIS_SEC_CF_NA_CMP(*(flds
+ al_offset
)) ? NULL
401 : strdup(*(flds
+ al_offset
));
404 * qop: optional field
405 * Make qop NULL if the field was empty or was "default" or
408 if (!*(flds
+ qp_offset
) ||
409 (strncasecmp(*(flds
+ qp_offset
), cf_secserv_default_str
,
410 strlen(cf_secserv_default_str
)) == 0) ||
411 NIS_SEC_CF_NA_CMP(*(flds
+ qp_offset
)))
414 m
->qop
= strdup(*(flds
+ qp_offset
));
416 /* security service: optional field */
417 m
->secserv
= str_to_secserv_t(*(flds
+ ss_offset
));
420 if (*(flds
+ al_offset
) &&
421 (strncasecmp(*(flds
+ al_offset
), cf_mech_des_str
,
422 strlen(cf_mech_des_str
)) == 0)) {
423 /* we've got the AUTH_DES compat line */
427 /* key length (bits) */
428 if (NIS_SEC_CF_NA_CMP(*(flds
+ kl_offset
)))
429 m
->keylen
= NIS_SEC_CF_NA_KA
;
430 else if (!isnumberstr(*(flds
+ kl_offset
))) {
431 free_fields(flds
, num_flds_max
);
435 m
->keylen
= atoi(*(flds
+ kl_offset
));
438 if (NIS_SEC_CF_NA_CMP(*(flds
+ at_offset
)))
439 m
->algtype
= NIS_SEC_CF_NA_KA
;
440 else if (!isnumberstr(*(flds
+ at_offset
))) {
441 free_fields(flds
, num_flds_max
);
445 m
->algtype
= atoi(*(flds
+ at_offset
));
448 free_fields(flds
, num_flds_max
);
454 * Return TRUE if both entries have the same
455 * mechname/alias/keylen/algotype combo. Else return FALSE.
458 equal_entries(const mechanism_t
*mp
, const mechanism_t
*tp
)
461 if (mp
->keylen
!= tp
->keylen
)
463 if (mp
->algtype
!= tp
->algtype
)
466 /* both NULL, the 2 are equal */
467 if (!mp
->mechname
&& !tp
->mechname
)
469 /* only one NULL, not equal */
470 if (!mp
->mechname
|| !tp
->mechname
)
472 if (strcmp(mp
->mechname
, tp
->mechname
) != 0)
475 if (!mp
->alias
&& !tp
->alias
)
477 if (!mp
->alias
|| !tp
->alias
)
479 if (strcmp(mp
->alias
, tp
->alias
) != 0)
487 sf_copy_mech_ent(mechanism_t
*mp
)
489 mechanism_t
*tp
= calloc(1, sizeof (*mp
));
494 tp
->mechname
= mp
->mechname
? strdup(mp
->mechname
) : NULL
;
495 tp
->alias
= mp
->alias
? strdup(mp
->alias
) : NULL
;
496 tp
->qop
= mp
->qop
? strdup(mp
->qop
) : NULL
;
497 tp
->keylen
= mp
->keylen
;
498 tp
->algtype
= mp
->algtype
;
499 tp
->secserv
= mp
->secserv
;
505 * Return TRUE if the mechname/alias/keylen/algtype combo
506 * already exists in the no dups array. Else return FALSE.
509 member_of_dups(mechanism_t
**t
, const mechanism_t
*mp
)
514 if (equal_entries(mp
, *t
))
521 * Return a list of valid mechanisms ranked by sequence in the NIS+
522 * security conf file. Return NULL if there are no valid entries.
523 * On success, the last pointer of the array of pointers will be NULL.
525 * If input arg 'qop_secserv' is TRUE, include duplicate
526 * mechname/alias/keylen/algtype entries that differ only in the QOP
527 * and security service. Else, duplicates are omitted.
529 * The list of mechanisms are gauranteed to be valid ones installed
532 * This implementation returns copies of the "master" list. The "master"
533 * list will updated if the file is modified.
537 __nis_get_mechanisms(bool_t qop_secserv
)
540 * 'mechs' is the "master" list of valid mechanisms from
541 * the NIS+ security conf file.
542 * 'mechs_no_dups' is the "master" list of valid mechanisms
543 * that differ only in QOP/SecuritySvc fields.
545 static mechanism_t
**mechs
= NULL
;
546 static mechanism_t
**mechs_no_dups
= NULL
;
549 mechanism_t
**tmechs
= NULL
; /* temp mechs */
550 mechanism_t
**tmechs_no_dups
= NULL
; /* temp mechs sans dups */
551 int ent_cnt
= 0; /* valid cf file entry count */
552 int ent_cnt_no_dups
= 0; /* valid cf count, no dups */
553 static uint_t last
= 0;
557 if (stat(NIS_SEC_CF_PATHNAME
, &sbuf
) != 0)
560 (void) mutex_lock(&nis_sec_cf_lock
);
561 if (sbuf
.st_mtime
> last
) {
562 last
= sbuf
.st_mtime
;
565 /* free old master lists */
566 __nis_release_mechanisms(mechs
);
569 mechs
= mechs_no_dups
= NULL
;
571 if (!(fptr
= fopen(NIS_SEC_CF_PATHNAME
, "rF"))) {
572 (void) mutex_unlock(&nis_sec_cf_lock
);
576 while (mp
= get_secfile_ent(fptr
)) {
578 * Make sure entry is either the AUTH_DES compat
579 * one or a valid GSS one that is installed.
581 if (!(AUTH_DES_COMPAT_CHK(mp
) ||
582 (NIS_SEC_CF_GSS_MECH(mp
) &&
583 rpc_gss_is_installed(mp
->mechname
)))) {
588 tmechs
= (mechanism_t
**)
589 list_append_ent((void *)mp
, (void **)tmechs
,
590 ent_cnt
, (void (*)())sf_free_mech_ent
);
591 if (tmechs
== NULL
) {
593 (void) mutex_unlock(&nis_sec_cf_lock
);
597 if (member_of_dups(tmechs_no_dups
, mp
))
601 tmechs_no_dups
= (mechanism_t
**)
602 list_append_ent((void *)mp
, (void **)tmechs_no_dups
,
603 ent_cnt_no_dups
, (void (*)())sf_free_mech_ent
);
604 if (tmechs_no_dups
== NULL
) {
606 (void) mutex_unlock(&nis_sec_cf_lock
);
612 /* set master lists to point to new built ones */
614 mechs_no_dups
= tmechs_no_dups
;
616 (void) mutex_unlock(&nis_sec_cf_lock
);
619 /* return a copy of the list with possible dups */
621 (mechanism_t
**)list_copy(
622 (void *(*)()) sf_copy_mech_ent
,
626 /* return a copy of the list without dups */
627 return (mechs_no_dups
?
628 (mechanism_t
**)list_copy((void *(*)()) sf_copy_mech_ent
,
629 (void **)mechs_no_dups
) :
634 * Search the mechs (no dups array) for an entry (mechname or alias)
635 * that matches (case not sig) the given mechname. On target match,
636 * load the given memory locations pointed to by args keylen and
637 * algtype with values from the matched entry.
639 * The AUTH_DES "compat" line (alias == "des") will return 192-0
640 * (overriding the fields in the conf file).
642 * For any other entry, a conf file field of '-' (not applicable),
643 * in the keylen or algtype field will result in the locations for
644 * keylen and algtype being set to -1. (this is actually done in
645 * __nis_get_mechanisms()).
647 * Returns 0 on success and -1 on failure.
650 __nis_translate_mechanism(const char *mechname
, int *keylen
, int *algtype
)
655 if (!mechname
|| !keylen
|| !algtype
)
659 if (strcmp(mechname
, NIS_SEC_CF_DES_ALIAS
) == 0) {
660 *keylen
= AUTH_DES_KEYLEN
;
661 *algtype
= AUTH_DES_ALGTYPE
;
665 if (!(mpp
= __nis_get_mechanisms(FALSE
)))
669 for (; *mpp
; mpp
++) {
670 mechanism_t
*mp
= *mpp
;
672 (!strcasecmp(mechname
, mp
->mechname
))) {
673 *keylen
= mp
->keylen
;
674 *algtype
= mp
->algtype
;
675 __nis_release_mechanisms(mpp_h
);
679 (!strcasecmp(mechname
, mp
->alias
))) {
680 *keylen
= mp
->keylen
;
681 *algtype
= mp
->algtype
;
682 __nis_release_mechanisms(mpp_h
);
687 __nis_release_mechanisms(mpp_h
);
693 * Translate a mechname to an alias name.
695 * Returns alias on success or NULL on failure.
697 * Note alias will be the nullstring CSTYLE(on success) if cf
698 * alias field was "Not Applicable".
701 __nis_mechname2alias(const char *mechname
, /* in */
702 char *alias
, /* out */
703 size_t bufsize
) /* in */
708 if (!mechname
|| !alias
)
711 if (!(mpp
= __nis_get_mechanisms(FALSE
)))
715 for (; *mpp
; mpp
++) {
716 mechanism_t
*mp
= *mpp
;
720 (strcasecmp(mechname
, mp
->mechname
) == 0)) {
722 if ((len
= strlen(mp
->alias
)) < bufsize
) {
723 (void) strncpy(alias
, mp
->alias
,
725 __nis_release_mechanisms(mpp_h
);
728 } else { /* cf file entry alias field was NA */
730 __nis_release_mechanisms(mpp_h
);
737 __nis_release_mechanisms(mpp_h
);
742 __nis_release_mechanisms(mechanism_t
**mpp
)
744 list_free_all(sf_free_mech_ent
, (void **)mpp
);
748 * Convert an authtype (ie. DH640-0) to mechanism alias (ie. dh640-0).
749 * Input the authtype ptr, the mechalis ptr and the size of the mechalias
752 * If mechalias buf is not large enough, truncate and don't indicate failure.
754 * Return the mechalias ptr on success or NULL on failure CSTYLE(any of
755 * the input args are NULL/0).
758 __nis_authtype2mechalias(
759 const char *authtype
, /* in */
760 char *mechalias
, /* out */
761 size_t mechaliaslen
) /* in */
763 char *dst
= mechalias
;
764 const char *src
= authtype
;
765 const char *max
= src
+ mechaliaslen
;
767 if (!src
|| !dst
|| mechaliaslen
== 0)
770 while (*src
&& src
< max
- 1)
771 *dst
++ = tolower(*src
++);
779 * Convert an mechalias (ie. dh640-0) to authtype (ie. DH640-0).
780 * Input the authtype ptr, the mechalis ptr and the size of the mechalias
783 * A special mechalias of "dh192-0" will get converted to "DES".
785 * If authtype buf is not large enough, truncate and don't indicate failure.
787 * Return the authtype ptr on success or NULL on failure (any of
788 * the input args are NULL/0.
791 __nis_mechalias2authtype(
792 const char *mechalias
, /* in */
793 char *authtype
, /* out */
794 size_t authtypelen
) /* in */
797 const char *src
= mechalias
;
798 char *dst
= authtype
;
799 const char *max
= src
+ authtypelen
;
800 const int slen
= strlen(cf_mech_dh1920_str
);
802 if (!src
|| !dst
|| !authtypelen
)
805 if (strncasecmp(src
, cf_mech_dh1920_str
, slen
+ 1)
807 if (slen
>= authtypelen
)
809 (void) strcpy(authtype
, AUTH_DES_AUTH_TYPE
);
813 while (*src
&& src
< max
- 1)
814 *dst
++ = toupper(*src
++);
822 * Given a DH key length and algorithm type, return the mech
823 * alias string. If the keyalg is not the classic AUTH_DES,
824 * then search the NIS+ security cf.
826 * On success return the mech alias string address. Return
827 * NULL on failure. Failure occurs if keylen or algtype is
828 * not found or the length of the input buf is too small
829 * or input args are bogus. Alias buf will not be
830 * changed on failure.
833 __nis_keyalg2mechalias(
834 keylen_t keylen
, /* in */
835 algtype_t algtype
, /* in */
836 char *alias
, /* out */
837 size_t alias_len
) /* in */
839 mechanism_t
**mechs
; /* array of mechanisms */
844 if (AUTH_DES_KEY(keylen
, algtype
)) {
845 if (alias_len
> strlen(NIS_SEC_CF_DES_ALIAS
)) {
846 (void) strcpy(alias
, NIS_SEC_CF_DES_ALIAS
);
852 if (mechs
= __nis_get_mechanisms(FALSE
)) {
855 for (mpp
= mechs
; *mpp
; mpp
++) {
856 mechanism_t
*mp
= *mpp
;
858 if (!VALID_MECH_ENTRY(mp
) ||
859 AUTH_DES_COMPAT_CHK(mp
))
862 if (keylen
== mp
->keylen
&&
863 algtype
== mp
->algtype
&& mp
->alias
) {
864 int al_len
= strlen(mp
->alias
);
866 if (alias_len
> al_len
) {
867 (void) strncpy(alias
, mp
->alias
,
871 __nis_release_mechanisms(mechs
);
876 __nis_release_mechanisms(mechs
);
883 * Given the key length and algorithm type, return the auth type
884 * string suitable for the cred table.
886 * Return the authtype on success and NULL on failure.
889 __nis_keyalg2authtype(
890 keylen_t keylen
, /* in */
891 algtype_t algtype
, /* in */
892 char *authtype
, /* out */
893 size_t authtype_len
) /* in */
895 char alias
[MECH_MAXALIASNAME
+1] = {0};
898 if (!authtype
|| authtype_len
== 0)
901 if (!__nis_keyalg2mechalias(keylen
, algtype
, alias
, sizeof (alias
)))
904 if (!__nis_mechalias2authtype(alias
, authtype
, authtype_len
))
911 * Return a ptr to the next mech file entry or NULL on EOF.
912 * The caller should free the storage of a successful return.
915 get_mechfile_ent(FILE *fptr
)
920 char line
[MF_MAX_LINELEN
] = {0};
924 while (((cp
= nextline(fptr
, line
)) != NULL
) &&
925 (*cp
== '#' || *cp
== '\0'))
930 if (!(flds
= parse_line(cp
, mech_file_flds_min
,
931 mech_file_flds_max
, MF_MAX_FLDLEN
)))
934 if (!(m
= malloc(sizeof (mfent_t
)))) {
935 free_fields(flds
, mech_file_flds_max
);
939 m
->mechname
= strdup(*flds
);
940 m
->oid
= strdup(*(flds
+ 1));
941 m
->libname
= strdup(*(flds
+ 2));
943 free_fields(flds
, mech_file_flds_max
);
949 mf_copy_ent(mfent_t
*mp
)
951 mfent_t
*tp
= calloc(1, sizeof (*mp
));
956 tp
->mechname
= mp
->mechname
? strdup(mp
->mechname
) : NULL
;
957 tp
->oid
= mp
->oid
? strdup(mp
->oid
) : NULL
;
958 tp
->libname
= mp
->libname
? strdup(mp
->libname
) : NULL
;
965 mf_free_ent(mfent_t
*mp
)
977 mf_free_mechs(mfent_t
**mpp
)
979 list_free_all(mf_free_ent
, (void **)mpp
);
983 * Return a copy of the list of the mech file entries. The ptr to the last
984 * entry will be NULL on success. The master list will be updated when
985 * the mechs file is modified.
987 * Return NULL if the file does not exist or no valid mechs exist in the
993 static mfent_t
**mechs
= NULL
; /* master mechs list */
994 mfent_t
*mp
; /* a mech entry */
995 mfent_t
**tmechs
= NULL
; /* temp mechs list */
996 uint_t ent_cnt
= 0; /* valid cf file entry count */
997 static uint_t last
= 0; /* file last modified date */
1001 if (stat(mech_file
, &sbuf
) != 0)
1004 (void) mutex_lock(&mech_file_lock
);
1005 if (sbuf
.st_mtime
> last
) {
1006 last
= sbuf
.st_mtime
;
1009 /* free old master list */
1010 mf_free_mechs(mechs
);
1014 if (!(fptr
= fopen(mech_file
, "rF"))) {
1015 (void) mutex_unlock(&mech_file_lock
);
1019 while (mp
= get_mechfile_ent(fptr
)) {
1021 tmechs
= (mfent_t
**)list_append_ent((void *)mp
,
1022 (void **)tmechs
, ent_cnt
, (void (*)()) mf_free_ent
);
1023 if (tmechs
== NULL
) {
1024 (void) fclose(fptr
);
1025 (void) mutex_unlock(&mech_file_lock
);
1029 (void) fclose(fptr
);
1031 mechs
= tmechs
; /* set master list to pt to newly built one */
1033 (void) mutex_unlock(&mech_file_lock
);
1035 /* return a copy of the master list */
1036 return (mechs
? (mfent_t
**)list_copy((void *(*)()) mf_copy_ent
,
1037 (void **)mechs
) : NULL
);
1041 * Translate a full mechname to it's corresponding library name
1042 * as specified in the mech file.
1045 mechfile_name2lib(const char *mechname
, char *libname
, int len
)
1047 mfent_t
**mechs
= mf_get_mechs();
1050 if (!mechs
|| !mechname
|| !libname
|| !len
)
1053 for (mpp
= mechs
; *mpp
; mpp
++) {
1056 if (mp
->mechname
&& strcasecmp(mechname
, mp
->mechname
) == 0) {
1057 if (strlen(mp
->libname
) < len
) {
1058 (void) strcpy(libname
, mp
->libname
);
1059 mf_free_mechs(mechs
);
1064 mf_free_mechs(mechs
);
1070 * Given a key length and algo type, return the appro DH mech library
1074 __nis_get_mechanism_library(keylen_t keylen
, algtype_t algtype
,
1075 char *buffer
, size_t buflen
)
1077 char mechname
[MAXDHNAME
+ 1];
1079 if (keylen
== 0 || !buffer
|| buflen
== 0)
1082 (void) snprintf(mechname
, sizeof (mechname
),
1083 "%s_%d_%d", dh_str
, keylen
, algtype
);
1085 if (!mechfile_name2lib(mechname
, buffer
, buflen
))
1092 * Input key length, algorithm type, and a string identifying a symbol
1093 * (example: "__gen_dhkeys").
1095 * Returns a function pointer to the specified symbol in the appropriate
1096 * key length/algorithm type library, or NULL if the symbol isn't found.
1099 __nis_get_mechanism_symbol(keylen_t keylen
,
1101 const char *symname
)
1105 char libname
[MAXDHNAME
+1];
1106 char libpath
[MAXPATHLEN
+1];
1108 if (!__nis_get_mechanism_library(keylen
, algtype
, libname
, MAXDHNAME
))
1111 if (strlen(MECH_LIB_PREFIX
) + strlen(libname
) + 1 > sizeof (libpath
))
1114 (void) snprintf(libpath
, sizeof (libpath
),
1115 "%s%s", MECH_LIB_PREFIX
, libname
);
1117 if (!(handle
= dlopen(libpath
, RTLD_LAZY
)))
1120 return (dlsym(handle
, symname
));