Esempio n. 1
0
File: util.c Progetto: kapilash/dc
int listMechanisms(int argc, char* argv[])
{
    OM_uint32 major, minor;
    gss_OID_set mechanisms;
    int index,i;
    gss_OID currElem = NULL;
    printf("\tListing available mechanisms\n");

    major = gss_indicate_mechs(&minor, &mechanisms);
    checkError(major, minor, "gss_indicate_mechs");
    printf("\tFound %zu elements:\n", mechanisms->count);
    for(index = 0; index < mechanisms->count; index++) {
        currElem = &(mechanisms->elements[index]);
        printf("\t{ %d,", currElem->length);
        for(i = 0; i < currElem->length; i++)
            printf("\\x%x", ((char *)currElem->elements)[i]);
        printf("}\n");
        printOid(currElem);
    }

    if (major != GSS_S_COMPLETE) {
        fprintf(stderr, "failed to get the mechanisms ");
        return 1;
    }

    printf("\tfreeing the oidset..\n");
    major = gss_release_oid_set(&minor, &mechanisms);
    checkError(major, minor, "gss_release_oid_set");
    return 0;
}
Esempio n. 2
0
/* Unprivileged */
void
ssh_gssapi_supported_oids(gss_OID_set *oidset)
{
	int i = 0;
	OM_uint32 min_status;
	int present;
	gss_OID_set supported;

	gss_create_empty_oid_set(&min_status, oidset);

	if (GSS_ERROR(gss_indicate_mechs(&min_status, &supported)))
		return;

	while (supported_mechs[i]->name != NULL) {
		if (GSS_ERROR(gss_test_oid_set_member(&min_status,
		    &supported_mechs[i]->oid, supported, &present)))
			present = 0;
		if (present)
			gss_add_oid_set_member(&min_status,
			    &supported_mechs[i]->oid, oidset);
		i++;
	}

	gss_release_oid_set(&min_status, &supported);
}
Esempio n. 3
0
static void *mag_create_server_config(apr_pool_t *p, server_rec *s)
{
    struct mag_server_config *scfg;
    uint32_t maj, min;
    apr_status_t rc;

    scfg = apr_pcalloc(p, sizeof(struct mag_server_config));

    maj = gss_indicate_mechs(&min, &scfg->default_mechs);
    if (maj != GSS_S_COMPLETE) {
        ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s,
                     "gss_indicate_mechs() failed");
    } else {
        /* Register the set in pool */
        apr_pool_cleanup_register(p, (void *)scfg->default_mechs,
                                  mag_oid_set_destroy, apr_pool_cleanup_null);
    }

    rc = SEAL_KEY_CREATE(p, &scfg->mag_skey, NULL);
    if (rc != OK) {
        ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
                     "Failed to generate random sealing key!");
    }

    return scfg;
}
Esempio n. 4
0
int
supported_mechanisms(void *argptr, int argc, char **argv)
{
    OM_uint32 maj_stat, min_stat;
    gss_OID_set mechs;
    rtbl_t ct;
    size_t i;

    maj_stat = gss_indicate_mechs(&min_stat, &mechs);
    if (maj_stat != GSS_S_COMPLETE)
	errx(1, "gss_indicate_mechs failed");

    printf("Supported mechanisms:\n");

    ct = rtbl_create();
    if (ct == NULL)
	errx(1, "rtbl_create");

    rtbl_set_separator(ct, "  ");
    rtbl_add_column(ct, COL_OID, 0);
    rtbl_add_column(ct, COL_NAME, 0);
    rtbl_add_column(ct, COL_DESC, 0);
    rtbl_add_column(ct, COL_SASL, 0);

    for (i = 0; i < mechs->count; i++) {
	gss_buffer_desc str, sasl_name, mech_name, mech_desc;

	maj_stat = gss_oid_to_str(&min_stat, &mechs->elements[i], &str);
	if (maj_stat != GSS_S_COMPLETE)
	    errx(1, "gss_oid_to_str failed");

	rtbl_add_column_entryv(ct, COL_OID, "%.*s",
			       (int)str.length, (char *)str.value);
	gss_release_buffer(&min_stat, &str);

	(void)gss_inquire_saslname_for_mech(&min_stat,
					    &mechs->elements[i],
					    &sasl_name,
					    &mech_name,
					    &mech_desc);

	rtbl_add_column_entryv(ct, COL_NAME, "%.*s",
			       (int)mech_name.length, (char *)mech_name.value);
	rtbl_add_column_entryv(ct, COL_DESC, "%.*s",
			       (int)mech_desc.length, (char *)mech_desc.value);
	rtbl_add_column_entryv(ct, COL_SASL, "%.*s",
			       (int)sasl_name.length, (char *)sasl_name.value);

	gss_release_buffer(&min_stat, &mech_name);
	gss_release_buffer(&min_stat, &mech_desc);
	gss_release_buffer(&min_stat, &sasl_name);

    }
    gss_release_oid_set(&min_stat, &mechs);

    rtbl_format(ct, stdout);
    rtbl_destroy(ct);

    return 0;
}
Esempio n. 5
0
static OM_uint32
spnego_supported_mechs(OM_uint32 *minor_status, gss_OID_set *mechs)
{
    OM_uint32 ret, junk;
    gss_OID_set m;
    size_t i;

    ret = gss_indicate_mechs(minor_status, &m);
    if (ret != GSS_S_COMPLETE)
	return ret;

    ret = gss_create_empty_oid_set(minor_status, mechs);
    if (ret != GSS_S_COMPLETE) {
	gss_release_oid_set(&junk, &m);
	return ret;
    }

    for (i = 0; i < m->count; i++) {
	if (gss_oid_equal(&m->elements[i], GSS_SPNEGO_MECHANISM))
	    continue;

	ret = gss_add_oid_set_member(minor_status, &m->elements[i], mechs);
	if (ret) {
	    gss_release_oid_set(&junk, &m);
	    gss_release_oid_set(&junk, mechs);
	    return ret;
	}
    }
    gss_release_oid_set(&junk, &m);
    return ret;
}
/**
 * Initialize a previously allocated error of type
 * GLOBUS_ERROR_TYPE_GSSAPI
 * @ingroup globus_gssapi_error_object 
 *
 * @param error
 *        The previously allocated error object.
 * @param base_source
 *        Pointer to the originating module.
 * @param base_cause
 *        The error object causing the error. If this is the original
 *        error this paramater may be NULL.
 * @param major_status
 *        The GSSAPI major status
 * @param minor_status
 *        The GSSAPI minor status
 * @return
 *        The resulting error object. You may have to call
 *        globus_error_put() on this object before passing it on.
 */
globus_object_t *
globus_error_initialize_gssapi_error(
    globus_object_t *                   error,
    globus_module_descriptor_t *        base_source,
    globus_object_t *                   base_cause,
    const OM_uint32                     major_status,
    const OM_uint32                     minor_status)
{
    globus_l_gssapi_error_data_t *      instance_data;
    globus_object_t *                   minor_obj;
    gss_OID_set                         actual_mechs;
    OM_uint32                           local_minor_status;
    extern gss_OID                      gss_mech_globus_gssapi_openssl;
    
    instance_data = (globus_l_gssapi_error_data_t *)
        malloc(sizeof(globus_l_gssapi_error_data_t));

    instance_data->major_status = major_status;
    instance_data->minor_status = minor_status;
    instance_data->is_globus_gsi = GLOBUS_FALSE;
    
    if(gss_indicate_mechs(
        &local_minor_status, &actual_mechs) == GSS_S_COMPLETE)
    {
        int                             boolean;
        
        if(gss_test_oid_set_member(
            &local_minor_status,
            gss_mech_globus_gssapi_openssl,
            actual_mechs,
            &boolean) == GSS_S_COMPLETE && boolean)
        {
            instance_data->is_globus_gsi = GLOBUS_TRUE;
        }
        
        gss_release_oid_set(&local_minor_status, &actual_mechs);
    }
    
    if(instance_data->is_globus_gsi)
    {
        minor_obj = globus_error_get((globus_result_t) minor_status);
        if(!base_cause)
        {
            base_cause = minor_obj;
        }
        else if(minor_obj)
        {
            base_cause = globus_error_initialize_base(
                minor_obj, globus_error_get_source(base_cause), base_cause);
        }
    }
        
    globus_object_set_local_instance_data(error, instance_data);
    
    return globus_error_initialize_base(error, base_source, base_cause);
}/* globus_error_initialize_gssapi_error() */
char *
ssh_gssapi_client_mechanisms(const char *host) {
	gss_OID_set gss_supported;
	OM_uint32 min_status;

	gss_indicate_mechs(&min_status, &gss_supported);

	return(ssh_gssapi_kex_mechs(gss_supported, ssh_gssapi_check_mechanism,
	    host));
}
Esempio n. 8
0
char *
ssh_gssapi_client_mechanisms(const char *host, const char *client) {
	gss_OID_set gss_supported;
	OM_uint32 min_status;

	if (GSS_ERROR(gss_indicate_mechs(&min_status, &gss_supported)))
		return NULL;

	return(ssh_gssapi_kex_mechs(gss_supported, ssh_gssapi_check_mechanism,
	    host, client));
}
Esempio n. 9
0
static int negotiate_init_context(
    http_auth_negotiate_context *ctx,
    const gitno_connection_data *connection_data)
{
    OM_uint32 status_major, status_minor;
    gss_OID item, *oid;
    gss_OID_set mechanism_list;
    size_t i;

    /* Query supported mechanisms looking for SPNEGO) */
    if (GSS_ERROR(status_major =
                      gss_indicate_mechs(&status_minor, &mechanism_list))) {
        negotiate_err_set(status_major, status_minor,
                          "could not query mechanisms");
        return -1;
    }

    if (mechanism_list) {
        for (oid = negotiate_oids; *oid; oid++) {
            for (i = 0; i < mechanism_list->count; i++) {
                item = &mechanism_list->elements[i];

                if (item->length == (*oid)->length &&
                        memcmp(item->elements, (*oid)->elements, item->length) == 0) {
                    ctx->oid = *oid;
                    break;
                }

            }

            if (ctx->oid)
                break;
        }
    }

    gss_release_oid_set(&status_minor, &mechanism_list);

    if (!ctx->oid) {
        giterr_set(GITERR_NET, "Negotiate authentication is not supported");
        return -1;
    }

    git_buf_puts(&ctx->target, "HTTP@");
    git_buf_puts(&ctx->target, connection_data->host);

    if (git_buf_oom(&ctx->target))
        return -1;

    ctx->gss_context = GSS_C_NO_CONTEXT;
    ctx->configured = 1;

    return 0;
}
Esempio n. 10
0
int
supported_mechanisms(void *argptr, int argc, char **argv)
{
    OM_uint32 maj_stat, min_stat;
    gss_OID_set mechs;
    rtbl_t ct;
    size_t i;

    maj_stat = gss_indicate_mechs(&min_stat, &mechs);
    if (maj_stat != GSS_S_COMPLETE)
	errx(1, "gss_indicate_mechs failed");

    printf("Supported mechanisms:\n");

    ct = rtbl_create();
    if (ct == NULL)
	errx(1, "rtbl_create");

    rtbl_set_separator(ct, "  ");
    rtbl_add_column(ct, COL_OID, 0);
    rtbl_add_column(ct, COL_NAME, 0);

    for (i = 0; i < mechs->count; i++) {
	gss_buffer_desc name;

	maj_stat = gss_oid_to_str(&min_stat, &mechs->elements[i], &name);
	if (maj_stat != GSS_S_COMPLETE)
	    errx(1, "gss_oid_to_str failed");

	rtbl_add_column_entryv(ct, COL_OID, "%.*s",
			       (int)name.length, (char *)name.value);
	gss_release_buffer(&min_stat, &name);

	if (gss_oid_equal(&mechs->elements[i], GSS_KRB5_MECHANISM))
	    rtbl_add_column_entry(ct, COL_NAME, "Kerberos 5");
	else if (gss_oid_equal(&mechs->elements[i], GSS_SPNEGO_MECHANISM))
	    rtbl_add_column_entry(ct, COL_NAME, "SPNEGO");
	else if (gss_oid_equal(&mechs->elements[i], GSS_NTLM_MECHANISM))
	    rtbl_add_column_entry(ct, COL_NAME, "NTLM");
    }
    gss_release_oid_set(&min_stat, &mechs);

    rtbl_format(ct, stdout);
    rtbl_destroy(ct);

    return 0;
}
Esempio n. 11
0
uint32_t
sapgss_indicate_mechs(
    uint32_t *minor_status,
    sapgss_OID_set *mech_set)
{
    gss_OID_set mech_set_loc;
    uint32_t major_status;
    int ret;

    memset(&mech_set_loc, 0, sizeof(mech_set_loc));
    major_status = gss_indicate_mechs(minor_status, &mech_set_loc);
    ret = gss_OID_set_loc_to_sap(mech_set_loc, mech_set);
    if (ret != 0) {
	*minor_status = ret;
	return GSS_S_FAILURE;
    }
    return major_status;
}
Esempio n. 12
0
int gssd_check_mechs(void)
{
	u_int32_t maj_stat, min_stat;
	gss_OID_set supported_mechs = GSS_C_NO_OID_SET;
	int retval = -1;

	maj_stat = gss_indicate_mechs(&min_stat, &supported_mechs);
	if (maj_stat != GSS_S_COMPLETE) {
		printerr(0, "Unable to obtain list of supported mechanisms. "
			 "Check that gss library is properly configured.\n");
		goto out;
	}
	if (supported_mechs == GSS_C_NO_OID_SET ||
	    supported_mechs->count == 0) {
		printerr(0, "Unable to obtain list of supported mechanisms. "
			 "Check that gss library is properly configured.\n");
		goto out;
	}
	maj_stat = gss_release_oid_set(&min_stat, &supported_mechs);
	retval = 0;
out:
	return retval;
}
Esempio n. 13
0
File: cssp.c Progetto: jeppeter/vbox
static RD_BOOL
cssp_gss_mech_available(gss_OID mech)
{
	int mech_found;
	OM_uint32 major_status, minor_status;
	gss_OID_set mech_set;

	mech_found = 0;

	if (mech == GSS_C_NO_OID)
		return True;

	major_status = gss_indicate_mechs(&minor_status, &mech_set);
	if (!mech_set)
		return False;

	if (GSS_ERROR(major_status))
	{
		cssp_gss_report_error(GSS_C_GSS_CODE, "Failed to get available mechs on system",
				      major_status, minor_status);
		return False;
	}

	gss_test_oid_set_member(&minor_status, mech, mech_set, &mech_found);

	if (GSS_ERROR(major_status))
	{
		cssp_gss_report_error(GSS_C_GSS_CODE, "Failed to match mechanism in set",
				      major_status, minor_status);
		return False;
	}

	if (!mech_found)
		return False;

	return True;
}
Esempio n. 14
0
void
ssh_gssapi_client_mechs(const char *server_host, gss_OID_set *mechs)
{
	gss_OID_set	indicated = GSS_C_NULL_OID_SET;
	gss_OID_set	acquired, supported;
	gss_OID		mech;
	gss_cred_id_t	creds;
	Gssctxt		*ctxt = NULL;
	gss_buffer_desc	tok;
	OM_uint32	maj, min;
	int		i;
	char		*errmsg;

	if (!mechs)
		return;
	*mechs = GSS_C_NULL_OID_SET;

	maj = gss_indicate_mechs(&min, &indicated);
	if (GSS_ERROR(maj)) {
		debug("No GSS-API mechanisms are installed");
		return;
	}

	maj = gss_create_empty_oid_set(&min, &supported);
	if (GSS_ERROR(maj)) {
		errmsg = ssh_gssapi_last_error(NULL, &maj, &min);
		debug("Failed to allocate resources (%s) for GSS-API", errmsg);
		xfree(errmsg);
		(void) gss_release_oid_set(&min, &indicated);
		return;
	}
	maj = gss_acquire_cred(&min, GSS_C_NO_NAME, 0, indicated,
	    GSS_C_INITIATE, &creds, &acquired, NULL);

	if (GSS_ERROR(maj)) {
		errmsg = ssh_gssapi_last_error(NULL, &maj, &min);
		debug("Failed to acquire GSS-API credentials for any "
		    "mechanisms (%s)", errmsg);
		xfree(errmsg);
		(void) gss_release_oid_set(&min, &indicated);
		(void) gss_release_oid_set(&min, &supported);
		return;
	}
	(void) gss_release_cred(&min, &creds);

	for (i = 0; i < acquired->count; i++) {
		mech = &acquired->elements[i];

		if (ssh_gssapi_is_spnego(mech))
			continue;

		ssh_gssapi_build_ctx(&ctxt, 1, mech);
		if (!ctxt)
			continue;

		/*
		 * This is useful for mechs like Kerberos, which can
		 * detect unknown target princs here, but not for
		 * mechs like SPKM, which cannot detect unknown princs
		 * until context tokens are actually exchanged.
		 *
		 * 'Twould be useful to have a test that could save us
		 * the bother of trying this for SPKM and the such...
		 */
		maj = ssh_gssapi_init_ctx(ctxt, server_host, 0, NULL, &tok);
		if (GSS_ERROR(maj)) {
			errmsg = ssh_gssapi_last_error(ctxt, NULL, NULL);
			debug("Skipping GSS-API mechanism %s (%s)",
			    ssh_gssapi_oid_to_name(mech), errmsg);
			xfree(errmsg);
			continue;
		}

		(void) gss_release_buffer(&min, &tok);

		maj = gss_add_oid_set_member(&min, mech, &supported);
		if (GSS_ERROR(maj)) {
			errmsg = ssh_gssapi_last_error(NULL, &maj, &min);
			debug("Failed to allocate resources (%s) for GSS-API",
			    errmsg);
			xfree(errmsg);
		}
	}

	*mechs = supported;
}
Esempio n. 15
0
OM_uint32 GSSAPI_CALLCONV
_gss_spnego_indicate_mechtypelist (OM_uint32 *minor_status,
				   gss_name_t target_name,
				   OM_uint32 (*func)(void *, gss_name_t, const gss_cred_id_t, gss_OID),
				   void *userctx,
				   int includeMSCompatOID,
				   const gss_cred_id_t cred_handle,
				   MechTypeList *mechtypelist,
				   gss_OID *preferred_mech)
{
    gss_OID_set supported_mechs = GSS_C_NO_OID_SET;
    gss_OID first_mech = GSS_C_NO_OID;
    OM_uint32 ret, junk;
    int present = 0;
    size_t i;

    mechtypelist->len = 0;
    mechtypelist->val = NULL;

    if (cred_handle) {
	ret = gss_inquire_cred(minor_status,
			       cred_handle,
			       NULL,
			       NULL,
			       NULL,
			       &supported_mechs);
    } else {
	ret = gss_indicate_mechs(minor_status, &supported_mechs);
    }

    if (ret != GSS_S_COMPLETE) {
	return ret;
    }

    if (supported_mechs->count == 0) {
	*minor_status = ENOENT;
	gss_release_oid_set(minor_status, &supported_mechs);
	return GSS_S_FAILURE;
    }

    /*
     * Propose Kerberos mech first if we have Kerberos credentials/supported mechs
     */

    ret = gss_test_oid_set_member(&junk, GSS_KRB5_MECHANISM, supported_mechs, &present);
    if (ret == GSS_S_COMPLETE && present) {
	ret = (*func)(userctx, target_name, cred_handle, GSS_KRB5_MECHANISM);
	if (ret == GSS_S_COMPLETE) {
	    ret = add_mech_type(GSS_KRB5_MECHANISM,
				includeMSCompatOID,
				mechtypelist);
	    if (!GSS_ERROR(ret)) {
		if (includeMSCompatOID)
		    first_mech = &_gss_spnego_mskrb_mechanism_oid_desc;
		else
		    first_mech = GSS_KRB5_MECHANISM;
	    }
#ifdef __APPLE_PRIVATE__
	    (void)add_mech_type(GSS_APPL_LKDC_SUPPORTED, 0, mechtypelist);
#endif
	}
    }
    ret = GSS_S_COMPLETE;

    /*
     * Now lets, check all other mechs
     */

    for (i = 0; i < supported_mechs->count; i++) {
	OM_uint32 subret;
	if (gss_oid_equal(&supported_mechs->elements[i], GSS_SPNEGO_MECHANISM))
	    continue;
	if (gss_oid_equal(&supported_mechs->elements[i], GSS_KRB5_MECHANISM))
	    continue;
	if (gss_oid_equal(&supported_mechs->elements[i], GSS_NETLOGON_MECHANISM))
	    continue;

	subret = (*func)(userctx, target_name, cred_handle, &supported_mechs->elements[i]);
	if (subret != GSS_S_COMPLETE)
	    continue;

	ret = add_mech_type(&supported_mechs->elements[i],
			    includeMSCompatOID,
			    mechtypelist);
	if (ret != 0) {
	    *minor_status = ret;
	    ret = GSS_S_FAILURE;
	    break;
	}
	if (first_mech == GSS_C_NO_OID)
	    first_mech = &supported_mechs->elements[i];
    }

    if (mechtypelist->len == 0) {
	gss_release_oid_set(minor_status, &supported_mechs);
	*minor_status = 0;
	return GSS_S_BAD_MECH;
    }

    if (preferred_mech != NULL) {
	ret = gss_duplicate_oid(minor_status, first_mech, preferred_mech);
	if (ret != GSS_S_COMPLETE)
	    free_MechTypeList(mechtypelist);
    }
    gss_release_oid_set(minor_status, &supported_mechs);

    return ret;
}
Esempio n. 16
0
/*
 * For now, just a simple wrapper that avoids recursion. When
 * we support gss_{get,set}_neg_mechs() we will need to expose
 * more functionality.
 */
OM_uint32 GSSAPI_CALLCONV _gss_spnego_acquire_cred
(OM_uint32 *minor_status,
 const gss_name_t desired_name,
 OM_uint32 time_req,
 const gss_OID_set desired_mechs,
 gss_cred_usage_t cred_usage,
 gss_cred_id_t * output_cred_handle,
 gss_OID_set * actual_mechs,
 OM_uint32 * time_rec
    )
{
    const spnego_name dname = (const spnego_name)desired_name;
    gss_name_t name = GSS_C_NO_NAME;
    OM_uint32 ret, tmp;
    gss_OID_set_desc actual_desired_mechs;
    gss_OID_set mechs;
    size_t i, j;

    *output_cred_handle = GSS_C_NO_CREDENTIAL;

    if (dname) {
	ret = gss_import_name(minor_status, &dname->value, &dname->type, &name);
	if (ret) {
	    return ret;
	}
    }

    ret = gss_indicate_mechs(minor_status, &mechs);
    if (ret != GSS_S_COMPLETE) {
	gss_release_name(minor_status, &name);
	return ret;
    }

    /* Remove ourselves from this list */
    actual_desired_mechs.count = mechs->count;
    actual_desired_mechs.elements = malloc(actual_desired_mechs.count *
					   sizeof(gss_OID_desc));
    if (actual_desired_mechs.elements == NULL) {
	*minor_status = ENOMEM;
	ret = GSS_S_FAILURE;
	goto out;
    }

    for (i = 0, j = 0; i < mechs->count; i++) {
	if (gss_oid_equal(&mechs->elements[i], GSS_SPNEGO_MECHANISM))
	    continue;

	actual_desired_mechs.elements[j] = mechs->elements[i];
	j++;
    }
    actual_desired_mechs.count = j;

    ret = gss_acquire_cred(minor_status, name,
			   time_req, &actual_desired_mechs,
			   cred_usage,
			   output_cred_handle,
			   actual_mechs, time_rec);
    if (ret != GSS_S_COMPLETE)
	goto out;

out:
    gss_release_name(minor_status, &name);
    gss_release_oid_set(&tmp, &mechs);
    if (actual_desired_mechs.elements != NULL) {
	free(actual_desired_mechs.elements);
    }
    if (ret != GSS_S_COMPLETE) {
	_gss_spnego_release_cred(&tmp, output_cred_handle);
    }

    return ret;
}
Esempio n. 17
0
int main(int argc, char *argv[])
{
    gss_OID_set mechs;
    OM_uint32 major, minor;
    size_t i;

    major = gss_indicate_mechs(&minor, &mechs);
    if (GSS_ERROR(major)) {
        displayStatus("gss_indicate_mechs", major, minor);
        return major;
    }

    for (i = 0; i < mechs->count; i++) {
        gss_buffer_desc oidstr = GSS_C_EMPTY_BUFFER;
        gss_buffer_desc sasl_mech_name = GSS_C_EMPTY_BUFFER;
        gss_buffer_desc mech_name = GSS_C_EMPTY_BUFFER;
        gss_buffer_desc mech_description = GSS_C_EMPTY_BUFFER;
        gss_OID oid = GSS_C_NO_OID;

        major = gss_oid_to_str(&minor, &mechs->elements[i], &oidstr);
        if (GSS_ERROR(major))
            continue;

        major = gss_inquire_saslname_for_mech(&minor, &mechs->elements[i],
                                              &sasl_mech_name, &mech_name,
                                              &mech_description);
        if (GSS_ERROR(major)) {
            gss_release_buffer(&minor, &oidstr);
            continue;
        }

        printf("-------------------------------------------------------------"
               "-----------------\n");
        printf("OID        : %.*s\n", (int)oidstr.length,
               (char *)oidstr.value);
        printf("SASL mech  : %.*s\n", (int)sasl_mech_name.length,
               (char *)sasl_mech_name.value);
        printf("Mech name  : %.*s\n", (int)mech_name.length,
               (char *)mech_name.value);
        printf("Mech desc  : %.*s\n", (int)mech_description.length,
               (char *)mech_description.value);
        dumpMechAttrs(&minor, &mechs->elements[i]);
        printf("-------------------------------------------------------------"
               "-----------------\n");

        if (GSS_ERROR(gss_inquire_mech_for_saslname(&minor, &sasl_mech_name,
                                                    &oid))) {
            displayStatus("gss_inquire_mech_for_saslname", major, minor);
        } else if (oid == GSS_C_NO_OID ||
            (oid->length != mechs->elements[i].length &&
             memcmp(oid->elements, mechs->elements[i].elements,
                    oid->length) != 0)) {
            gss_release_buffer(&minor, &oidstr);
            (void) gss_oid_to_str(&minor, oid, &oidstr);
            fprintf(stderr, "Got different OID %.*s for mechanism %.*s\n",
                    (int)oidstr.length, (char *)oidstr.value,
                    (int)sasl_mech_name.length, (char *)sasl_mech_name.value);
        }
        gss_release_buffer(&minor, &oidstr);
        gss_release_buffer(&minor, &sasl_mech_name);
        gss_release_buffer(&minor, &mech_name);
        gss_release_buffer(&minor, &mech_description);
    }

    gss_release_oid_set(&minor, &mechs);

    return GSS_ERROR(major) ? 1 : 0;
}
Esempio n. 18
0
/** @internal
 * @brief handles an user authentication using GSSAPI
 */
int ssh_gssapi_handle_userauth(ssh_session session, const char *user, uint32_t n_oid, ssh_string *oids){
    char service_name[]="host";
    gss_buffer_desc name_buf;
    gss_name_t server_name; /* local server fqdn */
    OM_uint32 maj_stat, min_stat;
    unsigned int i;
    char *ptr;
    gss_OID_set supported; /* oids supported by server */
    gss_OID_set both_supported; /* oids supported by both client and server */
    gss_OID_set selected; /* oid selected for authentication */
    int present=0;
    int oid_count=0;
    struct gss_OID_desc_struct oid;
    int rc;

    if (ssh_callbacks_exists(session->server_callbacks, gssapi_select_oid_function)){
        ssh_string oid_s = session->server_callbacks->gssapi_select_oid_function(session,
                user, n_oid, oids,
                session->server_callbacks->userdata);
        if (oid_s != NULL){
            if (ssh_gssapi_init(session) == SSH_ERROR)
                return SSH_ERROR;
            session->gssapi->state = SSH_GSSAPI_STATE_RCV_TOKEN;
            rc = ssh_gssapi_send_response(session, oid_s);
            ssh_string_free(oid_s);
            return rc;
        } else {
            return ssh_auth_reply_default(session,0);
        }
    }
    gss_create_empty_oid_set(&min_stat, &both_supported);

    maj_stat = gss_indicate_mechs(&min_stat, &supported);
    for (i=0; i < supported->count; ++i){
        ptr = ssh_get_hexa(supported->elements[i].elements, supported->elements[i].length);
        SSH_LOG(SSH_LOG_DEBUG, "Supported mech %d: %s\n", i, ptr);
        free(ptr);
    }

    for (i=0 ; i< n_oid ; ++i){
        unsigned char *oid_s = (unsigned char *) ssh_string_data(oids[i]);
        size_t len = ssh_string_len(oids[i]);
        if(len < 2 || oid_s[0] != SSH_OID_TAG || ((size_t)oid_s[1]) != len - 2){
            SSH_LOG(SSH_LOG_WARNING,"GSSAPI: received invalid OID");
            continue;
        }
        oid.elements = &oid_s[2];
        oid.length = len - 2;
        gss_test_oid_set_member(&min_stat,&oid,supported,&present);
        if(present){
            gss_add_oid_set_member(&min_stat,&oid,&both_supported);
            oid_count++;
        }
    }
    gss_release_oid_set(&min_stat, &supported);
    if (oid_count == 0){
        SSH_LOG(SSH_LOG_PROTOCOL,"GSSAPI: no OID match");
        ssh_auth_reply_default(session, 0);
        gss_release_oid_set(&min_stat, &both_supported);
        return SSH_OK;
    }
    /* from now we have room for context */
    if (ssh_gssapi_init(session) == SSH_ERROR)
        return SSH_ERROR;

    name_buf.value = service_name;
    name_buf.length = strlen(name_buf.value) + 1;
    maj_stat = gss_import_name(&min_stat, &name_buf,
            (gss_OID) GSS_C_NT_HOSTBASED_SERVICE, &server_name);
    if (maj_stat != GSS_S_COMPLETE) {
        SSH_LOG(SSH_LOG_WARNING, "importing name %d, %d", maj_stat, min_stat);
        ssh_gssapi_log_error(SSH_LOG_WARNING, "importing name", maj_stat);
        return -1;
    }

    maj_stat = gss_acquire_cred(&min_stat, server_name, 0,
            both_supported, GSS_C_ACCEPT,
            &session->gssapi->server_creds, &selected, NULL);
    gss_release_name(&min_stat, &server_name);
    gss_release_oid_set(&min_stat, &both_supported);

    if (maj_stat != GSS_S_COMPLETE) {
        SSH_LOG(SSH_LOG_WARNING, "error acquiring credentials %d, %d", maj_stat, min_stat);
        ssh_gssapi_log_error(SSH_LOG_WARNING, "acquiring creds", maj_stat);
        ssh_auth_reply_default(session,0);
        return SSH_ERROR;
    }

    SSH_LOG(SSH_LOG_PROTOCOL, "acquiring credentials %d, %d", maj_stat, min_stat);

    /* finding which OID from client we selected */
    for (i=0 ; i< n_oid ; ++i){
        unsigned char *oid_s = (unsigned char *) ssh_string_data(oids[i]);
        size_t len = ssh_string_len(oids[i]);
        if(len < 2 || oid_s[0] != SSH_OID_TAG || ((size_t)oid_s[1]) != len - 2){
            SSH_LOG(SSH_LOG_WARNING,"GSSAPI: received invalid OID");
            continue;
        }
        oid.elements = &oid_s[2];
        oid.length = len - 2;
        gss_test_oid_set_member(&min_stat,&oid,selected,&present);
        if(present){
            SSH_LOG(SSH_LOG_PACKET, "Selected oid %d", i);
            break;
        }
    }
    session->gssapi->mech.length = oid.length;
    session->gssapi->mech.elements = malloc(oid.length);
    if (session->gssapi->mech.elements == NULL){
        ssh_set_error_oom(session);
        return SSH_ERROR;
    }
    memcpy(session->gssapi->mech.elements, oid.elements, oid.length);
    gss_release_oid_set(&min_stat, &selected);
    session->gssapi->user = strdup(user);
    session->gssapi->service = service_name;
    session->gssapi->state = SSH_GSSAPI_STATE_RCV_TOKEN;
    return ssh_gssapi_send_response(session, oids[i]);
}
Esempio n. 19
0
OM_uint32 GSSAPI_CALLCONV
_gss_spnego_indicate_mechtypelist (OM_uint32 *minor_status,
				   gss_name_t target_name,
				   OM_uint32 (*func)(gss_name_t, gss_OID),
				   int includeMSCompatOID,
				   const gss_cred_id_t cred_handle,
				   MechTypeList *mechtypelist,
				   gss_OID *preferred_mech)
{
    gss_OID_set supported_mechs = GSS_C_NO_OID_SET;
    gss_OID first_mech = GSS_C_NO_OID;
    OM_uint32 ret;
    size_t i;

    mechtypelist->len = 0;
    mechtypelist->val = NULL;

    if (cred_handle) {
	ret = gss_inquire_cred(minor_status,
			       cred_handle,
			       NULL,
			       NULL,
			       NULL,
			       &supported_mechs);
    } else {
	ret = gss_indicate_mechs(minor_status, &supported_mechs);
    }

    if (ret != GSS_S_COMPLETE) {
	return ret;
    }

    if (supported_mechs->count == 0) {
	*minor_status = ENOENT;
	gss_release_oid_set(minor_status, &supported_mechs);
	return GSS_S_FAILURE;
    }

    ret = (*func)(target_name, GSS_KRB5_MECHANISM);
    if (ret == GSS_S_COMPLETE) {
	ret = add_mech_type(GSS_KRB5_MECHANISM,
			    includeMSCompatOID,
			    mechtypelist);
	if (!GSS_ERROR(ret))
	    first_mech = GSS_KRB5_MECHANISM;
    }
    ret = GSS_S_COMPLETE;

    for (i = 0; i < supported_mechs->count; i++) {
	OM_uint32 subret;
	if (gss_oid_equal(&supported_mechs->elements[i], GSS_SPNEGO_MECHANISM))
	    continue;
	if (gss_oid_equal(&supported_mechs->elements[i], GSS_KRB5_MECHANISM))
	    continue;

	subret = (*func)(target_name, &supported_mechs->elements[i]);
	if (subret != GSS_S_COMPLETE)
	    continue;

	ret = add_mech_type(&supported_mechs->elements[i],
			    includeMSCompatOID,
			    mechtypelist);
	if (ret != 0) {
	    *minor_status = ret;
	    ret = GSS_S_FAILURE;
	    break;
	}
	if (first_mech == GSS_C_NO_OID)
	    first_mech = &supported_mechs->elements[i];
    }

    if (mechtypelist->len == 0) {
	gss_release_oid_set(minor_status, &supported_mechs);
	*minor_status = 0;
	return GSS_S_BAD_MECH;
    }

    if (preferred_mech != NULL) {
	ret = gss_duplicate_oid(minor_status, first_mech, preferred_mech);
	if (ret != GSS_S_COMPLETE)
	    free_MechTypeList(mechtypelist);
    }
    gss_release_oid_set(minor_status, &supported_mechs);

    return ret;
}
Esempio n. 20
0
uint32_t NetSecurityNative_Wrap(uint32_t* minorStatus,
                                GssCtxId* contextHandle,
                                int32_t isEncrypt,
                                uint8_t* inputBytes,
                                int32_t offset,
                                int32_t count,
                                PAL_GssBuffer* outBuffer)
{
    assert(minorStatus != NULL);
    assert(contextHandle != NULL);
    assert(isEncrypt == 1 || isEncrypt == 0);
    assert(inputBytes != NULL);
    assert(offset >= 0);
    assert(count >= 0);
    assert(outBuffer != NULL);
    // count refers to the length of the input message. That is, number of bytes of inputBytes
    // starting at offset that need to be wrapped.

    int confState;
    GssBuffer inputMessageBuffer = {.length = (size_t)count, .value = inputBytes + offset};
    GssBuffer gssBuffer;
    uint32_t majorStatus =
        gss_wrap(minorStatus, contextHandle, isEncrypt, GSS_C_QOP_DEFAULT, &inputMessageBuffer, &confState, &gssBuffer);

    NetSecurityNative_MoveBuffer(&gssBuffer, outBuffer);
    return majorStatus;
}

uint32_t NetSecurityNative_Unwrap(uint32_t* minorStatus,
                                  GssCtxId* contextHandle,
                                  uint8_t* inputBytes,
                                  int32_t offset,
                                  int32_t count,
                                  PAL_GssBuffer* outBuffer)
{
    assert(minorStatus != NULL);
    assert(contextHandle != NULL);
    assert(inputBytes != NULL);
    assert(offset >= 0);
    assert(count >= 0);
    assert(outBuffer != NULL);

    // count refers to the length of the input message. That is, the number of bytes of inputBytes
    // starting at offset that need to be wrapped.
    GssBuffer inputMessageBuffer = {.length = (size_t)count, .value = inputBytes + offset};
    GssBuffer gssBuffer = {.length = 0, .value = NULL};
    uint32_t majorStatus = gss_unwrap(minorStatus, contextHandle, &inputMessageBuffer, &gssBuffer, NULL, NULL);
    NetSecurityNative_MoveBuffer(&gssBuffer, outBuffer);
    return majorStatus;
}

static uint32_t NetSecurityNative_AcquireCredWithPassword(uint32_t* minorStatus,
                                                          int32_t isNtlm,
                                                          GssName* desiredName,
                                                          char* password,
                                                          uint32_t passwdLen,
                                                          gss_cred_usage_t credUsage,
                                                          GssCredId** outputCredHandle)
{
    assert(minorStatus != NULL);
    assert(isNtlm == 1 || isNtlm == 0);
    assert(desiredName != NULL);
    assert(password != NULL);
    assert(outputCredHandle != NULL);
    assert(*outputCredHandle == NULL);

#if HAVE_GSS_SPNEGO_MECHANISM
    (void)isNtlm; // unused
    // Specifying GSS_SPNEGO_MECHANISM as a desiredMech on OSX fails.
    gss_OID_set desiredMech = GSS_C_NO_OID_SET;
#else
    gss_OID_desc gss_mech_OID_desc;
    if (isNtlm)
    {
        gss_mech_OID_desc = gss_mech_ntlm_OID_desc;
    }
    else
    {
        gss_mech_OID_desc = gss_mech_spnego_OID_desc;
    }

    gss_OID_set_desc gss_mech_OID_set_desc = {.count = 1, .elements = &gss_mech_OID_desc};
    gss_OID_set desiredMech = &gss_mech_OID_set_desc;
#endif

    GssBuffer passwordBuffer = {.length = passwdLen, .value = password};
    uint32_t majorStatus = gss_acquire_cred_with_password(
        minorStatus, desiredName, &passwordBuffer, 0, desiredMech, credUsage, outputCredHandle, NULL, NULL);

    // call gss_set_cred_option with GSS_KRB5_CRED_NO_CI_FLAGS_X to support Kerberos Sign Only option from *nix client against a windows server
#if HAVE_GSS_KRB5_CRED_NO_CI_FLAGS_X
    if (majorStatus == GSS_S_COMPLETE)
    {
        GssBuffer emptyBuffer = GSS_C_EMPTY_BUFFER;
        majorStatus = gss_set_cred_option(minorStatus, outputCredHandle, GSS_KRB5_CRED_NO_CI_FLAGS_X, &emptyBuffer);
    }
#endif

    return majorStatus;
}

uint32_t NetSecurityNative_InitiateCredWithPassword(uint32_t* minorStatus,
                                                    int32_t isNtlm,
                                                    GssName* desiredName,
                                                    char* password,
                                                    uint32_t passwdLen,
                                                    GssCredId** outputCredHandle)
{
    return NetSecurityNative_AcquireCredWithPassword(
        minorStatus, isNtlm, desiredName, password, passwdLen, GSS_C_INITIATE, outputCredHandle);
}

uint32_t NetSecurityNative_IsNtlmInstalled()
{
#if HAVE_GSS_SPNEGO_MECHANISM
    gss_OID ntlmOid = GSS_NTLM_MECHANISM;
#else
    gss_OID ntlmOid = &gss_mech_ntlm_OID_desc;
#endif

    uint32_t majorStatus;
    uint32_t minorStatus;
    gss_OID_set mechSet;
    gss_OID_desc oid;
    uint32_t foundNtlm = 0;

    majorStatus = gss_indicate_mechs(&minorStatus, &mechSet);
    if (majorStatus == GSS_S_COMPLETE)
    {
        for (size_t i = 0; i < mechSet->count; i++)
        {
            oid = mechSet->elements[i];
            if ((oid.length == ntlmOid->length) && (memcmp(oid.elements, ntlmOid->elements, oid.length) == 0))
            {
                foundNtlm = 1;
                break;
            }
        }

        gss_release_oid_set(&minorStatus, &mechSet);
    }

    return foundNtlm;
}
Esempio n. 21
0
char * 
ssh_gssapi_client_mechanisms(const char *host) {
	gss_OID_set 	supported;
	OM_uint32	min_status;
	Buffer		buf;
	int 		i = 0;
	char 		*mechs;
	char		*encoded;
	int		enclen;
	char		digest[EVP_MAX_MD_SIZE];
	char		deroid[2];
	const EVP_MD	*evp_md = EVP_md5();
	EVP_MD_CTX	md;
	int 		oidpos=0;
	
	
	gss_indicate_mechs(&min_status,&supported);
		if (datafellows & SSH_BUG_GSSAPI_BER) {
		gss_enc2oid=xmalloc(sizeof(ssh_gss_kex_mapping)
					*((supported->count*2)+1));
	} else {
		gss_enc2oid=xmalloc(sizeof(ssh_gss_kex_mapping)
					*(supported->count+1));
		}
	
	buffer_init(&buf);


	for (i=0;i<supported->count;i++) {

		gss_enc2oid[oidpos].encoded=NULL;
		
		if (supported->elements[i].length<128 &&
		    ssh_gssapi_check_mechanism(&(supported->elements[i]),host)) {

			/* Earlier versions of this code interpreted the
			 * spec incorrectly with regard to OID encoding. They
			 * also mis-encoded the krb5 OID. The following
			 * _temporary_ code interfaces with these broken
			 * servers */

			if (datafellows & SSH_BUG_GSSAPI_BER) {
				char *bodge=NULL;
				gss_OID_desc krb5oid={9, "\x2A\x86\x48\x86\xF7\x12\x01\x02\x02"};
				gss_OID_desc gsioid={9, "\x2B\x06\x01\x04\x01\x9B\x50\x01\x01"};
				
				if (supported->elements[i].length==krb5oid.length &&
				    memcmp(supported->elements[i].elements,
				    	   krb5oid.elements, krb5oid.length)==0) {
					bodge="Se3H81ismmOC3OE+FwYCiQ==";
				}
				
				if (supported->elements[i].length==gsioid.length &&
				    memcmp(supported->elements[i].elements,
				    	   gsioid.elements, gsioid.length)==0) {
					bodge="N3+k7/4wGxHyuP8Yxi4RhA==";
				}

				if (bodge) {				
					if (oidpos!=0) {
						buffer_put_char(&buf,',');
					}
				
					buffer_append(&buf, KEX_GSS_SHA1, sizeof(KEX_GSS_SHA1)-1);
					buffer_append(&buf, bodge, strlen(bodge));

					gss_enc2oid[oidpos].oid=&(supported->elements[i]);
					gss_enc2oid[oidpos].encoded=bodge;
			
					oidpos++;
				}
			}
			
			/* Add the required DER encoding octets and MD5 hash */
			deroid[0]=0x06; /* Object Identifier */
			deroid[1]=supported->elements[i].length;

			EVP_DigestInit(&md, evp_md);
			EVP_DigestUpdate(&md,deroid,2);
			EVP_DigestUpdate(&md,
					 supported->elements[i].elements,
					 supported->elements[i].length);
			EVP_DigestFinal(&md, digest, NULL);
			
			/* Base64 encode it */
			encoded=xmalloc(EVP_MD_size(evp_md)*2);
			enclen=__b64_ntop(digest, EVP_MD_size(evp_md),
				          encoded,EVP_MD_size(evp_md)*2);
			if (oidpos!=0) {
				buffer_put_char(&buf,',');
			}	
			buffer_append(&buf, KEX_GSS_SHA1, sizeof(KEX_GSS_SHA1)-1);
			buffer_append(&buf, encoded, enclen);

			debug("Mechanism encoded as %s",encoded);

			gss_enc2oid[oidpos].oid=&(supported->elements[i]);
			gss_enc2oid[oidpos].encoded=encoded;			
			oidpos++;
		}
	}
	gss_enc2oid[oidpos].oid=NULL;
	gss_enc2oid[oidpos].encoded=NULL;
	
	buffer_put_char(&buf,'\0');
	
	mechs=xmalloc(buffer_len(&buf));
	buffer_get(&buf,mechs,buffer_len(&buf));
	buffer_free(&buf);
	if (strlen(mechs)==0)
		return(NULL);
	else
		return(mechs);
}
Esempio n. 22
0
static OM_uint32
select_mech(OM_uint32 *minor_status, MechType *mechType, int verify_p,
	    gss_OID *mech_p)
{
    char mechbuf[64];
    size_t mech_len;
    gss_OID_desc oid;
    gss_OID oidp;
    gss_OID_set mechs;
    int i;
    OM_uint32 ret, junk;

    ret = der_put_oid ((unsigned char *)mechbuf + sizeof(mechbuf) - 1,
		       sizeof(mechbuf),
		       mechType,
		       &mech_len);
    if (ret) {
	return GSS_S_DEFECTIVE_TOKEN;
    }

    oid.length   = mech_len;
    oid.elements = mechbuf + sizeof(mechbuf) - mech_len;

    if (gss_oid_equal(&oid, GSS_SPNEGO_MECHANISM)) {
	return GSS_S_BAD_MECH;
    }

    *minor_status = 0;

    /* Translate broken MS Kebreros OID */
    if (gss_oid_equal(&oid, &_gss_spnego_mskrb_mechanism_oid_desc))
	    oidp = &_gss_spnego_krb5_mechanism_oid_desc;
    else
	    oidp = &oid;


    ret = gss_indicate_mechs(&junk, &mechs);
    if (ret)
	    return (ret);

    for (i = 0; i < mechs->count; i++)
	    if (gss_oid_equal(&mechs->elements[i], oidp))
		    break;

    if (i == mechs->count) {
	    gss_release_oid_set(&junk, &mechs);
	    return GSS_S_BAD_MECH;
    }
    gss_release_oid_set(&junk, &mechs);

    ret = gss_duplicate_oid(minor_status,
			    &oid, /* possibly this should be oidp */
			    mech_p);

    if (verify_p) {
	gss_name_t name = GSS_C_NO_NAME;
	gss_buffer_desc namebuf;
	char *str = NULL, *host, hostname[MAXHOSTNAMELEN];

	host = getenv("GSSAPI_SPNEGO_NAME");
	if (host == NULL || issuid()) {
	    if (gethostname(hostname, sizeof(hostname)) != 0) {
		*minor_status = errno;
		return GSS_S_FAILURE;
	    }
	    i = asprintf(&str, "host@%s", hostname);
	    if (i < 0 || str == NULL) {
		*minor_status = ENOMEM;
		return GSS_S_FAILURE;
	    }
	    host = str;
	}

	namebuf.length = strlen(host);
	namebuf.value = host;

	ret = gss_import_name(minor_status, &namebuf,
			      GSS_C_NT_HOSTBASED_SERVICE, &name);
	if (str)
	    free(str);
	if (ret != GSS_S_COMPLETE)
	    return ret;

	ret = acceptor_approved(name, *mech_p);
	gss_release_name(&junk, &name);
    }

    return ret;
}
Esempio n. 23
0
/** @brief returns the OIDs of the mechs that work with both
 * hostname and username
 */
static int ssh_gssapi_match(ssh_session session, char *hostname, char *username, gss_OID_set *valid_oids, int deleg){
    gss_buffer_desc host_namebuf, user_namebuf;
    gss_name_t host_name, user_name;
    OM_uint32 maj_stat, min_stat;
    gss_OID_set supported;
    gss_OID oid;
    gss_ctx_id_t ctx = GSS_C_NO_CONTEXT;
    gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER;
    gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER;
    gss_cred_id_t client_creds = GSS_C_NO_CREDENTIAL;
    unsigned int i;
    char *ptr;
    char hostname_buf[256];


    gss_create_empty_oid_set(&min_stat, valid_oids);
    maj_stat = gss_indicate_mechs(&min_stat, &supported);
    for (i=0; i < supported->count; ++i){
        ptr=ssh_get_hexa(supported->elements[i].elements, supported->elements[i].length);
        SSH_LOG(SSH_LOG_DEBUG, "GSSAPI oid supported %d : %s\n",i, ptr);
        SAFE_FREE(ptr);
    }

    user_namebuf.value = username;
    user_namebuf.length = strlen(username) + 1;
    maj_stat = gss_import_name(&min_stat, &user_namebuf,
            (gss_OID) GSS_C_NT_USER_NAME, &user_name);
    if (maj_stat != GSS_S_COMPLETE) {
        SSH_LOG(SSH_LOG_DEBUG, "importing name %d, %d", maj_stat, min_stat);
        ssh_gssapi_log_error(SSH_LOG_DEBUG, "importing name", maj_stat);
        return -1;
    }

    snprintf(hostname_buf, sizeof(hostname_buf),"host@%s", hostname);
    host_namebuf.value = hostname_buf;
    host_namebuf.length = strlen(hostname_buf) + 1;
    maj_stat = gss_import_name(&min_stat, &host_namebuf,
            (gss_OID) GSS_C_NT_HOSTBASED_SERVICE, &host_name);
    if (maj_stat != GSS_S_COMPLETE) {
        SSH_LOG(0, "importing name %d, %d", maj_stat, min_stat);
        ssh_gssapi_log_error(0, "importing name", maj_stat);
        return -1;
    }

    ssh_gssapi_init(session);
    session->gssapi->client_name = user_name;
    session->gssapi->client.server_name = host_name;
    session->gssapi->user = strdup(username);
    for (i=0; i<supported->count; ++i){
        oid = &supported->elements[i];
        maj_stat = gss_init_sec_context(&min_stat,
                session->gssapi->client.client_deleg_creds, &ctx, host_name, oid,
                GSS_C_MUTUAL_FLAG | GSS_C_INTEG_FLAG | (deleg ? GSS_C_DELEG_FLAG : 0),
                0, NULL, &input_token, NULL, &output_token, NULL, NULL);
        if (!GSS_ERROR(maj_stat)){
            gss_OID_set tmp;
            if (session->gssapi->client.client_deleg_creds != GSS_C_NO_CREDENTIAL){
                /* we know the oid is ok since init_sec_context worked */
                gss_add_oid_set_member(&min_stat, oid, valid_oids);
                SSH_LOG(SSH_LOG_PROTOCOL, "Matched oid %u for server (with forwarding)", i);
            } else {
                gss_create_empty_oid_set(&min_stat, &tmp);
                gss_add_oid_set_member(&min_stat, oid, &tmp);
                maj_stat = gss_acquire_cred(&min_stat, user_name, 0,
                        tmp, GSS_C_INITIATE,
                        &client_creds, NULL, NULL);
                gss_release_oid_set(&min_stat, &tmp);
                if (!GSS_ERROR(maj_stat)){
                    gss_release_cred(&min_stat, &client_creds);
                    gss_add_oid_set_member(&min_stat,oid,valid_oids);
                    SSH_LOG(SSH_LOG_PROTOCOL, "Matched oid %u for server", i);
                }
            }
        }
        gss_delete_sec_context(&min_stat,&ctx, &output_token);
        ctx = GSS_C_NO_CONTEXT;
    }

    return SSH_OK;
}