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 58200fe25Srmesta * Common Development and Distribution License (the "License"). 68200fe25Srmesta * 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 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 22*dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. 237c478bd9Sstevel@tonic-gate */ 247c478bd9Sstevel@tonic-gate 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate /* 277c478bd9Sstevel@tonic-gate * Door server routines for nfsmapid daemon 287c478bd9Sstevel@tonic-gate * Translate NFSv4 users and groups between numeric and string values 297c478bd9Sstevel@tonic-gate */ 307c478bd9Sstevel@tonic-gate #include <stdio.h> 317c478bd9Sstevel@tonic-gate #include <stdlib.h> 327c478bd9Sstevel@tonic-gate #include <alloca.h> 337c478bd9Sstevel@tonic-gate #include <signal.h> 347c478bd9Sstevel@tonic-gate #include <libintl.h> 357c478bd9Sstevel@tonic-gate #include <limits.h> 367c478bd9Sstevel@tonic-gate #include <errno.h> 377c478bd9Sstevel@tonic-gate #include <sys/types.h> 387c478bd9Sstevel@tonic-gate #include <string.h> 397c478bd9Sstevel@tonic-gate #include <memory.h> 407c478bd9Sstevel@tonic-gate #include <pwd.h> 417c478bd9Sstevel@tonic-gate #include <grp.h> 427c478bd9Sstevel@tonic-gate #include <door.h> 437c478bd9Sstevel@tonic-gate #include <syslog.h> 447c478bd9Sstevel@tonic-gate #include <fcntl.h> 457c478bd9Sstevel@tonic-gate #include <unistd.h> 467c478bd9Sstevel@tonic-gate #include <assert.h> 477c478bd9Sstevel@tonic-gate #include <deflt.h> 487c478bd9Sstevel@tonic-gate #include <nfs/nfs4.h> 497c478bd9Sstevel@tonic-gate #include <nfs/nfssys.h> 507c478bd9Sstevel@tonic-gate #include <nfs/nfsid_map.h> 518200fe25Srmesta #include <nfs/mapid.h> 528200fe25Srmesta #include <sys/sdt.h> 53dd5829d1Sbaban #include <sys/idmap.h> 54dd5829d1Sbaban #include <idmap.h> 552f172c55SRobert Thurlow #include <sys/fs/autofs.h> 562f172c55SRobert Thurlow #include <sys/mkdev.h> 572f172c55SRobert Thurlow #include "nfs_resolve.h" 587c478bd9Sstevel@tonic-gate 597c478bd9Sstevel@tonic-gate #define UID_MAX_STR_LEN 11 /* Digits in UID_MAX + 1 */ 607c478bd9Sstevel@tonic-gate #define DIAG_FILE "/var/run/nfs4_domain" 618200fe25Srmesta 628200fe25Srmesta /* 638200fe25Srmesta * idmap_kcall() takes a door descriptor as it's argument when we 648200fe25Srmesta * need to (re)establish the in-kernel door handles. When we only 658200fe25Srmesta * want to flush the id kernel caches, we don't redo the door setup. 668200fe25Srmesta */ 678200fe25Srmesta #define FLUSH_KCACHES_ONLY (int)-1 688200fe25Srmesta 697c478bd9Sstevel@tonic-gate FILE *n4_fp; 708200fe25Srmesta int n4_fd; 717c478bd9Sstevel@tonic-gate 727c478bd9Sstevel@tonic-gate extern size_t pwd_buflen; 737c478bd9Sstevel@tonic-gate extern size_t grp_buflen; 747c478bd9Sstevel@tonic-gate extern thread_t sig_thread; 757c478bd9Sstevel@tonic-gate 767c478bd9Sstevel@tonic-gate /* 777c478bd9Sstevel@tonic-gate * Prototypes 787c478bd9Sstevel@tonic-gate */ 797c478bd9Sstevel@tonic-gate extern void check_domain(int); 807c478bd9Sstevel@tonic-gate extern void idmap_kcall(int); 817c478bd9Sstevel@tonic-gate extern int _nfssys(int, void *); 828200fe25Srmesta extern int valid_domain(const char *); 838200fe25Srmesta extern int validate_id_str(const char *); 848200fe25Srmesta extern int extract_domain(char *, char **, char **); 857c478bd9Sstevel@tonic-gate extern void update_diag_file(char *); 868200fe25Srmesta extern void *cb_update_domain(void *); 878200fe25Srmesta extern int cur_domain_null(void); 887c478bd9Sstevel@tonic-gate 898200fe25Srmesta void 907c478bd9Sstevel@tonic-gate nfsmapid_str_uid(struct mapid_arg *argp, size_t arg_size) 917c478bd9Sstevel@tonic-gate { 927c478bd9Sstevel@tonic-gate struct mapid_res result; 937c478bd9Sstevel@tonic-gate struct passwd pwd; 94dd5829d1Sbaban struct passwd *pwd_ptr; 95dd5829d1Sbaban int pwd_rc; 967c478bd9Sstevel@tonic-gate char *pwd_buf; 977c478bd9Sstevel@tonic-gate char *user; 987c478bd9Sstevel@tonic-gate char *domain; 99dd5829d1Sbaban idmap_stat rc; 1007c478bd9Sstevel@tonic-gate 1017c478bd9Sstevel@tonic-gate if (argp->u_arg.len <= 0 || arg_size < MAPID_ARG_LEN(argp->u_arg.len)) { 1027c478bd9Sstevel@tonic-gate result.status = NFSMAPID_INVALID; 1037c478bd9Sstevel@tonic-gate result.u_res.uid = UID_NOBODY; 1047c478bd9Sstevel@tonic-gate goto done; 1057c478bd9Sstevel@tonic-gate } 1067c478bd9Sstevel@tonic-gate 1077c478bd9Sstevel@tonic-gate if (!extract_domain(argp->str, &user, &domain)) { 108dd5829d1Sbaban unsigned long id; 1097c478bd9Sstevel@tonic-gate 1107c478bd9Sstevel@tonic-gate /* 111dd5829d1Sbaban * Invalid "user@domain" string. Still, the user 1127c478bd9Sstevel@tonic-gate * part might be an encoded uid, so do a final check. 1137c478bd9Sstevel@tonic-gate * Remember, domain part of string was not set since 1147c478bd9Sstevel@tonic-gate * not a valid string. 1157c478bd9Sstevel@tonic-gate */ 1167c478bd9Sstevel@tonic-gate if (!validate_id_str(user)) { 1177c478bd9Sstevel@tonic-gate result.status = NFSMAPID_UNMAPPABLE; 1187c478bd9Sstevel@tonic-gate result.u_res.uid = UID_NOBODY; 1197c478bd9Sstevel@tonic-gate goto done; 1207c478bd9Sstevel@tonic-gate } 1217c478bd9Sstevel@tonic-gate 1227c478bd9Sstevel@tonic-gate errno = 0; 123dd5829d1Sbaban id = strtoul(user, (char **)NULL, 10); 1247c478bd9Sstevel@tonic-gate 125dd5829d1Sbaban /* 126dd5829d1Sbaban * We don't accept ephemeral ids from the wire. 127dd5829d1Sbaban */ 128dd5829d1Sbaban if (errno || id > UID_MAX) { 1297c478bd9Sstevel@tonic-gate result.status = NFSMAPID_UNMAPPABLE; 1307c478bd9Sstevel@tonic-gate result.u_res.uid = UID_NOBODY; 1317c478bd9Sstevel@tonic-gate goto done; 1327c478bd9Sstevel@tonic-gate } 1337c478bd9Sstevel@tonic-gate 1347c478bd9Sstevel@tonic-gate result.u_res.uid = (uid_t)id; 1357c478bd9Sstevel@tonic-gate result.status = NFSMAPID_NUMSTR; 1367c478bd9Sstevel@tonic-gate goto done; 1377c478bd9Sstevel@tonic-gate } 1387c478bd9Sstevel@tonic-gate 1397c478bd9Sstevel@tonic-gate /* 1407c478bd9Sstevel@tonic-gate * String properly constructed. Now we check for domain and 141dd5829d1Sbaban * group validity. 1427c478bd9Sstevel@tonic-gate */ 1438200fe25Srmesta if (!cur_domain_null() && !valid_domain(domain)) { 144dd5829d1Sbaban /* 145dd5829d1Sbaban * If the domain part of the string does not 146dd5829d1Sbaban * match the NFS domain, try to map it using 147dd5829d1Sbaban * idmap service. 148dd5829d1Sbaban */ 1493ee87bcaSJulian Pullen rc = idmap_getuidbywinname(user, domain, 0, &result.u_res.uid); 150dd5829d1Sbaban if (rc != IDMAP_SUCCESS) { 1517c478bd9Sstevel@tonic-gate result.status = NFSMAPID_BADDOMAIN; 1527c478bd9Sstevel@tonic-gate result.u_res.uid = UID_NOBODY; 1537c478bd9Sstevel@tonic-gate goto done; 1547c478bd9Sstevel@tonic-gate } 155dd5829d1Sbaban result.status = NFSMAPID_OK; 156dd5829d1Sbaban goto done; 157dd5829d1Sbaban } 1587c478bd9Sstevel@tonic-gate 1597c478bd9Sstevel@tonic-gate if ((pwd_buf = malloc(pwd_buflen)) == NULL || 160dd5829d1Sbaban (pwd_rc = getpwnam_r(user, &pwd, pwd_buf, pwd_buflen, &pwd_ptr)) 161dd5829d1Sbaban != 0 || pwd_ptr == NULL) { 1627c478bd9Sstevel@tonic-gate 163dd5829d1Sbaban if (pwd_buf == NULL || pwd_rc != 0) 1647c478bd9Sstevel@tonic-gate result.status = NFSMAPID_INTERNAL; 1657c478bd9Sstevel@tonic-gate else { 1667c478bd9Sstevel@tonic-gate /* 1677c478bd9Sstevel@tonic-gate * Not a valid user 1687c478bd9Sstevel@tonic-gate */ 1697c478bd9Sstevel@tonic-gate result.status = NFSMAPID_NOTFOUND; 1707c478bd9Sstevel@tonic-gate free(pwd_buf); 1717c478bd9Sstevel@tonic-gate } 1727c478bd9Sstevel@tonic-gate result.u_res.uid = UID_NOBODY; 1737c478bd9Sstevel@tonic-gate goto done; 1747c478bd9Sstevel@tonic-gate } 1757c478bd9Sstevel@tonic-gate 1767c478bd9Sstevel@tonic-gate /* 1777c478bd9Sstevel@tonic-gate * Valid user entry 1787c478bd9Sstevel@tonic-gate */ 1797c478bd9Sstevel@tonic-gate result.u_res.uid = pwd.pw_uid; 1807c478bd9Sstevel@tonic-gate result.status = NFSMAPID_OK; 1817c478bd9Sstevel@tonic-gate free(pwd_buf); 1827c478bd9Sstevel@tonic-gate done: 1837c478bd9Sstevel@tonic-gate (void) door_return((char *)&result, sizeof (struct mapid_res), NULL, 0); 1847c478bd9Sstevel@tonic-gate } 1857c478bd9Sstevel@tonic-gate 1867c478bd9Sstevel@tonic-gate /* ARGSUSED1 */ 1878200fe25Srmesta void 1887c478bd9Sstevel@tonic-gate nfsmapid_uid_str(struct mapid_arg *argp, size_t arg_size) 1897c478bd9Sstevel@tonic-gate { 1907c478bd9Sstevel@tonic-gate struct mapid_res result; 1917c478bd9Sstevel@tonic-gate struct mapid_res *resp; 1927c478bd9Sstevel@tonic-gate struct passwd pwd; 193dd5829d1Sbaban struct passwd *pwd_ptr; 194dd5829d1Sbaban char *pwd_buf = NULL; 195dd5829d1Sbaban char *idmap_buf = NULL; 1967c478bd9Sstevel@tonic-gate uid_t uid = argp->u_arg.uid; 1977c478bd9Sstevel@tonic-gate size_t uid_str_len; 1987c478bd9Sstevel@tonic-gate char *pw_str; 1997c478bd9Sstevel@tonic-gate size_t pw_str_len; 2007c478bd9Sstevel@tonic-gate char *at_str; 2017c478bd9Sstevel@tonic-gate size_t at_str_len; 2028200fe25Srmesta char dom_str[DNAMEMAX]; 2037c478bd9Sstevel@tonic-gate size_t dom_str_len; 204dd5829d1Sbaban idmap_stat rc; 2057c478bd9Sstevel@tonic-gate 206dd5829d1Sbaban if (uid == (uid_t)-1) { 2077c478bd9Sstevel@tonic-gate /* 208dd5829d1Sbaban * Sentinel uid is not a valid id 2097c478bd9Sstevel@tonic-gate */ 2107c478bd9Sstevel@tonic-gate resp = &result; 2117c478bd9Sstevel@tonic-gate resp->status = NFSMAPID_BADID; 2127c478bd9Sstevel@tonic-gate resp->u_res.len = 0; 2137c478bd9Sstevel@tonic-gate goto done; 2147c478bd9Sstevel@tonic-gate } 2157c478bd9Sstevel@tonic-gate 2167c478bd9Sstevel@tonic-gate /* 2177c478bd9Sstevel@tonic-gate * Make local copy of domain for further manipuation 2188200fe25Srmesta * NOTE: mapid_get_domain() returns a ptr to TSD. 2197c478bd9Sstevel@tonic-gate */ 2208200fe25Srmesta if (cur_domain_null()) { 2217c478bd9Sstevel@tonic-gate dom_str_len = 0; 2227c478bd9Sstevel@tonic-gate dom_str[0] = '\0'; 2237c478bd9Sstevel@tonic-gate } else { 2248200fe25Srmesta dom_str_len = strlcpy(dom_str, mapid_get_domain(), DNAMEMAX); 2257c478bd9Sstevel@tonic-gate } 2267c478bd9Sstevel@tonic-gate 2277c478bd9Sstevel@tonic-gate /* 228dd5829d1Sbaban * If uid is ephemeral then resolve it using idmap service 229dd5829d1Sbaban */ 230dd5829d1Sbaban if (uid > UID_MAX) { 2313ee87bcaSJulian Pullen rc = idmap_getwinnamebyuid(uid, 0, &idmap_buf, NULL); 232dd5829d1Sbaban if (rc != IDMAP_SUCCESS) { 233dd5829d1Sbaban /* 234dd5829d1Sbaban * We don't put stringified ephemeral uids on 235dd5829d1Sbaban * the wire. 236dd5829d1Sbaban */ 237dd5829d1Sbaban resp = &result; 238dd5829d1Sbaban resp->status = NFSMAPID_UNMAPPABLE; 239dd5829d1Sbaban resp->u_res.len = 0; 240dd5829d1Sbaban goto done; 241dd5829d1Sbaban } 242dd5829d1Sbaban 243dd5829d1Sbaban /* 244dd5829d1Sbaban * idmap_buf is already in the desired form i.e. name@domain 245dd5829d1Sbaban */ 246dd5829d1Sbaban pw_str = idmap_buf; 247dd5829d1Sbaban pw_str_len = strlen(pw_str); 248dd5829d1Sbaban at_str_len = dom_str_len = 0; 249dd5829d1Sbaban at_str = ""; 250dd5829d1Sbaban dom_str[0] = '\0'; 251dd5829d1Sbaban goto gen_result; 252dd5829d1Sbaban } 253dd5829d1Sbaban 254dd5829d1Sbaban /* 255dd5829d1Sbaban * Handling non-ephemeral uids 256dd5829d1Sbaban * 2577c478bd9Sstevel@tonic-gate * We want to encode the uid into a literal string... : 2587c478bd9Sstevel@tonic-gate * 2597c478bd9Sstevel@tonic-gate * - upon failure to allocate space from the heap 2607c478bd9Sstevel@tonic-gate * - if there is no current domain configured 2617c478bd9Sstevel@tonic-gate * - if there is no such uid in the passwd DB's 2627c478bd9Sstevel@tonic-gate */ 2637c478bd9Sstevel@tonic-gate if ((pwd_buf = malloc(pwd_buflen)) == NULL || dom_str_len == 0 || 264dd5829d1Sbaban getpwuid_r(uid, &pwd, pwd_buf, pwd_buflen, &pwd_ptr) != 0 || 265dd5829d1Sbaban pwd_ptr == NULL) { 2667c478bd9Sstevel@tonic-gate 2677c478bd9Sstevel@tonic-gate /* 2687c478bd9Sstevel@tonic-gate * If we could not allocate from the heap, try 2697c478bd9Sstevel@tonic-gate * allocating from the stack as a last resort. 2707c478bd9Sstevel@tonic-gate */ 2717c478bd9Sstevel@tonic-gate if (pwd_buf == NULL && (pwd_buf = 2727c478bd9Sstevel@tonic-gate alloca(MAPID_RES_LEN(UID_MAX_STR_LEN))) == NULL) { 2737c478bd9Sstevel@tonic-gate resp = &result; 2747c478bd9Sstevel@tonic-gate resp->status = NFSMAPID_INTERNAL; 2757c478bd9Sstevel@tonic-gate resp->u_res.len = 0; 2767c478bd9Sstevel@tonic-gate goto done; 2777c478bd9Sstevel@tonic-gate } 2787c478bd9Sstevel@tonic-gate 2797c478bd9Sstevel@tonic-gate /* 2807c478bd9Sstevel@tonic-gate * Constructing literal string without '@' so that 2817c478bd9Sstevel@tonic-gate * we'll know that it's not a user, but rather a 282dd5829d1Sbaban * uid encoded string. 2837c478bd9Sstevel@tonic-gate */ 2847c478bd9Sstevel@tonic-gate pw_str = pwd_buf; 285dd5829d1Sbaban (void) sprintf(pw_str, "%u", uid); 2867c478bd9Sstevel@tonic-gate pw_str_len = strlen(pw_str); 2877c478bd9Sstevel@tonic-gate at_str_len = dom_str_len = 0; 2887c478bd9Sstevel@tonic-gate at_str = ""; 2897c478bd9Sstevel@tonic-gate dom_str[0] = '\0'; 2907c478bd9Sstevel@tonic-gate } else { 2917c478bd9Sstevel@tonic-gate /* 292dd5829d1Sbaban * Otherwise, we construct the "user@domain" string if 293dd5829d1Sbaban * it's not already in that form. 2947c478bd9Sstevel@tonic-gate */ 2957c478bd9Sstevel@tonic-gate pw_str = pwd.pw_name; 2967c478bd9Sstevel@tonic-gate pw_str_len = strlen(pw_str); 297dd5829d1Sbaban if (strchr(pw_str, '@') == NULL) { 2987c478bd9Sstevel@tonic-gate at_str = "@"; 2997c478bd9Sstevel@tonic-gate at_str_len = 1; 300dd5829d1Sbaban } else { 301dd5829d1Sbaban at_str_len = dom_str_len = 0; 302dd5829d1Sbaban at_str = ""; 303dd5829d1Sbaban dom_str[0] = '\0'; 304dd5829d1Sbaban } 3057c478bd9Sstevel@tonic-gate } 3067c478bd9Sstevel@tonic-gate 307dd5829d1Sbaban gen_result: 3087c478bd9Sstevel@tonic-gate uid_str_len = pw_str_len + at_str_len + dom_str_len; 309dd5829d1Sbaban if ((resp = alloca(MAPID_RES_LEN(uid_str_len))) == NULL) { 3107c478bd9Sstevel@tonic-gate resp = &result; 3117c478bd9Sstevel@tonic-gate resp->status = NFSMAPID_INTERNAL; 3127c478bd9Sstevel@tonic-gate resp->u_res.len = 0; 3137c478bd9Sstevel@tonic-gate goto done; 3147c478bd9Sstevel@tonic-gate } 3157c478bd9Sstevel@tonic-gate /* LINTED format argument to sprintf */ 3167c478bd9Sstevel@tonic-gate (void) sprintf(resp->str, "%s%s%s", pw_str, at_str, dom_str); 3177c478bd9Sstevel@tonic-gate resp->u_res.len = uid_str_len; 318dd5829d1Sbaban if (pwd_buf) 3197c478bd9Sstevel@tonic-gate free(pwd_buf); 320dd5829d1Sbaban if (idmap_buf) 321dd5829d1Sbaban idmap_free(idmap_buf); 3227c478bd9Sstevel@tonic-gate resp->status = NFSMAPID_OK; 3237c478bd9Sstevel@tonic-gate 3247c478bd9Sstevel@tonic-gate done: 3257c478bd9Sstevel@tonic-gate /* 3267c478bd9Sstevel@tonic-gate * There is a chance that the door_return will fail because the 3277c478bd9Sstevel@tonic-gate * resulting string is too large, try to indicate that if possible 3287c478bd9Sstevel@tonic-gate */ 3297c478bd9Sstevel@tonic-gate if (door_return((char *)resp, 3307c478bd9Sstevel@tonic-gate MAPID_RES_LEN(resp->u_res.len), NULL, 0) == -1) { 3317c478bd9Sstevel@tonic-gate resp->status = NFSMAPID_INTERNAL; 3327c478bd9Sstevel@tonic-gate resp->u_res.len = 0; 3337c478bd9Sstevel@tonic-gate (void) door_return((char *)&result, sizeof (struct mapid_res), 3347c478bd9Sstevel@tonic-gate NULL, 0); 3357c478bd9Sstevel@tonic-gate } 3367c478bd9Sstevel@tonic-gate } 3377c478bd9Sstevel@tonic-gate 3388200fe25Srmesta void 3397c478bd9Sstevel@tonic-gate nfsmapid_str_gid(struct mapid_arg *argp, size_t arg_size) 3407c478bd9Sstevel@tonic-gate { 3417c478bd9Sstevel@tonic-gate struct mapid_res result; 3427c478bd9Sstevel@tonic-gate struct group grp; 343dd5829d1Sbaban struct group *grp_ptr; 344dd5829d1Sbaban int grp_rc; 3457c478bd9Sstevel@tonic-gate char *grp_buf; 3467c478bd9Sstevel@tonic-gate char *group; 3477c478bd9Sstevel@tonic-gate char *domain; 348dd5829d1Sbaban idmap_stat rc; 3497c478bd9Sstevel@tonic-gate 3507c478bd9Sstevel@tonic-gate if (argp->u_arg.len <= 0 || 3517c478bd9Sstevel@tonic-gate arg_size < MAPID_ARG_LEN(argp->u_arg.len)) { 3527c478bd9Sstevel@tonic-gate result.status = NFSMAPID_INVALID; 3537c478bd9Sstevel@tonic-gate result.u_res.gid = GID_NOBODY; 3547c478bd9Sstevel@tonic-gate goto done; 3557c478bd9Sstevel@tonic-gate } 3567c478bd9Sstevel@tonic-gate 3577c478bd9Sstevel@tonic-gate if (!extract_domain(argp->str, &group, &domain)) { 358dd5829d1Sbaban unsigned long id; 3597c478bd9Sstevel@tonic-gate 3607c478bd9Sstevel@tonic-gate /* 361dd5829d1Sbaban * Invalid "group@domain" string. Still, the 3627c478bd9Sstevel@tonic-gate * group part might be an encoded gid, so do a 3637c478bd9Sstevel@tonic-gate * final check. Remember, domain part of string 3647c478bd9Sstevel@tonic-gate * was not set since not a valid string. 3657c478bd9Sstevel@tonic-gate */ 3667c478bd9Sstevel@tonic-gate if (!validate_id_str(group)) { 3677c478bd9Sstevel@tonic-gate result.status = NFSMAPID_UNMAPPABLE; 3687c478bd9Sstevel@tonic-gate result.u_res.gid = GID_NOBODY; 3697c478bd9Sstevel@tonic-gate goto done; 3707c478bd9Sstevel@tonic-gate } 3717c478bd9Sstevel@tonic-gate 3727c478bd9Sstevel@tonic-gate errno = 0; 373dd5829d1Sbaban id = strtoul(group, (char **)NULL, 10); 3747c478bd9Sstevel@tonic-gate 375dd5829d1Sbaban /* 376dd5829d1Sbaban * We don't accept ephemeral ids from the wire. 377dd5829d1Sbaban */ 378dd5829d1Sbaban if (errno || id > UID_MAX) { 3797c478bd9Sstevel@tonic-gate result.status = NFSMAPID_UNMAPPABLE; 3807c478bd9Sstevel@tonic-gate result.u_res.gid = GID_NOBODY; 3817c478bd9Sstevel@tonic-gate goto done; 3827c478bd9Sstevel@tonic-gate } 3837c478bd9Sstevel@tonic-gate 3847c478bd9Sstevel@tonic-gate result.u_res.gid = (gid_t)id; 3857c478bd9Sstevel@tonic-gate result.status = NFSMAPID_NUMSTR; 3867c478bd9Sstevel@tonic-gate goto done; 3877c478bd9Sstevel@tonic-gate } 3887c478bd9Sstevel@tonic-gate 3897c478bd9Sstevel@tonic-gate /* 3907c478bd9Sstevel@tonic-gate * String properly constructed. Now we check for domain and 391dd5829d1Sbaban * group validity. 3927c478bd9Sstevel@tonic-gate */ 3938200fe25Srmesta if (!cur_domain_null() && !valid_domain(domain)) { 394dd5829d1Sbaban /* 395dd5829d1Sbaban * If the domain part of the string does not 396dd5829d1Sbaban * match the NFS domain, try to map it using 397dd5829d1Sbaban * idmap service. 398dd5829d1Sbaban */ 3993ee87bcaSJulian Pullen rc = idmap_getgidbywinname(group, domain, 0, &result.u_res.gid); 400dd5829d1Sbaban if (rc != IDMAP_SUCCESS) { 4017c478bd9Sstevel@tonic-gate result.status = NFSMAPID_BADDOMAIN; 4027c478bd9Sstevel@tonic-gate result.u_res.gid = GID_NOBODY; 4037c478bd9Sstevel@tonic-gate goto done; 4047c478bd9Sstevel@tonic-gate } 405dd5829d1Sbaban result.status = NFSMAPID_OK; 406dd5829d1Sbaban goto done; 407dd5829d1Sbaban } 4087c478bd9Sstevel@tonic-gate 4097c478bd9Sstevel@tonic-gate if ((grp_buf = malloc(grp_buflen)) == NULL || 410dd5829d1Sbaban (grp_rc = getgrnam_r(group, &grp, grp_buf, grp_buflen, &grp_ptr)) 411dd5829d1Sbaban != 0 || grp_ptr == NULL) { 4127c478bd9Sstevel@tonic-gate 413dd5829d1Sbaban if (grp_buf == NULL || grp_rc != 0) 4147c478bd9Sstevel@tonic-gate result.status = NFSMAPID_INTERNAL; 4157c478bd9Sstevel@tonic-gate else { 4167c478bd9Sstevel@tonic-gate /* 4177c478bd9Sstevel@tonic-gate * Not a valid group 4187c478bd9Sstevel@tonic-gate */ 4197c478bd9Sstevel@tonic-gate result.status = NFSMAPID_NOTFOUND; 4207c478bd9Sstevel@tonic-gate free(grp_buf); 4217c478bd9Sstevel@tonic-gate } 4227c478bd9Sstevel@tonic-gate result.u_res.gid = GID_NOBODY; 4237c478bd9Sstevel@tonic-gate goto done; 4247c478bd9Sstevel@tonic-gate } 4257c478bd9Sstevel@tonic-gate 4267c478bd9Sstevel@tonic-gate /* 4277c478bd9Sstevel@tonic-gate * Valid group entry 4287c478bd9Sstevel@tonic-gate */ 4297c478bd9Sstevel@tonic-gate result.status = NFSMAPID_OK; 4307c478bd9Sstevel@tonic-gate result.u_res.gid = grp.gr_gid; 4317c478bd9Sstevel@tonic-gate free(grp_buf); 4327c478bd9Sstevel@tonic-gate done: 4337c478bd9Sstevel@tonic-gate (void) door_return((char *)&result, sizeof (struct mapid_res), NULL, 0); 4347c478bd9Sstevel@tonic-gate } 4357c478bd9Sstevel@tonic-gate 4367c478bd9Sstevel@tonic-gate /* ARGSUSED1 */ 4378200fe25Srmesta void 4387c478bd9Sstevel@tonic-gate nfsmapid_gid_str(struct mapid_arg *argp, size_t arg_size) 4397c478bd9Sstevel@tonic-gate { 4407c478bd9Sstevel@tonic-gate struct mapid_res result; 4417c478bd9Sstevel@tonic-gate struct mapid_res *resp; 4427c478bd9Sstevel@tonic-gate struct group grp; 443dd5829d1Sbaban struct group *grp_ptr; 444dd5829d1Sbaban char *grp_buf = NULL; 445dd5829d1Sbaban char *idmap_buf = NULL; 446dd5829d1Sbaban idmap_stat rc; 4477c478bd9Sstevel@tonic-gate gid_t gid = argp->u_arg.gid; 4487c478bd9Sstevel@tonic-gate size_t gid_str_len; 4497c478bd9Sstevel@tonic-gate char *gr_str; 4507c478bd9Sstevel@tonic-gate size_t gr_str_len; 4517c478bd9Sstevel@tonic-gate char *at_str; 4527c478bd9Sstevel@tonic-gate size_t at_str_len; 4538200fe25Srmesta char dom_str[DNAMEMAX]; 4547c478bd9Sstevel@tonic-gate size_t dom_str_len; 4557c478bd9Sstevel@tonic-gate 456dd5829d1Sbaban if (gid == (gid_t)-1) { 4577c478bd9Sstevel@tonic-gate /* 458dd5829d1Sbaban * Sentinel gid is not a valid id 4597c478bd9Sstevel@tonic-gate */ 4607c478bd9Sstevel@tonic-gate resp = &result; 4617c478bd9Sstevel@tonic-gate resp->status = NFSMAPID_BADID; 4627c478bd9Sstevel@tonic-gate resp->u_res.len = 0; 4637c478bd9Sstevel@tonic-gate goto done; 4647c478bd9Sstevel@tonic-gate } 4657c478bd9Sstevel@tonic-gate 4667c478bd9Sstevel@tonic-gate /* 4677c478bd9Sstevel@tonic-gate * Make local copy of domain for further manipuation 4688200fe25Srmesta * NOTE: mapid_get_domain() returns a ptr to TSD. 4697c478bd9Sstevel@tonic-gate */ 4708200fe25Srmesta if (cur_domain_null()) { 4717c478bd9Sstevel@tonic-gate dom_str_len = 0; 4727c478bd9Sstevel@tonic-gate dom_str[0] = '\0'; 4737c478bd9Sstevel@tonic-gate } else { 4748200fe25Srmesta dom_str_len = strlen(mapid_get_domain()); 4758200fe25Srmesta bcopy(mapid_get_domain(), dom_str, dom_str_len); 4767c478bd9Sstevel@tonic-gate dom_str[dom_str_len] = '\0'; 4777c478bd9Sstevel@tonic-gate } 4787c478bd9Sstevel@tonic-gate 4797c478bd9Sstevel@tonic-gate /* 480dd5829d1Sbaban * If gid is ephemeral then resolve it using idmap service 481dd5829d1Sbaban */ 482dd5829d1Sbaban if (gid > UID_MAX) { 4833ee87bcaSJulian Pullen rc = idmap_getwinnamebygid(gid, 0, &idmap_buf, NULL); 484dd5829d1Sbaban if (rc != IDMAP_SUCCESS) { 485dd5829d1Sbaban /* 486dd5829d1Sbaban * We don't put stringified ephemeral gids on 487dd5829d1Sbaban * the wire. 488dd5829d1Sbaban */ 489dd5829d1Sbaban resp = &result; 490dd5829d1Sbaban resp->status = NFSMAPID_UNMAPPABLE; 491dd5829d1Sbaban resp->u_res.len = 0; 492dd5829d1Sbaban goto done; 493dd5829d1Sbaban } 494dd5829d1Sbaban 495dd5829d1Sbaban /* 496dd5829d1Sbaban * idmap_buf is already in the desired form i.e. name@domain 497dd5829d1Sbaban */ 498dd5829d1Sbaban gr_str = idmap_buf; 499dd5829d1Sbaban gr_str_len = strlen(gr_str); 500dd5829d1Sbaban at_str_len = dom_str_len = 0; 501dd5829d1Sbaban at_str = ""; 502dd5829d1Sbaban dom_str[0] = '\0'; 503dd5829d1Sbaban goto gen_result; 504dd5829d1Sbaban } 505dd5829d1Sbaban 506dd5829d1Sbaban /* 507dd5829d1Sbaban * Handling non-ephemeral gids 508dd5829d1Sbaban * 5097c478bd9Sstevel@tonic-gate * We want to encode the gid into a literal string... : 5107c478bd9Sstevel@tonic-gate * 5117c478bd9Sstevel@tonic-gate * - upon failure to allocate space from the heap 5127c478bd9Sstevel@tonic-gate * - if there is no current domain configured 5137c478bd9Sstevel@tonic-gate * - if there is no such gid in the group DB's 5147c478bd9Sstevel@tonic-gate */ 5157c478bd9Sstevel@tonic-gate if ((grp_buf = malloc(grp_buflen)) == NULL || dom_str_len == 0 || 516dd5829d1Sbaban getgrgid_r(gid, &grp, grp_buf, grp_buflen, &grp_ptr) != 0 || 517dd5829d1Sbaban grp_ptr == NULL) { 5187c478bd9Sstevel@tonic-gate 5197c478bd9Sstevel@tonic-gate /* 5207c478bd9Sstevel@tonic-gate * If we could not allocate from the heap, try 5217c478bd9Sstevel@tonic-gate * allocating from the stack as a last resort. 5227c478bd9Sstevel@tonic-gate */ 5237c478bd9Sstevel@tonic-gate if (grp_buf == NULL && (grp_buf = 5247c478bd9Sstevel@tonic-gate alloca(MAPID_RES_LEN(UID_MAX_STR_LEN))) == NULL) { 5257c478bd9Sstevel@tonic-gate resp = &result; 5267c478bd9Sstevel@tonic-gate resp->status = NFSMAPID_INTERNAL; 5277c478bd9Sstevel@tonic-gate resp->u_res.len = 0; 5287c478bd9Sstevel@tonic-gate goto done; 5297c478bd9Sstevel@tonic-gate } 5307c478bd9Sstevel@tonic-gate 5317c478bd9Sstevel@tonic-gate /* 5327c478bd9Sstevel@tonic-gate * Constructing literal string without '@' so that 5337c478bd9Sstevel@tonic-gate * we'll know that it's not a group, but rather a 534dd5829d1Sbaban * gid encoded string. 5357c478bd9Sstevel@tonic-gate */ 5367c478bd9Sstevel@tonic-gate gr_str = grp_buf; 537dd5829d1Sbaban (void) sprintf(gr_str, "%u", gid); 5387c478bd9Sstevel@tonic-gate gr_str_len = strlen(gr_str); 5397c478bd9Sstevel@tonic-gate at_str_len = dom_str_len = 0; 5407c478bd9Sstevel@tonic-gate at_str = ""; 5417c478bd9Sstevel@tonic-gate dom_str[0] = '\0'; 5427c478bd9Sstevel@tonic-gate } else { 5437c478bd9Sstevel@tonic-gate /* 544dd5829d1Sbaban * Otherwise, we construct the "group@domain" string if 545dd5829d1Sbaban * it's not already in that form. 5467c478bd9Sstevel@tonic-gate */ 5477c478bd9Sstevel@tonic-gate gr_str = grp.gr_name; 5487c478bd9Sstevel@tonic-gate gr_str_len = strlen(gr_str); 549dd5829d1Sbaban if (strchr(gr_str, '@') == NULL) { 5507c478bd9Sstevel@tonic-gate at_str = "@"; 5517c478bd9Sstevel@tonic-gate at_str_len = 1; 552dd5829d1Sbaban } else { 553dd5829d1Sbaban at_str_len = dom_str_len = 0; 554dd5829d1Sbaban at_str = ""; 555dd5829d1Sbaban dom_str[0] = '\0'; 556dd5829d1Sbaban } 5577c478bd9Sstevel@tonic-gate } 5587c478bd9Sstevel@tonic-gate 559dd5829d1Sbaban gen_result: 5607c478bd9Sstevel@tonic-gate gid_str_len = gr_str_len + at_str_len + dom_str_len; 561dd5829d1Sbaban if ((resp = alloca(MAPID_RES_LEN(gid_str_len))) == NULL) { 5627c478bd9Sstevel@tonic-gate resp = &result; 5637c478bd9Sstevel@tonic-gate resp->status = NFSMAPID_INTERNAL; 5647c478bd9Sstevel@tonic-gate resp->u_res.len = 0; 5657c478bd9Sstevel@tonic-gate goto done; 5667c478bd9Sstevel@tonic-gate } 5677c478bd9Sstevel@tonic-gate /* LINTED format argument to sprintf */ 5687c478bd9Sstevel@tonic-gate (void) sprintf(resp->str, "%s%s%s", gr_str, at_str, dom_str); 5697c478bd9Sstevel@tonic-gate resp->u_res.len = gid_str_len; 570dd5829d1Sbaban if (grp_buf) 5717c478bd9Sstevel@tonic-gate free(grp_buf); 572dd5829d1Sbaban if (idmap_buf) 573dd5829d1Sbaban idmap_free(idmap_buf); 5747c478bd9Sstevel@tonic-gate resp->status = NFSMAPID_OK; 5757c478bd9Sstevel@tonic-gate 5767c478bd9Sstevel@tonic-gate done: 5777c478bd9Sstevel@tonic-gate /* 5787c478bd9Sstevel@tonic-gate * There is a chance that the door_return will fail because the 5797c478bd9Sstevel@tonic-gate * resulting string is too large, try to indicate that if possible 5807c478bd9Sstevel@tonic-gate */ 5817c478bd9Sstevel@tonic-gate if (door_return((char *)resp, 5827c478bd9Sstevel@tonic-gate MAPID_RES_LEN(resp->u_res.len), NULL, 0) == -1) { 5837c478bd9Sstevel@tonic-gate resp->status = NFSMAPID_INTERNAL; 5847c478bd9Sstevel@tonic-gate resp->u_res.len = 0; 5857c478bd9Sstevel@tonic-gate (void) door_return((char *)&result, sizeof (struct mapid_res), 5867c478bd9Sstevel@tonic-gate NULL, 0); 5877c478bd9Sstevel@tonic-gate } 5887c478bd9Sstevel@tonic-gate } 5897c478bd9Sstevel@tonic-gate 5902f172c55SRobert Thurlow void 5912f172c55SRobert Thurlow nfsmapid_server_netinfo(refd_door_args_t *referral_args, size_t arg_size) 5922f172c55SRobert Thurlow { 5932f172c55SRobert Thurlow char *res; 5942f172c55SRobert Thurlow int res_size; 5952f172c55SRobert Thurlow int error; 5962f172c55SRobert Thurlow int srsz = 0; 5972f172c55SRobert Thurlow char host[MAXHOSTNAMELEN]; 5982f172c55SRobert Thurlow utf8string *nfsfsloc_args; 5992f172c55SRobert Thurlow refd_door_res_t *door_res; 6002f172c55SRobert Thurlow refd_door_res_t failed_res; 6012f172c55SRobert Thurlow struct nfs_fsl_info *nfs_fsloc_res; 6022f172c55SRobert Thurlow 6032f172c55SRobert Thurlow if (arg_size < sizeof (refd_door_args_t)) { 6042f172c55SRobert Thurlow failed_res.res_status = EINVAL; 6052f172c55SRobert Thurlow res = (char *)&failed_res; 6062f172c55SRobert Thurlow res_size = sizeof (refd_door_res_t); 6072f172c55SRobert Thurlow syslog(LOG_ERR, 6082f172c55SRobert Thurlow "nfsmapid_server_netinfo failed: Invalid data\n"); 6092f172c55SRobert Thurlow goto send_response; 6102f172c55SRobert Thurlow } 6112f172c55SRobert Thurlow 6122f172c55SRobert Thurlow if (decode_args(xdr_utf8string, (refd_door_args_t *)referral_args, 6132f172c55SRobert Thurlow (caddr_t *)&nfsfsloc_args, sizeof (utf8string))) { 6142f172c55SRobert Thurlow syslog(LOG_ERR, "cannot allocate memory"); 6152f172c55SRobert Thurlow failed_res.res_status = ENOMEM; 6162f172c55SRobert Thurlow failed_res.xdr_len = 0; 6172f172c55SRobert Thurlow res = (caddr_t)&failed_res; 6182f172c55SRobert Thurlow res_size = sizeof (refd_door_res_t); 6192f172c55SRobert Thurlow goto send_response; 6202f172c55SRobert Thurlow } 6212f172c55SRobert Thurlow 6222f172c55SRobert Thurlow if (nfsfsloc_args->utf8string_len >= MAXHOSTNAMELEN) { 6232f172c55SRobert Thurlow syslog(LOG_ERR, "argument too large"); 6242f172c55SRobert Thurlow failed_res.res_status = EOVERFLOW; 6252f172c55SRobert Thurlow failed_res.xdr_len = 0; 6262f172c55SRobert Thurlow res = (caddr_t)&failed_res; 6272f172c55SRobert Thurlow res_size = sizeof (refd_door_res_t); 6282f172c55SRobert Thurlow goto send_response; 6292f172c55SRobert Thurlow } 6302f172c55SRobert Thurlow 6312f172c55SRobert Thurlow snprintf(host, nfsfsloc_args->utf8string_len + 1, 6322f172c55SRobert Thurlow "%s", nfsfsloc_args->utf8string_val); 6332f172c55SRobert Thurlow 6342f172c55SRobert Thurlow nfs_fsloc_res = 6352f172c55SRobert Thurlow get_nfs4ref_info(host, NFS_PORT, NFS_V4); 6362f172c55SRobert Thurlow 6372f172c55SRobert Thurlow xdr_free(xdr_utf8string, (char *)&nfsfsloc_args); 6382f172c55SRobert Thurlow 6392f172c55SRobert Thurlow if (nfs_fsloc_res) { 6402f172c55SRobert Thurlow error = 0; 6412f172c55SRobert Thurlow error = encode_res(xdr_nfs_fsl_info, &door_res, 6422f172c55SRobert Thurlow (caddr_t)nfs_fsloc_res, &res_size); 6432f172c55SRobert Thurlow free_nfs4ref_info(nfs_fsloc_res); 6442f172c55SRobert Thurlow if (error != 0) { 6452f172c55SRobert Thurlow syslog(LOG_ERR, 6462f172c55SRobert Thurlow "error allocating fs_locations " 6472f172c55SRobert Thurlow "results buffer"); 6482f172c55SRobert Thurlow failed_res.res_status = error; 6492f172c55SRobert Thurlow failed_res.xdr_len = srsz; 6502f172c55SRobert Thurlow res = (caddr_t)&failed_res; 6512f172c55SRobert Thurlow res_size = sizeof (refd_door_res_t); 6522f172c55SRobert Thurlow } else { 6532f172c55SRobert Thurlow door_res->res_status = 0; 6542f172c55SRobert Thurlow res = (caddr_t)door_res; 6552f172c55SRobert Thurlow } 6562f172c55SRobert Thurlow } else { 6572f172c55SRobert Thurlow failed_res.res_status = EINVAL; 6582f172c55SRobert Thurlow failed_res.xdr_len = 0; 6592f172c55SRobert Thurlow res = (caddr_t)&failed_res; 6602f172c55SRobert Thurlow res_size = sizeof (refd_door_res_t); 6612f172c55SRobert Thurlow } 6622f172c55SRobert Thurlow 6632f172c55SRobert Thurlow send_response: 6642f172c55SRobert Thurlow srsz = res_size; 6652f172c55SRobert Thurlow errno = 0; 6662f172c55SRobert Thurlow 6672f172c55SRobert Thurlow error = door_return(res, res_size, NULL, 0); 6682f172c55SRobert Thurlow if (errno == E2BIG) { 6692f172c55SRobert Thurlow failed_res.res_status = EOVERFLOW; 6702f172c55SRobert Thurlow failed_res.xdr_len = srsz; 6712f172c55SRobert Thurlow res = (caddr_t)&failed_res; 6722f172c55SRobert Thurlow res_size = sizeof (refd_door_res_t); 6732f172c55SRobert Thurlow } else { 6742f172c55SRobert Thurlow res = NULL; 6752f172c55SRobert Thurlow res_size = 0; 6762f172c55SRobert Thurlow } 6772f172c55SRobert Thurlow 6782f172c55SRobert Thurlow door_return(res, res_size, NULL, 0); 6792f172c55SRobert Thurlow } 6802f172c55SRobert Thurlow 6817c478bd9Sstevel@tonic-gate /* ARGSUSED */ 6827c478bd9Sstevel@tonic-gate void 6837c478bd9Sstevel@tonic-gate nfsmapid_func(void *cookie, char *argp, size_t arg_size, 6847c478bd9Sstevel@tonic-gate door_desc_t *dp, uint_t n_desc) 6857c478bd9Sstevel@tonic-gate { 6867c478bd9Sstevel@tonic-gate struct mapid_arg *mapargp; 6877c478bd9Sstevel@tonic-gate struct mapid_res mapres; 6882f172c55SRobert Thurlow refd_door_args_t *referral_args; 6897c478bd9Sstevel@tonic-gate 6907c478bd9Sstevel@tonic-gate /* 6917c478bd9Sstevel@tonic-gate * Make sure we have a valid argument 6927c478bd9Sstevel@tonic-gate */ 6937c478bd9Sstevel@tonic-gate if (arg_size < sizeof (struct mapid_arg)) { 6947c478bd9Sstevel@tonic-gate mapres.status = NFSMAPID_INVALID; 6957c478bd9Sstevel@tonic-gate mapres.u_res.len = 0; 6967c478bd9Sstevel@tonic-gate (void) door_return((char *)&mapres, sizeof (struct mapid_res), 6977c478bd9Sstevel@tonic-gate NULL, 0); 6987c478bd9Sstevel@tonic-gate return; 6997c478bd9Sstevel@tonic-gate } 7007c478bd9Sstevel@tonic-gate 7017c478bd9Sstevel@tonic-gate /* LINTED pointer cast */ 7027c478bd9Sstevel@tonic-gate mapargp = (struct mapid_arg *)argp; 7032f172c55SRobert Thurlow referral_args = (refd_door_args_t *)argp; 7047c478bd9Sstevel@tonic-gate switch (mapargp->cmd) { 7057c478bd9Sstevel@tonic-gate case NFSMAPID_STR_UID: 7067c478bd9Sstevel@tonic-gate nfsmapid_str_uid(mapargp, arg_size); 7077c478bd9Sstevel@tonic-gate return; 7087c478bd9Sstevel@tonic-gate case NFSMAPID_UID_STR: 7097c478bd9Sstevel@tonic-gate nfsmapid_uid_str(mapargp, arg_size); 7107c478bd9Sstevel@tonic-gate return; 7117c478bd9Sstevel@tonic-gate case NFSMAPID_STR_GID: 7127c478bd9Sstevel@tonic-gate nfsmapid_str_gid(mapargp, arg_size); 7137c478bd9Sstevel@tonic-gate return; 7147c478bd9Sstevel@tonic-gate case NFSMAPID_GID_STR: 7157c478bd9Sstevel@tonic-gate nfsmapid_gid_str(mapargp, arg_size); 7167c478bd9Sstevel@tonic-gate return; 7172f172c55SRobert Thurlow case NFSMAPID_SRV_NETINFO: 7182f172c55SRobert Thurlow nfsmapid_server_netinfo(referral_args, arg_size); 7197c478bd9Sstevel@tonic-gate default: 7207c478bd9Sstevel@tonic-gate break; 7217c478bd9Sstevel@tonic-gate } 7227c478bd9Sstevel@tonic-gate mapres.status = NFSMAPID_INVALID; 7237c478bd9Sstevel@tonic-gate mapres.u_res.len = 0; 7247c478bd9Sstevel@tonic-gate (void) door_return((char *)&mapres, sizeof (struct mapid_res), NULL, 0); 7257c478bd9Sstevel@tonic-gate } 7267c478bd9Sstevel@tonic-gate 7278200fe25Srmesta /* 7288200fe25Srmesta * mapid_get_domain() always returns a ptr to TSD, so the 7298200fe25Srmesta * check for a NULL domain is not a simple comparison with 7308200fe25Srmesta * NULL but we need to check the contents of the TSD data. 7318200fe25Srmesta */ 7328200fe25Srmesta int 7338200fe25Srmesta cur_domain_null(void) 7348200fe25Srmesta { 7358200fe25Srmesta char *p; 7368200fe25Srmesta 7378200fe25Srmesta if ((p = mapid_get_domain()) == NULL) 7388200fe25Srmesta return (1); 7398200fe25Srmesta 7408200fe25Srmesta return (p[0] == '\0'); 7418200fe25Srmesta } 7428200fe25Srmesta 7438200fe25Srmesta int 7447c478bd9Sstevel@tonic-gate extract_domain(char *cp, char **upp, char **dpp) 7457c478bd9Sstevel@tonic-gate { 7467c478bd9Sstevel@tonic-gate /* 7477c478bd9Sstevel@tonic-gate * Caller must insure that the string is valid 7487c478bd9Sstevel@tonic-gate */ 7497c478bd9Sstevel@tonic-gate *upp = cp; 7507c478bd9Sstevel@tonic-gate 7517c478bd9Sstevel@tonic-gate if ((*dpp = strchr(cp, '@')) == NULL) 7527c478bd9Sstevel@tonic-gate return (0); 7537c478bd9Sstevel@tonic-gate *(*dpp)++ = '\0'; 7547c478bd9Sstevel@tonic-gate return (1); 7557c478bd9Sstevel@tonic-gate } 7567c478bd9Sstevel@tonic-gate 7578200fe25Srmesta int 7587c478bd9Sstevel@tonic-gate valid_domain(const char *dom) 7597c478bd9Sstevel@tonic-gate { 7607c478bd9Sstevel@tonic-gate const char *whoami = "valid_domain"; 7617c478bd9Sstevel@tonic-gate 7628200fe25Srmesta if (!mapid_stdchk_domain(dom)) { 7638200fe25Srmesta syslog(LOG_ERR, gettext("%s: Invalid inbound domain name %s."), 7648200fe25Srmesta whoami, dom); 7657c478bd9Sstevel@tonic-gate return (0); 7667c478bd9Sstevel@tonic-gate } 7677c478bd9Sstevel@tonic-gate 7688200fe25Srmesta /* 7698200fe25Srmesta * NOTE: mapid_get_domain() returns a ptr to TSD. 7708200fe25Srmesta */ 7718200fe25Srmesta return (strcasecmp(dom, mapid_get_domain()) == 0); 7727c478bd9Sstevel@tonic-gate } 7737c478bd9Sstevel@tonic-gate 7748200fe25Srmesta int 7757c478bd9Sstevel@tonic-gate validate_id_str(const char *id) 7767c478bd9Sstevel@tonic-gate { 7777c478bd9Sstevel@tonic-gate while (*id) { 7787c478bd9Sstevel@tonic-gate if (!isdigit(*id++)) 7797c478bd9Sstevel@tonic-gate return (0); 7807c478bd9Sstevel@tonic-gate } 7817c478bd9Sstevel@tonic-gate return (1); 7827c478bd9Sstevel@tonic-gate } 7837c478bd9Sstevel@tonic-gate 7847c478bd9Sstevel@tonic-gate void 7858200fe25Srmesta idmap_kcall(int door_id) 7867c478bd9Sstevel@tonic-gate { 7877c478bd9Sstevel@tonic-gate struct nfsidmap_args args; 7887c478bd9Sstevel@tonic-gate 7898200fe25Srmesta if (door_id >= 0) { 7907c478bd9Sstevel@tonic-gate args.state = 1; 7918200fe25Srmesta args.did = door_id; 7927c478bd9Sstevel@tonic-gate } else { 7937c478bd9Sstevel@tonic-gate args.state = 0; 7947c478bd9Sstevel@tonic-gate args.did = 0; 7957c478bd9Sstevel@tonic-gate } 7967c478bd9Sstevel@tonic-gate (void) _nfssys(NFS_IDMAP, &args); 7977c478bd9Sstevel@tonic-gate } 7987c478bd9Sstevel@tonic-gate 7997c478bd9Sstevel@tonic-gate /* 8007c478bd9Sstevel@tonic-gate * Get the current NFS domain. 8017c478bd9Sstevel@tonic-gate * 802*dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States * If nfsmapid_domain is set in NFS SMF, then it is the NFS domain; 8037c478bd9Sstevel@tonic-gate * otherwise, the DNS domain is used. 8047c478bd9Sstevel@tonic-gate */ 8057c478bd9Sstevel@tonic-gate void 8068200fe25Srmesta check_domain(int sighup) 8077c478bd9Sstevel@tonic-gate { 8087c478bd9Sstevel@tonic-gate const char *whoami = "check_domain"; 8097c478bd9Sstevel@tonic-gate static int setup_done = 0; 8108200fe25Srmesta static cb_t cb; 8117c478bd9Sstevel@tonic-gate 8127c478bd9Sstevel@tonic-gate /* 8138200fe25Srmesta * Construct the arguments to be passed to libmapid interface 8148200fe25Srmesta * If called in response to a SIGHUP, reset any cached DNS TXT 8158200fe25Srmesta * RR state. 8167c478bd9Sstevel@tonic-gate */ 8178200fe25Srmesta cb.fcn = cb_update_domain; 8188200fe25Srmesta cb.signal = sighup; 8198200fe25Srmesta mapid_reeval_domain(&cb); 8207c478bd9Sstevel@tonic-gate 8217c478bd9Sstevel@tonic-gate /* 8227c478bd9Sstevel@tonic-gate * Restart the signal handler thread if we're still setting up 8237c478bd9Sstevel@tonic-gate */ 8247c478bd9Sstevel@tonic-gate if (!setup_done) { 8257c478bd9Sstevel@tonic-gate setup_done = 1; 8267c478bd9Sstevel@tonic-gate if (thr_continue(sig_thread)) { 8277c478bd9Sstevel@tonic-gate syslog(LOG_ERR, gettext("%s: Fatal error: signal " 8287c478bd9Sstevel@tonic-gate "handler thread could not be restarted."), whoami); 8297c478bd9Sstevel@tonic-gate exit(6); 8307c478bd9Sstevel@tonic-gate } 8317c478bd9Sstevel@tonic-gate } 8327c478bd9Sstevel@tonic-gate } 8337c478bd9Sstevel@tonic-gate 8347c478bd9Sstevel@tonic-gate /* 8357c478bd9Sstevel@tonic-gate * Need to be able to open the DIAG_FILE before nfsmapid(1m) 8367c478bd9Sstevel@tonic-gate * releases it's root priviledges. The DIAG_FILE then remains 8378200fe25Srmesta * open for the duration of this nfsmapid instance via n4_fd. 8387c478bd9Sstevel@tonic-gate */ 8397c478bd9Sstevel@tonic-gate void 8407c478bd9Sstevel@tonic-gate open_diag_file() 8417c478bd9Sstevel@tonic-gate { 8427c478bd9Sstevel@tonic-gate static int msg_done = 0; 8437c478bd9Sstevel@tonic-gate 8448200fe25Srmesta if ((n4_fp = fopen(DIAG_FILE, "w+")) != NULL) { 8458200fe25Srmesta n4_fd = fileno(n4_fp); 8467c478bd9Sstevel@tonic-gate return; 8478200fe25Srmesta } 8487c478bd9Sstevel@tonic-gate 8497c478bd9Sstevel@tonic-gate if (msg_done) 8507c478bd9Sstevel@tonic-gate return; 8517c478bd9Sstevel@tonic-gate 8527c478bd9Sstevel@tonic-gate syslog(LOG_ERR, "Failed to create %s. Enable syslog " 8537c478bd9Sstevel@tonic-gate "daemon.debug for more info", DIAG_FILE); 8547c478bd9Sstevel@tonic-gate msg_done = 1; 8557c478bd9Sstevel@tonic-gate } 8567c478bd9Sstevel@tonic-gate 8577c478bd9Sstevel@tonic-gate /* 8587c478bd9Sstevel@tonic-gate * When a new domain name is configured, save to DIAG_FILE 8597c478bd9Sstevel@tonic-gate * and log to syslog, with LOG_DEBUG level (if configured). 8607c478bd9Sstevel@tonic-gate */ 8617c478bd9Sstevel@tonic-gate void 8627c478bd9Sstevel@tonic-gate update_diag_file(char *new) 8637c478bd9Sstevel@tonic-gate { 8648200fe25Srmesta char buf[DNAMEMAX]; 8658200fe25Srmesta ssize_t n; 8668200fe25Srmesta size_t len; 8678200fe25Srmesta 8688200fe25Srmesta (void) lseek(n4_fd, (off_t)0, SEEK_SET); 8698200fe25Srmesta (void) ftruncate(n4_fd, 0); 8708200fe25Srmesta (void) snprintf(buf, DNAMEMAX, "%s\n", new); 8718200fe25Srmesta 8728200fe25Srmesta len = strlen(buf); 8738200fe25Srmesta n = write(n4_fd, buf, len); 8748200fe25Srmesta if (n < 0 || n < len) 8758200fe25Srmesta syslog(LOG_DEBUG, "Could not write %s to diag file", new); 876dd5829d1Sbaban (void) fsync(n4_fd); 8777c478bd9Sstevel@tonic-gate 8787c478bd9Sstevel@tonic-gate syslog(LOG_DEBUG, "nfsmapid domain = %s", new); 8797c478bd9Sstevel@tonic-gate } 8808200fe25Srmesta 8818200fe25Srmesta /* 8828200fe25Srmesta * Callback function for libmapid. This will be called 8838200fe25Srmesta * by the lib, everytime the nfsmapid(1m) domain changes. 8848200fe25Srmesta */ 8858200fe25Srmesta void * 8868200fe25Srmesta cb_update_domain(void *arg) 8878200fe25Srmesta { 8888200fe25Srmesta char *new_dname = (char *)arg; 8898200fe25Srmesta 8908200fe25Srmesta DTRACE_PROBE1(nfsmapid, daemon__domain, new_dname); 8918200fe25Srmesta update_diag_file(new_dname); 8928200fe25Srmesta idmap_kcall(FLUSH_KCACHES_ONLY); 8938200fe25Srmesta 8948200fe25Srmesta return (NULL); 8958200fe25Srmesta } 8962f172c55SRobert Thurlow 8972f172c55SRobert Thurlow bool_t 8982f172c55SRobert Thurlow xdr_utf8string(XDR *xdrs, utf8string *objp) 8992f172c55SRobert Thurlow { 9002f172c55SRobert Thurlow if (xdrs->x_op != XDR_FREE) 9012f172c55SRobert Thurlow return (xdr_bytes(xdrs, (char **)&objp->utf8string_val, 9022f172c55SRobert Thurlow (uint_t *)&objp->utf8string_len, NFS4_MAX_UTF8STRING)); 9032f172c55SRobert Thurlow return (TRUE); 9042f172c55SRobert Thurlow } 9052f172c55SRobert Thurlow 9062f172c55SRobert Thurlow 9072f172c55SRobert Thurlow int 9082f172c55SRobert Thurlow decode_args(xdrproc_t xdrfunc, refd_door_args_t *argp, caddr_t *xdrargs, 9092f172c55SRobert Thurlow int size) 9102f172c55SRobert Thurlow { 9112f172c55SRobert Thurlow XDR xdrs; 9122f172c55SRobert Thurlow 9132f172c55SRobert Thurlow caddr_t tmpargs = (caddr_t)&((refd_door_args_t *)argp)->xdr_arg; 9142f172c55SRobert Thurlow size_t arg_size = ((refd_door_args_t *)argp)->xdr_len; 9152f172c55SRobert Thurlow 9162f172c55SRobert Thurlow xdrmem_create(&xdrs, tmpargs, arg_size, XDR_DECODE); 9172f172c55SRobert Thurlow 9182f172c55SRobert Thurlow *xdrargs = calloc(1, size); 9192f172c55SRobert Thurlow if (*xdrargs == NULL) { 9202f172c55SRobert Thurlow syslog(LOG_ERR, "error allocating arguments buffer"); 9212f172c55SRobert Thurlow return (ENOMEM); 9222f172c55SRobert Thurlow } 9232f172c55SRobert Thurlow 9242f172c55SRobert Thurlow if (!(*xdrfunc)(&xdrs, *xdrargs)) { 9252f172c55SRobert Thurlow free(*xdrargs); 9262f172c55SRobert Thurlow *xdrargs = NULL; 9272f172c55SRobert Thurlow syslog(LOG_ERR, "error decoding arguments"); 9282f172c55SRobert Thurlow return (EINVAL); 9292f172c55SRobert Thurlow } 9302f172c55SRobert Thurlow 9312f172c55SRobert Thurlow return (0); 9322f172c55SRobert Thurlow } 9332f172c55SRobert Thurlow 9342f172c55SRobert Thurlow int 9352f172c55SRobert Thurlow encode_res( 9362f172c55SRobert Thurlow xdrproc_t xdrfunc, 9372f172c55SRobert Thurlow refd_door_res_t **results, 9382f172c55SRobert Thurlow caddr_t resp, 9392f172c55SRobert Thurlow int *size) 9402f172c55SRobert Thurlow { 9412f172c55SRobert Thurlow XDR xdrs; 9422f172c55SRobert Thurlow 9432f172c55SRobert Thurlow *size = xdr_sizeof((*xdrfunc), resp); 9442f172c55SRobert Thurlow *results = malloc(sizeof (refd_door_res_t) + *size); 9452f172c55SRobert Thurlow if (*results == NULL) { 9462f172c55SRobert Thurlow return (ENOMEM); 9472f172c55SRobert Thurlow } 9482f172c55SRobert Thurlow (*results)->xdr_len = *size; 9492f172c55SRobert Thurlow *size = sizeof (refd_door_res_t) + (*results)->xdr_len; 9502f172c55SRobert Thurlow xdrmem_create(&xdrs, (caddr_t)((*results)->xdr_res), 9512f172c55SRobert Thurlow (*results)->xdr_len, XDR_ENCODE); 9522f172c55SRobert Thurlow if (!(*xdrfunc)(&xdrs, resp)) { 9532f172c55SRobert Thurlow (*results)->res_status = EINVAL; 9542f172c55SRobert Thurlow syslog(LOG_ERR, "error encoding results"); 9552f172c55SRobert Thurlow return ((*results)->res_status); 9562f172c55SRobert Thurlow } 9572f172c55SRobert Thurlow (*results)->res_status = 0; 9582f172c55SRobert Thurlow return ((*results)->res_status); 9592f172c55SRobert Thurlow } 9602f172c55SRobert Thurlow 9612f172c55SRobert Thurlow 9622f172c55SRobert Thurlow bool_t 9632f172c55SRobert Thurlow xdr_knetconfig(XDR *xdrs, struct knetconfig *objp) 9642f172c55SRobert Thurlow { 9652f172c55SRobert Thurlow rpc_inline_t *buf; 9662f172c55SRobert Thurlow int i; 9672f172c55SRobert Thurlow u_longlong_t dev64; 9682f172c55SRobert Thurlow #if !defined(_LP64) 9692f172c55SRobert Thurlow uint32_t major, minor; 9702f172c55SRobert Thurlow #endif 9712f172c55SRobert Thurlow 9722f172c55SRobert Thurlow if (!xdr_u_int(xdrs, &objp->knc_semantics)) 9732f172c55SRobert Thurlow return (FALSE); 9742f172c55SRobert Thurlow if (!xdr_opaque(xdrs, objp->knc_protofmly, KNC_STRSIZE)) 9752f172c55SRobert Thurlow return (FALSE); 9762f172c55SRobert Thurlow if (!xdr_opaque(xdrs, objp->knc_proto, KNC_STRSIZE)) 9772f172c55SRobert Thurlow return (FALSE); 9782f172c55SRobert Thurlow 9792f172c55SRobert Thurlow /* 9802f172c55SRobert Thurlow * For interoperability between 32-bit daemon and 64-bit kernel, 9812f172c55SRobert Thurlow * we always treat dev_t as 64-bit number and do the expanding 9822f172c55SRobert Thurlow * or compression of dev_t as needed. 9832f172c55SRobert Thurlow * We have to hand craft the conversion since there is no available 9842f172c55SRobert Thurlow * function in ddi.c. Besides ddi.c is available only in the kernel 9852f172c55SRobert Thurlow * and we want to keep both user and kernel of xdr_knetconfig() the 9862f172c55SRobert Thurlow * same for consistency. 9872f172c55SRobert Thurlow */ 9882f172c55SRobert Thurlow 9892f172c55SRobert Thurlow if (xdrs->x_op == XDR_ENCODE) { 9902f172c55SRobert Thurlow #if defined(_LP64) 9912f172c55SRobert Thurlow dev64 = objp->knc_rdev; 9922f172c55SRobert Thurlow #else 9932f172c55SRobert Thurlow major = (objp->knc_rdev >> NBITSMINOR32) & MAXMAJ32; 9942f172c55SRobert Thurlow minor = objp->knc_rdev & MAXMIN32; 9952f172c55SRobert Thurlow dev64 = (((unsigned long long)major) << NBITSMINOR64) | minor; 9962f172c55SRobert Thurlow #endif 9972f172c55SRobert Thurlow if (!xdr_u_longlong_t(xdrs, &dev64)) 9982f172c55SRobert Thurlow return (FALSE); 9992f172c55SRobert Thurlow } 10002f172c55SRobert Thurlow if (xdrs->x_op == XDR_DECODE) { 10012f172c55SRobert Thurlow #if defined(_LP64) 10022f172c55SRobert Thurlow if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->knc_rdev)) 10032f172c55SRobert Thurlow return (FALSE); 10042f172c55SRobert Thurlow #else 10052f172c55SRobert Thurlow if (!xdr_u_longlong_t(xdrs, &dev64)) 10062f172c55SRobert Thurlow return (FALSE); 10072f172c55SRobert Thurlow 10082f172c55SRobert Thurlow major = (dev64 >> NBITSMINOR64) & L_MAXMAJ32; 10092f172c55SRobert Thurlow minor = dev64 & L_MAXMIN32; 10102f172c55SRobert Thurlow objp->knc_rdev = (major << L_BITSMINOR32) | minor; 10112f172c55SRobert Thurlow #endif 10122f172c55SRobert Thurlow } 10132f172c55SRobert Thurlow 10142f172c55SRobert Thurlow if (xdrs->x_op == XDR_ENCODE) { 10152f172c55SRobert Thurlow buf = XDR_INLINE(xdrs, (8) * BYTES_PER_XDR_UNIT); 10162f172c55SRobert Thurlow if (buf == NULL) { 10172f172c55SRobert Thurlow if (!xdr_vector(xdrs, (char *)objp->knc_unused, 8, 10182f172c55SRobert Thurlow sizeof (uint_t), (xdrproc_t)xdr_u_int)) 10192f172c55SRobert Thurlow return (FALSE); 10202f172c55SRobert Thurlow } else { 10212f172c55SRobert Thurlow uint_t *genp; 10222f172c55SRobert Thurlow 10232f172c55SRobert Thurlow for (i = 0, genp = objp->knc_unused; 10242f172c55SRobert Thurlow i < 8; i++) { 10252f172c55SRobert Thurlow #if defined(_LP64) || defined(_KERNEL) 10262f172c55SRobert Thurlow IXDR_PUT_U_INT32(buf, *genp++); 10272f172c55SRobert Thurlow #else 10282f172c55SRobert Thurlow IXDR_PUT_U_LONG(buf, *genp++); 10292f172c55SRobert Thurlow #endif 10302f172c55SRobert Thurlow } 10312f172c55SRobert Thurlow } 10322f172c55SRobert Thurlow return (TRUE); 10332f172c55SRobert Thurlow } else if (xdrs->x_op == XDR_DECODE) { 10342f172c55SRobert Thurlow buf = XDR_INLINE(xdrs, (8) * BYTES_PER_XDR_UNIT); 10352f172c55SRobert Thurlow if (buf == NULL) { 10362f172c55SRobert Thurlow if (!xdr_vector(xdrs, (char *)objp->knc_unused, 8, 10372f172c55SRobert Thurlow sizeof (uint_t), (xdrproc_t)xdr_u_int)) 10382f172c55SRobert Thurlow return (FALSE); 10392f172c55SRobert Thurlow } else { 10402f172c55SRobert Thurlow uint_t *genp; 10412f172c55SRobert Thurlow 10422f172c55SRobert Thurlow for (i = 0, genp = objp->knc_unused; 10432f172c55SRobert Thurlow i < 8; i++) { 10442f172c55SRobert Thurlow #if defined(_LP64) || defined(_KERNEL) 10452f172c55SRobert Thurlow *genp++ = IXDR_GET_U_INT32(buf); 10462f172c55SRobert Thurlow #else 10472f172c55SRobert Thurlow *genp++ = IXDR_GET_U_LONG(buf); 10482f172c55SRobert Thurlow #endif 10492f172c55SRobert Thurlow } 10502f172c55SRobert Thurlow } 10512f172c55SRobert Thurlow return (TRUE); 10522f172c55SRobert Thurlow } 10532f172c55SRobert Thurlow 10542f172c55SRobert Thurlow if (!xdr_vector(xdrs, (char *)objp->knc_unused, 8, 10552f172c55SRobert Thurlow sizeof (uint_t), (xdrproc_t)xdr_u_int)) 10562f172c55SRobert Thurlow return (FALSE); 10572f172c55SRobert Thurlow return (TRUE); 10582f172c55SRobert Thurlow } 10592f172c55SRobert Thurlow 10602f172c55SRobert Thurlow /* 10612f172c55SRobert Thurlow * used by NFSv4 referrals to get info needed for NFSv4 referral mount. 10622f172c55SRobert Thurlow */ 10632f172c55SRobert Thurlow bool_t 10642f172c55SRobert Thurlow xdr_nfs_fsl_info(XDR *xdrs, struct nfs_fsl_info *objp) 10652f172c55SRobert Thurlow { 10662f172c55SRobert Thurlow 10672f172c55SRobert Thurlow if (!xdr_u_int(xdrs, &objp->netbuf_len)) 10682f172c55SRobert Thurlow return (FALSE); 10692f172c55SRobert Thurlow if (!xdr_u_int(xdrs, &objp->netnm_len)) 10702f172c55SRobert Thurlow return (FALSE); 10712f172c55SRobert Thurlow if (!xdr_u_int(xdrs, &objp->knconf_len)) 10722f172c55SRobert Thurlow return (FALSE); 10732f172c55SRobert Thurlow if (!xdr_string(xdrs, &objp->netname, ~0)) 10742f172c55SRobert Thurlow return (FALSE); 10752f172c55SRobert Thurlow if (!xdr_pointer(xdrs, (char **)&objp->addr, objp->netbuf_len, 10762f172c55SRobert Thurlow (xdrproc_t)xdr_netbuf)) 10772f172c55SRobert Thurlow return (FALSE); 10782f172c55SRobert Thurlow if (!xdr_pointer(xdrs, (char **)&objp->knconf, 10792f172c55SRobert Thurlow objp->knconf_len, (xdrproc_t)xdr_knetconfig)) 10802f172c55SRobert Thurlow return (FALSE); 10812f172c55SRobert Thurlow return (TRUE); 10822f172c55SRobert Thurlow } 1083