/* * XDR a reply message */ bool_t xdr_replymsg(XDR *xdrs, struct rpc_msg *rmsg) { int32_t *buf; enum msg_type *prm_direction; enum reply_stat *prp_stat; assert(xdrs != NULL); assert(rmsg != NULL); if (xdrs->x_op == XDR_DECODE) { buf = XDR_INLINE(xdrs, 3 * BYTES_PER_XDR_UNIT); if (buf != NULL) { rmsg->rm_xid = IXDR_GET_UINT32(buf); rmsg->rm_direction = IXDR_GET_ENUM(buf, enum msg_type); if (rmsg->rm_direction != REPLY) { return (FALSE); } rmsg->rm_reply.rp_stat = IXDR_GET_ENUM(buf, enum reply_stat); if (rmsg->rm_reply.rp_stat == MSG_ACCEPTED) return (xdr_accepted_reply(xdrs, &rmsg->acpted_rply)); else if (rmsg->rm_reply.rp_stat == MSG_DENIED) return (xdr_rejected_reply(xdrs, &rmsg->rjcted_rply)); else return (FALSE); }
/* * Unix longhand authenticator */ enum auth_stat _svcauth_unix(struct svc_req *rqst, struct rpc_msg *msg) { enum auth_stat stat; XDR xdrs; int32_t *buf; uint32_t time; struct xucred *xcr; u_int auth_len; size_t str_len, gid_len; u_int i; xcr = rqst->rq_clntcred; auth_len = (u_int)msg->rm_call.cb_cred.oa_length; xdrmem_create(&xdrs, msg->rm_call.cb_cred.oa_base, auth_len, XDR_DECODE); buf = XDR_INLINE(&xdrs, auth_len); if (buf != NULL) { time = IXDR_GET_UINT32(buf); str_len = (size_t)IXDR_GET_UINT32(buf); if (str_len > MAX_MACHINE_NAME) { stat = AUTH_BADCRED; goto done; } str_len = RNDUP(str_len); buf += str_len / sizeof (int32_t); xcr->cr_uid = IXDR_GET_UINT32(buf); xcr->cr_groups[0] = IXDR_GET_UINT32(buf); gid_len = (size_t)IXDR_GET_UINT32(buf); if (gid_len > NGRPS) { stat = AUTH_BADCRED; goto done; } for (i = 0; i < gid_len; i++) { if (i + 1 < XU_NGROUPS) xcr->cr_groups[i + 1] = IXDR_GET_INT32(buf); else buf++; } if (gid_len + 1 > XU_NGROUPS) xcr->cr_ngroups = XU_NGROUPS; else xcr->cr_ngroups = gid_len + 1; /* * five is the smallest unix credentials structure - * timestamp, hostname len (0), uid, gid, and gids len (0). */ if ((5 + gid_len) * BYTES_PER_XDR_UNIT + str_len > auth_len) { (void) printf("bad auth_len gid %ld str %ld auth %u\n", (long)gid_len, (long)str_len, auth_len); stat = AUTH_BADCRED; goto done; } } else if (! xdr_authunix_parms(&xdrs, &time, xcr)) { stat = AUTH_BADCRED; goto done; } rqst->rq_verf = _null_auth; stat = AUTH_OK; done: XDR_DESTROY(&xdrs); return (stat); }
/* * XDR a call message */ bool_t xdr_callmsg(XDR *xdrs, struct rpc_msg *cmsg) { enum msg_type *prm_direction; int32_t *buf; struct opaque_auth *oa; if (xdrs->x_op == XDR_ENCODE) { if (cmsg->rm_call.cb_cred.oa_length > MAX_AUTH_BYTES) { return (FALSE); } if (cmsg->rm_call.cb_verf.oa_length > MAX_AUTH_BYTES) { return (FALSE); } buf = XDR_INLINE(xdrs, 8 * BYTES_PER_XDR_UNIT + RNDUP(cmsg->rm_call.cb_cred.oa_length) + 2 * BYTES_PER_XDR_UNIT + RNDUP(cmsg->rm_call.cb_verf.oa_length)); if (buf != NULL) { IXDR_PUT_INT32(buf, cmsg->rm_xid); IXDR_PUT_ENUM(buf, cmsg->rm_direction); if (cmsg->rm_direction != CALL) { return (FALSE); } IXDR_PUT_INT32(buf, cmsg->rm_call.cb_rpcvers); if (cmsg->rm_call.cb_rpcvers != RPC_MSG_VERSION) { return (FALSE); } IXDR_PUT_INT32(buf, cmsg->rm_call.cb_prog); IXDR_PUT_INT32(buf, cmsg->rm_call.cb_vers); IXDR_PUT_INT32(buf, cmsg->rm_call.cb_proc); oa = &cmsg->rm_call.cb_cred; IXDR_PUT_ENUM(buf, oa->oa_flavor); IXDR_PUT_INT32(buf, oa->oa_length); if (oa->oa_length) { memcpy(buf, oa->oa_base, oa->oa_length); buf += RNDUP(oa->oa_length) / sizeof (int32_t); } oa = &cmsg->rm_call.cb_verf; IXDR_PUT_ENUM(buf, oa->oa_flavor); IXDR_PUT_INT32(buf, oa->oa_length); if (oa->oa_length) { memcpy(buf, oa->oa_base, oa->oa_length); /* no real need.... buf += RNDUP(oa->oa_length) / sizeof (int32_t); */ } return (TRUE); } } if (xdrs->x_op == XDR_DECODE) { buf = XDR_INLINE(xdrs, 8 * BYTES_PER_XDR_UNIT); if (buf != NULL) { cmsg->rm_xid = IXDR_GET_UINT32(buf); cmsg->rm_direction = IXDR_GET_ENUM(buf, enum msg_type); if (cmsg->rm_direction != CALL) { return (FALSE); } cmsg->rm_call.cb_rpcvers = IXDR_GET_UINT32(buf); if (cmsg->rm_call.cb_rpcvers != RPC_MSG_VERSION) { return (FALSE); } cmsg->rm_call.cb_prog = IXDR_GET_UINT32(buf); cmsg->rm_call.cb_vers = IXDR_GET_UINT32(buf); cmsg->rm_call.cb_proc = IXDR_GET_UINT32(buf); oa = &cmsg->rm_call.cb_cred; oa->oa_flavor = IXDR_GET_ENUM(buf, enum_t); oa->oa_length = (u_int)IXDR_GET_UINT32(buf); if (oa->oa_length) { if (oa->oa_length > MAX_AUTH_BYTES) { return (FALSE); } if (oa->oa_base == NULL) { oa->oa_base = (caddr_t) mem_alloc(oa->oa_length); if (oa->oa_base == NULL) return (FALSE); } buf = XDR_INLINE(xdrs, RNDUP(oa->oa_length)); if (buf == NULL) { if (xdr_opaque(xdrs, oa->oa_base, oa->oa_length) == FALSE) { return (FALSE); } } else { memcpy(oa->oa_base, buf, oa->oa_length); /* no real need.... buf += RNDUP(oa->oa_length) / sizeof (int32_t); */ } } oa = &cmsg->rm_call.cb_verf; buf = XDR_INLINE(xdrs, 2 * BYTES_PER_XDR_UNIT); if (buf == NULL) { if (xdr_enum(xdrs, &oa->oa_flavor) == FALSE || xdr_u_int(xdrs, &oa->oa_length) == FALSE) { return (FALSE); } } else { oa->oa_flavor = IXDR_GET_ENUM(buf, enum_t); oa->oa_length = (u_int)IXDR_GET_UINT32(buf); } if (oa->oa_length) { if (oa->oa_length > MAX_AUTH_BYTES) { return (FALSE); } if (oa->oa_base == NULL) { oa->oa_base = (caddr_t) mem_alloc(oa->oa_length); if (oa->oa_base == NULL) return (FALSE); } buf = XDR_INLINE(xdrs, RNDUP(oa->oa_length)); if (buf == NULL) { if (xdr_opaque(xdrs, oa->oa_base, oa->oa_length) == FALSE) { return (FALSE); } } else { memcpy(oa->oa_base, buf, oa->oa_length); /* no real need... buf += RNDUP(oa->oa_length) / sizeof (int32_t); */ } } return (TRUE); }