4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
28 * University Copyright- Copyright (c) 1982, 1986, 1988
29 * The Regents of the University of California
32 * University Acknowledgment- Portions of this document are derived from
33 * software developed by the University of California, Berkeley, and its
37 #pragma ident "%Z%%M% %I% %E% SMI"
40 * Do the real work of the keyserver.
41 * Store secret keys. Compute common keys,
42 * and use them to decrypt and encrypt DES keys.
43 * Cache the common keys, so the expensive computation is avoided.
49 #include <rpc/key_prot.h>
50 #include <rpc/des_crypt.h>
51 #include <rpcsvc/nis_dhext.h>
52 #include <sys/errno.h>
58 #include "keyserv_cache.h"
60 extern char ROOTKEY
[];
61 extern mechanism_t
**mechs
;
62 extern char **cache_options
;
63 extern int *cache_size
;
64 extern int disk_caching
;
67 static int hash_keys();
68 static keystatus
pk_crypt();
69 static keystatus
pk_crypt3();
70 static int nodefaultkeys
= 0;
73 #define DESALIAS "dh192-0"
74 #define DHMECHSTR "diffie_hellman"
75 #define CLASSIC_PK_DH(k, a) (((k) == 192) && ((a) == 0))
78 * Exponential caching management
80 struct cachekey_list
{
84 struct cachekey_list
*next
;
86 #define KEY_HASH_SIZE 256
87 static struct cachekey_list
*g_cachedkeys
[KEY_HASH_SIZE
];
88 static rwlock_t g_cachedkeys_lock
= DEFAULTRWLOCK
;
92 test_debug(debug_level level
, char *file
, int line
)
94 if (level
< debugging
)
96 fprintf(stderr
, "file %s,\tline %d :\t", file
, line
);
101 real_debug(char *fmt
, ...)
106 (void) vfprintf(stderr
, fmt
, args
);
108 fprintf(stderr
, "\n");
114 struct cacheuid_list
{
121 struct cacheuid_list
*next
;
124 #define NUMHASHBUCKETS 256
125 #define HASH_UID(x) (x & 0xff)
128 struct cacheuid_list
*bucket
[NUMHASHBUCKETS
];
132 struct cachekey3_list
*common
[NUMHASHBUCKETS
];
137 struct mechdata
*mechdata
;
139 struct psdata
*psdata
;
143 * we don't need to worry about locking for the keylen + algtype
144 * sparse array because it is created once and for all during
145 * initialization when there are no threads. The mechentry field
146 * and everything underneath it needs protection and this is what
147 * the *_lock fields are for.
151 struct algtypelist
*next
;
152 struct mechentry mech
;
157 struct algtypelist
*ap
;
158 struct keylenlist
*next
;
161 #define KEYSERV_VERSION "1.0"
163 static struct mechtable
{
165 struct keylenlist
*kp
;
166 } mechtable
= {KEYSERV_VERSION
, NULL
};
168 static struct keylenlist
**
169 getkeylen(keylen_t k
)
171 struct keylenlist
**kpp
;
173 debug(KEYSERV_DEBUG1
, ("getkeylen key: %d", k
));
174 for (kpp
= &mechtable
.kp
;
175 *kpp
!= NULL
&& (*kpp
)->keylen
!= k
;
177 debug(KEYSERV_DEBUG0
, ("getkeylen failed %x", kpp
));
178 debug(KEYSERV_DEBUG0
, ("getkeylen return: %x", kpp
));
183 appendkeylist(struct keylenlist
**kpp
, keylen_t k
)
185 struct keylenlist
*kp
;
188 kp
= (struct keylenlist
*)malloc(sizeof (*kp
));
190 debug(KEYSERV_INFO
, ("appendkeylist : malloc failed"));
193 debug(KEYSERV_DEBUG
, ("appendkeylist : %x %x %d", kpp
, kp
, k
));
200 /* do nothing; only happens for multiple algtypes */
201 debug(KEYSERV_DEBUG0
,
202 ("appendkeylist called for non tail element"));
206 static struct algtypelist
**
207 getalgtype(struct keylenlist
**kpp
, algtype_t a
)
209 struct algtypelist
**app
;
211 debug(KEYSERV_DEBUG1
, ("getalgtype key: %d", a
));
212 for (app
= &(*kpp
)->ap
;
213 *app
!= NULL
&& (*app
)->algtype
!= a
;
215 debug(KEYSERV_DEBUG0
, ("getalgtype key: %x", app
));
216 debug(KEYSERV_DEBUG0
, ("getalgtype return: %x", app
));
221 appendalgtype(struct algtypelist
**app
, algtype_t a
)
223 struct algtypelist
*ap
;
226 ap
= (struct algtypelist
*)malloc(sizeof (*ap
));
228 debug(KEYSERV_INFO
, ("appendalgtype : malloc failed"));
231 debug(KEYSERV_DEBUG
, ("appendalgtype : %x %x %d", app
, ap
, a
));
233 mutex_init(&ap
->mech
.mech_lock
, USYNC_THREAD
, NULL
);
234 mutex_init(&ap
->mech
.ps_lock
, USYNC_THREAD
, NULL
);
235 ap
->mech
.mechdata
= NULL
;
236 ap
->mech
.psdata
= NULL
;
241 /* don't mind duplicate (keylen,algtype) paris for now. */
242 debug(KEYSERV_DEBUG0
,
243 ("appendalgtype called for non tail element"));
247 static struct mechentry
*
248 getmechtype(keylen_t k
, algtype_t a
)
250 struct keylenlist
**kpp
;
251 struct algtypelist
**app
;
253 debug(KEYSERV_DEBUG1
, ("getmechtype %d %d", k
, a
));
256 debug(KEYSERV_DEBUG0
, ("getmechtype %d not found in keys", k
));
259 app
= getalgtype(kpp
, a
);
261 debug(KEYSERV_DEBUG0
, ("getmechtype %d not found in algs", a
));
264 debug(KEYSERV_DEBUG0
, ("getmechtype found %x", app
));
265 debug(KEYSERV_DEBUG0
, ("getmechtype return %x", &(*app
)->mech
));
266 return (&(*app
)->mech
);
274 debug(KEYSERV_DEBUG
, ("getkeybuf3 malloc %d", k
));
275 buf
= (keybuf3
*) malloc(sizeof (*buf
));
277 debug(KEYSERV_DEBUG
, ("getkeybuf3 malloc failed"));
278 syslog(LOG_ERR
, "file %s line %d: malloc failed",
282 buf
->keybuf3_len
= k
;
283 /* XXX special case k==0 */
285 buf
->keybuf3_val
= NULL
;
287 buf
->keybuf3_val
= (char *)malloc(k
);
288 if (buf
->keybuf3_val
== NULL
) {
289 debug(KEYSERV_DEBUG
, ("getkeybuf3 malloc failed"));
291 syslog(LOG_ERR
, "file %s line %d: malloc failed",
296 debug(KEYSERV_DEBUG1
, ("getkeybuf3 ret %x", buf
));
301 freekeybuf3(keybuf3
*kp
)
303 debug(KEYSERV_DEBUG1
, ("freekeybuf3 %x", kp
));
306 if (kp
->keybuf3_val
) {
307 /* XXX kp->keybuf3_len != 0? */
308 free(kp
->keybuf3_val
);
314 cpykeybuf3(keybuf3
*src
)
321 if ((dst
= getkeybuf3(src
->keybuf3_len
)) == NULL
) {
324 memcpy(dst
->keybuf3_val
, src
->keybuf3_val
, src
->keybuf3_len
);
325 debug(KEYSERV_DEBUG0
, ("cpykeybuf3 ret %x", dst
));
330 setkeybuf3(char *src
, int len
)
334 if ((dst
= getkeybuf3(++len
)) == NULL
) {
337 memcpy(dst
->keybuf3_val
, src
, len
);
342 cmpkeybuf3(keybuf3
*k1
, keybuf3
*k2
)
344 if ((k1
== NULL
) || (k2
== NULL
)) {
345 syslog(LOG_ERR
, "cmpkeybuf3: invalid parameter: %x, %x",
349 if (k1
->keybuf3_len
!= k2
->keybuf3_len
) {
352 return (!memcmp(k1
->keybuf3_val
, k2
->keybuf3_val
, k1
->keybuf3_len
));
356 storekeybuf3(keybuf3
*dst
, keybuf3
*src
)
360 if ((tmp
= cpykeybuf3(src
)) == NULL
) {
364 free(tmp
); /* but not the contents */
365 debug(KEYSERV_DEBUG0
, ("storekeybuf3 ret %d %x",
366 dst
->keybuf3_len
, dst
->keybuf3_val
));
371 getdeskeyarray(int k
)
375 debug(KEYSERV_DEBUG
, ("getdeskeyarray malloc %d", k
));
376 buf
= (deskeyarray
*) malloc(sizeof (*buf
));
378 debug(KEYSERV_DEBUG
, ("getdeskeyarray malloc failed"));
379 syslog(LOG_ERR
, "file %s line %d: malloc failed",
383 buf
->deskeyarray_len
= k
;
384 /* XXX special case k==0 */
386 buf
->deskeyarray_val
= NULL
;
388 buf
->deskeyarray_val
= (des_block
*)
389 malloc(k
* sizeof (des_block
));
390 if (buf
->deskeyarray_val
== NULL
) {
391 debug(KEYSERV_DEBUG
, ("getdeskeyarray malloc failed"));
393 syslog(LOG_ERR
, "file %s line %d: malloc failed",
398 debug(KEYSERV_DEBUG1
, ("getdeskeyarray ret %x", buf
));
403 cpydeskeyarray(deskeyarray
*src
)
410 if ((dst
= getdeskeyarray(src
->deskeyarray_len
)) == NULL
) {
413 memcpy(dst
->deskeyarray_val
, src
->deskeyarray_val
,
414 src
->deskeyarray_len
* sizeof (des_block
));
415 debug(KEYSERV_DEBUG0
, ("cpydeskeyarray ret %x", dst
));
420 storedeskeyarray(deskeyarray
*dst
, deskeyarray
*src
)
424 if ((tmp
= cpydeskeyarray(src
)) == NULL
) {
428 free(tmp
); /* but not the contents */
429 debug(KEYSERV_DEBUG0
, ("storedeskeyarray ret %d %x",
430 dst
->deskeyarray_len
, dst
->deskeyarray_val
));
435 setdeskeyarray(deskeyarray
*dst
, int k
)
439 if ((tmp
= getdeskeyarray(k
)) == NULL
) {
443 free(tmp
); /* but not the contents */
444 debug(KEYSERV_DEBUG0
, ("setdeskeyarray ret %d %x",
445 dst
->deskeyarray_len
, dst
->deskeyarray_val
));
450 cachehit3(keybuf3
*public, keybuf3
*secret
, struct cachekey3_list
*cp
)
452 return (cmpkeybuf3(public, cp
->public) &&
453 cmpkeybuf3(secret
, cp
->secret
));
456 static struct cacheuid_list
**
457 mapuid2cache(uid_t uid
, struct mechdata
*mdp
)
459 struct cacheuid_list
**cpp
;
460 int hash
= HASH_UID(uid
);
462 debug(KEYSERV_DEBUG
, ("mapuid2cache %d %d %x", uid
, hash
, mdp
));
463 for (cpp
= &mdp
->bucket
[hash
];
464 *cpp
!= NULL
&& (*cpp
)->uid
!= uid
;
465 cpp
= &(*cpp
)->next
) {
466 debug(KEYSERV_DEBUG0
, ("mapuid2cache %x", cpp
));
468 debug(KEYSERV_DEBUG
, ("mapuid2cache ret %x", cpp
));
473 appendsecretkey3(struct mechentry
*mp
, uid_t uid
, setkeyarg3
*skey
)
475 struct mechdata
*mdp
;
476 struct cacheuid_list
**cpp
, *cp
;
477 keybuf3 nullkey
= {0, NULL
};
479 debug(KEYSERV_DEBUG
, ("appendsecretkey3 %x", mp
));
480 if ((skey
== NULL
) || (mp
== NULL
)) {
483 if (skey
->key
.keybuf3_len
== 0) {
486 mutex_lock(&mp
->mech_lock
);
487 if ((mdp
= mp
->mechdata
) == NULL
) {
488 mdp
= (struct mechdata
*)calloc(1, sizeof (*mdp
));
490 mutex_unlock(&mp
->mech_lock
);
492 ("appendsecretkey3 : calloc failed"));
497 cpp
= mapuid2cache(uid
, mdp
);
499 cp
= (struct cacheuid_list
*)malloc(sizeof (*cp
));
501 mutex_unlock(&mp
->mech_lock
);
503 ("appendsecretkey3 : malloc failed"));
504 syslog(LOG_ERR
, "file %s line %d: malloc failed",
508 memset(cp
, 0, sizeof (*cp
));
514 freekeybuf3(cp
->secretkey
);
515 if ((cp
->secretkey
= cpykeybuf3(&skey
->key
)) == NULL
) {
516 mutex_unlock(&mp
->mech_lock
);
519 freekeybuf3(cp
->publickey
);
520 if ((cp
->publickey
= cpykeybuf3(&nullkey
)) == NULL
) {
521 mutex_unlock(&mp
->mech_lock
);
524 mutex_unlock(&mp
->mech_lock
);
529 * Store the vers 3 secretkey for this uid
532 storesecretkey3(uid_t uid
, setkeyarg3
*skey
)
534 struct mechentry
*mp
;
539 if ((mp
= getmechtype(skey
->keylen
, skey
->algtype
)) == NULL
) {
542 return (appendsecretkey3(mp
, uid
, skey
));
546 * Set the vers 3 secretkey key for this uid
549 pk_setkey3(uid_t uid
, setkeyarg3
*skey
)
551 if (!storesecretkey3(uid
, skey
)) {
552 return (KEY_SYSTEMERR
);
554 return (KEY_SUCCESS
);
558 * Set the secretkey key for this uid
565 int storesecretkey(uid_t
, keybuf
);
567 if (!storesecretkey(uid
, skey
)) {
568 return (KEY_SYSTEMERR
);
570 return (KEY_SUCCESS
);
574 storeotherrootkeys(FILE *fp
, char *netname
, char *passwd
, char *osecret
)
577 struct keylenlist
*kp
;
578 struct algtypelist
*ap
;
582 debug(KEYSERV_DEBUG
, ("storeotherrootkeys %s %s",
584 passwd2des_g(passwd
, netname
, strlen(netname
), &master
, FALSE
);
585 for (kp
= mechtable
.kp
; kp
!= NULL
; kp
= kp
->next
) {
586 debug(KEYSERV_DEBUG0
,
587 ("storeotherrootkeys key %d", kp
->keylen
));
588 for (ap
= kp
->ap
; ap
!= NULL
; ap
= ap
->next
) {
590 ("storeotherrootkeys alg: %d", ap
->algtype
));
591 if ((secret
= getkeybuf3(kp
->keylen
/4+1)) == NULL
) {
595 ("storeotherrootkeys calling getsecretkey_g"));
596 if (!getsecretkey_g(netname
,
597 kp
->keylen
, ap
->algtype
,
598 secret
->keybuf3_val
, secret
->keybuf3_len
,
601 ("Can't find %s's secret key", netname
));
604 if (*secret
->keybuf3_val
== 0) { /* XXX */
606 ("Password does not decrypt secret key for %s",
611 free(secret
); /* but not the buffer it points to */
612 skey
.userkey
= master
;
613 skey
.keylen
= kp
->keylen
;
614 skey
.algtype
= ap
->algtype
;
615 if (CLASSIC_PK_DH(kp
->keylen
, ap
->algtype
)) {
616 pk_setkey((uid_t
)0, osecret
);
617 fprintf(fp
, "%s\n", osecret
);
619 if (pk_setkey3(0, &skey
) != KEY_SUCCESS
) {
622 if (!CLASSIC_PK_DH(kp
->keylen
, ap
->algtype
)) {
623 fprintf(fp
, "%s %d\n", skey
.key
.keybuf3_val
,
632 * prohibit the nobody key on this machine k (the -d flag)
642 freedisklist(struct cacheuid_list
*cp
)
647 free(cp
->netname
); /* ok even if this is NULL */
648 freekeybuf3(cp
->secretkey
);
649 freekeybuf3(cp
->publickey
);
655 struct keylenlist
*kp
;
656 struct algtypelist
*ap
;
657 struct mechdata
*mdp
;
658 struct cacheuid_list
**cpp
, *cp
;
660 debug(KEYSERV_DEBUG
, ("pk_clear3 %d", uid
));
661 for (kp
= mechtable
.kp
; kp
!= NULL
; kp
= kp
->next
) {
662 debug(KEYSERV_DEBUG0
, ("pk_clear3 key %d", kp
->keylen
));
663 for (ap
= kp
->ap
; ap
!= NULL
; ap
= ap
->next
) {
664 debug(KEYSERV_DEBUG0
,
665 ("pk_clear3 alg: %d", ap
->algtype
));
666 mutex_lock(&ap
->mech
.mech_lock
);
667 if ((mdp
= ap
->mech
.mechdata
) == NULL
) {
668 mutex_unlock(&ap
->mech
.mech_lock
);
671 cpp
= mapuid2cache(uid
, mdp
);
673 mutex_unlock(&ap
->mech
.mech_lock
);
679 mutex_unlock(&ap
->mech
.mech_lock
);
682 /* XXX clear stuff out of the common key cache as well? */
683 /* XXX return success only if something was removed? */
684 return (KEY_SUCCESS
);
688 * Set the modulus for all our Diffie-Hellman operations
694 MODULUS
= mp_xtom(modx
);
699 * Encrypt the key using the public key associated with remote_name and the
700 * secret key associated with uid.
703 pk_encrypt(uid
, remote_name
, remote_key
, key
)
709 return (pk_crypt(uid
, remote_name
, remote_key
, key
, DES_ENCRYPT
));
713 * Encrypt the key using the public key associated with remote_name and the
714 * secret key associated with uid using vers 3
723 return (pk_crypt3(uid
, arg
, key
, DES_ENCRYPT
));
727 * Decrypt the key using the public key associated with remote_name and the
728 * secret key associated with uid.
731 pk_decrypt(uid
, remote_name
, remote_key
, key
)
737 return (pk_crypt(uid
, remote_name
, remote_key
, key
, DES_DECRYPT
));
741 * Decrypt the key using the public key associated with remote_name and the
742 * secret key associated with uid using vers 3
751 return (pk_crypt3(uid
, arg
, key
, DES_DECRYPT
));
755 * Key storage management
760 struct secretkey_netname_list
{
762 key_netstarg keynetdata
;
764 struct secretkey_netname_list
*next
;
767 #define HASH_UID(x) (x & 0xff)
768 static struct secretkey_netname_list
*g_secretkey_netname
[KEY_HASH_SIZE
];
769 static rwlock_t g_secretkey_netname_lock
= DEFAULTRWLOCK
;
772 * Store the keys and netname for this uid
775 store_netname(uid
, netstore
)
777 key_netstarg
*netstore
;
779 struct secretkey_netname_list
*new;
780 struct secretkey_netname_list
**l
;
781 int hash
= HASH_UID(uid
);
783 (void) rw_wrlock(&g_secretkey_netname_lock
);
784 for (l
= &g_secretkey_netname
[hash
]; *l
!= NULL
&& (*l
)->uid
!= uid
;
788 /* LINTED pointer alignment */
789 new = (struct secretkey_netname_list
*)malloc(sizeof (*new));
791 (void) rw_unlock(&g_secretkey_netname_lock
);
799 if (new->keynetdata
.st_netname
)
800 (void) free(new->keynetdata
.st_netname
);
802 memcpy(new->keynetdata
.st_priv_key
, netstore
->st_priv_key
,
804 memcpy(new->keynetdata
.st_pub_key
, netstore
->st_pub_key
, HEXKEYBYTES
);
806 if (netstore
->st_netname
)
807 new->keynetdata
.st_netname
= strdup(netstore
->st_netname
);
809 new->keynetdata
.st_netname
= (char *)NULL
;
810 new->sc_flag
= KEY_NAME
;
811 (void) rw_unlock(&g_secretkey_netname_lock
);
817 appendnetname3(struct mechentry
*mp
, uid_t uid
, key_netstarg3
*net
)
819 struct mechdata
*mdp
;
820 struct cacheuid_list
**cpp
, *cp
;
822 debug(KEYSERV_DEBUG
, ("appendnetname3 %x", mp
));
823 if ((mp
== NULL
) || (net
== NULL
)) {
826 mutex_lock(&mp
->mech_lock
);
827 if ((mdp
= mp
->mechdata
) == NULL
) {
828 mdp
= (struct mechdata
*)calloc(1, sizeof (*mdp
));
830 mutex_unlock(&mp
->mech_lock
);
831 debug(KEYSERV_INFO
, ("appendnetname3 : calloc failed"));
836 cpp
= mapuid2cache(uid
, mdp
);
838 cp
= (struct cacheuid_list
*)malloc(sizeof (*cp
));
840 mutex_unlock(&mp
->mech_lock
);
841 debug(KEYSERV_INFO
, ("appendnetname3 : malloc failed"));
842 syslog(LOG_ERR
, "file %s line %d: malloc failed",
846 memset(cp
, 0, sizeof (*cp
));
852 freekeybuf3(cp
->secretkey
);
853 if ((cp
->secretkey
= cpykeybuf3(&net
->st_priv_key
)) == NULL
) {
854 mutex_unlock(&mp
->mech_lock
);
857 freekeybuf3(cp
->publickey
);
858 if ((cp
->publickey
= cpykeybuf3(&net
->st_pub_key
)) == NULL
) {
859 mutex_unlock(&mp
->mech_lock
);
863 if (net
->st_netname
) {
864 cp
->netname
= strdup(net
->st_netname
);
866 cp
->netname
= (char *)NULL
;
868 mutex_unlock(&mp
->mech_lock
);
873 pk_netput(uid
, netstore
)
875 key_netstarg
*netstore
;
878 if (!store_netname(uid
, netstore
)) {
879 return (KEY_SYSTEMERR
);
881 return (KEY_SUCCESS
);
885 * Store the keys and netname for this uid vers 3
888 store_netname3(uid_t uid
, key_netstarg3
*net
)
890 struct mechentry
*mp
;
891 key_netstarg netstore
;
896 if ((mp
= getmechtype(net
->keylen
, net
->algtype
)) == NULL
) {
899 if (uid
== 0 && CLASSIC_PK_DH(net
->keylen
, net
->algtype
)) {
900 memcpy(netstore
.st_priv_key
, net
->st_priv_key
.keybuf3_val
,
902 memset(netstore
.st_pub_key
, 0, HEXKEYBYTES
);
903 netstore
.st_netname
= net
->st_netname
;
904 if (pk_netput(uid
, &netstore
) != KEY_SUCCESS
) {
905 (void) fprintf(stderr
,
906 "keyserv: could not set root's key and netname.\n");
910 return (appendnetname3(mp
, uid
, net
));
914 pk_netput3(uid_t uid
, key_netstarg3
*netstore
)
917 if (!store_netname3(uid
, netstore
)) {
918 return (KEY_SYSTEMERR
);
920 return (KEY_SUCCESS
);
924 addmasterkey(char *master
, char *netname
, algtype_t algtype
)
926 keybuf3
*secret
, *public;
927 int bytelen
= strlen(master
);
928 keylen_t keylen
= bytelen
*4;
931 if ((secret
= setkeybuf3(master
, bytelen
)) == NULL
) {
934 if ((public = getkeybuf3(bytelen
+1)) == NULL
) {
935 /* the +1 is mandated by getpublickey_g() */
939 * getpublickey_g(netname, keylen, algtype,
940 * public->keybuf3_val, public->keybuf3_len);
941 * cannot be called since rpc.nisd is not up yet
942 * so we continue to return a zero filled public key
943 * as in the earlier version
945 memset(public->keybuf3_val
, 0, bytelen
+1);
946 tmp
.st_priv_key
= *secret
;
948 tmp
.st_pub_key
= *public;
950 tmp
.st_netname
= strdup(netname
);
952 tmp
.algtype
= algtype
;
953 return (store_netname3(0, &tmp
));
957 * Fetch the keys and netname for this uid
960 fetch_netname(uid
, key_netst
)
962 struct key_netstarg
*key_netst
;
964 struct secretkey_netname_list
*l
;
965 int hash
= HASH_UID(uid
);
967 (void) rw_rdlock(&g_secretkey_netname_lock
);
968 for (l
= g_secretkey_netname
[hash
]; l
!= NULL
; l
= l
->next
) {
969 if ((l
->uid
== uid
) && (l
->sc_flag
== KEY_NAME
)) {
971 memcpy(key_netst
->st_priv_key
,
972 l
->keynetdata
.st_priv_key
, HEXKEYBYTES
);
974 memcpy(key_netst
->st_pub_key
,
975 l
->keynetdata
.st_pub_key
, HEXKEYBYTES
);
977 if (l
->keynetdata
.st_netname
)
978 strcpy(key_netst
->st_netname
,
979 l
->keynetdata
.st_netname
);
981 key_netst
->st_netname
= NULL
;
982 (void) rw_unlock(&g_secretkey_netname_lock
);
986 (void) rw_unlock(&g_secretkey_netname_lock
);
991 remove_ref(struct cacheuid_list
*cp
)
993 debug(KEYSERV_DEBUG0
, ("remove_ref %x", cp
));
996 * if we are going to do this along the lines of vn_rele,
997 * more stuff needs to be done here and the access to refcnt
998 * needs to be mutex locked. Keep it simple for now.
1004 add_ref(struct cacheuid_list
**cpp
)
1006 struct cacheuid_list
*cp
;
1011 /*LINTED assignment operator "=" found where "==" was expected*/
1013 debug(KEYSERV_DEBUG0
, ("add_ref %x", cp
));
1018 static struct cacheuid_list
*
1019 getcachekey3(uid_t uid
, struct mechentry
*mp
)
1021 struct cacheuid_list
**cpp
, *cp
;
1022 struct mechdata
*mdp
;
1024 debug(KEYSERV_DEBUG1
, ("getcachekey3 %d %x", uid
, mp
));
1028 mutex_lock(&mp
->mech_lock
);
1029 if ((mdp
= mp
->mechdata
) == NULL
) {
1030 mutex_unlock(&mp
->mech_lock
);
1031 debug(KEYSERV_DEBUG0
, ("getcachekey3 ret 0"));
1034 cpp
= mapuid2cache(uid
, mdp
);
1037 mutex_unlock(&mp
->mech_lock
);
1038 debug(KEYSERV_DEBUG0
, ("getcachekey3 ret %x", *cpp
));
1043 * Fetch any available cache for this uid (vers 3)
1045 static struct cacheuid_list
*
1046 getanycache3(uid_t uid
)
1048 struct keylenlist
*kp
;
1049 struct algtypelist
*ap
;
1050 struct mechdata
*mdp
;
1051 struct cacheuid_list
**cpp
, *cp
;
1053 debug(KEYSERV_DEBUG
, ("getanycache3 %d", uid
));
1054 for (kp
= mechtable
.kp
; kp
!= NULL
; kp
= kp
->next
) {
1055 debug(KEYSERV_DEBUG0
, ("getanycache3 key %d", kp
->keylen
));
1056 for (ap
= kp
->ap
; ap
!= NULL
; ap
= ap
->next
) {
1057 debug(KEYSERV_DEBUG0
,
1058 ("getanycache3 alg: %d", ap
->algtype
));
1059 mutex_lock(&ap
->mech
.mech_lock
);
1060 if ((mdp
= ap
->mech
.mechdata
) == NULL
) {
1061 mutex_unlock(&ap
->mech
.mech_lock
);
1064 cpp
= mapuid2cache(uid
, mdp
);
1066 mutex_unlock(&ap
->mech
.mech_lock
);
1071 mutex_unlock(&ap
->mech
.mech_lock
);
1078 static struct cacheuid_list
*
1079 fetchcache3(uid_t uid
, keylen_t k
, algtype_t a
)
1081 struct mechentry
*mp
;
1082 struct cacheuid_list
*cp
;
1084 debug(KEYSERV_DEBUG
, ("fetchcache3 %d %d %d", uid
, k
, a
));
1085 if ((mp
= getmechtype(k
, a
)) == NULL
) {
1088 if ((cp
= getcachekey3(uid
, mp
)) == NULL
) {
1091 debug(KEYSERV_DEBUG
, ("fetchcache3 ret %x", cp
));
1096 * Fetch the keys and netname for this uid vers 3
1099 fetch_netname3(uid_t uid
, mechtype
*net
, key_netstarg3
*ret
)
1101 struct cacheuid_list
*cp
;
1103 if ((net
== NULL
) || (ret
== NULL
)) {
1106 debug(KEYSERV_DEBUG
, ("fetch_netname3 %d %d %d",
1107 uid
, net
->keylen
, net
->algtype
));
1108 if (net
->keylen
== 0) {
1109 cp
= getanycache3(uid
);
1111 cp
= fetchcache3(uid
, net
->keylen
, net
->algtype
);
1113 debug(KEYSERV_DEBUG
, ("fetch_netname3 cp %x", cp
));
1117 debug(KEYSERV_DEBUG
, ("fetch_netname3 sec %x", cp
->secretkey
));
1118 if (!storekeybuf3(&ret
->st_priv_key
, cp
->secretkey
)) {
1121 debug(KEYSERV_DEBUG
, ("fetch_netname3 pub %x", cp
->publickey
));
1122 if (!storekeybuf3(&ret
->st_pub_key
, cp
->publickey
)) {
1126 debug(KEYSERV_DEBUG
, ("fetch_netname3 net %s", cp
->netname
));
1127 ret
->st_netname
= strdup(cp
->netname
);
1129 ret
->st_netname
= NULL
;
1136 pk_netget(uid
, netstore
)
1138 key_netstarg
*netstore
;
1140 if (!fetch_netname(uid
, netstore
)) {
1141 return (KEY_SYSTEMERR
);
1143 return (KEY_SUCCESS
);
1147 pk_netget3(uid_t uid
, mechtype
*net
, key_netstarg3
*ret
)
1149 if (!fetch_netname3(uid
, net
, ret
)) {
1150 return (KEY_SYSTEMERR
);
1152 return (KEY_SUCCESS
);
1155 #define cachehit(pub, sec, list) \
1156 (memcmp(pub, (list)->public, sizeof (keybuf)) == 0 && \
1157 memcmp(sec, (list)->secret, sizeof (keybuf)) == 0)
1160 * Try to find the common key in the cache
1163 readcache(pub
, sec
, deskey
, hash
)
1169 register struct cachekey_list
**l
;
1171 for (l
= &g_cachedkeys
[hash
]; (*l
) != NULL
&& !cachehit(pub
, sec
, *l
);
1176 *deskey
= (*l
)->deskey
;
1181 * cache result of expensive multiple precision exponential operation
1184 writecache(pub
, sec
, deskey
, hash
)
1190 struct cachekey_list
*new;
1192 new = (struct cachekey_list
*)malloc(sizeof (struct cachekey_list
));
1196 memcpy(new->public, pub
, sizeof (keybuf
));
1197 memcpy(new->secret
, sec
, sizeof (keybuf
));
1198 new->deskey
= *deskey
;
1200 new->next
= g_cachedkeys
[hash
];
1201 g_cachedkeys
[hash
] = new;
1206 * Choose middle 64 bits of the common key to use as our des key, possibly
1207 * overwriting the lower order bits by setting parity.
1210 extractdeskey(ck
, deskey
)
1214 void _mp_move(MINT
*, MINT
*);
1218 short base
= (1 << 8);
1223 for (i
= 0; i
< ((KEYSIZE
- 64) / 2) / 8; i
++) {
1224 mp_sdiv(a
, base
, a
, &r
);
1227 for (i
= 0; i
< 8; i
++) {
1228 mp_sdiv(a
, base
, a
, &r
);
1232 des_setparity((char *)deskey
);
1237 fetchsecretkey(uid
, buf
)
1241 struct secretkey_netname_list
*l
;
1242 int hash
= HASH_UID(uid
);
1244 (void) rw_rdlock(&g_secretkey_netname_lock
);
1245 for (l
= g_secretkey_netname
[hash
]; l
!= NULL
; l
= l
->next
) {
1246 if (l
->uid
== uid
) {
1247 memcpy(buf
, l
->keynetdata
.st_priv_key
,
1249 (void) rw_unlock(&g_secretkey_netname_lock
);
1253 (void) rw_unlock(&g_secretkey_netname_lock
);
1258 fetchsecretkey3(uid_t uid
, keylen_t k
, algtype_t a
)
1260 struct cacheuid_list
*cp
;
1262 debug(KEYSERV_DEBUG
, ("fetchsecretkey3 %d %d %d", uid
, k
, a
));
1263 if ((cp
= fetchcache3(uid
, k
, a
)) == NULL
) {
1266 debug(KEYSERV_DEBUG
, ("fetchsecretkey3 ret %x", cp
->secretkey
));
1267 return (cp
->secretkey
);
1271 * Do the work of pk_encrypt && pk_decrypt
1274 pk_crypt(uid
, remote_name
, remote_key
, key
, mode
)
1291 if (!fetchsecretkey(uid
, xsecret
) || xsecret
[0] == 0) {
1292 memset(zero
, 0, sizeof (zero
));
1294 return (KEY_NOSECRET
);
1296 if (!getsecretkey("nobody", xsecret
, zero
) || xsecret
[0] == 0) {
1297 return (KEY_NOSECRET
);
1301 memcpy(xpublic
, remote_key
->n_bytes
, remote_key
->n_len
);
1303 if (!getpublickey(remote_name
, xpublic
)) {
1304 if (nodefaultkeys
|| !getpublickey("nobody", xpublic
))
1305 return (KEY_UNKNOWN
);
1309 xsecret
[HEXKEYBYTES
] = '\0';
1310 xpublic
[HEXKEYBYTES
] = '\0';
1312 hash
= hash_keys(xpublic
, xsecret
);
1313 (void) rw_rdlock(&g_cachedkeys_lock
);
1314 if (!readcache(xpublic
, xsecret
, &deskey
, hash
)) {
1315 (void) rw_unlock(&g_cachedkeys_lock
);
1316 (void) rw_wrlock(&g_cachedkeys_lock
);
1317 if (!readcache(xpublic
, xsecret
, &deskey
, hash
)) {
1318 public = mp_xtom(xpublic
);
1319 secret
= mp_xtom(xsecret
);
1320 /* Sanity Check on public and private keys */
1321 if (public == NULL
|| secret
== NULL
) {
1322 (void) rw_unlock(&g_cachedkeys_lock
);
1323 return (KEY_SYSTEMERR
);
1325 common
= mp_itom(0);
1326 mp_pow(public, secret
, MODULUS
, common
);
1327 extractdeskey(common
, &deskey
);
1328 writecache(xpublic
, xsecret
, &deskey
, hash
);
1334 (void) rw_unlock(&g_cachedkeys_lock
);
1336 err
= ecb_crypt((char *)&deskey
, (char *)key
, sizeof (des_block
),
1338 if (DES_FAILED(err
)) {
1339 return (KEY_SYSTEMERR
);
1341 return (KEY_SUCCESS
);
1345 hash_keys3(keybuf3
*p
, keybuf3
*s
)
1349 char *pub
= p
->keybuf3_val
;
1350 char *sec
= s
->keybuf3_val
;
1352 debug(KEYSERV_DEBUG
, ("hash_keys3 public %d %s",
1353 p
->keybuf3_len
, pub
));
1354 debug(KEYSERV_DEBUG
, ("hash_keys3 secret %d %s",
1355 s
->keybuf3_len
, sec
));
1356 for (i
= 0; i
< s
->keybuf3_len
; i
+= 6, pub
+= 6, sec
+= 6) {
1360 debug(KEYSERV_DEBUG
, ("hash_keys3 ret %d", hash
& 0xff));
1361 return (hash
& 0xff);
1364 static struct cachekey3_list
**
1365 map_ps2cache(keybuf3
*public, keybuf3
*secret
, struct psdata
*pdp
)
1367 struct cachekey3_list
**cpp
;
1368 int hash
= hash_keys3(public, secret
);
1370 debug(KEYSERV_DEBUG
, ("map_ps2cache %x %d", pdp
, hash
));
1371 for (cpp
= &pdp
->common
[hash
];
1372 *cpp
!= NULL
&& !(cachehit3(public, secret
, *cpp
));
1373 cpp
= &(*cpp
)->next
) {
1374 debug(KEYSERV_DEBUG0
, ("map_ps2cache %x", cpp
));
1376 debug(KEYSERV_DEBUG
, ("map_ps2cache ret %x", cpp
));
1380 static struct cachekey3_list
*
1390 struct mechentry
*mp
;
1392 struct cachekey3_list
**cpp
, *cp
, *cachep
;
1393 struct cacheuid_list
*cu
;
1397 debug(KEYSERV_DEBUG
, ("getdeskey3 %d %d %d %x %x",
1398 keylen
, algtype
, desarylen
, public, secret
));
1399 if ((mp
= getmechtype(keylen
, algtype
)) == NULL
) {
1402 (void) mutex_lock(&mp
->ps_lock
);
1403 if ((pdp
= mp
->psdata
) == NULL
) {
1404 if ((pdp
= (struct psdata
*)calloc(1, sizeof (*pdp
))) ==
1406 mutex_unlock(&mp
->ps_lock
);
1407 debug(KEYSERV_INFO
, ("getdeskey3 : calloc failed"));
1412 debug(KEYSERV_DEBUG
, ("getdeskey3 %x", pdp
));
1413 cpp
= map_ps2cache(public, secret
, pdp
);
1415 debug(KEYSERV_DEBUG
, ("getdeskey3 calling fetchcache3"));
1417 (cu
= fetchcache3(uid
, keylen
, algtype
)) != NULL
) {
1418 debug(KEYSERV_DEBUG
,
1419 ("getdeskey3 calling cache_retrieve"));
1420 if ((cachep
= cache_retrieve(keylen
, algtype
, uid
,
1421 public, cu
->key
)) != NULL
) {
1422 if (cmpkeybuf3(cachep
->secret
, cu
->secretkey
)) {
1425 debug(KEYSERV_DEBUG
,
1426 ("getdeskey3 calling cache_remove"));
1427 cache_remove(keylen
, algtype
,
1435 if ((cp
= (struct cachekey3_list
*)
1436 malloc(sizeof (*cp
))) == NULL
) {
1437 mutex_unlock(&mp
->ps_lock
);
1439 ("getdeskey3 : malloc failed"));
1441 "file %s line %d: malloc failed",
1442 __FILE__
, __LINE__
);
1447 if ((cp
->public = cpykeybuf3(public)) == NULL
) {
1448 mutex_unlock(&mp
->ps_lock
);
1451 if ((cp
->secret
= cpykeybuf3(secret
)) == NULL
) {
1452 mutex_unlock(&mp
->ps_lock
);
1455 if (!setdeskeyarray(&cp
->deskey
, desarylen
)) {
1456 mutex_unlock(&mp
->ps_lock
);
1459 debug(KEYSERV_DEBUG
, ("getdeskey3 %x %x %x",
1460 cp
->public, cp
->secret
,
1461 cp
->deskey
.deskeyarray_val
));
1462 debug(KEYSERV_DEBUG
,
1463 ("getdeskey3 calling __gen_common_dhkeys_g"));
1464 if (!__gen_common_dhkeys_g(public->keybuf3_val
,
1465 secret
->keybuf3_val
,
1467 cp
->deskey
.deskeyarray_val
, desarylen
)) {
1468 mutex_unlock(&mp
->ps_lock
);
1471 for (i
= 0; i
< desarylen
; i
++) {
1472 debug(KEYSERV_DEBUG0
,
1473 ("getdeskey3 gendh key : (%x,%x)",
1474 cp
->deskey
.deskeyarray_val
[i
].key
.high
,
1475 cp
->deskey
.deskeyarray_val
[i
].key
.low
));
1477 if (disk_caching
&& cu
!= NULL
) {
1478 debug(KEYSERV_DEBUG
,
1479 ("getdeskey3 calling cache_insert"));
1480 cache_insert(keylen
, algtype
, uid
, cp
->deskey
,
1481 cu
->key
, public, secret
);
1489 mutex_unlock(&mp
->ps_lock
);
1490 debug(KEYSERV_DEBUG
, ("getdeskey3 ret %x", cp
));
1495 pk_get_conv_key3(uid_t uid
, deskeyarg3
*arg
, cryptkeyres3
*res
)
1497 keybuf3
*xsecret
, *xpublic
;
1499 struct cachekey3_list
*cp
;
1501 debug(KEYSERV_DEBUG
, ("pk_get_conv_key3 %d %x %x",
1503 if ((xsecret
= fetchsecretkey3(uid
,
1504 arg
->keylen
, arg
->algtype
)) == NULL
) {
1506 return (KEY_NOSECRET
);
1507 memset(zero
, 0, sizeof (zero
));
1508 if ((xsecret
= getkeybuf3(arg
->keylen
/4+1)) == NULL
) {
1509 return (KEY_SYSTEMERR
);
1511 debug(KEYSERV_DEBUG
,
1512 ("pk_get_conv_key3 calling getsecretkey_g"));
1513 if (!getsecretkey_g("nobody",
1514 arg
->keylen
, arg
->algtype
,
1515 xsecret
->keybuf3_val
, xsecret
->keybuf3_len
,
1516 zero
) || *xsecret
->keybuf3_val
== 0) { /* XXX */
1517 debug(KEYSERV_DEBUG
,
1518 ("pk_get_conv_key3 calling getsecretkey_g failed"));
1519 return (KEY_NOSECRET
);
1521 debug(KEYSERV_DEBUG
,
1522 ("pk_get_conv_key3 calling getsecretkey_g succeeded"));
1524 xpublic
= &arg
->pub_key
;
1525 if ((cp
= getdeskey3(arg
->keylen
, arg
->algtype
, arg
->nkeys
,
1526 xpublic
, xsecret
, uid
)) == NULL
) {
1527 return (KEY_SYSTEMERR
);
1529 storedeskeyarray(&res
->cryptkeyres3_u
.deskey
, &cp
->deskey
);
1530 return (KEY_SUCCESS
);
1534 * Do the work of pk_encrypt3 && pk_decrypt3
1544 keybuf3
*xsecret
= NULL
, *xpublic
= NULL
;
1546 struct cachekey3_list
*cp
;
1548 int xsecret_alloc
= 0;
1552 debug(KEYSERV_DEBUG1
, ("pk_crypt3 %d %x %x %d",
1553 uid
, arg
, key
, mode
));
1554 if ((xsecret
= fetchsecretkey3(uid
,
1555 arg
->keylen
, arg
->algtype
)) == NULL
) {
1557 return (KEY_NOSECRET
);
1558 memset(zero
, 0, sizeof (zero
));
1559 if ((xsecret
= getkeybuf3(arg
->keylen
/4+1)) == NULL
) {
1560 return (KEY_SYSTEMERR
);
1563 debug(KEYSERV_DEBUG1
, ("pk_crypt3 calling getsecretkey_g"));
1564 if (!getsecretkey_g("nobody",
1565 arg
->keylen
, arg
->algtype
,
1566 xsecret
->keybuf3_val
, xsecret
->keybuf3_len
,
1567 zero
) || *xsecret
->keybuf3_val
== 0) { /* XXX */
1568 debug(KEYSERV_DEBUG
,
1569 ("pk_crypt3 calling getsecretkey_g failed"));
1570 freekeybuf3(xsecret
);
1571 return (KEY_NOSECRET
);
1573 /* XXX optimize to cache nobody's secret key? */
1574 debug(KEYSERV_DEBUG0
,
1575 ("pk_crypt3 calling getsecretkey_g succeeded"));
1577 if (arg
->remotekey
.keybuf3_len
) {
1578 if ((xpublic
= cpykeybuf3(&arg
->remotekey
)) == NULL
) {
1579 if (xsecret_alloc
) freekeybuf3(xsecret
);
1580 return (KEY_SYSTEMERR
);
1583 if ((xpublic
= getkeybuf3(arg
->keylen
/4+1)) == NULL
) {
1584 if (xsecret_alloc
) freekeybuf3(xsecret
);
1585 return (KEY_SYSTEMERR
);
1587 debug(KEYSERV_DEBUG1
, ("pk_crypt3 calling getpublickey_g"));
1588 if (!getpublickey_g(arg
->remotename
,
1589 arg
->keylen
, arg
->algtype
,
1590 xpublic
->keybuf3_val
, xpublic
->keybuf3_len
)) {
1591 debug(KEYSERV_DEBUG0
,
1592 ("pk_crypt3 calling getpublickey_g nobody"));
1593 if (nodefaultkeys
|| !getpublickey_g("nobody",
1594 arg
->keylen
, arg
->algtype
,
1595 xpublic
->keybuf3_val
, xpublic
->keybuf3_len
)) {
1596 debug(KEYSERV_DEBUG
,
1597 ("pk_crypt3 calling getpublickey_g nobody failed"));
1598 if (xsecret_alloc
) freekeybuf3(xsecret
);
1599 freekeybuf3(xpublic
);
1600 return (KEY_UNKNOWN
);
1603 debug(KEYSERV_DEBUG0
,
1604 ("pk_crypt3 calling getpublickey_g succeeded"));
1607 if ((cp
= getdeskey3(arg
->keylen
, arg
->algtype
,
1608 arg
->deskey
.deskeyarray_len
, xpublic
, xsecret
, uid
)) == NULL
) {
1609 if (xsecret_alloc
) freekeybuf3(xsecret
);
1610 freekeybuf3(xpublic
);
1611 return (KEY_SYSTEMERR
);
1613 storedeskeyarray(key
, &arg
->deskey
);
1614 if (CLASSIC_PK_DH(arg
->keylen
, arg
->algtype
)) {
1616 debug(KEYSERV_DEBUG1
,
1617 ("pk_crypt3 WARNING received 192-bit key"));
1619 debug(KEYSERV_DEBUG
,
1620 ("pk_crypt3 calling __cbc_triple_crypt"));
1621 err
= __cbc_triple_crypt(cp
->deskey
.deskeyarray_val
,
1622 (char *)key
->deskeyarray_val
,
1623 cp
->deskey
.deskeyarray_len
*sizeof (des_block
),
1624 DES_HW
| mode
, ivec
);
1625 if (DES_FAILED(err
)) {
1626 debug(KEYSERV_DEBUG
,
1627 ("pk_crypt3 calling ecb_crypt/__cbc_triple_crypt failed"));
1628 if (xsecret_alloc
) freekeybuf3(xsecret
);
1629 freekeybuf3(xpublic
);
1630 return (KEY_SYSTEMERR
);
1632 debug(KEYSERV_DEBUG
,
1633 ("pk_crypt3 calling __cbc_triple_crypt succeeded"));
1635 if (xsecret_alloc
) freekeybuf3(xsecret
);
1636 freekeybuf3(xpublic
);
1637 return (KEY_SUCCESS
);
1641 pk_get_conv_key(uid
, pubkey
, result
)
1644 cryptkeyres
*result
;
1654 if (!fetchsecretkey(uid
, xsecret
) || xsecret
[0] == 0) {
1655 memset(zero
, 0, sizeof (zero
));
1657 return (KEY_NOSECRET
);
1659 if (!getsecretkey("nobody", xsecret
, zero
) ||
1661 return (KEY_NOSECRET
);
1664 memcpy(xpublic
, pubkey
, sizeof (keybuf
));
1665 xsecret
[HEXKEYBYTES
] = '\0';
1666 xpublic
[HEXKEYBYTES
] = '\0';
1668 hash
= hash_keys(xpublic
, xsecret
);
1669 (void) rw_rdlock(&g_cachedkeys_lock
);
1670 if (!readcache(xpublic
, xsecret
, &result
->cryptkeyres_u
.deskey
, hash
)) {
1671 (void) rw_unlock(&g_cachedkeys_lock
);
1672 (void) rw_wrlock(&g_cachedkeys_lock
);
1673 if (!readcache(xpublic
, xsecret
, &result
->cryptkeyres_u
.deskey
,
1675 public = mp_xtom(xpublic
);
1676 secret
= mp_xtom(xsecret
);
1677 /* Sanity Check on public and private keys */
1678 if (public == NULL
|| secret
== NULL
) {
1679 (void) rw_unlock(&g_cachedkeys_lock
);
1680 return (KEY_SYSTEMERR
);
1682 common
= mp_itom(0);
1683 mp_pow(public, secret
, MODULUS
, common
);
1684 extractdeskey(common
, &result
->cryptkeyres_u
.deskey
);
1685 writecache(xpublic
, xsecret
,
1686 &result
->cryptkeyres_u
.deskey
, hash
);
1692 (void) rw_unlock(&g_cachedkeys_lock
);
1694 return (KEY_SUCCESS
);
1697 #define findsec(sec, list) \
1698 (memcmp(sec, (list)->secret, sizeof (keybuf)) == 0)
1701 * Remove common keys from the cache.
1707 struct cachekey_list
*found
;
1708 register struct cachekey_list
**l
;
1711 (void) rw_wrlock(&g_cachedkeys_lock
);
1712 for (i
= 0; i
< KEY_HASH_SIZE
; i
++) {
1713 for (l
= &g_cachedkeys
[i
]; (*l
) != NULL
; ) {
1714 if (findsec(sec
, *l
)) {
1717 memset((char *)found
, 0,
1718 sizeof (struct cachekey_list
));
1725 (void) rw_unlock(&g_cachedkeys_lock
);
1730 * Store the secretkey for this uid
1733 storesecretkey(uid
, key
)
1737 struct secretkey_netname_list
*new;
1738 struct secretkey_netname_list
**l
;
1739 int hash
= HASH_UID(uid
);
1741 (void) rw_wrlock(&g_secretkey_netname_lock
);
1742 for (l
= &g_secretkey_netname
[hash
]; *l
!= NULL
&& (*l
)->uid
!= uid
;
1746 if (key
[0] == '\0') {
1747 (void) rw_unlock(&g_secretkey_netname_lock
);
1750 new = (struct secretkey_netname_list
*)malloc(sizeof (*new));
1752 (void) rw_unlock(&g_secretkey_netname_lock
);
1756 new->sc_flag
= KEY_ONLY
;
1757 memset(new->keynetdata
.st_pub_key
, 0, HEXKEYBYTES
);
1758 new->keynetdata
.st_netname
= NULL
;
1764 removecache(new->keynetdata
.st_priv_key
);
1767 memcpy(new->keynetdata
.st_priv_key
, key
,
1769 (void) rw_unlock(&g_secretkey_netname_lock
);
1777 return ("0123456789abcdef"[val
]);
1781 bin2hex(bin
, hex
, size
)
1788 for (i
= 0; i
< size
; i
++) {
1789 *hex
++ = hexdigit(*bin
>> 4);
1790 *hex
++ = hexdigit(*bin
++ & 0xf);
1799 if ('0' <= dig
&& dig
<= '9') {
1801 } else if ('a' <= dig
&& dig
<= 'f') {
1802 return (dig
- 'a' + 10);
1803 } else if ('A' <= dig
&& dig
<= 'F') {
1804 return (dig
- 'A' + 10);
1811 hex2bin(hex
, bin
, size
)
1818 for (i
= 0; i
< size
; i
++) {
1819 *bin
= hexval(*hex
++) << 4;
1820 *bin
++ |= hexval(*hex
++);
1833 for (i
= 0; i
< HEXKEYBYTES
; i
+= 6, pub
+= 6, sec
+= 6) {
1837 return (hash
& 0xff);
1841 * problem: keyserv loads keys from /etc/.rootkey based on nisauthconf(1M)
1842 * which is too nis+-centric (see secure_rpc(3N)).
1844 * So we want to make sure there is always a AUTH_DES compat entry
1845 * in the "list" of nis+ mechs so that the 192bit key always gets loaded so
1846 * non-nis+ services that use AUTH_DES (e.g. nfs) won't get hosed. The real
1847 * hacky part of it is we muck with the array returned from
1848 * __nis_get_mechanisms which we really don't have any business
1849 * doing cause we should not know/care how that is implemented. A better
1850 * way would be to change the __nis_get_mechanisms interface or add another
1851 * one similiar to it that forces the "des" compat entry into the list.
1853 * Return ptr to mechs array on success, else NULL on memory errs.
1858 mechanism_t
**mechs
= __nis_get_mechanisms(FALSE
);
1859 mechanism_t
**mechsbak
= NULL
;
1860 mechanism_t
*desmech
= NULL
;
1864 /* got some valid mechs and possibly the AUTH_DES compat one */
1865 for (i
= 0; mechs
[i
]; i
++) {
1866 if (AUTH_DES_COMPAT_CHK(mechs
[i
]))
1869 /* i == number of ptrs not counting terminating NULL */
1872 /* AUTH_DES compat entry not found, let's add it */
1873 if ((desmech
= malloc(sizeof (mechanism_t
))) == NULL
) {
1875 __nis_release_mechanisms(mechs
);
1878 desmech
->mechname
= NULL
;
1879 desmech
->alias
= NIS_SEC_CF_DES_ALIAS
;
1880 desmech
->keylen
= AUTH_DES_KEYLEN
;
1881 desmech
->algtype
= AUTH_DES_ALGTYPE
;
1882 desmech
->qop
= NULL
;
1883 desmech
->secserv
= rpc_gss_svc_default
;
1886 /* mechs == NULL and i == 0 is valid "no mechs configed" case */
1887 if ((mechs
= (mechanism_t
**)realloc(mechs
,
1888 sizeof (mechanism_t
*) * (i
+ 2))) == NULL
) {
1890 __nis_release_mechanisms(mechsbak
);
1903 int nmechs
, oldmechseen
;
1904 mechanism_t
**mechpp
;
1907 if (!(mechs
= getmechwrap()))
1911 * find how many mechanisms were specified and also
1912 * setup the mechanism table for unique keylen/algtype pair
1915 for (mechpp
= mechs
; *mechpp
!= NULL
; mechpp
++) {
1916 struct keylenlist
**kpp
;
1917 struct algtypelist
**app
;
1920 if (((*mechpp
)->keylen
< 0) || ((*mechpp
)->algtype
< 0)) {
1923 kpp
= getkeylen((*mechpp
)->keylen
);
1924 appendkeylist(kpp
, (*mechpp
)->keylen
);
1925 app
= getalgtype(kpp
, (*mechpp
)->algtype
);
1926 appendalgtype(app
, (*mechpp
)->algtype
);
1930 * set of mechs for getsubopt()
1932 cache_options
= (char **)calloc((size_t)nmechs
+ 1,
1933 sizeof (*cache_options
));
1934 if (cache_options
== NULL
) {
1935 (void) fprintf(stderr
, "unable to allocate option array");
1941 cache_size
= (int *)calloc((size_t)nmechs
, sizeof (int));
1942 if (cache_size
== NULL
) {
1943 (void) fprintf(stderr
, "unable to allocate cache array");
1948 cpp
= cache_options
;
1949 for (mechpp
= mechs
; *mechpp
!= NULL
; mechpp
++) {
1951 * usual case: a DH-style mechanism type, with an alias
1953 if ((*mechpp
)->mechname
!= NULL
&&
1954 strncmp((*mechpp
)->mechname
, DHMECHSTR
,
1955 strlen(DHMECHSTR
)) == 0 &&
1956 (*mechpp
)->alias
!= NULL
) {
1958 * Is this trad 192-DH? already added?
1960 if (strcmp((*mechpp
)->alias
, DESALIAS
) == 0) {
1967 *cpp
++ = (*mechpp
)->alias
;
1972 * HACK: we recognise a special alias for traditional
1973 * 192-bit DH, unless the latter has already been mentioned
1976 if ((*mechpp
)->mechname
== NULL
&& (*mechpp
)->alias
!= NULL
&&
1977 strcmp((*mechpp
)->alias
, DES
) == 0 && !oldmechseen
) {
1984 * Ignore anything else
1988 /* Terminate the options list */