1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate * 22*0Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 23*0Sstevel@tonic-gate * Use is subject to license terms. 24*0Sstevel@tonic-gate */ 25*0Sstevel@tonic-gate /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 26*0Sstevel@tonic-gate /* All Rights Reserved */ 27*0Sstevel@tonic-gate /* 28*0Sstevel@tonic-gate * Portions of this source code were derived from Berkeley 29*0Sstevel@tonic-gate * 4.3 BSD under license from the Regents of the University of 30*0Sstevel@tonic-gate * California. 31*0Sstevel@tonic-gate */ 32*0Sstevel@tonic-gate /* 33*0Sstevel@tonic-gate * ==== hack-attack: possibly MT-safe but definitely not MT-hot. 34*0Sstevel@tonic-gate * ==== turn this into a real switch frontend and backends 35*0Sstevel@tonic-gate * 36*0Sstevel@tonic-gate * Well, at least the API doesn't involve pointers-to-static. 37*0Sstevel@tonic-gate */ 38*0Sstevel@tonic-gate 39*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 40*0Sstevel@tonic-gate 41*0Sstevel@tonic-gate /* 42*0Sstevel@tonic-gate * netname utility routines convert from netnames to unix names (uid, gid) 43*0Sstevel@tonic-gate * 44*0Sstevel@tonic-gate * This module is operating system dependent! 45*0Sstevel@tonic-gate * What we define here will work with any unix system that has adopted 46*0Sstevel@tonic-gate * the Sun NIS domain architecture. 47*0Sstevel@tonic-gate */ 48*0Sstevel@tonic-gate 49*0Sstevel@tonic-gate #undef NIS 50*0Sstevel@tonic-gate #include "mt.h" 51*0Sstevel@tonic-gate #include "rpc_mt.h" 52*0Sstevel@tonic-gate #include <stdio.h> 53*0Sstevel@tonic-gate #include <stdlib.h> 54*0Sstevel@tonic-gate #include <sys/types.h> 55*0Sstevel@tonic-gate #include <rpc/trace.h> 56*0Sstevel@tonic-gate #include <ctype.h> 57*0Sstevel@tonic-gate #include <grp.h> 58*0Sstevel@tonic-gate #include <pwd.h> 59*0Sstevel@tonic-gate #include <string.h> 60*0Sstevel@tonic-gate #include <syslog.h> 61*0Sstevel@tonic-gate #include <sys/param.h> 62*0Sstevel@tonic-gate #include <nsswitch.h> 63*0Sstevel@tonic-gate #include <rpc/rpc.h> 64*0Sstevel@tonic-gate #include <rpcsvc/nis.h> 65*0Sstevel@tonic-gate #include <rpcsvc/ypclnt.h> 66*0Sstevel@tonic-gate #include "nsl_stdio_prv.h" 67*0Sstevel@tonic-gate #include <nss_dbdefs.h> 68*0Sstevel@tonic-gate 69*0Sstevel@tonic-gate static const char OPSYS[] = "unix"; 70*0Sstevel@tonic-gate static const char NETIDFILE[] = "/etc/netid"; 71*0Sstevel@tonic-gate static const char NETID[] = "netid.byname"; 72*0Sstevel@tonic-gate static const char PKTABLE[] = "cred.org_dir"; 73*0Sstevel@tonic-gate #define PKTABLE_LEN 12 74*0Sstevel@tonic-gate #define OPSYS_LEN 4 75*0Sstevel@tonic-gate 76*0Sstevel@tonic-gate #ifndef NGROUPS 77*0Sstevel@tonic-gate #define NGROUPS 16 78*0Sstevel@tonic-gate #endif 79*0Sstevel@tonic-gate 80*0Sstevel@tonic-gate extern int _getgroupsbymember(const char *, gid_t[], int, int); 81*0Sstevel@tonic-gate 82*0Sstevel@tonic-gate /* 83*0Sstevel@tonic-gate * the value for NOBODY_UID is set by the SVID. The following define also 84*0Sstevel@tonic-gate * appears in netname.c 85*0Sstevel@tonic-gate */ 86*0Sstevel@tonic-gate 87*0Sstevel@tonic-gate #define NOBODY_UID 60001 88*0Sstevel@tonic-gate 89*0Sstevel@tonic-gate /* 90*0Sstevel@tonic-gate * default publickey policy: 91*0Sstevel@tonic-gate * publickey: nis [NOTFOUND = return] files 92*0Sstevel@tonic-gate */ 93*0Sstevel@tonic-gate 94*0Sstevel@tonic-gate 95*0Sstevel@tonic-gate /* NSW_NOTSUCCESS NSW_NOTFOUND NSW_UNAVAIL NSW_TRYAGAIN */ 96*0Sstevel@tonic-gate #define DEF_ACTION {__NSW_RETURN, __NSW_RETURN, __NSW_CONTINUE, __NSW_CONTINUE} 97*0Sstevel@tonic-gate 98*0Sstevel@tonic-gate static struct __nsw_lookup lookup_files = {"files", DEF_ACTION, NULL, NULL}, 99*0Sstevel@tonic-gate lookup_nis = {"nis", DEF_ACTION, NULL, &lookup_files}; 100*0Sstevel@tonic-gate static struct __nsw_switchconfig publickey_default = 101*0Sstevel@tonic-gate {0, "publickey", 2, &lookup_nis}; 102*0Sstevel@tonic-gate 103*0Sstevel@tonic-gate static mutex_t serialize_netname_r = DEFAULTMUTEX; 104*0Sstevel@tonic-gate 105*0Sstevel@tonic-gate struct netid_userdata { 106*0Sstevel@tonic-gate uid_t *uidp; 107*0Sstevel@tonic-gate gid_t *gidp; 108*0Sstevel@tonic-gate int *gidlenp; 109*0Sstevel@tonic-gate gid_t *gidlist; 110*0Sstevel@tonic-gate }; 111*0Sstevel@tonic-gate 112*0Sstevel@tonic-gate static int 113*0Sstevel@tonic-gate parse_uid(s, argp) 114*0Sstevel@tonic-gate char *s; 115*0Sstevel@tonic-gate struct netid_userdata *argp; 116*0Sstevel@tonic-gate { 117*0Sstevel@tonic-gate uid_t u; 118*0Sstevel@tonic-gate 119*0Sstevel@tonic-gate trace1(TR_parse_uid, 0); 120*0Sstevel@tonic-gate 121*0Sstevel@tonic-gate if (!s || !isdigit(*s)) { 122*0Sstevel@tonic-gate syslog(LOG_ERR, 123*0Sstevel@tonic-gate "netname2user: expecting uid '%s'", s); 124*0Sstevel@tonic-gate trace1(TR_parse_uid, 1); 125*0Sstevel@tonic-gate return (__NSW_NOTFOUND); /* xxx need a better error */ 126*0Sstevel@tonic-gate } 127*0Sstevel@tonic-gate 128*0Sstevel@tonic-gate /* Fetch the uid */ 129*0Sstevel@tonic-gate u = (uid_t)(atoi(s)); 130*0Sstevel@tonic-gate 131*0Sstevel@tonic-gate if (u == 0) { 132*0Sstevel@tonic-gate syslog(LOG_ERR, "netname2user: should not have uid 0"); 133*0Sstevel@tonic-gate trace1(TR_parse_uid, 1); 134*0Sstevel@tonic-gate return (__NSW_NOTFOUND); 135*0Sstevel@tonic-gate } 136*0Sstevel@tonic-gate *(argp->uidp) = u; 137*0Sstevel@tonic-gate trace1(TR_parse_uid, 1); 138*0Sstevel@tonic-gate return (__NSW_SUCCESS); 139*0Sstevel@tonic-gate } 140*0Sstevel@tonic-gate 141*0Sstevel@tonic-gate 142*0Sstevel@tonic-gate /* parse a comma separated gid list */ 143*0Sstevel@tonic-gate static int 144*0Sstevel@tonic-gate parse_gidlist(p, argp) 145*0Sstevel@tonic-gate char *p; 146*0Sstevel@tonic-gate struct netid_userdata *argp; 147*0Sstevel@tonic-gate { 148*0Sstevel@tonic-gate int len; 149*0Sstevel@tonic-gate gid_t g; 150*0Sstevel@tonic-gate 151*0Sstevel@tonic-gate trace1(TR_parse_gidlist, 0); 152*0Sstevel@tonic-gate if (! p || (! isdigit(*p))) { 153*0Sstevel@tonic-gate syslog(LOG_ERR, 154*0Sstevel@tonic-gate "netname2user: missing group id list in '%s'.", 155*0Sstevel@tonic-gate p); 156*0Sstevel@tonic-gate trace1(TR_parse_gidlist, 1); 157*0Sstevel@tonic-gate return (__NSW_NOTFOUND); 158*0Sstevel@tonic-gate } 159*0Sstevel@tonic-gate 160*0Sstevel@tonic-gate g = (gid_t)(atoi(p)); 161*0Sstevel@tonic-gate *(argp->gidp) = g; 162*0Sstevel@tonic-gate 163*0Sstevel@tonic-gate len = 0; 164*0Sstevel@tonic-gate while (p = strchr(p, ',')) 165*0Sstevel@tonic-gate argp->gidlist[len++] = (gid_t)atoi(++p); 166*0Sstevel@tonic-gate *(argp->gidlenp) = len; 167*0Sstevel@tonic-gate trace1(TR_parse_gidlist, 1); 168*0Sstevel@tonic-gate return (__NSW_SUCCESS); 169*0Sstevel@tonic-gate } 170*0Sstevel@tonic-gate 171*0Sstevel@tonic-gate 172*0Sstevel@tonic-gate /* 173*0Sstevel@tonic-gate * parse_netid_str() 174*0Sstevel@tonic-gate * 175*0Sstevel@tonic-gate * Parse uid and group information from the passed string. 176*0Sstevel@tonic-gate * 177*0Sstevel@tonic-gate * The format of the string passed is 178*0Sstevel@tonic-gate * uid:gid,grp,grp, ... 179*0Sstevel@tonic-gate * 180*0Sstevel@tonic-gate */ 181*0Sstevel@tonic-gate static int 182*0Sstevel@tonic-gate parse_netid_str(s, argp) 183*0Sstevel@tonic-gate char *s; 184*0Sstevel@tonic-gate struct netid_userdata *argp; 185*0Sstevel@tonic-gate { 186*0Sstevel@tonic-gate char *p; 187*0Sstevel@tonic-gate int err; 188*0Sstevel@tonic-gate 189*0Sstevel@tonic-gate trace1(TR_parse_netid_str, 0); 190*0Sstevel@tonic-gate 191*0Sstevel@tonic-gate /* get uid */ 192*0Sstevel@tonic-gate err = parse_uid(s, argp); 193*0Sstevel@tonic-gate if (err != __NSW_SUCCESS) { 194*0Sstevel@tonic-gate trace1(TR_parse_netid_str, 1); 195*0Sstevel@tonic-gate return (err); 196*0Sstevel@tonic-gate } 197*0Sstevel@tonic-gate 198*0Sstevel@tonic-gate 199*0Sstevel@tonic-gate /* Now get the group list */ 200*0Sstevel@tonic-gate p = strchr(s, ':'); 201*0Sstevel@tonic-gate if (!p) { 202*0Sstevel@tonic-gate syslog(LOG_ERR, 203*0Sstevel@tonic-gate "netname2user: missing group id list in '%s'", 204*0Sstevel@tonic-gate s); 205*0Sstevel@tonic-gate trace1(TR_parse_netid_str, 1); 206*0Sstevel@tonic-gate return (__NSW_NOTFOUND); 207*0Sstevel@tonic-gate } 208*0Sstevel@tonic-gate ++p; /* skip ':' */ 209*0Sstevel@tonic-gate err = parse_gidlist(p, argp); 210*0Sstevel@tonic-gate trace1(TR_parse_netid_str, 1); 211*0Sstevel@tonic-gate return (err); 212*0Sstevel@tonic-gate } 213*0Sstevel@tonic-gate 214*0Sstevel@tonic-gate static int 215*0Sstevel@tonic-gate parse_uid_gidlist(ustr, gstr, argp) 216*0Sstevel@tonic-gate char *ustr; 217*0Sstevel@tonic-gate char *gstr; 218*0Sstevel@tonic-gate struct netid_userdata *argp; 219*0Sstevel@tonic-gate { 220*0Sstevel@tonic-gate int err; 221*0Sstevel@tonic-gate 222*0Sstevel@tonic-gate trace1(TR_parse_uid_gidlist, 0); 223*0Sstevel@tonic-gate 224*0Sstevel@tonic-gate /* get uid */ 225*0Sstevel@tonic-gate err = parse_uid(ustr, argp); 226*0Sstevel@tonic-gate if (err != __NSW_SUCCESS) { 227*0Sstevel@tonic-gate trace1(TR_parse_uid_gidlist, 1); 228*0Sstevel@tonic-gate return (err); 229*0Sstevel@tonic-gate } 230*0Sstevel@tonic-gate 231*0Sstevel@tonic-gate /* Now get the group list */ 232*0Sstevel@tonic-gate err = parse_gidlist(gstr, argp); 233*0Sstevel@tonic-gate trace1(TR_parse_uid_gidlist, 1); 234*0Sstevel@tonic-gate return (err); 235*0Sstevel@tonic-gate } 236*0Sstevel@tonic-gate 237*0Sstevel@tonic-gate 238*0Sstevel@tonic-gate /* 239*0Sstevel@tonic-gate * netname2user_files() 240*0Sstevel@tonic-gate * 241*0Sstevel@tonic-gate * This routine fetches the netid information from the "files" nameservice. 242*0Sstevel@tonic-gate * ie /etc/netid. 243*0Sstevel@tonic-gate */ 244*0Sstevel@tonic-gate static int 245*0Sstevel@tonic-gate netname2user_files(err, netname, argp) 246*0Sstevel@tonic-gate int *err; 247*0Sstevel@tonic-gate char *netname; 248*0Sstevel@tonic-gate struct netid_userdata *argp; 249*0Sstevel@tonic-gate { 250*0Sstevel@tonic-gate char buf[512]; /* one line from the file */ 251*0Sstevel@tonic-gate char *name; 252*0Sstevel@tonic-gate char *value; 253*0Sstevel@tonic-gate char *res; 254*0Sstevel@tonic-gate __NSL_FILE *fd; 255*0Sstevel@tonic-gate 256*0Sstevel@tonic-gate trace1(TR_netname2user_files, 0); 257*0Sstevel@tonic-gate fd = __nsl_fopen(NETIDFILE, "r"); 258*0Sstevel@tonic-gate if (fd == (__NSL_FILE *)0) { 259*0Sstevel@tonic-gate *err = __NSW_UNAVAIL; 260*0Sstevel@tonic-gate trace1(TR_netname2user_files, 1); 261*0Sstevel@tonic-gate return (0); 262*0Sstevel@tonic-gate } 263*0Sstevel@tonic-gate /* 264*0Sstevel@tonic-gate * for each line in the file parse it appropriately 265*0Sstevel@tonic-gate * file format is : 266*0Sstevel@tonic-gate * netid uid:grp,grp,grp # for users 267*0Sstevel@tonic-gate * netid 0:hostname # for hosts 268*0Sstevel@tonic-gate */ 269*0Sstevel@tonic-gate while (! __nsl_feof(fd)) { 270*0Sstevel@tonic-gate res = __nsl_fgets(buf, 512, fd); 271*0Sstevel@tonic-gate if (res == NULL) 272*0Sstevel@tonic-gate break; 273*0Sstevel@tonic-gate 274*0Sstevel@tonic-gate /* Skip comments and blank lines */ 275*0Sstevel@tonic-gate if ((*res == '#') || (*res == '\n')) 276*0Sstevel@tonic-gate continue; 277*0Sstevel@tonic-gate 278*0Sstevel@tonic-gate name = &(buf[0]); 279*0Sstevel@tonic-gate while (isspace(*name)) 280*0Sstevel@tonic-gate name++; 281*0Sstevel@tonic-gate if (*name == '\0') /* blank line continue */ 282*0Sstevel@tonic-gate continue; 283*0Sstevel@tonic-gate value = name; /* will contain the value eventually */ 284*0Sstevel@tonic-gate while (! isspace(*value)) 285*0Sstevel@tonic-gate value++; 286*0Sstevel@tonic-gate if (*value == '\0') { 287*0Sstevel@tonic-gate syslog(LOG_WARNING, 288*0Sstevel@tonic-gate "netname2user: badly formatted line in %s.", 289*0Sstevel@tonic-gate NETIDFILE); 290*0Sstevel@tonic-gate continue; 291*0Sstevel@tonic-gate } 292*0Sstevel@tonic-gate *value++ = '\0'; /* nul terminate the name */ 293*0Sstevel@tonic-gate 294*0Sstevel@tonic-gate if (strcasecmp(name, netname) == 0) { 295*0Sstevel@tonic-gate __nsl_fclose(fd); 296*0Sstevel@tonic-gate while (isspace(*value)) 297*0Sstevel@tonic-gate value++; 298*0Sstevel@tonic-gate *err = parse_netid_str(value, argp); 299*0Sstevel@tonic-gate trace1(TR_netname2user_files, 1); 300*0Sstevel@tonic-gate return (*err == __NSW_SUCCESS); 301*0Sstevel@tonic-gate } 302*0Sstevel@tonic-gate } 303*0Sstevel@tonic-gate __nsl_fclose(fd); 304*0Sstevel@tonic-gate *err = __NSW_NOTFOUND; 305*0Sstevel@tonic-gate trace1(TR_netname2user_files, 1); 306*0Sstevel@tonic-gate return (0); 307*0Sstevel@tonic-gate } 308*0Sstevel@tonic-gate 309*0Sstevel@tonic-gate /* 310*0Sstevel@tonic-gate * netname2user_nis() 311*0Sstevel@tonic-gate * 312*0Sstevel@tonic-gate * This function reads the netid from the NIS (YP) nameservice. 313*0Sstevel@tonic-gate */ 314*0Sstevel@tonic-gate static int 315*0Sstevel@tonic-gate netname2user_nis(err, netname, argp) 316*0Sstevel@tonic-gate int *err; 317*0Sstevel@tonic-gate char *netname; 318*0Sstevel@tonic-gate struct netid_userdata *argp; 319*0Sstevel@tonic-gate { 320*0Sstevel@tonic-gate char *domain; 321*0Sstevel@tonic-gate int yperr; 322*0Sstevel@tonic-gate char *lookup; 323*0Sstevel@tonic-gate int len; 324*0Sstevel@tonic-gate 325*0Sstevel@tonic-gate trace1(TR_netname2user_nis, 0); 326*0Sstevel@tonic-gate domain = strchr(netname, '@'); 327*0Sstevel@tonic-gate if (! domain) { 328*0Sstevel@tonic-gate *err = __NSW_UNAVAIL; 329*0Sstevel@tonic-gate trace1(TR_netname2user_nis, 1); 330*0Sstevel@tonic-gate return (0); 331*0Sstevel@tonic-gate } 332*0Sstevel@tonic-gate 333*0Sstevel@tonic-gate /* Point past the '@' character */ 334*0Sstevel@tonic-gate domain++; 335*0Sstevel@tonic-gate lookup = NULL; 336*0Sstevel@tonic-gate yperr = yp_match(domain, (char *)NETID, netname, strlen(netname), 337*0Sstevel@tonic-gate &lookup, &len); 338*0Sstevel@tonic-gate switch (yperr) { 339*0Sstevel@tonic-gate case 0: 340*0Sstevel@tonic-gate break; /* the successful case */ 341*0Sstevel@tonic-gate 342*0Sstevel@tonic-gate default : 343*0Sstevel@tonic-gate /* 344*0Sstevel@tonic-gate * XXX not sure about yp_match semantics. 345*0Sstevel@tonic-gate * should err be set to NOTFOUND here? 346*0Sstevel@tonic-gate */ 347*0Sstevel@tonic-gate *err = __NSW_UNAVAIL; 348*0Sstevel@tonic-gate trace1(TR_netname2user_nis, 1); 349*0Sstevel@tonic-gate return (0); 350*0Sstevel@tonic-gate } 351*0Sstevel@tonic-gate if (lookup) { 352*0Sstevel@tonic-gate lookup[len] = '\0'; 353*0Sstevel@tonic-gate *err = parse_netid_str(lookup, argp); 354*0Sstevel@tonic-gate free(lookup); 355*0Sstevel@tonic-gate trace1(TR_netname2user_nis, 1); 356*0Sstevel@tonic-gate return (*err == __NSW_SUCCESS); 357*0Sstevel@tonic-gate } else { 358*0Sstevel@tonic-gate trace1(TR_netname2user_nis, 1); 359*0Sstevel@tonic-gate *err = __NSW_NOTFOUND; 360*0Sstevel@tonic-gate return (0); 361*0Sstevel@tonic-gate } 362*0Sstevel@tonic-gate } 363*0Sstevel@tonic-gate 364*0Sstevel@tonic-gate /* 365*0Sstevel@tonic-gate * Obtain user information (uid, gidlist) from nisplus. 366*0Sstevel@tonic-gate * What we're trying to do here is to map a netname into 367*0Sstevel@tonic-gate * local unix information (uid, gids), relevant in 368*0Sstevel@tonic-gate * the *local* domain. 369*0Sstevel@tonic-gate * 370*0Sstevel@tonic-gate * cname auth_type auth_name public private 371*0Sstevel@tonic-gate * ---------------------------------------------------------- 372*0Sstevel@tonic-gate * nisname DES netname pubkey prikey 373*0Sstevel@tonic-gate * nisname LOCAL uid gidlist 374*0Sstevel@tonic-gate * 375*0Sstevel@tonic-gate * 1. Find out which 'home' domain to look for user's DES entry. 376*0Sstevel@tonic-gate * This is gotten from the domain part of the netname. 377*0Sstevel@tonic-gate * 2. Get the nisplus principal name from the DES entry in the cred 378*0Sstevel@tonic-gate * table of user's home domain. 379*0Sstevel@tonic-gate * 3. Use the nisplus principal name and search in the cred table of 380*0Sstevel@tonic-gate * the *local* directory for the LOCAL entry. 381*0Sstevel@tonic-gate * 382*0Sstevel@tonic-gate * Note that we need this translation of netname to <uid,gidlist> to be 383*0Sstevel@tonic-gate * secure, so we *must* use authenticated connections. 384*0Sstevel@tonic-gate */ 385*0Sstevel@tonic-gate static int 386*0Sstevel@tonic-gate netname2user_nisplus(err, netname, argp) 387*0Sstevel@tonic-gate int *err; 388*0Sstevel@tonic-gate char *netname; 389*0Sstevel@tonic-gate struct netid_userdata *argp; 390*0Sstevel@tonic-gate { 391*0Sstevel@tonic-gate char *domain; 392*0Sstevel@tonic-gate nis_result *res; 393*0Sstevel@tonic-gate char sname[NIS_MAXNAMELEN+1]; /* search criteria + table name */ 394*0Sstevel@tonic-gate char principal[NIS_MAXNAMELEN+1]; 395*0Sstevel@tonic-gate int len; 396*0Sstevel@tonic-gate 397*0Sstevel@tonic-gate trace1(TR_netname2user_nisplus, 0); 398*0Sstevel@tonic-gate 399*0Sstevel@tonic-gate 400*0Sstevel@tonic-gate /* 1. Get home domain of user. */ 401*0Sstevel@tonic-gate domain = strchr(netname, '@'); 402*0Sstevel@tonic-gate if (! domain) { 403*0Sstevel@tonic-gate *err = __NSW_UNAVAIL; 404*0Sstevel@tonic-gate trace1(TR_netname2user_nisplus, 1); 405*0Sstevel@tonic-gate return (0); 406*0Sstevel@tonic-gate } 407*0Sstevel@tonic-gate domain++; /* skip '@' */ 408*0Sstevel@tonic-gate 409*0Sstevel@tonic-gate 410*0Sstevel@tonic-gate /* 2. Get user's nisplus principal name. */ 411*0Sstevel@tonic-gate if ((strlen(netname)+strlen(domain)+PKTABLE_LEN+32) > 412*0Sstevel@tonic-gate (size_t)NIS_MAXNAMELEN) { 413*0Sstevel@tonic-gate *err = __NSW_UNAVAIL; 414*0Sstevel@tonic-gate trace1(TR_netname2user_nisplus, 1); 415*0Sstevel@tonic-gate return (0); 416*0Sstevel@tonic-gate } 417*0Sstevel@tonic-gate sprintf(sname, "[auth_name=\"%s\",auth_type=DES],%s.%s", 418*0Sstevel@tonic-gate netname, PKTABLE, domain); 419*0Sstevel@tonic-gate if (sname[strlen(sname) - 1] != '.') 420*0Sstevel@tonic-gate strcat(sname, "."); 421*0Sstevel@tonic-gate 422*0Sstevel@tonic-gate /* must use authenticated call here */ 423*0Sstevel@tonic-gate /* XXX but we cant, for now. XXX */ 424*0Sstevel@tonic-gate res = nis_list(sname, USE_DGRAM+NO_AUTHINFO+FOLLOW_LINKS+FOLLOW_PATH, 425*0Sstevel@tonic-gate NULL, NULL); 426*0Sstevel@tonic-gate switch (res->status) { 427*0Sstevel@tonic-gate case NIS_SUCCESS: 428*0Sstevel@tonic-gate case NIS_S_SUCCESS: 429*0Sstevel@tonic-gate break; /* go and do something useful */ 430*0Sstevel@tonic-gate case NIS_NOTFOUND: 431*0Sstevel@tonic-gate case NIS_PARTIAL: 432*0Sstevel@tonic-gate case NIS_NOSUCHNAME: 433*0Sstevel@tonic-gate case NIS_NOSUCHTABLE: 434*0Sstevel@tonic-gate *err = __NSW_NOTFOUND; 435*0Sstevel@tonic-gate nis_freeresult(res); 436*0Sstevel@tonic-gate trace1(TR_netname2user_nisplus, 1); 437*0Sstevel@tonic-gate return (0); 438*0Sstevel@tonic-gate case NIS_S_NOTFOUND: 439*0Sstevel@tonic-gate case NIS_TRYAGAIN: 440*0Sstevel@tonic-gate *err = __NSW_TRYAGAIN; 441*0Sstevel@tonic-gate syslog(LOG_ERR, 442*0Sstevel@tonic-gate "netname2user: (nis+ lookup): %s\n", 443*0Sstevel@tonic-gate nis_sperrno(res->status)); 444*0Sstevel@tonic-gate nis_freeresult(res); 445*0Sstevel@tonic-gate trace1(TR_netname2user_nisplus, 1); 446*0Sstevel@tonic-gate return (0); 447*0Sstevel@tonic-gate default: 448*0Sstevel@tonic-gate *err = __NSW_UNAVAIL; 449*0Sstevel@tonic-gate syslog(LOG_ERR, "netname2user: (nis+ lookup): %s\n", 450*0Sstevel@tonic-gate nis_sperrno(res->status)); 451*0Sstevel@tonic-gate nis_freeresult(res); 452*0Sstevel@tonic-gate trace1(TR_netname2user_nisplus, 1); 453*0Sstevel@tonic-gate return (0); 454*0Sstevel@tonic-gate } 455*0Sstevel@tonic-gate 456*0Sstevel@tonic-gate if (res->objects.objects_len > 1) { 457*0Sstevel@tonic-gate /* 458*0Sstevel@tonic-gate * A netname belonging to more than one principal? 459*0Sstevel@tonic-gate * Something wrong with cred table. should be unique. 460*0Sstevel@tonic-gate * Warn user and continue. 461*0Sstevel@tonic-gate */ 462*0Sstevel@tonic-gate syslog(LOG_ALERT, 463*0Sstevel@tonic-gate "netname2user: DES entry for %s in \ 464*0Sstevel@tonic-gate directory %s not unique", 465*0Sstevel@tonic-gate netname, domain); 466*0Sstevel@tonic-gate } 467*0Sstevel@tonic-gate 468*0Sstevel@tonic-gate len = ENTRY_LEN(res->objects.objects_val, 0); 469*0Sstevel@tonic-gate strncpy(principal, ENTRY_VAL(res->objects.objects_val, 0), len); 470*0Sstevel@tonic-gate principal[len] = '\0'; 471*0Sstevel@tonic-gate nis_freeresult(res); 472*0Sstevel@tonic-gate 473*0Sstevel@tonic-gate if (principal[0] == '\0') { 474*0Sstevel@tonic-gate *err = __NSW_UNAVAIL; 475*0Sstevel@tonic-gate trace1(TR_netname2user_nisplus, 1); 476*0Sstevel@tonic-gate return (0); 477*0Sstevel@tonic-gate } 478*0Sstevel@tonic-gate 479*0Sstevel@tonic-gate /* 480*0Sstevel@tonic-gate * 3. Use principal name to look up uid/gid information in 481*0Sstevel@tonic-gate * LOCAL entry in **local** cred table. 482*0Sstevel@tonic-gate */ 483*0Sstevel@tonic-gate domain = nis_local_directory(); 484*0Sstevel@tonic-gate if ((strlen(principal)+strlen(domain)+PKTABLE_LEN+30) > 485*0Sstevel@tonic-gate (size_t)NIS_MAXNAMELEN) { 486*0Sstevel@tonic-gate *err = __NSW_UNAVAIL; 487*0Sstevel@tonic-gate syslog(LOG_ERR, "netname2user: principal name '%s' too long", 488*0Sstevel@tonic-gate principal); 489*0Sstevel@tonic-gate trace1(TR_netname2user_nisplus, 1); 490*0Sstevel@tonic-gate return (0); 491*0Sstevel@tonic-gate } 492*0Sstevel@tonic-gate sprintf(sname, "[cname=\"%s\",auth_type=LOCAL],%s.%s", 493*0Sstevel@tonic-gate principal, PKTABLE, domain); 494*0Sstevel@tonic-gate if (sname[strlen(sname) - 1] != '.') 495*0Sstevel@tonic-gate strcat(sname, "."); 496*0Sstevel@tonic-gate 497*0Sstevel@tonic-gate /* must use authenticated call here */ 498*0Sstevel@tonic-gate /* XXX but we cant, for now. XXX */ 499*0Sstevel@tonic-gate res = nis_list(sname, USE_DGRAM+NO_AUTHINFO+FOLLOW_LINKS+FOLLOW_PATH, 500*0Sstevel@tonic-gate NULL, NULL); 501*0Sstevel@tonic-gate switch (res->status) { 502*0Sstevel@tonic-gate case NIS_NOTFOUND: 503*0Sstevel@tonic-gate case NIS_PARTIAL: 504*0Sstevel@tonic-gate case NIS_NOSUCHNAME: 505*0Sstevel@tonic-gate case NIS_NOSUCHTABLE: 506*0Sstevel@tonic-gate *err = __NSW_NOTFOUND; 507*0Sstevel@tonic-gate nis_freeresult(res); 508*0Sstevel@tonic-gate trace1(TR_netname2user_nisplus, 1); 509*0Sstevel@tonic-gate return (0); 510*0Sstevel@tonic-gate case NIS_S_NOTFOUND: 511*0Sstevel@tonic-gate case NIS_TRYAGAIN: 512*0Sstevel@tonic-gate *err = __NSW_TRYAGAIN; 513*0Sstevel@tonic-gate syslog(LOG_ERR, 514*0Sstevel@tonic-gate "netname2user: (nis+ lookup): %s\n", 515*0Sstevel@tonic-gate nis_sperrno(res->status)); 516*0Sstevel@tonic-gate nis_freeresult(res); 517*0Sstevel@tonic-gate trace1(TR_netname2user_nisplus, 1); 518*0Sstevel@tonic-gate return (0); 519*0Sstevel@tonic-gate case NIS_SUCCESS: 520*0Sstevel@tonic-gate case NIS_S_SUCCESS: 521*0Sstevel@tonic-gate break; /* go and do something useful */ 522*0Sstevel@tonic-gate default: 523*0Sstevel@tonic-gate *err = __NSW_UNAVAIL; 524*0Sstevel@tonic-gate syslog(LOG_ERR, "netname2user: (nis+ lookup): %s\n", 525*0Sstevel@tonic-gate nis_sperrno(res->status)); 526*0Sstevel@tonic-gate nis_freeresult(res); 527*0Sstevel@tonic-gate trace1(TR_netname2user_nisplus, 1); 528*0Sstevel@tonic-gate return (0); 529*0Sstevel@tonic-gate } 530*0Sstevel@tonic-gate 531*0Sstevel@tonic-gate if (res->objects.objects_len > 1) { 532*0Sstevel@tonic-gate /* 533*0Sstevel@tonic-gate * A principal can have more than one LOCAL entry? 534*0Sstevel@tonic-gate * Something wrong with cred table. 535*0Sstevel@tonic-gate * Warn user and continue. 536*0Sstevel@tonic-gate */ 537*0Sstevel@tonic-gate syslog(LOG_ALERT, 538*0Sstevel@tonic-gate "netname2user: LOCAL entry for %s in\ 539*0Sstevel@tonic-gate directory %s not unique", 540*0Sstevel@tonic-gate netname, domain); 541*0Sstevel@tonic-gate } 542*0Sstevel@tonic-gate /* nisname LOCAL uid grp,grp,grp */ 543*0Sstevel@tonic-gate *err = parse_uid_gidlist(ENTRY_VAL(res->objects.objects_val, 2), 544*0Sstevel@tonic-gate /* uid */ 545*0Sstevel@tonic-gate ENTRY_VAL(res->objects.objects_val, 3), /* gids */ 546*0Sstevel@tonic-gate argp); 547*0Sstevel@tonic-gate nis_freeresult(res); 548*0Sstevel@tonic-gate trace1(TR_netname2user_nisplus, 1); 549*0Sstevel@tonic-gate return (*err == __NSW_SUCCESS); 550*0Sstevel@tonic-gate } 551*0Sstevel@tonic-gate 552*0Sstevel@tonic-gate /* 553*0Sstevel@tonic-gate * Build the uid and gid from the netname for users in LDAP. 554*0Sstevel@tonic-gate * There is no netid container in LDAP. For this we build 555*0Sstevel@tonic-gate * the netname to user data dynamically from the passwd and 556*0Sstevel@tonic-gate * group data. This works only for users in a single domain. 557*0Sstevel@tonic-gate * This function is an interim solution until we support a 558*0Sstevel@tonic-gate * netid container in LDAP which enables us to do netname2user 559*0Sstevel@tonic-gate * resolution for multiple domains. 560*0Sstevel@tonic-gate */ 561*0Sstevel@tonic-gate static int 562*0Sstevel@tonic-gate netname2user_ldap(err, netname, argp) 563*0Sstevel@tonic-gate int *err; 564*0Sstevel@tonic-gate char *netname; 565*0Sstevel@tonic-gate struct netid_userdata *argp; 566*0Sstevel@tonic-gate { 567*0Sstevel@tonic-gate 568*0Sstevel@tonic-gate char buf[NSS_LINELEN_PASSWD]; 569*0Sstevel@tonic-gate char *p1, *p2, *lasts; 570*0Sstevel@tonic-gate struct passwd pw; 571*0Sstevel@tonic-gate uid_t uidnu; 572*0Sstevel@tonic-gate int ngroups = 0; 573*0Sstevel@tonic-gate int count; 574*0Sstevel@tonic-gate char pwbuf[NSS_LINELEN_PASSWD]; 575*0Sstevel@tonic-gate gid_t groups[NGROUPS_MAX]; 576*0Sstevel@tonic-gate 577*0Sstevel@tonic-gate if (strlcpy(buf, netname, NSS_LINELEN_PASSWD) >= NSS_LINELEN_PASSWD) { 578*0Sstevel@tonic-gate *err = __NSW_UNAVAIL; 579*0Sstevel@tonic-gate return (0); 580*0Sstevel@tonic-gate } 581*0Sstevel@tonic-gate 582*0Sstevel@tonic-gate /* get the uid from the netname */ 583*0Sstevel@tonic-gate if ((p1 = strtok_r(buf, ".", &lasts)) == NULL) { 584*0Sstevel@tonic-gate *err = __NSW_UNAVAIL; 585*0Sstevel@tonic-gate return (0); 586*0Sstevel@tonic-gate } 587*0Sstevel@tonic-gate if ((p2 = strtok_r(NULL, "@", &lasts)) == NULL) { 588*0Sstevel@tonic-gate *err = __NSW_UNAVAIL; 589*0Sstevel@tonic-gate return (0); 590*0Sstevel@tonic-gate } 591*0Sstevel@tonic-gate uidnu = atoi(p2); 592*0Sstevel@tonic-gate 593*0Sstevel@tonic-gate /* 594*0Sstevel@tonic-gate * check out the primary group and crosscheck the uid 595*0Sstevel@tonic-gate * with the passwd data 596*0Sstevel@tonic-gate */ 597*0Sstevel@tonic-gate if ((getpwuid_r(uidnu, &pw, pwbuf, sizeof (pwbuf))) == NULL) { 598*0Sstevel@tonic-gate *err = __NSW_UNAVAIL; 599*0Sstevel@tonic-gate return (0); 600*0Sstevel@tonic-gate } 601*0Sstevel@tonic-gate 602*0Sstevel@tonic-gate *(argp->uidp) = pw.pw_uid; 603*0Sstevel@tonic-gate *(argp->gidp) = pw.pw_gid; 604*0Sstevel@tonic-gate 605*0Sstevel@tonic-gate /* search through all groups for membership */ 606*0Sstevel@tonic-gate 607*0Sstevel@tonic-gate groups[0] = pw.pw_gid; 608*0Sstevel@tonic-gate 609*0Sstevel@tonic-gate ngroups = _getgroupsbymember(pw.pw_name, groups, NGROUPS_MAX, 610*0Sstevel@tonic-gate (pw.pw_gid >= 0) ? 1 : 0); 611*0Sstevel@tonic-gate 612*0Sstevel@tonic-gate if (ngroups < 0) { 613*0Sstevel@tonic-gate *err = __NSW_UNAVAIL; 614*0Sstevel@tonic-gate return (0); 615*0Sstevel@tonic-gate } 616*0Sstevel@tonic-gate 617*0Sstevel@tonic-gate *(argp->gidlenp) = ngroups; 618*0Sstevel@tonic-gate 619*0Sstevel@tonic-gate for (count = 0; count < ngroups; count++) { 620*0Sstevel@tonic-gate (argp->gidlist[count]) = groups[count]; 621*0Sstevel@tonic-gate } 622*0Sstevel@tonic-gate 623*0Sstevel@tonic-gate *err = __NSW_SUCCESS; 624*0Sstevel@tonic-gate return (1); 625*0Sstevel@tonic-gate 626*0Sstevel@tonic-gate } 627*0Sstevel@tonic-gate 628*0Sstevel@tonic-gate /* 629*0Sstevel@tonic-gate * Convert network-name into unix credential 630*0Sstevel@tonic-gate */ 631*0Sstevel@tonic-gate int 632*0Sstevel@tonic-gate netname2user(netname, uidp, gidp, gidlenp, gidlist) 633*0Sstevel@tonic-gate const char netname[MAXNETNAMELEN + 1]; 634*0Sstevel@tonic-gate uid_t *uidp; 635*0Sstevel@tonic-gate gid_t *gidp; 636*0Sstevel@tonic-gate int *gidlenp; 637*0Sstevel@tonic-gate gid_t *gidlist; 638*0Sstevel@tonic-gate { 639*0Sstevel@tonic-gate struct __nsw_switchconfig *conf; 640*0Sstevel@tonic-gate struct __nsw_lookup *look; 641*0Sstevel@tonic-gate enum __nsw_parse_err perr; 642*0Sstevel@tonic-gate int needfree = 1, res; 643*0Sstevel@tonic-gate struct netid_userdata argp; 644*0Sstevel@tonic-gate int err; 645*0Sstevel@tonic-gate 646*0Sstevel@tonic-gate trace1(TR_netname2user, 0); 647*0Sstevel@tonic-gate 648*0Sstevel@tonic-gate /* 649*0Sstevel@tonic-gate * Take care of the special case of nobody. Compare the netname 650*0Sstevel@tonic-gate * to the string "nobody". If they are equal, return the SVID 651*0Sstevel@tonic-gate * standard value for nobody. 652*0Sstevel@tonic-gate */ 653*0Sstevel@tonic-gate 654*0Sstevel@tonic-gate if (strcmp(netname, "nobody") == 0) { 655*0Sstevel@tonic-gate *uidp = NOBODY_UID; 656*0Sstevel@tonic-gate *gidp = NOBODY_UID; 657*0Sstevel@tonic-gate *gidlenp = 0; 658*0Sstevel@tonic-gate return (1); 659*0Sstevel@tonic-gate } 660*0Sstevel@tonic-gate 661*0Sstevel@tonic-gate /* 662*0Sstevel@tonic-gate * First we do some generic sanity checks on the name we were 663*0Sstevel@tonic-gate * passed. This lets us assume they are correct in the backends. 664*0Sstevel@tonic-gate * 665*0Sstevel@tonic-gate * NOTE: this code only recognizes names of the form : 666*0Sstevel@tonic-gate * unix.UID@domainname 667*0Sstevel@tonic-gate */ 668*0Sstevel@tonic-gate if (strncmp(netname, OPSYS, OPSYS_LEN) != 0) { 669*0Sstevel@tonic-gate trace1(TR_netname2user, 1); 670*0Sstevel@tonic-gate return (0); 671*0Sstevel@tonic-gate } 672*0Sstevel@tonic-gate if (! isdigit(netname[OPSYS_LEN+1])) { /* check for uid string */ 673*0Sstevel@tonic-gate trace1(TR_netname2user, 1); 674*0Sstevel@tonic-gate return (0); 675*0Sstevel@tonic-gate } 676*0Sstevel@tonic-gate 677*0Sstevel@tonic-gate argp.uidp = uidp; 678*0Sstevel@tonic-gate argp.gidp = gidp; 679*0Sstevel@tonic-gate argp.gidlenp = gidlenp; 680*0Sstevel@tonic-gate argp.gidlist = gidlist; 681*0Sstevel@tonic-gate mutex_lock(&serialize_netname_r); 682*0Sstevel@tonic-gate 683*0Sstevel@tonic-gate conf = __nsw_getconfig("publickey", &perr); 684*0Sstevel@tonic-gate if (! conf) { 685*0Sstevel@tonic-gate conf = &publickey_default; 686*0Sstevel@tonic-gate needfree = 0; 687*0Sstevel@tonic-gate } else 688*0Sstevel@tonic-gate needfree = 1; /* free the config structure */ 689*0Sstevel@tonic-gate 690*0Sstevel@tonic-gate for (look = conf->lookups; look; look = look->next) { 691*0Sstevel@tonic-gate if (strcmp(look->service_name, "nisplus") == 0) 692*0Sstevel@tonic-gate res = netname2user_nisplus(&err, 693*0Sstevel@tonic-gate (char *)netname, &argp); 694*0Sstevel@tonic-gate else if (strcmp(look->service_name, "nis") == 0) 695*0Sstevel@tonic-gate res = netname2user_nis(&err, (char *)netname, &argp); 696*0Sstevel@tonic-gate else if (strcmp(look->service_name, "files") == 0) 697*0Sstevel@tonic-gate res = netname2user_files(&err, (char *)netname, &argp); 698*0Sstevel@tonic-gate else if (strcmp(look->service_name, "ldap") == 0) 699*0Sstevel@tonic-gate res = netname2user_ldap(&err, (char *)netname, &argp); 700*0Sstevel@tonic-gate else { 701*0Sstevel@tonic-gate syslog(LOG_INFO, 702*0Sstevel@tonic-gate "netname2user: unknown nameservice for publickey info '%s'\n", 703*0Sstevel@tonic-gate look->service_name); 704*0Sstevel@tonic-gate err = __NSW_UNAVAIL; 705*0Sstevel@tonic-gate } 706*0Sstevel@tonic-gate switch (look->actions[err]) { 707*0Sstevel@tonic-gate case __NSW_CONTINUE : 708*0Sstevel@tonic-gate break; 709*0Sstevel@tonic-gate case __NSW_RETURN : 710*0Sstevel@tonic-gate if (needfree) 711*0Sstevel@tonic-gate __nsw_freeconfig(conf); 712*0Sstevel@tonic-gate mutex_unlock(&serialize_netname_r); 713*0Sstevel@tonic-gate trace1(TR_netname2user, 1); 714*0Sstevel@tonic-gate return (res); 715*0Sstevel@tonic-gate default : 716*0Sstevel@tonic-gate syslog(LOG_ERR, 717*0Sstevel@tonic-gate "netname2user: Unknown action for nameservice '%s'", 718*0Sstevel@tonic-gate look->service_name); 719*0Sstevel@tonic-gate } 720*0Sstevel@tonic-gate } 721*0Sstevel@tonic-gate if (needfree) 722*0Sstevel@tonic-gate __nsw_freeconfig(conf); 723*0Sstevel@tonic-gate mutex_unlock(&serialize_netname_r); 724*0Sstevel@tonic-gate trace1(TR_netname2user, 1); 725*0Sstevel@tonic-gate return (0); 726*0Sstevel@tonic-gate } 727*0Sstevel@tonic-gate 728*0Sstevel@tonic-gate /* 729*0Sstevel@tonic-gate * Convert network-name to hostname (fully qualified) 730*0Sstevel@tonic-gate * NOTE: this code only recognizes names of the form : 731*0Sstevel@tonic-gate * unix.HOST@domainname 732*0Sstevel@tonic-gate * 733*0Sstevel@tonic-gate * This is very simple. Since the netname is of the form: 734*0Sstevel@tonic-gate * unix.host@domainname 735*0Sstevel@tonic-gate * We just construct the hostname using information from the domainname. 736*0Sstevel@tonic-gate */ 737*0Sstevel@tonic-gate int 738*0Sstevel@tonic-gate netname2host(netname, hostname, hostlen) 739*0Sstevel@tonic-gate const char netname[MAXNETNAMELEN + 1]; 740*0Sstevel@tonic-gate char *hostname; 741*0Sstevel@tonic-gate int hostlen; 742*0Sstevel@tonic-gate { 743*0Sstevel@tonic-gate char *p, *domainname; 744*0Sstevel@tonic-gate int len, dlen; 745*0Sstevel@tonic-gate 746*0Sstevel@tonic-gate trace1(TR_netname2host, 0); 747*0Sstevel@tonic-gate 748*0Sstevel@tonic-gate if (!netname) { 749*0Sstevel@tonic-gate syslog(LOG_ERR, "netname2host: null netname"); 750*0Sstevel@tonic-gate goto bad_exit; 751*0Sstevel@tonic-gate } 752*0Sstevel@tonic-gate 753*0Sstevel@tonic-gate if (strncmp(netname, OPSYS, OPSYS_LEN) != 0) 754*0Sstevel@tonic-gate goto bad_netname; 755*0Sstevel@tonic-gate p = (char *)netname + OPSYS_LEN; /* skip OPSYS part */ 756*0Sstevel@tonic-gate if (*p != '.') 757*0Sstevel@tonic-gate goto bad_netname; 758*0Sstevel@tonic-gate ++p; /* skip '.' */ 759*0Sstevel@tonic-gate 760*0Sstevel@tonic-gate domainname = strchr(p, '@'); /* get domain name */ 761*0Sstevel@tonic-gate if (domainname == 0) 762*0Sstevel@tonic-gate goto bad_netname; 763*0Sstevel@tonic-gate 764*0Sstevel@tonic-gate len = domainname - p; /* host sits between '.' and '@' */ 765*0Sstevel@tonic-gate domainname++; /* skip '@' sign */ 766*0Sstevel@tonic-gate 767*0Sstevel@tonic-gate if (len <= 0) 768*0Sstevel@tonic-gate goto bad_netname; 769*0Sstevel@tonic-gate 770*0Sstevel@tonic-gate if (hostlen < len) { 771*0Sstevel@tonic-gate syslog(LOG_ERR, 772*0Sstevel@tonic-gate "netname2host: insufficient space for hostname"); 773*0Sstevel@tonic-gate goto bad_exit; 774*0Sstevel@tonic-gate } 775*0Sstevel@tonic-gate 776*0Sstevel@tonic-gate if (isdigit(*p)) /* don't want uid here */ 777*0Sstevel@tonic-gate goto bad_netname; 778*0Sstevel@tonic-gate 779*0Sstevel@tonic-gate if (*p == '\0') /* check for null hostname */ 780*0Sstevel@tonic-gate goto bad_netname; 781*0Sstevel@tonic-gate 782*0Sstevel@tonic-gate strncpy(hostname, p, len); 783*0Sstevel@tonic-gate 784*0Sstevel@tonic-gate /* make into fully qualified hostname by concatenating domain part */ 785*0Sstevel@tonic-gate dlen = strlen(domainname); 786*0Sstevel@tonic-gate if (hostlen < (len + dlen + 2)) { 787*0Sstevel@tonic-gate syslog(LOG_ERR, 788*0Sstevel@tonic-gate "netname2host: insufficient space for hostname"); 789*0Sstevel@tonic-gate goto bad_exit; 790*0Sstevel@tonic-gate } 791*0Sstevel@tonic-gate 792*0Sstevel@tonic-gate hostname[len] = '.'; 793*0Sstevel@tonic-gate strncpy(hostname+len+1, domainname, dlen); 794*0Sstevel@tonic-gate hostname[len+dlen+1] = '\0'; 795*0Sstevel@tonic-gate 796*0Sstevel@tonic-gate trace1(TR_netname2host, 1); 797*0Sstevel@tonic-gate return (1); 798*0Sstevel@tonic-gate 799*0Sstevel@tonic-gate 800*0Sstevel@tonic-gate bad_netname: 801*0Sstevel@tonic-gate syslog(LOG_ERR, "netname2host: invalid host netname %s", netname); 802*0Sstevel@tonic-gate 803*0Sstevel@tonic-gate bad_exit: 804*0Sstevel@tonic-gate hostname[0] = '\0'; 805*0Sstevel@tonic-gate trace1(TR_netname2host, 1); 806*0Sstevel@tonic-gate return (0); 807*0Sstevel@tonic-gate } 808