Esempio n. 1
0
bool_t
xdr_rpc_gss_wrap_data(struct mbuf **argsp,
		      gss_ctx_id_t ctx, gss_qop_t qop,
		      rpc_gss_service_t svc, u_int seq)
{
	struct mbuf	*args, *mic;
	OM_uint32	maj_stat, min_stat;
	int		conf_state;
	u_int		len;
	static char	zpad[4];

	args = *argsp;

	/*
	 * Prepend the sequence number before calling gss_get_mic or gss_wrap.
	 */
	put_uint32(&args, seq);
	len = m_length(args, NULL);

	if (svc == rpc_gss_svc_integrity) {
		/* Checksum rpc_gss_data_t. */
		maj_stat = gss_get_mic_mbuf(&min_stat, ctx, qop, args, &mic);
		if (maj_stat != GSS_S_COMPLETE) {
			rpc_gss_log_debug("gss_get_mic failed");
			m_freem(args);
			return (FALSE);
		}

		/*
		 * Marshal databody_integ. Note that since args is
		 * already RPC encoded, there will be no padding.
		 */
		put_uint32(&args, len);

		/*
		 * Marshal checksum. This is likely to need padding.
		 */
		len = m_length(mic, NULL);
		put_uint32(&mic, len);
		if (len != RNDUP(len)) {
			m_append(mic, RNDUP(len) - len, zpad);
		}

		/*
		 * Concatenate databody_integ with checksum.
		 */
		m_cat(args, mic);
	} else if (svc == rpc_gss_svc_privacy) {
		/* Encrypt rpc_gss_data_t. */
		maj_stat = gss_wrap_mbuf(&min_stat, ctx, TRUE, qop,
		    &args, &conf_state);
		if (maj_stat != GSS_S_COMPLETE) {
			rpc_gss_log_status("gss_wrap", NULL,
			    maj_stat, min_stat);
			return (FALSE);
		}

		/*
		 *  Marshal databody_priv and deal with RPC padding.
		 */
		len = m_length(args, NULL);
		put_uint32(&args, len);
		if (len != RNDUP(len)) {
			m_append(args, RNDUP(len) - len, zpad);
		}
	}
	*argsp = args;
	return (TRUE);
}
Esempio n. 2
0
bool_t
xdr_rpc_gss_unwrap_data(struct mbuf **resultsp,
                        gss_ctx_id_t ctx, gss_qop_t qop,
                        rpc_gss_service_t svc, u_int seq)
{
    struct mbuf	*results, *message, *mic;
    uint32_t	len, cklen;
    OM_uint32	maj_stat, min_stat;
    u_int		seq_num, conf_state, qop_state;

    results = *resultsp;
    *resultsp = NULL;

    message = NULL;
    if (svc == rpc_gss_svc_integrity) {
        /*
         * Extract the seq+message part. Remember that there
         * may be extra RPC padding in the checksum. The
         * message part is RPC encoded already so no
         * padding.
         */
        len = get_uint32(&results);
        message = results;
        results = m_split(results, len, M_WAIT);
        if (!results) {
            m_freem(message);
            return (FALSE);
        }

        /*
         * Extract the MIC and make it contiguous.
         */
        cklen = get_uint32(&results);
        KASSERT(cklen <= MHLEN, ("unexpected large GSS-API checksum"));
        mic = results;
        if (cklen > mic->m_len)
            mic = m_pullup(mic, cklen);
        if (cklen != RNDUP(cklen))
            m_trim(mic, cklen);

        /* Verify checksum and QOP. */
        maj_stat = gss_verify_mic_mbuf(&min_stat, ctx,
                                       message, mic, &qop_state);
        m_freem(mic);

        if (maj_stat != GSS_S_COMPLETE || qop_state != qop) {
            m_freem(message);
            rpc_gss_log_status("gss_verify_mic", NULL,
                               maj_stat, min_stat);
            return (FALSE);
        }
    } else if (svc == rpc_gss_svc_privacy) {
        /* Decode databody_priv. */
        len = get_uint32(&results);

        /* Decrypt databody. */
        message = results;
        if (len != RNDUP(len))
            m_trim(message, len);
        maj_stat = gss_unwrap_mbuf(&min_stat, ctx, &message,
                                   &conf_state, &qop_state);

        /* Verify encryption and QOP. */
        if (maj_stat != GSS_S_COMPLETE) {
            rpc_gss_log_status("gss_unwrap", NULL,
                               maj_stat, min_stat);
            return (FALSE);
        }
        if (qop_state != qop || conf_state != TRUE) {
            m_freem(results);
            return (FALSE);
        }
    }

    /* Decode rpc_gss_data_t (sequence number + arguments). */
    seq_num = get_uint32(&message);

    /* Verify sequence number. */
    if (seq_num != seq) {
        rpc_gss_log_debug("wrong sequence number in databody");
        m_freem(message);
        return (FALSE);
    }

    *resultsp = message;
    return (TRUE);
}