예제 #1
0
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);
}
예제 #2
0
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;
}
예제 #3
0
/*
 * 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);
		}
예제 #4
0
/*
 * 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);
		}
예제 #5
0
/*
 * 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;
	}
예제 #6
0
/*
 * 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 */
예제 #7
0
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);
}