usr/src/uts/common/fs/nfs/nfs4_client_secinfo.c
author jpk
Fri, 24 Mar 2006 12:29:20 -0800
changeset 1676 37f4a3e2bd99
parent 0 68f95e015346
child 1833 4b3da863bdb8
permissions -rw-r--r--
PSARC/2002/762 Layered Trusted Solaris PSARC/2005/060 TSNET: Trusted Networking with Security Labels PSARC/2005/259 Layered Trusted Solaris Label Interfaces PSARC/2005/573 Solaris Trusted Extensions for Printing PSARC/2005/691 Trusted Extensions for Device Allocation PSARC/2005/723 Solaris Trusted Extensions Filesystem Labeling PSARC/2006/009 Labeled Auditing PSARC/2006/155 Trusted Extensions RBAC Changes PSARC/2006/191 is_system_labeled 6293271 Zone processes should use zone_kcred instead of kcred 6394554 integrate Solaris Trusted Extensions
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     1
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     2
 * CDDL HEADER START
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     3
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     4
 * The contents of this file are subject to the terms of the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     5
 * Common Development and Distribution License, Version 1.0 only
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     6
 * (the "License").  You may not use this file except in compliance
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     7
 * with the License.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     8
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     9
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    10
 * or http://www.opensolaris.org/os/licensing.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    11
 * See the License for the specific language governing permissions
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    12
 * and limitations under the License.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    13
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    14
 * When distributing Covered Code, include this CDDL HEADER in each
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    15
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    16
 * If applicable, add the following below this CDDL HEADER, with the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    17
 * fields enclosed by brackets "[]" replaced with your own identifying
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    18
 * information: Portions Copyright [yyyy] [name of copyright owner]
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    19
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    20
 * CDDL HEADER END
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    21
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    22
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    23
 * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    24
 * Use is subject to license terms.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    25
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    26
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    27
#pragma ident	"%Z%%M%	%I%	%E% SMI"
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    28
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    29
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    30
 * NFS Version 4 client side SECINFO code.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    31
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    32
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    33
#include <nfs/nfs4_clnt.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    34
#include <nfs/nfs4.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    35
#include <nfs/nfs_clnt.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    36
#include <nfs/rnode4.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    37
#include <sys/cmn_err.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    38
#include <sys/cred.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    39
#include <sys/systm.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    40
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    41
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    42
 * Set up the security flavors supported in this release.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    43
 * In the order of potential usage.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    44
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    45
#define	SECINFO_SUPPORT_COUNT 6	/* sys, krb5, krb5i, krb5p, none, dh */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    46
static char krb5_val[] = {'\x2A', '\x86', '\x48', '\x86', '\xF7', \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    47
			'\x12', '\x01', '\x02', '\x02'};
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    48
static sec_oid4 krb5_oid = {9, krb5_val};
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    49
static SECINFO4res *secinfo_support;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    50
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    51
/* XXX should come from auth.h, do the cleanup someday */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    52
extern void sec_clnt_freeinfo(struct sec_data *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    53
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    54
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    55
 * "nfsstat -m" needs to print out what flavor is used for a mount
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    56
 * point. V3 kernel gets the nfs pseudo flavor from the userland and provides
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    57
 * nfsstat with such information. However, in V4, we do not have nfs pseudo
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    58
 * flavors mapping in the kernel for the rpcsec_gss data negotiated from
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    59
 * the nfs server.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    60
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    61
 * XXX
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    62
 * Hard coded the mapping in V4 for now. We should look into a possibility
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    63
 * to return the rpcsec_gss mechanism and service information to nfsstat and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    64
 * perhaps have nfsstat print out the mech and service seperately...
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    65
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    66
 * We should avoid referring to nfssec.conf file in V4. The original reason
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    67
 * for having /etc/nfssec.conf file is because V3 MOUNT protocol can only
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    68
 * return an integer for a flavor, thus the term "nfs pseudo flavor" is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    69
 * defined and the nfssec.conf file is used to map the nfs pseudo flavor
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    70
 * to rpcsec_gss data (mech, service, default-qop). Now, V4 can return the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    71
 * rpcsec_gss data instead of an integer, so in theory, V4 should not need
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    72
 * to depend on the nfssec.conf file anymore.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    73
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    74
#define	NFS_FLAVOR_KRB5		390003
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    75
#define	NFS_FLAVOR_KRB5I	390004
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    76
#define	NFS_FLAVOR_KRB5P	390005
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    77
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    78
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    79
 * Currently, 6 flavors are supported: sys, krb5, krb5i, krb5p, dh, none.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    80
 * Without proper keys, krb5* or dh will fail.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    81
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    82
 * XXX kgss_indicate_mechs() should be able to tell us what gss mechanisms
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    83
 * are supported on this host (/etc/gss/mech), thus nfs should be able to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    84
 * use them. However, the dh640 and dh1024 implementation are not nfs tested.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    85
 * Should look into using kgss_indicate_mechs when new gss mechanism is added.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    86
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    87
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    88
nfs4_secinfo_init(void)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    89
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    90
	secinfo4 *val;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    91
	int i;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    92
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    93
	secinfo_support = kmem_alloc(sizeof (SECINFO4res), KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    94
	secinfo_support->SECINFO4resok_len = SECINFO_SUPPORT_COUNT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    95
	val = kmem_alloc(
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    96
		secinfo_support->SECINFO4resok_len * sizeof (secinfo4),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    97
		KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    98
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    99
	val[0].flavor = AUTH_SYS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   100
	val[0].flavor_info.oid.sec_oid4_len = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   101
	val[0].flavor_info.oid.sec_oid4_val = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   102
	val[0].flavor_info.service = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   103
	val[0].flavor_info.qop = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   104
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   105
	/* add krb5, krb5i, krb5p */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   106
	for (i = 1; i <= 3; i++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   107
		val[i].flavor = RPCSEC_GSS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   108
		val[i].flavor_info.oid = krb5_oid;	/* struct copy */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   109
		val[i].flavor_info.service = i;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   110
		val[i].flavor_info.qop = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   111
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   112
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   113
	val[4].flavor = AUTH_DH;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   114
	val[4].flavor_info.oid.sec_oid4_len = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   115
	val[4].flavor_info.oid.sec_oid4_val = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   116
	val[4].flavor_info.service = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   117
	val[4].flavor_info.qop = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   118
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   119
	val[5].flavor = AUTH_NONE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   120
	val[5].flavor_info.oid.sec_oid4_len = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   121
	val[5].flavor_info.oid.sec_oid4_val = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   122
	val[5].flavor_info.service = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   123
	val[5].flavor_info.qop = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   124
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   125
#if !defined(lint)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   126
	ASSERT(SECINFO_SUPPORT_COUNT == 6);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   127
#endif
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   128
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   129
	secinfo_support->SECINFO4resok_val = val;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   130
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   131
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   132
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   133
 * clean up secinfo_support
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   134
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   135
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   136
nfs4_secinfo_fini(void)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   137
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   138
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   139
	kmem_free(secinfo_support->SECINFO4resok_val,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   140
		secinfo_support->SECINFO4resok_len * sizeof (secinfo4));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   141
	kmem_free(secinfo_support, sizeof (SECINFO4res));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   142
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   143
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   144
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   145
 * Map RPCSEC_GSS data to a nfs pseudo flavor number defined
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   146
 * in the nfssec.conf file.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   147
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   148
 * mechanism    service    qop       nfs-pseudo-flavor
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   149
 * ----------------------------------------------------
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   150
 * kerberos_v5  none       default   390003/krb5
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   151
 * kerberos_v5  integrity  default   390004/krb5i
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   152
 * kerberos_v5  privacy    default   390005/krb5p
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   153
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   154
 * XXX need to re-visit the mapping semantics when a new
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   155
 * security mechanism is to be added.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   156
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   157
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   158
secinfo2nfsflavor(sec_oid4 *mech_oid, rpc_gss_svc_t service)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   159
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   160
	/* Is this kerberos_v5? */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   161
	if (bcmp(mech_oid->sec_oid4_val, krb5_oid.sec_oid4_val,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   162
		krb5_oid.sec_oid4_len) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   163
		return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   164
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   165
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   166
	/* for krb5, krb5i, krb5p mapping */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   167
	switch (service) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   168
	case RPC_GSS_SVC_NONE:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   169
		return (NFS_FLAVOR_KRB5);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   170
	case RPC_GSS_SVC_INTEGRITY:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   171
		return (NFS_FLAVOR_KRB5I);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   172
	case RPC_GSS_SVC_PRIVACY:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   173
		return (NFS_FLAVOR_KRB5P);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   174
	default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   175
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   176
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   177
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   178
	/* no mapping */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   179
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   180
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   181
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   182
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   183
 * secinfo_create() maps the secinfo4 data coming over the wire
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   184
 * to sv_secinfo data structure in servinfo4_t
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   185
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   186
static sv_secinfo_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   187
secinfo_create(servinfo4_t *svp, SECINFO4res *sec_info, char *servname)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   188
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   189
	uint_t i, seccnt, scnt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   190
	sec_data_t *sdata;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   191
	sv_secinfo_t *sinfo;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   192
	uint_t len = sec_info->SECINFO4resok_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   193
	secinfo4 *value = sec_info->SECINFO4resok_val;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   194
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   195
	if (len == 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   196
		return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   197
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   198
	seccnt = len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   199
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   200
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   201
	 * If there is no valid sv_dhsec data available but an AUTH_DH
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   202
	 * is in the list, skip AUTH_DH flavor.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   203
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   204
	if (!svp->sv_dhsec) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   205
		for (i = 0; i < len; i++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   206
			if (value[i].flavor == AUTH_DH)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   207
				seccnt--;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   208
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   209
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   210
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   211
	if (seccnt == 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   212
		return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   213
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   214
	sdata = kmem_alloc(sizeof (sec_data_t) * seccnt, KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   215
	scnt = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   216
	for (i = 0; i < len; i++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   217
		secinfo4 *val = &value[i];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   218
		gss_clntdata_t *data;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   219
		rpcsec_gss_info *info;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   220
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   221
		sdata[scnt].flags = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   222
		sdata[scnt].rpcflavor = val->flavor;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   223
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   224
		switch (val->flavor) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   225
		case RPCSEC_GSS:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   226
			data = kmem_alloc(sizeof (gss_clntdata_t), KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   227
			data->realm[0] = '\0';
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   228
			info = &val->flavor_info;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   229
			data->service = (rpc_gss_service_t)info->service;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   230
			data->qop = (uint_t)info->qop;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   231
			data->mechanism.length = info->oid.sec_oid4_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   232
			data->mechanism.elements =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   233
				kmem_alloc(info->oid.sec_oid4_len, KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   234
			bcopy(info->oid.sec_oid4_val,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   235
			    data->mechanism.elements, info->oid.sec_oid4_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   236
			data->uname[0] = 'n'; data->uname[1] = 'f';
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   237
			data->uname[2] = 's'; data->uname[3] = '\0';
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   238
			(void) strcpy(data->inst, servname);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   239
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   240
			sdata[scnt].data = (caddr_t)data;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   241
			sdata[scnt].secmod =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   242
				secinfo2nfsflavor(&info->oid, info->service);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   243
			scnt++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   244
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   245
		case AUTH_DH:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   246
			if (svp->sv_dhsec) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   247
				sdata[scnt] = *svp->sv_dhsec;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   248
				scnt++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   249
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   250
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   251
			/* no auth_dh data on the client, skip auth_dh */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   252
			continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   253
		default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   254
			sdata[scnt].secmod = val->flavor;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   255
			sdata[scnt].data = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   256
			scnt++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   257
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   258
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   259
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   260
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   261
	ASSERT(seccnt == scnt);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   262
	sinfo = kmem_alloc(sizeof (sv_secinfo_t), KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   263
	sinfo->count = seccnt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   264
	sinfo->sdata = sdata;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   265
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   266
	return (sinfo);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   267
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   268
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   269
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   270
 * secinfo_free() frees the malloc'd portion of a sv_secinfo_t in servinfo4_t.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   271
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   272
 * This is similar to sec_clnt_freeinfo() offered from rpcsec module,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   273
 * except that sec_clnt_freeinfo() frees up an individual secdata.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   274
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   275
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   276
secinfo_free(sv_secinfo_t *secinfo)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   277
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   278
	int i;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   279
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   280
	if (secinfo == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   281
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   282
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   283
	for (i = 0; i < secinfo->count; i++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   284
	    if (secinfo->sdata[i].rpcflavor == RPCSEC_GSS) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   285
		gss_clntdata_t *data = (gss_clntdata_t *)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   286
						secinfo->sdata[i].data;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   287
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   288
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   289
		 * An auth handle may already cached in rpcsec_gss module
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   290
		 * per this secdata. Purge the cache entry before freeing
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   291
		 * up this secdata. Can't use sec_clnt_freeinfo since
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   292
		 * the allocation of secinfo is different from sec_data.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   293
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   294
		(void) rpc_gss_secpurge((void *)&secinfo->sdata[i]);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   295
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   296
		kmem_free(data->mechanism.elements, data->mechanism.length);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   297
		kmem_free(data, sizeof (gss_clntdata_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   298
	    }
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   299
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   300
	    if (secinfo->sdata[i].rpcflavor == AUTH_DH) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   301
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   302
		secinfo->sdata[i].data = NULL; /* release ref to sv_dhsec */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   303
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   304
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   305
		 * No need to purge the auth_dh cache entry (e.g. call
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   306
		 * purge_authtab()) since the AUTH_DH data used here
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   307
		 * are always the same.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   308
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   309
	    }
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   310
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   311
	kmem_free(secinfo->sdata, sizeof (sec_data_t) * secinfo->count);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   312
	kmem_free(secinfo, sizeof (sv_secinfo_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   313
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   314
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   315
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   316
 * Check if there is more secinfo to try.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   317
 * If TRUE, try again.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   318
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   319
static bool_t
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   320
secinfo_check(servinfo4_t *svp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   321
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   322
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   323
	(void) nfs_rw_enter_sig(&svp->sv_lock, RW_WRITER, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   324
	if (svp->sv_secinfo == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   325
		nfs_rw_exit(&svp->sv_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   326
		return (FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   327
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   328
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   329
	svp->sv_secinfo->index++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   330
	if (svp->sv_secinfo->index < svp->sv_secinfo->count) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   331
		svp->sv_flags |= SV4_TRYSECINFO;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   332
		svp->sv_currsec =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   333
			&svp->sv_secinfo->sdata[svp->sv_secinfo->index];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   334
		nfs_rw_exit(&svp->sv_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   335
		return (TRUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   336
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   337
		svp->sv_secinfo->index = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   338
		svp->sv_flags &= ~SV4_TRYSECINFO;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   339
		svp->sv_currsec = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   340
		nfs_rw_exit(&svp->sv_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   341
		return (FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   342
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   343
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   344
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   345
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   346
 * Update the secinfo related fields in svp.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   347
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   348
 * secinfo_update will free the previous sv_secinfo and update with
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   349
 * the new secinfo. However, if the sv_secinfo is saved into sv_save_secinfo
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   350
 * before the recovery starts via save_mnt_secinfo(), sv_secinfo will not
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   351
 * be freed until the recovery is done.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   352
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   353
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   354
secinfo_update(servinfo4_t *svp, SECINFO4res *sec_info)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   355
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   356
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   357
	sv_secinfo_t *newsecinfo;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   358
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   359
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   360
	 * Create secinfo before freeing the old one to make sure
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   361
	 * they are not using the same address.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   362
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   363
	newsecinfo = secinfo_create(svp, sec_info, svp->sv_hostname);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   364
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   365
	(void) nfs_rw_enter_sig(&svp->sv_lock, RW_WRITER, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   366
	if (svp->sv_secinfo && svp->sv_secinfo != svp->sv_save_secinfo) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   367
		secinfo_free(svp->sv_secinfo);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   368
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   369
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   370
	svp->sv_secinfo = newsecinfo;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   371
	if (svp->sv_secinfo) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   372
		svp->sv_secinfo->index = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   373
		svp->sv_flags |= SV4_TRYSECINFO;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   374
		svp->sv_currsec =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   375
			&svp->sv_secinfo->sdata[svp->sv_secinfo->index];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   376
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   377
		svp->sv_flags &= ~SV4_TRYSECINFO;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   378
		svp->sv_currsec = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   379
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   380
	nfs_rw_exit(&svp->sv_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   381
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   382
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   383
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   384
 * Save the original mount point security information.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   385
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   386
 * sv_savesec saves the pointer of sv_currsec which points to one of the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   387
 * secinfo data in the sv_secinfo list. i.e. sv_currsec == &sv_secinfo[index].
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   388
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   389
 * sv_save_secinfo saves the pointer of sv_secinfo which is the list of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   390
 * secinfo data returned by the server.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   391
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   392
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   393
save_mnt_secinfo(servinfo4_t *svp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   394
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   395
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   396
	(void) nfs_rw_enter_sig(&svp->sv_lock, RW_WRITER, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   397
	if (svp->sv_currsec) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   398
		svp->sv_savesec = svp->sv_currsec;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   399
		svp->sv_save_secinfo = svp->sv_secinfo;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   400
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   401
		ASSERT(svp->sv_save_secinfo == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   402
		svp->sv_savesec = svp->sv_secdata;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   403
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   404
	nfs_rw_exit(&svp->sv_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   405
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   406
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   407
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   408
 * Check if we need to restore what is saved in sv_savesec and sv_save_secinfo
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   409
 * to be the current secinfo information - sv_currsec and sv_secinfo.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   410
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   411
 * If op a node that is a stub for a crossed mount point,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   412
 * keep the original secinfo flavor for the current file system,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   413
 * not the crossed one.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   414
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   415
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   416
check_mnt_secinfo(servinfo4_t *svp, vnode_t *vp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   417
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   418
	bool_t is_restore;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   419
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   420
	(void) nfs_rw_enter_sig(&svp->sv_lock, RW_WRITER, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   421
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   422
	is_restore = (vp == NULL || (VTOR4(vp)->r_flags & R4SRVSTUB)) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   423
			svp->sv_save_secinfo &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   424
			(svp->sv_secinfo != svp->sv_save_secinfo);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   425
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   426
	if (is_restore) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   427
		secinfo_free(svp->sv_secinfo);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   428
		if (svp->sv_savesec == svp->sv_secdata) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   429
			ASSERT(svp->sv_save_secinfo == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   430
			svp->sv_secinfo = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   431
			svp->sv_currsec = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   432
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   433
			ASSERT(svp->sv_save_secinfo != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   434
			svp->sv_secinfo = svp->sv_save_secinfo;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   435
			svp->sv_currsec = svp->sv_savesec;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   436
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   437
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   438
		if (svp->sv_save_secinfo &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   439
				svp->sv_save_secinfo != svp->sv_secinfo)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   440
			secinfo_free(svp->sv_save_secinfo);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   441
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   442
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   443
	svp->sv_save_secinfo = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   444
	svp->sv_savesec = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   445
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   446
	nfs_rw_exit(&svp->sv_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   447
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   448
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   449
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   450
 * Use the security flavors supported on the client to try
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   451
 * PUTROOTFH until a flavor is found.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   452
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   453
 * PUTROOTFH could return NFS4ERR_RESOURCE and NFS4ERR_WRONGSEC that
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   454
 * may need a recovery action. This routine only handles NFS4ERR_WRONGSEC.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   455
 * For other recovery action, it returns ok to the caller for retry.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   456
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   457
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   458
secinfo_tryroot_otw(mntinfo4_t *mi, cred_t *cr)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   459
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   460
	COMPOUND4args_clnt args;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   461
	COMPOUND4res_clnt res;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   462
	nfs_argop4 argop;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   463
	int doqueue = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   464
	bool_t needrecov = FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   465
	nfs4_error_t e = { 0, NFS4_OK, RPC_SUCCESS };
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   466
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   467
	/* use the flavors supported on the client */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   468
	secinfo_update(mi->mi_curr_serv, secinfo_support);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   469
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   470
	/* Compound {Putroofh} */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   471
	args.ctag = TAG_PUTROOTFH;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   472
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   473
	args.array_len = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   474
	args.array = &argop;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   475
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   476
	argop.argop = OP_PUTROOTFH;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   477
retry:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   478
	NFS4_DEBUG(nfs4_client_call_debug, (CE_NOTE,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   479
	    "secinfo_tryroot_otw: %s call, mi 0x%p",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   480
	    needrecov ? "recov" : "first", (void*)mi));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   481
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   482
	rfs4call(mi, &args, &res, cr, &doqueue, RFSCALL_SOFT, &e);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   483
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   484
	needrecov = nfs4_needs_recovery(&e, FALSE, mi->mi_vfsp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   485
	if (e.error && !needrecov) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   486
		return (e.error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   487
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   488
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   489
	if (res.status == NFS4ERR_WRONGSEC) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   490
		(void) xdr_free(xdr_COMPOUND4res_clnt, (caddr_t)&res);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   491
		if (secinfo_check(mi->mi_curr_serv))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   492
			goto retry;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   493
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   494
		 * Have tried all flavors supported on the client,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   495
		 * but still get NFS4ERR_WRONGSEC. Nothing more can
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   496
		 * be done.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   497
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   498
		return (geterrno4(res.status));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   499
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   500
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   501
	if (needrecov) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   502
		NFS4_DEBUG(nfs4_client_recov_debug, (CE_NOTE,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   503
		    "secinfo_tryroot_otw: let the caller retry\n"));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   504
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   505
		if (!e.error)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   506
			(void) xdr_free(xdr_COMPOUND4res_clnt, (caddr_t)&res);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   507
		return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   508
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   509
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   510
	if (res.status) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   511
		(void) xdr_free(xdr_COMPOUND4res_clnt, (caddr_t)&res);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   512
		return (geterrno4(res.status));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   513
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   514
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   515
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   516
	 * Done.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   517
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   518
	 * Now, mi->sv_curr_server->sv_currsec points to the flavor found.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   519
	 * SV4_TRYSECINFO has been cleared in rfs4call.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   520
	 * sv_currsec will be used.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   521
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   522
	(void) xdr_free(xdr_COMPOUND4res_clnt, (caddr_t)&res);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   523
	return (e.error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   524
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   525
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   526
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   527
 * Caculate the total number of components within a given pathname.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   528
 * Assuming the given pathname is not null.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   529
 * e.g. returns 5 for "/a/b/c/d/e" or "a/b/c/d/e"
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   530
 *	returns 0 for "/"
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   531
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   532
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   533
comp_total(char *inpath)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   534
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   535
	int tnum = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   536
	char *slash;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   537
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   538
	while (*inpath != '\0') {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   539
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   540
		if (*inpath == '/') {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   541
			inpath++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   542
			continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   543
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   544
		if ((slash = (char *)strchr(inpath, '/')) == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   545
			tnum++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   546
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   547
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   548
			tnum++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   549
			inpath = slash + 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   550
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   551
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   552
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   553
	return (tnum);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   554
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   555
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   556
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   557
 * Get the pointer of the n-th component in the given path.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   558
 * Mark the preceeding '/' of the component to be '\0' when done.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   559
 * Assuming nth is > 0.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   560
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   561
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   562
comp_getn(char *inpath, int nth, component4 *comp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   563
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   564
	char *path = inpath, *comp_start, *slash = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   565
	int count = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   566
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   567
	while ((count != nth) && (*path != '\0')) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   568
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   569
		comp_start = path;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   570
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   571
		/* ignore slashes prior to the component name */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   572
		while (*path == '/')
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   573
			path++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   574
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   575
		if (*path != '\0') {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   576
			comp_start = path;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   577
			count++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   578
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   579
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   580
		if ((slash = strchr(path, '/')) == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   581
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   582
		else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   583
			path = slash + 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   584
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   585
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   586
	if (count == nth) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   587
		if (slash)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   588
			*slash = '\0';
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   589
		comp->utf8string_len = strlen(comp_start);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   590
		comp->utf8string_val = comp_start;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   591
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   592
		if (comp_start != inpath) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   593
			comp_start--;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   594
			*comp_start = '\0';
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   595
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   596
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   597
		comp->utf8string_len = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   598
		comp->utf8string_val = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   599
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   600
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   601
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   602
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   603
 * SECINFO over the wire compound operation
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   604
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   605
 *	compound {PUTROOTFH, {LOOKUP parent-path}, SECINFO component}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   606
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   607
 * This routine assumes there is a component to work on, thus the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   608
 * given pathname (svp->sv_path) has to have at least 1 component.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   609
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   610
 * isrecov - TRUE if this routine is called from a recovery thread.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   611
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   612
 * nfs4secinfo_otw() only deals with NFS4ERR_WRONGSEC recovery. If this
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   613
 * is already in a recovery thread, then setup the non-wrongsec recovery
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   614
 * action thru nfs4_start_recovery and return to the outer loop in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   615
 * nfs4_recov_thread() for recovery. If this is not called from a recovery
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   616
 * thread, then error out and let the caller decide what to do.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   617
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   618
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   619
nfs4secinfo_otw(mntinfo4_t *mi, cred_t *cr, servinfo4_t *svp, int isrecov)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   620
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   621
	COMPOUND4args_clnt args;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   622
	COMPOUND4res_clnt res;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   623
	nfs_argop4 *argop;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   624
	nfs_resop4 *resop;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   625
	lookup4_param_t lookuparg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   626
	uint_t path_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   627
	int doqueue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   628
	int numops, num_argops;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   629
	char *tmp_path;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   630
	component4 comp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   631
	uint_t ncomp, tcomp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   632
	bool_t needrecov = FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   633
	nfs4_error_t e = { 0, NFS4_OK, RPC_SUCCESS };
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   634
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   635
	(void) nfs_rw_enter_sig(&svp->sv_lock, RW_READER, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   636
	ncomp = tcomp = comp_total(svp->sv_path);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   637
	path_len = strlen(svp->sv_path);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   638
	nfs_rw_exit(&svp->sv_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   639
	ASSERT(ncomp > 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   640
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   641
retry:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   642
	tmp_path = kmem_alloc(path_len + 1, KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   643
	(void) nfs_rw_enter_sig(&svp->sv_lock, RW_READER, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   644
	bcopy(svp->sv_path, tmp_path, path_len + 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   645
	nfs_rw_exit(&svp->sv_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   646
	comp_getn(tmp_path, ncomp, &comp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   647
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   648
	args.ctag = TAG_SECINFO;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   649
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   650
	lookuparg.l4_getattrs = LKP4_NO_ATTRIBUTES;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   651
	lookuparg.argsp = &args;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   652
	lookuparg.resp = &res;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   653
	lookuparg.header_len = 1;	/* Putrootfh */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   654
	lookuparg.trailer_len = 1;	/* Secinfo */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   655
	lookuparg.ga_bits = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   656
	lookuparg.mi = mi;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   657
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   658
	/* setup LOOKUPs for parent path */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   659
	(void) nfs4lookup_setup(tmp_path, &lookuparg, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   660
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   661
	argop = args.array;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   662
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   663
	/* put root fh */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   664
	argop[0].argop = OP_PUTROOTFH;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   665
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   666
	/* setup SECINFO op */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   667
	num_argops = args.array_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   668
	argop[num_argops - 1].argop = OP_SECINFO;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   669
	argop[num_argops - 1].nfs_argop4_u.opsecinfo.name.utf8string_len =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   670
					comp.utf8string_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   671
	argop[num_argops - 1].nfs_argop4_u.opsecinfo.name.utf8string_val =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   672
					comp.utf8string_val;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   673
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   674
	doqueue = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   675
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   676
	NFS4_DEBUG(nfs4_client_call_debug, (CE_NOTE,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   677
	    "nfs4secinfo_otw: %s call, mi 0x%p",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   678
	    needrecov ? "recov" : "first", (void*)mi));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   679
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   680
	rfs4call(mi, &args, &res, cr, &doqueue, RFSCALL_SOFT, &e);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   681
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   682
	needrecov = nfs4_needs_recovery(&e, FALSE, mi->mi_vfsp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   683
	if (e.error && !needrecov) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   684
		nfs4args_lookup_free(argop, num_argops);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   685
		kmem_free(argop, lookuparg.arglen * sizeof (nfs_argop4));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   686
		kmem_free(tmp_path, path_len + 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   687
		return (e.error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   688
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   689
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   690
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   691
	 * Secinfo compound op may fail with NFS4ERR_WRONGSEC from
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   692
	 * PUTROOTFH or LOOKUP. Special handling here to recover it.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   693
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   694
	if (res.status == NFS4ERR_WRONGSEC) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   695
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   696
		if (res.array_len == 1) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   697
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   698
			 * If a flavor can not be found via trying
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   699
			 * all supported flavors on the client, no
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   700
			 * more operations.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   701
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   702
			ncomp = tcomp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   703
			nfs4args_lookup_free(argop, num_argops);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   704
			kmem_free(argop,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   705
					lookuparg.arglen * sizeof (nfs_argop4));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   706
			(void) xdr_free(xdr_COMPOUND4res_clnt, (caddr_t)&res);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   707
			kmem_free(tmp_path, path_len + 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   708
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   709
			if (e.error = secinfo_tryroot_otw(mi, cr)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   710
				return (e.error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   711
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   712
			goto retry;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   713
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   714
		ncomp = res.array_len - 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   715
		nfs4args_lookup_free(argop, num_argops);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   716
		kmem_free(argop, lookuparg.arglen * sizeof (nfs_argop4));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   717
		(void) xdr_free(xdr_COMPOUND4res_clnt, (caddr_t)&res);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   718
		kmem_free(tmp_path, path_len + 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   719
		goto retry;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   720
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   721
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   722
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   723
	 * This routine does not do recovery for non NFS4ERR_WRONGSEC error.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   724
	 * However, if this is already in a recovery thread, then
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   725
	 * set up the recovery action thru nfs4_start_recovery and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   726
	 * return ok back to the outer loop in nfs4_recov_thread for
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   727
	 * recovery.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   728
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   729
	if (needrecov) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   730
		bool_t abort;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   731
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   732
		/* If not in a recovery thread, bail out */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   733
		if (!isrecov) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   734
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   735
		    if (!e.error) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   736
			e.error = geterrno4(res.status);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   737
			(void) xdr_free(xdr_COMPOUND4res_clnt, (caddr_t)&res);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   738
		    }
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   739
		    nfs4args_lookup_free(argop, num_argops);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   740
		    kmem_free(argop, lookuparg.arglen * sizeof (nfs_argop4));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   741
		    kmem_free(tmp_path, path_len + 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   742
		    return (e.error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   743
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   744
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   745
		NFS4_DEBUG(nfs4_client_recov_debug, (CE_NOTE,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   746
		    "nfs4secinfo_otw: recovery in a recovery thread\n"));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   747
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   748
		abort = nfs4_start_recovery(&e, mi, NULL,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   749
			    NULL, NULL, NULL, OP_SECINFO, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   750
		if (!e.error) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   751
			e.error = geterrno4(res.status);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   752
			(void) xdr_free(xdr_COMPOUND4res_clnt, (caddr_t)&res);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   753
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   754
		nfs4args_lookup_free(argop, num_argops);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   755
		kmem_free(argop, lookuparg.arglen * sizeof (nfs_argop4));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   756
		kmem_free(tmp_path, path_len + 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   757
		if (abort == FALSE) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   758
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   759
			 * Return ok to let the outer loop in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   760
			 * nfs4_recov_thread continue with the recovery action.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   761
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   762
			return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   763
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   764
		return (e.error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   765
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   766
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   767
	if (res.status) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   768
		nfs4args_lookup_free(argop, num_argops);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   769
		kmem_free(argop, lookuparg.arglen * sizeof (nfs_argop4));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   770
		(void) xdr_free(xdr_COMPOUND4res_clnt, (caddr_t)&res);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   771
		kmem_free(tmp_path, path_len + 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   772
		return (geterrno4(res.status));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   773
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   774
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   775
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   776
	 * Success! Now get the SECINFO result.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   777
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   778
	numops = res.array_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   779
	resop = &res.array[numops-1];	/* secinfo res */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   780
	ASSERT(resop->resop == OP_SECINFO);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   781
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   782
	if (resop->nfs_resop4_u.opsecinfo.SECINFO4resok_len == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   783
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   784
		 * Server does not return any flavor for this export point.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   785
		 * Return EACCES.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   786
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   787
		nfs4args_lookup_free(argop, num_argops);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   788
		kmem_free(tmp_path, path_len + 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   789
		(void) xdr_free(xdr_COMPOUND4res_clnt, (caddr_t)&res);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   790
		kmem_free(argop, num_argops * sizeof (nfs_argop4));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   791
		return (EACCES);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   792
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   793
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   794
	secinfo_update(mi->mi_curr_serv, &resop->nfs_resop4_u.opsecinfo);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   795
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   796
	(void) nfs_rw_enter_sig(&svp->sv_lock, RW_READER, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   797
	if (svp->sv_secinfo == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   798
		nfs_rw_exit(&svp->sv_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   799
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   800
		 * This could be because the server requires AUTH_DH, but
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   801
		 * the client does not have netname/syncaddr data
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   802
		 * from sv_dhsec.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   803
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   804
		nfs4args_lookup_free(argop, num_argops);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   805
		kmem_free(argop, lookuparg.arglen * sizeof (nfs_argop4));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   806
		(void) xdr_free(xdr_COMPOUND4res_clnt, (caddr_t)&res);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   807
		kmem_free(tmp_path, path_len + 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   808
		return (EACCES);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   809
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   810
	nfs_rw_exit(&svp->sv_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   811
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   812
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   813
	 * If this is not the original request, try again using the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   814
	 * new secinfo data in mi.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   815
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   816
	if (ncomp != tcomp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   817
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   818
		ncomp = tcomp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   819
		nfs4args_lookup_free(argop, num_argops);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   820
		kmem_free(argop, lookuparg.arglen * sizeof (nfs_argop4));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   821
		(void) xdr_free(xdr_COMPOUND4res_clnt, (caddr_t)&res);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   822
		kmem_free(tmp_path, path_len + 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   823
		goto retry;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   824
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   825
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   826
	/* Done! */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   827
	nfs4args_lookup_free(argop, num_argops);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   828
	kmem_free(argop, lookuparg.arglen * sizeof (nfs_argop4));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   829
	(void) xdr_free(xdr_COMPOUND4res_clnt, (caddr_t)&res);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   830
	kmem_free(tmp_path, path_len + 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   831
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   832
	return (0); /* got the secinfo */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   833
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   834
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   835
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   836
 * Get the security information per mount point.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   837
 * Use the server pathname to get the secinfo.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   838
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   839
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   840
nfs4_secinfo_path(mntinfo4_t *mi, cred_t *cr, int isrecov)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   841
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   842
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   843
	int error = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   844
	int pathlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   845
	servinfo4_t *svp = mi->mi_curr_serv;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   846
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   847
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   848
	 * Get the server pathname that is being mounted on.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   849
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   850
	(void) nfs_rw_enter_sig(&svp->sv_lock, RW_READER, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   851
	ASSERT(svp->sv_path != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   852
	pathlen = strlen(svp->sv_path);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   853
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   854
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   855
	 * If mounting server rootdir, use available secinfo list
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   856
	 * on the client. No SECINFO call here since SECINFO op
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   857
	 * expects a component name.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   858
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   859
	if (pathlen == 1 && svp->sv_path[0] == '/') {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   860
		if (svp->sv_secinfo == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   861
			nfs_rw_exit(&svp->sv_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   862
			secinfo_update(svp, secinfo_support);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   863
			return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   864
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   865
		nfs_rw_exit(&svp->sv_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   866
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   867
		if (secinfo_check(svp))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   868
			return (0); /* try again */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   869
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   870
		/* no flavors in sv_secinfo work */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   871
		return (EACCES);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   872
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   873
	nfs_rw_exit(&svp->sv_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   874
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   875
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   876
	 * Get the secinfo from the server.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   877
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   878
	error = nfs4secinfo_otw(mi, cr, svp, isrecov);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   879
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   880
	if (error) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   881
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   882
		(void) nfs_rw_enter_sig(&svp->sv_lock, RW_WRITER, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   883
		if (svp->sv_secinfo) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   884
			if (svp->sv_save_secinfo == svp->sv_secinfo) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   885
				svp->sv_save_secinfo = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   886
				svp->sv_savesec = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   887
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   888
			secinfo_free(svp->sv_secinfo);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   889
			svp->sv_secinfo = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   890
			svp->sv_currsec = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   891
			svp->sv_flags &= ~SV4_TRYSECINFO;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   892
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   893
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   894
		if (svp->sv_save_secinfo) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   895
			secinfo_free(svp->sv_save_secinfo);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   896
			svp->sv_save_secinfo = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   897
			svp->sv_savesec = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   898
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   899
		nfs_rw_exit(&svp->sv_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   900
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   901
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   902
	return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   903
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   904
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   905
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   906
 * (secinfo) compound based on a given filehandle and component name.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   907
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   908
 * i.e. (secinfo) PUTFH (fh), SECINFO nm
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   909
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   910
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   911
nfs4_secinfo_fh_otw(mntinfo4_t *mi, nfs4_sharedfh_t *fh, char *nm, cred_t *cr)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   912
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   913
	COMPOUND4args_clnt args;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   914
	COMPOUND4res_clnt res;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   915
	nfs_argop4 argop[2];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   916
	nfs_resop4 *resop;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   917
	int num_argops, doqueue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   918
	nfs4_error_t e = { 0, NFS4_OK, RPC_SUCCESS };
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   919
	servinfo4_t *svp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   920
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   921
	ASSERT(strlen(nm) > 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   922
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   923
	num_argops = 2; /* Putfh, Secinfo nm */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   924
	args.ctag = TAG_SECINFO;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   925
	args.array_len = num_argops;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   926
	args.array = argop;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   927
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   928
	/* putfh fh */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   929
	argop[0].argop = OP_CPUTFH;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   930
	argop[0].nfs_argop4_u.opcputfh.sfh = fh;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   931
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   932
	/* setup SECINFO op */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   933
	argop[1].argop = OP_CSECINFO;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   934
	argop[1].nfs_argop4_u.opcsecinfo.cname = nm;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   935
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   936
	doqueue = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   937
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   938
	rfs4call(mi, &args, &res, cr, &doqueue, RFSCALL_SOFT, &e);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   939
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   940
	if (e.error)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   941
		return (e.error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   942
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   943
	if (res.status) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   944
		(void) xdr_free(xdr_COMPOUND4res_clnt, (caddr_t)&res);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   945
		return (geterrno4(res.status));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   946
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   947
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   948
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   949
	 * Success! Now get the SECINFO result.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   950
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   951
	resop = &res.array[1];	/* secinfo res */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   952
	ASSERT(resop->resop == OP_SECINFO);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   953
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   954
	if (resop->nfs_resop4_u.opsecinfo.SECINFO4resok_len == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   955
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   956
		 * Server does not return any flavor for this export point.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   957
		 * Return EACCES.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   958
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   959
		(void) xdr_free(xdr_COMPOUND4res_clnt, (caddr_t)&res);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   960
		return (EACCES);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   961
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   962
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   963
	secinfo_update(mi->mi_curr_serv, &resop->nfs_resop4_u.opsecinfo);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   964
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   965
	svp = mi->mi_curr_serv;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   966
	(void) nfs_rw_enter_sig(&svp->sv_lock, RW_READER, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   967
	if (mi->mi_curr_serv->sv_secinfo == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   968
		nfs_rw_exit(&svp->sv_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   969
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   970
		 * This could be because the server requires AUTH_DH, but
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   971
		 * the client does not have netname/syncaddr data
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   972
		 * from sv_dhsec.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   973
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   974
		(void) xdr_free(xdr_COMPOUND4res_clnt, (caddr_t)&res);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   975
		return (EACCES);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   976
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   977
	nfs_rw_exit(&svp->sv_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   978
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   979
	/* Done! */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   980
	(void) xdr_free(xdr_COMPOUND4res_clnt, (caddr_t)&res);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   981
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   982
	return (0); /* got the secinfo */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   983
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   984
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   985
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   986
 * Making secinfo operation with a given vnode.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   987
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   988
 * This routine is not used by the recovery thread.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   989
 * Mainly used in response to NFS4ERR_WRONGSEC from lookup.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   990
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   991
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   992
nfs4_secinfo_vnode_otw(vnode_t *dvp, char *nm, cred_t *cr)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   993
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   994
	ASSERT(strlen(nm) > 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   995
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   996
	return (nfs4_secinfo_fh_otw(VTOMI4(dvp), VTOR4(dvp)->r_fh, nm, cr));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   997
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   998
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   999
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1000
 * Making secinfo operation with a given vnode if this vnode
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1001
 * has a parent node. If the given vnode is a root node, use
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1002
 * the pathname from the mntinfor4_t to do the secinfo call.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1003
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1004
 * This routine is mainly used by the recovery thread.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1005
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1006
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1007
nfs4_secinfo_vnode(vnode_t *vp, cred_t *cr, int isrecov)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1008
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1009
	svnode_t *svp = VTOSV(vp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1010
	char *nm;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1011
	int error = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1012
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1013
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1014
	 * If there is a parent filehandle, use it to get the secinfo,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1015
	 * otherwise, use mntinfo4_t pathname to get the secinfo.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1016
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1017
	if (svp->sv_dfh) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1018
		nm = fn_name(svp->sv_name); /* get the actual component name */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1019
		error = nfs4_secinfo_fh_otw(VTOMI4(vp), svp->sv_dfh, nm, cr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1020
		kmem_free(nm, MAXNAMELEN);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1021
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1022
		error = nfs4_secinfo_path(VTOMI4(vp), cr, isrecov);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1023
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1024
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1025
	return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1026
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1027
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1028
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1029
 * We are here because the client gets NFS4ERR_WRONGSEC.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1030
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1031
 * Get the security information from the server and indicate
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1032
 * a set of new security information is here to try.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1033
 * Start with the server path that's mounted.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1034
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1035
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1036
nfs4_secinfo_recov(mntinfo4_t *mi, vnode_t *vp1, vnode_t *vp2)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1037
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1038
	int error = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1039
	cred_t *cr, *lcr = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1040
	servinfo4_t *svp = mi->mi_curr_serv;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1041
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1042
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1043
	 * If the client explicitly specifies a preferred flavor to use
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1044
	 * and gets NFS4ERR_WRONGSEC back, there is no need to negotiate
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1045
	 * the flavor.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1046
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1047
	(void) nfs_rw_enter_sig(&svp->sv_lock, RW_READER, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1048
	if (! (svp->sv_flags & SV4_TRYSECDEFAULT)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1049
		error = geterrno4(NFS4ERR_WRONGSEC);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1050
		nfs_rw_exit(&svp->sv_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1051
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1052
		cr = crgetcred();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1053
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1054
		if (svp->sv_secdata->uid != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1055
			lcr = crdup(cr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1056
			(void) crsetugid(lcr, svp->sv_secdata->uid,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1057
			    crgetgid(cr));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1058
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1059
		nfs_rw_exit(&svp->sv_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1060
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1061
		if (vp1 == NULL && vp2 == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1062
			error = nfs4_secinfo_path(mi, cr, TRUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1063
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1064
			if (lcr && error == EACCES)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1065
				error = nfs4_secinfo_path(mi, lcr, TRUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1066
		} else if (vp1) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1067
			error = nfs4_secinfo_vnode(vp1, cr, TRUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1068
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1069
			if (lcr && error == EACCES)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1070
				error = nfs4_secinfo_vnode(vp1, lcr, TRUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1071
		} /* else */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1072
			/* ??? */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1073
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1074
		crfree(cr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1075
		if (lcr != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1076
			crfree(lcr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1077
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1078
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1079
	mutex_enter(&mi->mi_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1080
	mi->mi_recovflags &= ~MI4R_NEED_SECINFO;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1081
	mutex_exit(&mi->mi_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1082
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1083
	return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1084
}