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 /*
22dd51520eSPavan 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
nfsmapid_str_uid(struct mapid_arg * argp,size_t arg_size)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
nfsmapid_uid_str(struct mapid_arg * argp,size_t arg_size)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
nfsmapid_str_gid(struct mapid_arg * argp,size_t arg_size)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
nfsmapid_gid_str(struct mapid_arg * argp,size_t arg_size)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
nfsmapid_server_netinfo(refd_door_args_t * referral_args,size_t arg_size)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
nfsmapid_func(void * cookie,char * argp,size_t arg_size,door_desc_t * dp,uint_t n_desc)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
cur_domain_null(void)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
extract_domain(char * cp,char ** upp,char ** dpp)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
valid_domain(const char * dom)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
validate_id_str(const char * id)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
idmap_kcall(int door_id)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 *
802dd51520eSPavan 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
check_domain(int sighup)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 /*
835*bbf21555SRichard Lowe * Need to be able to open the DIAG_FILE before nfsmapid(8)
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
open_diag_file()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
update_diag_file(char * new)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
883*bbf21555SRichard Lowe * by the lib, everytime the nfsmapid(8) domain changes.
8848200fe25Srmesta */
8858200fe25Srmesta void *
cb_update_domain(void * arg)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
xdr_utf8string(XDR * xdrs,utf8string * objp)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
decode_args(xdrproc_t xdrfunc,refd_door_args_t * argp,caddr_t * xdrargs,int size)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
encode_res(xdrproc_t xdrfunc,refd_door_res_t ** results,caddr_t resp,int * size)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
xdr_knetconfig(XDR * xdrs,struct knetconfig * objp)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
xdr_nfs_fsl_info(XDR * xdrs,struct nfs_fsl_info * objp)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