summaryrefslogtreecommitdiff
path: root/usr/src/uts/common/rpc/sec/auth_kern.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/uts/common/rpc/sec/auth_kern.c')
-rw-r--r--usr/src/uts/common/rpc/sec/auth_kern.c105
1 files changed, 72 insertions, 33 deletions
diff --git a/usr/src/uts/common/rpc/sec/auth_kern.c b/usr/src/uts/common/rpc/sec/auth_kern.c
index e045c1c08f..2c3286d35d 100644
--- a/usr/src/uts/common/rpc/sec/auth_kern.c
+++ b/usr/src/uts/common/rpc/sec/auth_kern.c
@@ -120,78 +120,117 @@ authkern_marshal(AUTH *auth, XDR *xdrs, struct cred *cr)
{
char *sercred;
XDR xdrm;
- struct opaque_auth *cred;
- bool_t ret = FALSE;
- const gid_t *gp, *gpend;
- int gidlen, credsize, namelen, rounded_namelen;
+ bool_t ret;
+ uint32_t gidlen, credsize, namelen, rounded_namelen;
int32_t *ptr;
char *nodename = uts_nodename();
+ uint_t startpos;
+
+ ASSERT(xdrs->x_op == XDR_ENCODE);
+ ASSERT(auth->ah_cred.oa_flavor == AUTH_SYS);
+ ASSERT(auth->ah_verf.oa_flavor == AUTH_NONE);
+ ASSERT(auth->ah_verf.oa_length == 0);
/*
* First we try a fast path to get through
* this very common operation.
*/
- gp = crgetgroups(cr);
+ namelen = (uint32_t)strlen(nodename);
+ if (namelen > MAX_MACHINE_NAME)
+ return (FALSE);
+ rounded_namelen = RNDUP(namelen);
+
+ /*
+ * NFIELDS is a number of the following fields we are going to encode:
+ * - stamp
+ * - strlen(machinename)
+ * - uid
+ * - gid
+ * - the number of gids
+ */
+#define NFIELDS 5
+ CTASSERT((NFIELDS + NGRPS) * BYTES_PER_XDR_UNIT +
+ RNDUP(MAX_MACHINE_NAME) <= MAX_AUTH_BYTES);
+
gidlen = crgetngroups(cr);
if (gidlen > NGRPS)
gidlen = NGRPS;
- gpend = &gp[gidlen-1];
- namelen = (int)strlen(nodename);
- rounded_namelen = RNDUP(namelen);
- credsize = 4 + 4 + rounded_namelen + 4 + 4 + 4 + gidlen * 4;
- ptr = XDR_INLINE(xdrs, 4 + 4 + credsize + 4 + 4);
- if (ptr) {
+ credsize = NFIELDS * BYTES_PER_XDR_UNIT + rounded_namelen +
+ gidlen * BYTES_PER_XDR_UNIT;
+ ASSERT(credsize <= MAX_AUTH_BYTES);
+#undef NFIELDS
+
+ /*
+ * We need to marshal both cred and verf parts of the rpc_msg body
+ * (call_body). For the cred part we need to inline the auth_flavor
+ * and the opaque auth body size. Then we inline the credsize bytes of
+ * the opaque auth body for the cred part. Finally we add the
+ * AUTH_NONE verifier (its auth_flavor and the opaque auth body size).
+ */
+ ptr = XDR_INLINE(xdrs, 2 * BYTES_PER_XDR_UNIT + credsize +
+ 2 * BYTES_PER_XDR_UNIT);
+ if (ptr != NULL) {
/*
* We can do the fast path.
*/
- IXDR_PUT_INT32(ptr, AUTH_UNIX); /* cred flavor */
- IXDR_PUT_INT32(ptr, credsize); /* cred len */
+ const gid_t *gp = crgetgroups(cr);
+
+ IXDR_PUT_U_INT32(ptr, AUTH_SYS); /* cred flavor */
+ IXDR_PUT_U_INT32(ptr, credsize); /* cred len */
+
IXDR_PUT_INT32(ptr, gethrestime_sec());
- IXDR_PUT_INT32(ptr, namelen);
- bcopy(nodename, (caddr_t)ptr, namelen);
- if (rounded_namelen - namelen)
- bzero(((caddr_t)ptr) + namelen,
- rounded_namelen - namelen);
+ IXDR_PUT_U_INT32(ptr, namelen);
+ bcopy(nodename, ptr, namelen);
+ if ((rounded_namelen - namelen) > 0)
+ bzero((char *)ptr + namelen, rounded_namelen - namelen);
ptr += rounded_namelen / BYTES_PER_XDR_UNIT;
- IXDR_PUT_INT32(ptr, crgetuid(cr));
- IXDR_PUT_INT32(ptr, crgetgid(cr));
- IXDR_PUT_INT32(ptr, gidlen);
- while (gp <= gpend) {
- IXDR_PUT_INT32(ptr, *gp++);
- }
- IXDR_PUT_INT32(ptr, AUTH_NULL); /* verf flavor */
- IXDR_PUT_INT32(ptr, 0); /* verf len */
+ IXDR_PUT_U_INT32(ptr, crgetuid(cr));
+ IXDR_PUT_U_INT32(ptr, crgetgid(cr));
+ IXDR_PUT_U_INT32(ptr, gidlen);
+ while (gidlen-- > 0)
+ IXDR_PUT_U_INT32(ptr, *gp++);
+
+ IXDR_PUT_U_INT32(ptr, AUTH_NULL); /* verf flavor */
+ IXDR_PUT_U_INT32(ptr, 0); /* verf len */
+
return (TRUE);
}
+
sercred = kmem_alloc(MAX_AUTH_BYTES, KM_SLEEP);
+
/*
- * serialize u struct stuff into sercred
+ * Serialize the auth body data into sercred.
*/
xdrmem_create(&xdrm, sercred, MAX_AUTH_BYTES, XDR_ENCODE);
- if (!xdr_authkern(&xdrm)) {
+ startpos = XDR_GETPOS(&xdrm);
+ if (!xdr_authkern(&xdrm, cr)) {
printf("authkern_marshal: xdr_authkern failed\n");
ret = FALSE;
goto done;
}
/*
- * Make opaque auth credentials that point at serialized u struct
+ * Make opaque auth credentials to point at the serialized auth body
+ * data.
*/
- cred = &(auth->ah_cred);
- cred->oa_length = XDR_GETPOS(&xdrm);
- cred->oa_base = sercred;
+ auth->ah_cred.oa_base = sercred;
+ auth->ah_cred.oa_length = XDR_GETPOS(&xdrm) - startpos;
+ ASSERT(auth->ah_cred.oa_length <= MAX_AUTH_BYTES);
/*
- * serialize credentials and verifiers (null)
+ * serialize credentials and verifier (null)
*/
if ((xdr_opaque_auth(xdrs, &(auth->ah_cred))) &&
(xdr_opaque_auth(xdrs, &(auth->ah_verf))))
ret = TRUE;
else
ret = FALSE;
+
done:
+ XDR_DESTROY(&xdrm);
kmem_free(sercred, MAX_AUTH_BYTES);
+
return (ret);
}