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 2003 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 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 28*7c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 29*7c478bd9Sstevel@tonic-gate 30*7c478bd9Sstevel@tonic-gate /* 31*7c478bd9Sstevel@tonic-gate * Portions of this source code were derived from Berkeley 4.3 BSD 32*7c478bd9Sstevel@tonic-gate * under license from the Regents of the University of California. 33*7c478bd9Sstevel@tonic-gate */ 34*7c478bd9Sstevel@tonic-gate 35*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 36*7c478bd9Sstevel@tonic-gate 37*7c478bd9Sstevel@tonic-gate /* 38*7c478bd9Sstevel@tonic-gate * publickey.c 39*7c478bd9Sstevel@tonic-gate * 40*7c478bd9Sstevel@tonic-gate * 41*7c478bd9Sstevel@tonic-gate * Public and Private (secret) key lookup routines. These functions 42*7c478bd9Sstevel@tonic-gate * are used by the secure RPC auth_des flavor to get the public and 43*7c478bd9Sstevel@tonic-gate * private keys for secure RPC principals. Originally designed to 44*7c478bd9Sstevel@tonic-gate * talk only to YP, AT&T modified them to talk to files, and now 45*7c478bd9Sstevel@tonic-gate * they can also talk to NIS+. The policy for these lookups is now 46*7c478bd9Sstevel@tonic-gate * defined in terms of the nameservice switch as follows : 47*7c478bd9Sstevel@tonic-gate * publickey: nis files 48*7c478bd9Sstevel@tonic-gate * 49*7c478bd9Sstevel@tonic-gate * Note : 50*7c478bd9Sstevel@tonic-gate * 1. NIS+ combines the netid.byname and publickey.byname maps 51*7c478bd9Sstevel@tonic-gate * into a single NIS+ table named cred.org_dir 52*7c478bd9Sstevel@tonic-gate * 2. To use NIS+, the publickey needs to be 53*7c478bd9Sstevel@tonic-gate * publickey: nisplus 54*7c478bd9Sstevel@tonic-gate * (or have nisplus as the first entry). 55*7c478bd9Sstevel@tonic-gate * The nsswitch.conf file should be updated after running nisinit 56*7c478bd9Sstevel@tonic-gate * to reflect this. 57*7c478bd9Sstevel@tonic-gate */ 58*7c478bd9Sstevel@tonic-gate #include "mt.h" 59*7c478bd9Sstevel@tonic-gate #include "../rpc/rpc_mt.h" 60*7c478bd9Sstevel@tonic-gate #include <stdio.h> 61*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 62*7c478bd9Sstevel@tonic-gate #include <string.h> 63*7c478bd9Sstevel@tonic-gate #include <syslog.h> 64*7c478bd9Sstevel@tonic-gate #include <assert.h> 65*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 66*7c478bd9Sstevel@tonic-gate #include <rpc/trace.h> 67*7c478bd9Sstevel@tonic-gate #include <pwd.h> 68*7c478bd9Sstevel@tonic-gate #include "nsswitch.h" 69*7c478bd9Sstevel@tonic-gate #include <rpc/rpc.h> 70*7c478bd9Sstevel@tonic-gate #include <rpc/key_prot.h> 71*7c478bd9Sstevel@tonic-gate #include <rpcsvc/nis.h> 72*7c478bd9Sstevel@tonic-gate #include <rpcsvc/ypclnt.h> 73*7c478bd9Sstevel@tonic-gate #include <rpcsvc/nis_dhext.h> 74*7c478bd9Sstevel@tonic-gate #include <thread.h> 75*7c478bd9Sstevel@tonic-gate #include "../nis/gen/nis_clnt.h" 76*7c478bd9Sstevel@tonic-gate #include <nss_dbdefs.h> 77*7c478bd9Sstevel@tonic-gate #include "nsl_stdio_prv.h" 78*7c478bd9Sstevel@tonic-gate 79*7c478bd9Sstevel@tonic-gate static const char *PKTABLE = "cred.org_dir"; 80*7c478bd9Sstevel@tonic-gate static const char *PKMAP = "publickey.byname"; 81*7c478bd9Sstevel@tonic-gate static const char *PKFILE = "/etc/publickey"; 82*7c478bd9Sstevel@tonic-gate static const char dh_caps_str[] = "DH"; 83*7c478bd9Sstevel@tonic-gate static const char des_caps_str[] = AUTH_DES_AUTH_TYPE; 84*7c478bd9Sstevel@tonic-gate 85*7c478bd9Sstevel@tonic-gate static char *netname2hashname(const char *, char *, int, keylen_t, 86*7c478bd9Sstevel@tonic-gate algtype_t); 87*7c478bd9Sstevel@tonic-gate 88*7c478bd9Sstevel@tonic-gate #define PKTABLE_LEN 12 89*7c478bd9Sstevel@tonic-gate #define WORKBUFSIZE 1024 90*7c478bd9Sstevel@tonic-gate 91*7c478bd9Sstevel@tonic-gate extern int xdecrypt(); 92*7c478bd9Sstevel@tonic-gate 93*7c478bd9Sstevel@tonic-gate extern int __yp_match_cflookup(char *, char *, char *, int, char **, 94*7c478bd9Sstevel@tonic-gate int *, int *); 95*7c478bd9Sstevel@tonic-gate 96*7c478bd9Sstevel@tonic-gate 97*7c478bd9Sstevel@tonic-gate /* 98*7c478bd9Sstevel@tonic-gate * default publickey policy: 99*7c478bd9Sstevel@tonic-gate * publickey: nis [NOTFOUND = return] files 100*7c478bd9Sstevel@tonic-gate */ 101*7c478bd9Sstevel@tonic-gate 102*7c478bd9Sstevel@tonic-gate 103*7c478bd9Sstevel@tonic-gate /* NSW_NOTSUCCESS NSW_NOTFOUND NSW_UNAVAIL NSW_TRYAGAIN */ 104*7c478bd9Sstevel@tonic-gate #define DEF_ACTION {__NSW_RETURN, __NSW_RETURN, __NSW_CONTINUE, __NSW_CONTINUE} 105*7c478bd9Sstevel@tonic-gate 106*7c478bd9Sstevel@tonic-gate static struct __nsw_lookup lookup_files = {"files", DEF_ACTION, NULL, NULL}, 107*7c478bd9Sstevel@tonic-gate lookup_nis = {"nis", DEF_ACTION, NULL, &lookup_files}; 108*7c478bd9Sstevel@tonic-gate static struct __nsw_switchconfig publickey_default = 109*7c478bd9Sstevel@tonic-gate {0, "publickey", 2, &lookup_nis}; 110*7c478bd9Sstevel@tonic-gate 111*7c478bd9Sstevel@tonic-gate #ifndef NUL 112*7c478bd9Sstevel@tonic-gate #define NUL '\0' 113*7c478bd9Sstevel@tonic-gate #endif 114*7c478bd9Sstevel@tonic-gate 115*7c478bd9Sstevel@tonic-gate extern mutex_t serialize_pkey; 116*7c478bd9Sstevel@tonic-gate 117*7c478bd9Sstevel@tonic-gate static void pkey_cache_add(); 118*7c478bd9Sstevel@tonic-gate static int pkey_cache_get(); 119*7c478bd9Sstevel@tonic-gate static void pkey_cache_flush(); 120*7c478bd9Sstevel@tonic-gate 121*7c478bd9Sstevel@tonic-gate static int extract_secret(); 122*7c478bd9Sstevel@tonic-gate 123*7c478bd9Sstevel@tonic-gate /* 124*7c478bd9Sstevel@tonic-gate * db_root is used for switch backends. 125*7c478bd9Sstevel@tonic-gate */ 126*7c478bd9Sstevel@tonic-gate static DEFINE_NSS_DB_ROOT(db_root); 127*7c478bd9Sstevel@tonic-gate 128*7c478bd9Sstevel@tonic-gate /* 129*7c478bd9Sstevel@tonic-gate * These functions are the "backends" for the switch for public keys. They 130*7c478bd9Sstevel@tonic-gate * get both the public and private keys from each of the supported name 131*7c478bd9Sstevel@tonic-gate * services (nis, nisplus, files). They are passed the appropriate parameters 132*7c478bd9Sstevel@tonic-gate * and return 0 if unsuccessful with *errp set, or 1 when they got just the 133*7c478bd9Sstevel@tonic-gate * public key and 3 when they got both the public and private keys. 134*7c478bd9Sstevel@tonic-gate * 135*7c478bd9Sstevel@tonic-gate * 136*7c478bd9Sstevel@tonic-gate * getkey_nis() 137*7c478bd9Sstevel@tonic-gate * 138*7c478bd9Sstevel@tonic-gate * Internal implementation of getpublickey() using NIS (aka Yellow Pages, 139*7c478bd9Sstevel@tonic-gate * aka YP). 140*7c478bd9Sstevel@tonic-gate * 141*7c478bd9Sstevel@tonic-gate * NOTE : *** this function returns nsswitch codes and _not_ the 142*7c478bd9Sstevel@tonic-gate * value returned by getpublickey. 143*7c478bd9Sstevel@tonic-gate */ 144*7c478bd9Sstevel@tonic-gate static int 145*7c478bd9Sstevel@tonic-gate getkeys_nis(errp, netname, pkey, skey, passwd) 146*7c478bd9Sstevel@tonic-gate int *errp; 147*7c478bd9Sstevel@tonic-gate char *netname; 148*7c478bd9Sstevel@tonic-gate char *pkey; 149*7c478bd9Sstevel@tonic-gate char *skey; 150*7c478bd9Sstevel@tonic-gate char *passwd; 151*7c478bd9Sstevel@tonic-gate { 152*7c478bd9Sstevel@tonic-gate char *domain; 153*7c478bd9Sstevel@tonic-gate char *keyval = NULL; 154*7c478bd9Sstevel@tonic-gate int keylen, err, r = 0; 155*7c478bd9Sstevel@tonic-gate char *p; 156*7c478bd9Sstevel@tonic-gate int len; 157*7c478bd9Sstevel@tonic-gate 158*7c478bd9Sstevel@tonic-gate trace1(TR_getkeys_nis, 0); 159*7c478bd9Sstevel@tonic-gate 160*7c478bd9Sstevel@tonic-gate p = strchr(netname, '@'); 161*7c478bd9Sstevel@tonic-gate if (! p) { 162*7c478bd9Sstevel@tonic-gate *errp = __NSW_UNAVAIL; 163*7c478bd9Sstevel@tonic-gate trace1(TR_getkeys_nis, 1); 164*7c478bd9Sstevel@tonic-gate return (0); 165*7c478bd9Sstevel@tonic-gate } 166*7c478bd9Sstevel@tonic-gate 167*7c478bd9Sstevel@tonic-gate domain = ++p; 168*7c478bd9Sstevel@tonic-gate 169*7c478bd9Sstevel@tonic-gate 170*7c478bd9Sstevel@tonic-gate /* 171*7c478bd9Sstevel@tonic-gate * Instead of calling yp_match(), we use __yp_match_cflookup() here 172*7c478bd9Sstevel@tonic-gate * which has time-out control for the binding operation to nis 173*7c478bd9Sstevel@tonic-gate * servers. 174*7c478bd9Sstevel@tonic-gate */ 175*7c478bd9Sstevel@tonic-gate err = __yp_match_cflookup(domain, (char *)PKMAP, netname, 176*7c478bd9Sstevel@tonic-gate strlen(netname), &keyval, &keylen, 0); 177*7c478bd9Sstevel@tonic-gate 178*7c478bd9Sstevel@tonic-gate switch (err) { 179*7c478bd9Sstevel@tonic-gate case YPERR_KEY : 180*7c478bd9Sstevel@tonic-gate if (keyval) 181*7c478bd9Sstevel@tonic-gate free(keyval); 182*7c478bd9Sstevel@tonic-gate *errp = __NSW_NOTFOUND; 183*7c478bd9Sstevel@tonic-gate trace1(TR_getkeys_nis, 1); 184*7c478bd9Sstevel@tonic-gate return (0); 185*7c478bd9Sstevel@tonic-gate default : 186*7c478bd9Sstevel@tonic-gate if (keyval) 187*7c478bd9Sstevel@tonic-gate free(keyval); 188*7c478bd9Sstevel@tonic-gate *errp = __NSW_UNAVAIL; 189*7c478bd9Sstevel@tonic-gate trace1(TR_getkeys_nis, 1); 190*7c478bd9Sstevel@tonic-gate return (0); 191*7c478bd9Sstevel@tonic-gate case 0: 192*7c478bd9Sstevel@tonic-gate break; 193*7c478bd9Sstevel@tonic-gate } 194*7c478bd9Sstevel@tonic-gate 195*7c478bd9Sstevel@tonic-gate p = strchr(keyval, ':'); 196*7c478bd9Sstevel@tonic-gate if (p == NULL) { 197*7c478bd9Sstevel@tonic-gate free(keyval); 198*7c478bd9Sstevel@tonic-gate *errp = __NSW_NOTFOUND; 199*7c478bd9Sstevel@tonic-gate trace1(TR_getkeys_nis, 1); 200*7c478bd9Sstevel@tonic-gate return (0); 201*7c478bd9Sstevel@tonic-gate } 202*7c478bd9Sstevel@tonic-gate *p = 0; 203*7c478bd9Sstevel@tonic-gate if (pkey) { 204*7c478bd9Sstevel@tonic-gate len = strlen(keyval); 205*7c478bd9Sstevel@tonic-gate if (len > HEXKEYBYTES) { 206*7c478bd9Sstevel@tonic-gate free(keyval); 207*7c478bd9Sstevel@tonic-gate *errp = __NSW_NOTFOUND; 208*7c478bd9Sstevel@tonic-gate trace1(TR_getkeys_nis, 1); 209*7c478bd9Sstevel@tonic-gate return (0); 210*7c478bd9Sstevel@tonic-gate } 211*7c478bd9Sstevel@tonic-gate (void) strcpy(pkey, keyval); 212*7c478bd9Sstevel@tonic-gate } 213*7c478bd9Sstevel@tonic-gate r = 1; 214*7c478bd9Sstevel@tonic-gate p++; 215*7c478bd9Sstevel@tonic-gate if (skey && extract_secret(p, skey, passwd)) 216*7c478bd9Sstevel@tonic-gate r |= 2; 217*7c478bd9Sstevel@tonic-gate free(keyval); 218*7c478bd9Sstevel@tonic-gate *errp = __NSW_SUCCESS; 219*7c478bd9Sstevel@tonic-gate trace1(TR_getkeys_nis, 1); 220*7c478bd9Sstevel@tonic-gate return (r); 221*7c478bd9Sstevel@tonic-gate } 222*7c478bd9Sstevel@tonic-gate 223*7c478bd9Sstevel@tonic-gate /* 224*7c478bd9Sstevel@tonic-gate * getkey_files() 225*7c478bd9Sstevel@tonic-gate * 226*7c478bd9Sstevel@tonic-gate * The files version of getpublickey. This function attempts to 227*7c478bd9Sstevel@tonic-gate * get the publickey from the file PKFILE . 228*7c478bd9Sstevel@tonic-gate * 229*7c478bd9Sstevel@tonic-gate * This function defines the format of the /etc/publickey file to 230*7c478bd9Sstevel@tonic-gate * be : 231*7c478bd9Sstevel@tonic-gate * netname <whitespace> publickey:privatekey 232*7c478bd9Sstevel@tonic-gate * 233*7c478bd9Sstevel@tonic-gate * NOTE : *** this function returns nsswitch codes and _not_ the 234*7c478bd9Sstevel@tonic-gate * value returned by getpublickey. 235*7c478bd9Sstevel@tonic-gate */ 236*7c478bd9Sstevel@tonic-gate 237*7c478bd9Sstevel@tonic-gate static int 238*7c478bd9Sstevel@tonic-gate getkeys_files(errp, netname, pkey, skey, passwd) 239*7c478bd9Sstevel@tonic-gate int *errp; 240*7c478bd9Sstevel@tonic-gate char *netname; 241*7c478bd9Sstevel@tonic-gate char *pkey; 242*7c478bd9Sstevel@tonic-gate char *skey; 243*7c478bd9Sstevel@tonic-gate char *passwd; 244*7c478bd9Sstevel@tonic-gate { 245*7c478bd9Sstevel@tonic-gate char *mkey; 246*7c478bd9Sstevel@tonic-gate char *mval; 247*7c478bd9Sstevel@tonic-gate char buf[WORKBUFSIZE]; 248*7c478bd9Sstevel@tonic-gate int r = 0; 249*7c478bd9Sstevel@tonic-gate char *res; 250*7c478bd9Sstevel@tonic-gate __NSL_FILE *fd; 251*7c478bd9Sstevel@tonic-gate char *p; 252*7c478bd9Sstevel@tonic-gate char *lasts; 253*7c478bd9Sstevel@tonic-gate 254*7c478bd9Sstevel@tonic-gate trace1(TR_getkeys_files, 0); 255*7c478bd9Sstevel@tonic-gate 256*7c478bd9Sstevel@tonic-gate fd = __nsl_fopen(PKFILE, "r"); 257*7c478bd9Sstevel@tonic-gate if (fd == (__NSL_FILE *)0) { 258*7c478bd9Sstevel@tonic-gate *errp = __NSW_UNAVAIL; 259*7c478bd9Sstevel@tonic-gate trace1(TR_getkeys_files, 1); 260*7c478bd9Sstevel@tonic-gate return (0); 261*7c478bd9Sstevel@tonic-gate } 262*7c478bd9Sstevel@tonic-gate 263*7c478bd9Sstevel@tonic-gate /* Search through the file linearly :-( */ 264*7c478bd9Sstevel@tonic-gate while ((res = __nsl_fgets(buf, WORKBUFSIZE, fd)) != NULL) { 265*7c478bd9Sstevel@tonic-gate 266*7c478bd9Sstevel@tonic-gate if ((res[0] == '#') || (res[0] == '\n')) 267*7c478bd9Sstevel@tonic-gate continue; 268*7c478bd9Sstevel@tonic-gate else { 269*7c478bd9Sstevel@tonic-gate mkey = strtok_r(buf, "\t ", &lasts); 270*7c478bd9Sstevel@tonic-gate if (mkey == NULL) { 271*7c478bd9Sstevel@tonic-gate syslog(LOG_INFO, 272*7c478bd9Sstevel@tonic-gate "getpublickey: Bad record in %s for %s", 273*7c478bd9Sstevel@tonic-gate PKFILE, netname); 274*7c478bd9Sstevel@tonic-gate continue; 275*7c478bd9Sstevel@tonic-gate } 276*7c478bd9Sstevel@tonic-gate mval = strtok_r((char *)NULL, " \t#\n", &lasts); 277*7c478bd9Sstevel@tonic-gate if (mval == NULL) { 278*7c478bd9Sstevel@tonic-gate syslog(LOG_INFO, 279*7c478bd9Sstevel@tonic-gate "getpublickey: Bad record in %s for %s", 280*7c478bd9Sstevel@tonic-gate PKFILE, netname); 281*7c478bd9Sstevel@tonic-gate continue; 282*7c478bd9Sstevel@tonic-gate } 283*7c478bd9Sstevel@tonic-gate /* NOTE : Case insensitive compare. */ 284*7c478bd9Sstevel@tonic-gate if (strcasecmp(mkey, netname) == 0) { 285*7c478bd9Sstevel@tonic-gate p = strchr(mval, ':'); 286*7c478bd9Sstevel@tonic-gate if (p == NULL) { 287*7c478bd9Sstevel@tonic-gate syslog(LOG_INFO, 288*7c478bd9Sstevel@tonic-gate "getpublickey: Bad record in %s for %s", 289*7c478bd9Sstevel@tonic-gate PKFILE, netname); 290*7c478bd9Sstevel@tonic-gate continue; 291*7c478bd9Sstevel@tonic-gate } 292*7c478bd9Sstevel@tonic-gate 293*7c478bd9Sstevel@tonic-gate *p = 0; 294*7c478bd9Sstevel@tonic-gate if (pkey) { 295*7c478bd9Sstevel@tonic-gate int len = strlen(mval); 296*7c478bd9Sstevel@tonic-gate 297*7c478bd9Sstevel@tonic-gate if (len > HEXKEYBYTES) { 298*7c478bd9Sstevel@tonic-gate syslog(LOG_INFO, 299*7c478bd9Sstevel@tonic-gate "getpublickey: Bad record in %s for %s", 300*7c478bd9Sstevel@tonic-gate PKFILE, netname); 301*7c478bd9Sstevel@tonic-gate continue; 302*7c478bd9Sstevel@tonic-gate } 303*7c478bd9Sstevel@tonic-gate (void) strcpy(pkey, mval); 304*7c478bd9Sstevel@tonic-gate } 305*7c478bd9Sstevel@tonic-gate r = 1; 306*7c478bd9Sstevel@tonic-gate p++; 307*7c478bd9Sstevel@tonic-gate if (skey && extract_secret(p, skey, passwd)) 308*7c478bd9Sstevel@tonic-gate r |= 2; 309*7c478bd9Sstevel@tonic-gate (void) __nsl_fclose(fd); 310*7c478bd9Sstevel@tonic-gate *errp = __NSW_SUCCESS; 311*7c478bd9Sstevel@tonic-gate trace1(TR_getkeys_files, 1); 312*7c478bd9Sstevel@tonic-gate return (r); 313*7c478bd9Sstevel@tonic-gate } 314*7c478bd9Sstevel@tonic-gate } 315*7c478bd9Sstevel@tonic-gate } 316*7c478bd9Sstevel@tonic-gate 317*7c478bd9Sstevel@tonic-gate (void) __nsl_fclose(fd); 318*7c478bd9Sstevel@tonic-gate *errp = __NSW_NOTFOUND; 319*7c478bd9Sstevel@tonic-gate trace1(TR_getkeys_files, 1); 320*7c478bd9Sstevel@tonic-gate return (0); 321*7c478bd9Sstevel@tonic-gate } 322*7c478bd9Sstevel@tonic-gate 323*7c478bd9Sstevel@tonic-gate /* 324*7c478bd9Sstevel@tonic-gate * getpublickey(netname, key) 325*7c478bd9Sstevel@tonic-gate * 326*7c478bd9Sstevel@tonic-gate * This is the actual exported interface for this function. 327*7c478bd9Sstevel@tonic-gate */ 328*7c478bd9Sstevel@tonic-gate 329*7c478bd9Sstevel@tonic-gate int 330*7c478bd9Sstevel@tonic-gate __getpublickey_cached(netname, pkey, from_cache) 331*7c478bd9Sstevel@tonic-gate char *netname; 332*7c478bd9Sstevel@tonic-gate char *pkey; 333*7c478bd9Sstevel@tonic-gate int *from_cache; 334*7c478bd9Sstevel@tonic-gate { 335*7c478bd9Sstevel@tonic-gate return (__getpublickey_cached_g(netname, KEYSIZE, 0, pkey, 336*7c478bd9Sstevel@tonic-gate HEXKEYBYTES+1, from_cache)); 337*7c478bd9Sstevel@tonic-gate } 338*7c478bd9Sstevel@tonic-gate 339*7c478bd9Sstevel@tonic-gate int 340*7c478bd9Sstevel@tonic-gate getpublickey(netname, pkey) 341*7c478bd9Sstevel@tonic-gate const char *netname; 342*7c478bd9Sstevel@tonic-gate char *pkey; 343*7c478bd9Sstevel@tonic-gate { 344*7c478bd9Sstevel@tonic-gate return (__getpublickey_cached((char *)netname, pkey, (int *)0)); 345*7c478bd9Sstevel@tonic-gate } 346*7c478bd9Sstevel@tonic-gate 347*7c478bd9Sstevel@tonic-gate void 348*7c478bd9Sstevel@tonic-gate __getpublickey_flush(const char *netname) 349*7c478bd9Sstevel@tonic-gate { 350*7c478bd9Sstevel@tonic-gate __getpublickey_flush_g(netname, 192, 0); 351*7c478bd9Sstevel@tonic-gate } 352*7c478bd9Sstevel@tonic-gate 353*7c478bd9Sstevel@tonic-gate int 354*7c478bd9Sstevel@tonic-gate getsecretkey(netname, skey, passwd) 355*7c478bd9Sstevel@tonic-gate const char *netname; 356*7c478bd9Sstevel@tonic-gate char *skey; 357*7c478bd9Sstevel@tonic-gate const char *passwd; 358*7c478bd9Sstevel@tonic-gate { 359*7c478bd9Sstevel@tonic-gate return (getsecretkey_g(netname, KEYSIZE, 0, skey, HEXKEYBYTES+1, 360*7c478bd9Sstevel@tonic-gate passwd)); 361*7c478bd9Sstevel@tonic-gate } 362*7c478bd9Sstevel@tonic-gate 363*7c478bd9Sstevel@tonic-gate /* 364*7c478bd9Sstevel@tonic-gate * Routines to cache publickeys. 365*7c478bd9Sstevel@tonic-gate */ 366*7c478bd9Sstevel@tonic-gate 367*7c478bd9Sstevel@tonic-gate static NIS_HASH_TABLE pkey_tbl; 368*7c478bd9Sstevel@tonic-gate struct pkey_item { 369*7c478bd9Sstevel@tonic-gate NIS_HASH_ITEM item; 370*7c478bd9Sstevel@tonic-gate char *pkey; 371*7c478bd9Sstevel@tonic-gate }; 372*7c478bd9Sstevel@tonic-gate 373*7c478bd9Sstevel@tonic-gate static void 374*7c478bd9Sstevel@tonic-gate pkey_cache_add(netname, pkey) 375*7c478bd9Sstevel@tonic-gate const char *netname; 376*7c478bd9Sstevel@tonic-gate char *pkey; 377*7c478bd9Sstevel@tonic-gate { 378*7c478bd9Sstevel@tonic-gate struct pkey_item *item; 379*7c478bd9Sstevel@tonic-gate 380*7c478bd9Sstevel@tonic-gate if (! netname || ! pkey) { 381*7c478bd9Sstevel@tonic-gate return; 382*7c478bd9Sstevel@tonic-gate } 383*7c478bd9Sstevel@tonic-gate 384*7c478bd9Sstevel@tonic-gate item = (struct pkey_item *)calloc(1, sizeof (struct pkey_item)); 385*7c478bd9Sstevel@tonic-gate if (item == NULL) { 386*7c478bd9Sstevel@tonic-gate return; 387*7c478bd9Sstevel@tonic-gate } 388*7c478bd9Sstevel@tonic-gate item->item.name = strdup(netname); 389*7c478bd9Sstevel@tonic-gate if (item->item.name == NULL) { 390*7c478bd9Sstevel@tonic-gate free((void *)item); 391*7c478bd9Sstevel@tonic-gate return; 392*7c478bd9Sstevel@tonic-gate } 393*7c478bd9Sstevel@tonic-gate item->pkey = strdup(pkey); 394*7c478bd9Sstevel@tonic-gate if (item->pkey == 0) { 395*7c478bd9Sstevel@tonic-gate free(item->item.name); 396*7c478bd9Sstevel@tonic-gate free(item); 397*7c478bd9Sstevel@tonic-gate return; 398*7c478bd9Sstevel@tonic-gate } 399*7c478bd9Sstevel@tonic-gate 400*7c478bd9Sstevel@tonic-gate (void) mutex_lock(&serialize_pkey); 401*7c478bd9Sstevel@tonic-gate if (!nis_insert_item((NIS_HASH_ITEM *)item, &pkey_tbl)) { 402*7c478bd9Sstevel@tonic-gate free(item->item.name); 403*7c478bd9Sstevel@tonic-gate free(item->pkey); 404*7c478bd9Sstevel@tonic-gate free((void *)item); 405*7c478bd9Sstevel@tonic-gate } 406*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&serialize_pkey); 407*7c478bd9Sstevel@tonic-gate } 408*7c478bd9Sstevel@tonic-gate 409*7c478bd9Sstevel@tonic-gate static int 410*7c478bd9Sstevel@tonic-gate pkey_cache_get(netname, pkey) 411*7c478bd9Sstevel@tonic-gate const char *netname; 412*7c478bd9Sstevel@tonic-gate char *pkey; 413*7c478bd9Sstevel@tonic-gate { 414*7c478bd9Sstevel@tonic-gate struct pkey_item *item; 415*7c478bd9Sstevel@tonic-gate 416*7c478bd9Sstevel@tonic-gate if (! netname || ! pkey) { 417*7c478bd9Sstevel@tonic-gate return (0); 418*7c478bd9Sstevel@tonic-gate } 419*7c478bd9Sstevel@tonic-gate 420*7c478bd9Sstevel@tonic-gate (void) mutex_lock(&serialize_pkey); 421*7c478bd9Sstevel@tonic-gate item = (struct pkey_item *)nis_find_item((char *)netname, &pkey_tbl); 422*7c478bd9Sstevel@tonic-gate if (item) { 423*7c478bd9Sstevel@tonic-gate (void) strcpy(pkey, item->pkey); 424*7c478bd9Sstevel@tonic-gate } 425*7c478bd9Sstevel@tonic-gate 426*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&serialize_pkey); 427*7c478bd9Sstevel@tonic-gate return (item != 0); 428*7c478bd9Sstevel@tonic-gate } 429*7c478bd9Sstevel@tonic-gate 430*7c478bd9Sstevel@tonic-gate static void 431*7c478bd9Sstevel@tonic-gate pkey_cache_flush(netname) 432*7c478bd9Sstevel@tonic-gate const char *netname; 433*7c478bd9Sstevel@tonic-gate { 434*7c478bd9Sstevel@tonic-gate struct pkey_item *item; 435*7c478bd9Sstevel@tonic-gate 436*7c478bd9Sstevel@tonic-gate (void) mutex_lock(&serialize_pkey); 437*7c478bd9Sstevel@tonic-gate 438*7c478bd9Sstevel@tonic-gate item = (struct pkey_item *)nis_remove_item((char *)netname, &pkey_tbl); 439*7c478bd9Sstevel@tonic-gate if (item) { 440*7c478bd9Sstevel@tonic-gate free(item->item.name); 441*7c478bd9Sstevel@tonic-gate free(item->pkey); 442*7c478bd9Sstevel@tonic-gate free((void *)item); 443*7c478bd9Sstevel@tonic-gate } 444*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&serialize_pkey); 445*7c478bd9Sstevel@tonic-gate } 446*7c478bd9Sstevel@tonic-gate 447*7c478bd9Sstevel@tonic-gate /* 448*7c478bd9Sstevel@tonic-gate * To avoid a potential deadlock with a single root domain NIS+ server 449*7c478bd9Sstevel@tonic-gate * talking to a sub-sub-domain server, the NIS+ directory cache manager 450*7c478bd9Sstevel@tonic-gate * code must be able to add public keys to the cache. Hence this routine. 451*7c478bd9Sstevel@tonic-gate */ 452*7c478bd9Sstevel@tonic-gate void 453*7c478bd9Sstevel@tonic-gate __pkey_cache_add(char *netname, char *pkey, keylen_t pkeylen, 454*7c478bd9Sstevel@tonic-gate algtype_t algtype) { 455*7c478bd9Sstevel@tonic-gate 456*7c478bd9Sstevel@tonic-gate char hashname[MAXNETNAMELEN+1]; 457*7c478bd9Sstevel@tonic-gate 458*7c478bd9Sstevel@tonic-gate pkey_cache_add(netname2hashname(netname, hashname, sizeof (hashname), 459*7c478bd9Sstevel@tonic-gate pkeylen, algtype), pkey); 460*7c478bd9Sstevel@tonic-gate } 461*7c478bd9Sstevel@tonic-gate 462*7c478bd9Sstevel@tonic-gate /* 463*7c478bd9Sstevel@tonic-gate * Generic DH (any size keys) version of extract_secret. 464*7c478bd9Sstevel@tonic-gate */ 465*7c478bd9Sstevel@tonic-gate static int 466*7c478bd9Sstevel@tonic-gate extract_secret_g( 467*7c478bd9Sstevel@tonic-gate char *raw, /* in */ 468*7c478bd9Sstevel@tonic-gate char *private, /* out */ 469*7c478bd9Sstevel@tonic-gate int prilen, /* in */ 470*7c478bd9Sstevel@tonic-gate char *passwd, /* in */ 471*7c478bd9Sstevel@tonic-gate char *netname, /* in */ 472*7c478bd9Sstevel@tonic-gate keylen_t keylen, /* in */ 473*7c478bd9Sstevel@tonic-gate algtype_t algtype) /* in */ 474*7c478bd9Sstevel@tonic-gate 475*7c478bd9Sstevel@tonic-gate { 476*7c478bd9Sstevel@tonic-gate char *buf = malloc(strlen(raw) + 1); /* private tmp buf */ 477*7c478bd9Sstevel@tonic-gate char *p; 478*7c478bd9Sstevel@tonic-gate 479*7c478bd9Sstevel@tonic-gate trace1(TR_extract_secret_g, 0); 480*7c478bd9Sstevel@tonic-gate if (! buf || ! passwd || ! raw || ! private || ! prilen || 481*7c478bd9Sstevel@tonic-gate ! VALID_KEYALG(keylen, algtype)) { 482*7c478bd9Sstevel@tonic-gate if (private) 483*7c478bd9Sstevel@tonic-gate *private = NUL; 484*7c478bd9Sstevel@tonic-gate if (buf) 485*7c478bd9Sstevel@tonic-gate free(buf); 486*7c478bd9Sstevel@tonic-gate trace1(TR_extract_secret_g, 1); 487*7c478bd9Sstevel@tonic-gate return (0); 488*7c478bd9Sstevel@tonic-gate } 489*7c478bd9Sstevel@tonic-gate 490*7c478bd9Sstevel@tonic-gate (void) strcpy(buf, raw); 491*7c478bd9Sstevel@tonic-gate 492*7c478bd9Sstevel@tonic-gate /* strip off pesky colon if it exists */ 493*7c478bd9Sstevel@tonic-gate p = strchr(buf, ':'); 494*7c478bd9Sstevel@tonic-gate if (p) { 495*7c478bd9Sstevel@tonic-gate *p = 0; 496*7c478bd9Sstevel@tonic-gate } 497*7c478bd9Sstevel@tonic-gate 498*7c478bd9Sstevel@tonic-gate /* raw buf has chksum appended, so let's verify it too */ 499*7c478bd9Sstevel@tonic-gate if (! xdecrypt_g(buf, keylen, algtype, passwd, netname, TRUE)) { 500*7c478bd9Sstevel@tonic-gate private[0] = 0; 501*7c478bd9Sstevel@tonic-gate free(buf); 502*7c478bd9Sstevel@tonic-gate trace1(TR_extract_secret_g, 1); 503*7c478bd9Sstevel@tonic-gate return (1); /* yes, return 1 even if xdecrypt fails */ 504*7c478bd9Sstevel@tonic-gate } 505*7c478bd9Sstevel@tonic-gate 506*7c478bd9Sstevel@tonic-gate if (strlen(buf) >= prilen) { 507*7c478bd9Sstevel@tonic-gate private[0] = 0; 508*7c478bd9Sstevel@tonic-gate free(buf); 509*7c478bd9Sstevel@tonic-gate trace1(TR_extract_secret_g, 1); 510*7c478bd9Sstevel@tonic-gate return (0); 511*7c478bd9Sstevel@tonic-gate } 512*7c478bd9Sstevel@tonic-gate 513*7c478bd9Sstevel@tonic-gate (void) strcpy(private, buf); 514*7c478bd9Sstevel@tonic-gate free(buf); 515*7c478bd9Sstevel@tonic-gate trace1(TR_extract_secret_g, 1); 516*7c478bd9Sstevel@tonic-gate return (1); 517*7c478bd9Sstevel@tonic-gate } 518*7c478bd9Sstevel@tonic-gate 519*7c478bd9Sstevel@tonic-gate /* 520*7c478bd9Sstevel@tonic-gate * extract_secret() 521*7c478bd9Sstevel@tonic-gate * 522*7c478bd9Sstevel@tonic-gate * This generic function will extract the private key 523*7c478bd9Sstevel@tonic-gate * from a string using the given password. Note that 524*7c478bd9Sstevel@tonic-gate * it uses the DES based function xdecrypt() 525*7c478bd9Sstevel@tonic-gate */ 526*7c478bd9Sstevel@tonic-gate static int 527*7c478bd9Sstevel@tonic-gate extract_secret(raw, private, passwd) 528*7c478bd9Sstevel@tonic-gate char *raw; 529*7c478bd9Sstevel@tonic-gate char *private; 530*7c478bd9Sstevel@tonic-gate char *passwd; 531*7c478bd9Sstevel@tonic-gate { 532*7c478bd9Sstevel@tonic-gate return (extract_secret_g(raw, private, HEXKEYBYTES+1, passwd, 533*7c478bd9Sstevel@tonic-gate NULL, KEYSIZE, 0)); 534*7c478bd9Sstevel@tonic-gate } 535*7c478bd9Sstevel@tonic-gate 536*7c478bd9Sstevel@tonic-gate /* 537*7c478bd9Sstevel@tonic-gate * getkeys_nisplus_g() 538*7c478bd9Sstevel@tonic-gate * 539*7c478bd9Sstevel@tonic-gate * Fetches the key pair from NIS+. This version handles any size 540*7c478bd9Sstevel@tonic-gate * DH keys. 541*7c478bd9Sstevel@tonic-gate */ 542*7c478bd9Sstevel@tonic-gate static int 543*7c478bd9Sstevel@tonic-gate getkeys_nisplus_g( 544*7c478bd9Sstevel@tonic-gate int *err, /* in */ 545*7c478bd9Sstevel@tonic-gate char *netname, /* in */ 546*7c478bd9Sstevel@tonic-gate char *pkey, /* out */ 547*7c478bd9Sstevel@tonic-gate int pkeylen, /* in */ 548*7c478bd9Sstevel@tonic-gate char *skey, /* out */ 549*7c478bd9Sstevel@tonic-gate int skeylen, /* in */ 550*7c478bd9Sstevel@tonic-gate char *passwd, /* in */ 551*7c478bd9Sstevel@tonic-gate keylen_t keylen, /* in */ 552*7c478bd9Sstevel@tonic-gate algtype_t algtype, /* in */ 553*7c478bd9Sstevel@tonic-gate int *retry_cache) /* in/out */ 554*7c478bd9Sstevel@tonic-gate { 555*7c478bd9Sstevel@tonic-gate nis_result *res; 556*7c478bd9Sstevel@tonic-gate int r = 0; 557*7c478bd9Sstevel@tonic-gate char *domain, *p; 558*7c478bd9Sstevel@tonic-gate char buf[NIS_MAXNAMELEN+1]; 559*7c478bd9Sstevel@tonic-gate char keytypename[NIS_MAXNAMELEN+1]; 560*7c478bd9Sstevel@tonic-gate int len; 561*7c478bd9Sstevel@tonic-gate const bool_t classic_des = AUTH_DES_KEY(keylen, algtype); 562*7c478bd9Sstevel@tonic-gate 563*7c478bd9Sstevel@tonic-gate trace1(TR_getkeys_nisplus_g, 0); 564*7c478bd9Sstevel@tonic-gate 565*7c478bd9Sstevel@tonic-gate domain = strchr(netname, '@'); 566*7c478bd9Sstevel@tonic-gate if (! domain) { 567*7c478bd9Sstevel@tonic-gate *err = __NSW_UNAVAIL; 568*7c478bd9Sstevel@tonic-gate trace1(TR_getkeys_nisplus_g, 1); 569*7c478bd9Sstevel@tonic-gate return (0); 570*7c478bd9Sstevel@tonic-gate } 571*7c478bd9Sstevel@tonic-gate domain++; 572*7c478bd9Sstevel@tonic-gate 573*7c478bd9Sstevel@tonic-gate if (retry_cache != NULL && *retry_cache == 1) { 574*7c478bd9Sstevel@tonic-gate nis_error bcerr; 575*7c478bd9Sstevel@tonic-gate directory_obj obj; 576*7c478bd9Sstevel@tonic-gate char hashname[MAXNETNAMELEN]; 577*7c478bd9Sstevel@tonic-gate 578*7c478bd9Sstevel@tonic-gate bcerr = __nis_CacheBind(domain, &obj); 579*7c478bd9Sstevel@tonic-gate xdr_free(xdr_directory_obj, (char *)&obj); 580*7c478bd9Sstevel@tonic-gate /* 581*7c478bd9Sstevel@tonic-gate * Even if the __nis_CacheBind failed, we may have reached 582*7c478bd9Sstevel@tonic-gate * part-way to the goal, so have another look in the public 583*7c478bd9Sstevel@tonic-gate * key cache. 584*7c478bd9Sstevel@tonic-gate */ 585*7c478bd9Sstevel@tonic-gate if (pkey_cache_get(netname2hashname(netname, hashname, 586*7c478bd9Sstevel@tonic-gate MAXNETNAMELEN, pkeylen, 587*7c478bd9Sstevel@tonic-gate algtype), pkey)) { 588*7c478bd9Sstevel@tonic-gate *err = __NSW_SUCCESS; 589*7c478bd9Sstevel@tonic-gate trace1(TR_getkeys_nisplus_g, 1); 590*7c478bd9Sstevel@tonic-gate return (1); 591*7c478bd9Sstevel@tonic-gate } 592*7c478bd9Sstevel@tonic-gate *retry_cache = 0; 593*7c478bd9Sstevel@tonic-gate } 594*7c478bd9Sstevel@tonic-gate 595*7c478bd9Sstevel@tonic-gate if ((strlen(netname)+PKTABLE_LEN+strlen(domain)+32) > 596*7c478bd9Sstevel@tonic-gate (size_t)NIS_MAXNAMELEN) { 597*7c478bd9Sstevel@tonic-gate *err = __NSW_UNAVAIL; 598*7c478bd9Sstevel@tonic-gate trace1(TR_getkeys_nisplus_g, 1); 599*7c478bd9Sstevel@tonic-gate return (0); 600*7c478bd9Sstevel@tonic-gate } 601*7c478bd9Sstevel@tonic-gate 602*7c478bd9Sstevel@tonic-gate /* 603*7c478bd9Sstevel@tonic-gate * Cred table has following format for PK crypto entries: 604*7c478bd9Sstevel@tonic-gate * cname auth_type auth_name public private 605*7c478bd9Sstevel@tonic-gate * ---------------------------------------------------------- 606*7c478bd9Sstevel@tonic-gate * nisname AT netname pubkey prikey 607*7c478bd9Sstevel@tonic-gate * 608*7c478bd9Sstevel@tonic-gate * where AT can be "DES" for classic AUTH_DES, or something like 609*7c478bd9Sstevel@tonic-gate * "DH640-0" for a longer Diffie-Hellman key pair. 610*7c478bd9Sstevel@tonic-gate */ 611*7c478bd9Sstevel@tonic-gate if (classic_des) 612*7c478bd9Sstevel@tonic-gate (void) strcpy(keytypename, des_caps_str); 613*7c478bd9Sstevel@tonic-gate else 614*7c478bd9Sstevel@tonic-gate (void) sprintf(keytypename, "%s%d-%d", 615*7c478bd9Sstevel@tonic-gate dh_caps_str, keylen, algtype); 616*7c478bd9Sstevel@tonic-gate (void) sprintf(buf, "[auth_name=\"%s\",auth_type=%s],%s.%s", 617*7c478bd9Sstevel@tonic-gate netname, keytypename, PKTABLE, domain); 618*7c478bd9Sstevel@tonic-gate if (buf[strlen(buf)-1] != '.') 619*7c478bd9Sstevel@tonic-gate (void) strcat(buf, "."); 620*7c478bd9Sstevel@tonic-gate 621*7c478bd9Sstevel@tonic-gate /* 622*7c478bd9Sstevel@tonic-gate * Because of some bootstrapping issues (keylogin, etc) the 623*7c478bd9Sstevel@tonic-gate * keys lookup needs to be done without auth. This is 624*7c478bd9Sstevel@tonic-gate * less-then-ideal from a security perspective and hopefully 625*7c478bd9Sstevel@tonic-gate * will be revisited soon... 626*7c478bd9Sstevel@tonic-gate */ 627*7c478bd9Sstevel@tonic-gate res = nis_list(buf, USE_DGRAM+NO_AUTHINFO+FOLLOW_LINKS+FOLLOW_PATH, 628*7c478bd9Sstevel@tonic-gate NULL, NULL); 629*7c478bd9Sstevel@tonic-gate switch (res->status) { 630*7c478bd9Sstevel@tonic-gate case NIS_SUCCESS: 631*7c478bd9Sstevel@tonic-gate case NIS_S_SUCCESS: 632*7c478bd9Sstevel@tonic-gate break; 633*7c478bd9Sstevel@tonic-gate case NIS_NOTFOUND: 634*7c478bd9Sstevel@tonic-gate case NIS_PARTIAL: 635*7c478bd9Sstevel@tonic-gate case NIS_NOSUCHNAME: 636*7c478bd9Sstevel@tonic-gate case NIS_NOSUCHTABLE: 637*7c478bd9Sstevel@tonic-gate nis_freeresult(res); 638*7c478bd9Sstevel@tonic-gate *err = __NSW_NOTFOUND; 639*7c478bd9Sstevel@tonic-gate trace1(TR_getkeys_nisplus_g, 1); 640*7c478bd9Sstevel@tonic-gate return (0); 641*7c478bd9Sstevel@tonic-gate case NIS_S_NOTFOUND: 642*7c478bd9Sstevel@tonic-gate case NIS_TRYAGAIN: 643*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, "getkeys: (nis+ key lookup): %s\n", 644*7c478bd9Sstevel@tonic-gate nis_sperrno(res->status)); 645*7c478bd9Sstevel@tonic-gate nis_freeresult(res); 646*7c478bd9Sstevel@tonic-gate *err = __NSW_TRYAGAIN; 647*7c478bd9Sstevel@tonic-gate trace1(TR_getkeys_nisplus_g, 1); 648*7c478bd9Sstevel@tonic-gate return (0); 649*7c478bd9Sstevel@tonic-gate default: 650*7c478bd9Sstevel@tonic-gate *err = __NSW_UNAVAIL; 651*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 652*7c478bd9Sstevel@tonic-gate "getkeys: (nis+ key lookup): %s\n", 653*7c478bd9Sstevel@tonic-gate nis_sperrno(res->status)); 654*7c478bd9Sstevel@tonic-gate nis_freeresult(res); 655*7c478bd9Sstevel@tonic-gate trace1(TR_getkeys_nisplus_g, 1); 656*7c478bd9Sstevel@tonic-gate return (0); 657*7c478bd9Sstevel@tonic-gate } 658*7c478bd9Sstevel@tonic-gate 659*7c478bd9Sstevel@tonic-gate if (pkey) { 660*7c478bd9Sstevel@tonic-gate char *key_start; 661*7c478bd9Sstevel@tonic-gate char *colon_pos; 662*7c478bd9Sstevel@tonic-gate 663*7c478bd9Sstevel@tonic-gate /* 664*7c478bd9Sstevel@tonic-gate * For backward compatibility with the old 665*7c478bd9Sstevel@tonic-gate * cred.org_dir format, first locate the ":", if any, 666*7c478bd9Sstevel@tonic-gate * and prepare to null it out. 667*7c478bd9Sstevel@tonic-gate */ 668*7c478bd9Sstevel@tonic-gate key_start = (char *)ENTRY_VAL(res->objects.objects_val, 3); 669*7c478bd9Sstevel@tonic-gate colon_pos = strchr(key_start, ':'); 670*7c478bd9Sstevel@tonic-gate 671*7c478bd9Sstevel@tonic-gate /* 672*7c478bd9Sstevel@tonic-gate * Set the value of len keeping in mind that both len 673*7c478bd9Sstevel@tonic-gate * and pklen include space for the terminating null. 674*7c478bd9Sstevel@tonic-gate */ 675*7c478bd9Sstevel@tonic-gate 676*7c478bd9Sstevel@tonic-gate if (colon_pos != NULL) 677*7c478bd9Sstevel@tonic-gate /* 678*7c478bd9Sstevel@tonic-gate * Set len to include the colon because that is 679*7c478bd9Sstevel@tonic-gate * where the terminating null will be 680*7c478bd9Sstevel@tonic-gate * placed. 681*7c478bd9Sstevel@tonic-gate */ 682*7c478bd9Sstevel@tonic-gate len = (int)((uintptr_t)colon_pos - 683*7c478bd9Sstevel@tonic-gate (uintptr_t)key_start + 1); 684*7c478bd9Sstevel@tonic-gate else 685*7c478bd9Sstevel@tonic-gate /* 686*7c478bd9Sstevel@tonic-gate * ENTRY_LEN already includes the terminating 687*7c478bd9Sstevel@tonic-gate * null. 688*7c478bd9Sstevel@tonic-gate */ 689*7c478bd9Sstevel@tonic-gate len = ENTRY_LEN(res->objects.objects_val, 3); 690*7c478bd9Sstevel@tonic-gate 691*7c478bd9Sstevel@tonic-gate if (len > pkeylen) { 692*7c478bd9Sstevel@tonic-gate *err = __NSW_UNAVAIL; 693*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 694*7c478bd9Sstevel@tonic-gate "getkeys(nis+): pub key for '%s' (keytype = '%s') too long", 695*7c478bd9Sstevel@tonic-gate netname, keytypename); 696*7c478bd9Sstevel@tonic-gate nis_freeresult(res); 697*7c478bd9Sstevel@tonic-gate return (0); 698*7c478bd9Sstevel@tonic-gate } 699*7c478bd9Sstevel@tonic-gate 700*7c478bd9Sstevel@tonic-gate (void) strncpy(pkey, key_start, len); 701*7c478bd9Sstevel@tonic-gate 702*7c478bd9Sstevel@tonic-gate /* 703*7c478bd9Sstevel@tonic-gate * Now null out the colon if it exists 704*7c478bd9Sstevel@tonic-gate */ 705*7c478bd9Sstevel@tonic-gate if (colon_pos != NULL) 706*7c478bd9Sstevel@tonic-gate pkey[len-1] = NULL; 707*7c478bd9Sstevel@tonic-gate 708*7c478bd9Sstevel@tonic-gate } 709*7c478bd9Sstevel@tonic-gate r = 1; /* At least public key was found; always true at this point */ 710*7c478bd9Sstevel@tonic-gate 711*7c478bd9Sstevel@tonic-gate if (skey && extract_secret_g(ENTRY_VAL(res->objects.objects_val, 4), 712*7c478bd9Sstevel@tonic-gate skey, skeylen, passwd, netname, keylen, 713*7c478bd9Sstevel@tonic-gate algtype)) 714*7c478bd9Sstevel@tonic-gate r |= 2; 715*7c478bd9Sstevel@tonic-gate 716*7c478bd9Sstevel@tonic-gate nis_freeresult(res); 717*7c478bd9Sstevel@tonic-gate *err = __NSW_SUCCESS; 718*7c478bd9Sstevel@tonic-gate trace1(TR_getkeys_nisplus_g, 1); 719*7c478bd9Sstevel@tonic-gate return (r); 720*7c478bd9Sstevel@tonic-gate } 721*7c478bd9Sstevel@tonic-gate 722*7c478bd9Sstevel@tonic-gate 723*7c478bd9Sstevel@tonic-gate /* 724*7c478bd9Sstevel@tonic-gate * getkeys_ldap_g() 725*7c478bd9Sstevel@tonic-gate * 726*7c478bd9Sstevel@tonic-gate * Fetches the key pair from LDAP. This version handles any size 727*7c478bd9Sstevel@tonic-gate * DH keys. 728*7c478bd9Sstevel@tonic-gate */ 729*7c478bd9Sstevel@tonic-gate 730*7c478bd9Sstevel@tonic-gate void 731*7c478bd9Sstevel@tonic-gate _nss_initf_publickey(nss_db_params_t *p) 732*7c478bd9Sstevel@tonic-gate { 733*7c478bd9Sstevel@tonic-gate p->name = NSS_DBNAM_PUBLICKEY; 734*7c478bd9Sstevel@tonic-gate p->default_config = NSS_DEFCONF_PUBLICKEY; 735*7c478bd9Sstevel@tonic-gate } 736*7c478bd9Sstevel@tonic-gate 737*7c478bd9Sstevel@tonic-gate 738*7c478bd9Sstevel@tonic-gate static int 739*7c478bd9Sstevel@tonic-gate getkeys_ldap_g( 740*7c478bd9Sstevel@tonic-gate int *err, /* in */ 741*7c478bd9Sstevel@tonic-gate char *netname, /* in */ 742*7c478bd9Sstevel@tonic-gate char *pkey, /* out */ 743*7c478bd9Sstevel@tonic-gate int pkeylen, /* in */ 744*7c478bd9Sstevel@tonic-gate char *skey, /* out */ 745*7c478bd9Sstevel@tonic-gate int skeylen, /* in */ 746*7c478bd9Sstevel@tonic-gate char *passwd, /* in */ 747*7c478bd9Sstevel@tonic-gate keylen_t keylen, /* in */ 748*7c478bd9Sstevel@tonic-gate algtype_t algtype) /* in */ 749*7c478bd9Sstevel@tonic-gate { 750*7c478bd9Sstevel@tonic-gate int r = 0; 751*7c478bd9Sstevel@tonic-gate char *p; 752*7c478bd9Sstevel@tonic-gate char keytypename[NIS_MAXNAMELEN+1]; 753*7c478bd9Sstevel@tonic-gate int len; 754*7c478bd9Sstevel@tonic-gate const bool_t classic_des = AUTH_DES_KEY(keylen, algtype); 755*7c478bd9Sstevel@tonic-gate int rc = 0; 756*7c478bd9Sstevel@tonic-gate nss_XbyY_args_t arg; 757*7c478bd9Sstevel@tonic-gate nss_XbyY_buf_t *buf = NULL; 758*7c478bd9Sstevel@tonic-gate char *keyval; 759*7c478bd9Sstevel@tonic-gate 760*7c478bd9Sstevel@tonic-gate trace1(TR_getkeys_ldap_g, 0); 761*7c478bd9Sstevel@tonic-gate NSS_XbyY_ALLOC(&buf, 0, NSS_BUFLEN_PUBLICKEY); 762*7c478bd9Sstevel@tonic-gate 763*7c478bd9Sstevel@tonic-gate NSS_XbyY_INIT(&arg, buf->result, buf->buffer, buf->buflen, NULL); 764*7c478bd9Sstevel@tonic-gate arg.key.pkey.name = netname; 765*7c478bd9Sstevel@tonic-gate 766*7c478bd9Sstevel@tonic-gate /* 767*7c478bd9Sstevel@tonic-gate * LDAP stores the public and secret key info in entries using 768*7c478bd9Sstevel@tonic-gate * nisKeyObject objectclass. Each key is tagged with the 769*7c478bd9Sstevel@tonic-gate * keytype, keylength, and algorithm. The tag has the following 770*7c478bd9Sstevel@tonic-gate * format: {<keytype><keylength>-<algorithm>}. For example, 771*7c478bd9Sstevel@tonic-gate * {DH192-0}. 772*7c478bd9Sstevel@tonic-gate */ 773*7c478bd9Sstevel@tonic-gate if (classic_des) 774*7c478bd9Sstevel@tonic-gate (void) strcpy(keytypename, "{DH192-0}"); 775*7c478bd9Sstevel@tonic-gate else 776*7c478bd9Sstevel@tonic-gate (void) sprintf(keytypename, "{%s%d-%d}", 777*7c478bd9Sstevel@tonic-gate dh_caps_str, keylen, algtype); 778*7c478bd9Sstevel@tonic-gate arg.key.pkey.keytype = keytypename; 779*7c478bd9Sstevel@tonic-gate 780*7c478bd9Sstevel@tonic-gate if (nss_search(&db_root, _nss_initf_publickey, NSS_DBOP_KEYS_BYNAME, 781*7c478bd9Sstevel@tonic-gate &arg) != NSS_SUCCESS) { 782*7c478bd9Sstevel@tonic-gate NSS_XbyY_FREE(&buf); 783*7c478bd9Sstevel@tonic-gate *err = __NSW_NOTFOUND; 784*7c478bd9Sstevel@tonic-gate trace1(TR_getkeys_ldap_g, 1); 785*7c478bd9Sstevel@tonic-gate return (0); 786*7c478bd9Sstevel@tonic-gate } 787*7c478bd9Sstevel@tonic-gate keyval = buf->buffer; 788*7c478bd9Sstevel@tonic-gate p = strchr(keyval, ':'); 789*7c478bd9Sstevel@tonic-gate if (p == NULL) { 790*7c478bd9Sstevel@tonic-gate NSS_XbyY_FREE(&buf); 791*7c478bd9Sstevel@tonic-gate *err = __NSW_NOTFOUND; 792*7c478bd9Sstevel@tonic-gate trace1(TR_getkeys_ldap_g, 1); 793*7c478bd9Sstevel@tonic-gate return (0); 794*7c478bd9Sstevel@tonic-gate } 795*7c478bd9Sstevel@tonic-gate *p = 0; 796*7c478bd9Sstevel@tonic-gate if (pkey) { 797*7c478bd9Sstevel@tonic-gate len = strlen(keyval); 798*7c478bd9Sstevel@tonic-gate if (len > HEXKEYBYTES) { 799*7c478bd9Sstevel@tonic-gate NSS_XbyY_FREE(&buf); 800*7c478bd9Sstevel@tonic-gate *err = __NSW_NOTFOUND; 801*7c478bd9Sstevel@tonic-gate trace1(TR_getkeys_ldap_g, 1); 802*7c478bd9Sstevel@tonic-gate return (0); 803*7c478bd9Sstevel@tonic-gate } 804*7c478bd9Sstevel@tonic-gate (void) strcpy(pkey, keyval); 805*7c478bd9Sstevel@tonic-gate } 806*7c478bd9Sstevel@tonic-gate r = 1; 807*7c478bd9Sstevel@tonic-gate p++; 808*7c478bd9Sstevel@tonic-gate if (skey && extract_secret(p, skey, passwd)) 809*7c478bd9Sstevel@tonic-gate r |= 2; 810*7c478bd9Sstevel@tonic-gate NSS_XbyY_FREE(&buf); 811*7c478bd9Sstevel@tonic-gate *err = __NSW_SUCCESS; 812*7c478bd9Sstevel@tonic-gate trace1(TR_getkeys_ldap_g, 1); 813*7c478bd9Sstevel@tonic-gate return (r); 814*7c478bd9Sstevel@tonic-gate } 815*7c478bd9Sstevel@tonic-gate 816*7c478bd9Sstevel@tonic-gate 817*7c478bd9Sstevel@tonic-gate /* 818*7c478bd9Sstevel@tonic-gate * Convert a netname to a name we will hash on. For classic_des, 819*7c478bd9Sstevel@tonic-gate * just copy netname as is. But for new and improved ("now in 820*7c478bd9Sstevel@tonic-gate * new longer sizes!") DHEXT, add a ":keylen-algtype" suffix to hash on. 821*7c478bd9Sstevel@tonic-gate * 822*7c478bd9Sstevel@tonic-gate * Returns the hashname string on success or NULL on failure. 823*7c478bd9Sstevel@tonic-gate */ 824*7c478bd9Sstevel@tonic-gate static char * 825*7c478bd9Sstevel@tonic-gate netname2hashname( 826*7c478bd9Sstevel@tonic-gate const char *netname, 827*7c478bd9Sstevel@tonic-gate char *hashname, 828*7c478bd9Sstevel@tonic-gate int bufsiz, 829*7c478bd9Sstevel@tonic-gate keylen_t keylen, 830*7c478bd9Sstevel@tonic-gate algtype_t algtype) 831*7c478bd9Sstevel@tonic-gate { 832*7c478bd9Sstevel@tonic-gate const bool_t classic_des = AUTH_DES_KEY(keylen, algtype); 833*7c478bd9Sstevel@tonic-gate 834*7c478bd9Sstevel@tonic-gate trace3(TR_netname2hashname, 0, keylen, algtype); 835*7c478bd9Sstevel@tonic-gate if (! netname || ! hashname || ! bufsiz) { 836*7c478bd9Sstevel@tonic-gate trace1(TR_netname2hashname, 1); 837*7c478bd9Sstevel@tonic-gate return (NULL); 838*7c478bd9Sstevel@tonic-gate } 839*7c478bd9Sstevel@tonic-gate 840*7c478bd9Sstevel@tonic-gate if (classic_des) { 841*7c478bd9Sstevel@tonic-gate if (bufsiz > strlen(netname)) 842*7c478bd9Sstevel@tonic-gate (void) strcpy(hashname, netname); 843*7c478bd9Sstevel@tonic-gate else { 844*7c478bd9Sstevel@tonic-gate trace1(TR_netname2hashname, 1); 845*7c478bd9Sstevel@tonic-gate return (NULL); 846*7c478bd9Sstevel@tonic-gate } 847*7c478bd9Sstevel@tonic-gate } else { 848*7c478bd9Sstevel@tonic-gate char tmp[128]; 849*7c478bd9Sstevel@tonic-gate (void) sprintf(tmp, ":%d-%d", keylen, algtype); 850*7c478bd9Sstevel@tonic-gate if (bufsiz > (strlen(netname) + strlen(tmp))) 851*7c478bd9Sstevel@tonic-gate (void) sprintf(hashname, "%s%s", netname, tmp); 852*7c478bd9Sstevel@tonic-gate else { 853*7c478bd9Sstevel@tonic-gate trace1(TR_netname2hashname, 1); 854*7c478bd9Sstevel@tonic-gate return (NULL); 855*7c478bd9Sstevel@tonic-gate } 856*7c478bd9Sstevel@tonic-gate } 857*7c478bd9Sstevel@tonic-gate 858*7c478bd9Sstevel@tonic-gate trace1(TR_netname2hashname, 1); 859*7c478bd9Sstevel@tonic-gate return (hashname); 860*7c478bd9Sstevel@tonic-gate } 861*7c478bd9Sstevel@tonic-gate 862*7c478bd9Sstevel@tonic-gate /* 863*7c478bd9Sstevel@tonic-gate * Flush netname's publickey of the given key length and algorithm type. 864*7c478bd9Sstevel@tonic-gate */ 865*7c478bd9Sstevel@tonic-gate void 866*7c478bd9Sstevel@tonic-gate __getpublickey_flush_g(const char *netname, keylen_t keylen, algtype_t algtype) 867*7c478bd9Sstevel@tonic-gate { 868*7c478bd9Sstevel@tonic-gate char *p, hashname[MAXNETNAMELEN+1]; 869*7c478bd9Sstevel@tonic-gate 870*7c478bd9Sstevel@tonic-gate p = netname2hashname(netname, hashname, MAXNETNAMELEN, keylen, algtype); 871*7c478bd9Sstevel@tonic-gate if (p) 872*7c478bd9Sstevel@tonic-gate pkey_cache_flush(hashname); 873*7c478bd9Sstevel@tonic-gate } 874*7c478bd9Sstevel@tonic-gate 875*7c478bd9Sstevel@tonic-gate 876*7c478bd9Sstevel@tonic-gate /* 877*7c478bd9Sstevel@tonic-gate * Generic DH (any size keys) version of __getpublickey_cached. 878*7c478bd9Sstevel@tonic-gate */ 879*7c478bd9Sstevel@tonic-gate int 880*7c478bd9Sstevel@tonic-gate __getpublickey_cached_g(const char netname[], /* in */ 881*7c478bd9Sstevel@tonic-gate keylen_t keylen, /* in */ 882*7c478bd9Sstevel@tonic-gate algtype_t algtype, /* in */ 883*7c478bd9Sstevel@tonic-gate char *pkey, /* out */ 884*7c478bd9Sstevel@tonic-gate size_t pkeylen, /* in */ 885*7c478bd9Sstevel@tonic-gate int *from_cache) /* in/out */ 886*7c478bd9Sstevel@tonic-gate { 887*7c478bd9Sstevel@tonic-gate int needfree = 1, res, err; 888*7c478bd9Sstevel@tonic-gate struct __nsw_switchconfig *conf; 889*7c478bd9Sstevel@tonic-gate struct __nsw_lookup *look; 890*7c478bd9Sstevel@tonic-gate enum __nsw_parse_err perr; 891*7c478bd9Sstevel@tonic-gate const bool_t classic_des = AUTH_DES_KEY(keylen, algtype); 892*7c478bd9Sstevel@tonic-gate int retry_cache = 0; 893*7c478bd9Sstevel@tonic-gate 894*7c478bd9Sstevel@tonic-gate trace1(TR_getpublickey_cached_g, 0); 895*7c478bd9Sstevel@tonic-gate if (! netname || ! pkey) { 896*7c478bd9Sstevel@tonic-gate trace1(TR_getpublickey_cached_g, 1); 897*7c478bd9Sstevel@tonic-gate return (0); 898*7c478bd9Sstevel@tonic-gate } 899*7c478bd9Sstevel@tonic-gate 900*7c478bd9Sstevel@tonic-gate 901*7c478bd9Sstevel@tonic-gate if (from_cache) { 902*7c478bd9Sstevel@tonic-gate char hashname[MAXNETNAMELEN]; 903*7c478bd9Sstevel@tonic-gate if (pkey_cache_get(netname2hashname(netname, hashname, 904*7c478bd9Sstevel@tonic-gate MAXNETNAMELEN, keylen, 905*7c478bd9Sstevel@tonic-gate algtype), pkey)) { 906*7c478bd9Sstevel@tonic-gate *from_cache = 1; 907*7c478bd9Sstevel@tonic-gate trace1(TR_getpublickey_cached_g, 1); 908*7c478bd9Sstevel@tonic-gate return (1); 909*7c478bd9Sstevel@tonic-gate } 910*7c478bd9Sstevel@tonic-gate *from_cache = 0; 911*7c478bd9Sstevel@tonic-gate retry_cache = 1; 912*7c478bd9Sstevel@tonic-gate } 913*7c478bd9Sstevel@tonic-gate 914*7c478bd9Sstevel@tonic-gate conf = __nsw_getconfig("publickey", &perr); 915*7c478bd9Sstevel@tonic-gate if (! conf) { 916*7c478bd9Sstevel@tonic-gate conf = &publickey_default; 917*7c478bd9Sstevel@tonic-gate needfree = 0; 918*7c478bd9Sstevel@tonic-gate } 919*7c478bd9Sstevel@tonic-gate for (look = conf->lookups; look; look = look->next) { 920*7c478bd9Sstevel@tonic-gate if (strcmp(look->service_name, "nisplus") == 0) { 921*7c478bd9Sstevel@tonic-gate res = getkeys_nisplus_g(&err, (char *)netname, 922*7c478bd9Sstevel@tonic-gate pkey, pkeylen, 923*7c478bd9Sstevel@tonic-gate (char *)NULL, 0, 924*7c478bd9Sstevel@tonic-gate (char *)NULL, 925*7c478bd9Sstevel@tonic-gate keylen, algtype, &retry_cache); 926*7c478bd9Sstevel@tonic-gate if (retry_cache) 927*7c478bd9Sstevel@tonic-gate *from_cache = 1; 928*7c478bd9Sstevel@tonic-gate } else if (strcmp(look->service_name, "ldap") == 0) { 929*7c478bd9Sstevel@tonic-gate res = getkeys_ldap_g(&err, (char *)netname, 930*7c478bd9Sstevel@tonic-gate pkey, pkeylen, 931*7c478bd9Sstevel@tonic-gate (char *)NULL, 0, 932*7c478bd9Sstevel@tonic-gate (char *)NULL, 933*7c478bd9Sstevel@tonic-gate keylen, algtype); 934*7c478bd9Sstevel@tonic-gate /* long DH keys will not be in nis or files */ 935*7c478bd9Sstevel@tonic-gate } else if (classic_des && 936*7c478bd9Sstevel@tonic-gate strcmp(look->service_name, "nis") == 0) 937*7c478bd9Sstevel@tonic-gate res = getkeys_nis(&err, (char *)netname, pkey, 938*7c478bd9Sstevel@tonic-gate (char *)NULL, (char *)NULL); 939*7c478bd9Sstevel@tonic-gate else if (classic_des && 940*7c478bd9Sstevel@tonic-gate strcmp(look->service_name, "files") == 0) 941*7c478bd9Sstevel@tonic-gate res = getkeys_files(&err, (char *)netname, pkey, 942*7c478bd9Sstevel@tonic-gate (char *)NULL, (char *)NULL); 943*7c478bd9Sstevel@tonic-gate else { 944*7c478bd9Sstevel@tonic-gate syslog(LOG_INFO, "Unknown publickey nameservice '%s'", 945*7c478bd9Sstevel@tonic-gate look->service_name); 946*7c478bd9Sstevel@tonic-gate err = __NSW_UNAVAIL; 947*7c478bd9Sstevel@tonic-gate } 948*7c478bd9Sstevel@tonic-gate 949*7c478bd9Sstevel@tonic-gate /* 950*7c478bd9Sstevel@tonic-gate * If we found the publickey, save it in the cache. 951*7c478bd9Sstevel@tonic-gate * However, if retry_cache == 1, it's already been 952*7c478bd9Sstevel@tonic-gate * added to the cache under our feet. 953*7c478bd9Sstevel@tonic-gate */ 954*7c478bd9Sstevel@tonic-gate if (err == __NSW_SUCCESS && !retry_cache) { 955*7c478bd9Sstevel@tonic-gate char hashname[MAXNETNAMELEN]; 956*7c478bd9Sstevel@tonic-gate pkey_cache_add(netname2hashname(netname, hashname, 957*7c478bd9Sstevel@tonic-gate MAXNETNAMELEN, keylen, 958*7c478bd9Sstevel@tonic-gate algtype), pkey); 959*7c478bd9Sstevel@tonic-gate } 960*7c478bd9Sstevel@tonic-gate 961*7c478bd9Sstevel@tonic-gate switch (look->actions[err]) { 962*7c478bd9Sstevel@tonic-gate case __NSW_CONTINUE : 963*7c478bd9Sstevel@tonic-gate continue; 964*7c478bd9Sstevel@tonic-gate case __NSW_RETURN : 965*7c478bd9Sstevel@tonic-gate if (needfree) 966*7c478bd9Sstevel@tonic-gate __nsw_freeconfig(conf); 967*7c478bd9Sstevel@tonic-gate trace1(TR_getpublickey_cached_g, 1); 968*7c478bd9Sstevel@tonic-gate return ((res & 1) != 0); 969*7c478bd9Sstevel@tonic-gate default : 970*7c478bd9Sstevel@tonic-gate syslog(LOG_INFO, "Unknown action for nameservice %s", 971*7c478bd9Sstevel@tonic-gate look->service_name); 972*7c478bd9Sstevel@tonic-gate } 973*7c478bd9Sstevel@tonic-gate } 974*7c478bd9Sstevel@tonic-gate 975*7c478bd9Sstevel@tonic-gate if (needfree) 976*7c478bd9Sstevel@tonic-gate __nsw_freeconfig(conf); 977*7c478bd9Sstevel@tonic-gate trace1(TR_getpublickey_cached_g, 1); 978*7c478bd9Sstevel@tonic-gate return (0); 979*7c478bd9Sstevel@tonic-gate } 980*7c478bd9Sstevel@tonic-gate 981*7c478bd9Sstevel@tonic-gate 982*7c478bd9Sstevel@tonic-gate /* 983*7c478bd9Sstevel@tonic-gate * The public key cache (used by nisd in this case) must be filled with 984*7c478bd9Sstevel@tonic-gate * the data in the NIS_COLD_START file in order for extended Diffie-Hellman 985*7c478bd9Sstevel@tonic-gate * operations to work. 986*7c478bd9Sstevel@tonic-gate */ 987*7c478bd9Sstevel@tonic-gate void 988*7c478bd9Sstevel@tonic-gate prime_pkey_cache(directory_obj *dobj) 989*7c478bd9Sstevel@tonic-gate { 990*7c478bd9Sstevel@tonic-gate int scount; 991*7c478bd9Sstevel@tonic-gate 992*7c478bd9Sstevel@tonic-gate for (scount = 0; scount < dobj->do_servers.do_servers_len; scount++) { 993*7c478bd9Sstevel@tonic-gate nis_server *srv = &(dobj->do_servers.do_servers_val[scount]); 994*7c478bd9Sstevel@tonic-gate extdhkey_t *keylens = NULL; 995*7c478bd9Sstevel@tonic-gate char *pkey = NULL, hashname[MAXNETNAMELEN]; 996*7c478bd9Sstevel@tonic-gate char netname[MAXNETNAMELEN]; 997*7c478bd9Sstevel@tonic-gate int kcount, nkeys = 0; 998*7c478bd9Sstevel@tonic-gate 999*7c478bd9Sstevel@tonic-gate (void) host2netname(netname, srv->name, NULL); 1000*7c478bd9Sstevel@tonic-gate 1001*7c478bd9Sstevel@tonic-gate /* determine the number of keys to process */ 1002*7c478bd9Sstevel@tonic-gate if (!(nkeys = __nis_dhext_extract_keyinfo(srv, &keylens))) 1003*7c478bd9Sstevel@tonic-gate continue; 1004*7c478bd9Sstevel@tonic-gate 1005*7c478bd9Sstevel@tonic-gate /* store them */ 1006*7c478bd9Sstevel@tonic-gate if (srv->key_type == NIS_PK_DHEXT) { 1007*7c478bd9Sstevel@tonic-gate for (kcount = 0; kcount < nkeys; kcount++) { 1008*7c478bd9Sstevel@tonic-gate if (!netname2hashname(netname, hashname, 1009*7c478bd9Sstevel@tonic-gate MAXNETNAMELEN, 1010*7c478bd9Sstevel@tonic-gate keylens[kcount].keylen, 1011*7c478bd9Sstevel@tonic-gate keylens[kcount].algtype)) 1012*7c478bd9Sstevel@tonic-gate continue; 1013*7c478bd9Sstevel@tonic-gate 1014*7c478bd9Sstevel@tonic-gate if (!(pkey = __nis_dhext_extract_pkey( 1015*7c478bd9Sstevel@tonic-gate &srv->pkey, keylens[kcount].keylen, 1016*7c478bd9Sstevel@tonic-gate keylens[kcount].algtype))) 1017*7c478bd9Sstevel@tonic-gate continue; 1018*7c478bd9Sstevel@tonic-gate 1019*7c478bd9Sstevel@tonic-gate if (!pkey_cache_get(hashname, pkey)) 1020*7c478bd9Sstevel@tonic-gate pkey_cache_add(hashname, pkey); 1021*7c478bd9Sstevel@tonic-gate } 1022*7c478bd9Sstevel@tonic-gate } else if (srv->key_type == NIS_PK_DH) { 1023*7c478bd9Sstevel@tonic-gate pkey = srv->pkey.n_bytes; 1024*7c478bd9Sstevel@tonic-gate 1025*7c478bd9Sstevel@tonic-gate if (netname2hashname(netname, hashname, MAXNETNAMELEN, 1026*7c478bd9Sstevel@tonic-gate KEYSIZE, 0) && 1027*7c478bd9Sstevel@tonic-gate !pkey_cache_get(hashname, pkey)) 1028*7c478bd9Sstevel@tonic-gate pkey_cache_add(hashname, pkey); 1029*7c478bd9Sstevel@tonic-gate } 1030*7c478bd9Sstevel@tonic-gate if (keylens != NULL) 1031*7c478bd9Sstevel@tonic-gate free(keylens); 1032*7c478bd9Sstevel@tonic-gate keylens = NULL; 1033*7c478bd9Sstevel@tonic-gate } 1034*7c478bd9Sstevel@tonic-gate } 1035*7c478bd9Sstevel@tonic-gate 1036*7c478bd9Sstevel@tonic-gate /* 1037*7c478bd9Sstevel@tonic-gate * Generic (all sizes) DH version of getpublickey. 1038*7c478bd9Sstevel@tonic-gate */ 1039*7c478bd9Sstevel@tonic-gate int 1040*7c478bd9Sstevel@tonic-gate getpublickey_g( 1041*7c478bd9Sstevel@tonic-gate const char *netname, /* in */ 1042*7c478bd9Sstevel@tonic-gate int keylen, /* in */ 1043*7c478bd9Sstevel@tonic-gate int algtype, /* in */ 1044*7c478bd9Sstevel@tonic-gate char *pkey, /* out */ 1045*7c478bd9Sstevel@tonic-gate size_t pkeylen) /* in */ 1046*7c478bd9Sstevel@tonic-gate { 1047*7c478bd9Sstevel@tonic-gate trace1(TR_getpublickey_g, 0); 1048*7c478bd9Sstevel@tonic-gate return (__getpublickey_cached_g(netname, keylen, algtype, pkey, 1049*7c478bd9Sstevel@tonic-gate pkeylen, (int *)0)); 1050*7c478bd9Sstevel@tonic-gate } 1051*7c478bd9Sstevel@tonic-gate 1052*7c478bd9Sstevel@tonic-gate /* 1053*7c478bd9Sstevel@tonic-gate * Generic (all sizes) DH version of getsecretkey_g. 1054*7c478bd9Sstevel@tonic-gate */ 1055*7c478bd9Sstevel@tonic-gate int 1056*7c478bd9Sstevel@tonic-gate getsecretkey_g( 1057*7c478bd9Sstevel@tonic-gate const char *netname, /* in */ 1058*7c478bd9Sstevel@tonic-gate keylen_t keylen, /* in */ 1059*7c478bd9Sstevel@tonic-gate algtype_t algtype, /* in */ 1060*7c478bd9Sstevel@tonic-gate char *skey, /* out */ 1061*7c478bd9Sstevel@tonic-gate size_t skeylen, /* in */ 1062*7c478bd9Sstevel@tonic-gate const char *passwd) /* in */ 1063*7c478bd9Sstevel@tonic-gate { 1064*7c478bd9Sstevel@tonic-gate int needfree = 1, res, err; 1065*7c478bd9Sstevel@tonic-gate struct __nsw_switchconfig *conf; 1066*7c478bd9Sstevel@tonic-gate struct __nsw_lookup *look; 1067*7c478bd9Sstevel@tonic-gate enum __nsw_parse_err perr; 1068*7c478bd9Sstevel@tonic-gate const bool_t classic_des = AUTH_DES_KEY(keylen, algtype); 1069*7c478bd9Sstevel@tonic-gate 1070*7c478bd9Sstevel@tonic-gate trace1(TR_getsecretkey_g, 0); 1071*7c478bd9Sstevel@tonic-gate if (! netname || !skey || ! skeylen) { 1072*7c478bd9Sstevel@tonic-gate trace1(TR_getsecretkey_g, 1); 1073*7c478bd9Sstevel@tonic-gate return (0); 1074*7c478bd9Sstevel@tonic-gate } 1075*7c478bd9Sstevel@tonic-gate 1076*7c478bd9Sstevel@tonic-gate conf = __nsw_getconfig("publickey", &perr); 1077*7c478bd9Sstevel@tonic-gate 1078*7c478bd9Sstevel@tonic-gate if (! conf) { 1079*7c478bd9Sstevel@tonic-gate conf = &publickey_default; 1080*7c478bd9Sstevel@tonic-gate needfree = 0; 1081*7c478bd9Sstevel@tonic-gate } 1082*7c478bd9Sstevel@tonic-gate 1083*7c478bd9Sstevel@tonic-gate for (look = conf->lookups; look; look = look->next) { 1084*7c478bd9Sstevel@tonic-gate if (strcmp(look->service_name, "nisplus") == 0) 1085*7c478bd9Sstevel@tonic-gate res = getkeys_nisplus_g(&err, (char *)netname, 1086*7c478bd9Sstevel@tonic-gate (char *)NULL, 0, skey, skeylen, 1087*7c478bd9Sstevel@tonic-gate (char *)passwd, keylen, algtype, 0); 1088*7c478bd9Sstevel@tonic-gate else if (strcmp(look->service_name, "ldap") == 0) 1089*7c478bd9Sstevel@tonic-gate res = getkeys_ldap_g(&err, (char *)netname, 1090*7c478bd9Sstevel@tonic-gate (char *)NULL, 0, skey, skeylen, 1091*7c478bd9Sstevel@tonic-gate (char *)passwd, keylen, algtype); 1092*7c478bd9Sstevel@tonic-gate /* long DH keys will not be in nis or files */ 1093*7c478bd9Sstevel@tonic-gate else if (classic_des && strcmp(look->service_name, "nis") == 0) 1094*7c478bd9Sstevel@tonic-gate res = getkeys_nis(&err, (char *)netname, 1095*7c478bd9Sstevel@tonic-gate (char *)NULL, skey, (char *)passwd); 1096*7c478bd9Sstevel@tonic-gate else if (classic_des && 1097*7c478bd9Sstevel@tonic-gate strcmp(look->service_name, "files") == 0) 1098*7c478bd9Sstevel@tonic-gate res = getkeys_files(&err, (char *)netname, 1099*7c478bd9Sstevel@tonic-gate (char *)NULL, skey, (char *)passwd); 1100*7c478bd9Sstevel@tonic-gate else { 1101*7c478bd9Sstevel@tonic-gate syslog(LOG_INFO, "Unknown publickey nameservice '%s'", 1102*7c478bd9Sstevel@tonic-gate look->service_name); 1103*7c478bd9Sstevel@tonic-gate err = __NSW_UNAVAIL; 1104*7c478bd9Sstevel@tonic-gate } 1105*7c478bd9Sstevel@tonic-gate switch (look->actions[err]) { 1106*7c478bd9Sstevel@tonic-gate case __NSW_CONTINUE : 1107*7c478bd9Sstevel@tonic-gate continue; 1108*7c478bd9Sstevel@tonic-gate case __NSW_RETURN : 1109*7c478bd9Sstevel@tonic-gate if (needfree) 1110*7c478bd9Sstevel@tonic-gate __nsw_freeconfig(conf); 1111*7c478bd9Sstevel@tonic-gate trace1(TR_getsecretkey_g, 1); 1112*7c478bd9Sstevel@tonic-gate return ((res & 2) != 0); 1113*7c478bd9Sstevel@tonic-gate default : 1114*7c478bd9Sstevel@tonic-gate syslog(LOG_INFO, "Unknown action for nameservice %s", 1115*7c478bd9Sstevel@tonic-gate look->service_name); 1116*7c478bd9Sstevel@tonic-gate } 1117*7c478bd9Sstevel@tonic-gate } 1118*7c478bd9Sstevel@tonic-gate if (needfree) 1119*7c478bd9Sstevel@tonic-gate __nsw_freeconfig(conf); 1120*7c478bd9Sstevel@tonic-gate trace1(TR_getsecretkey_g, 1); 1121*7c478bd9Sstevel@tonic-gate return (0); 1122*7c478bd9Sstevel@tonic-gate } 1123