17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5141ae836Speteh * Common Development and Distribution License (the "License"). 6141ae836Speteh * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 2061961e0fSrobinson */ 2161961e0fSrobinson 2261961e0fSrobinson /* 2336e852a1SRaja Andra * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 277c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 287c478bd9Sstevel@tonic-gate /* 297c478bd9Sstevel@tonic-gate * Portions of this source code were derived from Berkeley 307c478bd9Sstevel@tonic-gate * 4.3 BSD under license from the Regents of the University of 317c478bd9Sstevel@tonic-gate * California. 327c478bd9Sstevel@tonic-gate */ 337c478bd9Sstevel@tonic-gate /* 347c478bd9Sstevel@tonic-gate * ==== hack-attack: possibly MT-safe but definitely not MT-hot. 357c478bd9Sstevel@tonic-gate * ==== turn this into a real switch frontend and backends 367c478bd9Sstevel@tonic-gate * 377c478bd9Sstevel@tonic-gate * Well, at least the API doesn't involve pointers-to-static. 387c478bd9Sstevel@tonic-gate */ 397c478bd9Sstevel@tonic-gate 407c478bd9Sstevel@tonic-gate /* 417c478bd9Sstevel@tonic-gate * netname utility routines (getnetname, user2netname, host2netname). 427c478bd9Sstevel@tonic-gate * 437c478bd9Sstevel@tonic-gate * Convert from unix names (uid, gid) to network wide names. 447c478bd9Sstevel@tonic-gate * This module is operating system dependent! 457c478bd9Sstevel@tonic-gate * What we define here will work with any unix system that has adopted 467c478bd9Sstevel@tonic-gate * the Sun NIS domain architecture. 477c478bd9Sstevel@tonic-gate */ 487c478bd9Sstevel@tonic-gate 497c478bd9Sstevel@tonic-gate #undef NIS 507c478bd9Sstevel@tonic-gate 517c478bd9Sstevel@tonic-gate #include "mt.h" 527c478bd9Sstevel@tonic-gate #include "rpc_mt.h" 537c478bd9Sstevel@tonic-gate #include <stdio.h> 547c478bd9Sstevel@tonic-gate #include <stdlib.h> 557c478bd9Sstevel@tonic-gate #include <unistd.h> 567c478bd9Sstevel@tonic-gate #include <sys/types.h> 577c478bd9Sstevel@tonic-gate #include <ctype.h> 587c478bd9Sstevel@tonic-gate #include <string.h> 597c478bd9Sstevel@tonic-gate #include <syslog.h> 607c478bd9Sstevel@tonic-gate #include <sys/param.h> 617c478bd9Sstevel@tonic-gate #include <rpc/rpc.h> 627c478bd9Sstevel@tonic-gate #include <rpcsvc/nis.h> 637c478bd9Sstevel@tonic-gate #include <rpcsvc/nis_dhext.h> 647c478bd9Sstevel@tonic-gate #include <nsswitch.h> 657c478bd9Sstevel@tonic-gate #include <syslog.h> 66141ae836Speteh #include <errno.h> 677c478bd9Sstevel@tonic-gate 687c478bd9Sstevel@tonic-gate #ifndef MAXHOSTNAMELEN 697c478bd9Sstevel@tonic-gate #define MAXHOSTNAMELEN 256 707c478bd9Sstevel@tonic-gate #endif 717c478bd9Sstevel@tonic-gate #ifndef NGROUPS 727c478bd9Sstevel@tonic-gate #define NGROUPS 16 737c478bd9Sstevel@tonic-gate #endif 747c478bd9Sstevel@tonic-gate 757c478bd9Sstevel@tonic-gate /* 767c478bd9Sstevel@tonic-gate * the value for NOBODY_UID is set by the SVID. The following define also 777c478bd9Sstevel@tonic-gate * appears in netnamer.c 787c478bd9Sstevel@tonic-gate */ 797c478bd9Sstevel@tonic-gate 807c478bd9Sstevel@tonic-gate #define NOBODY_UID 60001 817c478bd9Sstevel@tonic-gate 827c478bd9Sstevel@tonic-gate extern int getdomainname(); 837c478bd9Sstevel@tonic-gate extern int key_call(); 847c478bd9Sstevel@tonic-gate #define OPSYS_LEN 4 857c478bd9Sstevel@tonic-gate static const char *OPSYS = "unix"; 867c478bd9Sstevel@tonic-gate 877c478bd9Sstevel@tonic-gate /* 887c478bd9Sstevel@tonic-gate * default publickey policy: 897c478bd9Sstevel@tonic-gate * publickey: nis [NOTFOUND = return] files 907c478bd9Sstevel@tonic-gate */ 917c478bd9Sstevel@tonic-gate 927c478bd9Sstevel@tonic-gate 937c478bd9Sstevel@tonic-gate /* NSW_NOTSUCCESS NSW_NOTFOUND NSW_UNAVAIL NSW_TRYAGAIN */ 947c478bd9Sstevel@tonic-gate #define DEF_ACTION {__NSW_RETURN, __NSW_RETURN, __NSW_CONTINUE, __NSW_CONTINUE} 957c478bd9Sstevel@tonic-gate 967c478bd9Sstevel@tonic-gate static struct __nsw_lookup lookup_files = {"files", DEF_ACTION, NULL, NULL}, 977c478bd9Sstevel@tonic-gate lookup_nis = {"nis", DEF_ACTION, NULL, &lookup_files}; 987c478bd9Sstevel@tonic-gate static struct __nsw_switchconfig publickey_default = 997c478bd9Sstevel@tonic-gate {0, "publickey", 2, &lookup_nis}; 1007c478bd9Sstevel@tonic-gate 101141ae836Speteh static mutex_t serialize_netname = ERRORCHECKMUTEX; 1027c478bd9Sstevel@tonic-gate 1037c478bd9Sstevel@tonic-gate 1047c478bd9Sstevel@tonic-gate #define MAXIPRINT (11) /* max length of printed integer */ 1057c478bd9Sstevel@tonic-gate 1067c478bd9Sstevel@tonic-gate /* 1077c478bd9Sstevel@tonic-gate * Convert unix cred to network-name by concatenating the 1087c478bd9Sstevel@tonic-gate * 3 pieces of information <opsys type> <uid> <domain>. 1097c478bd9Sstevel@tonic-gate */ 1107c478bd9Sstevel@tonic-gate 1117c478bd9Sstevel@tonic-gate static int 11261961e0fSrobinson user2netname_nis(int *err, char netname[MAXNETNAMELEN + 1], uid_t uid, 11361961e0fSrobinson char *domain) 1147c478bd9Sstevel@tonic-gate { 1157c478bd9Sstevel@tonic-gate int i; 1167c478bd9Sstevel@tonic-gate char *dfltdom; 1177c478bd9Sstevel@tonic-gate if (domain == NULL) { 1187c478bd9Sstevel@tonic-gate if (__rpc_get_default_domain(&dfltdom) != 0) { 1197c478bd9Sstevel@tonic-gate *err = __NSW_UNAVAIL; 1207c478bd9Sstevel@tonic-gate return (0); 1217c478bd9Sstevel@tonic-gate } 1227c478bd9Sstevel@tonic-gate domain = dfltdom; 1237c478bd9Sstevel@tonic-gate } 1247c478bd9Sstevel@tonic-gate if ((strlen(domain) + OPSYS_LEN + 3 + MAXIPRINT) > 1257c478bd9Sstevel@tonic-gate (size_t)MAXNETNAMELEN) { 1267c478bd9Sstevel@tonic-gate *err = __NSW_UNAVAIL; 1277c478bd9Sstevel@tonic-gate return (0); 1287c478bd9Sstevel@tonic-gate } 12961961e0fSrobinson (void) snprintf(netname, MAXNETNAMELEN + 1, 13061961e0fSrobinson "%s.%d@%s", OPSYS, (int)uid, domain); 1317c478bd9Sstevel@tonic-gate i = strlen(netname); 1327c478bd9Sstevel@tonic-gate if (netname[i-1] == '.') 1337c478bd9Sstevel@tonic-gate netname[i-1] = '\0'; 1347c478bd9Sstevel@tonic-gate *err = __NSW_SUCCESS; 1357c478bd9Sstevel@tonic-gate return (1); 1367c478bd9Sstevel@tonic-gate } 1377c478bd9Sstevel@tonic-gate 1387c478bd9Sstevel@tonic-gate /* 1397c478bd9Sstevel@tonic-gate * Figure out my fully qualified network name 1407c478bd9Sstevel@tonic-gate */ 1417c478bd9Sstevel@tonic-gate int 14261961e0fSrobinson getnetname(char name[MAXNETNAMELEN + 1]) 1437c478bd9Sstevel@tonic-gate { 1447c478bd9Sstevel@tonic-gate uid_t uid; 1457c478bd9Sstevel@tonic-gate 1467c478bd9Sstevel@tonic-gate uid = geteuid(); 1477c478bd9Sstevel@tonic-gate if (uid == 0) 14861961e0fSrobinson return (host2netname(name, NULL, NULL)); 14961961e0fSrobinson return (user2netname(name, uid, NULL)); 1507c478bd9Sstevel@tonic-gate } 1517c478bd9Sstevel@tonic-gate 1527c478bd9Sstevel@tonic-gate 1537c478bd9Sstevel@tonic-gate /* 1547c478bd9Sstevel@tonic-gate * Figure out the fully qualified network name for the given uid. 1557c478bd9Sstevel@tonic-gate * This is a private interface. 1567c478bd9Sstevel@tonic-gate */ 1577c478bd9Sstevel@tonic-gate int 15861961e0fSrobinson __getnetnamebyuid(char name[MAXNETNAMELEN + 1], uid_t uid) 1597c478bd9Sstevel@tonic-gate { 1607c478bd9Sstevel@tonic-gate if (uid == 0) 16161961e0fSrobinson return (host2netname(name, NULL, NULL)); 16261961e0fSrobinson return (user2netname(name, uid, NULL)); 1637c478bd9Sstevel@tonic-gate } 1647c478bd9Sstevel@tonic-gate 1657c478bd9Sstevel@tonic-gate /* 1667c478bd9Sstevel@tonic-gate * Convert unix cred to network-name 1677c478bd9Sstevel@tonic-gate * 1687c478bd9Sstevel@tonic-gate * It uses the publickey policy in the /etc/nsswitch.conf file 1697c478bd9Sstevel@tonic-gate * (Unless the netname is "nobody", which is special cased). 1707c478bd9Sstevel@tonic-gate * If there is no publickey policy in /etc/nsswitch.conf, 1717c478bd9Sstevel@tonic-gate * the default publickey policy is used, which is 1727c478bd9Sstevel@tonic-gate * publickey: nis [NOTFOUND=return] files 1737c478bd9Sstevel@tonic-gate * Note that for the non-nisplus case, there is no failover 1747c478bd9Sstevel@tonic-gate * so only the first entry would be relevant for those cases. 1757c478bd9Sstevel@tonic-gate */ 1767c478bd9Sstevel@tonic-gate int 17761961e0fSrobinson user2netname(char netname[MAXNETNAMELEN + 1], const uid_t uid, 17861961e0fSrobinson const char *domain) 1797c478bd9Sstevel@tonic-gate { 1807c478bd9Sstevel@tonic-gate struct __nsw_switchconfig *conf; 1817c478bd9Sstevel@tonic-gate struct __nsw_lookup *look; 1827c478bd9Sstevel@tonic-gate int needfree = 1, res = 0; 1837c478bd9Sstevel@tonic-gate enum __nsw_parse_err perr; 1847c478bd9Sstevel@tonic-gate int err; 1857c478bd9Sstevel@tonic-gate 1867c478bd9Sstevel@tonic-gate /* 1877c478bd9Sstevel@tonic-gate * Take care of the special case of "nobody". If the uid is 1887c478bd9Sstevel@tonic-gate * the value assigned by the SVID for nobody, return the string 1897c478bd9Sstevel@tonic-gate * "nobody". 1907c478bd9Sstevel@tonic-gate */ 1917c478bd9Sstevel@tonic-gate 1927c478bd9Sstevel@tonic-gate if (uid == NOBODY_UID) { 193141ae836Speteh (void) strlcpy(netname, "nobody", sizeof (netname)); 1947c478bd9Sstevel@tonic-gate return (1); 1957c478bd9Sstevel@tonic-gate } 1967c478bd9Sstevel@tonic-gate 1977c478bd9Sstevel@tonic-gate netname[0] = '\0'; /* make null first (no need for memset) */ 1987c478bd9Sstevel@tonic-gate 199141ae836Speteh if (mutex_lock(&serialize_netname) == EDEADLK) { 200141ae836Speteh /* 201141ae836Speteh * This thread already holds this lock. This scenario 202141ae836Speteh * occurs when a process requires a netname which 203141ae836Speteh * itself requires a netname to look up. As we clearly 204141ae836Speteh * can't continue like this we return 'nobody'. 205141ae836Speteh */ 206141ae836Speteh (void) strlcpy(netname, "nobody", sizeof (netname)); 207141ae836Speteh return (1); 208141ae836Speteh } 2097c478bd9Sstevel@tonic-gate 2107c478bd9Sstevel@tonic-gate conf = __nsw_getconfig("publickey", &perr); 2117c478bd9Sstevel@tonic-gate if (!conf) { 2127c478bd9Sstevel@tonic-gate conf = &publickey_default; 2137c478bd9Sstevel@tonic-gate needfree = 0; 2147c478bd9Sstevel@tonic-gate } 2157c478bd9Sstevel@tonic-gate 2167c478bd9Sstevel@tonic-gate for (look = conf->lookups; look; look = look->next) { 2177c478bd9Sstevel@tonic-gate /* ldap, nis, and files all do the same thing. */ 21836e852a1SRaja Andra if (strcmp(look->service_name, "ldap") == 0 || 2197c478bd9Sstevel@tonic-gate strcmp(look->service_name, "nis") == 0 || 2207c478bd9Sstevel@tonic-gate strcmp(look->service_name, "files") == 0) 2217c478bd9Sstevel@tonic-gate res = user2netname_nis(&err, 2227c478bd9Sstevel@tonic-gate netname, uid, (char *)domain); 2237c478bd9Sstevel@tonic-gate else { 2247c478bd9Sstevel@tonic-gate syslog(LOG_INFO, 2257c478bd9Sstevel@tonic-gate "user2netname: unknown nameservice \ 2267c478bd9Sstevel@tonic-gate for publickey info '%s'\n", 2277c478bd9Sstevel@tonic-gate look->service_name); 2287c478bd9Sstevel@tonic-gate err = __NSW_UNAVAIL; 2297c478bd9Sstevel@tonic-gate } 2307c478bd9Sstevel@tonic-gate switch (look->actions[err]) { 2317c478bd9Sstevel@tonic-gate case __NSW_CONTINUE : 2327c478bd9Sstevel@tonic-gate break; 2337c478bd9Sstevel@tonic-gate case __NSW_RETURN : 2347c478bd9Sstevel@tonic-gate if (needfree) 235*5ad42b1bSSurya Prakki (void) __nsw_freeconfig(conf); 23661961e0fSrobinson (void) mutex_unlock(&serialize_netname); 2377c478bd9Sstevel@tonic-gate return (res); 2387c478bd9Sstevel@tonic-gate default : 2397c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 2407c478bd9Sstevel@tonic-gate "user2netname: Unknown action for nameservice '%s'", 2417c478bd9Sstevel@tonic-gate look->service_name); 2427c478bd9Sstevel@tonic-gate } 2437c478bd9Sstevel@tonic-gate } 2447c478bd9Sstevel@tonic-gate if (needfree) 245*5ad42b1bSSurya Prakki (void) __nsw_freeconfig(conf); 24661961e0fSrobinson (void) mutex_unlock(&serialize_netname); 2477c478bd9Sstevel@tonic-gate return (0); 2487c478bd9Sstevel@tonic-gate } 2497c478bd9Sstevel@tonic-gate 2507c478bd9Sstevel@tonic-gate 2517c478bd9Sstevel@tonic-gate /* 2527c478bd9Sstevel@tonic-gate * Convert host to network-name 2537c478bd9Sstevel@tonic-gate * This routine returns following netnames given the host and domain 2547c478bd9Sstevel@tonic-gate * arguments defined below: (domainname=y.z) 2557c478bd9Sstevel@tonic-gate * Arguments 2567c478bd9Sstevel@tonic-gate * host domain netname 2577c478bd9Sstevel@tonic-gate * ---- ------ ------- 2587c478bd9Sstevel@tonic-gate * - - unix.m@y.z (hostname=m) 2597c478bd9Sstevel@tonic-gate * - a.b unix.m@a.b (hostname=m) 2607c478bd9Sstevel@tonic-gate * - - unix.m@y.z (hostname=m.w.x) 2617c478bd9Sstevel@tonic-gate * - a.b unix.m@a.b (hostname=m.w.x) 2627c478bd9Sstevel@tonic-gate * h - unix.h@y.z 2637c478bd9Sstevel@tonic-gate * h a.b unix.h@a.b 2647c478bd9Sstevel@tonic-gate * h.w.x - unix.h@w.x 2657c478bd9Sstevel@tonic-gate * h.w.x a.b unix.h@a.b 2667c478bd9Sstevel@tonic-gate */ 2677c478bd9Sstevel@tonic-gate int 26861961e0fSrobinson host2netname(char netname[MAXNETNAMELEN + 1], const char *host, 26961961e0fSrobinson const char *domain) 2707c478bd9Sstevel@tonic-gate { 2717c478bd9Sstevel@tonic-gate char *p; 2727c478bd9Sstevel@tonic-gate char hostname[MAXHOSTNAMELEN + 1]; 2737c478bd9Sstevel@tonic-gate char domainname[MAXHOSTNAMELEN + 1]; 2747c478bd9Sstevel@tonic-gate char *dot_in_host; 2757c478bd9Sstevel@tonic-gate int i; 2767c478bd9Sstevel@tonic-gate size_t len; 2777c478bd9Sstevel@tonic-gate 2787c478bd9Sstevel@tonic-gate netname[0] = '\0'; /* make null first (no need for memset) */ 2797c478bd9Sstevel@tonic-gate 2807c478bd9Sstevel@tonic-gate if (host == NULL) { 2817c478bd9Sstevel@tonic-gate (void) strncpy(hostname, nis_local_host(), sizeof (hostname)); 2827c478bd9Sstevel@tonic-gate p = (char *)strchr(hostname, '.'); 2837c478bd9Sstevel@tonic-gate if (p) { 2847c478bd9Sstevel@tonic-gate *p++ = '\0'; 2857c478bd9Sstevel@tonic-gate /* if no domain passed, use tail of nis_local_host() */ 2867c478bd9Sstevel@tonic-gate if (domain == NULL) { 2877c478bd9Sstevel@tonic-gate domain = p; 2887c478bd9Sstevel@tonic-gate } 2897c478bd9Sstevel@tonic-gate } 2907c478bd9Sstevel@tonic-gate } else { 2917c478bd9Sstevel@tonic-gate len = strlen(host); 2927c478bd9Sstevel@tonic-gate if (len >= sizeof (hostname)) { 2937c478bd9Sstevel@tonic-gate return (0); 2947c478bd9Sstevel@tonic-gate } 2957c478bd9Sstevel@tonic-gate (void) strcpy(hostname, host); 2967c478bd9Sstevel@tonic-gate } 2977c478bd9Sstevel@tonic-gate 2987c478bd9Sstevel@tonic-gate dot_in_host = (char *)strchr(hostname, '.'); 2997c478bd9Sstevel@tonic-gate if (domain == NULL) { 3007c478bd9Sstevel@tonic-gate p = dot_in_host; 3017c478bd9Sstevel@tonic-gate if (p) { 3027c478bd9Sstevel@tonic-gate p = (char *)nis_domain_of(hostname); 3037c478bd9Sstevel@tonic-gate len = strlen(p); 3047c478bd9Sstevel@tonic-gate if (len >= sizeof (domainname)) { 3057c478bd9Sstevel@tonic-gate return (0); 3067c478bd9Sstevel@tonic-gate } 3077c478bd9Sstevel@tonic-gate (void) strcpy(domainname, p); 3087c478bd9Sstevel@tonic-gate } else { 3097c478bd9Sstevel@tonic-gate domainname[0] = NULL; 3107c478bd9Sstevel@tonic-gate if (getdomainname(domainname, MAXHOSTNAMELEN) < 0) 3117c478bd9Sstevel@tonic-gate return (0); 3127c478bd9Sstevel@tonic-gate } 3137c478bd9Sstevel@tonic-gate } else { 3147c478bd9Sstevel@tonic-gate len = strlen(domain); 3157c478bd9Sstevel@tonic-gate if (len >= sizeof (domainname)) { 3167c478bd9Sstevel@tonic-gate return (0); 3177c478bd9Sstevel@tonic-gate } 3187c478bd9Sstevel@tonic-gate (void) strcpy(domainname, domain); 3197c478bd9Sstevel@tonic-gate } 3207c478bd9Sstevel@tonic-gate 3217c478bd9Sstevel@tonic-gate i = strlen(domainname); 3227c478bd9Sstevel@tonic-gate if (i == 0) 3237c478bd9Sstevel@tonic-gate /* No domainname */ 3247c478bd9Sstevel@tonic-gate return (0); 3257c478bd9Sstevel@tonic-gate if (domainname[i - 1] == '.') 3267c478bd9Sstevel@tonic-gate domainname[i - 1] = 0; 3277c478bd9Sstevel@tonic-gate 3287c478bd9Sstevel@tonic-gate if (dot_in_host) { /* strip off rest of name */ 3297c478bd9Sstevel@tonic-gate *dot_in_host = '\0'; 3307c478bd9Sstevel@tonic-gate } 3317c478bd9Sstevel@tonic-gate 3327c478bd9Sstevel@tonic-gate if ((strlen(domainname) + strlen(hostname) + OPSYS_LEN + 3) 3337c478bd9Sstevel@tonic-gate > (size_t)MAXNETNAMELEN) { 3347c478bd9Sstevel@tonic-gate return (0); 3357c478bd9Sstevel@tonic-gate } 3367c478bd9Sstevel@tonic-gate 33761961e0fSrobinson (void) snprintf(netname, MAXNETNAMELEN + 1, 33861961e0fSrobinson "%s.%s@%s", OPSYS, hostname, domainname); 3397c478bd9Sstevel@tonic-gate return (1); 3407c478bd9Sstevel@tonic-gate } 341