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 1998 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 /* 28*7c478bd9Sstevel@tonic-gate * University Copyright- Copyright (c) 1982, 1986, 1988 29*7c478bd9Sstevel@tonic-gate * The Regents of the University of California 30*7c478bd9Sstevel@tonic-gate * All Rights Reserved 31*7c478bd9Sstevel@tonic-gate * 32*7c478bd9Sstevel@tonic-gate * University Acknowledgment- Portions of this document are derived from 33*7c478bd9Sstevel@tonic-gate * software developed by the University of California, Berkeley, and its 34*7c478bd9Sstevel@tonic-gate * contributors. 35*7c478bd9Sstevel@tonic-gate */ 36*7c478bd9Sstevel@tonic-gate 37*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 38*7c478bd9Sstevel@tonic-gate 39*7c478bd9Sstevel@tonic-gate /* 40*7c478bd9Sstevel@tonic-gate * Do the real work of the keyserver. 41*7c478bd9Sstevel@tonic-gate * Store secret keys. Compute common keys, 42*7c478bd9Sstevel@tonic-gate * and use them to decrypt and encrypt DES keys. 43*7c478bd9Sstevel@tonic-gate * Cache the common keys, so the expensive computation is avoided. 44*7c478bd9Sstevel@tonic-gate */ 45*7c478bd9Sstevel@tonic-gate #include <stdio.h> 46*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 47*7c478bd9Sstevel@tonic-gate #include <mp.h> 48*7c478bd9Sstevel@tonic-gate #include <rpc/rpc.h> 49*7c478bd9Sstevel@tonic-gate #include <rpc/key_prot.h> 50*7c478bd9Sstevel@tonic-gate #include <rpc/des_crypt.h> 51*7c478bd9Sstevel@tonic-gate #include <rpcsvc/nis_dhext.h> 52*7c478bd9Sstevel@tonic-gate #include <sys/errno.h> 53*7c478bd9Sstevel@tonic-gate #include <string.h> 54*7c478bd9Sstevel@tonic-gate #include <thread.h> 55*7c478bd9Sstevel@tonic-gate #include <syslog.h> 56*7c478bd9Sstevel@tonic-gate 57*7c478bd9Sstevel@tonic-gate #include "debug.h" 58*7c478bd9Sstevel@tonic-gate #include "keyserv_cache.h" 59*7c478bd9Sstevel@tonic-gate 60*7c478bd9Sstevel@tonic-gate extern char ROOTKEY[]; 61*7c478bd9Sstevel@tonic-gate extern mechanism_t **mechs; 62*7c478bd9Sstevel@tonic-gate extern char **cache_options; 63*7c478bd9Sstevel@tonic-gate extern int *cache_size; 64*7c478bd9Sstevel@tonic-gate extern int disk_caching; 65*7c478bd9Sstevel@tonic-gate 66*7c478bd9Sstevel@tonic-gate static MINT *MODULUS; 67*7c478bd9Sstevel@tonic-gate static int hash_keys(); 68*7c478bd9Sstevel@tonic-gate static keystatus pk_crypt(); 69*7c478bd9Sstevel@tonic-gate static keystatus pk_crypt3(); 70*7c478bd9Sstevel@tonic-gate static int nodefaultkeys = 0; 71*7c478bd9Sstevel@tonic-gate 72*7c478bd9Sstevel@tonic-gate #define DES "des" 73*7c478bd9Sstevel@tonic-gate #define DESALIAS "dh192-0" 74*7c478bd9Sstevel@tonic-gate #define DHMECHSTR "diffie_hellman" 75*7c478bd9Sstevel@tonic-gate #define CLASSIC_PK_DH(k, a) (((k) == 192) && ((a) == 0)) 76*7c478bd9Sstevel@tonic-gate 77*7c478bd9Sstevel@tonic-gate /* 78*7c478bd9Sstevel@tonic-gate * Exponential caching management 79*7c478bd9Sstevel@tonic-gate */ 80*7c478bd9Sstevel@tonic-gate struct cachekey_list { 81*7c478bd9Sstevel@tonic-gate keybuf secret; 82*7c478bd9Sstevel@tonic-gate keybuf public; 83*7c478bd9Sstevel@tonic-gate des_block deskey; 84*7c478bd9Sstevel@tonic-gate struct cachekey_list *next; 85*7c478bd9Sstevel@tonic-gate }; 86*7c478bd9Sstevel@tonic-gate #define KEY_HASH_SIZE 256 87*7c478bd9Sstevel@tonic-gate static struct cachekey_list *g_cachedkeys[KEY_HASH_SIZE]; 88*7c478bd9Sstevel@tonic-gate static rwlock_t g_cachedkeys_lock = DEFAULTRWLOCK; 89*7c478bd9Sstevel@tonic-gate 90*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 91*7c478bd9Sstevel@tonic-gate int 92*7c478bd9Sstevel@tonic-gate test_debug(debug_level level, char *file, int line) 93*7c478bd9Sstevel@tonic-gate { 94*7c478bd9Sstevel@tonic-gate if (level < debugging) 95*7c478bd9Sstevel@tonic-gate return (0); 96*7c478bd9Sstevel@tonic-gate fprintf(stderr, "file %s,\tline %d :\t", file, line); 97*7c478bd9Sstevel@tonic-gate return (1); 98*7c478bd9Sstevel@tonic-gate } 99*7c478bd9Sstevel@tonic-gate 100*7c478bd9Sstevel@tonic-gate int 101*7c478bd9Sstevel@tonic-gate real_debug(char *fmt, ...) 102*7c478bd9Sstevel@tonic-gate { 103*7c478bd9Sstevel@tonic-gate va_list args; 104*7c478bd9Sstevel@tonic-gate 105*7c478bd9Sstevel@tonic-gate va_start(args, fmt); 106*7c478bd9Sstevel@tonic-gate (void) vfprintf(stderr, fmt, args); 107*7c478bd9Sstevel@tonic-gate va_end(args); 108*7c478bd9Sstevel@tonic-gate fprintf(stderr, "\n"); 109*7c478bd9Sstevel@tonic-gate fflush(stderr); 110*7c478bd9Sstevel@tonic-gate return (1); 111*7c478bd9Sstevel@tonic-gate } 112*7c478bd9Sstevel@tonic-gate #endif /* DEBUG */ 113*7c478bd9Sstevel@tonic-gate 114*7c478bd9Sstevel@tonic-gate struct cacheuid_list { 115*7c478bd9Sstevel@tonic-gate uid_t uid; 116*7c478bd9Sstevel@tonic-gate int refcnt; 117*7c478bd9Sstevel@tonic-gate keybuf3 *secretkey; 118*7c478bd9Sstevel@tonic-gate keybuf3 *publickey; 119*7c478bd9Sstevel@tonic-gate netnamestr netname; 120*7c478bd9Sstevel@tonic-gate des_block key; 121*7c478bd9Sstevel@tonic-gate struct cacheuid_list *next; 122*7c478bd9Sstevel@tonic-gate }; 123*7c478bd9Sstevel@tonic-gate 124*7c478bd9Sstevel@tonic-gate #define NUMHASHBUCKETS 256 125*7c478bd9Sstevel@tonic-gate #define HASH_UID(x) (x & 0xff) 126*7c478bd9Sstevel@tonic-gate 127*7c478bd9Sstevel@tonic-gate struct mechdata { 128*7c478bd9Sstevel@tonic-gate struct cacheuid_list *bucket[NUMHASHBUCKETS]; 129*7c478bd9Sstevel@tonic-gate }; 130*7c478bd9Sstevel@tonic-gate 131*7c478bd9Sstevel@tonic-gate struct psdata { 132*7c478bd9Sstevel@tonic-gate struct cachekey3_list *common[NUMHASHBUCKETS]; 133*7c478bd9Sstevel@tonic-gate }; 134*7c478bd9Sstevel@tonic-gate 135*7c478bd9Sstevel@tonic-gate struct mechentry { 136*7c478bd9Sstevel@tonic-gate mutex_t mech_lock; 137*7c478bd9Sstevel@tonic-gate struct mechdata *mechdata; 138*7c478bd9Sstevel@tonic-gate mutex_t ps_lock; 139*7c478bd9Sstevel@tonic-gate struct psdata *psdata; 140*7c478bd9Sstevel@tonic-gate }; 141*7c478bd9Sstevel@tonic-gate 142*7c478bd9Sstevel@tonic-gate /* 143*7c478bd9Sstevel@tonic-gate * we don't need to worry about locking for the keylen + algtype 144*7c478bd9Sstevel@tonic-gate * sparse array because it is created once and for all during 145*7c478bd9Sstevel@tonic-gate * initialization when there are no threads. The mechentry field 146*7c478bd9Sstevel@tonic-gate * and everything underneath it needs protection and this is what 147*7c478bd9Sstevel@tonic-gate * the *_lock fields are for. 148*7c478bd9Sstevel@tonic-gate */ 149*7c478bd9Sstevel@tonic-gate struct algtypelist { 150*7c478bd9Sstevel@tonic-gate algtype_t algtype; 151*7c478bd9Sstevel@tonic-gate struct algtypelist *next; 152*7c478bd9Sstevel@tonic-gate struct mechentry mech; 153*7c478bd9Sstevel@tonic-gate }; 154*7c478bd9Sstevel@tonic-gate 155*7c478bd9Sstevel@tonic-gate struct keylenlist { 156*7c478bd9Sstevel@tonic-gate keylen_t keylen; 157*7c478bd9Sstevel@tonic-gate struct algtypelist *ap; 158*7c478bd9Sstevel@tonic-gate struct keylenlist *next; 159*7c478bd9Sstevel@tonic-gate }; 160*7c478bd9Sstevel@tonic-gate 161*7c478bd9Sstevel@tonic-gate #define KEYSERV_VERSION "1.0" 162*7c478bd9Sstevel@tonic-gate 163*7c478bd9Sstevel@tonic-gate static struct mechtable { 164*7c478bd9Sstevel@tonic-gate char *version; 165*7c478bd9Sstevel@tonic-gate struct keylenlist *kp; 166*7c478bd9Sstevel@tonic-gate } mechtable = {KEYSERV_VERSION, NULL}; 167*7c478bd9Sstevel@tonic-gate 168*7c478bd9Sstevel@tonic-gate static struct keylenlist ** 169*7c478bd9Sstevel@tonic-gate getkeylen(keylen_t k) 170*7c478bd9Sstevel@tonic-gate { 171*7c478bd9Sstevel@tonic-gate struct keylenlist **kpp; 172*7c478bd9Sstevel@tonic-gate 173*7c478bd9Sstevel@tonic-gate debug(KEYSERV_DEBUG1, ("getkeylen key: %d", k)); 174*7c478bd9Sstevel@tonic-gate for (kpp = &mechtable.kp; 175*7c478bd9Sstevel@tonic-gate *kpp != NULL && (*kpp)->keylen != k; 176*7c478bd9Sstevel@tonic-gate kpp = &(*kpp)->next) 177*7c478bd9Sstevel@tonic-gate debug(KEYSERV_DEBUG0, ("getkeylen failed %x", kpp)); 178*7c478bd9Sstevel@tonic-gate debug(KEYSERV_DEBUG0, ("getkeylen return: %x", kpp)); 179*7c478bd9Sstevel@tonic-gate return (kpp); 180*7c478bd9Sstevel@tonic-gate } 181*7c478bd9Sstevel@tonic-gate 182*7c478bd9Sstevel@tonic-gate static void 183*7c478bd9Sstevel@tonic-gate appendkeylist(struct keylenlist **kpp, keylen_t k) 184*7c478bd9Sstevel@tonic-gate { 185*7c478bd9Sstevel@tonic-gate struct keylenlist *kp; 186*7c478bd9Sstevel@tonic-gate 187*7c478bd9Sstevel@tonic-gate if (*kpp == NULL) { 188*7c478bd9Sstevel@tonic-gate kp = (struct keylenlist *)malloc(sizeof (*kp)); 189*7c478bd9Sstevel@tonic-gate if (kp == NULL) { 190*7c478bd9Sstevel@tonic-gate debug(KEYSERV_INFO, ("appendkeylist : malloc failed")); 191*7c478bd9Sstevel@tonic-gate return; 192*7c478bd9Sstevel@tonic-gate } 193*7c478bd9Sstevel@tonic-gate debug(KEYSERV_DEBUG, ("appendkeylist : %x %x %d", kpp, kp, k)); 194*7c478bd9Sstevel@tonic-gate kp->keylen = k; 195*7c478bd9Sstevel@tonic-gate kp->ap = NULL; 196*7c478bd9Sstevel@tonic-gate kp->next = NULL; 197*7c478bd9Sstevel@tonic-gate *kpp = kp; 198*7c478bd9Sstevel@tonic-gate } else { 199*7c478bd9Sstevel@tonic-gate /*EMPTY*/ 200*7c478bd9Sstevel@tonic-gate /* do nothing; only happens for multiple algtypes */ 201*7c478bd9Sstevel@tonic-gate debug(KEYSERV_DEBUG0, 202*7c478bd9Sstevel@tonic-gate ("appendkeylist called for non tail element")); 203*7c478bd9Sstevel@tonic-gate } 204*7c478bd9Sstevel@tonic-gate } 205*7c478bd9Sstevel@tonic-gate 206*7c478bd9Sstevel@tonic-gate static struct algtypelist ** 207*7c478bd9Sstevel@tonic-gate getalgtype(struct keylenlist **kpp, algtype_t a) 208*7c478bd9Sstevel@tonic-gate { 209*7c478bd9Sstevel@tonic-gate struct algtypelist **app; 210*7c478bd9Sstevel@tonic-gate 211*7c478bd9Sstevel@tonic-gate debug(KEYSERV_DEBUG1, ("getalgtype key: %d", a)); 212*7c478bd9Sstevel@tonic-gate for (app = &(*kpp)->ap; 213*7c478bd9Sstevel@tonic-gate *app != NULL && (*app)->algtype != a; 214*7c478bd9Sstevel@tonic-gate app = &(*app)->next) 215*7c478bd9Sstevel@tonic-gate debug(KEYSERV_DEBUG0, ("getalgtype key: %x", app)); 216*7c478bd9Sstevel@tonic-gate debug(KEYSERV_DEBUG0, ("getalgtype return: %x", app)); 217*7c478bd9Sstevel@tonic-gate return (app); 218*7c478bd9Sstevel@tonic-gate } 219*7c478bd9Sstevel@tonic-gate 220*7c478bd9Sstevel@tonic-gate static void 221*7c478bd9Sstevel@tonic-gate appendalgtype(struct algtypelist **app, algtype_t a) 222*7c478bd9Sstevel@tonic-gate { 223*7c478bd9Sstevel@tonic-gate struct algtypelist *ap; 224*7c478bd9Sstevel@tonic-gate 225*7c478bd9Sstevel@tonic-gate if (*app == NULL) { 226*7c478bd9Sstevel@tonic-gate ap = (struct algtypelist *)malloc(sizeof (*ap)); 227*7c478bd9Sstevel@tonic-gate if (ap == NULL) { 228*7c478bd9Sstevel@tonic-gate debug(KEYSERV_INFO, ("appendalgtype : malloc failed")); 229*7c478bd9Sstevel@tonic-gate return; 230*7c478bd9Sstevel@tonic-gate } 231*7c478bd9Sstevel@tonic-gate debug(KEYSERV_DEBUG, ("appendalgtype : %x %x %d", app, ap, a)); 232*7c478bd9Sstevel@tonic-gate ap->algtype = a; 233*7c478bd9Sstevel@tonic-gate mutex_init(&ap->mech.mech_lock, USYNC_THREAD, NULL); 234*7c478bd9Sstevel@tonic-gate mutex_init(&ap->mech.ps_lock, USYNC_THREAD, NULL); 235*7c478bd9Sstevel@tonic-gate ap->mech.mechdata = NULL; 236*7c478bd9Sstevel@tonic-gate ap->mech.psdata = NULL; 237*7c478bd9Sstevel@tonic-gate ap->next = NULL; 238*7c478bd9Sstevel@tonic-gate *app = ap; 239*7c478bd9Sstevel@tonic-gate } else { 240*7c478bd9Sstevel@tonic-gate /*EMPTY*/ 241*7c478bd9Sstevel@tonic-gate /* don't mind duplicate (keylen,algtype) paris for now. */ 242*7c478bd9Sstevel@tonic-gate debug(KEYSERV_DEBUG0, 243*7c478bd9Sstevel@tonic-gate ("appendalgtype called for non tail element")); 244*7c478bd9Sstevel@tonic-gate } 245*7c478bd9Sstevel@tonic-gate } 246*7c478bd9Sstevel@tonic-gate 247*7c478bd9Sstevel@tonic-gate static struct mechentry * 248*7c478bd9Sstevel@tonic-gate getmechtype(keylen_t k, algtype_t a) 249*7c478bd9Sstevel@tonic-gate { 250*7c478bd9Sstevel@tonic-gate struct keylenlist **kpp; 251*7c478bd9Sstevel@tonic-gate struct algtypelist **app; 252*7c478bd9Sstevel@tonic-gate 253*7c478bd9Sstevel@tonic-gate debug(KEYSERV_DEBUG1, ("getmechtype %d %d", k, a)); 254*7c478bd9Sstevel@tonic-gate kpp = getkeylen(k); 255*7c478bd9Sstevel@tonic-gate if (*kpp == NULL) { 256*7c478bd9Sstevel@tonic-gate debug(KEYSERV_DEBUG0, ("getmechtype %d not found in keys", k)); 257*7c478bd9Sstevel@tonic-gate return (0); 258*7c478bd9Sstevel@tonic-gate } 259*7c478bd9Sstevel@tonic-gate app = getalgtype(kpp, a); 260*7c478bd9Sstevel@tonic-gate if (*app == NULL) { 261*7c478bd9Sstevel@tonic-gate debug(KEYSERV_DEBUG0, ("getmechtype %d not found in algs", a)); 262*7c478bd9Sstevel@tonic-gate return (0); 263*7c478bd9Sstevel@tonic-gate } 264*7c478bd9Sstevel@tonic-gate debug(KEYSERV_DEBUG0, ("getmechtype found %x", app)); 265*7c478bd9Sstevel@tonic-gate debug(KEYSERV_DEBUG0, ("getmechtype return %x", &(*app)->mech)); 266*7c478bd9Sstevel@tonic-gate return (&(*app)->mech); 267*7c478bd9Sstevel@tonic-gate } 268*7c478bd9Sstevel@tonic-gate 269*7c478bd9Sstevel@tonic-gate static keybuf3 * 270*7c478bd9Sstevel@tonic-gate getkeybuf3(int k) 271*7c478bd9Sstevel@tonic-gate { 272*7c478bd9Sstevel@tonic-gate keybuf3 *buf; 273*7c478bd9Sstevel@tonic-gate 274*7c478bd9Sstevel@tonic-gate debug(KEYSERV_DEBUG, ("getkeybuf3 malloc %d", k)); 275*7c478bd9Sstevel@tonic-gate buf = (keybuf3 *) malloc(sizeof (*buf)); 276*7c478bd9Sstevel@tonic-gate if (buf == NULL) { 277*7c478bd9Sstevel@tonic-gate debug(KEYSERV_DEBUG, ("getkeybuf3 malloc failed")); 278*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, "file %s line %d: malloc failed", 279*7c478bd9Sstevel@tonic-gate __FILE__, __LINE__); 280*7c478bd9Sstevel@tonic-gate return (NULL); 281*7c478bd9Sstevel@tonic-gate } 282*7c478bd9Sstevel@tonic-gate buf->keybuf3_len = k; 283*7c478bd9Sstevel@tonic-gate /* XXX special case k==0 */ 284*7c478bd9Sstevel@tonic-gate if (k == 0) { 285*7c478bd9Sstevel@tonic-gate buf->keybuf3_val = NULL; 286*7c478bd9Sstevel@tonic-gate } else { 287*7c478bd9Sstevel@tonic-gate buf->keybuf3_val = (char *)malloc(k); 288*7c478bd9Sstevel@tonic-gate if (buf->keybuf3_val == NULL) { 289*7c478bd9Sstevel@tonic-gate debug(KEYSERV_DEBUG, ("getkeybuf3 malloc failed")); 290*7c478bd9Sstevel@tonic-gate free(buf); 291*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, "file %s line %d: malloc failed", 292*7c478bd9Sstevel@tonic-gate __FILE__, __LINE__); 293*7c478bd9Sstevel@tonic-gate return (NULL); 294*7c478bd9Sstevel@tonic-gate } 295*7c478bd9Sstevel@tonic-gate } 296*7c478bd9Sstevel@tonic-gate debug(KEYSERV_DEBUG1, ("getkeybuf3 ret %x", buf)); 297*7c478bd9Sstevel@tonic-gate return (buf); 298*7c478bd9Sstevel@tonic-gate } 299*7c478bd9Sstevel@tonic-gate 300*7c478bd9Sstevel@tonic-gate static void 301*7c478bd9Sstevel@tonic-gate freekeybuf3(keybuf3 *kp) 302*7c478bd9Sstevel@tonic-gate { 303*7c478bd9Sstevel@tonic-gate debug(KEYSERV_DEBUG1, ("freekeybuf3 %x", kp)); 304*7c478bd9Sstevel@tonic-gate if (kp == NULL) 305*7c478bd9Sstevel@tonic-gate return; 306*7c478bd9Sstevel@tonic-gate if (kp->keybuf3_val) { 307*7c478bd9Sstevel@tonic-gate /* XXX kp->keybuf3_len != 0? */ 308*7c478bd9Sstevel@tonic-gate free(kp->keybuf3_val); 309*7c478bd9Sstevel@tonic-gate } 310*7c478bd9Sstevel@tonic-gate free(kp); 311*7c478bd9Sstevel@tonic-gate } 312*7c478bd9Sstevel@tonic-gate 313*7c478bd9Sstevel@tonic-gate static keybuf3 * 314*7c478bd9Sstevel@tonic-gate cpykeybuf3(keybuf3 *src) 315*7c478bd9Sstevel@tonic-gate { 316*7c478bd9Sstevel@tonic-gate keybuf3 *dst; 317*7c478bd9Sstevel@tonic-gate 318*7c478bd9Sstevel@tonic-gate if (src == NULL) { 319*7c478bd9Sstevel@tonic-gate return (NULL); 320*7c478bd9Sstevel@tonic-gate } 321*7c478bd9Sstevel@tonic-gate if ((dst = getkeybuf3(src->keybuf3_len)) == NULL) { 322*7c478bd9Sstevel@tonic-gate return (NULL); 323*7c478bd9Sstevel@tonic-gate } 324*7c478bd9Sstevel@tonic-gate memcpy(dst->keybuf3_val, src->keybuf3_val, src->keybuf3_len); 325*7c478bd9Sstevel@tonic-gate debug(KEYSERV_DEBUG0, ("cpykeybuf3 ret %x", dst)); 326*7c478bd9Sstevel@tonic-gate return (dst); 327*7c478bd9Sstevel@tonic-gate } 328*7c478bd9Sstevel@tonic-gate 329*7c478bd9Sstevel@tonic-gate static keybuf3 * 330*7c478bd9Sstevel@tonic-gate setkeybuf3(char *src, int len) 331*7c478bd9Sstevel@tonic-gate { 332*7c478bd9Sstevel@tonic-gate keybuf3 *dst; 333*7c478bd9Sstevel@tonic-gate 334*7c478bd9Sstevel@tonic-gate if ((dst = getkeybuf3(++len)) == NULL) { 335*7c478bd9Sstevel@tonic-gate return (NULL); 336*7c478bd9Sstevel@tonic-gate } 337*7c478bd9Sstevel@tonic-gate memcpy(dst->keybuf3_val, src, len); 338*7c478bd9Sstevel@tonic-gate return (dst); 339*7c478bd9Sstevel@tonic-gate } 340*7c478bd9Sstevel@tonic-gate 341*7c478bd9Sstevel@tonic-gate static int 342*7c478bd9Sstevel@tonic-gate cmpkeybuf3(keybuf3 *k1, keybuf3 *k2) 343*7c478bd9Sstevel@tonic-gate { 344*7c478bd9Sstevel@tonic-gate if ((k1 == NULL) || (k2 == NULL)) { 345*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, "cmpkeybuf3: invalid parameter: %x, %x", 346*7c478bd9Sstevel@tonic-gate k1, k2); 347*7c478bd9Sstevel@tonic-gate return (0); 348*7c478bd9Sstevel@tonic-gate } 349*7c478bd9Sstevel@tonic-gate if (k1->keybuf3_len != k2->keybuf3_len) { 350*7c478bd9Sstevel@tonic-gate return (0); 351*7c478bd9Sstevel@tonic-gate } 352*7c478bd9Sstevel@tonic-gate return (!memcmp(k1->keybuf3_val, k2->keybuf3_val, k1->keybuf3_len)); 353*7c478bd9Sstevel@tonic-gate } 354*7c478bd9Sstevel@tonic-gate 355*7c478bd9Sstevel@tonic-gate static int 356*7c478bd9Sstevel@tonic-gate storekeybuf3(keybuf3 *dst, keybuf3 *src) 357*7c478bd9Sstevel@tonic-gate { 358*7c478bd9Sstevel@tonic-gate keybuf3 *tmp; 359*7c478bd9Sstevel@tonic-gate 360*7c478bd9Sstevel@tonic-gate if ((tmp = cpykeybuf3(src)) == NULL) { 361*7c478bd9Sstevel@tonic-gate return (0); 362*7c478bd9Sstevel@tonic-gate } 363*7c478bd9Sstevel@tonic-gate *dst = *tmp; 364*7c478bd9Sstevel@tonic-gate free(tmp); /* but not the contents */ 365*7c478bd9Sstevel@tonic-gate debug(KEYSERV_DEBUG0, ("storekeybuf3 ret %d %x", 366*7c478bd9Sstevel@tonic-gate dst->keybuf3_len, dst->keybuf3_val)); 367*7c478bd9Sstevel@tonic-gate return (1); 368*7c478bd9Sstevel@tonic-gate } 369*7c478bd9Sstevel@tonic-gate 370*7c478bd9Sstevel@tonic-gate static deskeyarray * 371*7c478bd9Sstevel@tonic-gate getdeskeyarray(int k) 372*7c478bd9Sstevel@tonic-gate { 373*7c478bd9Sstevel@tonic-gate deskeyarray *buf; 374*7c478bd9Sstevel@tonic-gate 375*7c478bd9Sstevel@tonic-gate debug(KEYSERV_DEBUG, ("getdeskeyarray malloc %d", k)); 376*7c478bd9Sstevel@tonic-gate buf = (deskeyarray *) malloc(sizeof (*buf)); 377*7c478bd9Sstevel@tonic-gate if (buf == NULL) { 378*7c478bd9Sstevel@tonic-gate debug(KEYSERV_DEBUG, ("getdeskeyarray malloc failed")); 379*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, "file %s line %d: malloc failed", 380*7c478bd9Sstevel@tonic-gate __FILE__, __LINE__); 381*7c478bd9Sstevel@tonic-gate return (NULL); 382*7c478bd9Sstevel@tonic-gate } 383*7c478bd9Sstevel@tonic-gate buf->deskeyarray_len = k; 384*7c478bd9Sstevel@tonic-gate /* XXX special case k==0 */ 385*7c478bd9Sstevel@tonic-gate if (k == 0) { 386*7c478bd9Sstevel@tonic-gate buf->deskeyarray_val = NULL; 387*7c478bd9Sstevel@tonic-gate } else { 388*7c478bd9Sstevel@tonic-gate buf->deskeyarray_val = (des_block *) 389*7c478bd9Sstevel@tonic-gate malloc(k * sizeof (des_block)); 390*7c478bd9Sstevel@tonic-gate if (buf->deskeyarray_val == NULL) { 391*7c478bd9Sstevel@tonic-gate debug(KEYSERV_DEBUG, ("getdeskeyarray malloc failed")); 392*7c478bd9Sstevel@tonic-gate free(buf); 393*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, "file %s line %d: malloc failed", 394*7c478bd9Sstevel@tonic-gate __FILE__, __LINE__); 395*7c478bd9Sstevel@tonic-gate return (NULL); 396*7c478bd9Sstevel@tonic-gate } 397*7c478bd9Sstevel@tonic-gate } 398*7c478bd9Sstevel@tonic-gate debug(KEYSERV_DEBUG1, ("getdeskeyarray ret %x", buf)); 399*7c478bd9Sstevel@tonic-gate return (buf); 400*7c478bd9Sstevel@tonic-gate } 401*7c478bd9Sstevel@tonic-gate 402*7c478bd9Sstevel@tonic-gate static deskeyarray * 403*7c478bd9Sstevel@tonic-gate cpydeskeyarray(deskeyarray *src) 404*7c478bd9Sstevel@tonic-gate { 405*7c478bd9Sstevel@tonic-gate deskeyarray *dst; 406*7c478bd9Sstevel@tonic-gate 407*7c478bd9Sstevel@tonic-gate if (src == NULL) { 408*7c478bd9Sstevel@tonic-gate return (NULL); 409*7c478bd9Sstevel@tonic-gate } 410*7c478bd9Sstevel@tonic-gate if ((dst = getdeskeyarray(src->deskeyarray_len)) == NULL) { 411*7c478bd9Sstevel@tonic-gate return (NULL); 412*7c478bd9Sstevel@tonic-gate } 413*7c478bd9Sstevel@tonic-gate memcpy(dst->deskeyarray_val, src->deskeyarray_val, 414*7c478bd9Sstevel@tonic-gate src->deskeyarray_len * sizeof (des_block)); 415*7c478bd9Sstevel@tonic-gate debug(KEYSERV_DEBUG0, ("cpydeskeyarray ret %x", dst)); 416*7c478bd9Sstevel@tonic-gate return (dst); 417*7c478bd9Sstevel@tonic-gate } 418*7c478bd9Sstevel@tonic-gate 419*7c478bd9Sstevel@tonic-gate static int 420*7c478bd9Sstevel@tonic-gate storedeskeyarray(deskeyarray *dst, deskeyarray *src) 421*7c478bd9Sstevel@tonic-gate { 422*7c478bd9Sstevel@tonic-gate deskeyarray *tmp; 423*7c478bd9Sstevel@tonic-gate 424*7c478bd9Sstevel@tonic-gate if ((tmp = cpydeskeyarray(src)) == NULL) { 425*7c478bd9Sstevel@tonic-gate return (0); 426*7c478bd9Sstevel@tonic-gate } 427*7c478bd9Sstevel@tonic-gate *dst = *tmp; 428*7c478bd9Sstevel@tonic-gate free(tmp); /* but not the contents */ 429*7c478bd9Sstevel@tonic-gate debug(KEYSERV_DEBUG0, ("storedeskeyarray ret %d %x", 430*7c478bd9Sstevel@tonic-gate dst->deskeyarray_len, dst->deskeyarray_val)); 431*7c478bd9Sstevel@tonic-gate return (1); 432*7c478bd9Sstevel@tonic-gate } 433*7c478bd9Sstevel@tonic-gate 434*7c478bd9Sstevel@tonic-gate int 435*7c478bd9Sstevel@tonic-gate setdeskeyarray(deskeyarray *dst, int k) 436*7c478bd9Sstevel@tonic-gate { 437*7c478bd9Sstevel@tonic-gate deskeyarray *tmp; 438*7c478bd9Sstevel@tonic-gate 439*7c478bd9Sstevel@tonic-gate if ((tmp = getdeskeyarray(k)) == NULL) { 440*7c478bd9Sstevel@tonic-gate return (0); 441*7c478bd9Sstevel@tonic-gate } 442*7c478bd9Sstevel@tonic-gate *dst = *tmp; 443*7c478bd9Sstevel@tonic-gate free(tmp); /* but not the contents */ 444*7c478bd9Sstevel@tonic-gate debug(KEYSERV_DEBUG0, ("setdeskeyarray ret %d %x", 445*7c478bd9Sstevel@tonic-gate dst->deskeyarray_len, dst->deskeyarray_val)); 446*7c478bd9Sstevel@tonic-gate return (1); 447*7c478bd9Sstevel@tonic-gate } 448*7c478bd9Sstevel@tonic-gate 449*7c478bd9Sstevel@tonic-gate static int 450*7c478bd9Sstevel@tonic-gate cachehit3(keybuf3 *public, keybuf3 *secret, struct cachekey3_list *cp) 451*7c478bd9Sstevel@tonic-gate { 452*7c478bd9Sstevel@tonic-gate return (cmpkeybuf3(public, cp->public) && 453*7c478bd9Sstevel@tonic-gate cmpkeybuf3(secret, cp->secret)); 454*7c478bd9Sstevel@tonic-gate } 455*7c478bd9Sstevel@tonic-gate 456*7c478bd9Sstevel@tonic-gate static struct cacheuid_list ** 457*7c478bd9Sstevel@tonic-gate mapuid2cache(uid_t uid, struct mechdata *mdp) 458*7c478bd9Sstevel@tonic-gate { 459*7c478bd9Sstevel@tonic-gate struct cacheuid_list **cpp; 460*7c478bd9Sstevel@tonic-gate int hash = HASH_UID(uid); 461*7c478bd9Sstevel@tonic-gate 462*7c478bd9Sstevel@tonic-gate debug(KEYSERV_DEBUG, ("mapuid2cache %d %d %x", uid, hash, mdp)); 463*7c478bd9Sstevel@tonic-gate for (cpp = &mdp->bucket[hash]; 464*7c478bd9Sstevel@tonic-gate *cpp != NULL && (*cpp)->uid != uid; 465*7c478bd9Sstevel@tonic-gate cpp = &(*cpp)->next) { 466*7c478bd9Sstevel@tonic-gate debug(KEYSERV_DEBUG0, ("mapuid2cache %x", cpp)); 467*7c478bd9Sstevel@tonic-gate } 468*7c478bd9Sstevel@tonic-gate debug(KEYSERV_DEBUG, ("mapuid2cache ret %x", cpp)); 469*7c478bd9Sstevel@tonic-gate return (cpp); 470*7c478bd9Sstevel@tonic-gate } 471*7c478bd9Sstevel@tonic-gate 472*7c478bd9Sstevel@tonic-gate static int 473*7c478bd9Sstevel@tonic-gate appendsecretkey3(struct mechentry *mp, uid_t uid, setkeyarg3 *skey) 474*7c478bd9Sstevel@tonic-gate { 475*7c478bd9Sstevel@tonic-gate struct mechdata *mdp; 476*7c478bd9Sstevel@tonic-gate struct cacheuid_list **cpp, *cp; 477*7c478bd9Sstevel@tonic-gate keybuf3 nullkey = {0, NULL}; 478*7c478bd9Sstevel@tonic-gate 479*7c478bd9Sstevel@tonic-gate debug(KEYSERV_DEBUG, ("appendsecretkey3 %x", mp)); 480*7c478bd9Sstevel@tonic-gate if ((skey == NULL) || (mp == NULL)) { 481*7c478bd9Sstevel@tonic-gate return (0); 482*7c478bd9Sstevel@tonic-gate } 483*7c478bd9Sstevel@tonic-gate if (skey->key.keybuf3_len == 0) { 484*7c478bd9Sstevel@tonic-gate return (0); 485*7c478bd9Sstevel@tonic-gate } 486*7c478bd9Sstevel@tonic-gate mutex_lock(&mp->mech_lock); 487*7c478bd9Sstevel@tonic-gate if ((mdp = mp->mechdata) == NULL) { 488*7c478bd9Sstevel@tonic-gate mdp = (struct mechdata *)calloc(1, sizeof (*mdp)); 489*7c478bd9Sstevel@tonic-gate if (mdp == NULL) { 490*7c478bd9Sstevel@tonic-gate mutex_unlock(&mp->mech_lock); 491*7c478bd9Sstevel@tonic-gate debug(KEYSERV_INFO, 492*7c478bd9Sstevel@tonic-gate ("appendsecretkey3 : calloc failed")); 493*7c478bd9Sstevel@tonic-gate return (0); 494*7c478bd9Sstevel@tonic-gate } 495*7c478bd9Sstevel@tonic-gate mp->mechdata = mdp; 496*7c478bd9Sstevel@tonic-gate } 497*7c478bd9Sstevel@tonic-gate cpp = mapuid2cache(uid, mdp); 498*7c478bd9Sstevel@tonic-gate if (*cpp == NULL) { 499*7c478bd9Sstevel@tonic-gate cp = (struct cacheuid_list *)malloc(sizeof (*cp)); 500*7c478bd9Sstevel@tonic-gate if (cp == NULL) { 501*7c478bd9Sstevel@tonic-gate mutex_unlock(&mp->mech_lock); 502*7c478bd9Sstevel@tonic-gate debug(KEYSERV_INFO, 503*7c478bd9Sstevel@tonic-gate ("appendsecretkey3 : malloc failed")); 504*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, "file %s line %d: malloc failed", 505*7c478bd9Sstevel@tonic-gate __FILE__, __LINE__); 506*7c478bd9Sstevel@tonic-gate return (0); 507*7c478bd9Sstevel@tonic-gate } 508*7c478bd9Sstevel@tonic-gate memset(cp, 0, sizeof (*cp)); 509*7c478bd9Sstevel@tonic-gate cp->uid = uid; 510*7c478bd9Sstevel@tonic-gate *cpp = cp; 511*7c478bd9Sstevel@tonic-gate } else { 512*7c478bd9Sstevel@tonic-gate cp = *cpp; 513*7c478bd9Sstevel@tonic-gate } 514*7c478bd9Sstevel@tonic-gate freekeybuf3(cp->secretkey); 515*7c478bd9Sstevel@tonic-gate if ((cp->secretkey = cpykeybuf3(&skey->key)) == NULL) { 516*7c478bd9Sstevel@tonic-gate mutex_unlock(&mp->mech_lock); 517*7c478bd9Sstevel@tonic-gate return (0); 518*7c478bd9Sstevel@tonic-gate } 519*7c478bd9Sstevel@tonic-gate freekeybuf3(cp->publickey); 520*7c478bd9Sstevel@tonic-gate if ((cp->publickey = cpykeybuf3(&nullkey)) == NULL) { 521*7c478bd9Sstevel@tonic-gate mutex_unlock(&mp->mech_lock); 522*7c478bd9Sstevel@tonic-gate return (0); 523*7c478bd9Sstevel@tonic-gate } 524*7c478bd9Sstevel@tonic-gate mutex_unlock(&mp->mech_lock); 525*7c478bd9Sstevel@tonic-gate return (1); 526*7c478bd9Sstevel@tonic-gate } 527*7c478bd9Sstevel@tonic-gate 528*7c478bd9Sstevel@tonic-gate /* 529*7c478bd9Sstevel@tonic-gate * Store the vers 3 secretkey for this uid 530*7c478bd9Sstevel@tonic-gate */ 531*7c478bd9Sstevel@tonic-gate static int 532*7c478bd9Sstevel@tonic-gate storesecretkey3(uid_t uid, setkeyarg3 *skey) 533*7c478bd9Sstevel@tonic-gate { 534*7c478bd9Sstevel@tonic-gate struct mechentry *mp; 535*7c478bd9Sstevel@tonic-gate 536*7c478bd9Sstevel@tonic-gate if (skey == NULL) { 537*7c478bd9Sstevel@tonic-gate return (0); 538*7c478bd9Sstevel@tonic-gate } 539*7c478bd9Sstevel@tonic-gate if ((mp = getmechtype(skey->keylen, skey->algtype)) == NULL) { 540*7c478bd9Sstevel@tonic-gate return (0); 541*7c478bd9Sstevel@tonic-gate } 542*7c478bd9Sstevel@tonic-gate return (appendsecretkey3(mp, uid, skey)); 543*7c478bd9Sstevel@tonic-gate } 544*7c478bd9Sstevel@tonic-gate 545*7c478bd9Sstevel@tonic-gate /* 546*7c478bd9Sstevel@tonic-gate * Set the vers 3 secretkey key for this uid 547*7c478bd9Sstevel@tonic-gate */ 548*7c478bd9Sstevel@tonic-gate keystatus 549*7c478bd9Sstevel@tonic-gate pk_setkey3(uid_t uid, setkeyarg3 *skey) 550*7c478bd9Sstevel@tonic-gate { 551*7c478bd9Sstevel@tonic-gate if (!storesecretkey3(uid, skey)) { 552*7c478bd9Sstevel@tonic-gate return (KEY_SYSTEMERR); 553*7c478bd9Sstevel@tonic-gate } 554*7c478bd9Sstevel@tonic-gate return (KEY_SUCCESS); 555*7c478bd9Sstevel@tonic-gate } 556*7c478bd9Sstevel@tonic-gate 557*7c478bd9Sstevel@tonic-gate /* 558*7c478bd9Sstevel@tonic-gate * Set the secretkey key for this uid 559*7c478bd9Sstevel@tonic-gate */ 560*7c478bd9Sstevel@tonic-gate keystatus 561*7c478bd9Sstevel@tonic-gate pk_setkey(uid, skey) 562*7c478bd9Sstevel@tonic-gate uid_t uid; 563*7c478bd9Sstevel@tonic-gate keybuf skey; 564*7c478bd9Sstevel@tonic-gate { 565*7c478bd9Sstevel@tonic-gate int storesecretkey(uid_t, keybuf); 566*7c478bd9Sstevel@tonic-gate 567*7c478bd9Sstevel@tonic-gate if (!storesecretkey(uid, skey)) { 568*7c478bd9Sstevel@tonic-gate return (KEY_SYSTEMERR); 569*7c478bd9Sstevel@tonic-gate } 570*7c478bd9Sstevel@tonic-gate return (KEY_SUCCESS); 571*7c478bd9Sstevel@tonic-gate } 572*7c478bd9Sstevel@tonic-gate 573*7c478bd9Sstevel@tonic-gate int 574*7c478bd9Sstevel@tonic-gate storeotherrootkeys(FILE *fp, char *netname, char *passwd, char *osecret) 575*7c478bd9Sstevel@tonic-gate { 576*7c478bd9Sstevel@tonic-gate des_block master; 577*7c478bd9Sstevel@tonic-gate struct keylenlist *kp; 578*7c478bd9Sstevel@tonic-gate struct algtypelist *ap; 579*7c478bd9Sstevel@tonic-gate keybuf3 *secret; 580*7c478bd9Sstevel@tonic-gate setkeyarg3 skey; 581*7c478bd9Sstevel@tonic-gate 582*7c478bd9Sstevel@tonic-gate debug(KEYSERV_DEBUG, ("storeotherrootkeys %s %s", 583*7c478bd9Sstevel@tonic-gate netname, passwd)); 584*7c478bd9Sstevel@tonic-gate passwd2des_g(passwd, netname, strlen(netname), &master, FALSE); 585*7c478bd9Sstevel@tonic-gate for (kp = mechtable.kp; kp != NULL; kp = kp->next) { 586*7c478bd9Sstevel@tonic-gate debug(KEYSERV_DEBUG0, 587*7c478bd9Sstevel@tonic-gate ("storeotherrootkeys key %d", kp->keylen)); 588*7c478bd9Sstevel@tonic-gate for (ap = kp->ap; ap != NULL; ap = ap->next) { 589*7c478bd9Sstevel@tonic-gate debug(KEYSERV_DEBUG, 590*7c478bd9Sstevel@tonic-gate ("storeotherrootkeys alg: %d", ap->algtype)); 591*7c478bd9Sstevel@tonic-gate if ((secret = getkeybuf3(kp->keylen/4+1)) == NULL) { 592*7c478bd9Sstevel@tonic-gate return (0); 593*7c478bd9Sstevel@tonic-gate } 594*7c478bd9Sstevel@tonic-gate debug(KEYSERV_DEBUG, 595*7c478bd9Sstevel@tonic-gate ("storeotherrootkeys calling getsecretkey_g")); 596*7c478bd9Sstevel@tonic-gate if (!getsecretkey_g(netname, 597*7c478bd9Sstevel@tonic-gate kp->keylen, ap->algtype, 598*7c478bd9Sstevel@tonic-gate secret->keybuf3_val, secret->keybuf3_len, 599*7c478bd9Sstevel@tonic-gate passwd)) { 600*7c478bd9Sstevel@tonic-gate debug(KEYSERV_INFO, 601*7c478bd9Sstevel@tonic-gate ("Can't find %s's secret key", netname)); 602*7c478bd9Sstevel@tonic-gate return (0); 603*7c478bd9Sstevel@tonic-gate } 604*7c478bd9Sstevel@tonic-gate if (*secret->keybuf3_val == 0) { /* XXX */ 605*7c478bd9Sstevel@tonic-gate debug(KEYSERV_INFO, 606*7c478bd9Sstevel@tonic-gate ("Password does not decrypt secret key for %s", 607*7c478bd9Sstevel@tonic-gate netname)); 608*7c478bd9Sstevel@tonic-gate return (0); 609*7c478bd9Sstevel@tonic-gate } 610*7c478bd9Sstevel@tonic-gate skey.key = *secret; 611*7c478bd9Sstevel@tonic-gate free(secret); /* but not the buffer it points to */ 612*7c478bd9Sstevel@tonic-gate skey.userkey = master; 613*7c478bd9Sstevel@tonic-gate skey.keylen = kp->keylen; 614*7c478bd9Sstevel@tonic-gate skey.algtype = ap->algtype; 615*7c478bd9Sstevel@tonic-gate if (CLASSIC_PK_DH(kp->keylen, ap->algtype)) { 616*7c478bd9Sstevel@tonic-gate pk_setkey((uid_t)0, osecret); 617*7c478bd9Sstevel@tonic-gate fprintf(fp, "%s\n", osecret); 618*7c478bd9Sstevel@tonic-gate } 619*7c478bd9Sstevel@tonic-gate if (pk_setkey3(0, &skey) != KEY_SUCCESS) { 620*7c478bd9Sstevel@tonic-gate return (0); 621*7c478bd9Sstevel@tonic-gate } 622*7c478bd9Sstevel@tonic-gate if (!CLASSIC_PK_DH(kp->keylen, ap->algtype)) { 623*7c478bd9Sstevel@tonic-gate fprintf(fp, "%s %d\n", skey.key.keybuf3_val, 624*7c478bd9Sstevel@tonic-gate ap->algtype); 625*7c478bd9Sstevel@tonic-gate } 626*7c478bd9Sstevel@tonic-gate } 627*7c478bd9Sstevel@tonic-gate } 628*7c478bd9Sstevel@tonic-gate return (1); 629*7c478bd9Sstevel@tonic-gate } 630*7c478bd9Sstevel@tonic-gate 631*7c478bd9Sstevel@tonic-gate /* 632*7c478bd9Sstevel@tonic-gate * prohibit the nobody key on this machine k (the -d flag) 633*7c478bd9Sstevel@tonic-gate */ 634*7c478bd9Sstevel@tonic-gate pk_nodefaultkeys() 635*7c478bd9Sstevel@tonic-gate { 636*7c478bd9Sstevel@tonic-gate nodefaultkeys = 1; 637*7c478bd9Sstevel@tonic-gate return (0); 638*7c478bd9Sstevel@tonic-gate } 639*7c478bd9Sstevel@tonic-gate 640*7c478bd9Sstevel@tonic-gate static void 641*7c478bd9Sstevel@tonic-gate freedisklist(struct cacheuid_list *cp) 642*7c478bd9Sstevel@tonic-gate { 643*7c478bd9Sstevel@tonic-gate if (cp == NULL) { 644*7c478bd9Sstevel@tonic-gate return; 645*7c478bd9Sstevel@tonic-gate } 646*7c478bd9Sstevel@tonic-gate free(cp->netname); /* ok even if this is NULL */ 647*7c478bd9Sstevel@tonic-gate freekeybuf3(cp->secretkey); 648*7c478bd9Sstevel@tonic-gate freekeybuf3(cp->publickey); 649*7c478bd9Sstevel@tonic-gate } 650*7c478bd9Sstevel@tonic-gate 651*7c478bd9Sstevel@tonic-gate keystatus 652*7c478bd9Sstevel@tonic-gate pk_clear3(uid_t uid) 653*7c478bd9Sstevel@tonic-gate { 654*7c478bd9Sstevel@tonic-gate struct keylenlist *kp; 655*7c478bd9Sstevel@tonic-gate struct algtypelist *ap; 656*7c478bd9Sstevel@tonic-gate struct mechdata *mdp; 657*7c478bd9Sstevel@tonic-gate struct cacheuid_list **cpp, *cp; 658*7c478bd9Sstevel@tonic-gate 659*7c478bd9Sstevel@tonic-gate debug(KEYSERV_DEBUG, ("pk_clear3 %d", uid)); 660*7c478bd9Sstevel@tonic-gate for (kp = mechtable.kp; kp != NULL; kp = kp->next) { 661*7c478bd9Sstevel@tonic-gate debug(KEYSERV_DEBUG0, ("pk_clear3 key %d", kp->keylen)); 662*7c478bd9Sstevel@tonic-gate for (ap = kp->ap; ap != NULL; ap = ap->next) { 663*7c478bd9Sstevel@tonic-gate debug(KEYSERV_DEBUG0, 664*7c478bd9Sstevel@tonic-gate ("pk_clear3 alg: %d", ap->algtype)); 665*7c478bd9Sstevel@tonic-gate mutex_lock(&ap->mech.mech_lock); 666*7c478bd9Sstevel@tonic-gate if ((mdp = ap->mech.mechdata) == NULL) { 667*7c478bd9Sstevel@tonic-gate mutex_unlock(&ap->mech.mech_lock); 668*7c478bd9Sstevel@tonic-gate continue; 669*7c478bd9Sstevel@tonic-gate } 670*7c478bd9Sstevel@tonic-gate cpp = mapuid2cache(uid, mdp); 671*7c478bd9Sstevel@tonic-gate if (*cpp == NULL) { 672*7c478bd9Sstevel@tonic-gate mutex_unlock(&ap->mech.mech_lock); 673*7c478bd9Sstevel@tonic-gate continue; 674*7c478bd9Sstevel@tonic-gate } 675*7c478bd9Sstevel@tonic-gate cp = (*cpp)->next; 676*7c478bd9Sstevel@tonic-gate freedisklist(*cpp); 677*7c478bd9Sstevel@tonic-gate *cpp = cp; 678*7c478bd9Sstevel@tonic-gate mutex_unlock(&ap->mech.mech_lock); 679*7c478bd9Sstevel@tonic-gate } 680*7c478bd9Sstevel@tonic-gate } 681*7c478bd9Sstevel@tonic-gate /* XXX clear stuff out of the common key cache as well? */ 682*7c478bd9Sstevel@tonic-gate /* XXX return success only if something was removed? */ 683*7c478bd9Sstevel@tonic-gate return (KEY_SUCCESS); 684*7c478bd9Sstevel@tonic-gate } 685*7c478bd9Sstevel@tonic-gate 686*7c478bd9Sstevel@tonic-gate /* 687*7c478bd9Sstevel@tonic-gate * Set the modulus for all our Diffie-Hellman operations 688*7c478bd9Sstevel@tonic-gate */ 689*7c478bd9Sstevel@tonic-gate setmodulus(modx) 690*7c478bd9Sstevel@tonic-gate char *modx; 691*7c478bd9Sstevel@tonic-gate { 692*7c478bd9Sstevel@tonic-gate MODULUS = mp_xtom(modx); 693*7c478bd9Sstevel@tonic-gate return (0); 694*7c478bd9Sstevel@tonic-gate } 695*7c478bd9Sstevel@tonic-gate 696*7c478bd9Sstevel@tonic-gate /* 697*7c478bd9Sstevel@tonic-gate * Encrypt the key using the public key associated with remote_name and the 698*7c478bd9Sstevel@tonic-gate * secret key associated with uid. 699*7c478bd9Sstevel@tonic-gate */ 700*7c478bd9Sstevel@tonic-gate keystatus 701*7c478bd9Sstevel@tonic-gate pk_encrypt(uid, remote_name, remote_key, key) 702*7c478bd9Sstevel@tonic-gate uid_t uid; 703*7c478bd9Sstevel@tonic-gate char *remote_name; 704*7c478bd9Sstevel@tonic-gate netobj *remote_key; 705*7c478bd9Sstevel@tonic-gate des_block *key; 706*7c478bd9Sstevel@tonic-gate { 707*7c478bd9Sstevel@tonic-gate return (pk_crypt(uid, remote_name, remote_key, key, DES_ENCRYPT)); 708*7c478bd9Sstevel@tonic-gate } 709*7c478bd9Sstevel@tonic-gate 710*7c478bd9Sstevel@tonic-gate /* 711*7c478bd9Sstevel@tonic-gate * Encrypt the key using the public key associated with remote_name and the 712*7c478bd9Sstevel@tonic-gate * secret key associated with uid using vers 3 713*7c478bd9Sstevel@tonic-gate */ 714*7c478bd9Sstevel@tonic-gate keystatus 715*7c478bd9Sstevel@tonic-gate pk_encrypt3( 716*7c478bd9Sstevel@tonic-gate uid_t uid, 717*7c478bd9Sstevel@tonic-gate cryptkeyarg3 *arg, 718*7c478bd9Sstevel@tonic-gate deskeyarray *key 719*7c478bd9Sstevel@tonic-gate ) 720*7c478bd9Sstevel@tonic-gate { 721*7c478bd9Sstevel@tonic-gate return (pk_crypt3(uid, arg, key, DES_ENCRYPT)); 722*7c478bd9Sstevel@tonic-gate } 723*7c478bd9Sstevel@tonic-gate 724*7c478bd9Sstevel@tonic-gate /* 725*7c478bd9Sstevel@tonic-gate * Decrypt the key using the public key associated with remote_name and the 726*7c478bd9Sstevel@tonic-gate * secret key associated with uid. 727*7c478bd9Sstevel@tonic-gate */ 728*7c478bd9Sstevel@tonic-gate keystatus 729*7c478bd9Sstevel@tonic-gate pk_decrypt(uid, remote_name, remote_key, key) 730*7c478bd9Sstevel@tonic-gate uid_t uid; 731*7c478bd9Sstevel@tonic-gate char *remote_name; 732*7c478bd9Sstevel@tonic-gate netobj *remote_key; 733*7c478bd9Sstevel@tonic-gate des_block *key; 734*7c478bd9Sstevel@tonic-gate { 735*7c478bd9Sstevel@tonic-gate return (pk_crypt(uid, remote_name, remote_key, key, DES_DECRYPT)); 736*7c478bd9Sstevel@tonic-gate } 737*7c478bd9Sstevel@tonic-gate 738*7c478bd9Sstevel@tonic-gate /* 739*7c478bd9Sstevel@tonic-gate * Decrypt the key using the public key associated with remote_name and the 740*7c478bd9Sstevel@tonic-gate * secret key associated with uid using vers 3 741*7c478bd9Sstevel@tonic-gate */ 742*7c478bd9Sstevel@tonic-gate keystatus 743*7c478bd9Sstevel@tonic-gate pk_decrypt3( 744*7c478bd9Sstevel@tonic-gate uid_t uid, 745*7c478bd9Sstevel@tonic-gate cryptkeyarg3 *arg, 746*7c478bd9Sstevel@tonic-gate deskeyarray *key 747*7c478bd9Sstevel@tonic-gate ) 748*7c478bd9Sstevel@tonic-gate { 749*7c478bd9Sstevel@tonic-gate return (pk_crypt3(uid, arg, key, DES_DECRYPT)); 750*7c478bd9Sstevel@tonic-gate } 751*7c478bd9Sstevel@tonic-gate 752*7c478bd9Sstevel@tonic-gate /* 753*7c478bd9Sstevel@tonic-gate * Key storage management 754*7c478bd9Sstevel@tonic-gate */ 755*7c478bd9Sstevel@tonic-gate 756*7c478bd9Sstevel@tonic-gate #define KEY_ONLY 0 757*7c478bd9Sstevel@tonic-gate #define KEY_NAME 1 758*7c478bd9Sstevel@tonic-gate struct secretkey_netname_list { 759*7c478bd9Sstevel@tonic-gate uid_t uid; 760*7c478bd9Sstevel@tonic-gate key_netstarg keynetdata; 761*7c478bd9Sstevel@tonic-gate uchar_t sc_flag; 762*7c478bd9Sstevel@tonic-gate struct secretkey_netname_list *next; 763*7c478bd9Sstevel@tonic-gate }; 764*7c478bd9Sstevel@tonic-gate 765*7c478bd9Sstevel@tonic-gate #define HASH_UID(x) (x & 0xff) 766*7c478bd9Sstevel@tonic-gate static struct secretkey_netname_list *g_secretkey_netname[KEY_HASH_SIZE]; 767*7c478bd9Sstevel@tonic-gate static rwlock_t g_secretkey_netname_lock = DEFAULTRWLOCK; 768*7c478bd9Sstevel@tonic-gate 769*7c478bd9Sstevel@tonic-gate /* 770*7c478bd9Sstevel@tonic-gate * Store the keys and netname for this uid 771*7c478bd9Sstevel@tonic-gate */ 772*7c478bd9Sstevel@tonic-gate static int 773*7c478bd9Sstevel@tonic-gate store_netname(uid, netstore) 774*7c478bd9Sstevel@tonic-gate uid_t uid; 775*7c478bd9Sstevel@tonic-gate key_netstarg *netstore; 776*7c478bd9Sstevel@tonic-gate { 777*7c478bd9Sstevel@tonic-gate struct secretkey_netname_list *new; 778*7c478bd9Sstevel@tonic-gate struct secretkey_netname_list **l; 779*7c478bd9Sstevel@tonic-gate int hash = HASH_UID(uid); 780*7c478bd9Sstevel@tonic-gate 781*7c478bd9Sstevel@tonic-gate (void) rw_wrlock(&g_secretkey_netname_lock); 782*7c478bd9Sstevel@tonic-gate for (l = &g_secretkey_netname[hash]; *l != NULL && (*l)->uid != uid; 783*7c478bd9Sstevel@tonic-gate l = &(*l)->next) { 784*7c478bd9Sstevel@tonic-gate } 785*7c478bd9Sstevel@tonic-gate if (*l == NULL) { 786*7c478bd9Sstevel@tonic-gate /* LINTED pointer alignment */ 787*7c478bd9Sstevel@tonic-gate new = (struct secretkey_netname_list *)malloc(sizeof (*new)); 788*7c478bd9Sstevel@tonic-gate if (new == NULL) { 789*7c478bd9Sstevel@tonic-gate (void) rw_unlock(&g_secretkey_netname_lock); 790*7c478bd9Sstevel@tonic-gate return (0); 791*7c478bd9Sstevel@tonic-gate } 792*7c478bd9Sstevel@tonic-gate new->uid = uid; 793*7c478bd9Sstevel@tonic-gate new->next = NULL; 794*7c478bd9Sstevel@tonic-gate *l = new; 795*7c478bd9Sstevel@tonic-gate } else { 796*7c478bd9Sstevel@tonic-gate new = *l; 797*7c478bd9Sstevel@tonic-gate if (new->keynetdata.st_netname) 798*7c478bd9Sstevel@tonic-gate (void) free(new->keynetdata.st_netname); 799*7c478bd9Sstevel@tonic-gate } 800*7c478bd9Sstevel@tonic-gate memcpy(new->keynetdata.st_priv_key, netstore->st_priv_key, 801*7c478bd9Sstevel@tonic-gate HEXKEYBYTES); 802*7c478bd9Sstevel@tonic-gate memcpy(new->keynetdata.st_pub_key, netstore->st_pub_key, HEXKEYBYTES); 803*7c478bd9Sstevel@tonic-gate 804*7c478bd9Sstevel@tonic-gate if (netstore->st_netname) 805*7c478bd9Sstevel@tonic-gate new->keynetdata.st_netname = strdup(netstore->st_netname); 806*7c478bd9Sstevel@tonic-gate else 807*7c478bd9Sstevel@tonic-gate new->keynetdata.st_netname = (char *)NULL; 808*7c478bd9Sstevel@tonic-gate new->sc_flag = KEY_NAME; 809*7c478bd9Sstevel@tonic-gate (void) rw_unlock(&g_secretkey_netname_lock); 810*7c478bd9Sstevel@tonic-gate return (1); 811*7c478bd9Sstevel@tonic-gate 812*7c478bd9Sstevel@tonic-gate } 813*7c478bd9Sstevel@tonic-gate 814*7c478bd9Sstevel@tonic-gate static int 815*7c478bd9Sstevel@tonic-gate appendnetname3(struct mechentry *mp, uid_t uid, key_netstarg3 *net) 816*7c478bd9Sstevel@tonic-gate { 817*7c478bd9Sstevel@tonic-gate struct mechdata *mdp; 818*7c478bd9Sstevel@tonic-gate struct cacheuid_list **cpp, *cp; 819*7c478bd9Sstevel@tonic-gate 820*7c478bd9Sstevel@tonic-gate debug(KEYSERV_DEBUG, ("appendnetname3 %x", mp)); 821*7c478bd9Sstevel@tonic-gate if ((mp == NULL) || (net == NULL)) { 822*7c478bd9Sstevel@tonic-gate return (0); 823*7c478bd9Sstevel@tonic-gate } 824*7c478bd9Sstevel@tonic-gate mutex_lock(&mp->mech_lock); 825*7c478bd9Sstevel@tonic-gate if ((mdp = mp->mechdata) == NULL) { 826*7c478bd9Sstevel@tonic-gate mdp = (struct mechdata *)calloc(1, sizeof (*mdp)); 827*7c478bd9Sstevel@tonic-gate if (mdp == NULL) { 828*7c478bd9Sstevel@tonic-gate mutex_unlock(&mp->mech_lock); 829*7c478bd9Sstevel@tonic-gate debug(KEYSERV_INFO, ("appendnetname3 : calloc failed")); 830*7c478bd9Sstevel@tonic-gate return (0); 831*7c478bd9Sstevel@tonic-gate } 832*7c478bd9Sstevel@tonic-gate mp->mechdata = mdp; 833*7c478bd9Sstevel@tonic-gate } 834*7c478bd9Sstevel@tonic-gate cpp = mapuid2cache(uid, mdp); 835*7c478bd9Sstevel@tonic-gate if (*cpp == NULL) { 836*7c478bd9Sstevel@tonic-gate cp = (struct cacheuid_list *)malloc(sizeof (*cp)); 837*7c478bd9Sstevel@tonic-gate if (cp == NULL) { 838*7c478bd9Sstevel@tonic-gate mutex_unlock(&mp->mech_lock); 839*7c478bd9Sstevel@tonic-gate debug(KEYSERV_INFO, ("appendnetname3 : malloc failed")); 840*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, "file %s line %d: malloc failed", 841*7c478bd9Sstevel@tonic-gate __FILE__, __LINE__); 842*7c478bd9Sstevel@tonic-gate return (0); 843*7c478bd9Sstevel@tonic-gate } 844*7c478bd9Sstevel@tonic-gate memset(cp, 0, sizeof (*cp)); 845*7c478bd9Sstevel@tonic-gate cp->uid = uid; 846*7c478bd9Sstevel@tonic-gate *cpp = cp; 847*7c478bd9Sstevel@tonic-gate } else { 848*7c478bd9Sstevel@tonic-gate cp = *cpp; 849*7c478bd9Sstevel@tonic-gate } 850*7c478bd9Sstevel@tonic-gate freekeybuf3(cp->secretkey); 851*7c478bd9Sstevel@tonic-gate if ((cp->secretkey = cpykeybuf3(&net->st_priv_key)) == NULL) { 852*7c478bd9Sstevel@tonic-gate mutex_unlock(&mp->mech_lock); 853*7c478bd9Sstevel@tonic-gate return (0); 854*7c478bd9Sstevel@tonic-gate } 855*7c478bd9Sstevel@tonic-gate freekeybuf3(cp->publickey); 856*7c478bd9Sstevel@tonic-gate if ((cp->publickey = cpykeybuf3(&net->st_pub_key)) == NULL) { 857*7c478bd9Sstevel@tonic-gate mutex_unlock(&mp->mech_lock); 858*7c478bd9Sstevel@tonic-gate return (0); 859*7c478bd9Sstevel@tonic-gate } 860*7c478bd9Sstevel@tonic-gate free(cp->netname); 861*7c478bd9Sstevel@tonic-gate if (net->st_netname) { 862*7c478bd9Sstevel@tonic-gate cp->netname = strdup(net->st_netname); 863*7c478bd9Sstevel@tonic-gate } else { 864*7c478bd9Sstevel@tonic-gate cp->netname = (char *)NULL; 865*7c478bd9Sstevel@tonic-gate } 866*7c478bd9Sstevel@tonic-gate mutex_unlock(&mp->mech_lock); 867*7c478bd9Sstevel@tonic-gate return (1); 868*7c478bd9Sstevel@tonic-gate } 869*7c478bd9Sstevel@tonic-gate 870*7c478bd9Sstevel@tonic-gate keystatus 871*7c478bd9Sstevel@tonic-gate pk_netput(uid, netstore) 872*7c478bd9Sstevel@tonic-gate uid_t uid; 873*7c478bd9Sstevel@tonic-gate key_netstarg *netstore; 874*7c478bd9Sstevel@tonic-gate { 875*7c478bd9Sstevel@tonic-gate 876*7c478bd9Sstevel@tonic-gate if (!store_netname(uid, netstore)) { 877*7c478bd9Sstevel@tonic-gate return (KEY_SYSTEMERR); 878*7c478bd9Sstevel@tonic-gate } 879*7c478bd9Sstevel@tonic-gate return (KEY_SUCCESS); 880*7c478bd9Sstevel@tonic-gate } 881*7c478bd9Sstevel@tonic-gate 882*7c478bd9Sstevel@tonic-gate /* 883*7c478bd9Sstevel@tonic-gate * Store the keys and netname for this uid vers 3 884*7c478bd9Sstevel@tonic-gate */ 885*7c478bd9Sstevel@tonic-gate static int 886*7c478bd9Sstevel@tonic-gate store_netname3(uid_t uid, key_netstarg3 *net) 887*7c478bd9Sstevel@tonic-gate { 888*7c478bd9Sstevel@tonic-gate struct mechentry *mp; 889*7c478bd9Sstevel@tonic-gate key_netstarg netstore; 890*7c478bd9Sstevel@tonic-gate 891*7c478bd9Sstevel@tonic-gate if (net == NULL) { 892*7c478bd9Sstevel@tonic-gate return (0); 893*7c478bd9Sstevel@tonic-gate } 894*7c478bd9Sstevel@tonic-gate if ((mp = getmechtype(net->keylen, net->algtype)) == NULL) { 895*7c478bd9Sstevel@tonic-gate return (0); 896*7c478bd9Sstevel@tonic-gate } 897*7c478bd9Sstevel@tonic-gate if (uid == 0 && CLASSIC_PK_DH(net->keylen, net->algtype)) { 898*7c478bd9Sstevel@tonic-gate memcpy(netstore.st_priv_key, net->st_priv_key.keybuf3_val, 899*7c478bd9Sstevel@tonic-gate HEXKEYBYTES); 900*7c478bd9Sstevel@tonic-gate memset(netstore.st_pub_key, 0, HEXKEYBYTES); 901*7c478bd9Sstevel@tonic-gate netstore.st_netname = net->st_netname; 902*7c478bd9Sstevel@tonic-gate if (pk_netput(uid, &netstore) != KEY_SUCCESS) { 903*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 904*7c478bd9Sstevel@tonic-gate "keyserv: could not set root's key and netname.\n"); 905*7c478bd9Sstevel@tonic-gate return (0); 906*7c478bd9Sstevel@tonic-gate } 907*7c478bd9Sstevel@tonic-gate } 908*7c478bd9Sstevel@tonic-gate return (appendnetname3(mp, uid, net)); 909*7c478bd9Sstevel@tonic-gate } 910*7c478bd9Sstevel@tonic-gate 911*7c478bd9Sstevel@tonic-gate keystatus 912*7c478bd9Sstevel@tonic-gate pk_netput3(uid_t uid, key_netstarg3 *netstore) 913*7c478bd9Sstevel@tonic-gate { 914*7c478bd9Sstevel@tonic-gate 915*7c478bd9Sstevel@tonic-gate if (!store_netname3(uid, netstore)) { 916*7c478bd9Sstevel@tonic-gate return (KEY_SYSTEMERR); 917*7c478bd9Sstevel@tonic-gate } 918*7c478bd9Sstevel@tonic-gate return (KEY_SUCCESS); 919*7c478bd9Sstevel@tonic-gate } 920*7c478bd9Sstevel@tonic-gate 921*7c478bd9Sstevel@tonic-gate int 922*7c478bd9Sstevel@tonic-gate addmasterkey(char *master, char *netname, algtype_t algtype) 923*7c478bd9Sstevel@tonic-gate { 924*7c478bd9Sstevel@tonic-gate keybuf3 *secret, *public; 925*7c478bd9Sstevel@tonic-gate int bytelen = strlen(master); 926*7c478bd9Sstevel@tonic-gate keylen_t keylen = bytelen*4; 927*7c478bd9Sstevel@tonic-gate key_netstarg3 tmp; 928*7c478bd9Sstevel@tonic-gate 929*7c478bd9Sstevel@tonic-gate if ((secret = setkeybuf3(master, bytelen)) == NULL) { 930*7c478bd9Sstevel@tonic-gate return (0); 931*7c478bd9Sstevel@tonic-gate } 932*7c478bd9Sstevel@tonic-gate if ((public = getkeybuf3(bytelen+1)) == NULL) { 933*7c478bd9Sstevel@tonic-gate /* the +1 is mandated by getpublickey_g() */ 934*7c478bd9Sstevel@tonic-gate return (0); 935*7c478bd9Sstevel@tonic-gate } 936*7c478bd9Sstevel@tonic-gate /* 937*7c478bd9Sstevel@tonic-gate * getpublickey_g(netname, keylen, algtype, 938*7c478bd9Sstevel@tonic-gate * public->keybuf3_val, public->keybuf3_len); 939*7c478bd9Sstevel@tonic-gate * cannot be called since rpc.nisd is not up yet 940*7c478bd9Sstevel@tonic-gate * so we continue to return a zero filled public key 941*7c478bd9Sstevel@tonic-gate * as in the earlier version 942*7c478bd9Sstevel@tonic-gate */ 943*7c478bd9Sstevel@tonic-gate memset(public->keybuf3_val, 0, bytelen+1); 944*7c478bd9Sstevel@tonic-gate tmp.st_priv_key = *secret; 945*7c478bd9Sstevel@tonic-gate free(secret); 946*7c478bd9Sstevel@tonic-gate tmp.st_pub_key = *public; 947*7c478bd9Sstevel@tonic-gate free(public); 948*7c478bd9Sstevel@tonic-gate tmp.st_netname = strdup(netname); 949*7c478bd9Sstevel@tonic-gate tmp.keylen = keylen; 950*7c478bd9Sstevel@tonic-gate tmp.algtype = algtype; 951*7c478bd9Sstevel@tonic-gate return (store_netname3(0, &tmp)); 952*7c478bd9Sstevel@tonic-gate } 953*7c478bd9Sstevel@tonic-gate 954*7c478bd9Sstevel@tonic-gate /* 955*7c478bd9Sstevel@tonic-gate * Fetch the keys and netname for this uid 956*7c478bd9Sstevel@tonic-gate */ 957*7c478bd9Sstevel@tonic-gate static int 958*7c478bd9Sstevel@tonic-gate fetch_netname(uid, key_netst) 959*7c478bd9Sstevel@tonic-gate uid_t uid; 960*7c478bd9Sstevel@tonic-gate struct key_netstarg *key_netst; 961*7c478bd9Sstevel@tonic-gate { 962*7c478bd9Sstevel@tonic-gate struct secretkey_netname_list *l; 963*7c478bd9Sstevel@tonic-gate int hash = HASH_UID(uid); 964*7c478bd9Sstevel@tonic-gate 965*7c478bd9Sstevel@tonic-gate (void) rw_rdlock(&g_secretkey_netname_lock); 966*7c478bd9Sstevel@tonic-gate for (l = g_secretkey_netname[hash]; l != NULL; l = l->next) { 967*7c478bd9Sstevel@tonic-gate if ((l->uid == uid) && (l->sc_flag == KEY_NAME)) { 968*7c478bd9Sstevel@tonic-gate 969*7c478bd9Sstevel@tonic-gate memcpy(key_netst->st_priv_key, 970*7c478bd9Sstevel@tonic-gate l->keynetdata.st_priv_key, HEXKEYBYTES); 971*7c478bd9Sstevel@tonic-gate 972*7c478bd9Sstevel@tonic-gate memcpy(key_netst->st_pub_key, 973*7c478bd9Sstevel@tonic-gate l->keynetdata.st_pub_key, HEXKEYBYTES); 974*7c478bd9Sstevel@tonic-gate 975*7c478bd9Sstevel@tonic-gate if (l->keynetdata.st_netname) 976*7c478bd9Sstevel@tonic-gate strcpy(key_netst->st_netname, 977*7c478bd9Sstevel@tonic-gate l->keynetdata.st_netname); 978*7c478bd9Sstevel@tonic-gate else 979*7c478bd9Sstevel@tonic-gate key_netst->st_netname = NULL; 980*7c478bd9Sstevel@tonic-gate (void) rw_unlock(&g_secretkey_netname_lock); 981*7c478bd9Sstevel@tonic-gate return (1); 982*7c478bd9Sstevel@tonic-gate } 983*7c478bd9Sstevel@tonic-gate } 984*7c478bd9Sstevel@tonic-gate (void) rw_unlock(&g_secretkey_netname_lock); 985*7c478bd9Sstevel@tonic-gate return (0); 986*7c478bd9Sstevel@tonic-gate } 987*7c478bd9Sstevel@tonic-gate 988*7c478bd9Sstevel@tonic-gate static void 989*7c478bd9Sstevel@tonic-gate remove_ref(struct cacheuid_list *cp) 990*7c478bd9Sstevel@tonic-gate { 991*7c478bd9Sstevel@tonic-gate debug(KEYSERV_DEBUG0, ("remove_ref %x", cp)); 992*7c478bd9Sstevel@tonic-gate /* 993*7c478bd9Sstevel@tonic-gate * XXX 994*7c478bd9Sstevel@tonic-gate * if we are going to do this along the lines of vn_rele, 995*7c478bd9Sstevel@tonic-gate * more stuff needs to be done here and the access to refcnt 996*7c478bd9Sstevel@tonic-gate * needs to be mutex locked. Keep it simple for now. 997*7c478bd9Sstevel@tonic-gate */ 998*7c478bd9Sstevel@tonic-gate cp->refcnt--; 999*7c478bd9Sstevel@tonic-gate } 1000*7c478bd9Sstevel@tonic-gate 1001*7c478bd9Sstevel@tonic-gate static void 1002*7c478bd9Sstevel@tonic-gate add_ref(struct cacheuid_list **cpp) 1003*7c478bd9Sstevel@tonic-gate { 1004*7c478bd9Sstevel@tonic-gate struct cacheuid_list *cp; 1005*7c478bd9Sstevel@tonic-gate 1006*7c478bd9Sstevel@tonic-gate if (cpp == NULL) { 1007*7c478bd9Sstevel@tonic-gate return; 1008*7c478bd9Sstevel@tonic-gate } 1009*7c478bd9Sstevel@tonic-gate /*LINTED assignment operator "=" found where "==" was expected*/ 1010*7c478bd9Sstevel@tonic-gate if (cp = *cpp) { 1011*7c478bd9Sstevel@tonic-gate debug(KEYSERV_DEBUG0, ("add_ref %x", cp)); 1012*7c478bd9Sstevel@tonic-gate cp->refcnt++; 1013*7c478bd9Sstevel@tonic-gate } 1014*7c478bd9Sstevel@tonic-gate } 1015*7c478bd9Sstevel@tonic-gate 1016*7c478bd9Sstevel@tonic-gate static struct cacheuid_list * 1017*7c478bd9Sstevel@tonic-gate getcachekey3(uid_t uid, struct mechentry *mp) 1018*7c478bd9Sstevel@tonic-gate { 1019*7c478bd9Sstevel@tonic-gate struct cacheuid_list **cpp, *cp; 1020*7c478bd9Sstevel@tonic-gate struct mechdata *mdp; 1021*7c478bd9Sstevel@tonic-gate 1022*7c478bd9Sstevel@tonic-gate debug(KEYSERV_DEBUG1, ("getcachekey3 %d %x", uid, mp)); 1023*7c478bd9Sstevel@tonic-gate if (mp == NULL) { 1024*7c478bd9Sstevel@tonic-gate return (0); 1025*7c478bd9Sstevel@tonic-gate } 1026*7c478bd9Sstevel@tonic-gate mutex_lock(&mp->mech_lock); 1027*7c478bd9Sstevel@tonic-gate if ((mdp = mp->mechdata) == NULL) { 1028*7c478bd9Sstevel@tonic-gate mutex_unlock(&mp->mech_lock); 1029*7c478bd9Sstevel@tonic-gate debug(KEYSERV_DEBUG0, ("getcachekey3 ret 0")); 1030*7c478bd9Sstevel@tonic-gate return (0); 1031*7c478bd9Sstevel@tonic-gate } 1032*7c478bd9Sstevel@tonic-gate cpp = mapuid2cache(uid, mdp); 1033*7c478bd9Sstevel@tonic-gate cp = *cpp; 1034*7c478bd9Sstevel@tonic-gate add_ref(cpp); 1035*7c478bd9Sstevel@tonic-gate mutex_unlock(&mp->mech_lock); 1036*7c478bd9Sstevel@tonic-gate debug(KEYSERV_DEBUG0, ("getcachekey3 ret %x", *cpp)); 1037*7c478bd9Sstevel@tonic-gate return (cp); 1038*7c478bd9Sstevel@tonic-gate } 1039*7c478bd9Sstevel@tonic-gate 1040*7c478bd9Sstevel@tonic-gate /* 1041*7c478bd9Sstevel@tonic-gate * Fetch any available cache for this uid (vers 3) 1042*7c478bd9Sstevel@tonic-gate */ 1043*7c478bd9Sstevel@tonic-gate static struct cacheuid_list * 1044*7c478bd9Sstevel@tonic-gate getanycache3(uid_t uid) 1045*7c478bd9Sstevel@tonic-gate { 1046*7c478bd9Sstevel@tonic-gate struct keylenlist *kp; 1047*7c478bd9Sstevel@tonic-gate struct algtypelist *ap; 1048*7c478bd9Sstevel@tonic-gate struct mechdata *mdp; 1049*7c478bd9Sstevel@tonic-gate struct cacheuid_list **cpp, *cp; 1050*7c478bd9Sstevel@tonic-gate 1051*7c478bd9Sstevel@tonic-gate debug(KEYSERV_DEBUG, ("getanycache3 %d", uid)); 1052*7c478bd9Sstevel@tonic-gate for (kp = mechtable.kp; kp != NULL; kp = kp->next) { 1053*7c478bd9Sstevel@tonic-gate debug(KEYSERV_DEBUG0, ("getanycache3 key %d", kp->keylen)); 1054*7c478bd9Sstevel@tonic-gate for (ap = kp->ap; ap != NULL; ap = ap->next) { 1055*7c478bd9Sstevel@tonic-gate debug(KEYSERV_DEBUG0, 1056*7c478bd9Sstevel@tonic-gate ("getanycache3 alg: %d", ap->algtype)); 1057*7c478bd9Sstevel@tonic-gate mutex_lock(&ap->mech.mech_lock); 1058*7c478bd9Sstevel@tonic-gate if ((mdp = ap->mech.mechdata) == NULL) { 1059*7c478bd9Sstevel@tonic-gate mutex_unlock(&ap->mech.mech_lock); 1060*7c478bd9Sstevel@tonic-gate continue; 1061*7c478bd9Sstevel@tonic-gate } 1062*7c478bd9Sstevel@tonic-gate cpp = mapuid2cache(uid, mdp); 1063*7c478bd9Sstevel@tonic-gate if (*cpp == NULL) { 1064*7c478bd9Sstevel@tonic-gate mutex_unlock(&ap->mech.mech_lock); 1065*7c478bd9Sstevel@tonic-gate continue; 1066*7c478bd9Sstevel@tonic-gate } 1067*7c478bd9Sstevel@tonic-gate cp = *cpp; 1068*7c478bd9Sstevel@tonic-gate cp->refcnt++; 1069*7c478bd9Sstevel@tonic-gate mutex_unlock(&ap->mech.mech_lock); 1070*7c478bd9Sstevel@tonic-gate return (cp); 1071*7c478bd9Sstevel@tonic-gate } 1072*7c478bd9Sstevel@tonic-gate } 1073*7c478bd9Sstevel@tonic-gate return (NULL); 1074*7c478bd9Sstevel@tonic-gate } 1075*7c478bd9Sstevel@tonic-gate 1076*7c478bd9Sstevel@tonic-gate static struct cacheuid_list * 1077*7c478bd9Sstevel@tonic-gate fetchcache3(uid_t uid, keylen_t k, algtype_t a) 1078*7c478bd9Sstevel@tonic-gate { 1079*7c478bd9Sstevel@tonic-gate struct mechentry *mp; 1080*7c478bd9Sstevel@tonic-gate struct cacheuid_list *cp; 1081*7c478bd9Sstevel@tonic-gate 1082*7c478bd9Sstevel@tonic-gate debug(KEYSERV_DEBUG, ("fetchcache3 %d %d %d", uid, k, a)); 1083*7c478bd9Sstevel@tonic-gate if ((mp = getmechtype(k, a)) == NULL) { 1084*7c478bd9Sstevel@tonic-gate return (NULL); 1085*7c478bd9Sstevel@tonic-gate } 1086*7c478bd9Sstevel@tonic-gate if ((cp = getcachekey3(uid, mp)) == NULL) { 1087*7c478bd9Sstevel@tonic-gate return (NULL); 1088*7c478bd9Sstevel@tonic-gate } 1089*7c478bd9Sstevel@tonic-gate debug(KEYSERV_DEBUG, ("fetchcache3 ret %x", cp)); 1090*7c478bd9Sstevel@tonic-gate return (cp); 1091*7c478bd9Sstevel@tonic-gate } 1092*7c478bd9Sstevel@tonic-gate 1093*7c478bd9Sstevel@tonic-gate /* 1094*7c478bd9Sstevel@tonic-gate * Fetch the keys and netname for this uid vers 3 1095*7c478bd9Sstevel@tonic-gate */ 1096*7c478bd9Sstevel@tonic-gate static int 1097*7c478bd9Sstevel@tonic-gate fetch_netname3(uid_t uid, mechtype *net, key_netstarg3 *ret) 1098*7c478bd9Sstevel@tonic-gate { 1099*7c478bd9Sstevel@tonic-gate struct cacheuid_list *cp; 1100*7c478bd9Sstevel@tonic-gate 1101*7c478bd9Sstevel@tonic-gate if ((net == NULL) || (ret == NULL)) { 1102*7c478bd9Sstevel@tonic-gate return (0); 1103*7c478bd9Sstevel@tonic-gate } 1104*7c478bd9Sstevel@tonic-gate debug(KEYSERV_DEBUG, ("fetch_netname3 %d %d %d", 1105*7c478bd9Sstevel@tonic-gate uid, net->keylen, net->algtype)); 1106*7c478bd9Sstevel@tonic-gate if (net->keylen == 0) { 1107*7c478bd9Sstevel@tonic-gate cp = getanycache3(uid); 1108*7c478bd9Sstevel@tonic-gate } else { 1109*7c478bd9Sstevel@tonic-gate cp = fetchcache3(uid, net->keylen, net->algtype); 1110*7c478bd9Sstevel@tonic-gate } 1111*7c478bd9Sstevel@tonic-gate debug(KEYSERV_DEBUG, ("fetch_netname3 cp %x", cp)); 1112*7c478bd9Sstevel@tonic-gate if (cp == NULL) { 1113*7c478bd9Sstevel@tonic-gate return (0); 1114*7c478bd9Sstevel@tonic-gate } 1115*7c478bd9Sstevel@tonic-gate debug(KEYSERV_DEBUG, ("fetch_netname3 sec %x", cp->secretkey)); 1116*7c478bd9Sstevel@tonic-gate if (!storekeybuf3(&ret->st_priv_key, cp->secretkey)) { 1117*7c478bd9Sstevel@tonic-gate return (0); 1118*7c478bd9Sstevel@tonic-gate } 1119*7c478bd9Sstevel@tonic-gate debug(KEYSERV_DEBUG, ("fetch_netname3 pub %x", cp->publickey)); 1120*7c478bd9Sstevel@tonic-gate if (!storekeybuf3(&ret->st_pub_key, cp->publickey)) { 1121*7c478bd9Sstevel@tonic-gate return (0); 1122*7c478bd9Sstevel@tonic-gate } 1123*7c478bd9Sstevel@tonic-gate if (cp->netname) { 1124*7c478bd9Sstevel@tonic-gate debug(KEYSERV_DEBUG, ("fetch_netname3 net %s", cp->netname)); 1125*7c478bd9Sstevel@tonic-gate ret->st_netname = strdup(cp->netname); 1126*7c478bd9Sstevel@tonic-gate } else { 1127*7c478bd9Sstevel@tonic-gate ret->st_netname = NULL; 1128*7c478bd9Sstevel@tonic-gate } 1129*7c478bd9Sstevel@tonic-gate remove_ref(cp); 1130*7c478bd9Sstevel@tonic-gate return (1); 1131*7c478bd9Sstevel@tonic-gate } 1132*7c478bd9Sstevel@tonic-gate 1133*7c478bd9Sstevel@tonic-gate keystatus 1134*7c478bd9Sstevel@tonic-gate pk_netget(uid, netstore) 1135*7c478bd9Sstevel@tonic-gate uid_t uid; 1136*7c478bd9Sstevel@tonic-gate key_netstarg *netstore; 1137*7c478bd9Sstevel@tonic-gate { 1138*7c478bd9Sstevel@tonic-gate if (!fetch_netname(uid, netstore)) { 1139*7c478bd9Sstevel@tonic-gate return (KEY_SYSTEMERR); 1140*7c478bd9Sstevel@tonic-gate } 1141*7c478bd9Sstevel@tonic-gate return (KEY_SUCCESS); 1142*7c478bd9Sstevel@tonic-gate } 1143*7c478bd9Sstevel@tonic-gate 1144*7c478bd9Sstevel@tonic-gate keystatus 1145*7c478bd9Sstevel@tonic-gate pk_netget3(uid_t uid, mechtype *net, key_netstarg3 *ret) 1146*7c478bd9Sstevel@tonic-gate { 1147*7c478bd9Sstevel@tonic-gate if (!fetch_netname3(uid, net, ret)) { 1148*7c478bd9Sstevel@tonic-gate return (KEY_SYSTEMERR); 1149*7c478bd9Sstevel@tonic-gate } 1150*7c478bd9Sstevel@tonic-gate return (KEY_SUCCESS); 1151*7c478bd9Sstevel@tonic-gate } 1152*7c478bd9Sstevel@tonic-gate 1153*7c478bd9Sstevel@tonic-gate #define cachehit(pub, sec, list) \ 1154*7c478bd9Sstevel@tonic-gate (memcmp(pub, (list)->public, sizeof (keybuf)) == 0 && \ 1155*7c478bd9Sstevel@tonic-gate memcmp(sec, (list)->secret, sizeof (keybuf)) == 0) 1156*7c478bd9Sstevel@tonic-gate 1157*7c478bd9Sstevel@tonic-gate /* 1158*7c478bd9Sstevel@tonic-gate * Try to find the common key in the cache 1159*7c478bd9Sstevel@tonic-gate */ 1160*7c478bd9Sstevel@tonic-gate static 1161*7c478bd9Sstevel@tonic-gate readcache(pub, sec, deskey, hash) 1162*7c478bd9Sstevel@tonic-gate char *pub; 1163*7c478bd9Sstevel@tonic-gate char *sec; 1164*7c478bd9Sstevel@tonic-gate des_block *deskey; 1165*7c478bd9Sstevel@tonic-gate int hash; 1166*7c478bd9Sstevel@tonic-gate { 1167*7c478bd9Sstevel@tonic-gate register struct cachekey_list **l; 1168*7c478bd9Sstevel@tonic-gate 1169*7c478bd9Sstevel@tonic-gate for (l = &g_cachedkeys[hash]; (*l) != NULL && !cachehit(pub, sec, *l); 1170*7c478bd9Sstevel@tonic-gate l = &(*l)->next) 1171*7c478bd9Sstevel@tonic-gate ; 1172*7c478bd9Sstevel@tonic-gate if ((*l) == NULL) 1173*7c478bd9Sstevel@tonic-gate return (0); 1174*7c478bd9Sstevel@tonic-gate *deskey = (*l)->deskey; 1175*7c478bd9Sstevel@tonic-gate return (1); 1176*7c478bd9Sstevel@tonic-gate } 1177*7c478bd9Sstevel@tonic-gate 1178*7c478bd9Sstevel@tonic-gate /* 1179*7c478bd9Sstevel@tonic-gate * cache result of expensive multiple precision exponential operation 1180*7c478bd9Sstevel@tonic-gate */ 1181*7c478bd9Sstevel@tonic-gate static 1182*7c478bd9Sstevel@tonic-gate writecache(pub, sec, deskey, hash) 1183*7c478bd9Sstevel@tonic-gate char *pub; 1184*7c478bd9Sstevel@tonic-gate char *sec; 1185*7c478bd9Sstevel@tonic-gate des_block *deskey; 1186*7c478bd9Sstevel@tonic-gate int hash; 1187*7c478bd9Sstevel@tonic-gate { 1188*7c478bd9Sstevel@tonic-gate struct cachekey_list *new; 1189*7c478bd9Sstevel@tonic-gate 1190*7c478bd9Sstevel@tonic-gate new = (struct cachekey_list *)malloc(sizeof (struct cachekey_list)); 1191*7c478bd9Sstevel@tonic-gate if (new == NULL) { 1192*7c478bd9Sstevel@tonic-gate return (0); 1193*7c478bd9Sstevel@tonic-gate } 1194*7c478bd9Sstevel@tonic-gate memcpy(new->public, pub, sizeof (keybuf)); 1195*7c478bd9Sstevel@tonic-gate memcpy(new->secret, sec, sizeof (keybuf)); 1196*7c478bd9Sstevel@tonic-gate new->deskey = *deskey; 1197*7c478bd9Sstevel@tonic-gate 1198*7c478bd9Sstevel@tonic-gate new->next = g_cachedkeys[hash]; 1199*7c478bd9Sstevel@tonic-gate g_cachedkeys[hash] = new; 1200*7c478bd9Sstevel@tonic-gate return (1); 1201*7c478bd9Sstevel@tonic-gate } 1202*7c478bd9Sstevel@tonic-gate 1203*7c478bd9Sstevel@tonic-gate /* 1204*7c478bd9Sstevel@tonic-gate * Choose middle 64 bits of the common key to use as our des key, possibly 1205*7c478bd9Sstevel@tonic-gate * overwriting the lower order bits by setting parity. 1206*7c478bd9Sstevel@tonic-gate */ 1207*7c478bd9Sstevel@tonic-gate static 1208*7c478bd9Sstevel@tonic-gate extractdeskey(ck, deskey) 1209*7c478bd9Sstevel@tonic-gate MINT *ck; 1210*7c478bd9Sstevel@tonic-gate des_block *deskey; 1211*7c478bd9Sstevel@tonic-gate { 1212*7c478bd9Sstevel@tonic-gate void _mp_move(MINT *, MINT *); 1213*7c478bd9Sstevel@tonic-gate MINT *a; 1214*7c478bd9Sstevel@tonic-gate short r; 1215*7c478bd9Sstevel@tonic-gate int i; 1216*7c478bd9Sstevel@tonic-gate short base = (1 << 8); 1217*7c478bd9Sstevel@tonic-gate char *k; 1218*7c478bd9Sstevel@tonic-gate 1219*7c478bd9Sstevel@tonic-gate a = mp_itom(0); 1220*7c478bd9Sstevel@tonic-gate _mp_move(ck, a); 1221*7c478bd9Sstevel@tonic-gate for (i = 0; i < ((KEYSIZE - 64) / 2) / 8; i++) { 1222*7c478bd9Sstevel@tonic-gate mp_sdiv(a, base, a, &r); 1223*7c478bd9Sstevel@tonic-gate } 1224*7c478bd9Sstevel@tonic-gate k = deskey->c; 1225*7c478bd9Sstevel@tonic-gate for (i = 0; i < 8; i++) { 1226*7c478bd9Sstevel@tonic-gate mp_sdiv(a, base, a, &r); 1227*7c478bd9Sstevel@tonic-gate *k++ = r; 1228*7c478bd9Sstevel@tonic-gate } 1229*7c478bd9Sstevel@tonic-gate mp_mfree(a); 1230*7c478bd9Sstevel@tonic-gate des_setparity((char *)deskey); 1231*7c478bd9Sstevel@tonic-gate return (0); 1232*7c478bd9Sstevel@tonic-gate } 1233*7c478bd9Sstevel@tonic-gate 1234*7c478bd9Sstevel@tonic-gate static bool_t 1235*7c478bd9Sstevel@tonic-gate fetchsecretkey(uid, buf) 1236*7c478bd9Sstevel@tonic-gate uid_t uid; 1237*7c478bd9Sstevel@tonic-gate char *buf; 1238*7c478bd9Sstevel@tonic-gate { 1239*7c478bd9Sstevel@tonic-gate struct secretkey_netname_list *l; 1240*7c478bd9Sstevel@tonic-gate int hash = HASH_UID(uid); 1241*7c478bd9Sstevel@tonic-gate 1242*7c478bd9Sstevel@tonic-gate (void) rw_rdlock(&g_secretkey_netname_lock); 1243*7c478bd9Sstevel@tonic-gate for (l = g_secretkey_netname[hash]; l != NULL; l = l->next) { 1244*7c478bd9Sstevel@tonic-gate if (l->uid == uid) { 1245*7c478bd9Sstevel@tonic-gate memcpy(buf, l->keynetdata.st_priv_key, 1246*7c478bd9Sstevel@tonic-gate sizeof (keybuf)); 1247*7c478bd9Sstevel@tonic-gate (void) rw_unlock(&g_secretkey_netname_lock); 1248*7c478bd9Sstevel@tonic-gate return (TRUE); 1249*7c478bd9Sstevel@tonic-gate } 1250*7c478bd9Sstevel@tonic-gate } 1251*7c478bd9Sstevel@tonic-gate (void) rw_unlock(&g_secretkey_netname_lock); 1252*7c478bd9Sstevel@tonic-gate return (FALSE); 1253*7c478bd9Sstevel@tonic-gate } 1254*7c478bd9Sstevel@tonic-gate 1255*7c478bd9Sstevel@tonic-gate static keybuf3 * 1256*7c478bd9Sstevel@tonic-gate fetchsecretkey3(uid_t uid, keylen_t k, algtype_t a) 1257*7c478bd9Sstevel@tonic-gate { 1258*7c478bd9Sstevel@tonic-gate struct cacheuid_list *cp; 1259*7c478bd9Sstevel@tonic-gate 1260*7c478bd9Sstevel@tonic-gate debug(KEYSERV_DEBUG, ("fetchsecretkey3 %d %d %d", uid, k, a)); 1261*7c478bd9Sstevel@tonic-gate if ((cp = fetchcache3(uid, k, a)) == NULL) { 1262*7c478bd9Sstevel@tonic-gate return (NULL); 1263*7c478bd9Sstevel@tonic-gate } 1264*7c478bd9Sstevel@tonic-gate debug(KEYSERV_DEBUG, ("fetchsecretkey3 ret %x", cp->secretkey)); 1265*7c478bd9Sstevel@tonic-gate return (cp->secretkey); 1266*7c478bd9Sstevel@tonic-gate } 1267*7c478bd9Sstevel@tonic-gate 1268*7c478bd9Sstevel@tonic-gate /* 1269*7c478bd9Sstevel@tonic-gate * Do the work of pk_encrypt && pk_decrypt 1270*7c478bd9Sstevel@tonic-gate */ 1271*7c478bd9Sstevel@tonic-gate static keystatus 1272*7c478bd9Sstevel@tonic-gate pk_crypt(uid, remote_name, remote_key, key, mode) 1273*7c478bd9Sstevel@tonic-gate uid_t uid; 1274*7c478bd9Sstevel@tonic-gate char *remote_name; 1275*7c478bd9Sstevel@tonic-gate netobj *remote_key; 1276*7c478bd9Sstevel@tonic-gate des_block *key; 1277*7c478bd9Sstevel@tonic-gate int mode; 1278*7c478bd9Sstevel@tonic-gate { 1279*7c478bd9Sstevel@tonic-gate char xsecret[1024]; 1280*7c478bd9Sstevel@tonic-gate char xpublic[1024]; 1281*7c478bd9Sstevel@tonic-gate des_block deskey; 1282*7c478bd9Sstevel@tonic-gate int err; 1283*7c478bd9Sstevel@tonic-gate MINT *public; 1284*7c478bd9Sstevel@tonic-gate MINT *secret; 1285*7c478bd9Sstevel@tonic-gate MINT *common; 1286*7c478bd9Sstevel@tonic-gate char zero[8]; 1287*7c478bd9Sstevel@tonic-gate int hash; 1288*7c478bd9Sstevel@tonic-gate 1289*7c478bd9Sstevel@tonic-gate if (!fetchsecretkey(uid, xsecret) || xsecret[0] == 0) { 1290*7c478bd9Sstevel@tonic-gate memset(zero, 0, sizeof (zero)); 1291*7c478bd9Sstevel@tonic-gate if (nodefaultkeys) 1292*7c478bd9Sstevel@tonic-gate return (KEY_NOSECRET); 1293*7c478bd9Sstevel@tonic-gate 1294*7c478bd9Sstevel@tonic-gate if (!getsecretkey("nobody", xsecret, zero) || xsecret[0] == 0) { 1295*7c478bd9Sstevel@tonic-gate return (KEY_NOSECRET); 1296*7c478bd9Sstevel@tonic-gate } 1297*7c478bd9Sstevel@tonic-gate } 1298*7c478bd9Sstevel@tonic-gate if (remote_key) { 1299*7c478bd9Sstevel@tonic-gate memcpy(xpublic, remote_key->n_bytes, remote_key->n_len); 1300*7c478bd9Sstevel@tonic-gate } else { 1301*7c478bd9Sstevel@tonic-gate if (!getpublickey(remote_name, xpublic)) { 1302*7c478bd9Sstevel@tonic-gate if (nodefaultkeys || !getpublickey("nobody", xpublic)) 1303*7c478bd9Sstevel@tonic-gate return (KEY_UNKNOWN); 1304*7c478bd9Sstevel@tonic-gate } 1305*7c478bd9Sstevel@tonic-gate } 1306*7c478bd9Sstevel@tonic-gate 1307*7c478bd9Sstevel@tonic-gate xsecret[HEXKEYBYTES] = '\0'; 1308*7c478bd9Sstevel@tonic-gate xpublic[HEXKEYBYTES] = '\0'; 1309*7c478bd9Sstevel@tonic-gate 1310*7c478bd9Sstevel@tonic-gate hash = hash_keys(xpublic, xsecret); 1311*7c478bd9Sstevel@tonic-gate (void) rw_rdlock(&g_cachedkeys_lock); 1312*7c478bd9Sstevel@tonic-gate if (!readcache(xpublic, xsecret, &deskey, hash)) { 1313*7c478bd9Sstevel@tonic-gate (void) rw_unlock(&g_cachedkeys_lock); 1314*7c478bd9Sstevel@tonic-gate (void) rw_wrlock(&g_cachedkeys_lock); 1315*7c478bd9Sstevel@tonic-gate if (!readcache(xpublic, xsecret, &deskey, hash)) { 1316*7c478bd9Sstevel@tonic-gate public = mp_xtom(xpublic); 1317*7c478bd9Sstevel@tonic-gate secret = mp_xtom(xsecret); 1318*7c478bd9Sstevel@tonic-gate /* Sanity Check on public and private keys */ 1319*7c478bd9Sstevel@tonic-gate if (public == NULL || secret == NULL) { 1320*7c478bd9Sstevel@tonic-gate (void) rw_unlock(&g_cachedkeys_lock); 1321*7c478bd9Sstevel@tonic-gate return (KEY_SYSTEMERR); 1322*7c478bd9Sstevel@tonic-gate } 1323*7c478bd9Sstevel@tonic-gate common = mp_itom(0); 1324*7c478bd9Sstevel@tonic-gate mp_pow(public, secret, MODULUS, common); 1325*7c478bd9Sstevel@tonic-gate extractdeskey(common, &deskey); 1326*7c478bd9Sstevel@tonic-gate writecache(xpublic, xsecret, &deskey, hash); 1327*7c478bd9Sstevel@tonic-gate mp_mfree(secret); 1328*7c478bd9Sstevel@tonic-gate mp_mfree(public); 1329*7c478bd9Sstevel@tonic-gate mp_mfree(common); 1330*7c478bd9Sstevel@tonic-gate } 1331*7c478bd9Sstevel@tonic-gate } 1332*7c478bd9Sstevel@tonic-gate (void) rw_unlock(&g_cachedkeys_lock); 1333*7c478bd9Sstevel@tonic-gate 1334*7c478bd9Sstevel@tonic-gate err = ecb_crypt((char *)&deskey, (char *)key, sizeof (des_block), 1335*7c478bd9Sstevel@tonic-gate DES_HW | mode); 1336*7c478bd9Sstevel@tonic-gate if (DES_FAILED(err)) { 1337*7c478bd9Sstevel@tonic-gate return (KEY_SYSTEMERR); 1338*7c478bd9Sstevel@tonic-gate } 1339*7c478bd9Sstevel@tonic-gate return (KEY_SUCCESS); 1340*7c478bd9Sstevel@tonic-gate } 1341*7c478bd9Sstevel@tonic-gate 1342*7c478bd9Sstevel@tonic-gate static int 1343*7c478bd9Sstevel@tonic-gate hash_keys3(keybuf3 *p, keybuf3 *s) 1344*7c478bd9Sstevel@tonic-gate { 1345*7c478bd9Sstevel@tonic-gate int i; 1346*7c478bd9Sstevel@tonic-gate int hash = 0; 1347*7c478bd9Sstevel@tonic-gate char *pub = p->keybuf3_val; 1348*7c478bd9Sstevel@tonic-gate char *sec = s->keybuf3_val; 1349*7c478bd9Sstevel@tonic-gate 1350*7c478bd9Sstevel@tonic-gate debug(KEYSERV_DEBUG, ("hash_keys3 public %d %s", 1351*7c478bd9Sstevel@tonic-gate p->keybuf3_len, pub)); 1352*7c478bd9Sstevel@tonic-gate debug(KEYSERV_DEBUG, ("hash_keys3 secret %d %s", 1353*7c478bd9Sstevel@tonic-gate s->keybuf3_len, sec)); 1354*7c478bd9Sstevel@tonic-gate for (i = 0; i < s->keybuf3_len; i += 6, pub += 6, sec += 6) { 1355*7c478bd9Sstevel@tonic-gate hash ^= *pub; 1356*7c478bd9Sstevel@tonic-gate hash ^= *sec; 1357*7c478bd9Sstevel@tonic-gate } 1358*7c478bd9Sstevel@tonic-gate debug(KEYSERV_DEBUG, ("hash_keys3 ret %d", hash & 0xff)); 1359*7c478bd9Sstevel@tonic-gate return (hash & 0xff); 1360*7c478bd9Sstevel@tonic-gate } 1361*7c478bd9Sstevel@tonic-gate 1362*7c478bd9Sstevel@tonic-gate static struct cachekey3_list ** 1363*7c478bd9Sstevel@tonic-gate map_ps2cache(keybuf3 *public, keybuf3 *secret, struct psdata *pdp) 1364*7c478bd9Sstevel@tonic-gate { 1365*7c478bd9Sstevel@tonic-gate struct cachekey3_list **cpp; 1366*7c478bd9Sstevel@tonic-gate int hash = hash_keys3(public, secret); 1367*7c478bd9Sstevel@tonic-gate 1368*7c478bd9Sstevel@tonic-gate debug(KEYSERV_DEBUG, ("map_ps2cache %x %d", pdp, hash)); 1369*7c478bd9Sstevel@tonic-gate for (cpp = &pdp->common[hash]; 1370*7c478bd9Sstevel@tonic-gate *cpp != NULL && !(cachehit3(public, secret, *cpp)); 1371*7c478bd9Sstevel@tonic-gate cpp = &(*cpp)->next) { 1372*7c478bd9Sstevel@tonic-gate debug(KEYSERV_DEBUG0, ("map_ps2cache %x", cpp)); 1373*7c478bd9Sstevel@tonic-gate } 1374*7c478bd9Sstevel@tonic-gate debug(KEYSERV_DEBUG, ("map_ps2cache ret %x", cpp)); 1375*7c478bd9Sstevel@tonic-gate return (cpp); 1376*7c478bd9Sstevel@tonic-gate } 1377*7c478bd9Sstevel@tonic-gate 1378*7c478bd9Sstevel@tonic-gate static struct cachekey3_list * 1379*7c478bd9Sstevel@tonic-gate getdeskey3( 1380*7c478bd9Sstevel@tonic-gate keylen_t keylen, 1381*7c478bd9Sstevel@tonic-gate algtype_t algtype, 1382*7c478bd9Sstevel@tonic-gate int desarylen, 1383*7c478bd9Sstevel@tonic-gate keybuf3 *public, 1384*7c478bd9Sstevel@tonic-gate keybuf3 *secret, 1385*7c478bd9Sstevel@tonic-gate uid_t uid 1386*7c478bd9Sstevel@tonic-gate ) 1387*7c478bd9Sstevel@tonic-gate { 1388*7c478bd9Sstevel@tonic-gate struct mechentry *mp; 1389*7c478bd9Sstevel@tonic-gate struct psdata *pdp; 1390*7c478bd9Sstevel@tonic-gate struct cachekey3_list **cpp, *cp, *cachep; 1391*7c478bd9Sstevel@tonic-gate struct cacheuid_list *cu; 1392*7c478bd9Sstevel@tonic-gate int i; 1393*7c478bd9Sstevel@tonic-gate int cached = 0; 1394*7c478bd9Sstevel@tonic-gate 1395*7c478bd9Sstevel@tonic-gate debug(KEYSERV_DEBUG, ("getdeskey3 %d %d %d %x %x", 1396*7c478bd9Sstevel@tonic-gate keylen, algtype, desarylen, public, secret)); 1397*7c478bd9Sstevel@tonic-gate if ((mp = getmechtype(keylen, algtype)) == NULL) { 1398*7c478bd9Sstevel@tonic-gate return (0); 1399*7c478bd9Sstevel@tonic-gate } 1400*7c478bd9Sstevel@tonic-gate (void) mutex_lock(&mp->ps_lock); 1401*7c478bd9Sstevel@tonic-gate if ((pdp = mp->psdata) == NULL) { 1402*7c478bd9Sstevel@tonic-gate if ((pdp = (struct psdata *)calloc(1, sizeof (*pdp))) == 1403*7c478bd9Sstevel@tonic-gate NULL) { 1404*7c478bd9Sstevel@tonic-gate mutex_unlock(&mp->ps_lock); 1405*7c478bd9Sstevel@tonic-gate debug(KEYSERV_INFO, ("getdeskey3 : calloc failed")); 1406*7c478bd9Sstevel@tonic-gate return (0); 1407*7c478bd9Sstevel@tonic-gate } 1408*7c478bd9Sstevel@tonic-gate mp->psdata = pdp; 1409*7c478bd9Sstevel@tonic-gate } 1410*7c478bd9Sstevel@tonic-gate debug(KEYSERV_DEBUG, ("getdeskey3 %x", pdp)); 1411*7c478bd9Sstevel@tonic-gate cpp = map_ps2cache(public, secret, pdp); 1412*7c478bd9Sstevel@tonic-gate if (*cpp == NULL) { 1413*7c478bd9Sstevel@tonic-gate debug(KEYSERV_DEBUG, ("getdeskey3 calling fetchcache3")); 1414*7c478bd9Sstevel@tonic-gate if (disk_caching && 1415*7c478bd9Sstevel@tonic-gate (cu = fetchcache3(uid, keylen, algtype)) != NULL) { 1416*7c478bd9Sstevel@tonic-gate debug(KEYSERV_DEBUG, 1417*7c478bd9Sstevel@tonic-gate ("getdeskey3 calling cache_retrieve")); 1418*7c478bd9Sstevel@tonic-gate if ((cachep = cache_retrieve(keylen, algtype, uid, 1419*7c478bd9Sstevel@tonic-gate public, cu->key)) != NULL) { 1420*7c478bd9Sstevel@tonic-gate if (cmpkeybuf3(cachep->secret, cu->secretkey)) { 1421*7c478bd9Sstevel@tonic-gate cached = 1; 1422*7c478bd9Sstevel@tonic-gate } else { 1423*7c478bd9Sstevel@tonic-gate debug(KEYSERV_DEBUG, 1424*7c478bd9Sstevel@tonic-gate ("getdeskey3 calling cache_remove")); 1425*7c478bd9Sstevel@tonic-gate cache_remove(keylen, algtype, 1426*7c478bd9Sstevel@tonic-gate uid, NULL); 1427*7c478bd9Sstevel@tonic-gate } 1428*7c478bd9Sstevel@tonic-gate } 1429*7c478bd9Sstevel@tonic-gate } 1430*7c478bd9Sstevel@tonic-gate if (cached) { 1431*7c478bd9Sstevel@tonic-gate cp = cachep; 1432*7c478bd9Sstevel@tonic-gate } else { 1433*7c478bd9Sstevel@tonic-gate if ((cp = (struct cachekey3_list *) 1434*7c478bd9Sstevel@tonic-gate malloc(sizeof (*cp))) == NULL) { 1435*7c478bd9Sstevel@tonic-gate mutex_unlock(&mp->ps_lock); 1436*7c478bd9Sstevel@tonic-gate debug(KEYSERV_INFO, 1437*7c478bd9Sstevel@tonic-gate ("getdeskey3 : malloc failed")); 1438*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 1439*7c478bd9Sstevel@tonic-gate "file %s line %d: malloc failed", 1440*7c478bd9Sstevel@tonic-gate __FILE__, __LINE__); 1441*7c478bd9Sstevel@tonic-gate return (0); 1442*7c478bd9Sstevel@tonic-gate } 1443*7c478bd9Sstevel@tonic-gate cp->refcnt = 0; 1444*7c478bd9Sstevel@tonic-gate cp->next = NULL; 1445*7c478bd9Sstevel@tonic-gate if ((cp->public = cpykeybuf3(public)) == NULL) { 1446*7c478bd9Sstevel@tonic-gate mutex_unlock(&mp->ps_lock); 1447*7c478bd9Sstevel@tonic-gate return (0); 1448*7c478bd9Sstevel@tonic-gate } 1449*7c478bd9Sstevel@tonic-gate if ((cp->secret = cpykeybuf3(secret)) == NULL) { 1450*7c478bd9Sstevel@tonic-gate mutex_unlock(&mp->ps_lock); 1451*7c478bd9Sstevel@tonic-gate return (0); 1452*7c478bd9Sstevel@tonic-gate } 1453*7c478bd9Sstevel@tonic-gate if (!setdeskeyarray(&cp->deskey, desarylen)) { 1454*7c478bd9Sstevel@tonic-gate mutex_unlock(&mp->ps_lock); 1455*7c478bd9Sstevel@tonic-gate return (0); 1456*7c478bd9Sstevel@tonic-gate } 1457*7c478bd9Sstevel@tonic-gate debug(KEYSERV_DEBUG, ("getdeskey3 %x %x %x", 1458*7c478bd9Sstevel@tonic-gate cp->public, cp->secret, 1459*7c478bd9Sstevel@tonic-gate cp->deskey.deskeyarray_val)); 1460*7c478bd9Sstevel@tonic-gate debug(KEYSERV_DEBUG, 1461*7c478bd9Sstevel@tonic-gate ("getdeskey3 calling __gen_common_dhkeys_g")); 1462*7c478bd9Sstevel@tonic-gate if (!__gen_common_dhkeys_g(public->keybuf3_val, 1463*7c478bd9Sstevel@tonic-gate secret->keybuf3_val, 1464*7c478bd9Sstevel@tonic-gate keylen, algtype, 1465*7c478bd9Sstevel@tonic-gate cp->deskey.deskeyarray_val, desarylen)) { 1466*7c478bd9Sstevel@tonic-gate mutex_unlock(&mp->ps_lock); 1467*7c478bd9Sstevel@tonic-gate return (0); 1468*7c478bd9Sstevel@tonic-gate } 1469*7c478bd9Sstevel@tonic-gate for (i = 0; i < desarylen; i++) { 1470*7c478bd9Sstevel@tonic-gate debug(KEYSERV_DEBUG0, 1471*7c478bd9Sstevel@tonic-gate ("getdeskey3 gendh key : (%x,%x)", 1472*7c478bd9Sstevel@tonic-gate cp->deskey.deskeyarray_val[i].key.high, 1473*7c478bd9Sstevel@tonic-gate cp->deskey.deskeyarray_val[i].key.low)); 1474*7c478bd9Sstevel@tonic-gate } 1475*7c478bd9Sstevel@tonic-gate if (disk_caching && cu != NULL) { 1476*7c478bd9Sstevel@tonic-gate debug(KEYSERV_DEBUG, 1477*7c478bd9Sstevel@tonic-gate ("getdeskey3 calling cache_insert")); 1478*7c478bd9Sstevel@tonic-gate cache_insert(keylen, algtype, uid, cp->deskey, 1479*7c478bd9Sstevel@tonic-gate cu->key, public, secret); 1480*7c478bd9Sstevel@tonic-gate } 1481*7c478bd9Sstevel@tonic-gate } 1482*7c478bd9Sstevel@tonic-gate *cpp = cp; 1483*7c478bd9Sstevel@tonic-gate } else { 1484*7c478bd9Sstevel@tonic-gate cp = *cpp; 1485*7c478bd9Sstevel@tonic-gate } 1486*7c478bd9Sstevel@tonic-gate cp->refcnt++; 1487*7c478bd9Sstevel@tonic-gate mutex_unlock(&mp->ps_lock); 1488*7c478bd9Sstevel@tonic-gate debug(KEYSERV_DEBUG, ("getdeskey3 ret %x", cp)); 1489*7c478bd9Sstevel@tonic-gate return (cp); 1490*7c478bd9Sstevel@tonic-gate } 1491*7c478bd9Sstevel@tonic-gate 1492*7c478bd9Sstevel@tonic-gate keystatus 1493*7c478bd9Sstevel@tonic-gate pk_get_conv_key3(uid_t uid, deskeyarg3 *arg, cryptkeyres3 *res) 1494*7c478bd9Sstevel@tonic-gate { 1495*7c478bd9Sstevel@tonic-gate keybuf3 *xsecret, *xpublic; 1496*7c478bd9Sstevel@tonic-gate char zero[8]; 1497*7c478bd9Sstevel@tonic-gate struct cachekey3_list *cp; 1498*7c478bd9Sstevel@tonic-gate 1499*7c478bd9Sstevel@tonic-gate debug(KEYSERV_DEBUG, ("pk_get_conv_key3 %d %x %x", 1500*7c478bd9Sstevel@tonic-gate uid, arg, res)); 1501*7c478bd9Sstevel@tonic-gate if ((xsecret = fetchsecretkey3(uid, 1502*7c478bd9Sstevel@tonic-gate arg->keylen, arg->algtype)) == NULL) { 1503*7c478bd9Sstevel@tonic-gate if (nodefaultkeys) 1504*7c478bd9Sstevel@tonic-gate return (KEY_NOSECRET); 1505*7c478bd9Sstevel@tonic-gate memset(zero, 0, sizeof (zero)); 1506*7c478bd9Sstevel@tonic-gate if ((xsecret = getkeybuf3(arg->keylen/4+1)) == NULL) { 1507*7c478bd9Sstevel@tonic-gate return (KEY_SYSTEMERR); 1508*7c478bd9Sstevel@tonic-gate } 1509*7c478bd9Sstevel@tonic-gate debug(KEYSERV_DEBUG, 1510*7c478bd9Sstevel@tonic-gate ("pk_get_conv_key3 calling getsecretkey_g")); 1511*7c478bd9Sstevel@tonic-gate if (!getsecretkey_g("nobody", 1512*7c478bd9Sstevel@tonic-gate arg->keylen, arg->algtype, 1513*7c478bd9Sstevel@tonic-gate xsecret->keybuf3_val, xsecret->keybuf3_len, 1514*7c478bd9Sstevel@tonic-gate zero) || *xsecret->keybuf3_val == 0) { /* XXX */ 1515*7c478bd9Sstevel@tonic-gate debug(KEYSERV_DEBUG, 1516*7c478bd9Sstevel@tonic-gate ("pk_get_conv_key3 calling getsecretkey_g failed")); 1517*7c478bd9Sstevel@tonic-gate return (KEY_NOSECRET); 1518*7c478bd9Sstevel@tonic-gate } 1519*7c478bd9Sstevel@tonic-gate debug(KEYSERV_DEBUG, 1520*7c478bd9Sstevel@tonic-gate ("pk_get_conv_key3 calling getsecretkey_g succeeded")); 1521*7c478bd9Sstevel@tonic-gate } 1522*7c478bd9Sstevel@tonic-gate xpublic = &arg->pub_key; 1523*7c478bd9Sstevel@tonic-gate if ((cp = getdeskey3(arg->keylen, arg->algtype, arg->nkeys, 1524*7c478bd9Sstevel@tonic-gate xpublic, xsecret, uid)) == NULL) { 1525*7c478bd9Sstevel@tonic-gate return (KEY_SYSTEMERR); 1526*7c478bd9Sstevel@tonic-gate } 1527*7c478bd9Sstevel@tonic-gate storedeskeyarray(&res->cryptkeyres3_u.deskey, &cp->deskey); 1528*7c478bd9Sstevel@tonic-gate return (KEY_SUCCESS); 1529*7c478bd9Sstevel@tonic-gate } 1530*7c478bd9Sstevel@tonic-gate 1531*7c478bd9Sstevel@tonic-gate /* 1532*7c478bd9Sstevel@tonic-gate * Do the work of pk_encrypt3 && pk_decrypt3 1533*7c478bd9Sstevel@tonic-gate */ 1534*7c478bd9Sstevel@tonic-gate static keystatus 1535*7c478bd9Sstevel@tonic-gate pk_crypt3( 1536*7c478bd9Sstevel@tonic-gate uid_t uid, 1537*7c478bd9Sstevel@tonic-gate cryptkeyarg3 *arg, 1538*7c478bd9Sstevel@tonic-gate deskeyarray *key, 1539*7c478bd9Sstevel@tonic-gate int mode 1540*7c478bd9Sstevel@tonic-gate ) 1541*7c478bd9Sstevel@tonic-gate { 1542*7c478bd9Sstevel@tonic-gate keybuf3 *xsecret = NULL, *xpublic = NULL; 1543*7c478bd9Sstevel@tonic-gate char zero[8]; 1544*7c478bd9Sstevel@tonic-gate struct cachekey3_list *cp; 1545*7c478bd9Sstevel@tonic-gate int err; 1546*7c478bd9Sstevel@tonic-gate int xsecret_alloc = 0; 1547*7c478bd9Sstevel@tonic-gate char ivec[8]; 1548*7c478bd9Sstevel@tonic-gate 1549*7c478bd9Sstevel@tonic-gate memset(ivec, 0, 8); 1550*7c478bd9Sstevel@tonic-gate debug(KEYSERV_DEBUG1, ("pk_crypt3 %d %x %x %d", 1551*7c478bd9Sstevel@tonic-gate uid, arg, key, mode)); 1552*7c478bd9Sstevel@tonic-gate if ((xsecret = fetchsecretkey3(uid, 1553*7c478bd9Sstevel@tonic-gate arg->keylen, arg->algtype)) == NULL) { 1554*7c478bd9Sstevel@tonic-gate if (nodefaultkeys) 1555*7c478bd9Sstevel@tonic-gate return (KEY_NOSECRET); 1556*7c478bd9Sstevel@tonic-gate memset(zero, 0, sizeof (zero)); 1557*7c478bd9Sstevel@tonic-gate if ((xsecret = getkeybuf3(arg->keylen/4+1)) == NULL) { 1558*7c478bd9Sstevel@tonic-gate return (KEY_SYSTEMERR); 1559*7c478bd9Sstevel@tonic-gate } 1560*7c478bd9Sstevel@tonic-gate xsecret_alloc = 1; 1561*7c478bd9Sstevel@tonic-gate debug(KEYSERV_DEBUG1, ("pk_crypt3 calling getsecretkey_g")); 1562*7c478bd9Sstevel@tonic-gate if (!getsecretkey_g("nobody", 1563*7c478bd9Sstevel@tonic-gate arg->keylen, arg->algtype, 1564*7c478bd9Sstevel@tonic-gate xsecret->keybuf3_val, xsecret->keybuf3_len, 1565*7c478bd9Sstevel@tonic-gate zero) || *xsecret->keybuf3_val == 0) { /* XXX */ 1566*7c478bd9Sstevel@tonic-gate debug(KEYSERV_DEBUG, 1567*7c478bd9Sstevel@tonic-gate ("pk_crypt3 calling getsecretkey_g failed")); 1568*7c478bd9Sstevel@tonic-gate freekeybuf3(xsecret); 1569*7c478bd9Sstevel@tonic-gate return (KEY_NOSECRET); 1570*7c478bd9Sstevel@tonic-gate } 1571*7c478bd9Sstevel@tonic-gate /* XXX optimize to cache nobody's secret key? */ 1572*7c478bd9Sstevel@tonic-gate debug(KEYSERV_DEBUG0, 1573*7c478bd9Sstevel@tonic-gate ("pk_crypt3 calling getsecretkey_g succeeded")); 1574*7c478bd9Sstevel@tonic-gate } 1575*7c478bd9Sstevel@tonic-gate if (arg->remotekey.keybuf3_len) { 1576*7c478bd9Sstevel@tonic-gate if ((xpublic = cpykeybuf3(&arg->remotekey)) == NULL) { 1577*7c478bd9Sstevel@tonic-gate if (xsecret_alloc) freekeybuf3(xsecret); 1578*7c478bd9Sstevel@tonic-gate return (KEY_SYSTEMERR); 1579*7c478bd9Sstevel@tonic-gate } 1580*7c478bd9Sstevel@tonic-gate } else { 1581*7c478bd9Sstevel@tonic-gate if ((xpublic = getkeybuf3(arg->keylen/4+1)) == NULL) { 1582*7c478bd9Sstevel@tonic-gate if (xsecret_alloc) freekeybuf3(xsecret); 1583*7c478bd9Sstevel@tonic-gate return (KEY_SYSTEMERR); 1584*7c478bd9Sstevel@tonic-gate } 1585*7c478bd9Sstevel@tonic-gate debug(KEYSERV_DEBUG1, ("pk_crypt3 calling getpublickey_g")); 1586*7c478bd9Sstevel@tonic-gate if (!getpublickey_g(arg->remotename, 1587*7c478bd9Sstevel@tonic-gate arg->keylen, arg->algtype, 1588*7c478bd9Sstevel@tonic-gate xpublic->keybuf3_val, xpublic->keybuf3_len)) { 1589*7c478bd9Sstevel@tonic-gate debug(KEYSERV_DEBUG0, 1590*7c478bd9Sstevel@tonic-gate ("pk_crypt3 calling getpublickey_g nobody")); 1591*7c478bd9Sstevel@tonic-gate if (nodefaultkeys || !getpublickey_g("nobody", 1592*7c478bd9Sstevel@tonic-gate arg->keylen, arg->algtype, 1593*7c478bd9Sstevel@tonic-gate xpublic->keybuf3_val, xpublic->keybuf3_len)) { 1594*7c478bd9Sstevel@tonic-gate debug(KEYSERV_DEBUG, 1595*7c478bd9Sstevel@tonic-gate ("pk_crypt3 calling getpublickey_g nobody failed")); 1596*7c478bd9Sstevel@tonic-gate if (xsecret_alloc) freekeybuf3(xsecret); 1597*7c478bd9Sstevel@tonic-gate freekeybuf3(xpublic); 1598*7c478bd9Sstevel@tonic-gate return (KEY_UNKNOWN); 1599*7c478bd9Sstevel@tonic-gate } 1600*7c478bd9Sstevel@tonic-gate } 1601*7c478bd9Sstevel@tonic-gate debug(KEYSERV_DEBUG0, 1602*7c478bd9Sstevel@tonic-gate ("pk_crypt3 calling getpublickey_g succeeded")); 1603*7c478bd9Sstevel@tonic-gate } 1604*7c478bd9Sstevel@tonic-gate 1605*7c478bd9Sstevel@tonic-gate if ((cp = getdeskey3(arg->keylen, arg->algtype, 1606*7c478bd9Sstevel@tonic-gate arg->deskey.deskeyarray_len, xpublic, xsecret, uid)) == NULL) { 1607*7c478bd9Sstevel@tonic-gate if (xsecret_alloc) freekeybuf3(xsecret); 1608*7c478bd9Sstevel@tonic-gate freekeybuf3(xpublic); 1609*7c478bd9Sstevel@tonic-gate return (KEY_SYSTEMERR); 1610*7c478bd9Sstevel@tonic-gate } 1611*7c478bd9Sstevel@tonic-gate storedeskeyarray(key, &arg->deskey); 1612*7c478bd9Sstevel@tonic-gate if (CLASSIC_PK_DH(arg->keylen, arg->algtype)) { 1613*7c478bd9Sstevel@tonic-gate /*EMPTY*/ 1614*7c478bd9Sstevel@tonic-gate debug(KEYSERV_DEBUG1, 1615*7c478bd9Sstevel@tonic-gate ("pk_crypt3 WARNING received 192-bit key")); 1616*7c478bd9Sstevel@tonic-gate } else { 1617*7c478bd9Sstevel@tonic-gate debug(KEYSERV_DEBUG, 1618*7c478bd9Sstevel@tonic-gate ("pk_crypt3 calling __cbc_triple_crypt")); 1619*7c478bd9Sstevel@tonic-gate err = __cbc_triple_crypt(cp->deskey.deskeyarray_val, 1620*7c478bd9Sstevel@tonic-gate (char *)key->deskeyarray_val, 1621*7c478bd9Sstevel@tonic-gate cp->deskey.deskeyarray_len*sizeof (des_block), 1622*7c478bd9Sstevel@tonic-gate DES_HW | mode, ivec); 1623*7c478bd9Sstevel@tonic-gate if (DES_FAILED(err)) { 1624*7c478bd9Sstevel@tonic-gate debug(KEYSERV_DEBUG, 1625*7c478bd9Sstevel@tonic-gate ("pk_crypt3 calling ecb_crypt/__cbc_triple_crypt failed")); 1626*7c478bd9Sstevel@tonic-gate if (xsecret_alloc) freekeybuf3(xsecret); 1627*7c478bd9Sstevel@tonic-gate freekeybuf3(xpublic); 1628*7c478bd9Sstevel@tonic-gate return (KEY_SYSTEMERR); 1629*7c478bd9Sstevel@tonic-gate } 1630*7c478bd9Sstevel@tonic-gate debug(KEYSERV_DEBUG, 1631*7c478bd9Sstevel@tonic-gate ("pk_crypt3 calling __cbc_triple_crypt succeeded")); 1632*7c478bd9Sstevel@tonic-gate } 1633*7c478bd9Sstevel@tonic-gate if (xsecret_alloc) freekeybuf3(xsecret); 1634*7c478bd9Sstevel@tonic-gate freekeybuf3(xpublic); 1635*7c478bd9Sstevel@tonic-gate return (KEY_SUCCESS); 1636*7c478bd9Sstevel@tonic-gate } 1637*7c478bd9Sstevel@tonic-gate 1638*7c478bd9Sstevel@tonic-gate keystatus 1639*7c478bd9Sstevel@tonic-gate pk_get_conv_key(uid, pubkey, result) 1640*7c478bd9Sstevel@tonic-gate uid_t uid; 1641*7c478bd9Sstevel@tonic-gate keybuf pubkey; 1642*7c478bd9Sstevel@tonic-gate cryptkeyres *result; 1643*7c478bd9Sstevel@tonic-gate { 1644*7c478bd9Sstevel@tonic-gate char xsecret[1024]; 1645*7c478bd9Sstevel@tonic-gate char xpublic[1024]; 1646*7c478bd9Sstevel@tonic-gate MINT *public; 1647*7c478bd9Sstevel@tonic-gate MINT *secret; 1648*7c478bd9Sstevel@tonic-gate MINT *common; 1649*7c478bd9Sstevel@tonic-gate char zero[8]; 1650*7c478bd9Sstevel@tonic-gate int hash; 1651*7c478bd9Sstevel@tonic-gate 1652*7c478bd9Sstevel@tonic-gate if (!fetchsecretkey(uid, xsecret) || xsecret[0] == 0) { 1653*7c478bd9Sstevel@tonic-gate memset(zero, 0, sizeof (zero)); 1654*7c478bd9Sstevel@tonic-gate if (nodefaultkeys) 1655*7c478bd9Sstevel@tonic-gate return (KEY_NOSECRET); 1656*7c478bd9Sstevel@tonic-gate 1657*7c478bd9Sstevel@tonic-gate if (!getsecretkey("nobody", xsecret, zero) || 1658*7c478bd9Sstevel@tonic-gate xsecret[0] == 0) 1659*7c478bd9Sstevel@tonic-gate return (KEY_NOSECRET); 1660*7c478bd9Sstevel@tonic-gate } 1661*7c478bd9Sstevel@tonic-gate 1662*7c478bd9Sstevel@tonic-gate memcpy(xpublic, pubkey, sizeof (keybuf)); 1663*7c478bd9Sstevel@tonic-gate xsecret[HEXKEYBYTES] = '\0'; 1664*7c478bd9Sstevel@tonic-gate xpublic[HEXKEYBYTES] = '\0'; 1665*7c478bd9Sstevel@tonic-gate 1666*7c478bd9Sstevel@tonic-gate hash = hash_keys(xpublic, xsecret); 1667*7c478bd9Sstevel@tonic-gate (void) rw_rdlock(&g_cachedkeys_lock); 1668*7c478bd9Sstevel@tonic-gate if (!readcache(xpublic, xsecret, &result->cryptkeyres_u.deskey, hash)) { 1669*7c478bd9Sstevel@tonic-gate (void) rw_unlock(&g_cachedkeys_lock); 1670*7c478bd9Sstevel@tonic-gate (void) rw_wrlock(&g_cachedkeys_lock); 1671*7c478bd9Sstevel@tonic-gate if (!readcache(xpublic, xsecret, &result->cryptkeyres_u.deskey, 1672*7c478bd9Sstevel@tonic-gate hash)) { 1673*7c478bd9Sstevel@tonic-gate public = mp_xtom(xpublic); 1674*7c478bd9Sstevel@tonic-gate secret = mp_xtom(xsecret); 1675*7c478bd9Sstevel@tonic-gate /* Sanity Check on public and private keys */ 1676*7c478bd9Sstevel@tonic-gate if (public == NULL || secret == NULL) { 1677*7c478bd9Sstevel@tonic-gate (void) rw_unlock(&g_cachedkeys_lock); 1678*7c478bd9Sstevel@tonic-gate return (KEY_SYSTEMERR); 1679*7c478bd9Sstevel@tonic-gate } 1680*7c478bd9Sstevel@tonic-gate common = mp_itom(0); 1681*7c478bd9Sstevel@tonic-gate mp_pow(public, secret, MODULUS, common); 1682*7c478bd9Sstevel@tonic-gate extractdeskey(common, &result->cryptkeyres_u.deskey); 1683*7c478bd9Sstevel@tonic-gate writecache(xpublic, xsecret, 1684*7c478bd9Sstevel@tonic-gate &result->cryptkeyres_u.deskey, hash); 1685*7c478bd9Sstevel@tonic-gate mp_mfree(secret); 1686*7c478bd9Sstevel@tonic-gate mp_mfree(public); 1687*7c478bd9Sstevel@tonic-gate mp_mfree(common); 1688*7c478bd9Sstevel@tonic-gate } 1689*7c478bd9Sstevel@tonic-gate } 1690*7c478bd9Sstevel@tonic-gate (void) rw_unlock(&g_cachedkeys_lock); 1691*7c478bd9Sstevel@tonic-gate 1692*7c478bd9Sstevel@tonic-gate return (KEY_SUCCESS); 1693*7c478bd9Sstevel@tonic-gate } 1694*7c478bd9Sstevel@tonic-gate 1695*7c478bd9Sstevel@tonic-gate #define findsec(sec, list) \ 1696*7c478bd9Sstevel@tonic-gate (memcmp(sec, (list)->secret, sizeof (keybuf)) == 0) 1697*7c478bd9Sstevel@tonic-gate 1698*7c478bd9Sstevel@tonic-gate /* 1699*7c478bd9Sstevel@tonic-gate * Remove common keys from the cache. 1700*7c478bd9Sstevel@tonic-gate */ 1701*7c478bd9Sstevel@tonic-gate static 1702*7c478bd9Sstevel@tonic-gate removecache(sec) 1703*7c478bd9Sstevel@tonic-gate char *sec; 1704*7c478bd9Sstevel@tonic-gate { 1705*7c478bd9Sstevel@tonic-gate struct cachekey_list *found; 1706*7c478bd9Sstevel@tonic-gate register struct cachekey_list **l; 1707*7c478bd9Sstevel@tonic-gate int i; 1708*7c478bd9Sstevel@tonic-gate 1709*7c478bd9Sstevel@tonic-gate (void) rw_wrlock(&g_cachedkeys_lock); 1710*7c478bd9Sstevel@tonic-gate for (i = 0; i < KEY_HASH_SIZE; i++) { 1711*7c478bd9Sstevel@tonic-gate for (l = &g_cachedkeys[i]; (*l) != NULL; ) { 1712*7c478bd9Sstevel@tonic-gate if (findsec(sec, *l)) { 1713*7c478bd9Sstevel@tonic-gate found = *l; 1714*7c478bd9Sstevel@tonic-gate *l = (*l)->next; 1715*7c478bd9Sstevel@tonic-gate memset((char *)found, 0, 1716*7c478bd9Sstevel@tonic-gate sizeof (struct cachekey_list)); 1717*7c478bd9Sstevel@tonic-gate free(found); 1718*7c478bd9Sstevel@tonic-gate } else { 1719*7c478bd9Sstevel@tonic-gate l = &(*l)->next; 1720*7c478bd9Sstevel@tonic-gate } 1721*7c478bd9Sstevel@tonic-gate } 1722*7c478bd9Sstevel@tonic-gate } 1723*7c478bd9Sstevel@tonic-gate (void) rw_unlock(&g_cachedkeys_lock); 1724*7c478bd9Sstevel@tonic-gate return (1); 1725*7c478bd9Sstevel@tonic-gate } 1726*7c478bd9Sstevel@tonic-gate 1727*7c478bd9Sstevel@tonic-gate /* 1728*7c478bd9Sstevel@tonic-gate * Store the secretkey for this uid 1729*7c478bd9Sstevel@tonic-gate */ 1730*7c478bd9Sstevel@tonic-gate storesecretkey(uid, key) 1731*7c478bd9Sstevel@tonic-gate uid_t uid; 1732*7c478bd9Sstevel@tonic-gate keybuf key; 1733*7c478bd9Sstevel@tonic-gate { 1734*7c478bd9Sstevel@tonic-gate struct secretkey_netname_list *new; 1735*7c478bd9Sstevel@tonic-gate struct secretkey_netname_list **l; 1736*7c478bd9Sstevel@tonic-gate int hash = HASH_UID(uid); 1737*7c478bd9Sstevel@tonic-gate 1738*7c478bd9Sstevel@tonic-gate (void) rw_wrlock(&g_secretkey_netname_lock); 1739*7c478bd9Sstevel@tonic-gate for (l = &g_secretkey_netname[hash]; *l != NULL && (*l)->uid != uid; 1740*7c478bd9Sstevel@tonic-gate l = &(*l)->next) { 1741*7c478bd9Sstevel@tonic-gate } 1742*7c478bd9Sstevel@tonic-gate if (*l == NULL) { 1743*7c478bd9Sstevel@tonic-gate if (key[0] == '\0') { 1744*7c478bd9Sstevel@tonic-gate (void) rw_unlock(&g_secretkey_netname_lock); 1745*7c478bd9Sstevel@tonic-gate return (0); 1746*7c478bd9Sstevel@tonic-gate } 1747*7c478bd9Sstevel@tonic-gate new = (struct secretkey_netname_list *)malloc(sizeof (*new)); 1748*7c478bd9Sstevel@tonic-gate if (new == NULL) { 1749*7c478bd9Sstevel@tonic-gate (void) rw_unlock(&g_secretkey_netname_lock); 1750*7c478bd9Sstevel@tonic-gate return (0); 1751*7c478bd9Sstevel@tonic-gate } 1752*7c478bd9Sstevel@tonic-gate new->uid = uid; 1753*7c478bd9Sstevel@tonic-gate new->sc_flag = KEY_ONLY; 1754*7c478bd9Sstevel@tonic-gate memset(new->keynetdata.st_pub_key, 0, HEXKEYBYTES); 1755*7c478bd9Sstevel@tonic-gate new->keynetdata.st_netname = NULL; 1756*7c478bd9Sstevel@tonic-gate new->next = NULL; 1757*7c478bd9Sstevel@tonic-gate *l = new; 1758*7c478bd9Sstevel@tonic-gate } else { 1759*7c478bd9Sstevel@tonic-gate new = *l; 1760*7c478bd9Sstevel@tonic-gate if (key[0] == '\0') 1761*7c478bd9Sstevel@tonic-gate removecache(new->keynetdata.st_priv_key); 1762*7c478bd9Sstevel@tonic-gate } 1763*7c478bd9Sstevel@tonic-gate 1764*7c478bd9Sstevel@tonic-gate memcpy(new->keynetdata.st_priv_key, key, 1765*7c478bd9Sstevel@tonic-gate HEXKEYBYTES); 1766*7c478bd9Sstevel@tonic-gate (void) rw_unlock(&g_secretkey_netname_lock); 1767*7c478bd9Sstevel@tonic-gate return (1); 1768*7c478bd9Sstevel@tonic-gate } 1769*7c478bd9Sstevel@tonic-gate 1770*7c478bd9Sstevel@tonic-gate static 1771*7c478bd9Sstevel@tonic-gate hexdigit(val) 1772*7c478bd9Sstevel@tonic-gate int val; 1773*7c478bd9Sstevel@tonic-gate { 1774*7c478bd9Sstevel@tonic-gate return ("0123456789abcdef"[val]); 1775*7c478bd9Sstevel@tonic-gate } 1776*7c478bd9Sstevel@tonic-gate 1777*7c478bd9Sstevel@tonic-gate bin2hex(bin, hex, size) 1778*7c478bd9Sstevel@tonic-gate unsigned char *bin; 1779*7c478bd9Sstevel@tonic-gate unsigned char *hex; 1780*7c478bd9Sstevel@tonic-gate int size; 1781*7c478bd9Sstevel@tonic-gate { 1782*7c478bd9Sstevel@tonic-gate int i; 1783*7c478bd9Sstevel@tonic-gate 1784*7c478bd9Sstevel@tonic-gate for (i = 0; i < size; i++) { 1785*7c478bd9Sstevel@tonic-gate *hex++ = hexdigit(*bin >> 4); 1786*7c478bd9Sstevel@tonic-gate *hex++ = hexdigit(*bin++ & 0xf); 1787*7c478bd9Sstevel@tonic-gate } 1788*7c478bd9Sstevel@tonic-gate return (0); 1789*7c478bd9Sstevel@tonic-gate } 1790*7c478bd9Sstevel@tonic-gate 1791*7c478bd9Sstevel@tonic-gate static 1792*7c478bd9Sstevel@tonic-gate hexval(dig) 1793*7c478bd9Sstevel@tonic-gate char dig; 1794*7c478bd9Sstevel@tonic-gate { 1795*7c478bd9Sstevel@tonic-gate if ('0' <= dig && dig <= '9') { 1796*7c478bd9Sstevel@tonic-gate return (dig - '0'); 1797*7c478bd9Sstevel@tonic-gate } else if ('a' <= dig && dig <= 'f') { 1798*7c478bd9Sstevel@tonic-gate return (dig - 'a' + 10); 1799*7c478bd9Sstevel@tonic-gate } else if ('A' <= dig && dig <= 'F') { 1800*7c478bd9Sstevel@tonic-gate return (dig - 'A' + 10); 1801*7c478bd9Sstevel@tonic-gate } else { 1802*7c478bd9Sstevel@tonic-gate return (-1); 1803*7c478bd9Sstevel@tonic-gate } 1804*7c478bd9Sstevel@tonic-gate } 1805*7c478bd9Sstevel@tonic-gate 1806*7c478bd9Sstevel@tonic-gate hex2bin(hex, bin, size) 1807*7c478bd9Sstevel@tonic-gate unsigned char *hex; 1808*7c478bd9Sstevel@tonic-gate unsigned char *bin; 1809*7c478bd9Sstevel@tonic-gate int size; 1810*7c478bd9Sstevel@tonic-gate { 1811*7c478bd9Sstevel@tonic-gate int i; 1812*7c478bd9Sstevel@tonic-gate 1813*7c478bd9Sstevel@tonic-gate for (i = 0; i < size; i++) { 1814*7c478bd9Sstevel@tonic-gate *bin = hexval(*hex++) << 4; 1815*7c478bd9Sstevel@tonic-gate *bin++ |= hexval(*hex++); 1816*7c478bd9Sstevel@tonic-gate } 1817*7c478bd9Sstevel@tonic-gate return (0); 1818*7c478bd9Sstevel@tonic-gate } 1819*7c478bd9Sstevel@tonic-gate 1820*7c478bd9Sstevel@tonic-gate static int 1821*7c478bd9Sstevel@tonic-gate hash_keys(pub, sec) 1822*7c478bd9Sstevel@tonic-gate char *pub; 1823*7c478bd9Sstevel@tonic-gate char *sec; 1824*7c478bd9Sstevel@tonic-gate { 1825*7c478bd9Sstevel@tonic-gate int i; 1826*7c478bd9Sstevel@tonic-gate int hash = 0; 1827*7c478bd9Sstevel@tonic-gate 1828*7c478bd9Sstevel@tonic-gate for (i = 0; i < HEXKEYBYTES; i += 6, pub += 6, sec += 6) { 1829*7c478bd9Sstevel@tonic-gate hash ^= *pub; 1830*7c478bd9Sstevel@tonic-gate hash ^= *sec; 1831*7c478bd9Sstevel@tonic-gate } 1832*7c478bd9Sstevel@tonic-gate return (hash & 0xff); 1833*7c478bd9Sstevel@tonic-gate } 1834*7c478bd9Sstevel@tonic-gate 1835*7c478bd9Sstevel@tonic-gate /* 1836*7c478bd9Sstevel@tonic-gate * problem: keyserv loads keys from /etc/.rootkey based on nisauthconf(1M) 1837*7c478bd9Sstevel@tonic-gate * which is too nis+-centric (see secure_rpc(3N)). 1838*7c478bd9Sstevel@tonic-gate * 1839*7c478bd9Sstevel@tonic-gate * So we want to make sure there is always a AUTH_DES compat entry 1840*7c478bd9Sstevel@tonic-gate * in the "list" of nis+ mechs so that the 192bit key always gets loaded so 1841*7c478bd9Sstevel@tonic-gate * non-nis+ services that use AUTH_DES (e.g. nfs) won't get hosed. The real 1842*7c478bd9Sstevel@tonic-gate * hacky part of it is we muck with the array returned from 1843*7c478bd9Sstevel@tonic-gate * __nis_get_mechanisms which we really don't have any business 1844*7c478bd9Sstevel@tonic-gate * doing cause we should not know/care how that is implemented. A better 1845*7c478bd9Sstevel@tonic-gate * way would be to change the __nis_get_mechanisms interface or add another 1846*7c478bd9Sstevel@tonic-gate * one similiar to it that forces the "des" compat entry into the list. 1847*7c478bd9Sstevel@tonic-gate * 1848*7c478bd9Sstevel@tonic-gate * Return ptr to mechs array on success, else NULL on memory errs. 1849*7c478bd9Sstevel@tonic-gate */ 1850*7c478bd9Sstevel@tonic-gate mechanism_t ** 1851*7c478bd9Sstevel@tonic-gate getmechwrap() 1852*7c478bd9Sstevel@tonic-gate { 1853*7c478bd9Sstevel@tonic-gate mechanism_t **mechs = __nis_get_mechanisms(FALSE); 1854*7c478bd9Sstevel@tonic-gate mechanism_t **mechsbak = NULL; 1855*7c478bd9Sstevel@tonic-gate mechanism_t *desmech = NULL; 1856*7c478bd9Sstevel@tonic-gate int i = 0; 1857*7c478bd9Sstevel@tonic-gate 1858*7c478bd9Sstevel@tonic-gate if (mechs) { 1859*7c478bd9Sstevel@tonic-gate /* got some valid mechs and possibly the AUTH_DES compat one */ 1860*7c478bd9Sstevel@tonic-gate for (i = 0; mechs[i]; i++) { 1861*7c478bd9Sstevel@tonic-gate if (AUTH_DES_COMPAT_CHK(mechs[i])) 1862*7c478bd9Sstevel@tonic-gate return (mechs); 1863*7c478bd9Sstevel@tonic-gate } 1864*7c478bd9Sstevel@tonic-gate /* i == number of ptrs not counting terminating NULL */ 1865*7c478bd9Sstevel@tonic-gate } 1866*7c478bd9Sstevel@tonic-gate 1867*7c478bd9Sstevel@tonic-gate /* AUTH_DES compat entry not found, let's add it */ 1868*7c478bd9Sstevel@tonic-gate if ((desmech = malloc(sizeof (mechanism_t))) == NULL) { 1869*7c478bd9Sstevel@tonic-gate if (mechs) 1870*7c478bd9Sstevel@tonic-gate __nis_release_mechanisms(mechs); 1871*7c478bd9Sstevel@tonic-gate return (NULL); 1872*7c478bd9Sstevel@tonic-gate } 1873*7c478bd9Sstevel@tonic-gate desmech->mechname = NULL; 1874*7c478bd9Sstevel@tonic-gate desmech->alias = NIS_SEC_CF_DES_ALIAS; 1875*7c478bd9Sstevel@tonic-gate desmech->keylen = AUTH_DES_KEYLEN; 1876*7c478bd9Sstevel@tonic-gate desmech->algtype = AUTH_DES_ALGTYPE; 1877*7c478bd9Sstevel@tonic-gate desmech->qop = NULL; 1878*7c478bd9Sstevel@tonic-gate desmech->secserv = rpc_gss_svc_default; 1879*7c478bd9Sstevel@tonic-gate 1880*7c478bd9Sstevel@tonic-gate mechsbak = mechs; 1881*7c478bd9Sstevel@tonic-gate /* mechs == NULL and i == 0 is valid "no mechs configed" case */ 1882*7c478bd9Sstevel@tonic-gate if ((mechs = (mechanism_t **)realloc(mechs, 1883*7c478bd9Sstevel@tonic-gate sizeof (mechanism_t *) * (i + 2))) == NULL) { 1884*7c478bd9Sstevel@tonic-gate if (mechsbak) 1885*7c478bd9Sstevel@tonic-gate __nis_release_mechanisms(mechsbak); 1886*7c478bd9Sstevel@tonic-gate free(desmech); 1887*7c478bd9Sstevel@tonic-gate return (NULL); 1888*7c478bd9Sstevel@tonic-gate } 1889*7c478bd9Sstevel@tonic-gate mechs[i] = desmech; 1890*7c478bd9Sstevel@tonic-gate mechs[i+1] = NULL; 1891*7c478bd9Sstevel@tonic-gate 1892*7c478bd9Sstevel@tonic-gate return (mechs); 1893*7c478bd9Sstevel@tonic-gate } 1894*7c478bd9Sstevel@tonic-gate 1895*7c478bd9Sstevel@tonic-gate int 1896*7c478bd9Sstevel@tonic-gate init_mechs() 1897*7c478bd9Sstevel@tonic-gate { 1898*7c478bd9Sstevel@tonic-gate int nmechs, oldmechseen; 1899*7c478bd9Sstevel@tonic-gate mechanism_t **mechpp; 1900*7c478bd9Sstevel@tonic-gate char **cpp; 1901*7c478bd9Sstevel@tonic-gate 1902*7c478bd9Sstevel@tonic-gate if (!(mechs = getmechwrap())) 1903*7c478bd9Sstevel@tonic-gate return (-1); 1904*7c478bd9Sstevel@tonic-gate 1905*7c478bd9Sstevel@tonic-gate /* 1906*7c478bd9Sstevel@tonic-gate * find how many mechanisms were specified and also 1907*7c478bd9Sstevel@tonic-gate * setup the mechanism table for unique keylen/algtype pair 1908*7c478bd9Sstevel@tonic-gate */ 1909*7c478bd9Sstevel@tonic-gate nmechs = 0; 1910*7c478bd9Sstevel@tonic-gate for (mechpp = mechs; *mechpp != NULL; mechpp++) { 1911*7c478bd9Sstevel@tonic-gate struct keylenlist **kpp; 1912*7c478bd9Sstevel@tonic-gate struct algtypelist **app; 1913*7c478bd9Sstevel@tonic-gate 1914*7c478bd9Sstevel@tonic-gate nmechs++; 1915*7c478bd9Sstevel@tonic-gate if (((*mechpp)->keylen < 0) || ((*mechpp)->algtype < 0)) { 1916*7c478bd9Sstevel@tonic-gate continue; 1917*7c478bd9Sstevel@tonic-gate } 1918*7c478bd9Sstevel@tonic-gate kpp = getkeylen((*mechpp)->keylen); 1919*7c478bd9Sstevel@tonic-gate appendkeylist(kpp, (*mechpp)->keylen); 1920*7c478bd9Sstevel@tonic-gate app = getalgtype(kpp, (*mechpp)->algtype); 1921*7c478bd9Sstevel@tonic-gate appendalgtype(app, (*mechpp)->algtype); 1922*7c478bd9Sstevel@tonic-gate } 1923*7c478bd9Sstevel@tonic-gate 1924*7c478bd9Sstevel@tonic-gate /* 1925*7c478bd9Sstevel@tonic-gate * set of mechs for getsubopt() 1926*7c478bd9Sstevel@tonic-gate */ 1927*7c478bd9Sstevel@tonic-gate cache_options = (char **)calloc((size_t)nmechs + 1, 1928*7c478bd9Sstevel@tonic-gate sizeof (*cache_options)); 1929*7c478bd9Sstevel@tonic-gate if (cache_options == NULL) { 1930*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "unable to allocate option array"); 1931*7c478bd9Sstevel@tonic-gate return (-1); 1932*7c478bd9Sstevel@tonic-gate } 1933*7c478bd9Sstevel@tonic-gate /* 1934*7c478bd9Sstevel@tonic-gate * cache sizes 1935*7c478bd9Sstevel@tonic-gate */ 1936*7c478bd9Sstevel@tonic-gate cache_size = (int *)calloc((size_t)nmechs, sizeof (int)); 1937*7c478bd9Sstevel@tonic-gate if (cache_size == NULL) { 1938*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "unable to allocate cache array"); 1939*7c478bd9Sstevel@tonic-gate return (-1); 1940*7c478bd9Sstevel@tonic-gate } 1941*7c478bd9Sstevel@tonic-gate 1942*7c478bd9Sstevel@tonic-gate oldmechseen = 0; 1943*7c478bd9Sstevel@tonic-gate cpp = cache_options; 1944*7c478bd9Sstevel@tonic-gate for (mechpp = mechs; *mechpp != NULL; mechpp++) { 1945*7c478bd9Sstevel@tonic-gate /* 1946*7c478bd9Sstevel@tonic-gate * usual case: a DH-style mechanism type, with an alias 1947*7c478bd9Sstevel@tonic-gate */ 1948*7c478bd9Sstevel@tonic-gate if ((*mechpp)->mechname != NULL && 1949*7c478bd9Sstevel@tonic-gate strncmp((*mechpp)->mechname, DHMECHSTR, 1950*7c478bd9Sstevel@tonic-gate strlen(DHMECHSTR)) == 0 && 1951*7c478bd9Sstevel@tonic-gate (*mechpp)->alias != NULL) { 1952*7c478bd9Sstevel@tonic-gate /* 1953*7c478bd9Sstevel@tonic-gate * Is this trad 192-DH? already added? 1954*7c478bd9Sstevel@tonic-gate */ 1955*7c478bd9Sstevel@tonic-gate if (strcmp((*mechpp)->alias, DESALIAS) == 0) { 1956*7c478bd9Sstevel@tonic-gate if (oldmechseen) { 1957*7c478bd9Sstevel@tonic-gate continue; 1958*7c478bd9Sstevel@tonic-gate } 1959*7c478bd9Sstevel@tonic-gate oldmechseen++; 1960*7c478bd9Sstevel@tonic-gate } 1961*7c478bd9Sstevel@tonic-gate 1962*7c478bd9Sstevel@tonic-gate *cpp++ = (*mechpp)->alias; 1963*7c478bd9Sstevel@tonic-gate continue; 1964*7c478bd9Sstevel@tonic-gate } 1965*7c478bd9Sstevel@tonic-gate 1966*7c478bd9Sstevel@tonic-gate /* 1967*7c478bd9Sstevel@tonic-gate * HACK: we recognise a special alias for traditional 1968*7c478bd9Sstevel@tonic-gate * 192-bit DH, unless the latter has already been mentioned 1969*7c478bd9Sstevel@tonic-gate * in it's full form 1970*7c478bd9Sstevel@tonic-gate */ 1971*7c478bd9Sstevel@tonic-gate if ((*mechpp)->mechname == NULL && (*mechpp)->alias != NULL && 1972*7c478bd9Sstevel@tonic-gate strcmp((*mechpp)->alias, DES) == 0 && !oldmechseen) { 1973*7c478bd9Sstevel@tonic-gate *cpp++ = DESALIAS; 1974*7c478bd9Sstevel@tonic-gate oldmechseen++; 1975*7c478bd9Sstevel@tonic-gate continue; 1976*7c478bd9Sstevel@tonic-gate } 1977*7c478bd9Sstevel@tonic-gate 1978*7c478bd9Sstevel@tonic-gate /* 1979*7c478bd9Sstevel@tonic-gate * Ignore anything else 1980*7c478bd9Sstevel@tonic-gate */ 1981*7c478bd9Sstevel@tonic-gate } 1982*7c478bd9Sstevel@tonic-gate 1983*7c478bd9Sstevel@tonic-gate /* Terminate the options list */ 1984*7c478bd9Sstevel@tonic-gate *cpp = NULL; 1985*7c478bd9Sstevel@tonic-gate 1986*7c478bd9Sstevel@tonic-gate return (0); 1987*7c478bd9Sstevel@tonic-gate } 1988