X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/5ba3f43ea354af8ad55bea84372a2bc834d8757c..c3c9b80d004dbbfdf763edeb97968c6997e3b45b:/bsd/nfs/nfs_gss.c diff --git a/bsd/nfs/nfs_gss.c b/bsd/nfs/nfs_gss.c index 0c97dda9c..2d90650f0 100644 --- a/bsd/nfs/nfs_gss.c +++ b/bsd/nfs/nfs_gss.c @@ -1,8 +1,8 @@ /* - * Copyright (c) 2007-2015 Apple Inc. All rights reserved. + * Copyright (c) 2007-2020 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in @@ -11,10 +11,10 @@ * unlawful or unlicensed copies of an Apple operating system, or to * circumvent, violate, or enable the circumvention or violation of, any * terms of an Apple operating system software license agreement. - * + * * Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -22,10 +22,13 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ */ +#include +#if CONFIG_NFS + /************* * These functions implement RPCSEC_GSS security for the NFS client and server. * The code is specific to the use of Kerberos v5 and the use of DES MAC MD5 @@ -120,60 +123,62 @@ #define NFS_GSS_ISDBG (NFS_DEBUG_FACILITY & NFS_FAC_GSS) -#if NFSSERVER +#if CONFIG_NFS_SERVER u_long nfs_gss_svc_ctx_hash; struct nfs_gss_svc_ctx_hashhead *nfs_gss_svc_ctx_hashtbl; -lck_mtx_t *nfs_gss_svc_ctx_mutex; -lck_grp_t *nfs_gss_svc_grp; +static LCK_GRP_DECLARE(nfs_gss_svc_grp, "rpcsec_gss_svc"); +static LCK_MTX_DECLARE(nfs_gss_svc_ctx_mutex, &nfs_gss_svc_grp); uint32_t nfsrv_gss_context_ttl = GSS_CTX_EXPIRE; #define GSS_SVC_CTX_TTL ((uint64_t)max(2*GSS_CTX_PEND, nfsrv_gss_context_ttl) * NSEC_PER_SEC) -#endif /* NFSSERVER */ +#endif /* CONFIG_NFS_SERVER */ -#if NFSCLIENT -lck_grp_t *nfs_gss_clnt_grp; -#endif /* NFSCLIENT */ +#if CONFIG_NFS_CLIENT +LCK_GRP_DECLARE(nfs_gss_clnt_grp, "rpcsec_gss_clnt"); +#endif /* CONFIG_NFS_CLIENT */ #define KRB5_MAX_MIC_SIZE 128 uint8_t krb5_mech_oid[11] = { 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x01, 0x02, 0x02 }; static uint8_t xdrpad[] = { 0x00, 0x00, 0x00, 0x00}; -#if NFSCLIENT -static int nfs_gss_clnt_ctx_find(struct nfsreq *); -static int nfs_gss_clnt_ctx_init(struct nfsreq *, struct nfs_gss_clnt_ctx *); -static int nfs_gss_clnt_ctx_init_retry(struct nfsreq *, struct nfs_gss_clnt_ctx *); -static int nfs_gss_clnt_ctx_callserver(struct nfsreq *, struct nfs_gss_clnt_ctx *); -static uint8_t *nfs_gss_clnt_svcname(struct nfsmount *, gssd_nametype *, uint32_t *); -static int nfs_gss_clnt_gssd_upcall(struct nfsreq *, struct nfs_gss_clnt_ctx *, uint32_t); -void nfs_gss_clnt_ctx_neg_cache_reap(struct nfsmount *); -static void nfs_gss_clnt_ctx_clean(struct nfs_gss_clnt_ctx *); -static int nfs_gss_clnt_ctx_copy(struct nfs_gss_clnt_ctx *, struct nfs_gss_clnt_ctx **); -static void nfs_gss_clnt_ctx_destroy(struct nfs_gss_clnt_ctx *); -static void nfs_gss_clnt_log_error(struct nfsreq *, struct nfs_gss_clnt_ctx *, uint32_t, uint32_t); -#endif /* NFSCLIENT */ - -#if NFSSERVER +#if CONFIG_NFS_CLIENT +static int nfs_gss_clnt_ctx_find(struct nfsreq *); +static int nfs_gss_clnt_ctx_init(struct nfsreq *, struct nfs_gss_clnt_ctx *); +static int nfs_gss_clnt_ctx_init_retry(struct nfsreq *, struct nfs_gss_clnt_ctx *); +static int nfs_gss_clnt_ctx_callserver(struct nfsreq *, struct nfs_gss_clnt_ctx *); +static uint8_t *nfs_gss_clnt_svcname(struct nfsmount *, gssd_nametype *, size_t *); +static int nfs_gss_clnt_gssd_upcall(struct nfsreq *, struct nfs_gss_clnt_ctx *, uint32_t); +void nfs_gss_clnt_ctx_neg_cache_reap(struct nfsmount *); +static void nfs_gss_clnt_ctx_clean(struct nfs_gss_clnt_ctx *); +static int nfs_gss_clnt_ctx_copy(struct nfs_gss_clnt_ctx *, struct nfs_gss_clnt_ctx **); +static void nfs_gss_clnt_ctx_destroy(struct nfs_gss_clnt_ctx *); +static void nfs_gss_clnt_log_error(struct nfsreq *, struct nfs_gss_clnt_ctx *, uint32_t, uint32_t); +#endif /* CONFIG_NFS_CLIENT */ + +#if CONFIG_NFS_SERVER static struct nfs_gss_svc_ctx *nfs_gss_svc_ctx_find(uint32_t); -static void nfs_gss_svc_ctx_insert(struct nfs_gss_svc_ctx *); -static void nfs_gss_svc_ctx_timer(void *, void *); -static int nfs_gss_svc_gssd_upcall(struct nfs_gss_svc_ctx *); -static int nfs_gss_svc_seqnum_valid(struct nfs_gss_svc_ctx *, uint32_t); -#endif /* NFSSERVER */ +static void nfs_gss_svc_ctx_insert(struct nfs_gss_svc_ctx *); +static void nfs_gss_svc_ctx_timer(void *, void *); +static int nfs_gss_svc_gssd_upcall(struct nfs_gss_svc_ctx *); +static int nfs_gss_svc_seqnum_valid(struct nfs_gss_svc_ctx *, uint32_t); + +/* This is only used by server code */ +static void nfs_gss_nfsm_chain(struct nfsm_chain *, mbuf_t); +#endif /* CONFIG_NFS_SERVER */ -static void host_release_special_port(mach_port_t); +static void host_release_special_port(mach_port_t); static mach_port_t host_copy_special_port(mach_port_t); -static void nfs_gss_mach_alloc_buffer(u_char *, uint32_t, vm_map_copy_t *); -static int nfs_gss_mach_vmcopyout(vm_map_copy_t, uint32_t, u_char *); +static void nfs_gss_mach_alloc_buffer(u_char *, size_t, vm_map_copy_t *); +static int nfs_gss_mach_vmcopyout(vm_map_copy_t, uint32_t, u_char *); -static int nfs_gss_mchain_length(mbuf_t); -static int nfs_gss_append_chain(struct nfsm_chain *, mbuf_t); -static void nfs_gss_nfsm_chain(struct nfsm_chain *, mbuf_t); +static int nfs_gss_mchain_length(mbuf_t); +static int nfs_gss_append_chain(struct nfsm_chain *, mbuf_t); -#if NFSSERVER +#if CONFIG_NFS_SERVER thread_call_t nfs_gss_svc_ctx_timer_call; int nfs_gss_timer_on = 0; uint32_t nfs_gss_ctx_count = 0; const uint32_t nfs_gss_ctx_max = GSS_SVC_MAXCONTEXTS; -#endif /* NFSSERVER */ +#endif /* CONFIG_NFS_SERVER */ /* * Initialization when NFS starts @@ -181,18 +186,11 @@ const uint32_t nfs_gss_ctx_max = GSS_SVC_MAXCONTEXTS; void nfs_gss_init(void) { -#if NFSCLIENT - nfs_gss_clnt_grp = lck_grp_alloc_init("rpcsec_gss_clnt", LCK_GRP_ATTR_NULL); -#endif /* NFSCLIENT */ - -#if NFSSERVER - nfs_gss_svc_grp = lck_grp_alloc_init("rpcsec_gss_svc", LCK_GRP_ATTR_NULL); - +#if CONFIG_NFS_SERVER nfs_gss_svc_ctx_hashtbl = hashinit(SVC_CTX_HASHSZ, M_TEMP, &nfs_gss_svc_ctx_hash); - nfs_gss_svc_ctx_mutex = lck_mtx_alloc_init(nfs_gss_svc_grp, LCK_ATTR_NULL); nfs_gss_svc_ctx_timer_call = thread_call_allocate(nfs_gss_svc_ctx_timer, NULL); -#endif /* NFSSERVER */ +#endif /* CONFIG_NFS_SERVER */ } /* @@ -216,20 +214,22 @@ rpc_gss_prepend_32(mbuf_t *mb, uint32_t value) mbuf_t nmb; error = mbuf_get(MBUF_WAITOK, MBUF_TYPE_DATA, &nmb); - if (error) - return (error); + if (error) { + return error; + } mbuf_setnext(nmb, *mb); *mb = nmb; } #endif error = mbuf_prepend(mb, sizeof(uint32_t), MBUF_WAITOK); - if (error) - return (error); + if (error) { + return error; + } data = mbuf_data(*mb); *data = txdr_unsigned(value); - return (0); + return 0; } /* @@ -250,8 +250,9 @@ rpc_gss_data_create(mbuf_t *mbp_head, uint32_t seqnum) uint8_t *data; error = mbuf_get(MBUF_WAITOK, MBUF_TYPE_DATA, &mb); - if (error) - return (error); + if (error) { + return error; + } data = mbuf_data(mb); #if 0 /* Reserve space for prepending */ @@ -259,26 +260,28 @@ rpc_gss_data_create(mbuf_t *mbp_head, uint32_t seqnum) len = (len & ~0x3) - NFSX_UNSIGNED; printf("%s: data = %p, len = %d\n", __func__, data, (int)len); error = mbuf_setdata(mb, data + len, 0); - if (error || mbuf_trailingspace(mb)) + if (error || mbuf_trailingspace(mb)) { printf("%s: data = %p trailingspace = %d error = %d\n", __func__, mbuf_data(mb), (int)mbuf_trailingspace(mb), error); + } #endif /* Reserve 16 words for prepending */ - error = mbuf_setdata(mb, data + 16*sizeof(uint32_t), 0); + error = mbuf_setdata(mb, data + 16 * sizeof(uint32_t), 0); nfsm_chain_init(nmcp, mb); nfsm_chain_add_32(error, nmcp, seqnum); nfsm_chain_build_done(error, nmcp); - if (error) - return (EINVAL); + if (error) { + return EINVAL; + } mbuf_setnext(nmcp->nmc_mcur, *mbp_head); *mbp_head = nmcp->nmc_mhead; - return (0); + return 0; } /* * Create an rpc_gss_integ_data_t given an argument or result in mb_head. * On successful return mb_head will point to the rpc_gss_integ_data_t of length len. - * Note mb_head will now point to a 4 byte sequence number. len does not include + * Note mb_head will now point to a 4 byte sequence number. len does not include * any extra xdr padding. * Returns 0 on success, else an errno_t */ @@ -294,11 +297,13 @@ rpc_gss_integ_data_create(gss_ctx_id_t ctx, mbuf_t *mb_head, uint32_t seqnum, ui /* Length of the argument or result */ length = nfs_gss_mchain_length(*mb_head); - if (len) + if (len) { *len = length; + } error = rpc_gss_data_create(mb_head, seqnum); - if (error) - return (error); + if (error) { + return error; + } /* * length is the length of the rpc_gss_data @@ -307,12 +312,13 @@ rpc_gss_integ_data_create(gss_ctx_id_t ctx, mbuf_t *mb_head, uint32_t seqnum, ui major = gss_krb5_get_mic_mbuf(&error, ctx, 0, *mb_head, 0, length, &mic); if (major != GSS_S_COMPLETE) { printf("gss_krb5_get_mic_mbuf failed %d\n", error); - return (error); + return error; } error = rpc_gss_prepend_32(mb_head, length); - if (error) - return (error); + if (error) { + return error; + } nfsm_chain_dissect_init(error, &nmc, *mb_head); /* Append GSS mic token by advancing rpc_gss_data_t length + NFSX_UNSIGNED (size of the length field) */ @@ -326,7 +332,7 @@ rpc_gss_integ_data_create(gss_ctx_id_t ctx, mbuf_t *mb_head, uint32_t seqnum, ui // printmbuf("rpc_gss_integ_data_create done", *mb_head, 0, 0); assert(nmc.nmc_mhead == *mb_head); - return (error); + return error; } /* @@ -345,24 +351,28 @@ rpc_gss_priv_data_create(gss_ctx_id_t ctx, mbuf_t *mb_head, uint32_t seqnum, uin uint32_t length; error = rpc_gss_data_create(mb_head, seqnum); - if (error) - return (error); + if (error) { + return error; + } length = nfs_gss_mchain_length(*mb_head); major = gss_krb5_wrap_mbuf(&error, ctx, 1, 0, mb_head, 0, length, NULL); - if (major != GSS_S_COMPLETE) - return (error); + if (major != GSS_S_COMPLETE) { + return error; + } length = nfs_gss_mchain_length(*mb_head); - if (len) + if (len) { *len = length; + } pad = nfsm_pad(length); /* Prepend the opaque length of rep rpc_gss_priv_data */ error = rpc_gss_prepend_32(mb_head, length); - if (error) - return (error); + if (error) { + return error; + } if (pad) { nfsm_chain_dissect_init(error, &nmc, *mb_head); /* Advance the opauque size of length and length data */ @@ -372,10 +382,10 @@ rpc_gss_priv_data_create(gss_ctx_id_t ctx, mbuf_t *mb_head, uint32_t seqnum, uin nfsm_chain_build_done(error, &nmc); } - return (error); + return error; } -#if NFSCLIENT +#if CONFIG_NFS_CLIENT /* * Restore the argument or result from an rpc_gss_integ_data mbuf chain @@ -399,27 +409,29 @@ rpc_gss_integ_data_restore(gss_ctx_id_t ctx __unused, mbuf_t *mb_head, size_t le /* should only be one, ... but */ for (; mb; mb = next) { next = mbuf_next(mb); - if (mbuf_len(mb) == 0) + if (mbuf_len(mb) == 0) { mbuf_free(mb); - else + } else { break; + } } *mb_head = mb; for (; mb && len; mb = mbuf_next(mb)) { tail = mb; - if (mbuf_len(mb) <= len) + if (mbuf_len(mb) <= len) { len -= mbuf_len(mb); - else - return (EBADRPC); + } else { + return EBADRPC; + } } /* drop the mic */ if (tail) { - mbuf_setnext(tail, NULL); - mbuf_freem(mb); + mbuf_setnext(tail, NULL); + mbuf_freem(mb); } - return (0); + return 0; } /* @@ -434,8 +446,7 @@ rpc_gss_priv_data_restore(gss_ctx_id_t ctx, mbuf_t *mb_head, size_t len) { uint32_t major, error; mbuf_t mb = *mb_head, next; - uint32_t plen; - size_t length; + size_t plen, length; gss_qop_t qop = GSS_C_QOP_REVERSE; /* Chop of the opaque length */ @@ -445,12 +456,13 @@ rpc_gss_priv_data_restore(gss_ctx_id_t ctx, mbuf_t *mb_head, size_t len) if (plen) { mbuf_t tail = NULL; - for(length = 0; length < len && mb; mb = mbuf_next(mb)) { + for (length = 0; length < len && mb; mb = mbuf_next(mb)) { tail = mb; length += mbuf_len(mb); } - if ((length != len) || (mb == NULL) || (tail == NULL)) - return (EBADRPC); + if ((length != len) || (mb == NULL) || (tail == NULL)) { + return EBADRPC; + } mbuf_freem(mb); mbuf_setnext(tail, NULL); @@ -459,7 +471,7 @@ rpc_gss_priv_data_restore(gss_ctx_id_t ctx, mbuf_t *mb_head, size_t len) major = gss_krb5_unwrap_mbuf(&error, ctx, mb_head, 0, len, NULL, &qop); if (major != GSS_S_COMPLETE) { printf("gss_krb5_unwrap_mbuf failed. major = %d minor = %d\n", (int)major, error); - return (error); + return error; } mb = *mb_head; @@ -470,14 +482,15 @@ rpc_gss_priv_data_restore(gss_ctx_id_t ctx, mbuf_t *mb_head, size_t len) /* Chop of any empty mbufs */ for (mb = *mb_head; mb; mb = next) { next = mbuf_next(mb); - if (mbuf_len(mb) == 0) + if (mbuf_len(mb) == 0) { mbuf_free(mb); - else + } else { break; + } } *mb_head = mb; - return (0); + return 0; } /* @@ -503,7 +516,7 @@ uid_t nfs_cred_getasid2uid(kauth_cred_t cred) { uid_t result = SAFE_CAST_INTTYPE(uid_t, kauth_cred_getasid(cred)); - return (result); + return result; } /* @@ -517,12 +530,12 @@ nfs_gss_clnt_ctx_dump(struct nfsmount *nmp) lck_mtx_lock(&nmp->nm_lock); NFS_GSS_DBG("Enter\n"); TAILQ_FOREACH(cp, &nmp->nm_gsscl, gss_clnt_entries) { - lck_mtx_lock(cp->gss_clnt_mtx); + lck_mtx_lock(&cp->gss_clnt_mtx); printf("context %d/%d: refcnt = %d, flags = %x\n", - kauth_cred_getasid(cp->gss_clnt_cred), - kauth_cred_getauid(cp->gss_clnt_cred), - cp->gss_clnt_refcnt, cp->gss_clnt_flags); - lck_mtx_unlock(cp->gss_clnt_mtx); + kauth_cred_getasid(cp->gss_clnt_cred), + kauth_cred_getauid(cp->gss_clnt_cred), + cp->gss_clnt_refcnt, cp->gss_clnt_flags); + lck_mtx_unlock(&cp->gss_clnt_mtx); } NFS_GSS_DBG("Exit\n"); lck_mtx_unlock(&nmp->nm_lock); @@ -532,15 +545,16 @@ static char * nfs_gss_clnt_ctx_name(struct nfsmount *nmp, struct nfs_gss_clnt_ctx *cp, char *buf, int len) { char *np; - int nlen; + size_t nlen; const char *server = ""; - if (nmp && nmp->nm_mountp) + if (nmp && nmp->nm_mountp) { server = vfs_statfs(nmp->nm_mountp)->f_mntfromname; + } if (cp == NULL) { snprintf(buf, len, "[%s] NULL context", server); - return (buf); + return buf; } if (cp->gss_clnt_principal && !cp->gss_clnt_display) { @@ -550,33 +564,35 @@ nfs_gss_clnt_ctx_name(struct nfsmount *nmp, struct nfs_gss_clnt_ctx *cp, char *b np = cp->gss_clnt_display; nlen = np ? strlen(cp->gss_clnt_display) : 0; } - if (nlen) - snprintf(buf, len, "[%s] %.*s %d/%d %s", server, nlen, np, - kauth_cred_getasid(cp->gss_clnt_cred), - kauth_cred_getuid(cp->gss_clnt_cred), - cp->gss_clnt_principal ? "" : "[from default cred] "); - else + if (nlen) { + snprintf(buf, len, "[%s] %.*s %d/%d %s", server, nlen > INT_MAX ? INT_MAX : (int)nlen, np, + kauth_cred_getasid(cp->gss_clnt_cred), + kauth_cred_getuid(cp->gss_clnt_cred), + cp->gss_clnt_principal ? "" : "[from default cred] "); + } else { snprintf(buf, len, "[%s] using default %d/%d ", server, - kauth_cred_getasid(cp->gss_clnt_cred), - kauth_cred_getuid(cp->gss_clnt_cred)); - return (buf); + kauth_cred_getasid(cp->gss_clnt_cred), + kauth_cred_getuid(cp->gss_clnt_cred)); + } + return buf; } #define NFS_CTXBUFSZ 80 #define NFS_GSS_CTX(req, cp) nfs_gss_clnt_ctx_name((req)->r_nmp, cp ? cp : (req)->r_gss_ctx, CTXBUF, sizeof(CTXBUF)) -#define NFS_GSS_CLNT_CTX_DUMP(nmp) \ - do { \ - if (NFS_GSS_ISDBG && (NFS_DEBUG_FLAGS & 0x2)) \ - nfs_gss_clnt_ctx_dump((nmp)); \ +#define NFS_GSS_CLNT_CTX_DUMP(nmp) \ + do { \ + if (NFS_GSS_ISDBG && (NFS_DEBUG_FLAGS & 0x2)) \ + nfs_gss_clnt_ctx_dump((nmp)); \ } while (0) static int nfs_gss_clnt_ctx_cred_match(kauth_cred_t cred1, kauth_cred_t cred2) { - if (kauth_cred_getasid(cred1) == kauth_cred_getasid(cred2)) - return (1); - return (0); + if (kauth_cred_getasid(cred1) == kauth_cred_getasid(cred2)) { + return 1; + } + return 0; } /* @@ -591,68 +607,74 @@ nfs_gss_clnt_ctx_cred_match(kauth_cred_t cred1, kauth_cred_t cred2) * so that defaults can be set by service identities. */ -static void +static int nfs_gss_clnt_mnt_ref(struct nfsmount *nmp) { int error; vnode_t rvp; if (nmp == NULL || - !(vfs_flags(nmp->nm_mountp) & MNT_AUTOMOUNTED)) - return; + !(vfs_flags(nmp->nm_mountp) & MNT_AUTOMOUNTED)) { + return EINVAL; + } error = VFS_ROOT(nmp->nm_mountp, &rvp, NULL); if (!error) { - vnode_ref(rvp); + error = vnode_ref(rvp); vnode_put(rvp); } + + return error; } /* - * Unbusy the mout. See above comment, + * Unbusy the mount. See above comment, */ -static void +static int nfs_gss_clnt_mnt_rele(struct nfsmount *nmp) { int error; vnode_t rvp; if (nmp == NULL || - !(vfs_flags(nmp->nm_mountp) & MNT_AUTOMOUNTED)) - return; + !(vfs_flags(nmp->nm_mountp) & MNT_AUTOMOUNTED)) { + return EINVAL; + } error = VFS_ROOT(nmp->nm_mountp, &rvp, NULL); if (!error) { vnode_rele(rvp); vnode_put(rvp); } + + return error; } int nfs_root_steals_ctx = 0; static int -nfs_gss_clnt_ctx_find_principal(struct nfsreq *req, uint8_t *principal, uint32_t plen, uint32_t nt) +nfs_gss_clnt_ctx_find_principal(struct nfsreq *req, uint8_t *principal, size_t plen, uint32_t nt) { struct nfsmount *nmp = req->r_nmp; - struct nfs_gss_clnt_ctx *cp; - struct nfsreq treq; + struct nfs_gss_clnt_ctx *cp, *tcp; + struct nfsreq *treq; int error = 0; struct timeval now; char CTXBUF[NFS_CTXBUFSZ]; - bzero(&treq, sizeof (struct nfsreq)); - treq.r_nmp = nmp; + treq = zalloc_flags(nfs_req_zone, Z_WAITOK | Z_ZERO); + treq->r_nmp = nmp; microuptime(&now); lck_mtx_lock(&nmp->nm_lock); - TAILQ_FOREACH(cp, &nmp->nm_gsscl, gss_clnt_entries) { - lck_mtx_lock(cp->gss_clnt_mtx); + TAILQ_FOREACH_SAFE(cp, &nmp->nm_gsscl, gss_clnt_entries, tcp) { + lck_mtx_lock(&cp->gss_clnt_mtx); if (cp->gss_clnt_flags & GSS_CTX_DESTROY) { NFS_GSS_DBG("Found destroyed context %s refcnt = %d continuing\n", - NFS_GSS_CTX(req, cp), - cp->gss_clnt_refcnt); - lck_mtx_unlock(cp->gss_clnt_mtx); + NFS_GSS_CTX(req, cp), + cp->gss_clnt_refcnt); + lck_mtx_unlock(&cp->gss_clnt_mtx); continue; } if (nfs_gss_clnt_ctx_cred_match(cp->gss_clnt_cred, req->r_cred)) { @@ -669,12 +691,12 @@ nfs_gss_clnt_ctx_find_principal(struct nfsreq *req, uint8_t *principal, uint32_t bcmp(cp->gss_clnt_principal, principal, plen) != 0) { cp->gss_clnt_flags |= (GSS_CTX_INVAL | GSS_CTX_DESTROY); cp->gss_clnt_refcnt++; - lck_mtx_unlock(cp->gss_clnt_mtx); + lck_mtx_unlock(&cp->gss_clnt_mtx); NFS_GSS_DBG("Marking %s for deletion because %s does not match\n", - NFS_GSS_CTX(req, cp), principal); - NFS_GSS_DBG("len = (%d,%d), nt = (%d,%d)\n", cp->gss_clnt_prinlen, plen, - cp->gss_clnt_prinnt, nt); - treq.r_gss_ctx = cp; + NFS_GSS_CTX(req, cp), principal); + NFS_GSS_DBG("len = (%zu,%zu), nt = (%d,%d)\n", cp->gss_clnt_prinlen, plen, + cp->gss_clnt_prinnt, nt); + treq->r_gss_ctx = cp; cp = NULL; break; } @@ -687,10 +709,11 @@ nfs_gss_clnt_ctx_find_principal(struct nfsreq *req, uint8_t *principal, uint32_t */ if (cp->gss_clnt_nctime + GSS_NEG_CACHE_TO >= now.tv_sec || cp->gss_clnt_nctime == 0) { NFS_GSS_DBG("Context %s (refcnt = %d) not expired returning EAUTH nctime = %ld now = %ld\n", - NFS_GSS_CTX(req, cp), cp->gss_clnt_refcnt, cp->gss_clnt_nctime, now.tv_sec); - lck_mtx_unlock(cp->gss_clnt_mtx); + NFS_GSS_CTX(req, cp), cp->gss_clnt_refcnt, cp->gss_clnt_nctime, now.tv_sec); + lck_mtx_unlock(&cp->gss_clnt_mtx); lck_mtx_unlock(&nmp->nm_lock); - return (NFSERR_EAUTH); + NFS_ZFREE(nfs_req_zone, treq); + return NFSERR_EAUTH; } if (cp->gss_clnt_refcnt) { struct nfs_gss_clnt_ctx *ncp; @@ -701,19 +724,21 @@ nfs_gss_clnt_ctx_find_principal(struct nfsreq *req, uint8_t *principal, uint32_t */ cp->gss_clnt_flags |= GSS_CTX_DESTROY; NFS_GSS_DBG("Context %s has expired but we still have %d references\n", - NFS_GSS_CTX(req, cp), cp->gss_clnt_refcnt); + NFS_GSS_CTX(req, cp), cp->gss_clnt_refcnt); error = nfs_gss_clnt_ctx_copy(cp, &ncp); - lck_mtx_unlock(cp->gss_clnt_mtx); + lck_mtx_unlock(&cp->gss_clnt_mtx); if (error) { lck_mtx_unlock(&nmp->nm_lock); - return (error); + NFS_ZFREE(nfs_req_zone, treq); + return error; } cp = ncp; break; } else { - if (cp->gss_clnt_nctime) + if (cp->gss_clnt_nctime) { nmp->nm_ncentries--; - lck_mtx_unlock(cp->gss_clnt_mtx); + } + lck_mtx_unlock(&cp->gss_clnt_mtx); TAILQ_REMOVE(&nmp->nm_gsscl, cp, gss_clnt_entries); break; } @@ -721,11 +746,12 @@ nfs_gss_clnt_ctx_find_principal(struct nfsreq *req, uint8_t *principal, uint32_t /* Found a valid context to return */ cp->gss_clnt_refcnt++; req->r_gss_ctx = cp; - lck_mtx_unlock(cp->gss_clnt_mtx); + lck_mtx_unlock(&cp->gss_clnt_mtx); lck_mtx_unlock(&nmp->nm_lock); - return (0); + NFS_ZFREE(nfs_req_zone, treq); + return 0; } - lck_mtx_unlock(cp->gss_clnt_mtx); + lck_mtx_unlock(&cp->gss_clnt_mtx); } if (!cp && nfs_root_steals_ctx && principal == NULL && kauth_cred_getuid(req->r_cred) == 0) { @@ -737,43 +763,48 @@ nfs_gss_clnt_ctx_find_principal(struct nfsreq *req, uint8_t *principal, uint32_t * in case one is set up for it. */ TAILQ_FOREACH(cp, &nmp->nm_gsscl, gss_clnt_entries) { - if (!(cp->gss_clnt_flags & (GSS_CTX_INVAL|GSS_CTX_DESTROY))) { + if (!(cp->gss_clnt_flags & (GSS_CTX_INVAL | GSS_CTX_DESTROY))) { nfs_gss_clnt_ctx_ref(req, cp); lck_mtx_unlock(&nmp->nm_lock); NFS_GSS_DBG("Root stole context %s\n", NFS_GSS_CTX(req, NULL)); - return (0); + NFS_ZFREE(nfs_req_zone, treq); + return 0; } } } NFS_GSS_DBG("Context %s%sfound in Neg Cache @ %ld\n", - NFS_GSS_CTX(req, cp), - cp == NULL ? " not " : "", - cp == NULL ? 0L : cp->gss_clnt_nctime); + NFS_GSS_CTX(req, cp), + cp == NULL ? " not " : "", + cp == NULL ? 0L : cp->gss_clnt_nctime); /* * Not found - create a new context */ if (cp == NULL) { - MALLOC(cp, struct nfs_gss_clnt_ctx *, sizeof(*cp), M_TEMP, M_WAITOK|M_ZERO); + MALLOC(cp, struct nfs_gss_clnt_ctx *, sizeof(*cp), M_TEMP, M_WAITOK | M_ZERO); if (cp == NULL) { lck_mtx_unlock(&nmp->nm_lock); - return (ENOMEM); + NFS_ZFREE(nfs_req_zone, treq); + return ENOMEM; } cp->gss_clnt_cred = req->r_cred; kauth_cred_ref(cp->gss_clnt_cred); - cp->gss_clnt_mtx = lck_mtx_alloc_init(nfs_gss_clnt_grp, LCK_ATTR_NULL); + lck_mtx_init(&cp->gss_clnt_mtx, &nfs_gss_clnt_grp, LCK_ATTR_NULL); cp->gss_clnt_ptime = now.tv_sec - GSS_PRINT_DELAY; if (principal) { - MALLOC(cp->gss_clnt_principal, uint8_t *, plen+1, M_TEMP, M_WAITOK|M_ZERO); + MALLOC(cp->gss_clnt_principal, uint8_t *, plen + 1, M_TEMP, M_WAITOK | M_ZERO); memcpy(cp->gss_clnt_principal, principal, plen); cp->gss_clnt_prinlen = plen; cp->gss_clnt_prinnt = nt; cp->gss_clnt_flags |= GSS_CTX_STICKY; - nfs_gss_clnt_mnt_ref(nmp); + if (!nfs_gss_clnt_mnt_ref(nmp)) { + cp->gss_clnt_flags |= GSS_CTX_USECOUNT; + } } } else { + uint32_t oldflags = cp->gss_clnt_flags; nfs_gss_clnt_ctx_clean(cp); if (principal) { /* @@ -789,6 +820,14 @@ nfs_gss_clnt_ctx_find_principal(struct nfsreq *req, uint8_t *principal, uint32_t * match and we will fall through here. */ cp->gss_clnt_flags |= GSS_CTX_STICKY; + + /* + * We are preserving old flags if it set, and we take a ref if not set. + * Also, because of the short circuit we will not take extra refs here. + */ + if ((oldflags & GSS_CTX_USECOUNT) || !nfs_gss_clnt_mnt_ref(nmp)) { + cp->gss_clnt_flags |= GSS_CTX_USECOUNT; + } } } @@ -804,15 +843,15 @@ nfs_gss_clnt_ctx_find_principal(struct nfsreq *req, uint8_t *principal, uint32_t } /* Remove any old matching contex that had a different principal */ - nfs_gss_clnt_ctx_unref(&treq); - - return (error); + nfs_gss_clnt_ctx_unref(treq); + NFS_ZFREE(nfs_req_zone, treq); + return error; } static int nfs_gss_clnt_ctx_find(struct nfsreq *req) { - return (nfs_gss_clnt_ctx_find_principal(req, NULL, 0, 0)); + return nfs_gss_clnt_ctx_find_principal(req, NULL, 0, 0); } /* @@ -833,7 +872,7 @@ nfs_gss_clnt_cred_put(struct nfsreq *req, struct nfsm_chain *nmc, mbuf_t args) struct gss_seq *gsp; gss_buffer_desc mic; - slpflag = (PZERO-1); + slpflag = (PZERO - 1); if (req->r_nmp) { slpflag |= (NMFLAG(req->r_nmp, INTR) && req->r_thread && !(req->r_flags & R_NOINTR)) ? PCATCH : 0; recordmark = (req->r_nmp->nm_sotype == SOCK_STREAM); @@ -847,8 +886,9 @@ retry: * be created. */ error = nfs_gss_clnt_ctx_find(req); - if (error) - return (error); + if (error) { + return error; + } } cp = req->r_gss_ctx; @@ -858,17 +898,18 @@ retry: * doing the context setup. Wait until the context thread * is null. */ - lck_mtx_lock(cp->gss_clnt_mtx); + lck_mtx_lock(&cp->gss_clnt_mtx); if (cp->gss_clnt_thread && cp->gss_clnt_thread != current_thread()) { cp->gss_clnt_flags |= GSS_NEEDCTX; - msleep(cp, cp->gss_clnt_mtx, slpflag | PDROP, "ctxwait", NULL); + msleep(cp, &cp->gss_clnt_mtx, slpflag | PDROP, "ctxwait", NULL); slpflag &= ~PCATCH; - if ((error = nfs_sigintr(req->r_nmp, req, req->r_thread, 0))) - return (error); + if ((error = nfs_sigintr(req->r_nmp, req, req->r_thread, 0))) { + return error; + } nfs_gss_clnt_ctx_unref(req); goto retry; } - lck_mtx_unlock(cp->gss_clnt_mtx); + lck_mtx_unlock(&cp->gss_clnt_mtx); if (cp->gss_clnt_flags & GSS_CTX_COMPLETE) { /* @@ -878,30 +919,31 @@ retry: * we allocate a new sequence number and allow this request * to proceed. */ - lck_mtx_lock(cp->gss_clnt_mtx); - while (win_getbit(cp->gss_clnt_seqbits, - ((cp->gss_clnt_seqnum - cp->gss_clnt_seqwin) + 1) % cp->gss_clnt_seqwin)) { + lck_mtx_lock(&cp->gss_clnt_mtx); + while (win_getbit(cp->gss_clnt_seqbits, + ((cp->gss_clnt_seqnum - cp->gss_clnt_seqwin) + 1) % cp->gss_clnt_seqwin)) { cp->gss_clnt_flags |= GSS_NEEDSEQ; - msleep(cp, cp->gss_clnt_mtx, slpflag | PDROP, "seqwin", NULL); + msleep(cp, &cp->gss_clnt_mtx, slpflag | PDROP, "seqwin", NULL); slpflag &= ~PCATCH; if ((error = nfs_sigintr(req->r_nmp, req, req->r_thread, 0))) { - return (error); + return error; } - lck_mtx_lock(cp->gss_clnt_mtx); + lck_mtx_lock(&cp->gss_clnt_mtx); if (cp->gss_clnt_flags & GSS_CTX_INVAL) { /* Renewed while while we were waiting */ - lck_mtx_unlock(cp->gss_clnt_mtx); + lck_mtx_unlock(&cp->gss_clnt_mtx); nfs_gss_clnt_ctx_unref(req); goto retry; } } seqnum = ++cp->gss_clnt_seqnum; win_setbit(cp->gss_clnt_seqbits, seqnum % cp->gss_clnt_seqwin); - lck_mtx_unlock(cp->gss_clnt_mtx); + lck_mtx_unlock(&cp->gss_clnt_mtx); - MALLOC(gsp, struct gss_seq *, sizeof(*gsp), M_TEMP, M_WAITOK|M_ZERO); - if (gsp == NULL) - return (ENOMEM); + MALLOC(gsp, struct gss_seq *, sizeof(*gsp), M_TEMP, M_WAITOK | M_ZERO); + if (gsp == NULL) { + return ENOMEM; + } gsp->gss_seqnum = seqnum; SLIST_INSERT_HEAD(&req->r_gss_seqlist, gsp, gss_seqnext); } @@ -915,27 +957,30 @@ retry: nfsm_chain_add_32(error, nmc, cp->gss_clnt_service); nfsm_chain_add_32(error, nmc, cp->gss_clnt_handle_len); if (cp->gss_clnt_handle_len > 0) { - if (cp->gss_clnt_handle == NULL) - return (EBADRPC); + if (cp->gss_clnt_handle == NULL) { + return EBADRPC; + } nfsm_chain_add_opaque(error, nmc, cp->gss_clnt_handle, cp->gss_clnt_handle_len); } - if (error) - return(error); + if (error) { + return error; + } /* * Now add the verifier */ if (cp->gss_clnt_proc == RPCSEC_GSS_INIT || - cp->gss_clnt_proc == RPCSEC_GSS_CONTINUE_INIT) { + cp->gss_clnt_proc == RPCSEC_GSS_CONTINUE_INIT) { /* * If the context is still being created * then use a null verifier. */ - nfsm_chain_add_32(error, nmc, RPCAUTH_NULL); // flavor - nfsm_chain_add_32(error, nmc, 0); // length + nfsm_chain_add_32(error, nmc, RPCAUTH_NULL); // flavor + nfsm_chain_add_32(error, nmc, 0); // length nfsm_chain_build_done(error, nmc); - if (!error) + if (!error) { nfs_gss_append_chain(nmc, args); - return (error); + } + return error; } offset = recordmark ? NFSX_UNSIGNED : 0; // record mark @@ -943,17 +988,18 @@ retry: major = gss_krb5_get_mic_mbuf((uint32_t *)&error, cp->gss_clnt_ctx_id, 0, nmc->nmc_mhead, offset, 0, &mic); if (major != GSS_S_COMPLETE) { - printf ("gss_krb5_get_mic_buf failed %d\n", error); - return (error); + printf("gss_krb5_get_mic_buf failed %d\n", error); + return error; } - nfsm_chain_add_32(error, nmc, RPCSEC_GSS); // flavor - nfsm_chain_add_32(error, nmc, mic.length); // length + nfsm_chain_add_32(error, nmc, RPCSEC_GSS); // flavor + nfsm_chain_add_32(error, nmc, mic.length); // length nfsm_chain_add_opaque(error, nmc, mic.value, mic.length); (void)gss_release_buffer(NULL, &mic); nfsm_chain_build_done(error, nmc); - if (error) - return (error); + if (error) { + return error; + } /* * Now we may have to compute integrity or encrypt the call args @@ -961,8 +1007,9 @@ retry: */ switch (cp->gss_clnt_service) { case RPCSEC_GSS_SVC_NONE: - if (args) + if (args) { nfs_gss_append_chain(nmc, args); + } break; case RPCSEC_GSS_SVC_INTEGRITY: /* @@ -972,11 +1019,13 @@ retry: /* Note the mbufs that were used in r_mrest are being encapsulated in the rpc_gss_integ_data_t */ assert(req->r_mrest == args); nfsm_chain_finish_mbuf(error, nmc); - if (error) - return (error); + if (error) { + return error; + } error = rpc_gss_integ_data_create(cp->gss_clnt_ctx_id, &args, seqnum, &req->r_gss_arglen); - if (error) + if (error) { break; + } req->r_mrest = args; req->r_gss_argoff = nfsm_chain_offset(nmc); nfs_gss_append_chain(nmc, args); @@ -989,20 +1038,22 @@ retry: /* Note the mbufs that were used in r_mrest are being encapsulated in the rpc_gss_priv_data_t */ assert(req->r_mrest == args); nfsm_chain_finish_mbuf(error, nmc); - if (error) - return (error); + if (error) { + return error; + } error = rpc_gss_priv_data_create(cp->gss_clnt_ctx_id, &args, seqnum, &req->r_gss_arglen); - if (error) + if (error) { break; + } req->r_mrest = args; req->r_gss_argoff = nfsm_chain_offset(nmc); nfs_gss_append_chain(nmc, args); break; default: - return (EINVAL); + return EINVAL; } - return (error); + return error; } /* @@ -1027,16 +1078,17 @@ nfs_gss_clnt_verf_get( struct nfs_gss_clnt_ctx *cp = req->r_gss_ctx; struct nfsm_chain nmc_tmp; struct gss_seq *gsp; - uint32_t reslen, offset; + uint32_t reslen; int error = 0; mbuf_t results_mbuf, prev_mbuf, pad_mbuf; - size_t ressize; + size_t ressize, offset; reslen = 0; *accepted_statusp = 0; - if (cp == NULL) - return (NFSERR_EAUTH); + if (cp == NULL) { + return NFSERR_EAUTH; + } /* * If it's not an RPCSEC_GSS verifier, then it has to * be a null verifier that resulted from either @@ -1045,14 +1097,17 @@ nfs_gss_clnt_verf_get( * context that resulted from a fallback to sec=sys. */ if (verftype != RPCSEC_GSS) { - if (verftype != RPCAUTH_NULL) - return (NFSERR_EAUTH); - if (cp->gss_clnt_flags & GSS_CTX_COMPLETE) - return (NFSERR_EAUTH); - if (verflen > 0) + if (verftype != RPCAUTH_NULL) { + return NFSERR_EAUTH; + } + if (cp->gss_clnt_flags & GSS_CTX_COMPLETE) { + return NFSERR_EAUTH; + } + if (verflen > 0) { nfsm_chain_adv(error, nmc, nfsm_rndup(verflen)); + } nfsm_chain_get_32(error, nmc, *accepted_statusp); - return (error); + return error; } /* @@ -1066,17 +1121,22 @@ nfs_gss_clnt_verf_get( * the context is complete. */ if (!(cp->gss_clnt_flags & GSS_CTX_COMPLETE)) { - MALLOC(cp->gss_clnt_verf, u_char *, verflen, M_TEMP, M_WAITOK|M_ZERO); - if (cp->gss_clnt_verf == NULL) - return (ENOMEM); + if (verflen > KRB5_MAX_MIC_SIZE) { + return EBADRPC; + } + MALLOC(cp->gss_clnt_verf, u_char *, verflen, M_TEMP, M_WAITOK | M_ZERO); + if (cp->gss_clnt_verf == NULL) { + return ENOMEM; + } cp->gss_clnt_verflen = verflen; nfsm_chain_get_opaque(error, nmc, verflen, cp->gss_clnt_verf); nfsm_chain_get_32(error, nmc, *accepted_statusp); - return (error); + return error; } - if (verflen > KRB5_MAX_MIC_SIZE) - return (EBADRPC); + if (verflen > KRB5_MAX_MIC_SIZE) { + return EBADRPC; + } cksum.length = verflen; MALLOC(cksum.value, void *, verflen, M_TEMP, M_WAITOK); @@ -1101,19 +1161,22 @@ nfs_gss_clnt_verf_get( seqnum_buf.length = sizeof(network_seqnum); seqnum_buf.value = &network_seqnum; major = gss_krb5_verify_mic(NULL, cp->gss_clnt_ctx_id, &seqnum_buf, &cksum, NULL); - if (major == GSS_S_COMPLETE) + if (major == GSS_S_COMPLETE) { break; + } } FREE(cksum.value, M_TEMP); - if (gsp == NULL) - return (NFSERR_EAUTH); + if (gsp == NULL) { + return NFSERR_EAUTH; + } /* * Get the RPC accepted status */ nfsm_chain_get_32(error, nmc, *accepted_statusp); - if (*accepted_statusp != RPC_SUCCESS) - return (0); + if (*accepted_statusp != RPC_SUCCESS) { + return 0; + } /* * Now we may have to check integrity or decrypt the results @@ -1134,7 +1197,7 @@ nfs_gss_clnt_verf_get( * - checksum of seqnum + results */ - nfsm_chain_get_32(error, nmc, reslen); // length of results + nfsm_chain_get_32(error, nmc, reslen); // length of results if (reslen > NFS_MAXPACKET) { error = EBADRPC; goto nfsmout; @@ -1142,8 +1205,12 @@ nfs_gss_clnt_verf_get( /* Advance and fetch the mic */ nmc_tmp = *nmc; - nfsm_chain_adv(error, &nmc_tmp, reslen); // skip over the results - nfsm_chain_get_32(error, &nmc_tmp, cksum.length); + nfsm_chain_adv(error, &nmc_tmp, reslen); // skip over the results + nfsm_chain_get_32(error, &nmc_tmp, cksum.length); + if (cksum.length > KRB5_MAX_MIC_SIZE) { + error = EBADRPC; + goto nfsmout; + } MALLOC(cksum.value, void *, cksum.length, M_TEMP, M_WAITOK); nfsm_chain_get_opaque(error, &nmc_tmp, cksum.length, cksum.value); //XXX chop offf the cksum? @@ -1169,8 +1236,9 @@ nfs_gss_clnt_verf_get( } #if 0 SLIST_FOREACH(gsp, &req->r_gss_seqlist, gss_seqnext) { - if (seqnum == gsp->gss_seqnum) + if (seqnum == gsp->gss_seqnum) { break; + } } if (gsp == NULL) { error = EBADRPC; @@ -1187,7 +1255,7 @@ nfs_gss_clnt_verf_get( * - wrap token */ prev_mbuf = nmc->nmc_mcur; - nfsm_chain_get_32(error, nmc, reslen); // length of results + nfsm_chain_get_32(error, nmc, reslen); // length of results if (reslen == 0 || reslen > NFS_MAXPACKET) { error = EBADRPC; goto nfsmout; @@ -1199,8 +1267,9 @@ nfs_gss_clnt_verf_get( /* split out the wrap token */ ressize = reslen; error = gss_normalize_mbuf(nmc->nmc_mcur, offset, &ressize, &results_mbuf, &pad_mbuf, 0); - if (error) + if (error) { goto nfsmout; + } if (pad_mbuf) { assert(nfsm_pad(reslen) == mbuf_len(pad_mbuf)); @@ -1231,8 +1300,9 @@ nfs_gss_clnt_verf_get( } #if 0 SLIST_FOREACH(gsp, &req->r_gss_seqlist, gss_seqnext) { - if (seqnum == gsp->gss_seqnum) + if (seqnum == gsp->gss_seqnum) { break; + } } if (gsp == NULL) { error = EBADRPC; @@ -1242,7 +1312,7 @@ nfs_gss_clnt_verf_get( break; } nfsmout: - return (error); + return error; } /* @@ -1265,30 +1335,35 @@ nfs_gss_clnt_args_restore(struct nfsreq *req) struct nfsm_chain mchain, *nmc = &mchain; int error = 0, merr; - if (cp == NULL) - return (NFSERR_EAUTH); + if (cp == NULL) { + return NFSERR_EAUTH; + } - if ((cp->gss_clnt_flags & GSS_CTX_COMPLETE) == 0) - return (ENEEDAUTH); + if ((cp->gss_clnt_flags & GSS_CTX_COMPLETE) == 0) { + return ENEEDAUTH; + } /* Nothing to restore for SVC_NONE */ - if (cp->gss_clnt_service == RPCSEC_GSS_SVC_NONE) - return (0); + if (cp->gss_clnt_service == RPCSEC_GSS_SVC_NONE) { + return 0; + } - nfsm_chain_dissect_init(error, nmc, req->r_mhead); // start at RPC header - nfsm_chain_adv(error, nmc, req->r_gss_argoff); // advance to args - if (error) - return (error); + nfsm_chain_dissect_init(error, nmc, req->r_mhead); // start at RPC header + nfsm_chain_adv(error, nmc, req->r_gss_argoff); // advance to args + if (error) { + return error; + } - if (cp->gss_clnt_service == RPCSEC_GSS_SVC_INTEGRITY) + if (cp->gss_clnt_service == RPCSEC_GSS_SVC_INTEGRITY) { error = rpc_gss_integ_data_restore(cp->gss_clnt_ctx_id, &req->r_mrest, req->r_gss_arglen); - else + } else { error = rpc_gss_priv_data_restore(cp->gss_clnt_ctx_id, &req->r_mrest, req->r_gss_arglen); + } merr = mbuf_setnext(nmc->nmc_mcur, req->r_mrest); /* Should always succeed */ - assert (merr == 0); + assert(merr == 0); - return (error ? error : merr); + return error ? error : merr; } /* @@ -1326,9 +1401,9 @@ nfs_gss_clnt_ctx_init(struct nfsreq *req, struct nfs_gss_clnt_ctx *cp) cp->gss_clnt_proc = RPCSEC_GSS_INIT; cp->gss_clnt_service = - req->r_auth == RPCAUTH_KRB5 ? RPCSEC_GSS_SVC_NONE : - req->r_auth == RPCAUTH_KRB5I ? RPCSEC_GSS_SVC_INTEGRITY : - req->r_auth == RPCAUTH_KRB5P ? RPCSEC_GSS_SVC_PRIVACY : 0; + req->r_auth == RPCAUTH_KRB5 ? RPCSEC_GSS_SVC_NONE : + req->r_auth == RPCAUTH_KRB5I ? RPCSEC_GSS_SVC_INTEGRITY : + req->r_auth == RPCAUTH_KRB5P ? RPCSEC_GSS_SVC_PRIVACY : 0; /* * Now loop around alternating gss_init_sec_context and @@ -1339,14 +1414,16 @@ nfs_gss_clnt_ctx_init(struct nfsreq *req, struct nfs_gss_clnt_ctx *cp) retry: /* Upcall to the gss_init_sec_context in the gssd */ error = nfs_gss_clnt_gssd_upcall(req, cp, retrycnt); - if (error) + if (error) { goto nfsmout; + } if (cp->gss_clnt_major == GSS_S_COMPLETE) { client_complete = 1; NFS_GSS_DBG("Client complete\n"); - if (server_complete) + if (server_complete) { break; + } } else if (cp->gss_clnt_major != GSS_S_CONTINUE_NEEDED) { /* * We may have gotten here because the accept sec context @@ -1369,7 +1446,7 @@ retry: if (error) { if (error == ENEEDAUTH && (cp->gss_clnt_proc == RPCSEC_GSS_INIT || - cp->gss_clnt_proc == RPCSEC_GSS_CONTINUE_INIT)) { + cp->gss_clnt_proc == RPCSEC_GSS_CONTINUE_INIT)) { /* * We got here because the server had a problem * trying to establish a context and sent that there @@ -1389,8 +1466,9 @@ retry: if (cp->gss_clnt_major == GSS_S_COMPLETE) { NFS_GSS_DBG("Server complete\n"); server_complete = 1; - if (client_complete) + if (client_complete) { break; + } } else if (cp->gss_clnt_major == GSS_S_CONTINUE_NEEDED) { cp->gss_clnt_proc = RPCSEC_GSS_CONTINUE_INIT; } else { @@ -1404,13 +1482,13 @@ retry: /* * The context is apparently established successfully */ - lck_mtx_lock(cp->gss_clnt_mtx); + lck_mtx_lock(&cp->gss_clnt_mtx); cp->gss_clnt_flags |= GSS_CTX_COMPLETE; - lck_mtx_unlock(cp->gss_clnt_mtx); + lck_mtx_unlock(&cp->gss_clnt_mtx); cp->gss_clnt_proc = RPCSEC_GSS_DATA; network_seqnum = htonl(cp->gss_clnt_seqwin); - window.length = sizeof (cp->gss_clnt_seqwin); + window.length = sizeof(cp->gss_clnt_seqwin); window.value = &network_seqnum; cksum.value = cp->gss_clnt_verf; cksum.length = cp->gss_clnt_verflen; @@ -1437,9 +1515,10 @@ retry: * are pending within the sequence number window. */ MALLOC(cp->gss_clnt_seqbits, uint32_t *, - nfsm_rndup((cp->gss_clnt_seqwin + 7) / 8), M_TEMP, M_WAITOK|M_ZERO); - if (cp->gss_clnt_seqbits == NULL) + nfsm_rndup((cp->gss_clnt_seqwin + 7) / 8), M_TEMP, M_WAITOK | M_ZERO); + if (cp->gss_clnt_seqbits == NULL) { error = NFSERR_EAUTH; + } nfsmout: /* @@ -1449,7 +1528,7 @@ nfsmout: */ if (error == ENEEDAUTH) { NFS_GSS_DBG("Returning ENEEDAUTH\n"); - return (error); + return error; } /* @@ -1457,9 +1536,10 @@ nfsmout: * It will be removed when the reference count * drops to zero. */ - lck_mtx_lock(cp->gss_clnt_mtx); - if (error) + lck_mtx_lock(&cp->gss_clnt_mtx); + if (error) { cp->gss_clnt_flags |= GSS_CTX_INVAL; + } /* * Wake any threads waiting to use the context @@ -1469,10 +1549,10 @@ nfsmout: cp->gss_clnt_flags &= ~GSS_NEEDCTX; wakeup(cp); } - lck_mtx_unlock(cp->gss_clnt_mtx); + lck_mtx_unlock(&cp->gss_clnt_mtx); NFS_GSS_DBG("Returning error = %d\n", error); - return (error); + return error; } /* @@ -1508,8 +1588,9 @@ nfs_gss_clnt_ctx_init_retry(struct nfsreq *req, struct nfs_gss_clnt_ctx *cp) tsleep(NULL, PSOCK | slpflag, "nfs_gss_clnt_ctx_init_retry", hz); slpflag = 0; error = nfs_sigintr(req->r_nmp, req, current_thread(), 0); - if (error) + if (error) { goto bad; + } microuptime(&now); } @@ -1520,17 +1601,19 @@ nfs_gss_clnt_ctx_init_retry(struct nfsreq *req, struct nfs_gss_clnt_ctx *cp) goto bad; } timeo *= 2; - if (timeo > 60) + if (timeo > 60) { timeo = 60; + } } - if (error == 0) - return 0; // success + if (error == 0) { + return 0; // success + } bad: /* * Give up on this context */ - lck_mtx_lock(cp->gss_clnt_mtx); + lck_mtx_lock(&cp->gss_clnt_mtx); cp->gss_clnt_flags |= GSS_CTX_INVAL; /* @@ -1541,7 +1624,7 @@ bad: cp->gss_clnt_flags &= ~GSS_NEEDCTX; wakeup(cp); } - lck_mtx_unlock(cp->gss_clnt_mtx); + lck_mtx_unlock(&cp->gss_clnt_mtx); return error; } @@ -1560,30 +1643,35 @@ nfs_gss_clnt_ctx_callserver(struct nfsreq *req, struct nfs_gss_clnt_ctx *cp) uint32_t major = cp->gss_clnt_major, minor = cp->gss_clnt_minor; int sz; - if (nfs_mount_gone(req->r_nmp)) - return (ENXIO); + if (nfs_mount_gone(req->r_nmp)) { + return ENXIO; + } nfsm_chain_null(&nmreq); nfsm_chain_null(&nmrep); sz = NFSX_UNSIGNED + nfsm_rndup(cp->gss_clnt_tokenlen); nfsm_chain_build_alloc_init(error, &nmreq, sz); nfsm_chain_add_32(error, &nmreq, cp->gss_clnt_tokenlen); - if (cp->gss_clnt_tokenlen > 0) + if (cp->gss_clnt_tokenlen > 0) { nfsm_chain_add_opaque(error, &nmreq, cp->gss_clnt_token, cp->gss_clnt_tokenlen); + } nfsm_chain_build_done(error, &nmreq); - if (error) + if (error) { goto nfsmout; + } /* Call the server */ - error = nfs_request_gss(req->r_nmp->nm_mountp, &nmreq, req->r_thread, req->r_cred, - (req->r_flags & R_OPTMASK), cp, &nmrep, &status); + error = nfs_request_gss(req->r_nmp->nm_mountp, &nmreq, req->r_thread, req->r_cred, + (req->r_flags & R_OPTMASK), cp, &nmrep, &status); if (cp->gss_clnt_token != NULL) { FREE(cp->gss_clnt_token, M_TEMP); cp->gss_clnt_token = NULL; } - if (!error) + if (!error) { error = status; - if (error) + } + if (error) { goto nfsmout; + } /* Get the server's reply */ @@ -1592,27 +1680,32 @@ nfs_gss_clnt_ctx_callserver(struct nfsreq *req, struct nfs_gss_clnt_ctx *cp) FREE(cp->gss_clnt_handle, M_TEMP); cp->gss_clnt_handle = NULL; } - if (cp->gss_clnt_handle_len > 0) { + if (cp->gss_clnt_handle_len > 0 && cp->gss_clnt_handle_len < GSS_MAX_CTX_HANDLE_LEN) { MALLOC(cp->gss_clnt_handle, u_char *, cp->gss_clnt_handle_len, M_TEMP, M_WAITOK); if (cp->gss_clnt_handle == NULL) { error = ENOMEM; goto nfsmout; } nfsm_chain_get_opaque(error, &nmrep, cp->gss_clnt_handle_len, cp->gss_clnt_handle); + } else { + error = EBADRPC; } nfsm_chain_get_32(error, &nmrep, cp->gss_clnt_major); nfsm_chain_get_32(error, &nmrep, cp->gss_clnt_minor); nfsm_chain_get_32(error, &nmrep, cp->gss_clnt_seqwin); nfsm_chain_get_32(error, &nmrep, cp->gss_clnt_tokenlen); - if (error) + if (error) { goto nfsmout; - if (cp->gss_clnt_tokenlen > 0) { + } + if (cp->gss_clnt_tokenlen > 0 && cp->gss_clnt_tokenlen < GSS_MAX_TOKEN_LEN) { MALLOC(cp->gss_clnt_token, u_char *, cp->gss_clnt_tokenlen, M_TEMP, M_WAITOK); if (cp->gss_clnt_token == NULL) { error = ENOMEM; goto nfsmout; } nfsm_chain_get_opaque(error, &nmrep, cp->gss_clnt_tokenlen, cp->gss_clnt_token); + } else { + error = EBADRPC; } /* @@ -1620,17 +1713,15 @@ nfs_gss_clnt_ctx_callserver(struct nfsreq *req, struct nfs_gss_clnt_ctx *cp) */ if (cp->gss_clnt_major != GSS_S_COMPLETE && cp->gss_clnt_major != GSS_S_CONTINUE_NEEDED) { - printf("nfs_gss_clnt_ctx_callserver: gss_clnt_major = %d\n", cp->gss_clnt_major); nfs_gss_clnt_log_error(req, cp, major, minor); - } nfsmout: nfsm_chain_cleanup(&nmreq); nfsm_chain_cleanup(&nmrep); - return (error); + return error; } /* @@ -1646,23 +1737,25 @@ nfsmout: */ static uint8_t * -nfs_gss_clnt_svcname(struct nfsmount *nmp, gssd_nametype *nt, uint32_t *len) +nfs_gss_clnt_svcname(struct nfsmount *nmp, gssd_nametype *nt, size_t *len) { char *svcname, *d, *server; int lindx, sindx; - if (nfs_mount_gone(nmp)) - return (NULL); + if (nfs_mount_gone(nmp)) { + return NULL; + } if (nmp->nm_sprinc) { *len = strlen(nmp->nm_sprinc) + 1; MALLOC(svcname, char *, *len, M_TEMP, M_WAITOK); *nt = GSSD_HOSTBASED; - if (svcname == NULL) - return (NULL); + if (svcname == NULL) { + return NULL; + } strlcpy(svcname, nmp->nm_sprinc, *len); - return ((uint8_t *)svcname); + return (uint8_t *)svcname; } *nt = GSSD_HOSTBASED; @@ -1678,7 +1771,7 @@ nfs_gss_clnt_svcname(struct nfsmount *nmp, gssd_nametype *nt, uint32_t *len) d = strchr(server, ':'); *len = (uint32_t)(d ? (d - server) : strlen(server)); } - + *len += 5; /* "nfs@" plus null */ MALLOC(svcname, char *, *len, M_TEMP, M_WAITOK); strlcpy(svcname, "nfs", *len); @@ -1686,7 +1779,7 @@ nfs_gss_clnt_svcname(struct nfsmount *nmp, gssd_nametype *nt, uint32_t *len) strlcat(svcname, server, *len); NFS_GSS_DBG("nfs svcname = %s\n", svcname); - return ((uint8_t *)svcname); + return (uint8_t *)svcname; } /* @@ -1707,30 +1800,32 @@ nfs_gss_clnt_get_upcall_port(kauth_cred_t credp) kr = host_get_gssd_port(host_priv_self(), &gssd_host_port); if (kr != KERN_SUCCESS) { printf("nfs_gss_get_upcall_port: can't get gssd port, status %x (%d)\n", kr, kr); - return (IPC_PORT_NULL); + return IPC_PORT_NULL; } if (!IPC_PORT_VALID(gssd_host_port)) { printf("nfs_gss_get_upcall_port: gssd port not valid\n"); - return (IPC_PORT_NULL); + return IPC_PORT_NULL; } asid = kauth_cred_getasid(credp); uid = kauth_cred_getauid(credp); - if (uid == AU_DEFAUDITID) + if (uid == AU_DEFAUDITID) { uid = kauth_cred_getuid(credp); + } kr = mach_gss_lookup(gssd_host_port, uid, asid, &uc_port); - if (kr != KERN_SUCCESS) + if (kr != KERN_SUCCESS) { printf("nfs_gss_clnt_get_upcall_port: mach_gssd_lookup failed: status %x (%d)\n", kr, kr); + } host_release_special_port(gssd_host_port); - return (uc_port); + return uc_port; } static void nfs_gss_clnt_log_error(struct nfsreq *req, struct nfs_gss_clnt_ctx *cp, uint32_t major, uint32_t minor) { -#define GETMAJERROR(x) (((x) >> GSS_C_ROUTINE_ERROR_OFFSET) & GSS_C_ROUTINE_ERROR_MASK) +#define GETMAJERROR(x) (((x) >> GSS_C_ROUTINE_ERROR_OFFSET) & GSS_C_ROUTINE_ERROR_MASK) struct nfsmount *nmp = req->r_nmp; char who[] = "client"; uint32_t gss_error = GETMAJERROR(cp->gss_clnt_major); @@ -1741,23 +1836,25 @@ nfs_gss_clnt_log_error(struct nfsreq *req, struct nfs_gss_clnt_ctx *cp, uint32_t if (req->r_thread) { proc = (proc_t)get_bsdthreadtask_info(req->r_thread); - if (proc != NULL && (proc->p_fd == NULL || (proc->p_lflag & P_LVFORK))) + if (proc != NULL && (proc->p_fd == NULL || (proc->p_lflag & P_LVFORK))) { proc = NULL; + } if (proc) { - if (*proc->p_comm) + if (*proc->p_comm) { procn = proc->p_comm; + } pid = proc->p_pid; } } else { procn = "kernproc"; pid = 0; } - + microuptime(&now); if ((cp->gss_clnt_major != major || cp->gss_clnt_minor != minor || - cp->gss_clnt_ptime + GSS_PRINT_DELAY < now.tv_sec) && + cp->gss_clnt_ptime + GSS_PRINT_DELAY < now.tv_sec) && (nmp->nm_state & NFSSTA_MOUNTED)) { - /* + /* * Will let gssd do some logging in hopes that it can translate * the minor code. */ @@ -1776,21 +1873,21 @@ nfs_gss_clnt_log_error(struct nfsreq *req, struct nfs_gss_clnt_ctx *cp, uint32_t *%%% It would be really nice to get the terminal from the proc or auditinfo_addr struct and print that here. */ printf("NFS: gssd auth failure by %s on audit session %d uid %d proc %s/%d for mount %s. Error: major = %d minor = %d\n", - cp->gss_clnt_display ? cp->gss_clnt_display : who, kauth_cred_getasid(req->r_cred), kauth_cred_getuid(req->r_cred), - procn, pid, vfs_statfs(nmp->nm_mountp)->f_mntfromname, gss_error, (int32_t)cp->gss_clnt_minor); + cp->gss_clnt_display ? cp->gss_clnt_display : who, kauth_cred_getasid(req->r_cred), kauth_cred_getuid(req->r_cred), + procn, pid, vfs_statfs(nmp->nm_mountp)->f_mntfromname, gss_error, (int32_t)cp->gss_clnt_minor); cp->gss_clnt_ptime = now.tv_sec; switch (gss_error) { case 7: printf("NFS: gssd does not have credentials for session %d/%d, (kinit)?\n", - kauth_cred_getasid(req->r_cred), kauth_cred_getauid(req->r_cred)); + kauth_cred_getasid(req->r_cred), kauth_cred_getauid(req->r_cred)); break; case 11: printf("NFS: gssd has expired credentals for session %d/%d, (kinit)?\n", - kauth_cred_getasid(req->r_cred), kauth_cred_getauid(req->r_cred)); + kauth_cred_getasid(req->r_cred), kauth_cred_getauid(req->r_cred)); break; } } else { NFS_GSS_DBG("NFS: gssd auth failure by %s on audit session %d uid %d proc %s/%d for mount %s. Error: major = %d minor = %d\n", - cp->gss_clnt_display ? cp->gss_clnt_display : who, kauth_cred_getasid(req->r_cred), kauth_cred_getuid(req->r_cred), - procn, pid, vfs_statfs(nmp->nm_mountp)->f_mntfromname, gss_error, (int32_t)cp->gss_clnt_minor); + cp->gss_clnt_display ? cp->gss_clnt_display : who, kauth_cred_getasid(req->r_cred), kauth_cred_getuid(req->r_cred), + procn, pid, vfs_statfs(nmp->nm_mountp)->f_mntfromname, gss_error, (int32_t)cp->gss_clnt_minor); } } @@ -1814,7 +1911,7 @@ nfs_gss_clnt_gssd_upcall(struct nfsreq *req, struct nfs_gss_clnt_ctx *cp, uint32 mach_msg_type_number_t otokenlen; int error = 0; uint8_t *principal = NULL; - uint32_t plen = 0; + size_t plen = 0; int32_t nt = GSSD_STRING_NAME; vm_map_copy_t pname = NULL; vm_map_copy_t svcname = NULL; @@ -1825,12 +1922,14 @@ nfs_gss_clnt_gssd_upcall(struct nfsreq *req, struct nfs_gss_clnt_ctx *cp, uint32 uint32_t selected = (uint32_t)-1; struct nfs_etype etype; - if (nmp == NULL || vfs_isforce(nmp->nm_mountp) || (nmp->nm_state & (NFSSTA_FORCE | NFSSTA_DEAD))) - return (ENXIO); + if (nmp == NULL || vfs_isforce(nmp->nm_mountp) || (nmp->nm_state & (NFSSTA_FORCE | NFSSTA_DEAD))) { + return ENXIO; + } if (cp->gss_clnt_gssd_flags & GSSD_RESTART) { - if (cp->gss_clnt_token) + if (cp->gss_clnt_token) { FREE(cp->gss_clnt_token, M_TEMP); + } cp->gss_clnt_token = NULL; cp->gss_clnt_tokenlen = 0; cp->gss_clnt_proc = RPCSEC_GSS_INIT; @@ -1843,8 +1942,9 @@ nfs_gss_clnt_gssd_upcall(struct nfsreq *req, struct nfs_gss_clnt_ctx *cp, uint32 } NFS_GSS_DBG("Retrycnt = %d nm_etype.count = %d\n", retrycnt, nmp->nm_etype.count); - if (retrycnt >= nmp->nm_etype.count) - return (EACCES); + if (retrycnt >= nmp->nm_etype.count) { + return EACCES; + } /* Copy the mount etypes to an order set of etypes to try */ etype = nmp->nm_etype; @@ -1856,15 +1956,18 @@ nfs_gss_clnt_gssd_upcall(struct nfsreq *req, struct nfs_gss_clnt_ctx *cp, uint32 */ if (etype.selected < etype.count) { etype.etypes[0] = nmp->nm_etype.etypes[etype.selected]; - for (uint32_t i = 0; i < etype.selected; i++) - etype.etypes[i+1] = nmp->nm_etype.etypes[i]; - for (uint32_t i = etype.selected + 1; i < etype.count; i++) + for (uint32_t i = 0; i < etype.selected; i++) { + etype.etypes[i + 1] = nmp->nm_etype.etypes[i]; + } + for (uint32_t i = etype.selected + 1; i < etype.count; i++) { etype.etypes[i] = nmp->nm_etype.etypes[i]; + } } /* Remove the ones we've already have tried */ - for (uint32_t i = retrycnt; i < etype.count; i++) + for (uint32_t i = retrycnt; i < etype.count; i++) { etype.etypes[i - retrycnt] = etype.etypes[i]; + } etype.count = etype.count - retrycnt; NFS_GSS_DBG("etype count = %d preferred etype = %d\n", etype.count, etype.etypes[0]); @@ -1887,8 +1990,7 @@ nfs_gss_clnt_gssd_upcall(struct nfsreq *req, struct nfs_gss_clnt_ctx *cp, uint32 plen = (uint32_t)strlen(nmp->nm_principal); principal = (uint8_t *)nmp->nm_principal; cp->gss_clnt_prinnt = nt = GSSD_USER; - } - else if (nmp->nm_realm) { + } else if (nmp->nm_realm) { plen = (uint32_t)strlen(nmp->nm_realm); principal = (uint8_t *)nmp->nm_realm; nt = GSSD_USER; @@ -1896,16 +1998,20 @@ nfs_gss_clnt_gssd_upcall(struct nfsreq *req, struct nfs_gss_clnt_ctx *cp, uint32 if (!IPC_PORT_VALID(cp->gss_clnt_mport)) { cp->gss_clnt_mport = nfs_gss_clnt_get_upcall_port(req->r_cred); - if (cp->gss_clnt_mport == IPC_PORT_NULL) + if (cp->gss_clnt_mport == IPC_PORT_NULL) { goto out; + } } - if (plen) + if (plen) { nfs_gss_mach_alloc_buffer(principal, plen, &pname); - if (cp->gss_clnt_svcnamlen) + } + if (cp->gss_clnt_svcnamlen) { nfs_gss_mach_alloc_buffer(cp->gss_clnt_svcname, cp->gss_clnt_svcnamlen, &svcname); - if (cp->gss_clnt_tokenlen) + } + if (cp->gss_clnt_tokenlen) { nfs_gss_mach_alloc_buffer(cp->gss_clnt_token, cp->gss_clnt_tokenlen, &itoken); + } /* Always want to export the lucid context */ cp->gss_clnt_gssd_flags |= GSSD_LUCID_CONTEXT; @@ -1926,7 +2032,7 @@ retry: &cp->gss_clnt_context, &cp->gss_clnt_cred_handle, &ret_flags, - &octx, (mach_msg_type_number_t *) &lucidlen, + &octx, (mach_msg_type_number_t *) &lucidlen, &otoken, &otokenlen, cp->gss_clnt_display ? NULL : display_name, &cp->gss_clnt_major, @@ -1943,14 +2049,17 @@ retry: if (kr != KERN_SUCCESS) { printf("nfs_gss_clnt_gssd_upcall: mach_gss_init_sec_context failed: %x (%d)\n", kr, kr); if (kr == MIG_SERVER_DIED && cp->gss_clnt_cred_handle == 0 && - retry_cnt++ < NFS_GSS_MACH_MAX_RETRIES && - !vfs_isforce(nmp->nm_mountp) && (nmp->nm_state & (NFSSTA_FORCE | NFSSTA_DEAD)) == 0) { - if (plen) + retry_cnt++ < NFS_GSS_MACH_MAX_RETRIES && + !vfs_isforce(nmp->nm_mountp) && (nmp->nm_state & (NFSSTA_FORCE | NFSSTA_DEAD)) == 0) { + if (plen) { nfs_gss_mach_alloc_buffer(principal, plen, &pname); - if (cp->gss_clnt_svcnamlen) + } + if (cp->gss_clnt_svcnamlen) { nfs_gss_mach_alloc_buffer(cp->gss_clnt_svcname, cp->gss_clnt_svcnamlen, &svcname); - if (cp->gss_clnt_tokenlen > 0) + } + if (cp->gss_clnt_tokenlen > 0) { nfs_gss_mach_alloc_buffer(cp->gss_clnt_token, cp->gss_clnt_tokenlen, &itoken); + } goto retry; } @@ -1960,13 +2069,14 @@ retry: } if (cp->gss_clnt_display == NULL && *display_name != '\0') { - int dlen = strnlen(display_name, MAX_DISPLAY_STR) + 1; /* Add extra byte to include '\0' */ + size_t dlen = strnlen(display_name, MAX_DISPLAY_STR) + 1; /* Add extra byte to include '\0' */ if (dlen < MAX_DISPLAY_STR) { MALLOC(cp->gss_clnt_display, char *, dlen, M_TEMP, M_WAITOK); - if (cp->gss_clnt_display == NULL) + if (cp->gss_clnt_display == NULL) { goto skip; - bcopy(display_name, cp->gss_clnt_display, dlen); + } + bcopy(display_name, cp->gss_clnt_display, dlen); } else { goto skip; } @@ -2003,8 +2113,9 @@ skip: goto out; } - if (cp->gss_clnt_ctx_id) + if (cp->gss_clnt_ctx_id) { gss_krb5_destroy_context(cp->gss_clnt_ctx_id); + } cp->gss_clnt_ctx_id = gss_krb5_make_context(lucid_ctx_buffer, lucidlen); if (cp->gss_clnt_ctx_id == NULL) { printf("Failed to make context from lucid_ctx_buffer\n"); @@ -2019,8 +2130,9 @@ skip: } /* Free context token used as input */ - if (cp->gss_clnt_token) + if (cp->gss_clnt_token) { FREE(cp->gss_clnt_token, M_TEMP); + } cp->gss_clnt_token = NULL; cp->gss_clnt_tokenlen = 0; @@ -2030,14 +2142,14 @@ skip: if (cp->gss_clnt_token == NULL) { printf("nfs_gss_clnt_gssd_upcall: could not allocate %d bytes\n", otokenlen); vm_map_copy_discard((vm_map_copy_t) otoken); - return (ENOMEM); + return ENOMEM; } error = nfs_gss_mach_vmcopyout((vm_map_copy_t) otoken, otokenlen, cp->gss_clnt_token); if (error) { printf("Could not copyout gss token\n"); FREE(cp->gss_clnt_token, M_TEMP); cp->gss_clnt_token = NULL; - return (NFSERR_EAUTH); + return NFSERR_EAUTH; } cp->gss_clnt_tokenlen = otokenlen; } @@ -2047,11 +2159,12 @@ skip: NFS_GSS_DBG("etype selected = %d\n", nmp->nm_etype.etypes[selected]); } NFS_GSS_DBG("Up call succeeded major = %d\n", cp->gss_clnt_major); - return (0); + return 0; out: - if (cp->gss_clnt_token) + if (cp->gss_clnt_token) { FREE(cp->gss_clnt_token, M_TEMP); + } cp->gss_clnt_token = NULL; cp->gss_clnt_tokenlen = 0; /* Server's handle isn't valid. Don't reuse */ @@ -2060,9 +2173,9 @@ out: FREE(cp->gss_clnt_handle, M_TEMP); cp->gss_clnt_handle = NULL; } - + NFS_GSS_DBG("Up call returned NFSERR_EAUTH"); - return (NFSERR_EAUTH); + return NFSERR_EAUTH; } /* @@ -2086,18 +2199,20 @@ nfs_gss_clnt_rpcdone(struct nfsreq *req) struct gss_seq *gsp, *ngsp; int i = 0; - if (cp == NULL || !(cp->gss_clnt_flags & GSS_CTX_COMPLETE)) - return; // no context - don't bother + if (cp == NULL || !(cp->gss_clnt_flags & GSS_CTX_COMPLETE)) { + return; // no context - don't bother + } /* * Reset the bit for this request in the * sequence number window to indicate it's done. * We do this even if the request timed out. */ - lck_mtx_lock(cp->gss_clnt_mtx); + lck_mtx_lock(&cp->gss_clnt_mtx); gsp = SLIST_FIRST(&req->r_gss_seqlist); - if (gsp && gsp->gss_seqnum > (cp->gss_clnt_seqnum - cp->gss_clnt_seqwin)) + if (gsp && gsp->gss_seqnum > (cp->gss_clnt_seqnum - cp->gss_clnt_seqwin)) { win_resetbit(cp->gss_clnt_seqbits, - gsp->gss_seqnum % cp->gss_clnt_seqwin); + gsp->gss_seqnum % cp->gss_clnt_seqwin); + } /* * Limit the seqnum list to GSS_CLNT_SEQLISTMAX entries @@ -2117,7 +2232,7 @@ nfs_gss_clnt_rpcdone(struct nfsreq *req) cp->gss_clnt_flags &= ~GSS_NEEDSEQ; wakeup(cp); } - lck_mtx_unlock(cp->gss_clnt_mtx); + lck_mtx_unlock(&cp->gss_clnt_mtx); } /* @@ -2129,9 +2244,9 @@ nfs_gss_clnt_ctx_ref(struct nfsreq *req, struct nfs_gss_clnt_ctx *cp) { req->r_gss_ctx = cp; - lck_mtx_lock(cp->gss_clnt_mtx); + lck_mtx_lock(&cp->gss_clnt_mtx); cp->gss_clnt_refcnt++; - lck_mtx_unlock(cp->gss_clnt_mtx); + lck_mtx_unlock(&cp->gss_clnt_mtx); } /* @@ -2150,14 +2265,16 @@ nfs_gss_clnt_ctx_unref(struct nfsreq *req) struct timeval now; char CTXBUF[NFS_CTXBUFSZ]; - if (cp == NULL) + if (cp == NULL) { return; + } req->r_gss_ctx = NULL; - lck_mtx_lock(cp->gss_clnt_mtx); - if (--cp->gss_clnt_refcnt < 0) + lck_mtx_lock(&cp->gss_clnt_mtx); + if (--cp->gss_clnt_refcnt < 0) { panic("Over release of gss context!\n"); + } if (cp->gss_clnt_refcnt == 0) { if ((cp->gss_clnt_flags & GSS_CTX_INVAL) && @@ -2167,10 +2284,12 @@ nfs_gss_clnt_ctx_unref(struct nfsreq *req) } if (cp->gss_clnt_flags & GSS_CTX_DESTROY) { destroy = 1; - if (cp->gss_clnt_flags & GSS_CTX_STICKY) - nfs_gss_clnt_mnt_rele(nmp); - if (cp->gss_clnt_nctime) + if ((cp->gss_clnt_flags & GSS_CTX_USECOUNT) && !nfs_gss_clnt_mnt_rele(nmp)) { + cp->gss_clnt_flags &= ~GSS_CTX_USECOUNT; + } + if (cp->gss_clnt_nctime) { on_neg_cache = 1; + } } } if (!destroy && cp->gss_clnt_nctime == 0 && @@ -2179,7 +2298,7 @@ nfs_gss_clnt_ctx_unref(struct nfsreq *req) cp->gss_clnt_nctime = now.tv_sec; neg_cache = 1; } - lck_mtx_unlock(cp->gss_clnt_mtx); + lck_mtx_unlock(&cp->gss_clnt_mtx); if (destroy) { NFS_GSS_DBG("Destroying context %s\n", NFS_GSS_CTX(req, cp)); if (nmp) { @@ -2226,21 +2345,24 @@ nfs_gss_clnt_ctx_neg_cache_reap(struct nfsmount *nmp) /* Don't reap STICKY contexts */ if ((cp->gss_clnt_flags & GSS_CTX_STICKY) || - !(cp->gss_clnt_flags & GSS_CTX_INVAL)) + !(cp->gss_clnt_flags & GSS_CTX_INVAL)) { continue; + } /* Keep up to GSS_MAX_NEG_CACHE_ENTRIES */ - if (nmp->nm_ncentries <= GSS_MAX_NEG_CACHE_ENTRIES) + if (nmp->nm_ncentries <= GSS_MAX_NEG_CACHE_ENTRIES) { break; + } /* Contexts too young */ - if (cp->gss_clnt_nctime + GSS_NEG_CACHE_TO >= now.tv_sec) + if (cp->gss_clnt_nctime + GSS_NEG_CACHE_TO >= now.tv_sec) { continue; + } /* Not referenced, remove it. */ - lck_mtx_lock(cp->gss_clnt_mtx); + lck_mtx_lock(&cp->gss_clnt_mtx); if (cp->gss_clnt_refcnt == 0) { cp->gss_clnt_flags |= GSS_CTX_DESTROY; destroy = 1; } - lck_mtx_unlock(cp->gss_clnt_mtx); + lck_mtx_unlock(&cp->gss_clnt_mtx); if (destroy) { TAILQ_REMOVE(&nmp->nm_gsscl, cp, gss_clnt_entries); nmp->nm_ncentries++; @@ -2326,11 +2448,12 @@ nfs_gss_clnt_ctx_copy(struct nfs_gss_clnt_ctx *scp, struct nfs_gss_clnt_ctx **dc struct nfs_gss_clnt_ctx *dcp; *dcpp = (struct nfs_gss_clnt_ctx *)NULL; - MALLOC(dcp, struct nfs_gss_clnt_ctx *, sizeof (struct nfs_gss_clnt_ctx), M_TEMP, M_WAITOK); - if (dcp == NULL) - return (ENOMEM); - bzero(dcp, sizeof (struct nfs_gss_clnt_ctx)); - dcp->gss_clnt_mtx = lck_mtx_alloc_init(nfs_gss_clnt_grp, LCK_ATTR_NULL); + MALLOC(dcp, struct nfs_gss_clnt_ctx *, sizeof(struct nfs_gss_clnt_ctx), M_TEMP, M_WAITOK); + if (dcp == NULL) { + return ENOMEM; + } + bzero(dcp, sizeof(struct nfs_gss_clnt_ctx)); + lck_mtx_init(&dcp->gss_clnt_mtx, &nfs_gss_clnt_grp, LCK_ATTR_NULL); dcp->gss_clnt_cred = scp->gss_clnt_cred; kauth_cred_ref(dcp->gss_clnt_cred); dcp->gss_clnt_prinlen = scp->gss_clnt_prinlen; @@ -2339,7 +2462,7 @@ nfs_gss_clnt_ctx_copy(struct nfs_gss_clnt_ctx *scp, struct nfs_gss_clnt_ctx **dc MALLOC(dcp->gss_clnt_principal, uint8_t *, dcp->gss_clnt_prinlen, M_TEMP, M_WAITOK | M_ZERO); if (dcp->gss_clnt_principal == NULL) { FREE(dcp, M_TEMP); - return (ENOMEM); + return ENOMEM; } bcopy(scp->gss_clnt_principal, dcp->gss_clnt_principal, dcp->gss_clnt_prinlen); } @@ -2354,7 +2477,7 @@ nfs_gss_clnt_ctx_copy(struct nfs_gss_clnt_ctx *scp, struct nfs_gss_clnt_ctx **dc *dcpp = dcp; - return (0); + return 0; } /* @@ -2364,18 +2487,17 @@ static void nfs_gss_clnt_ctx_destroy(struct nfs_gss_clnt_ctx *cp) { NFS_GSS_DBG("Destroying context %d/%d\n", - kauth_cred_getasid(cp->gss_clnt_cred), - kauth_cred_getauid(cp->gss_clnt_cred)); + kauth_cred_getasid(cp->gss_clnt_cred), + kauth_cred_getauid(cp->gss_clnt_cred)); host_release_special_port(cp->gss_clnt_mport); cp->gss_clnt_mport = IPC_PORT_NULL; - if (cp->gss_clnt_mtx) { - lck_mtx_destroy(cp->gss_clnt_mtx, nfs_gss_clnt_grp); - cp->gss_clnt_mtx = (lck_mtx_t *)NULL; - } - if (IS_VALID_CRED(cp->gss_clnt_cred)) + lck_mtx_destroy(&cp->gss_clnt_mtx, &nfs_gss_clnt_grp); + + if (IS_VALID_CRED(cp->gss_clnt_cred)) { kauth_cred_unref(&cp->gss_clnt_cred); + } cp->gss_clnt_entries.tqe_next = NFSNOLIST; cp->gss_clnt_entries.tqe_prev = NFSNOLIST; if (cp->gss_clnt_principal) { @@ -2410,18 +2532,20 @@ nfs_gss_clnt_ctx_renew(struct nfsreq *req) int error = 0; char CTXBUF[NFS_CTXBUFSZ]; - if (cp == NULL) - return (0); + if (cp == NULL) { + return 0; + } - if (req->r_nmp == NULL) - return (ENXIO); + if (req->r_nmp == NULL) { + return ENXIO; + } nmp = req->r_nmp; - lck_mtx_lock(cp->gss_clnt_mtx); + lck_mtx_lock(&cp->gss_clnt_mtx); if (cp->gss_clnt_flags & GSS_CTX_INVAL) { - lck_mtx_unlock(cp->gss_clnt_mtx); + lck_mtx_unlock(&cp->gss_clnt_mtx); nfs_gss_clnt_ctx_unref(req); - return (0); // already being renewed + return 0; // already being renewed } cp->gss_clnt_flags |= (GSS_CTX_INVAL | GSS_CTX_DESTROY); @@ -2430,21 +2554,24 @@ nfs_gss_clnt_ctx_renew(struct nfsreq *req) cp->gss_clnt_flags &= ~GSS_NEEDSEQ; wakeup(cp); } - lck_mtx_unlock(cp->gss_clnt_mtx); + lck_mtx_unlock(&cp->gss_clnt_mtx); - if (cp->gss_clnt_proc == RPCSEC_GSS_DESTROY) - return (EACCES); /* Destroying a context is best effort. Don't renew. */ + if (cp->gss_clnt_proc == RPCSEC_GSS_DESTROY) { + return EACCES; /* Destroying a context is best effort. Don't renew. */ + } /* * If we're setting up a context let nfs_gss_clnt_ctx_init know this is not working * and to try some other etype. */ - if (cp->gss_clnt_proc != RPCSEC_GSS_DATA) - return (ENEEDAUTH); + if (cp->gss_clnt_proc != RPCSEC_GSS_DATA) { + return ENEEDAUTH; + } error = nfs_gss_clnt_ctx_copy(cp, &ncp); NFS_GSS_DBG("Renewing context %s\n", NFS_GSS_CTX(req, ncp)); nfs_gss_clnt_ctx_unref(req); - if (error) - return (error); + if (error) { + return error; + } lck_mtx_lock(&nmp->nm_lock); /* @@ -2457,10 +2584,11 @@ nfs_gss_clnt_ctx_renew(struct nfsreq *req) lck_mtx_unlock(&nmp->nm_lock); error = nfs_gss_clnt_ctx_init_retry(req, ncp); // Initialize new context - if (error) + if (error) { nfs_gss_clnt_ctx_unref(req); + } - return (error); + return error; } @@ -2474,25 +2602,26 @@ nfs_gss_clnt_ctx_unmount(struct nfsmount *nmp) struct nfs_gss_clnt_ctx *cp; struct nfsm_chain nmreq, nmrep; int error, status; - struct nfsreq req; - req.r_nmp = nmp; + struct nfsreq *req; - if (!nmp) + if (!nmp) { return; + } - + req = zalloc(nfs_req_zone); + req->r_nmp = nmp; lck_mtx_lock(&nmp->nm_lock); - while((cp = TAILQ_FIRST(&nmp->nm_gsscl))) { + while ((cp = TAILQ_FIRST(&nmp->nm_gsscl))) { TAILQ_REMOVE(&nmp->nm_gsscl, cp, gss_clnt_entries); cp->gss_clnt_entries.tqe_next = NFSNOLIST; - lck_mtx_lock(cp->gss_clnt_mtx); + lck_mtx_lock(&cp->gss_clnt_mtx); if (cp->gss_clnt_flags & GSS_CTX_DESTROY) { - lck_mtx_unlock(cp->gss_clnt_mtx); + lck_mtx_unlock(&cp->gss_clnt_mtx); continue; } cp->gss_clnt_refcnt++; - lck_mtx_unlock(cp->gss_clnt_mtx); - req.r_gss_ctx = cp; + lck_mtx_unlock(&cp->gss_clnt_mtx); + req->r_gss_ctx = cp; lck_mtx_unlock(&nmp->nm_lock); /* @@ -2508,9 +2637,10 @@ nfs_gss_clnt_ctx_unmount(struct nfsmount *nmp) nfsm_chain_null(&nmrep); nfsm_chain_build_alloc_init(error, &nmreq, 0); nfsm_chain_build_done(error, &nmreq); - if (!error) + if (!error) { nfs_request_gss(nmp->nm_mountp, &nmreq, - current_thread(), cp->gss_clnt_cred, 0, cp, &nmrep, &status); + current_thread(), cp->gss_clnt_cred, 0, cp, &nmrep, &status); + } nfsm_chain_cleanup(&nmreq); nfsm_chain_cleanup(&nmrep); } @@ -2520,14 +2650,15 @@ nfs_gss_clnt_ctx_unmount(struct nfsmount *nmp) * the reference to remove it if its * refcount is zero. */ - lck_mtx_lock(cp->gss_clnt_mtx); + lck_mtx_lock(&cp->gss_clnt_mtx); cp->gss_clnt_flags |= (GSS_CTX_INVAL | GSS_CTX_DESTROY); - lck_mtx_unlock(cp->gss_clnt_mtx); - nfs_gss_clnt_ctx_unref(&req); + lck_mtx_unlock(&cp->gss_clnt_mtx); + nfs_gss_clnt_ctx_unref(req); lck_mtx_lock(&nmp->nm_lock); } lck_mtx_unlock(&nmp->nm_lock); assert(TAILQ_EMPTY(&nmp->nm_gsscl)); + NFS_ZFREE(nfs_req_zone, req); } @@ -2537,48 +2668,51 @@ nfs_gss_clnt_ctx_unmount(struct nfsmount *nmp) int nfs_gss_clnt_ctx_remove(struct nfsmount *nmp, kauth_cred_t cred) { - struct nfs_gss_clnt_ctx *cp; - struct nfsreq req; + struct nfs_gss_clnt_ctx *cp, *tcp; + struct nfsreq *req; - req.r_nmp = nmp; + req = zalloc(nfs_req_zone); + req->r_nmp = nmp; NFS_GSS_DBG("Enter\n"); NFS_GSS_CLNT_CTX_DUMP(nmp); lck_mtx_lock(&nmp->nm_lock); - TAILQ_FOREACH(cp, &nmp->nm_gsscl, gss_clnt_entries) { - lck_mtx_lock(cp->gss_clnt_mtx); + TAILQ_FOREACH_SAFE(cp, &nmp->nm_gsscl, gss_clnt_entries, tcp) { + lck_mtx_lock(&cp->gss_clnt_mtx); if (nfs_gss_clnt_ctx_cred_match(cp->gss_clnt_cred, cred)) { if (cp->gss_clnt_flags & GSS_CTX_DESTROY) { NFS_GSS_DBG("Found destroyed context %d/%d. refcnt = %d continuing\n", - kauth_cred_getasid(cp->gss_clnt_cred), - kauth_cred_getauid(cp->gss_clnt_cred), - cp->gss_clnt_refcnt); - lck_mtx_unlock(cp->gss_clnt_mtx); + kauth_cred_getasid(cp->gss_clnt_cred), + kauth_cred_getauid(cp->gss_clnt_cred), + cp->gss_clnt_refcnt); + lck_mtx_unlock(&cp->gss_clnt_mtx); continue; } cp->gss_clnt_refcnt++; cp->gss_clnt_flags |= (GSS_CTX_INVAL | GSS_CTX_DESTROY); - lck_mtx_unlock(cp->gss_clnt_mtx); - req.r_gss_ctx = cp; + lck_mtx_unlock(&cp->gss_clnt_mtx); + req->r_gss_ctx = cp; lck_mtx_unlock(&nmp->nm_lock); /* * Drop the reference to remove it if its * refcount is zero. */ NFS_GSS_DBG("Removed context %d/%d refcnt = %d\n", - kauth_cred_getasid(cp->gss_clnt_cred), - kauth_cred_getuid(cp->gss_clnt_cred), - cp->gss_clnt_refcnt); - nfs_gss_clnt_ctx_unref(&req); - return (0); + kauth_cred_getasid(cp->gss_clnt_cred), + kauth_cred_getuid(cp->gss_clnt_cred), + cp->gss_clnt_refcnt); + nfs_gss_clnt_ctx_unref(req); + NFS_ZFREE(nfs_req_zone, req); + return 0; } - lck_mtx_unlock(cp->gss_clnt_mtx); + lck_mtx_unlock(&cp->gss_clnt_mtx); } lck_mtx_unlock(&nmp->nm_lock); - + + NFS_ZFREE(nfs_req_zone, req); NFS_GSS_DBG("Returning ENOENT\n"); - return (ENOENT); + return ENOENT; } /* @@ -2586,35 +2720,34 @@ nfs_gss_clnt_ctx_remove(struct nfsmount *nmp, kauth_cred_t cred) */ int nfs_gss_clnt_ctx_set_principal(struct nfsmount *nmp, vfs_context_t ctx, - uint8_t *principal, uint32_t princlen, uint32_t nametype) - + uint8_t *principal, size_t princlen, uint32_t nametype) { - struct nfsreq req; + struct nfsreq *req; int error; NFS_GSS_DBG("Enter:\n"); - bzero(&req, sizeof(struct nfsreq)); - req.r_nmp = nmp; - req.r_gss_ctx = NULL; - req.r_auth = nmp->nm_auth; - req.r_thread = vfs_context_thread(ctx); - req.r_cred = vfs_context_ucred(ctx); + req = zalloc_flags(nfs_req_zone, Z_WAITOK | Z_ZERO); + req->r_nmp = nmp; + req->r_auth = nmp->nm_auth; + req->r_thread = vfs_context_thread(ctx); + req->r_cred = vfs_context_ucred(ctx); - error = nfs_gss_clnt_ctx_find_principal(&req, principal, princlen, nametype); + error = nfs_gss_clnt_ctx_find_principal(req, principal, princlen, nametype); NFS_GSS_DBG("nfs_gss_clnt_ctx_find_principal returned %d\n", error); /* * We don't care about auth errors. Those would indicate that the context is in the * neagative cache and if and when the user has credentials for the principal * we should be good to go in that we will select those credentials for this principal. */ - if (error == EACCES || error == EAUTH || error == ENEEDAUTH) + if (error == EACCES || error == EAUTH || error == ENEEDAUTH) { error = 0; + } /* We're done with this request */ - nfs_gss_clnt_ctx_unref(&req); - - return (error); + nfs_gss_clnt_ctx_unref(req); + NFS_ZFREE(nfs_req_zone, req); + return error; } /* @@ -2622,9 +2755,9 @@ nfs_gss_clnt_ctx_set_principal(struct nfsmount *nmp, vfs_context_t ctx, */ int nfs_gss_clnt_ctx_get_principal(struct nfsmount *nmp, vfs_context_t ctx, - struct user_nfs_gss_principal *p) + struct user_nfs_gss_principal *p) { - struct nfsreq req; + struct nfsreq *req; int error = 0; struct nfs_gss_clnt_ctx *cp; kauth_cred_t cred = vfs_context_ucred(ctx); @@ -2637,23 +2770,24 @@ nfs_gss_clnt_ctx_get_principal(struct nfsmount *nmp, vfs_context_t ctx, p->princlen = 0; p->flags = 0; - req.r_nmp = nmp; + req = zalloc_flags(nfs_req_zone, Z_WAITOK); + req->r_nmp = nmp; lck_mtx_lock(&nmp->nm_lock); TAILQ_FOREACH(cp, &nmp->nm_gsscl, gss_clnt_entries) { - lck_mtx_lock(cp->gss_clnt_mtx); + lck_mtx_lock(&cp->gss_clnt_mtx); if (cp->gss_clnt_flags & GSS_CTX_DESTROY) { NFS_GSS_DBG("Found destroyed context %s refcnt = %d continuing\n", - NFS_GSS_CTX(&req, cp), - cp->gss_clnt_refcnt); - lck_mtx_unlock(cp->gss_clnt_mtx); + NFS_GSS_CTX(req, cp), + cp->gss_clnt_refcnt); + lck_mtx_unlock(&cp->gss_clnt_mtx); continue; } if (nfs_gss_clnt_ctx_cred_match(cp->gss_clnt_cred, cred)) { cp->gss_clnt_refcnt++; - lck_mtx_unlock(cp->gss_clnt_mtx); + lck_mtx_unlock(&cp->gss_clnt_mtx); goto out; } - lck_mtx_unlock(cp->gss_clnt_mtx); + lck_mtx_unlock(&cp->gss_clnt_mtx); } out: @@ -2661,13 +2795,15 @@ out: lck_mtx_unlock(&nmp->nm_lock); p->flags |= NFS_IOC_NO_CRED_FLAG; /* No credentials, valid or invalid on this mount */ NFS_GSS_DBG("No context found for session %d by uid %d\n", - kauth_cred_getasid(cred), kauth_cred_getuid(cred)); - return (0); + kauth_cred_getasid(cred), kauth_cred_getuid(cred)); + NFS_ZFREE(nfs_req_zone, req); + return 0; } /* Indicate if the cred is INVALID */ - if (cp->gss_clnt_flags & GSS_CTX_INVAL) + if (cp->gss_clnt_flags & GSS_CTX_INVAL) { p->flags |= NFS_IOC_INVALID_CRED_FLAG; + } /* We have set a principal on the mount */ if (cp->gss_clnt_principal) { @@ -2695,19 +2831,20 @@ out: lck_mtx_unlock(&nmp->nm_lock); - req.r_gss_ctx = cp; - NFS_GSS_DBG("Found context %s\n", NFS_GSS_CTX(&req, NULL)); - nfs_gss_clnt_ctx_unref(&req); - return (error); + req->r_gss_ctx = cp; + NFS_GSS_DBG("Found context %s\n", NFS_GSS_CTX(req, NULL)); + nfs_gss_clnt_ctx_unref(req); + NFS_ZFREE(nfs_req_zone, req); + return error; } -#endif /* NFSCLIENT */ +#endif /* CONFIG_NFS_CLIENT */ /************* * * Server functions */ -#if NFSSERVER +#if CONFIG_NFS_SERVER /* * Find a server context based on a handle value received @@ -2720,28 +2857,29 @@ nfs_gss_svc_ctx_find(uint32_t handle) struct nfs_gss_svc_ctx *cp; uint64_t timenow; - if (handle == 0) - return (NULL); - + if (handle == 0) { + return NULL; + } + head = &nfs_gss_svc_ctx_hashtbl[SVC_CTX_HASH(handle)]; /* * Don't return a context that is going to expire in GSS_CTX_PEND seconds */ clock_interval_to_deadline(GSS_CTX_PEND, NSEC_PER_SEC, &timenow); - lck_mtx_lock(nfs_gss_svc_ctx_mutex); + lck_mtx_lock(&nfs_gss_svc_ctx_mutex); LIST_FOREACH(cp, head, gss_svc_entries) { if (cp->gss_svc_handle == handle) { if (timenow > cp->gss_svc_incarnation + GSS_SVC_CTX_TTL) { - /* + /* * Context has or is about to expire. Don't use. * We'll return null and the client will have to create * a new context. */ cp->gss_svc_handle = 0; /* - * Make sure though that we stay around for GSS_CTX_PEND seconds + * Make sure though that we stay around for GSS_CTX_PEND seconds * for other threads that might be using the context. */ cp->gss_svc_incarnation = timenow; @@ -2749,16 +2887,16 @@ nfs_gss_svc_ctx_find(uint32_t handle) cp = NULL; break; } - lck_mtx_lock(cp->gss_svc_mtx); + lck_mtx_lock(&cp->gss_svc_mtx); cp->gss_svc_refcnt++; - lck_mtx_unlock(cp->gss_svc_mtx); + lck_mtx_unlock(&cp->gss_svc_mtx); break; } } - lck_mtx_unlock(nfs_gss_svc_ctx_mutex); + lck_mtx_unlock(&nfs_gss_svc_ctx_mutex); - return (cp); + return cp; } /* @@ -2770,8 +2908,8 @@ nfs_gss_svc_ctx_insert(struct nfs_gss_svc_ctx *cp) { struct nfs_gss_svc_ctx_hashhead *head; struct nfs_gss_svc_ctx *p; - - lck_mtx_lock(nfs_gss_svc_ctx_mutex); + + lck_mtx_lock(&nfs_gss_svc_ctx_mutex); /* * Give the client a random handle so that if we reboot @@ -2780,15 +2918,17 @@ nfs_gss_svc_ctx_insert(struct nfs_gss_svc_ctx *cp) */ retry: cp->gss_svc_handle = random(); - if (cp->gss_svc_handle == 0) + if (cp->gss_svc_handle == 0) { goto retry; + } head = &nfs_gss_svc_ctx_hashtbl[SVC_CTX_HASH(cp->gss_svc_handle)]; LIST_FOREACH(p, head, gss_svc_entries) - if (p->gss_svc_handle == cp->gss_svc_handle) - goto retry; + if (p->gss_svc_handle == cp->gss_svc_handle) { + goto retry; + } clock_interval_to_deadline(GSS_CTX_PEND, NSEC_PER_SEC, - &cp->gss_svc_incarnation); + &cp->gss_svc_incarnation); LIST_INSERT_HEAD(head, cp, gss_svc_entries); nfs_gss_ctx_count++; @@ -2796,10 +2936,10 @@ retry: nfs_gss_timer_on = 1; nfs_interval_timer_start(nfs_gss_svc_ctx_timer_call, - min(GSS_TIMER_PERIOD, max(GSS_CTX_TTL_MIN, nfsrv_gss_context_ttl)) * MSECS_PER_SEC); + min(GSS_TIMER_PERIOD, max(GSS_CTX_TTL_MIN, nfsrv_gss_context_ttl)) * MSECS_PER_SEC); } - lck_mtx_unlock(nfs_gss_svc_ctx_mutex); + lck_mtx_unlock(&nfs_gss_svc_ctx_mutex); } /* @@ -2815,7 +2955,7 @@ nfs_gss_svc_ctx_timer(__unused void *param1, __unused void *param2) int contexts = 0; int i; - lck_mtx_lock(nfs_gss_svc_ctx_mutex); + lck_mtx_lock(&nfs_gss_svc_ctx_mutex); clock_get_uptime(&timenow); NFS_GSS_DBG("is running\n"); @@ -2830,17 +2970,18 @@ nfs_gss_svc_ctx_timer(__unused void *param1, __unused void *param2) */ LIST_FOREACH_SAFE(cp, &nfs_gss_svc_ctx_hashtbl[i], gss_svc_entries, next) { contexts++; - if (timenow > cp->gss_svc_incarnation + - (cp->gss_svc_handle ? GSS_SVC_CTX_TTL : 0) - && cp->gss_svc_refcnt == 0) { + if (timenow > cp->gss_svc_incarnation + + (cp->gss_svc_handle ? GSS_SVC_CTX_TTL : 0) + && cp->gss_svc_refcnt == 0) { /* * A stale context - remove it */ LIST_REMOVE(cp, gss_svc_entries); NFS_GSS_DBG("Removing contex for %d\n", cp->gss_svc_uid); - if (cp->gss_svc_seqbits) + if (cp->gss_svc_seqbits) { FREE(cp->gss_svc_seqbits, M_TEMP); - lck_mtx_destroy(cp->gss_svc_mtx, nfs_gss_svc_grp); + } + lck_mtx_destroy(&cp->gss_svc_mtx, &nfs_gss_svc_grp); FREE(cp, M_TEMP); contexts--; } @@ -2854,11 +2995,12 @@ nfs_gss_svc_ctx_timer(__unused void *param1, __unused void *param2) * set up another callout to check on them later. */ nfs_gss_timer_on = nfs_gss_ctx_count > 0; - if (nfs_gss_timer_on) + if (nfs_gss_timer_on) { nfs_interval_timer_start(nfs_gss_svc_ctx_timer_call, - min(GSS_TIMER_PERIOD, max(GSS_CTX_TTL_MIN, nfsrv_gss_context_ttl)) * MSECS_PER_SEC); + min(GSS_TIMER_PERIOD, max(GSS_CTX_TTL_MIN, nfsrv_gss_context_ttl)) * MSECS_PER_SEC); + } - lck_mtx_unlock(nfs_gss_svc_ctx_mutex); + lck_mtx_unlock(&nfs_gss_svc_ctx_mutex); } /* @@ -2878,10 +3020,10 @@ nfs_gss_svc_cred_get(struct nfsrv_descript *nd, struct nfsm_chain *nmc) uint32_t handle, handle_len; uint32_t major; struct nfs_gss_svc_ctx *cp = NULL; - uint32_t flavor = 0, header_len; + uint32_t flavor = 0; int error = 0; - uint32_t arglen, start; - size_t argsize; + uint32_t arglen; + size_t argsize, start, header_len; gss_buffer_desc cksum; struct nfsm_chain nmc_tmp; mbuf_t reply_mbuf, prev_mbuf, pad_mbuf; @@ -2899,8 +3041,9 @@ nfs_gss_svc_cred_get(struct nfsrv_descript *nd, struct nfsm_chain *nmc) nfsm_chain_get_32(error, nmc, seqnum); nfsm_chain_get_32(error, nmc, service); nfsm_chain_get_32(error, nmc, handle_len); - if (error) + if (error) { goto nfsmout; + } /* * Make sure context setup/destroy is being done with a nullproc @@ -2920,10 +3063,10 @@ nfs_gss_svc_cred_get(struct nfsrv_descript *nd, struct nfsm_chain *nmc) goto nfsmout; } - nd->nd_sec = - service == RPCSEC_GSS_SVC_NONE ? RPCAUTH_KRB5 : - service == RPCSEC_GSS_SVC_INTEGRITY ? RPCAUTH_KRB5I : - service == RPCSEC_GSS_SVC_PRIVACY ? RPCAUTH_KRB5P : 0; + nd->nd_sec = + service == RPCSEC_GSS_SVC_NONE ? RPCAUTH_KRB5 : + service == RPCSEC_GSS_SVC_INTEGRITY ? RPCAUTH_KRB5I : + service == RPCSEC_GSS_SVC_PRIVACY ? RPCAUTH_KRB5P : 0; if (proc == RPCSEC_GSS_INIT) { /* @@ -2937,12 +3080,12 @@ nfs_gss_svc_cred_get(struct nfsrv_descript *nd, struct nfsm_chain *nmc) /* * Set up a new context */ - MALLOC(cp, struct nfs_gss_svc_ctx *, sizeof(*cp), M_TEMP, M_WAITOK|M_ZERO); + MALLOC(cp, struct nfs_gss_svc_ctx *, sizeof(*cp), M_TEMP, M_WAITOK | M_ZERO); if (cp == NULL) { error = ENOMEM; goto nfsmout; } - cp->gss_svc_mtx = lck_mtx_alloc_init(nfs_gss_svc_grp, LCK_ATTR_NULL); + lck_mtx_init(&cp->gss_svc_mtx, &nfs_gss_svc_grp, LCK_ATTR_NULL); cp->gss_svc_refcnt = 1; } else { /* @@ -2953,8 +3096,9 @@ nfs_gss_svc_cred_get(struct nfsrv_descript *nd, struct nfsm_chain *nmc) goto nfsmout; } nfsm_chain_get_32(error, nmc, handle); - if (error) + if (error) { goto nfsmout; + } cp = nfs_gss_svc_ctx_find(handle); if (cp == NULL) { error = NFSERR_AUTHERR | RPCSEC_GSS_CTXPROBLEM; @@ -2979,7 +3123,7 @@ nfs_gss_svc_cred_get(struct nfsrv_descript *nd, struct nfsm_chain *nmc) /* * Sequence number is bad */ - error = EINVAL; // drop the request + error = EINVAL; // drop the request goto nfsmout; } @@ -2994,14 +3138,18 @@ nfs_gss_svc_cred_get(struct nfsrv_descript *nd, struct nfsm_chain *nmc) header_len = nfsm_chain_offset(nmc); nfsm_chain_get_32(error, nmc, flavor); nfsm_chain_get_32(error, nmc, cksum.length); - if (error) + if (error) { goto nfsmout; - if (flavor != RPCSEC_GSS || cksum.length > KRB5_MAX_MIC_SIZE) + } + if (flavor != RPCSEC_GSS || cksum.length > KRB5_MAX_MIC_SIZE) { error = NFSERR_AUTHERR | AUTH_BADVERF; - MALLOC(cksum.value, void *, cksum.length, M_TEMP, M_WAITOK); - nfsm_chain_get_opaque(error, nmc, cksum.length, cksum.value); - if (error) + } else { + MALLOC(cksum.value, void *, cksum.length, M_TEMP, M_WAITOK); + nfsm_chain_get_opaque(error, nmc, cksum.length, cksum.value); + } + if (error) { goto nfsmout; + } /* Now verify the client's call header checksum */ major = gss_krb5_verify_mic_mbuf((uint32_t *)&error, cp->gss_svc_ctx_id, nmc->nmc_mhead, 0, header_len, &cksum, NULL); @@ -3020,8 +3168,8 @@ nfs_gss_svc_cred_get(struct nfsrv_descript *nd, struct nfsm_chain *nmc) bzero(&temp_pcred, sizeof(temp_pcred)); temp_pcred.cr_uid = cp->gss_svc_uid; bcopy(cp->gss_svc_gids, temp_pcred.cr_groups, - sizeof(gid_t) * cp->gss_svc_ngroups); - temp_pcred.cr_ngroups = cp->gss_svc_ngroups; + sizeof(gid_t) * cp->gss_svc_ngroups); + temp_pcred.cr_ngroups = (short)cp->gss_svc_ngroups; nd->nd_cr = posix_cred_create(&temp_pcred); if (nd->nd_cr == NULL) { @@ -3048,7 +3196,7 @@ nfs_gss_svc_cred_get(struct nfsrv_descript *nd, struct nfsm_chain *nmc) * - length of checksum token * - checksum of seqnum + call args */ - nfsm_chain_get_32(error, nmc, arglen); // length of args + nfsm_chain_get_32(error, nmc, arglen); // length of args if (arglen > NFS_MAXPACKET) { error = EBADRPC; goto nfsmout; @@ -3057,7 +3205,10 @@ nfs_gss_svc_cred_get(struct nfsrv_descript *nd, struct nfsm_chain *nmc) nmc_tmp = *nmc; nfsm_chain_adv(error, &nmc_tmp, arglen); nfsm_chain_get_32(error, &nmc_tmp, cksum.length); - MALLOC(cksum.value, void *, cksum.length, M_TEMP, M_WAITOK); + cksum.value = NULL; + if (cksum.length > 0 && cksum.length < GSS_MAX_MIC_LEN) { + MALLOC(cksum.value, void *, cksum.length, M_TEMP, M_WAITOK); + } if (cksum.value == NULL) { error = EBADRPC; @@ -3069,7 +3220,7 @@ nfs_gss_svc_cred_get(struct nfsrv_descript *nd, struct nfsm_chain *nmc) start = nfsm_chain_offset(nmc); major = gss_krb5_verify_mic_mbuf((uint32_t *)&error, cp->gss_svc_ctx_id, - nmc->nmc_mhead, start, arglen, &cksum, NULL); + nmc->nmc_mhead, start, arglen, &cksum, NULL); FREE(cksum.value, M_TEMP); if (major != GSS_S_COMPLETE) { printf("Server args: gss_krb5_verify_mic_mbuf failed %d\n", error); @@ -3084,7 +3235,7 @@ nfs_gss_svc_cred_get(struct nfsrv_descript *nd, struct nfsm_chain *nmc) */ nfsm_chain_get_32(error, nmc, seqnum); if (seqnum != nd->nd_gss_seqnum) { - error = EBADRPC; // returns as GARBAGEARGS + error = EBADRPC; // returns as GARBAGEARGS goto nfsmout; } break; @@ -3096,7 +3247,7 @@ nfs_gss_svc_cred_get(struct nfsrv_descript *nd, struct nfsm_chain *nmc) * - wrap token (37-40 bytes) */ prev_mbuf = nmc->nmc_mcur; - nfsm_chain_get_32(error, nmc, arglen); // length of args + nfsm_chain_get_32(error, nmc, arglen); // length of args if (arglen > NFS_MAXPACKET) { error = EBADRPC; goto nfsmout; @@ -3108,8 +3259,9 @@ nfs_gss_svc_cred_get(struct nfsrv_descript *nd, struct nfsm_chain *nmc) /* split out the wrap token */ argsize = arglen; error = gss_normalize_mbuf(nmc->nmc_mcur, start, &argsize, &reply_mbuf, &pad_mbuf, 0); - if (error) + if (error) { goto nfsmout; + } assert(argsize == arglen); if (pad_mbuf) { @@ -3146,10 +3298,10 @@ nfs_gss_svc_cred_get(struct nfsrv_descript *nd, struct nfsm_chain *nmc) nfsm_chain_get_32(error, nmc, seqnum); if (seqnum != nd->nd_gss_seqnum) { printf("%s: Sequence number mismatch seqnum = %d nd->nd_gss_seqnum = %d\n", - __func__, seqnum, nd->nd_gss_seqnum); + __func__, seqnum, nd->nd_gss_seqnum); printmbuf("reply_mbuf", nmc->nmc_mhead, 0, 0); printf("reply_mbuf %p nmc_head %p\n", reply_mbuf, nmc->nmc_mhead); - error = EBADRPC; // returns as GARBAGEARGS + error = EBADRPC; // returns as GARBAGEARGS goto nfsmout; } break; @@ -3162,11 +3314,12 @@ nfs_gss_svc_cred_get(struct nfsrv_descript *nd, struct nfsm_chain *nmc) */ nfsm_chain_get_32(error, nmc, flavor); nfsm_chain_get_32(error, nmc, verflen); - if (error || flavor != RPCAUTH_NULL || verflen > 0) + if (error || flavor != RPCAUTH_NULL || verflen > 0) { error = NFSERR_AUTHERR | RPCSEC_GSS_CREDPROBLEM; + } if (error) { if (proc == RPCSEC_GSS_INIT) { - lck_mtx_destroy(cp->gss_svc_mtx, nfs_gss_svc_grp); + lck_mtx_destroy(&cp->gss_svc_mtx, &nfs_gss_svc_grp); FREE(cp, M_TEMP); cp = NULL; } @@ -3177,9 +3330,10 @@ nfs_gss_svc_cred_get(struct nfsrv_descript *nd, struct nfsm_chain *nmc) nd->nd_gss_context = cp; return 0; nfsmout: - if (cp) + if (cp) { nfs_gss_svc_ctx_deref(cp); - return (error); + } + return error; } /* @@ -3205,7 +3359,7 @@ nfs_gss_svc_verf_put(struct nfsrv_descript *nd, struct nfsm_chain *nmc) */ nfsm_chain_add_32(error, nmc, RPCAUTH_NULL); nfsm_chain_add_32(error, nmc, 0); - return (error); + return error; } /* @@ -3216,15 +3370,17 @@ nfs_gss_svc_verf_put(struct nfsrv_descript *nd, struct nfsm_chain *nmc) */ seqbuf.length = NFSX_UNSIGNED; if (cp->gss_svc_proc == RPCSEC_GSS_INIT || - cp->gss_svc_proc == RPCSEC_GSS_CONTINUE_INIT) + cp->gss_svc_proc == RPCSEC_GSS_CONTINUE_INIT) { network_seqnum = htonl(cp->gss_svc_seqwin); - else + } else { network_seqnum = htonl(nd->nd_gss_seqnum); + } seqbuf.value = &network_seqnum; major = gss_krb5_get_mic((uint32_t *)&error, cp->gss_svc_ctx_id, 0, &seqbuf, &cksum); - if (major != GSS_S_COMPLETE) - return (error); + if (major != GSS_S_COMPLETE) { + return error; + } /* * Now wrap it in a token and add @@ -3235,7 +3391,7 @@ nfs_gss_svc_verf_put(struct nfsrv_descript *nd, struct nfsm_chain *nmc) nfsm_chain_add_opaque(error, nmc, cksum.value, cksum.length); gss_release_buffer(NULL, &cksum); - return (error); + return error; } /* @@ -3253,8 +3409,9 @@ nfs_gss_svc_prepare_reply(struct nfsrv_descript *nd, struct nfsm_chain *nmc) int error = 0; if (cp->gss_svc_proc == RPCSEC_GSS_INIT || - cp->gss_svc_proc == RPCSEC_GSS_CONTINUE_INIT) - return (0); + cp->gss_svc_proc == RPCSEC_GSS_CONTINUE_INIT) { + return 0; + } switch (nd->nd_sec) { case RPCAUTH_KRB5: @@ -3262,12 +3419,12 @@ nfs_gss_svc_prepare_reply(struct nfsrv_descript *nd, struct nfsm_chain *nmc) break; case RPCAUTH_KRB5I: case RPCAUTH_KRB5P: - nd->nd_gss_mb = nmc->nmc_mcur; // record current mbuf - nfsm_chain_finish_mbuf(error, nmc); // split the chain here + nd->nd_gss_mb = nmc->nmc_mcur; // record current mbuf + nfsm_chain_finish_mbuf(error, nmc); // split the chain here break; } - return (error); + return error; } /* @@ -3291,15 +3448,17 @@ nfs_gss_svc_protect_reply(struct nfsrv_descript *nd, mbuf_t mrep __unused) * together. */ - mb = nd->nd_gss_mb; // the mbuf where we split - results = mbuf_next(mb); // first mbuf in the results - error = mbuf_setnext(mb, NULL); // disconnect the chains - if (error) - return (error); - nfs_gss_nfsm_chain(nmc_res, mb); // set up the prepend chain + mb = nd->nd_gss_mb; // the mbuf where we split + results = mbuf_next(mb); // first mbuf in the results + error = mbuf_setnext(mb, NULL); // disconnect the chains + if (error) { + return error; + } + nfs_gss_nfsm_chain(nmc_res, mb); // set up the prepend chain nfsm_chain_build_done(error, nmc_res); - if (error) - return (error); + if (error) { + return error; + } if (nd->nd_sec == RPCAUTH_KRB5I) { error = rpc_gss_integ_data_create(cp->gss_svc_ctx_id, &results, nd->nd_gss_seqnum, &reslen); @@ -3307,10 +3466,10 @@ nfs_gss_svc_protect_reply(struct nfsrv_descript *nd, mbuf_t mrep __unused) /* RPCAUTH_KRB5P */ error = rpc_gss_priv_data_create(cp->gss_svc_ctx_id, &results, nd->nd_gss_seqnum, &reslen); } - nfs_gss_append_chain(nmc_res, results); // Append the results mbufs + nfs_gss_append_chain(nmc_res, results); // Append the results mbufs nfsm_chain_build_done(error, nmc_res); - return (error); + return error; } /* @@ -3341,16 +3500,15 @@ nfs_gss_svc_ctx_init(struct nfsrv_descript *nd, struct nfsrv_sock *slp, mbuf_t * switch (cp->gss_svc_proc) { case RPCSEC_GSS_INIT: nfs_gss_svc_ctx_insert(cp); - /* FALLTHRU */ + OS_FALLTHROUGH; case RPCSEC_GSS_CONTINUE_INIT: /* Get the token from the request */ nfsm_chain_get_32(error, nmreq, cp->gss_svc_tokenlen); - if (cp->gss_svc_tokenlen == 0) { - autherr = RPCSEC_GSS_CREDPROBLEM; - break; + cp->gss_svc_token = NULL; + if (cp->gss_svc_tokenlen > 0 && cp->gss_svc_tokenlen < GSS_MAX_TOKEN_LEN) { + MALLOC(cp->gss_svc_token, u_char *, cp->gss_svc_tokenlen, M_TEMP, M_WAITOK); } - MALLOC(cp->gss_svc_token, u_char *, cp->gss_svc_tokenlen, M_TEMP, M_WAITOK); if (cp->gss_svc_token == NULL) { autherr = RPCSEC_GSS_CREDPROBLEM; break; @@ -3361,8 +3519,9 @@ nfs_gss_svc_ctx_init(struct nfsrv_descript *nd, struct nfsrv_sock *slp, mbuf_t * error = nfs_gss_svc_gssd_upcall(cp); if (error) { autherr = RPCSEC_GSS_CREDPROBLEM; - if (error == NFSERR_EAUTH) + if (error == NFSERR_EAUTH) { error = 0; + } break; } @@ -3370,8 +3529,9 @@ nfs_gss_svc_ctx_init(struct nfsrv_descript *nd, struct nfsrv_sock *slp, mbuf_t * * If the context isn't complete, pass the new token * back to the client for another round. */ - if (cp->gss_svc_major != GSS_S_COMPLETE) + if (cp->gss_svc_major != GSS_S_COMPLETE) { break; + } /* * Now the server context is complete. @@ -3381,7 +3541,7 @@ nfs_gss_svc_ctx_init(struct nfsrv_descript *nd, struct nfsrv_sock *slp, mbuf_t * cp->gss_svc_seqwin = GSS_SVC_SEQWINDOW; MALLOC(cp->gss_svc_seqbits, uint32_t *, - nfsm_rndup((cp->gss_svc_seqwin + 7) / 8), M_TEMP, M_WAITOK|M_ZERO); + nfsm_rndup((cp->gss_svc_seqwin + 7) / 8), M_TEMP, M_WAITOK | M_ZERO); if (cp->gss_svc_seqbits == NULL) { autherr = RPCSEC_GSS_CREDPROBLEM; break; @@ -3401,11 +3561,11 @@ nfs_gss_svc_ctx_init(struct nfsrv_descript *nd, struct nfsrv_sock *slp, mbuf_t * */ cp = nfs_gss_svc_ctx_find(cp->gss_svc_handle); if (cp != NULL) { - cp->gss_svc_handle = 0; // so it can't be found - lck_mtx_lock(cp->gss_svc_mtx); + cp->gss_svc_handle = 0; // so it can't be found + lck_mtx_lock(&cp->gss_svc_mtx); clock_interval_to_deadline(GSS_CTX_PEND, NSEC_PER_SEC, - &cp->gss_svc_incarnation); - lck_mtx_unlock(cp->gss_svc_mtx); + &cp->gss_svc_incarnation); + lck_mtx_unlock(&cp->gss_svc_mtx); } break; default: @@ -3415,23 +3575,25 @@ nfs_gss_svc_ctx_init(struct nfsrv_descript *nd, struct nfsrv_sock *slp, mbuf_t * /* Now build the reply */ - if (nd->nd_repstat == 0) + if (nd->nd_repstat == 0) { nd->nd_repstat = autherr ? (NFSERR_AUTHERR | autherr) : NFSERR_RETVOID; + } sz = 7 * NFSX_UNSIGNED + nfsm_rndup(cp->gss_svc_tokenlen); // size of results error = nfsrv_rephead(nd, slp, &nmrep, sz); *mrepp = nmrep.nmc_mhead; - if (error || autherr) + if (error || autherr) { goto nfsmout; + } if (cp->gss_svc_proc == RPCSEC_GSS_INIT || cp->gss_svc_proc == RPCSEC_GSS_CONTINUE_INIT) { nfsm_chain_add_32(error, &nmrep, sizeof(cp->gss_svc_handle)); nfsm_chain_add_32(error, &nmrep, cp->gss_svc_handle); - + nfsm_chain_add_32(error, &nmrep, cp->gss_svc_major); nfsm_chain_add_32(error, &nmrep, cp->gss_svc_minor); nfsm_chain_add_32(error, &nmrep, cp->gss_svc_seqwin); - + nfsm_chain_add_32(error, &nmrep, cp->gss_svc_tokenlen); if (cp->gss_svc_token != NULL) { nfsm_chain_add_opaque(error, &nmrep, cp->gss_svc_token, cp->gss_svc_tokenlen); @@ -3444,11 +3606,13 @@ nfsmout: if (autherr != 0) { nd->nd_gss_context = NULL; LIST_REMOVE(cp, gss_svc_entries); - if (cp->gss_svc_seqbits != NULL) + if (cp->gss_svc_seqbits != NULL) { FREE(cp->gss_svc_seqbits, M_TEMP); - if (cp->gss_svc_token != NULL) + } + if (cp->gss_svc_token != NULL) { FREE(cp->gss_svc_token, M_TEMP); - lck_mtx_destroy(cp->gss_svc_mtx, nfs_gss_svc_grp); + } + lck_mtx_destroy(&cp->gss_svc_mtx, &nfs_gss_svc_grp); FREE(cp, M_TEMP); } @@ -3457,7 +3621,7 @@ nfsmout: nfsm_chain_cleanup(&nmrep); *mrepp = NULL; } - return (error); + return error; } /* @@ -3492,8 +3656,9 @@ nfs_gss_svc_gssd_upcall(struct nfs_gss_svc_ctx *cp) goto out; } - if (cp->gss_svc_tokenlen > 0) + if (cp->gss_svc_tokenlen > 0) { nfs_gss_mach_alloc_buffer(cp->gss_svc_token, cp->gss_svc_tokenlen, &itoken); + } retry: printf("Calling mach_gss_accept_sec_context\n"); @@ -3514,12 +3679,13 @@ retry: &cp->gss_svc_minor); printf("mach_gss_accept_sec_context returned %d\n", kr); - if (kr != KERN_SUCCESS) { + if (kr != KERN_SUCCESS) { printf("nfs_gss_svc_gssd_upcall failed: %x (%d)\n", kr, kr); if (kr == MIG_SERVER_DIED && cp->gss_svc_context == 0 && - retry_cnt++ < NFS_GSS_MACH_MAX_RETRIES) { - if (cp->gss_svc_tokenlen > 0) + retry_cnt++ < NFS_GSS_MACH_MAX_RETRIES) { + if (cp->gss_svc_tokenlen > 0) { nfs_gss_mach_alloc_buffer(cp->gss_svc_token, cp->gss_svc_tokenlen, &itoken); + } goto retry; } host_release_special_port(mp); @@ -3542,8 +3708,9 @@ retry: FREE(lucid_ctx_buffer, M_TEMP); goto out; } - if (cp->gss_svc_ctx_id) + if (cp->gss_svc_ctx_id) { gss_krb5_destroy_context(cp->gss_svc_ctx_id); + } cp->gss_svc_ctx_id = gss_krb5_make_context(lucid_ctx_buffer, lucidlen); if (cp->gss_svc_ctx_id == NULL) { printf("Failed to make context from lucid_ctx_buffer\n"); @@ -3552,36 +3719,37 @@ retry: } /* Free context token used as input */ - if (cp->gss_svc_token) + if (cp->gss_svc_token) { FREE(cp->gss_svc_token, M_TEMP); + } cp->gss_svc_token = NULL; cp->gss_svc_tokenlen = 0; - + if (otokenlen > 0) { /* Set context token to gss output token */ MALLOC(cp->gss_svc_token, u_char *, otokenlen, M_TEMP, M_WAITOK); if (cp->gss_svc_token == NULL) { printf("nfs_gss_svc_gssd_upcall: could not allocate %d bytes\n", otokenlen); vm_map_copy_discard((vm_map_copy_t) otoken); - return (ENOMEM); + return ENOMEM; } error = nfs_gss_mach_vmcopyout((vm_map_copy_t) otoken, otokenlen, cp->gss_svc_token); if (error) { FREE(cp->gss_svc_token, M_TEMP); cp->gss_svc_token = NULL; - return (NFSERR_EAUTH); + return NFSERR_EAUTH; } cp->gss_svc_tokenlen = otokenlen; } - return (0); + return 0; out: FREE(cp->gss_svc_token, M_TEMP); cp->gss_svc_tokenlen = 0; cp->gss_svc_token = NULL; - return (NFSERR_EAUTH); + return NFSERR_EAUTH; } /* @@ -3601,42 +3769,44 @@ nfs_gss_svc_seqnum_valid(struct nfs_gss_svc_ctx *cp, uint32_t seq) uint32_t win = cp->gss_svc_seqwin; uint32_t i; - lck_mtx_lock(cp->gss_svc_mtx); + lck_mtx_lock(&cp->gss_svc_mtx); /* * If greater than the window upper bound, * move the window up, and set the bit. */ if (seq > cp->gss_svc_seqmax) { - if (seq - cp->gss_svc_seqmax > win) + if (seq - cp->gss_svc_seqmax > win) { bzero(bits, nfsm_rndup((win + 7) / 8)); - else - for (i = cp->gss_svc_seqmax + 1; i < seq; i++) + } else { + for (i = cp->gss_svc_seqmax + 1; i < seq; i++) { win_resetbit(bits, i % win); + } + } win_setbit(bits, seq % win); cp->gss_svc_seqmax = seq; - lck_mtx_unlock(cp->gss_svc_mtx); - return (1); + lck_mtx_unlock(&cp->gss_svc_mtx); + return 1; } /* * Invalid if below the lower bound of the window */ if (seq <= cp->gss_svc_seqmax - win) { - lck_mtx_unlock(cp->gss_svc_mtx); - return (0); + lck_mtx_unlock(&cp->gss_svc_mtx); + return 0; } /* * In the window, invalid if the bit is already set */ if (win_getbit(bits, seq % win)) { - lck_mtx_unlock(cp->gss_svc_mtx); - return (0); + lck_mtx_unlock(&cp->gss_svc_mtx); + return 0; } win_setbit(bits, seq % win); - lck_mtx_unlock(cp->gss_svc_mtx); - return (1); + lck_mtx_unlock(&cp->gss_svc_mtx); + return 1; } /* @@ -3649,12 +3819,13 @@ nfs_gss_svc_seqnum_valid(struct nfs_gss_svc_ctx *cp, uint32_t seq) void nfs_gss_svc_ctx_deref(struct nfs_gss_svc_ctx *cp) { - lck_mtx_lock(cp->gss_svc_mtx); - if (cp->gss_svc_refcnt > 0) + lck_mtx_lock(&cp->gss_svc_mtx); + if (cp->gss_svc_refcnt > 0) { cp->gss_svc_refcnt--; - else + } else { printf("nfs_gss_ctx_deref: zero refcount\n"); - lck_mtx_unlock(cp->gss_svc_mtx); + } + lck_mtx_unlock(&cp->gss_svc_mtx); } /* @@ -3666,8 +3837,8 @@ nfs_gss_svc_cleanup(void) struct nfs_gss_svc_ctx_hashhead *head; struct nfs_gss_svc_ctx *cp, *ncp; int i; - - lck_mtx_lock(nfs_gss_svc_ctx_mutex); + + lck_mtx_lock(&nfs_gss_svc_ctx_mutex); /* * Run through all the buckets @@ -3679,17 +3850,18 @@ nfs_gss_svc_cleanup(void) head = &nfs_gss_svc_ctx_hashtbl[i]; LIST_FOREACH_SAFE(cp, head, gss_svc_entries, ncp) { LIST_REMOVE(cp, gss_svc_entries); - if (cp->gss_svc_seqbits) + if (cp->gss_svc_seqbits) { FREE(cp->gss_svc_seqbits, M_TEMP); - lck_mtx_destroy(cp->gss_svc_mtx, nfs_gss_svc_grp); + } + lck_mtx_destroy(&cp->gss_svc_mtx, &nfs_gss_svc_grp); FREE(cp, M_TEMP); } } - lck_mtx_unlock(nfs_gss_svc_ctx_mutex); + lck_mtx_unlock(&nfs_gss_svc_ctx_mutex); } -#endif /* NFSSERVER */ +#endif /* CONFIG_NFS_SERVER */ /************* @@ -3699,7 +3871,7 @@ nfs_gss_svc_cleanup(void) /* * Release a host special port that was obtained by host_get_special_port * or one of its macros (host_get_gssd_port in this case). - * This really should be in a public kpi. + * This really should be in a public kpi. */ /* This should be in a public header if this routine is not */ @@ -3709,14 +3881,15 @@ extern ipc_port_t ipc_port_copy_send(ipc_port_t); static void host_release_special_port(mach_port_t mp) { - if (IPC_PORT_VALID(mp)) + if (IPC_PORT_VALID(mp)) { ipc_port_release_send(mp); + } } static mach_port_t host_copy_special_port(mach_port_t mp) { - return (ipc_port_copy_send(mp)); + return ipc_port_copy_send(mp); } /* @@ -3731,18 +3904,25 @@ host_copy_special_port(mach_port_t mp) * complete. */ static void -nfs_gss_mach_alloc_buffer(u_char *buf, uint32_t buflen, vm_map_copy_t *addr) +nfs_gss_mach_alloc_buffer(u_char *buf, size_t buflen, vm_map_copy_t *addr) { kern_return_t kr; vm_offset_t kmem_buf; vm_size_t tbuflen; *addr = NULL; - if (buf == NULL || buflen == 0) + if (buf == NULL || buflen == 0) { return; + } tbuflen = vm_map_round_page(buflen, - vm_map_page_mask(ipc_kernel_map)); + vm_map_page_mask(ipc_kernel_map)); + + if (tbuflen < buflen) { + printf("nfs_gss_mach_alloc_buffer: vm_map_round_page failed\n"); + return; + } + kr = vm_allocate_kernel(ipc_kernel_map, &kmem_buf, tbuflen, VM_FLAGS_ANYWHERE, VM_KERN_MEMORY_FILE); if (kr != 0) { printf("nfs_gss_mach_alloc_buffer: vm_allocate failed\n"); @@ -3750,33 +3930,33 @@ nfs_gss_mach_alloc_buffer(u_char *buf, uint32_t buflen, vm_map_copy_t *addr) } kr = vm_map_wire_kernel(ipc_kernel_map, - vm_map_trunc_page(kmem_buf, - vm_map_page_mask(ipc_kernel_map)), - vm_map_round_page(kmem_buf + tbuflen, - vm_map_page_mask(ipc_kernel_map)), - VM_PROT_READ|VM_PROT_WRITE, VM_KERN_MEMORY_FILE, FALSE); + vm_map_trunc_page(kmem_buf, + vm_map_page_mask(ipc_kernel_map)), + vm_map_round_page(kmem_buf + tbuflen, + vm_map_page_mask(ipc_kernel_map)), + VM_PROT_READ | VM_PROT_WRITE, VM_KERN_MEMORY_FILE, FALSE); if (kr != 0) { printf("nfs_gss_mach_alloc_buffer: vm_map_wire failed\n"); return; } - + bcopy(buf, (void *) kmem_buf, buflen); // Shouldn't need to bzero below since vm_allocate returns zeroed pages // bzero(kmem_buf + buflen, tbuflen - buflen); - + kr = vm_map_unwire(ipc_kernel_map, - vm_map_trunc_page(kmem_buf, - vm_map_page_mask(ipc_kernel_map)), - vm_map_round_page(kmem_buf + tbuflen, - vm_map_page_mask(ipc_kernel_map)), - FALSE); + vm_map_trunc_page(kmem_buf, + vm_map_page_mask(ipc_kernel_map)), + vm_map_round_page(kmem_buf + tbuflen, + vm_map_page_mask(ipc_kernel_map)), + FALSE); if (kr != 0) { printf("nfs_gss_mach_alloc_buffer: vm_map_unwire failed\n"); return; } kr = vm_map_copyin(ipc_kernel_map, (vm_map_address_t) kmem_buf, - (vm_map_size_t) buflen, TRUE, addr); + (vm_map_size_t) buflen, TRUE, addr); if (kr != 0) { printf("nfs_gss_mach_alloc_buffer: vm_map_copyin failed\n"); return; @@ -3797,14 +3977,15 @@ nfs_gss_mach_vmcopyout(vm_map_copy_t in, uint32_t len, u_char *out) int error; error = vm_map_copyout(ipc_kernel_map, &map_data, in); - if (error) - return (error); + if (error) { + return error; + } data = CAST_DOWN(vm_offset_t, map_data); bcopy((void *) data, out, len); vm_deallocate(ipc_kernel_map, data, len); - return (0); + return 0; } /* @@ -3816,10 +3997,11 @@ nfs_gss_mchain_length(mbuf_t mhead) mbuf_t mb; int len = 0; - for (mb = mhead; mb; mb = mbuf_next(mb)) + for (mb = mhead; mb; mb = mbuf_next(mb)) { len += mbuf_len(mb); + } - return (len); + return len; } /* @@ -3833,21 +4015,24 @@ nfs_gss_append_chain(struct nfsm_chain *nmc, mbuf_t mc) /* Connect the mbuf chains */ error = mbuf_setnext(nmc->nmc_mcur, mc); - if (error) - return (error); + if (error) { + return error; + } /* Find the last mbuf in the chain */ tail = NULL; - for (mb = mc; mb; mb = mbuf_next(mb)) + for (mb = mc; mb; mb = mbuf_next(mb)) { tail = mb; + } nmc->nmc_mcur = tail; nmc->nmc_ptr = (caddr_t) mbuf_data(tail) + mbuf_len(tail); nmc->nmc_left = mbuf_trailingspace(tail); - return (0); + return 0; } +#if CONFIG_NFS_SERVER /* Only used by CONFIG_NFS_SERVER */ /* * Convert an mbuf chain to an NFS mbuf chain */ @@ -3858,8 +4043,9 @@ nfs_gss_nfsm_chain(struct nfsm_chain *nmc, mbuf_t mc) /* Find the last mbuf in the chain */ tail = NULL; - for (mb = mc; mb; mb = mbuf_next(mb)) + for (mb = mc; mb; mb = mbuf_next(mb)) { tail = mb; + } nmc->nmc_mhead = mc; nmc->nmc_mcur = tail; @@ -3867,7 +4053,7 @@ nfs_gss_nfsm_chain(struct nfsm_chain *nmc, mbuf_t mc) nmc->nmc_left = mbuf_trailingspace(tail); nmc->nmc_flags = 0; } - +#endif /* CONFIG_NFS_SERVER */ #if 0 @@ -3879,16 +4065,20 @@ hexdump(const char *msg, void *data, size_t len) { size_t i, j; u_char *d = data; - char *p, disbuf[3*DISPLAYLEN+1]; - + char *p, disbuf[3 * DISPLAYLEN + 1]; + printf("NFS DEBUG %s len=%d:\n", msg, (uint32_t)len); - if (len > MAXDISPLAYLEN) + if (len > MAXDISPLAYLEN) { len = MAXDISPLAYLEN; + } for (i = 0; i < len; i += DISPLAYLEN) { - for (p = disbuf, j = 0; (j + i) < len && j < DISPLAYLEN; j++, p += 3) + for (p = disbuf, j = 0; (j + i) < len && j < DISPLAYLEN; j++, p += 3) { snprintf(p, 4, "%02x ", d[i + j]); + } printf("\t%s\n", disbuf); } } #endif + +#endif /* CONFIG_NFS */