Home | History | Annotate | Download | only in mountd
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 
     22 /*
     23  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     24  * Use is subject to license terms.
     25  */
     26 
     27 #include <stdio.h>
     28 #include <stdlib.h>
     29 #include <sys/types.h>
     30 #include <string.h>
     31 #include <sys/param.h>
     32 #include <sys/stat.h>
     33 #include <sys/file.h>
     34 #include <sys/time.h>
     35 #include <sys/errno.h>
     36 #include <rpcsvc/mount.h>
     37 #include <sys/pathconf.h>
     38 #include <sys/systeminfo.h>
     39 #include <sys/utsname.h>
     40 #include <arpa/inet.h>
     41 #include <signal.h>
     42 #include <syslog.h>
     43 #include <locale.h>
     44 #include <unistd.h>
     45 #include <thread.h>
     46 #include <netdir.h>
     47 #include <nfs/auth.h>
     48 #include <sharefs/share.h>
     49 #include "../lib/sharetab.h"
     50 #include "mountd.h"
     51 
     52 static void
     53 nfsauth_access(auth_req *argp, auth_res *result)
     54 {
     55 	struct netconfig *nconf;
     56 	struct nd_hostservlist *clnames = NULL;
     57 	struct netbuf nbuf;
     58 	struct share *sh;
     59 	char tmp[MAXIPADDRLEN];
     60 	char *host = NULL;
     61 
     62 	result->auth_perm = NFSAUTH_DENIED;
     63 
     64 	/*
     65 	 * Convert the client's address to a hostname
     66 	 */
     67 	nconf = getnetconfigent(argp->req_netid);
     68 	if (nconf == NULL) {
     69 		syslog(LOG_ERR, "No netconfig entry for %s", argp->req_netid);
     70 		return;
     71 	}
     72 
     73 	nbuf.len = argp->req_client.n_len;
     74 	nbuf.buf = argp->req_client.n_bytes;
     75 
     76 	if (nbuf.len == 0 || nbuf.buf == NULL)
     77 		goto done;
     78 
     79 	if (netdir_getbyaddr(nconf, &clnames, &nbuf)) {
     80 		host = &tmp[0];
     81 		if (strcmp(nconf->nc_protofmly, NC_INET) == 0) {
     82 			struct sockaddr_in *sa;
     83 
     84 			/* LINTED pointer alignment */
     85 			sa = (struct sockaddr_in *)nbuf.buf;
     86 			(void) inet_ntoa_r(sa->sin_addr, tmp);
     87 		} else if (strcmp(nconf->nc_protofmly, NC_INET6) == 0) {
     88 			struct sockaddr_in6 *sa;
     89 			/* LINTED pointer */
     90 			sa = (struct sockaddr_in6 *)nbuf.buf;
     91 			(void) inet_ntop(AF_INET6, sa->sin6_addr.s6_addr,
     92 			    tmp, INET6_ADDRSTRLEN);
     93 		}
     94 		clnames = anon_client(host);
     95 	}
     96 	/*
     97 	 * Both netdir_getbyaddr() and anon_client() can return a NULL
     98 	 * clnames.  This has been seen when the DNS entry for the client
     99 	 * name does not have the correct format or a reverse lookup DNS
    100 	 * entry cannot be found for the client's IP address.
    101 	 */
    102 	if (clnames == NULL) {
    103 		syslog(LOG_ERR, "Could not find DNS entry for %s",
    104 		    argp->req_netid);
    105 		goto done;
    106 	}
    107 
    108 	/*
    109 	 * Now find the export
    110 	 */
    111 	sh = findentry(argp->req_path);
    112 	if (sh == NULL) {
    113 		syslog(LOG_ERR, "%s not exported", argp->req_path);
    114 		goto done;
    115 	}
    116 
    117 	result->auth_perm = check_client(sh, &nbuf, clnames, argp->req_flavor);
    118 
    119 	sharefree(sh);
    120 
    121 	if (result->auth_perm == NFSAUTH_DENIED) {
    122 		syslog(LOG_ERR, "%s denied access to %s",
    123 		    clnames->h_hostservs[0].h_host, argp->req_path);
    124 	}
    125 
    126 done:
    127 	freenetconfigent(nconf);
    128 	if (clnames)
    129 		netdir_free(clnames, ND_HOSTSERVLIST);
    130 }
    131 
    132 void
    133 nfsauth_func(void *cookie, char *dataptr, size_t arg_size,
    134 	door_desc_t *dp, uint_t n_desc)
    135 
    136 {
    137 	nfsauth_arg_t	*ap;
    138 	nfsauth_res_t	 res = {0};
    139 	nfsauth_res_t	*rp = &res;
    140 	XDR		 xdrs_a;
    141 	XDR		 xdrs_r;
    142 	caddr_t		 abuf = dataptr;
    143 	size_t		 absz = arg_size;
    144 	size_t		 rbsz = (size_t)(BYTES_PER_XDR_UNIT * 2);
    145 	char		 result[BYTES_PER_XDR_UNIT * 2];
    146 	caddr_t		 rbuf = (caddr_t)&result;
    147 	varg_t		 varg = {0};
    148 
    149 	/*
    150 	 * Decode the inbound door data, so we can look at the cmd.
    151 	 */
    152 	xdrmem_create(&xdrs_a, abuf, absz, XDR_DECODE);
    153 	if (!xdr_varg(&xdrs_a, &varg)) {
    154 		/*
    155 		 * If the arguments can't be decoded, bail.
    156 		 */
    157 		if (varg.vers == V_ERROR)
    158 			syslog(LOG_ERR, gettext("Arg version mismatch"));
    159 		res.stat = NFSAUTH_DR_DECERR;
    160 		goto encres;
    161 	}
    162 
    163 	/*
    164 	 * Now set the args pointer to the proper version of the args
    165 	 */
    166 	switch (varg.vers) {
    167 	case V_PROTO:
    168 		ap = &varg.arg_u.arg;
    169 		break;
    170 
    171 		/* Additional arguments versions go here */
    172 
    173 	default:
    174 		syslog(LOG_ERR, gettext("Invalid args version"));
    175 		goto encres;
    176 	}
    177 
    178 	/*
    179 	 * Call the specified cmd
    180 	 */
    181 	switch (ap->cmd) {
    182 		case NFSAUTH_ACCESS:
    183 			nfsauth_access(&ap->areq, &rp->ares);
    184 			rp->stat = NFSAUTH_DR_OKAY;
    185 			break;
    186 		default:
    187 			rp->stat = NFSAUTH_DR_BADCMD;
    188 			break;
    189 	}
    190 
    191 encres:
    192 	/*
    193 	 * Free space used to decode the args
    194 	 */
    195 	xdrs_a.x_op = XDR_FREE;
    196 	(void) xdr_varg(&xdrs_a, &varg);
    197 	xdr_destroy(&xdrs_a);
    198 
    199 	/*
    200 	 * Encode the results before passing thru door.
    201 	 *
    202 	 * The result (nfsauth_res_t) is always two int's, so we don't
    203 	 * have to dynamically size (or allocate) the results buffer.
    204 	 */
    205 	xdrmem_create(&xdrs_r, rbuf, rbsz, XDR_ENCODE);
    206 	if (!xdr_nfsauth_res(&xdrs_r, rp)) {
    207 		/*
    208 		 * return only the status code
    209 		 */
    210 		rp->stat = NFSAUTH_DR_EFAIL;
    211 		rbsz = sizeof (uint_t);
    212 		*rbuf = (uint_t)rp->stat;
    213 	}
    214 	xdr_destroy(&xdrs_r);
    215 
    216 	(void) door_return((char *)rbuf, rbsz, NULL, 0);
    217 	(void) door_return(NULL, 0, NULL, 0);
    218 	/* NOTREACHED */
    219 }
    220