GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
gss_encapsulate_token(gss_const_buffer_t input_token,
		      gss_const_OID oid,
		      gss_buffer_t output_token)
{
    GSSAPIContextToken ct;
    int ret;
    size_t size;

    ret = der_get_oid (oid->elements, oid->length, &ct.thisMech, &size);
    if (ret) {
	_mg_buffer_zero(output_token);
	return GSS_S_FAILURE;
    }

    ct.innerContextToken.data = input_token->value;
    ct.innerContextToken.length = input_token->length;

    ASN1_MALLOC_ENCODE(GSSAPIContextToken,
		       output_token->value, output_token->length,
		       &ct, &size, ret);
    der_free_oid(&ct.thisMech);
    if (ret) {
	_mg_buffer_zero(output_token);
	return GSS_S_FAILURE;
    }
    if (output_token->length != size)
	abort();

    return GSS_S_COMPLETE;
}
Beispiel #2
0
GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
gss_oid_to_str(OM_uint32 *minor_status, gss_OID oid, gss_buffer_t oid_str)
{
    int ret;
    size_t size;
    heim_oid o;
    char *p;

    _mg_buffer_zero(oid_str);

    if (oid == GSS_C_NULL_OID)
	return GSS_S_FAILURE;

    ret = der_get_oid (oid->elements, oid->length, &o, &size);
    if (ret) {
	*minor_status = ret;
	return GSS_S_FAILURE;
    }

    ret = der_print_heim_oid(&o, ' ', &p);
    der_free_oid(&o);
    if (ret) {
	*minor_status = ret;
	return GSS_S_FAILURE;
    }

    oid_str->value = p;
    oid_str->length = strlen(p);

    *minor_status = 0;
    return GSS_S_COMPLETE;
}
Beispiel #3
0
OM_uint32 GSSAPI_LIB_FUNCTION
gss_pseudo_random(OM_uint32 *minor_status,
		  gss_ctx_id_t context,
		  int prf_key,
		  const gss_buffer_t prf_in,
		  ssize_t desired_output_len,
		  gss_buffer_t prf_out)
{
    struct _gss_context *ctx = (struct _gss_context *) context;
    gssapi_mech_interface m;
    OM_uint32 major_status;

    _mg_buffer_zero(prf_out);
    *minor_status = 0;

    if (ctx == NULL) {
	*minor_status = 0;
	return GSS_S_NO_CONTEXT;
    }

    m = ctx->gc_mech;

    if (m->gm_pseudo_random == NULL)
	return GSS_S_UNAVAILABLE;

    major_status = (*m->gm_pseudo_random)(minor_status, ctx->gc_ctx,
					  prf_key, prf_in, desired_output_len,
					  prf_out);
    if (major_status != GSS_S_COMPLETE)
	_gss_mg_error(m, major_status, *minor_status);

    return major_status;
}
Beispiel #4
0
GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
gss_wrap(OM_uint32 *minor_status,
    const gss_ctx_id_t context_handle,
    int conf_req_flag,
    gss_qop_t qop_req,
    const gss_buffer_t input_message_buffer,
    int *conf_state,
    gss_buffer_t output_message_buffer)
{
	struct _gss_context *ctx = (struct _gss_context *) context_handle;
	gssapi_mech_interface m;

	if (conf_state)
	    *conf_state = 0;
	_mg_buffer_zero(output_message_buffer);
	if (ctx == NULL) {
	    *minor_status = 0;
	    return GSS_S_NO_CONTEXT;
	}

	m = ctx->gc_mech;

	return (m->gm_wrap(minor_status, ctx->gc_ctx,
		    conf_req_flag, qop_req, input_message_buffer,
		    conf_state, output_message_buffer));
}
OM_uint32 GSSAPI_LIB_FUNCTION
gss_export_sec_context(OM_uint32 *minor_status,
    gss_ctx_id_t *context_handle,
    gss_buffer_t interprocess_token)
{
	OM_uint32 major_status;
	struct _gss_context *ctx = (struct _gss_context *) *context_handle;
	gssapi_mech_interface m = ctx->gc_mech;
	gss_buffer_desc buf;

	_mg_buffer_zero(interprocess_token);

	major_status = m->gm_export_sec_context(minor_status,
	    &ctx->gc_ctx, &buf);
	
	if (major_status == GSS_S_COMPLETE) {
		unsigned char *p;

		free(ctx);
		*context_handle = GSS_C_NO_CONTEXT;
		interprocess_token->length = buf.length
			+ 2 + m->gm_mech_oid.length;
		interprocess_token->value = malloc(interprocess_token->length);
		if (!interprocess_token->value) {
			/*
			 * We are in trouble here - the context is
			 * already gone. This is allowed as long as we
			 * set the caller's context_handle to
			 * GSS_C_NO_CONTEXT, which we did above.
			 * Return GSS_S_FAILURE.
			 */
			_mg_buffer_zero(interprocess_token);
			*minor_status = ENOMEM;
			return (GSS_S_FAILURE);
		}
		p = interprocess_token->value;
		p[0] = m->gm_mech_oid.length >> 8;
		p[1] = m->gm_mech_oid.length;
		memcpy(p + 2, m->gm_mech_oid.elements, m->gm_mech_oid.length);
		memcpy(p + 2 + m->gm_mech_oid.length, buf.value, buf.length);
		gss_release_buffer(minor_status, &buf);
	} else {
Beispiel #6
0
GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
gss_get_mic(OM_uint32 *minor_status,
    const gss_ctx_id_t context_handle,
    gss_qop_t qop_req,
    const gss_buffer_t message_buffer,
    gss_buffer_t message_token)
{
	struct _gss_context *ctx = (struct _gss_context *) context_handle;
	gssapi_mech_interface m;

	_mg_buffer_zero(message_token);
	if (ctx == NULL) {
	    *minor_status = 0;
	    return GSS_S_NO_CONTEXT;
	}

	m = ctx->gc_mech;

	return (m->gm_get_mic(minor_status, ctx->gc_ctx, qop_req,
		    message_buffer, message_token));
}
Beispiel #7
0
GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
gss_decapsulate_token(gss_const_buffer_t input_token,
		      gss_const_OID oid,
		      gss_buffer_t output_token)
{
    GSSAPIContextToken ct;
    heim_oid o;
    OM_uint32 status;
    int ret;
    size_t size;

    _mg_buffer_zero(output_token);

    ret = der_get_oid (oid->elements, oid->length, &o, &size);
    if (ret)
	return GSS_S_FAILURE;

    ret = decode_GSSAPIContextToken(input_token->value, input_token->length,
				    &ct, NULL);
    if (ret) {
	der_free_oid(&o);
	return GSS_S_FAILURE;
    }

    if (der_heim_oid_cmp(&ct.thisMech, &o) == 0) {
	status = GSS_S_COMPLETE;
	output_token->value = ct.innerContextToken.data;
	output_token->length = ct.innerContextToken.length;
	der_free_oid(&ct.thisMech);
    } else {
	free_GSSAPIContextToken(&ct);
 	status = GSS_S_FAILURE;
    }
    der_free_oid(&o);

    return status;
}
GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
gss_export_name(OM_uint32 *minor_status,
    const gss_name_t input_name,
    gss_buffer_t exported_name)
{
	struct _gss_name *name = (struct _gss_name *) input_name;
	struct _gss_mechanism_name *mn;

	_mg_buffer_zero(exported_name);

	/*
	 * If this name already has any attached MNs, export the first
	 * one, otherwise export based on the first mechanism in our
	 * list.
	 */
	mn = SLIST_FIRST(&name->gn_mn);
	if (!mn) {
		*minor_status = 0;
		return (GSS_S_NAME_NOT_MN);
	}

	return mn->gmn_mech->gm_export_name(minor_status,
	    mn->gmn_name, exported_name);
}
Beispiel #9
0
GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
gss_display_status(OM_uint32 *minor_status,
    OM_uint32 status_value,
    int status_type,
    const gss_OID mech_type,
    OM_uint32 *message_content,
    gss_buffer_t status_string)
{
	OM_uint32 major_status;

	_mg_buffer_zero(status_string);
	*message_content = 0;

	major_status = _gss_mg_get_error(mech_type, status_type,
					 status_value, status_string);
	if (major_status == GSS_S_COMPLETE) {

	    *message_content = 0;
	    *minor_status = 0;
	    return GSS_S_COMPLETE;
	}

	*minor_status = 0;
	switch (status_type) {
	case GSS_C_GSS_CODE: {
	    	char *buf = NULL;
		int e;

		if (GSS_SUPPLEMENTARY_INFO(status_value))
		    e = asprintf(&buf, "%s", supplementary_error(
		        GSS_SUPPLEMENTARY_INFO(status_value)));
		else
		    e = asprintf (&buf, "%s %s",
		        calling_error(GSS_CALLING_ERROR(status_value)),
			routine_error(GSS_ROUTINE_ERROR(status_value)));

		if (e < 0 || buf == NULL)
		    break;

		status_string->length = strlen(buf);
		status_string->value  = buf;

		return GSS_S_COMPLETE;
	}
	case GSS_C_MECH_CODE: {
		OM_uint32 maj_junk, min_junk;
		gss_buffer_desc oid;
		char *buf = NULL;
		int e;

		maj_junk = gss_oid_to_str(&min_junk, mech_type, &oid);
		if (maj_junk != GSS_S_COMPLETE) {
		    oid.value = rk_UNCONST("unknown");
		    oid.length = 7;
		}
		
		e = asprintf (&buf, "unknown mech-code %lu for mech %.*s",
			  (unsigned long)status_value,
			  (int)oid.length, (char *)oid.value);
		if (maj_junk == GSS_S_COMPLETE)
		    gss_release_buffer(&min_junk, &oid);

		if (e < 0 || buf == NULL)
		    break;

		status_string->length = strlen(buf);
		status_string->value  = buf;

		return GSS_S_COMPLETE;
	}
	}
	_mg_buffer_zero(status_string);
	return (GSS_S_BAD_STATUS);
}
GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
gss_accept_sec_context(OM_uint32 *minor_status,
    gss_ctx_id_t *context_handle,
    const gss_cred_id_t acceptor_cred_handle,
    const gss_buffer_t input_token,
    const gss_channel_bindings_t input_chan_bindings,
    gss_name_t *src_name,
    gss_OID *mech_type,
    gss_buffer_t output_token,
    OM_uint32 *ret_flags,
    OM_uint32 *time_rec,
    gss_cred_id_t *delegated_cred_handle)
{
	OM_uint32 major_status, mech_ret_flags, junk;
	gssapi_mech_interface m;
	struct _gss_context *ctx = (struct _gss_context *) *context_handle;
	struct _gss_cred *cred = (struct _gss_cred *) acceptor_cred_handle;
	struct _gss_mechanism_cred *mc;
	gss_cred_id_t acceptor_mc, delegated_mc;
	gss_name_t src_mn;
	gss_OID mech_ret_type = NULL;

	*minor_status = 0;
	if (src_name)
	    *src_name = GSS_C_NO_NAME;
	if (mech_type)
	    *mech_type = GSS_C_NO_OID;
	if (ret_flags)
	    *ret_flags = 0;
	if (time_rec)
	    *time_rec = 0;
	if (delegated_cred_handle)
	    *delegated_cred_handle = GSS_C_NO_CREDENTIAL;
	_mg_buffer_zero(output_token);


	/*
	 * If this is the first call (*context_handle is NULL), we must
	 * parse the input token to figure out the mechanism to use.
	 */
	if (*context_handle == GSS_C_NO_CONTEXT) {
		gss_OID_desc mech_oid;

		major_status = choose_mech(input_token, &mech_oid);
		if (major_status != GSS_S_COMPLETE)
			return major_status;

		/*
		 * Now that we have a mechanism, we can find the
		 * implementation.
		 */
		ctx = malloc(sizeof(struct _gss_context));
		if (!ctx) {
			*minor_status = ENOMEM;
			return (GSS_S_DEFECTIVE_TOKEN);
		}
		memset(ctx, 0, sizeof(struct _gss_context));
		m = ctx->gc_mech = __gss_get_mechanism(&mech_oid);
		if (!m) {
			free(ctx);
			return (GSS_S_BAD_MECH);
		}
		*context_handle = (gss_ctx_id_t) ctx;
	} else {
		m = ctx->gc_mech;
	}

	if (cred) {
		HEIM_SLIST_FOREACH(mc, &cred->gc_mc, gmc_link)
			if (mc->gmc_mech == m)
				break;
		if (!mc) {
		        gss_delete_sec_context(&junk, context_handle, NULL);
			return (GSS_S_BAD_MECH);
		}
		acceptor_mc = mc->gmc_cred;
	} else {