static bool_t svcauth_gss_validate(struct svc_req *rqst, struct svc_rpc_gss_data *gd, struct rpc_msg *msg) { struct opaque_auth *oa; gss_buffer_desc rpcbuf, checksum; OM_uint32 maj_stat, min_stat, qop_state; u_char rpchdr[128]; int32_t *buf; log_debug("in svcauth_gss_validate()"); memset(rpchdr, 0, sizeof(rpchdr)); /* XXX - Reconstruct RPC header for signing (from xdr_callmsg). */ oa = &msg->rm_call.cb_cred; if (oa->oa_length > MAX_AUTH_BYTES) return (FALSE); /* 8 XDR units from the IXDR macro calls. */ if (sizeof(rpchdr) < (8 * BYTES_PER_XDR_UNIT + RNDUP(oa->oa_length))) return (FALSE); buf = (int32_t *)(void *)rpchdr; IXDR_PUT_LONG(buf, msg->rm_xid); IXDR_PUT_ENUM(buf, msg->rm_direction); IXDR_PUT_LONG(buf, msg->rm_call.cb_rpcvers); IXDR_PUT_LONG(buf, msg->rm_call.cb_prog); IXDR_PUT_LONG(buf, msg->rm_call.cb_vers); IXDR_PUT_LONG(buf, msg->rm_call.cb_proc); IXDR_PUT_ENUM(buf, oa->oa_flavor); IXDR_PUT_LONG(buf, oa->oa_length); if (oa->oa_length) { memcpy((caddr_t)buf, oa->oa_base, oa->oa_length); buf += RNDUP(oa->oa_length) / sizeof(int32_t); } rpcbuf.value = rpchdr; rpcbuf.length = (u_char *)buf - rpchdr; checksum.value = msg->rm_call.cb_verf.oa_base; checksum.length = msg->rm_call.cb_verf.oa_length; maj_stat = gss_verify_mic(&min_stat, gd->ctx, &rpcbuf, &checksum, &qop_state); if (maj_stat != GSS_S_COMPLETE) { log_status("gss_verify_mic", maj_stat, min_stat); if (log_badverf != NULL) (*log_badverf)(gd->client_name, svcauth_gss_name, rqst, msg, log_badverf_data); return (FALSE); } return (TRUE); }
static int svcauth_gss_validate(struct svc_req *req, struct svc_rpc_gss_data *gd, struct rpc_msg *msg) { struct opaque_auth *oa; gss_buffer_desc rpcbuf, checksum; OM_uint32 maj_stat, min_stat, qop_state; u_char rpchdr[RPCHDR_LEN]; int32_t *buf; memset(rpchdr, 0, RPCHDR_LEN); /* XXX - Reconstruct RPC header for signing (from xdr_callmsg). */ oa = &msg->rm_call.cb_cred; if (oa->oa_length > MAX_AUTH_BYTES) return GSS_S_CALL_BAD_STRUCTURE; /* XXX since MAX_AUTH_BYTES is 400, the following code trivially * overruns (up to 431 per Coverity, but compare RPCHDR_LEN with * what is marshalled below). */ buf = (int32_t *) rpchdr; IXDR_PUT_LONG(buf, msg->rm_xid); IXDR_PUT_ENUM(buf, msg->rm_direction); IXDR_PUT_LONG(buf, msg->rm_call.cb_rpcvers); IXDR_PUT_LONG(buf, msg->rm_call.cb_prog); IXDR_PUT_LONG(buf, msg->rm_call.cb_vers); IXDR_PUT_LONG(buf, msg->rm_call.cb_proc); IXDR_PUT_ENUM(buf, oa->oa_flavor); IXDR_PUT_LONG(buf, oa->oa_length); if (oa->oa_length) { memcpy((caddr_t) buf, oa->oa_base, oa->oa_length); buf += RNDUP(oa->oa_length) / sizeof(int32_t); } rpcbuf.value = rpchdr; rpcbuf.length = (u_char *) buf - rpchdr; checksum.value = msg->rm_call.cb_verf.oa_base; checksum.length = msg->rm_call.cb_verf.oa_length; maj_stat = gss_verify_mic(&min_stat, gd->ctx, &rpcbuf, &checksum, &qop_state); if (maj_stat != GSS_S_COMPLETE) { __warnx(TIRPC_DEBUG_FLAG_AUTH, "%s: %d %d", __func__, maj_stat, min_stat); return (maj_stat); } return GSS_S_COMPLETE; }
/* * XDR a call message */ bool_t xdr_callmsg( register XDR *xdrs, register struct rpc_msg *cmsg) { register uint32_t *buf; register 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_LONG(buf, (uint32_t)cmsg->rm_xid); IXDR_PUT_ENUM(buf, (uint32_t)cmsg->rm_direction); if (cmsg->rm_direction != CALL) { return (FALSE); } IXDR_PUT_LONG(buf, (uint32_t)cmsg->rm_call.cb_rpcvers); if (cmsg->rm_call.cb_rpcvers != RPC_MSG_VERSION) { return (FALSE); } IXDR_PUT_LONG(buf, (uint32_t)cmsg->rm_call.cb_prog); IXDR_PUT_LONG(buf, (uint32_t)cmsg->rm_call.cb_vers); IXDR_PUT_LONG(buf, (uint32_t)cmsg->rm_call.cb_proc); oa = &cmsg->rm_call.cb_cred; IXDR_PUT_ENUM(buf, oa->oa_flavor); IXDR_PUT_LONG(buf, oa->oa_length); if (oa->oa_length) { bcopy(oa->oa_base, (char*)buf, oa->oa_length); buf += RNDUP(oa->oa_length) / sizeof (*buf); } oa = &cmsg->rm_call.cb_verf; IXDR_PUT_ENUM(buf, oa->oa_flavor); IXDR_PUT_LONG(buf, oa->oa_length); if (oa->oa_length) { bcopy(oa->oa_base, (char*)buf, oa->oa_length); /* no real need.... buf += RNDUP(oa->oa_length) / sizeof (*buf); */ } 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_LONG(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_LONG(buf); if (cmsg->rm_call.cb_rpcvers != RPC_MSG_VERSION) { return (FALSE); } cmsg->rm_call.cb_prog = IXDR_GET_LONG(buf); cmsg->rm_call.cb_vers = IXDR_GET_LONG(buf); cmsg->rm_call.cb_proc = IXDR_GET_LONG(buf); oa = &cmsg->rm_call.cb_cred; oa->oa_flavor = IXDR_GET_ENUM(buf, enum_t); oa->oa_length = IXDR_GET_LONG(buf); if (oa->oa_length) { if (oa->oa_length > MAX_AUTH_BYTES) { return (FALSE); } if (oa->oa_base == NULL) { oa->oa_base = (char*) mem_alloc(oa->oa_length); } 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 { bcopy((char*)buf, oa->oa_base, oa->oa_length); /* no real need.... buf += RNDUP(oa->oa_length) / sizeof (*buf); */ } } 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 = IXDR_GET_LONG(buf); } if (oa->oa_length) { if (oa->oa_length > MAX_AUTH_BYTES) { return (FALSE); } if (oa->oa_base == NULL) { oa->oa_base = (char*) mem_alloc(oa->oa_length); } 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 { bcopy((char*)buf, oa->oa_base, oa->oa_length); /* no real need... buf += RNDUP(oa->oa_length) / sizeof (*buf); */ } } return (TRUE); }
/* * XDR a call message */ bool_t xdr_callmsg(XDR *xdrs, struct rpc_msg *cmsg) { rpc_inline_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) { (void) 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) { (void) 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_INT32(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_INT32(buf); if (cmsg->rm_call.cb_rpcvers != RPC_MSG_VERSION) return (FALSE); cmsg->rm_call.cb_prog = IXDR_GET_INT32(buf); cmsg->rm_call.cb_vers = IXDR_GET_INT32(buf); cmsg->rm_call.cb_proc = IXDR_GET_INT32(buf); oa = &cmsg->rm_call.cb_cred; oa->oa_flavor = IXDR_GET_ENUM(buf, enum_t); oa->oa_length = IXDR_GET_INT32(buf); if (oa->oa_length) { if (oa->oa_length > MAX_AUTH_BYTES) return (FALSE); if (oa->oa_base == NULL) { oa->oa_base = malloc(oa->oa_length); if (oa->oa_base == NULL) { syslog(LOG_ERR, "xdr_callmsg : " "out of memory."); 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 { (void) memcpy(oa->oa_base, buf, (size_t)oa->oa_length); /* * no real need.... * buf += RNDUP(oa->oa_length) / * (int)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 = IXDR_GET_INT32(buf); } if (oa->oa_length) { if (oa->oa_length > MAX_AUTH_BYTES) return (FALSE); if (oa->oa_base == NULL) { oa->oa_base = malloc(oa->oa_length); if (oa->oa_base == NULL) { syslog(LOG_ERR, "xdr_callmsg : " "out of memory."); 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 { (void) memcpy(oa->oa_base, buf, (size_t)oa->oa_length); /* * no real need... * buf += RNDUP(oa->oa_length) / * (int)sizeof (int32_t); */ } } return (TRUE); }
/* * XDR a call message */ bool_t xdr_callmsg (XDR *xdrs, struct rpc_msg *cmsg) { 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) { (void) IXDR_PUT_LONG (buf, cmsg->rm_xid); (void) IXDR_PUT_ENUM (buf, cmsg->rm_direction); if (cmsg->rm_direction != CALL) return FALSE; (void) IXDR_PUT_LONG (buf, cmsg->rm_call.cb_rpcvers); if (cmsg->rm_call.cb_rpcvers != RPC_MSG_VERSION) return FALSE; (void) IXDR_PUT_LONG (buf, cmsg->rm_call.cb_prog); (void) IXDR_PUT_LONG (buf, cmsg->rm_call.cb_vers); (void) IXDR_PUT_LONG (buf, cmsg->rm_call.cb_proc); oa = &cmsg->rm_call.cb_cred; (void) IXDR_PUT_ENUM (buf, oa->oa_flavor); (void) IXDR_PUT_INT32 (buf, oa->oa_length); if (oa->oa_length) { memcpy ((caddr_t) buf, oa->oa_base, oa->oa_length); buf = (int32_t *) ((char *) buf + RNDUP (oa->oa_length)); } oa = &cmsg->rm_call.cb_verf; (void) IXDR_PUT_ENUM (buf, oa->oa_flavor); (void) IXDR_PUT_INT32 (buf, oa->oa_length); if (oa->oa_length) { memcpy ((caddr_t) buf, oa->oa_base, oa->oa_length); /* no real need.... buf = (long *) ((char *) buf + RNDUP(oa->oa_length)); */ } 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_LONG (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_LONG (buf); if (cmsg->rm_call.cb_rpcvers != RPC_MSG_VERSION) { return FALSE; } cmsg->rm_call.cb_prog = IXDR_GET_LONG (buf); cmsg->rm_call.cb_vers = IXDR_GET_LONG (buf); cmsg->rm_call.cb_proc = IXDR_GET_LONG (buf); oa = &cmsg->rm_call.cb_cred; oa->oa_flavor = IXDR_GET_ENUM (buf, enum_t); oa->oa_length = IXDR_GET_INT32 (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); } buf = XDR_INLINE (xdrs, RNDUP (oa->oa_length)); if (buf == NULL) { if (INTUSE(xdr_opaque) (xdrs, oa->oa_base, oa->oa_length) == FALSE) return FALSE; } else { memcpy (oa->oa_base, (caddr_t) buf, oa->oa_length); /* no real need.... buf = (long *) ((char *) buf + RNDUP(oa->oa_length)); */ } } oa = &cmsg->rm_call.cb_verf; buf = XDR_INLINE (xdrs, 2 * BYTES_PER_XDR_UNIT); if (buf == NULL) { if (INTUSE(xdr_enum) (xdrs, &oa->oa_flavor) == FALSE || INTUSE(xdr_u_int) (xdrs, &oa->oa_length) == FALSE) { return FALSE; } } else { oa->oa_flavor = IXDR_GET_ENUM (buf, enum_t); oa->oa_length = IXDR_GET_INT32 (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); } buf = XDR_INLINE (xdrs, RNDUP (oa->oa_length)); if (buf == NULL) { if (INTUSE(xdr_opaque) (xdrs, oa->oa_base, oa->oa_length) == FALSE) return FALSE; } else { memcpy (oa->oa_base, (caddr_t) buf, oa->oa_length); /* no real need... buf = (long *) ((char *) buf + RNDUP(oa->oa_length)); */ } } return TRUE; }
/* * encode a reply message, log error messages */ bool xdr_reply_encode(XDR *xdrs, struct rpc_msg *dmsg) { struct opaque_auth *oa; int32_t *buf; switch (dmsg->rm_reply.rp_stat) { case MSG_ACCEPTED: { struct accepted_reply *ar = (struct accepted_reply *) &(dmsg->rm_reply.ru); oa = &ar->ar_verf; if (oa->oa_length > MAX_AUTH_BYTES) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s:%u ERROR ar_verf.oa_length (%u) > %u", __func__, __LINE__, oa->oa_length, MAX_AUTH_BYTES); return (false); } buf = XDR_INLINE(xdrs, 6 * BYTES_PER_XDR_UNIT + RNDUP(oa->oa_length)); if (buf != NULL) { __warnx(TIRPC_DEBUG_FLAG_RPC_MSG, "%s:%u ACCEPTED INLINE", __func__, __LINE__); IXDR_PUT_INT32(buf, dmsg->rm_xid); IXDR_PUT_ENUM(buf, dmsg->rm_direction); IXDR_PUT_ENUM(buf, dmsg->rm_reply.rp_stat); 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); } IXDR_PUT_ENUM(buf, ar->ar_stat); switch (ar->ar_stat) { case SUCCESS: __warnx(TIRPC_DEBUG_FLAG_RPC_MSG, "%s:%u SUCCESS", __func__, __LINE__); return ((*(ar->ar_results.proc))(xdrs, ar->ar_results.where)); case PROG_MISMATCH: __warnx(TIRPC_DEBUG_FLAG_RPC_MSG, "%s:%u MISMATCH", __func__, __LINE__); buf = XDR_INLINE(xdrs, 2 * BYTES_PER_XDR_UNIT); if (buf != NULL) { IXDR_PUT_ENUM(buf, ar->ar_vers.low); IXDR_PUT_ENUM(buf, ar->ar_vers.high); } else if (!xdr_putuint32(xdrs, &(ar->ar_vers.low))) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s:%u ERROR ar_vers.low %u", __func__, __LINE__, ar->ar_vers.low); return (false); } else if (!xdr_putuint32(xdrs, &(ar->ar_vers.high))) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s:%u ERROR ar_vers.high %u", __func__, __LINE__, ar->ar_vers.high); return (false); } /* fallthru */ case GARBAGE_ARGS: case SYSTEM_ERR: case PROC_UNAVAIL: case PROG_UNAVAIL: break; }; return (true); } else { __warnx(TIRPC_DEBUG_FLAG_RPC_MSG, "%s:%u ACCEPTED non-INLINE", __func__, __LINE__); return (inline_xdr_union(xdrs, (enum_t *) &(dmsg->rm_reply.rp_stat), (caddr_t)(void *)&(dmsg->rm_reply.ru), reply_dscrm, NULL_xdrproc_t)); } /* never arrives here */ break; } case MSG_DENIED: { struct rejected_reply *rr = (struct rejected_reply *) &(dmsg->rm_reply.ru); switch (rr->rj_stat) { case RPC_MISMATCH: __warnx(TIRPC_DEBUG_FLAG_RPC_MSG, "%s:%u DENIED MISMATCH", __func__, __LINE__); buf = XDR_INLINE(xdrs, 3 * BYTES_PER_XDR_UNIT); if (buf != NULL) { IXDR_PUT_ENUM(buf, rr->rj_stat); IXDR_PUT_U_INT32(buf, rr->rj_vers.low); IXDR_PUT_U_INT32(buf, rr->rj_vers.high); } else if (!xdr_putenum(xdrs, rr->rj_stat)) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s:%u ERROR rj_stat %u", __func__, __LINE__, rr->rj_stat); return (false); } else if (!xdr_putuint32(xdrs, &(rr->rj_vers.low))) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s:%u ERROR rj_vers.low %u", __func__, __LINE__, rr->rj_vers.low); return (false); } else if (!xdr_putuint32(xdrs, &(rr->rj_vers.high))) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s:%u ERROR rj_vers.high %u", __func__, __LINE__, rr->rj_vers.high); return (false); } return (true); /* bugfix */ case AUTH_ERROR: __warnx(TIRPC_DEBUG_FLAG_RPC_MSG, "%s:%u DENIED AUTH", __func__, __LINE__); buf = XDR_INLINE(xdrs, 2 * BYTES_PER_XDR_UNIT); if (buf != NULL) { IXDR_PUT_ENUM(buf, rr->rj_stat); IXDR_PUT_ENUM(buf, rr->rj_why); } else if (!xdr_putenum(xdrs, rr->rj_stat)) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s:%u ERROR rj_stat %u", __func__, __LINE__, rr->rj_stat); return (false); } else if (!xdr_putenum(xdrs, rr->rj_why)) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s:%u ERROR rj_why %u", __func__, __LINE__, rr->rj_why); return (false); } return (true); /* bugfix */ default: __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s:%u ERROR rr->rj_stat (%u)", __func__, __LINE__, rr->rj_stat); break; }; break; } default: __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s:%u ERROR dmsg->rm_reply.rp_stat (%u)", __func__, __LINE__, dmsg->rm_reply.rp_stat); break; }; return (false); } /* XDR_ENCODE */
static bool_t Svcauth_gss_validate(struct svc_req *rqst, struct svc_rpc_gss_data *gd, struct rpc_msg *msg) { struct opaque_auth *oa; gss_buffer_desc rpcbuf, checksum; OM_uint32 maj_stat, min_stat, qop_state; u_char rpchdr[128]; int32_t *buf; char GssError[256]; memset(rpchdr, 0, sizeof(rpchdr)); /* XXX - Reconstruct RPC header for signing (from xdr_callmsg). */ oa = &msg->rm_call.cb_cred; LogFullDebug(COMPONENT_RPCSEC_GSS, "Call to Svcauth_gss_validate --> xid=%u dir=%u rpcvers=%u prog=%u vers=%u proc=%u flavor=%u len=%u base=%p ckeck.len=%u check.val=%p", msg->rm_xid, msg->rm_direction, msg->rm_call.cb_rpcvers, msg->rm_call.cb_prog, msg->rm_call.cb_vers, msg->rm_call.cb_proc, oa->oa_flavor, oa->oa_length, oa->oa_base, msg->rm_call.cb_verf.oa_length, msg->rm_call.cb_verf.oa_base); if(oa->oa_length > MAX_AUTH_BYTES) { LogCrit(COMPONENT_RPCSEC_GSS, "Svcauth_gss_validate oa->oa_length (%u) > MAX_AUTH_BYTES (%u)", oa->oa_length, MAX_AUTH_BYTES); return (FALSE); } /* 8 XDR units from the IXDR macro calls. */ if(sizeof(rpchdr) < (8 * BYTES_PER_XDR_UNIT + RNDUP(oa->oa_length))) { LogCrit(COMPONENT_RPCSEC_GSS, "Svcauth_gss_validate sizeof(rpchdr) (%d) < (8 * BYTES_PER_XDR_UNIT (%d) + RNDUP(oa->oa_length (%u))) (%d)", (int) sizeof(rpchdr), (int) (8 * BYTES_PER_XDR_UNIT), oa->oa_length, (int) (8 * BYTES_PER_XDR_UNIT + RNDUP(oa->oa_length))); return (FALSE); } buf = (int32_t *) (void *)rpchdr; IXDR_PUT_LONG(buf, msg->rm_xid); IXDR_PUT_ENUM(buf, msg->rm_direction); IXDR_PUT_LONG(buf, msg->rm_call.cb_rpcvers); IXDR_PUT_LONG(buf, msg->rm_call.cb_prog); IXDR_PUT_LONG(buf, msg->rm_call.cb_vers); IXDR_PUT_LONG(buf, msg->rm_call.cb_proc); IXDR_PUT_ENUM(buf, oa->oa_flavor); IXDR_PUT_LONG(buf, oa->oa_length); if(oa->oa_length) { memcpy((caddr_t) buf, oa->oa_base, oa->oa_length); buf += RNDUP(oa->oa_length) / sizeof(int32_t); } rpcbuf.value = rpchdr; rpcbuf.length = (u_char *) buf - rpchdr; checksum.value = msg->rm_call.cb_verf.oa_base; checksum.length = msg->rm_call.cb_verf.oa_length; if(isFullDebug(COMPONENT_RPCSEC_GSS)) { char ctx_str[64]; sprint_ctx(ctx_str, (unsigned char *)gd->ctx, sizeof(gss_union_ctx_id_desc)); LogFullDebug(COMPONENT_RPCSEC_GSS, "Svcauth_gss_validate context %s rpcbuf=%p:%u checksum=%p:$%u)", ctx_str, rpcbuf.value, (unsigned int) rpcbuf.length, checksum.value, (unsigned int) checksum.length); } maj_stat = gss_verify_mic(&min_stat, gd->ctx, &rpcbuf, &checksum, &qop_state); if(maj_stat != GSS_S_COMPLETE) { log_sperror_gss(GssError, maj_stat, min_stat); LogCrit(COMPONENT_RPCSEC_GSS, "Error in gss_verify_mic: %s", GssError); return (FALSE); } return (TRUE); }