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 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 23*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 24*7c478bd9Sstevel@tonic-gate */ 25*7c478bd9Sstevel@tonic-gate /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 26*7c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 27*7c478bd9Sstevel@tonic-gate /* 28*7c478bd9Sstevel@tonic-gate * Portions of this source code were derived from Berkeley 29*7c478bd9Sstevel@tonic-gate * 4.3 BSD under license from the Regents of the University of 30*7c478bd9Sstevel@tonic-gate * California. 31*7c478bd9Sstevel@tonic-gate */ 32*7c478bd9Sstevel@tonic-gate /* 33*7c478bd9Sstevel@tonic-gate * ==== hack-attack: possibly MT-safe but definitely not MT-hot. 34*7c478bd9Sstevel@tonic-gate * ==== turn this into a real switch frontend and backends 35*7c478bd9Sstevel@tonic-gate * 36*7c478bd9Sstevel@tonic-gate * Well, at least the API doesn't involve pointers-to-static. 37*7c478bd9Sstevel@tonic-gate */ 38*7c478bd9Sstevel@tonic-gate 39*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 40*7c478bd9Sstevel@tonic-gate 41*7c478bd9Sstevel@tonic-gate /* 42*7c478bd9Sstevel@tonic-gate * netname utility routines (getnetname, user2netname, host2netname). 43*7c478bd9Sstevel@tonic-gate * 44*7c478bd9Sstevel@tonic-gate * Convert from unix names (uid, gid) to network wide names. 45*7c478bd9Sstevel@tonic-gate * This module is operating system dependent! 46*7c478bd9Sstevel@tonic-gate * What we define here will work with any unix system that has adopted 47*7c478bd9Sstevel@tonic-gate * the Sun NIS domain architecture. 48*7c478bd9Sstevel@tonic-gate */ 49*7c478bd9Sstevel@tonic-gate 50*7c478bd9Sstevel@tonic-gate #undef NIS 51*7c478bd9Sstevel@tonic-gate 52*7c478bd9Sstevel@tonic-gate #include "mt.h" 53*7c478bd9Sstevel@tonic-gate #include "rpc_mt.h" 54*7c478bd9Sstevel@tonic-gate #include <stdio.h> 55*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 56*7c478bd9Sstevel@tonic-gate #include <unistd.h> 57*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 58*7c478bd9Sstevel@tonic-gate #include <rpc/trace.h> 59*7c478bd9Sstevel@tonic-gate #include <ctype.h> 60*7c478bd9Sstevel@tonic-gate #include <string.h> 61*7c478bd9Sstevel@tonic-gate #include <syslog.h> 62*7c478bd9Sstevel@tonic-gate #include <sys/param.h> 63*7c478bd9Sstevel@tonic-gate #include <rpc/rpc.h> 64*7c478bd9Sstevel@tonic-gate #include <rpcsvc/nis.h> 65*7c478bd9Sstevel@tonic-gate #include <rpcsvc/nis_dhext.h> 66*7c478bd9Sstevel@tonic-gate #include <nsswitch.h> 67*7c478bd9Sstevel@tonic-gate #include <syslog.h> 68*7c478bd9Sstevel@tonic-gate 69*7c478bd9Sstevel@tonic-gate #ifndef MAXHOSTNAMELEN 70*7c478bd9Sstevel@tonic-gate #define MAXHOSTNAMELEN 256 71*7c478bd9Sstevel@tonic-gate #endif 72*7c478bd9Sstevel@tonic-gate #ifndef NGROUPS 73*7c478bd9Sstevel@tonic-gate #define NGROUPS 16 74*7c478bd9Sstevel@tonic-gate #endif 75*7c478bd9Sstevel@tonic-gate 76*7c478bd9Sstevel@tonic-gate /* 77*7c478bd9Sstevel@tonic-gate * the value for NOBODY_UID is set by the SVID. The following define also 78*7c478bd9Sstevel@tonic-gate * appears in netnamer.c 79*7c478bd9Sstevel@tonic-gate */ 80*7c478bd9Sstevel@tonic-gate 81*7c478bd9Sstevel@tonic-gate #define NOBODY_UID 60001 82*7c478bd9Sstevel@tonic-gate 83*7c478bd9Sstevel@tonic-gate extern int __nis_principal(); 84*7c478bd9Sstevel@tonic-gate extern int getdomainname(); 85*7c478bd9Sstevel@tonic-gate extern char *strncpy(); 86*7c478bd9Sstevel@tonic-gate extern int key_call(); 87*7c478bd9Sstevel@tonic-gate #define OPSYS_LEN 4 88*7c478bd9Sstevel@tonic-gate #define PKTABLE_LEN 12 89*7c478bd9Sstevel@tonic-gate static const char *OPSYS = "unix"; 90*7c478bd9Sstevel@tonic-gate static const char *PKTABLE = "cred.org_dir"; 91*7c478bd9Sstevel@tonic-gate 92*7c478bd9Sstevel@tonic-gate 93*7c478bd9Sstevel@tonic-gate /* 94*7c478bd9Sstevel@tonic-gate * default publickey policy: 95*7c478bd9Sstevel@tonic-gate * publickey: nis [NOTFOUND = return] files 96*7c478bd9Sstevel@tonic-gate */ 97*7c478bd9Sstevel@tonic-gate 98*7c478bd9Sstevel@tonic-gate 99*7c478bd9Sstevel@tonic-gate /* NSW_NOTSUCCESS NSW_NOTFOUND NSW_UNAVAIL NSW_TRYAGAIN */ 100*7c478bd9Sstevel@tonic-gate #define DEF_ACTION {__NSW_RETURN, __NSW_RETURN, __NSW_CONTINUE, __NSW_CONTINUE} 101*7c478bd9Sstevel@tonic-gate 102*7c478bd9Sstevel@tonic-gate static struct __nsw_lookup lookup_files = {"files", DEF_ACTION, NULL, NULL}, 103*7c478bd9Sstevel@tonic-gate lookup_nis = {"nis", DEF_ACTION, NULL, &lookup_files}; 104*7c478bd9Sstevel@tonic-gate static struct __nsw_switchconfig publickey_default = 105*7c478bd9Sstevel@tonic-gate {0, "publickey", 2, &lookup_nis}; 106*7c478bd9Sstevel@tonic-gate 107*7c478bd9Sstevel@tonic-gate static mutex_t serialize_netname = DEFAULTMUTEX; 108*7c478bd9Sstevel@tonic-gate 109*7c478bd9Sstevel@tonic-gate /* 110*7c478bd9Sstevel@tonic-gate * Convert unix cred to network-name using nisplus 111*7c478bd9Sstevel@tonic-gate * nisplus cred table has the following format: 112*7c478bd9Sstevel@tonic-gate * 113*7c478bd9Sstevel@tonic-gate * cname auth_type auth_name public private 114*7c478bd9Sstevel@tonic-gate * ---------------------------------------------------------- 115*7c478bd9Sstevel@tonic-gate * nisname DES netname pubkey private_key 116*7c478bd9Sstevel@tonic-gate * nisname LOCAL uid gidlist 117*7c478bd9Sstevel@tonic-gate * 118*7c478bd9Sstevel@tonic-gate * Obtain netname given <uid,domain>. 119*7c478bd9Sstevel@tonic-gate * 0. If domain is NULL (indicating local domain), first try to get 120*7c478bd9Sstevel@tonic-gate * netname from keyserv (keylogin sets this). 121*7c478bd9Sstevel@tonic-gate * 1. Get the nisplus principal name from the LOCAL entry of the cred 122*7c478bd9Sstevel@tonic-gate * table in the specified domain (the local domain if domain is NULL). 123*7c478bd9Sstevel@tonic-gate * 2. Using the principal name, lookup the DES entry and extract netname. 124*7c478bd9Sstevel@tonic-gate */ 125*7c478bd9Sstevel@tonic-gate 126*7c478bd9Sstevel@tonic-gate static int 127*7c478bd9Sstevel@tonic-gate user2netname_nisplus(err, netname, uid, domain) 128*7c478bd9Sstevel@tonic-gate int *err; 129*7c478bd9Sstevel@tonic-gate char netname[MAXNETNAMELEN + 1]; 130*7c478bd9Sstevel@tonic-gate uid_t uid; 131*7c478bd9Sstevel@tonic-gate char *domain; 132*7c478bd9Sstevel@tonic-gate { 133*7c478bd9Sstevel@tonic-gate key_netstres kres; 134*7c478bd9Sstevel@tonic-gate nis_result *nres; 135*7c478bd9Sstevel@tonic-gate int len; 136*7c478bd9Sstevel@tonic-gate uid_t my_uid; 137*7c478bd9Sstevel@tonic-gate char principal[NIS_MAXNAMELEN+1]; 138*7c478bd9Sstevel@tonic-gate char buf[NIS_MAXNAMELEN+1]; 139*7c478bd9Sstevel@tonic-gate int status; 140*7c478bd9Sstevel@tonic-gate mechanism_t **mechs; 141*7c478bd9Sstevel@tonic-gate char auth_type[MECH_MAXATNAME+1]; 142*7c478bd9Sstevel@tonic-gate 143*7c478bd9Sstevel@tonic-gate trace1(TR_user2netname_nisplus, 0); 144*7c478bd9Sstevel@tonic-gate 145*7c478bd9Sstevel@tonic-gate my_uid = geteuid(); 146*7c478bd9Sstevel@tonic-gate 147*7c478bd9Sstevel@tonic-gate if (my_uid == uid && domain == NULL) { 148*7c478bd9Sstevel@tonic-gate /* 149*7c478bd9Sstevel@tonic-gate * Look up the keyserv interface routines to see if 150*7c478bd9Sstevel@tonic-gate * netname is stored there. 151*7c478bd9Sstevel@tonic-gate */ 152*7c478bd9Sstevel@tonic-gate kres.key_netstres_u.knet.st_netname = NULL; 153*7c478bd9Sstevel@tonic-gate if (key_call((rpcproc_t)KEY_NET_GET, xdr_void, (char *)NULL, 154*7c478bd9Sstevel@tonic-gate xdr_key_netstres, (char *)&kres) && 155*7c478bd9Sstevel@tonic-gate kres.status == KEY_SUCCESS) { 156*7c478bd9Sstevel@tonic-gate len = strlen(kres.key_netstres_u.knet.st_netname); 157*7c478bd9Sstevel@tonic-gate (void) strncpy(netname, 158*7c478bd9Sstevel@tonic-gate kres.key_netstres_u.knet.st_netname, 159*7c478bd9Sstevel@tonic-gate len +1); 160*7c478bd9Sstevel@tonic-gate free(kres.key_netstres_u.knet.st_netname); 161*7c478bd9Sstevel@tonic-gate trace1(TR_user2netname_nisplus, 1); 162*7c478bd9Sstevel@tonic-gate *err = __NSW_SUCCESS; 163*7c478bd9Sstevel@tonic-gate return (1); 164*7c478bd9Sstevel@tonic-gate } 165*7c478bd9Sstevel@tonic-gate } 166*7c478bd9Sstevel@tonic-gate 167*7c478bd9Sstevel@tonic-gate 168*7c478bd9Sstevel@tonic-gate /* 169*7c478bd9Sstevel@tonic-gate * 1. Determine user's nis+ principal name. 170*7c478bd9Sstevel@tonic-gate * 171*7c478bd9Sstevel@tonic-gate * If domain is specified, we want to look up the uid in the 172*7c478bd9Sstevel@tonic-gate * specified domain to determine the user's principal name. 173*7c478bd9Sstevel@tonic-gate * Otherwise, get principal name from local directory. 174*7c478bd9Sstevel@tonic-gate */ 175*7c478bd9Sstevel@tonic-gate if (domain == NULL) 176*7c478bd9Sstevel@tonic-gate domain = nis_local_directory(); 177*7c478bd9Sstevel@tonic-gate /* 178*7c478bd9Sstevel@tonic-gate * Don't use nis_local_principal here because we want to 179*7c478bd9Sstevel@tonic-gate * catch the TRYAGAIN case so that we handle it properly. 180*7c478bd9Sstevel@tonic-gate */ 181*7c478bd9Sstevel@tonic-gate status = __nis_principal(principal, uid, domain); 182*7c478bd9Sstevel@tonic-gate 183*7c478bd9Sstevel@tonic-gate if (status != NIS_SUCCESS && status != NIS_S_SUCCESS) { 184*7c478bd9Sstevel@tonic-gate switch (status) { 185*7c478bd9Sstevel@tonic-gate case NIS_NOTFOUND: 186*7c478bd9Sstevel@tonic-gate case NIS_PARTIAL: 187*7c478bd9Sstevel@tonic-gate case NIS_NOSUCHNAME: 188*7c478bd9Sstevel@tonic-gate case NIS_NOSUCHTABLE: 189*7c478bd9Sstevel@tonic-gate *err = __NSW_NOTFOUND; 190*7c478bd9Sstevel@tonic-gate break; 191*7c478bd9Sstevel@tonic-gate case NIS_S_NOTFOUND: 192*7c478bd9Sstevel@tonic-gate case NIS_TRYAGAIN: 193*7c478bd9Sstevel@tonic-gate *err = __NSW_TRYAGAIN; 194*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 195*7c478bd9Sstevel@tonic-gate "user2netname: (nis+ lookup): %s\n", 196*7c478bd9Sstevel@tonic-gate nis_sperrno(status)); 197*7c478bd9Sstevel@tonic-gate break; 198*7c478bd9Sstevel@tonic-gate default: 199*7c478bd9Sstevel@tonic-gate *err = __NSW_UNAVAIL; 200*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 201*7c478bd9Sstevel@tonic-gate "user2netname: (nis+ lookup): %s\n", 202*7c478bd9Sstevel@tonic-gate nis_sperrno(status)); 203*7c478bd9Sstevel@tonic-gate } 204*7c478bd9Sstevel@tonic-gate 205*7c478bd9Sstevel@tonic-gate trace1(TR_user2netname_nisplus, 1); 206*7c478bd9Sstevel@tonic-gate return (0); 207*7c478bd9Sstevel@tonic-gate } 208*7c478bd9Sstevel@tonic-gate 209*7c478bd9Sstevel@tonic-gate /* 210*7c478bd9Sstevel@tonic-gate * 2. use nis+ principal name to get netname by getting a PK entry. 211*7c478bd9Sstevel@tonic-gate * 212*7c478bd9Sstevel@tonic-gate * (Use NOAUTH to prevent recursion.) 213*7c478bd9Sstevel@tonic-gate */ 214*7c478bd9Sstevel@tonic-gate domain = nis_domain_of(principal); 215*7c478bd9Sstevel@tonic-gate if ((strlen(principal)+strlen(domain)+PKTABLE_LEN+ 28) > 216*7c478bd9Sstevel@tonic-gate (size_t)NIS_MAXNAMELEN) { 217*7c478bd9Sstevel@tonic-gate *err = __NSW_UNAVAIL; 218*7c478bd9Sstevel@tonic-gate trace1(TR_user2netname_nisplus, 1); 219*7c478bd9Sstevel@tonic-gate return (0); 220*7c478bd9Sstevel@tonic-gate } 221*7c478bd9Sstevel@tonic-gate 222*7c478bd9Sstevel@tonic-gate if (mechs = __nis_get_mechanisms(FALSE)) { 223*7c478bd9Sstevel@tonic-gate mechanism_t **mpp; 224*7c478bd9Sstevel@tonic-gate 225*7c478bd9Sstevel@tonic-gate /* 226*7c478bd9Sstevel@tonic-gate * Loop thru mechanism types till we find one in the 227*7c478bd9Sstevel@tonic-gate * cred table for this user. 228*7c478bd9Sstevel@tonic-gate */ 229*7c478bd9Sstevel@tonic-gate for (mpp = mechs; *mpp; mpp++) { 230*7c478bd9Sstevel@tonic-gate mechanism_t *mp = *mpp; 231*7c478bd9Sstevel@tonic-gate 232*7c478bd9Sstevel@tonic-gate if (AUTH_DES_COMPAT_CHK(mp)) { 233*7c478bd9Sstevel@tonic-gate __nis_release_mechanisms(mechs); 234*7c478bd9Sstevel@tonic-gate goto try_auth_des; 235*7c478bd9Sstevel@tonic-gate } 236*7c478bd9Sstevel@tonic-gate if (! VALID_MECH_ENTRY(mp)) 237*7c478bd9Sstevel@tonic-gate continue; 238*7c478bd9Sstevel@tonic-gate 239*7c478bd9Sstevel@tonic-gate if (! __nis_mechalias2authtype(mp->alias, auth_type, 240*7c478bd9Sstevel@tonic-gate sizeof (auth_type))) 241*7c478bd9Sstevel@tonic-gate continue; 242*7c478bd9Sstevel@tonic-gate 243*7c478bd9Sstevel@tonic-gate (void) sprintf(buf, 244*7c478bd9Sstevel@tonic-gate "[cname=\"%s\",auth_type=\"%s\"],%s.%s", 245*7c478bd9Sstevel@tonic-gate principal, auth_type, PKTABLE, domain); 246*7c478bd9Sstevel@tonic-gate if (buf[strlen(buf)-1] != '.') 247*7c478bd9Sstevel@tonic-gate (void) strcat(buf, "."); 248*7c478bd9Sstevel@tonic-gate 249*7c478bd9Sstevel@tonic-gate nres = nis_list(buf, 250*7c478bd9Sstevel@tonic-gate USE_DGRAM+NO_AUTHINFO+FOLLOW_LINKS+FOLLOW_PATH, 251*7c478bd9Sstevel@tonic-gate NULL, NULL); 252*7c478bd9Sstevel@tonic-gate 253*7c478bd9Sstevel@tonic-gate /* 254*7c478bd9Sstevel@tonic-gate * If the entry is not found, let's try the next one, 255*7c478bd9Sstevel@tonic-gate * else it's success or a serious enough NIS+ err 256*7c478bd9Sstevel@tonic-gate * to bail on. 257*7c478bd9Sstevel@tonic-gate */ 258*7c478bd9Sstevel@tonic-gate if (nres->status != NIS_NOTFOUND) 259*7c478bd9Sstevel@tonic-gate break; 260*7c478bd9Sstevel@tonic-gate } 261*7c478bd9Sstevel@tonic-gate } else { 262*7c478bd9Sstevel@tonic-gate try_auth_des: 263*7c478bd9Sstevel@tonic-gate /* 264*7c478bd9Sstevel@tonic-gate * No valid mechs exist or the AUTH_DES compat entry was 265*7c478bd9Sstevel@tonic-gate * found in the security cf. 266*7c478bd9Sstevel@tonic-gate */ 267*7c478bd9Sstevel@tonic-gate (void) sprintf(buf, "[cname=\"%s\",auth_type=DES],%s.%s", 268*7c478bd9Sstevel@tonic-gate principal, PKTABLE, domain); 269*7c478bd9Sstevel@tonic-gate if (buf[strlen(buf)-1] != '.') 270*7c478bd9Sstevel@tonic-gate (void) strcat(buf, "."); 271*7c478bd9Sstevel@tonic-gate 272*7c478bd9Sstevel@tonic-gate nres = nis_list(buf, 273*7c478bd9Sstevel@tonic-gate USE_DGRAM+NO_AUTHINFO+FOLLOW_LINKS+FOLLOW_PATH, 274*7c478bd9Sstevel@tonic-gate NULL, NULL); 275*7c478bd9Sstevel@tonic-gate } 276*7c478bd9Sstevel@tonic-gate 277*7c478bd9Sstevel@tonic-gate switch (nres->status) { 278*7c478bd9Sstevel@tonic-gate case NIS_SUCCESS: 279*7c478bd9Sstevel@tonic-gate case NIS_S_SUCCESS: 280*7c478bd9Sstevel@tonic-gate break; /* go and do something useful */ 281*7c478bd9Sstevel@tonic-gate case NIS_NOTFOUND: 282*7c478bd9Sstevel@tonic-gate case NIS_PARTIAL: 283*7c478bd9Sstevel@tonic-gate case NIS_NOSUCHNAME: 284*7c478bd9Sstevel@tonic-gate case NIS_NOSUCHTABLE: 285*7c478bd9Sstevel@tonic-gate *err = __NSW_NOTFOUND; 286*7c478bd9Sstevel@tonic-gate nis_freeresult(nres); 287*7c478bd9Sstevel@tonic-gate trace1(TR_user2netname_nisplus, 1); 288*7c478bd9Sstevel@tonic-gate return (0); 289*7c478bd9Sstevel@tonic-gate case NIS_S_NOTFOUND: 290*7c478bd9Sstevel@tonic-gate case NIS_TRYAGAIN: 291*7c478bd9Sstevel@tonic-gate *err = __NSW_TRYAGAIN; 292*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 293*7c478bd9Sstevel@tonic-gate "user2netname: (nis+ lookup): %s\n", 294*7c478bd9Sstevel@tonic-gate nis_sperrno(nres->status)); 295*7c478bd9Sstevel@tonic-gate nis_freeresult(nres); 296*7c478bd9Sstevel@tonic-gate trace1(TR_user2netname_nisplus, 1); 297*7c478bd9Sstevel@tonic-gate return (0); 298*7c478bd9Sstevel@tonic-gate default: 299*7c478bd9Sstevel@tonic-gate *err = __NSW_UNAVAIL; 300*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, "user2netname: (nis+ lookup): %s\n", 301*7c478bd9Sstevel@tonic-gate nis_sperrno(nres->status)); 302*7c478bd9Sstevel@tonic-gate nis_freeresult(nres); 303*7c478bd9Sstevel@tonic-gate trace1(TR_user2netname_nisplus, 1); 304*7c478bd9Sstevel@tonic-gate return (0); 305*7c478bd9Sstevel@tonic-gate } 306*7c478bd9Sstevel@tonic-gate 307*7c478bd9Sstevel@tonic-gate if (nres->objects.objects_len > 1) { 308*7c478bd9Sstevel@tonic-gate /* 309*7c478bd9Sstevel@tonic-gate * Principal with more than one entry for this mech type? 310*7c478bd9Sstevel@tonic-gate * Something wrong with cred table. Should be unique. 311*7c478bd9Sstevel@tonic-gate * Warn user and continue. 312*7c478bd9Sstevel@tonic-gate */ 313*7c478bd9Sstevel@tonic-gate syslog(LOG_ALERT, 314*7c478bd9Sstevel@tonic-gate "user2netname: %s entry for %s not unique", 315*7c478bd9Sstevel@tonic-gate auth_type, principal); 316*7c478bd9Sstevel@tonic-gate } 317*7c478bd9Sstevel@tonic-gate 318*7c478bd9Sstevel@tonic-gate len = ENTRY_LEN(nres->objects.objects_val, 2); 319*7c478bd9Sstevel@tonic-gate if (len > MAXNETNAMELEN) { 320*7c478bd9Sstevel@tonic-gate *err = __NSW_UNAVAIL; 321*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, "user2netname: netname of '%s' too long", 322*7c478bd9Sstevel@tonic-gate principal); 323*7c478bd9Sstevel@tonic-gate nis_freeresult(nres); 324*7c478bd9Sstevel@tonic-gate trace1(TR_user2netname_nisplus, 1); 325*7c478bd9Sstevel@tonic-gate return (0); 326*7c478bd9Sstevel@tonic-gate } 327*7c478bd9Sstevel@tonic-gate (void) strncpy(netname, ENTRY_VAL(nres->objects.objects_val, 2), len); 328*7c478bd9Sstevel@tonic-gate netname[len] = '\0'; 329*7c478bd9Sstevel@tonic-gate nis_freeresult(nres); 330*7c478bd9Sstevel@tonic-gate *err = __NSW_SUCCESS; 331*7c478bd9Sstevel@tonic-gate trace1(TR_user2netname_nisplus, 1); 332*7c478bd9Sstevel@tonic-gate return (1); 333*7c478bd9Sstevel@tonic-gate } 334*7c478bd9Sstevel@tonic-gate 335*7c478bd9Sstevel@tonic-gate #define MAXIPRINT (11) /* max length of printed integer */ 336*7c478bd9Sstevel@tonic-gate 337*7c478bd9Sstevel@tonic-gate /* 338*7c478bd9Sstevel@tonic-gate * Convert unix cred to network-name by concatenating the 339*7c478bd9Sstevel@tonic-gate * 3 pieces of information <opsys type> <uid> <domain>. 340*7c478bd9Sstevel@tonic-gate */ 341*7c478bd9Sstevel@tonic-gate 342*7c478bd9Sstevel@tonic-gate static int 343*7c478bd9Sstevel@tonic-gate user2netname_nis(err, netname, uid, domain) 344*7c478bd9Sstevel@tonic-gate int *err; 345*7c478bd9Sstevel@tonic-gate char netname[MAXNETNAMELEN + 1]; 346*7c478bd9Sstevel@tonic-gate uid_t uid; 347*7c478bd9Sstevel@tonic-gate char *domain; 348*7c478bd9Sstevel@tonic-gate { 349*7c478bd9Sstevel@tonic-gate int i; 350*7c478bd9Sstevel@tonic-gate char *dfltdom; 351*7c478bd9Sstevel@tonic-gate if (domain == NULL) { 352*7c478bd9Sstevel@tonic-gate if (__rpc_get_default_domain(&dfltdom) != 0) { 353*7c478bd9Sstevel@tonic-gate trace1(TR_user2netname_nis, 1); 354*7c478bd9Sstevel@tonic-gate *err = __NSW_UNAVAIL; 355*7c478bd9Sstevel@tonic-gate return (0); 356*7c478bd9Sstevel@tonic-gate } 357*7c478bd9Sstevel@tonic-gate domain = dfltdom; 358*7c478bd9Sstevel@tonic-gate } 359*7c478bd9Sstevel@tonic-gate if ((strlen(domain) + OPSYS_LEN + 3 + MAXIPRINT) > 360*7c478bd9Sstevel@tonic-gate (size_t)MAXNETNAMELEN) { 361*7c478bd9Sstevel@tonic-gate trace1(TR_user2netname_nis, 1); 362*7c478bd9Sstevel@tonic-gate *err = __NSW_UNAVAIL; 363*7c478bd9Sstevel@tonic-gate return (0); 364*7c478bd9Sstevel@tonic-gate } 365*7c478bd9Sstevel@tonic-gate (void) sprintf(netname, "%s.%d@%s", OPSYS, (int)uid, domain); 366*7c478bd9Sstevel@tonic-gate i = strlen(netname); 367*7c478bd9Sstevel@tonic-gate if (netname[i-1] == '.') 368*7c478bd9Sstevel@tonic-gate netname[i-1] = '\0'; 369*7c478bd9Sstevel@tonic-gate trace1(TR_user2netname_nis, 1); 370*7c478bd9Sstevel@tonic-gate *err = __NSW_SUCCESS; 371*7c478bd9Sstevel@tonic-gate return (1); 372*7c478bd9Sstevel@tonic-gate } 373*7c478bd9Sstevel@tonic-gate 374*7c478bd9Sstevel@tonic-gate /* 375*7c478bd9Sstevel@tonic-gate * Figure out my fully qualified network name 376*7c478bd9Sstevel@tonic-gate */ 377*7c478bd9Sstevel@tonic-gate int 378*7c478bd9Sstevel@tonic-gate getnetname(name) 379*7c478bd9Sstevel@tonic-gate char name[MAXNETNAMELEN + 1]; 380*7c478bd9Sstevel@tonic-gate { 381*7c478bd9Sstevel@tonic-gate uid_t uid; 382*7c478bd9Sstevel@tonic-gate int dummy; 383*7c478bd9Sstevel@tonic-gate 384*7c478bd9Sstevel@tonic-gate trace1(TR_getnetname, 0); 385*7c478bd9Sstevel@tonic-gate 386*7c478bd9Sstevel@tonic-gate uid = geteuid(); 387*7c478bd9Sstevel@tonic-gate if (uid == 0) 388*7c478bd9Sstevel@tonic-gate dummy = host2netname(name, (char *)NULL, (char *)NULL); 389*7c478bd9Sstevel@tonic-gate else 390*7c478bd9Sstevel@tonic-gate dummy = user2netname(name, uid, (char *)NULL); 391*7c478bd9Sstevel@tonic-gate 392*7c478bd9Sstevel@tonic-gate trace1(TR_getnetname, 1); 393*7c478bd9Sstevel@tonic-gate return (dummy); 394*7c478bd9Sstevel@tonic-gate } 395*7c478bd9Sstevel@tonic-gate 396*7c478bd9Sstevel@tonic-gate 397*7c478bd9Sstevel@tonic-gate /* 398*7c478bd9Sstevel@tonic-gate * Figure out the fully qualified network name for the given uid. 399*7c478bd9Sstevel@tonic-gate * This is a private interface. 400*7c478bd9Sstevel@tonic-gate */ 401*7c478bd9Sstevel@tonic-gate int 402*7c478bd9Sstevel@tonic-gate __getnetnamebyuid(name, uid) 403*7c478bd9Sstevel@tonic-gate char name[MAXNETNAMELEN + 1]; 404*7c478bd9Sstevel@tonic-gate uid_t uid; 405*7c478bd9Sstevel@tonic-gate { 406*7c478bd9Sstevel@tonic-gate int dummy; 407*7c478bd9Sstevel@tonic-gate 408*7c478bd9Sstevel@tonic-gate trace1(TR___getnetnamebyuid, 0); 409*7c478bd9Sstevel@tonic-gate 410*7c478bd9Sstevel@tonic-gate if (uid == 0) 411*7c478bd9Sstevel@tonic-gate dummy = host2netname(name, (char *)NULL, (char *)NULL); 412*7c478bd9Sstevel@tonic-gate else 413*7c478bd9Sstevel@tonic-gate dummy = user2netname(name, uid, (char *)NULL); 414*7c478bd9Sstevel@tonic-gate 415*7c478bd9Sstevel@tonic-gate trace1(TR___getnetnamebyuid, 1); 416*7c478bd9Sstevel@tonic-gate return (dummy); 417*7c478bd9Sstevel@tonic-gate } 418*7c478bd9Sstevel@tonic-gate 419*7c478bd9Sstevel@tonic-gate /* 420*7c478bd9Sstevel@tonic-gate * Convert unix cred to network-name 421*7c478bd9Sstevel@tonic-gate * 422*7c478bd9Sstevel@tonic-gate * It uses the publickey policy in the /etc/nsswitch.conf file 423*7c478bd9Sstevel@tonic-gate * (Unless the netname is "nobody", which is special cased). 424*7c478bd9Sstevel@tonic-gate * If there is no publickey policy in /etc/nsswitch.conf, 425*7c478bd9Sstevel@tonic-gate * the default publickey policy is used, which is 426*7c478bd9Sstevel@tonic-gate * publickey: nis [NOTFOUND=return] files 427*7c478bd9Sstevel@tonic-gate * Note that for the non-nisplus case, there is no failover 428*7c478bd9Sstevel@tonic-gate * so only the first entry would be relevant for those cases. 429*7c478bd9Sstevel@tonic-gate */ 430*7c478bd9Sstevel@tonic-gate int 431*7c478bd9Sstevel@tonic-gate user2netname(netname, uid, domain) 432*7c478bd9Sstevel@tonic-gate char netname[MAXNETNAMELEN + 1]; 433*7c478bd9Sstevel@tonic-gate const uid_t uid; 434*7c478bd9Sstevel@tonic-gate const char *domain; 435*7c478bd9Sstevel@tonic-gate { 436*7c478bd9Sstevel@tonic-gate struct __nsw_switchconfig *conf; 437*7c478bd9Sstevel@tonic-gate struct __nsw_lookup *look; 438*7c478bd9Sstevel@tonic-gate int needfree = 1, res = 0; 439*7c478bd9Sstevel@tonic-gate enum __nsw_parse_err perr; 440*7c478bd9Sstevel@tonic-gate int err; 441*7c478bd9Sstevel@tonic-gate 442*7c478bd9Sstevel@tonic-gate trace1(TR_user2netname, 0); 443*7c478bd9Sstevel@tonic-gate 444*7c478bd9Sstevel@tonic-gate /* 445*7c478bd9Sstevel@tonic-gate * Take care of the special case of "nobody". If the uid is 446*7c478bd9Sstevel@tonic-gate * the value assigned by the SVID for nobody, return the string 447*7c478bd9Sstevel@tonic-gate * "nobody". 448*7c478bd9Sstevel@tonic-gate */ 449*7c478bd9Sstevel@tonic-gate 450*7c478bd9Sstevel@tonic-gate if (uid == NOBODY_UID) { 451*7c478bd9Sstevel@tonic-gate (void) strcpy(netname, "nobody"); 452*7c478bd9Sstevel@tonic-gate return (1); 453*7c478bd9Sstevel@tonic-gate } 454*7c478bd9Sstevel@tonic-gate 455*7c478bd9Sstevel@tonic-gate netname[0] = '\0'; /* make null first (no need for memset) */ 456*7c478bd9Sstevel@tonic-gate 457*7c478bd9Sstevel@tonic-gate mutex_lock(&serialize_netname); 458*7c478bd9Sstevel@tonic-gate 459*7c478bd9Sstevel@tonic-gate conf = __nsw_getconfig("publickey", &perr); 460*7c478bd9Sstevel@tonic-gate if (! conf) { 461*7c478bd9Sstevel@tonic-gate conf = &publickey_default; 462*7c478bd9Sstevel@tonic-gate needfree = 0; 463*7c478bd9Sstevel@tonic-gate } 464*7c478bd9Sstevel@tonic-gate 465*7c478bd9Sstevel@tonic-gate for (look = conf->lookups; look; look = look->next) { 466*7c478bd9Sstevel@tonic-gate if (strcmp(look->service_name, "nisplus") == 0) 467*7c478bd9Sstevel@tonic-gate res = user2netname_nisplus(&err, 468*7c478bd9Sstevel@tonic-gate netname, uid, (char *)domain); 469*7c478bd9Sstevel@tonic-gate /* ldap, nis, and files all do the same thing. */ 470*7c478bd9Sstevel@tonic-gate else if (strcmp(look->service_name, "ldap") == 0 || 471*7c478bd9Sstevel@tonic-gate strcmp(look->service_name, "nis") == 0 || 472*7c478bd9Sstevel@tonic-gate strcmp(look->service_name, "files") == 0) 473*7c478bd9Sstevel@tonic-gate res = user2netname_nis(&err, 474*7c478bd9Sstevel@tonic-gate netname, uid, (char *)domain); 475*7c478bd9Sstevel@tonic-gate else { 476*7c478bd9Sstevel@tonic-gate syslog(LOG_INFO, 477*7c478bd9Sstevel@tonic-gate "user2netname: unknown nameservice \ 478*7c478bd9Sstevel@tonic-gate for publickey info '%s'\n", 479*7c478bd9Sstevel@tonic-gate look->service_name); 480*7c478bd9Sstevel@tonic-gate err = __NSW_UNAVAIL; 481*7c478bd9Sstevel@tonic-gate } 482*7c478bd9Sstevel@tonic-gate switch (look->actions[err]) { 483*7c478bd9Sstevel@tonic-gate case __NSW_CONTINUE : 484*7c478bd9Sstevel@tonic-gate break; 485*7c478bd9Sstevel@tonic-gate case __NSW_RETURN : 486*7c478bd9Sstevel@tonic-gate if (needfree) 487*7c478bd9Sstevel@tonic-gate __nsw_freeconfig(conf); 488*7c478bd9Sstevel@tonic-gate mutex_unlock(&serialize_netname); 489*7c478bd9Sstevel@tonic-gate trace1(TR_user2netname, 1); 490*7c478bd9Sstevel@tonic-gate return (res); 491*7c478bd9Sstevel@tonic-gate default : 492*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 493*7c478bd9Sstevel@tonic-gate "user2netname: Unknown action for nameservice '%s'", 494*7c478bd9Sstevel@tonic-gate look->service_name); 495*7c478bd9Sstevel@tonic-gate } 496*7c478bd9Sstevel@tonic-gate } 497*7c478bd9Sstevel@tonic-gate if (needfree) 498*7c478bd9Sstevel@tonic-gate __nsw_freeconfig(conf); 499*7c478bd9Sstevel@tonic-gate mutex_unlock(&serialize_netname); 500*7c478bd9Sstevel@tonic-gate trace1(TR_user2netname, 1); 501*7c478bd9Sstevel@tonic-gate return (0); 502*7c478bd9Sstevel@tonic-gate } 503*7c478bd9Sstevel@tonic-gate 504*7c478bd9Sstevel@tonic-gate 505*7c478bd9Sstevel@tonic-gate /* 506*7c478bd9Sstevel@tonic-gate * Convert host to network-name 507*7c478bd9Sstevel@tonic-gate * This routine returns following netnames given the host and domain 508*7c478bd9Sstevel@tonic-gate * arguments defined below: (domainname=y.z) 509*7c478bd9Sstevel@tonic-gate * Arguments 510*7c478bd9Sstevel@tonic-gate * host domain netname 511*7c478bd9Sstevel@tonic-gate * ---- ------ ------- 512*7c478bd9Sstevel@tonic-gate * - - unix.m@y.z (hostname=m) 513*7c478bd9Sstevel@tonic-gate * - a.b unix.m@a.b (hostname=m) 514*7c478bd9Sstevel@tonic-gate * - - unix.m@y.z (hostname=m.w.x) 515*7c478bd9Sstevel@tonic-gate * - a.b unix.m@a.b (hostname=m.w.x) 516*7c478bd9Sstevel@tonic-gate * h - unix.h@y.z 517*7c478bd9Sstevel@tonic-gate * h a.b unix.h@a.b 518*7c478bd9Sstevel@tonic-gate * h.w.x - unix.h@w.x 519*7c478bd9Sstevel@tonic-gate * h.w.x a.b unix.h@a.b 520*7c478bd9Sstevel@tonic-gate */ 521*7c478bd9Sstevel@tonic-gate int 522*7c478bd9Sstevel@tonic-gate host2netname(netname, host, domain) 523*7c478bd9Sstevel@tonic-gate char netname[MAXNETNAMELEN + 1]; 524*7c478bd9Sstevel@tonic-gate const char *host; 525*7c478bd9Sstevel@tonic-gate const char *domain; 526*7c478bd9Sstevel@tonic-gate { 527*7c478bd9Sstevel@tonic-gate char *p; 528*7c478bd9Sstevel@tonic-gate char hostname[MAXHOSTNAMELEN + 1]; 529*7c478bd9Sstevel@tonic-gate char domainname[MAXHOSTNAMELEN + 1]; 530*7c478bd9Sstevel@tonic-gate char *dot_in_host; 531*7c478bd9Sstevel@tonic-gate int i; 532*7c478bd9Sstevel@tonic-gate size_t len; 533*7c478bd9Sstevel@tonic-gate 534*7c478bd9Sstevel@tonic-gate trace1(TR_host2netname, 0); 535*7c478bd9Sstevel@tonic-gate 536*7c478bd9Sstevel@tonic-gate netname[0] = '\0'; /* make null first (no need for memset) */ 537*7c478bd9Sstevel@tonic-gate 538*7c478bd9Sstevel@tonic-gate if (host == NULL) { 539*7c478bd9Sstevel@tonic-gate (void) strncpy(hostname, nis_local_host(), sizeof (hostname)); 540*7c478bd9Sstevel@tonic-gate p = (char *)strchr(hostname, '.'); 541*7c478bd9Sstevel@tonic-gate if (p) { 542*7c478bd9Sstevel@tonic-gate *p++ = '\0'; 543*7c478bd9Sstevel@tonic-gate /* if no domain passed, use tail of nis_local_host() */ 544*7c478bd9Sstevel@tonic-gate if (domain == NULL) { 545*7c478bd9Sstevel@tonic-gate domain = p; 546*7c478bd9Sstevel@tonic-gate } 547*7c478bd9Sstevel@tonic-gate } 548*7c478bd9Sstevel@tonic-gate } else { 549*7c478bd9Sstevel@tonic-gate len = strlen(host); 550*7c478bd9Sstevel@tonic-gate if (len >= sizeof (hostname)) { 551*7c478bd9Sstevel@tonic-gate return (0); 552*7c478bd9Sstevel@tonic-gate } 553*7c478bd9Sstevel@tonic-gate (void) strcpy(hostname, host); 554*7c478bd9Sstevel@tonic-gate } 555*7c478bd9Sstevel@tonic-gate 556*7c478bd9Sstevel@tonic-gate dot_in_host = (char *)strchr(hostname, '.'); 557*7c478bd9Sstevel@tonic-gate if (domain == NULL) { 558*7c478bd9Sstevel@tonic-gate p = dot_in_host; 559*7c478bd9Sstevel@tonic-gate if (p) { 560*7c478bd9Sstevel@tonic-gate p = (char *)nis_domain_of(hostname); 561*7c478bd9Sstevel@tonic-gate len = strlen(p); 562*7c478bd9Sstevel@tonic-gate if (len >= sizeof (domainname)) { 563*7c478bd9Sstevel@tonic-gate return (0); 564*7c478bd9Sstevel@tonic-gate } 565*7c478bd9Sstevel@tonic-gate (void) strcpy(domainname, p); 566*7c478bd9Sstevel@tonic-gate } else { 567*7c478bd9Sstevel@tonic-gate domainname[0] = NULL; 568*7c478bd9Sstevel@tonic-gate if (getdomainname(domainname, MAXHOSTNAMELEN) < 0) 569*7c478bd9Sstevel@tonic-gate return (0); 570*7c478bd9Sstevel@tonic-gate } 571*7c478bd9Sstevel@tonic-gate } else { 572*7c478bd9Sstevel@tonic-gate len = strlen(domain); 573*7c478bd9Sstevel@tonic-gate if (len >= sizeof (domainname)) { 574*7c478bd9Sstevel@tonic-gate return (0); 575*7c478bd9Sstevel@tonic-gate } 576*7c478bd9Sstevel@tonic-gate (void) strcpy(domainname, domain); 577*7c478bd9Sstevel@tonic-gate } 578*7c478bd9Sstevel@tonic-gate 579*7c478bd9Sstevel@tonic-gate i = strlen(domainname); 580*7c478bd9Sstevel@tonic-gate if (i == 0) 581*7c478bd9Sstevel@tonic-gate /* No domainname */ 582*7c478bd9Sstevel@tonic-gate return (0); 583*7c478bd9Sstevel@tonic-gate if (domainname[i - 1] == '.') 584*7c478bd9Sstevel@tonic-gate domainname[i - 1] = 0; 585*7c478bd9Sstevel@tonic-gate 586*7c478bd9Sstevel@tonic-gate if (dot_in_host) { /* strip off rest of name */ 587*7c478bd9Sstevel@tonic-gate *dot_in_host = '\0'; 588*7c478bd9Sstevel@tonic-gate } 589*7c478bd9Sstevel@tonic-gate 590*7c478bd9Sstevel@tonic-gate if ((strlen(domainname) + strlen(hostname) + OPSYS_LEN + 3) 591*7c478bd9Sstevel@tonic-gate > (size_t)MAXNETNAMELEN) { 592*7c478bd9Sstevel@tonic-gate trace1(TR_host2netname, 1); 593*7c478bd9Sstevel@tonic-gate return (0); 594*7c478bd9Sstevel@tonic-gate } 595*7c478bd9Sstevel@tonic-gate 596*7c478bd9Sstevel@tonic-gate (void) sprintf(netname, "%s.%s@%s", OPSYS, hostname, domainname); 597*7c478bd9Sstevel@tonic-gate trace1(TR_host2netname, 1); 598*7c478bd9Sstevel@tonic-gate return (1); 599*7c478bd9Sstevel@tonic-gate } 600