예제 #1
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);
}
예제 #2
0
OM_uint32
ssh_gssapi_test_oid_supported(OM_uint32 *ms, gss_OID member, int *present)
{
	if (supported_oids == NULL)
		ssh_gssapi_prepare_supported_oids();
	return gss_test_oid_set_member(ms, member, supported_oids, present);
}
OM_uint32
gss_add_oid_set_member (OM_uint32 * minor_status,
			const gss_OID member_oid,
			gss_OID_set * oid_set)
{
    gss_OID tmp;
    size_t n;
    OM_uint32 res;
    int present;

    res = gss_test_oid_set_member(minor_status, member_oid, *oid_set, &present);
    if (res != GSS_S_COMPLETE)
	return res;

    if (present) {
	*minor_status = 0;
	return GSS_S_COMPLETE;
    }

    n = (*oid_set)->count + 1;
    tmp = realloc ((*oid_set)->elements, n * sizeof(gss_OID_desc));
    if (tmp == NULL) {
	*minor_status = ENOMEM;
	return GSS_S_FAILURE;
    }
    (*oid_set)->elements = tmp;
    (*oid_set)->count = n;
    (*oid_set)->elements[n-1] = *member_oid;
    *minor_status = 0;
    return GSS_S_COMPLETE;
}
예제 #4
0
/**
 * 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() */
예제 #5
0
/*
 * Return TRUE if cred available for mechanism. Caller need no acquire
 * lock because mechanisms list is immutable.
 */
int
gssEapCredAvailable(gss_cred_id_t cred, gss_OID mech)
{
    OM_uint32 minor;
    int present = 0;

    GSSEAP_ASSERT(mech != GSS_C_NO_OID);

    if (cred == GSS_C_NO_CREDENTIAL || cred->mechanisms == GSS_C_NO_OID_SET)
        return 1;

    gss_test_oid_set_member(&minor, mech, cred->mechanisms, &present);

    return present;
}
예제 #6
0
OM_uint32 GSSAPI_CALLCONV _gsskrb5_acquire_cred
(OM_uint32 * minor_status,
 gss_const_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
    )
{
    OM_uint32 ret;

    if (desired_mechs) {
	int present = 0;

	ret = gss_test_oid_set_member(minor_status, GSS_KRB5_MECHANISM,
				      desired_mechs, &present);
	if (ret)
	    return ret;
	if (!present) {
	    *minor_status = 0;
	    return GSS_S_BAD_MECH;
	}
    }

    ret = _gsskrb5_acquire_cred_ext(minor_status,
				    desired_name,
				    GSS_C_NO_OID,
				    NULL,
				    time_req,
				    GSS_KRB5_MECHANISM,
				    cred_usage,
				    output_cred_handle);
    if (ret)
	return ret;


    ret = _gsskrb5_inquire_cred(minor_status, *output_cred_handle,
				NULL, time_rec, NULL, actual_mechs);
    if (ret) {
	OM_uint32 tmp;
	_gsskrb5_release_cred(&tmp, output_cred_handle);
    }

    return ret;
}
static OM_uint32
acceptor_approved(void *userptr,
		  gss_name_t target_name, 
		  const gss_cred_id_t cred_handle,
		  gss_OID mech)
{
    OM_uint32 junk, ret;
    gss_OID_set oidset;

    if (cred_handle) {
	int present = 0;

	ret = gss_inquire_cred(&junk,
			       cred_handle,
			       NULL,
			       NULL,
			       NULL,
			       &oidset);
	if (ret != GSS_S_COMPLETE)
	    return ret;

	ret = gss_test_oid_set_member(&junk, mech, oidset, &present);
	gss_release_oid_set(&junk, &oidset);
	
	if (ret != GSS_S_COMPLETE || present == 0)
	    return GSS_S_FAILURE;

    } else {
	gss_cred_id_t cred = GSS_C_NO_CREDENTIAL;

	if (target_name == GSS_C_NO_NAME)
	    return GSS_S_COMPLETE;
	
	gss_create_empty_oid_set(&junk, &oidset);
	gss_add_oid_set_member(&junk, mech, &oidset);

	ret = gss_acquire_cred(&junk, target_name, GSS_C_INDEFINITE, oidset,
			       GSS_C_ACCEPT, &cred, NULL, NULL);
	gss_release_oid_set(&junk, &oidset);
	if (ret != GSS_S_COMPLETE)
	    return ret;
	gss_release_cred(&junk, &cred);
    }

    return GSS_S_COMPLETE;
}
예제 #8
0
gss_OID_set mag_filter_unwanted_mechs(gss_OID_set src)
{
    gss_const_OID unwanted_mechs[] = {
        &gss_mech_spnego,
        gss_mech_krb5_old,
        gss_mech_krb5_wrong,
        gss_mech_iakerb,
        GSS_C_NO_OID
    };
    gss_OID_set dst;
    uint32_t maj, min;
    int present = 0;

    if (src == GSS_C_NO_OID_SET) return GSS_C_NO_OID_SET;

    for (int i = 0; unwanted_mechs[i] != GSS_C_NO_OID; i++) {
        maj = gss_test_oid_set_member(&min,
                                      discard_const(unwanted_mechs[i]),
                                      src, &present);
        if (present) break;
    }
    if (present) {
        maj = gss_create_empty_oid_set(&min, &dst);
        if (maj != GSS_S_COMPLETE) {
            return GSS_C_NO_OID_SET;
        }
        for (int i = 0; i < src->count; i++) {
            present = 0;
            for (int j = 0; unwanted_mechs[j] != GSS_C_NO_OID; j++) {
                if (gss_oid_equal(&src->elements[i], unwanted_mechs[j])) {
                    present = 1;
                    break;
                }
            }
            if (present) continue;
            maj = gss_add_oid_set_member(&min, &src->elements[i], &dst);
            if (maj != GSS_S_COMPLETE) {
                gss_release_oid_set(&min, &dst);
                return GSS_C_NO_OID_SET;
            }
        }
        return dst;
    }
    return src;
}
예제 #9
0
OM_uint32
gss_add_oid_set_member(OM_uint32 *minor_status,
    const gss_OID member_oid,
    gss_OID_set *oid_set)
{
	OM_uint32 major_status;
	gss_OID_set set = *oid_set;
	gss_OID new_elements;
	gss_OID new_oid;
	int t;

	*minor_status = 0;

	major_status = gss_test_oid_set_member(minor_status,
	    member_oid, *oid_set, &t);
	if (major_status)
		return (major_status);
	if (t)
		return (GSS_S_COMPLETE);

	new_elements = malloc((set->count + 1) * sizeof(gss_OID_desc));
	if (!new_elements) {
		*minor_status = ENOMEM;
		return (GSS_S_FAILURE);
	}

	new_oid = &new_elements[set->count];
	new_oid->elements = malloc(member_oid->length);
	if (!new_oid->elements) {
		free(new_elements);
		return (GSS_S_FAILURE);
	}
	new_oid->length = member_oid->length;
	memcpy(new_oid->elements, member_oid->elements, member_oid->length);

	if (set->elements) {
		memcpy(new_elements, set->elements,
		    set->count * sizeof(gss_OID_desc));
		free(set->elements);
	}
	set->elements = new_elements;
	set->count++;

	return (GSS_S_COMPLETE);
}
예제 #10
0
파일: cssp.c 프로젝트: 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;
}
예제 #11
0
/*
 * We only support those mechanisms that we know about (ie ones that we know
 * how to check local user kuserok and the like)
 */
static int
userauth_gssapi(struct ssh *ssh)
{
	Authctxt *authctxt = ssh->authctxt;
	gss_OID_desc goid = {0, NULL};
	Gssctxt *ctxt = NULL;
	int r, mechs, present;
	gss_OID_set supported;
	OM_uint32 ms;
	size_t len;
	u_char *doid = NULL;

	if (!authctxt->valid || authctxt->user == NULL)
		return (0);

	if ((r = sshpkt_get_u32(ssh, &mechs)) != 0)
		fatal("%s: %s", __func__, ssh_err(r));

	if (mechs == 0) {
		debug("Mechanism negotiation is not supported");
		return (0);
	}

	ssh_gssapi_supported_oids(&supported);
	do {
		mechs--;

		if (doid)
			xfree(doid);

		present = 0;
		if ((r = sshpkt_get_string(ssh, &doid, &len)) != 0)
			fatal("%s: %s", __func__, ssh_err(r));

		if (len > 2 && doid[0] == SSH_GSS_OIDTYPE &&
		    doid[1] == len - 2) {
			goid.elements = doid + 2;
			goid.length   = len - 2;
			gss_test_oid_set_member(&ms, &goid, supported,
			    &present);
		} else {
			logit("Badly formed OID received");
		}
	} while (mechs > 0 && !present);

	gss_release_oid_set(&ms, &supported);

	if (!present) {
		xfree(doid);
		authctxt->server_caused_failure = 1;
		return (0);
	}

	if (GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctxt, &goid)))) {
		if (ctxt != NULL)
			ssh_gssapi_delete_ctx(&ctxt);
		xfree(doid);
		authctxt->server_caused_failure = 1;
		return (0);
	}

	authctxt->methoddata = (void *)ctxt;

	/* Return the OID that we received */
	if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_GSSAPI_RESPONSE)) != 0 ||
	    (r = sshpkt_put_string(ssh, doid, len)) != 0 ||
	    (r = sshpkt_send(ssh)) != 0)
		fatal("%s: %s", __func__, ssh_err(r));

	xfree(doid);

	ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_TOKEN, &input_gssapi_token);
	ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, &input_gssapi_errtok);
	authctxt->postponed = 1;

	return (0);
}
예제 #12
0
OM_uint32
gss_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)
{
	OM_uint32 major_status;
	gss_OID_set mechs = desired_mechs;
	gss_OID_set_desc set;
	struct _gss_name *name = (struct _gss_name *) desired_name;
	gssapi_mech_interface m;
	struct _gss_cred *cred;
	struct _gss_mechanism_cred *mc;
	OM_uint32 min_time, cred_time;
	int i;

	_gss_load_mech();

	/*
	 * First make sure that at least one of the requested
	 * mechanisms is one that we support.
	 */
	if (mechs) {
		for (i = 0; i < mechs->count; i++) {
			int t;
			gss_test_oid_set_member(minor_status,
			    &mechs->elements[i], _gss_mech_oids, &t);
			if (t)
				break;
		}
		if (i == mechs->count) {
			*output_cred_handle = 0;
			*minor_status = 0;
			return (GSS_S_BAD_MECH);
		}
	}

	if (actual_mechs) {
		major_status = gss_create_empty_oid_set(minor_status,
		    actual_mechs);
		if (major_status)
			return (major_status);
	}

	cred = malloc(sizeof(struct _gss_cred));
	if (!cred) {
		if (actual_mechs)
			gss_release_oid_set(minor_status, actual_mechs);
		*minor_status = ENOMEM;
		return (GSS_S_FAILURE);
	}
	cred->gc_usage = cred_usage;
	SLIST_INIT(&cred->gc_mc);

	if (mechs == GSS_C_NO_OID_SET)
		mechs = _gss_mech_oids;

	set.count = 1;
	min_time = GSS_C_INDEFINITE;
	for (i = 0; i < mechs->count; i++) {
		struct _gss_mechanism_name *mn = NULL;

		m = __gss_get_mechanism(&mechs->elements[i]);
		if (!m)
			continue;

		if (desired_name != GSS_C_NO_NAME) {
			mn = _gss_find_mn(name, &mechs->elements[i]);
			if (!mn)
				continue;
		}

		mc = malloc(sizeof(struct _gss_mechanism_cred));
		if (!mc) {
			continue;
		}
		SLIST_INIT(&cred->gc_mc);
		mc->gmc_mech = m;
		mc->gmc_mech_oid = &m->gm_mech_oid;

		/*
		 * XXX Probably need to do something with actual_mechs.
		 */
		set.elements = &mechs->elements[i];
		major_status = m->gm_acquire_cred(minor_status,
		    (desired_name != GSS_C_NO_NAME
			? mn->gmn_name : GSS_C_NO_NAME),
		    time_req, &set, cred_usage,
		    &mc->gmc_cred, NULL, &cred_time);
		if (major_status) {
			free(mc);
			continue;
		}
		if (cred_time < min_time)
			min_time = cred_time;

		if (actual_mechs) {
			major_status = gss_add_oid_set_member(minor_status,
			    mc->gmc_mech_oid, actual_mechs);
			if (major_status) {
				m->gm_release_cred(minor_status,
				    &mc->gmc_cred);
				free(mc);
				continue;
			}
		}

		SLIST_INSERT_HEAD(&cred->gc_mc, mc, gmc_link);
	}

	/*
	 * If we didn't manage to create a single credential, return
	 * an error.
	 */
	if (!SLIST_FIRST(&cred->gc_mc)) {
		free(cred);
		if (actual_mechs)
			gss_release_oid_set(minor_status, actual_mechs);
		*output_cred_handle = 0;
		*minor_status = 0;
		return (GSS_S_NO_CRED);
	}

	if (time_rec)
		*time_rec = min_time;
	*output_cred_handle = (gss_cred_id_t) cred;
	*minor_status = 0;
	return (GSS_S_COMPLETE);
}
OM_uint32 GSSAPI_LIB_FUNCTION
gss_acquire_cred_ex_f(gss_status_id_t status,
		      gss_name_t desired_name,
		      OM_uint32 flags,
		      OM_uint32 time_req,
		      gss_const_OID desired_mech,
		      gss_cred_usage_t cred_usage,
		      gss_auth_identity_t identity,
		      void * userctx,
		      void (*usercomplete)(void *, OM_uint32, gss_status_id_t, gss_cred_id_t, gss_OID_set, OM_uint32))
{
        OM_uint32 major_status, minor_status;
	gss_name_t name = GSS_C_NO_NAME;
	gss_cred_id_t cred;
	OM_uint32 junk;
	gss_buffer_desc buffer;

	if (usercomplete == NULL)
	    return GSS_S_CALL_INACCESSIBLE_READ;

	/*
	 * If no desired_name, make one up from the identity
	 */
	if (desired_name == GSS_C_NO_NAME) {
	    char *str;
	    if (identity->username == NULL)
		return GSS_S_FAILURE;
	    if (identity->realm)
		asprintf(&str, "%s@%s", identity->username, identity->realm);
	    else
		str = strdup(identity->username);
	    buffer.value = str;
	    buffer.length = strlen(str);
	    
	    major_status = gss_import_name(&minor_status, &buffer, GSS_C_NT_USER_NAME, &name);
	    free(str);
	    if (major_status)
		return major_status;

	    desired_name = name;
	}

	/*
	 * First make sure that at least one of the requested
	 * mechanisms is one that we support.
	 */
	if (desired_mech) {
		int t;
		gss_test_oid_set_member(&junk, desired_mech, _gss_mech_oids, &t);
		if (!t) {
			if (name)
				gss_release_name(&junk, &name);
			return (GSS_S_BAD_MECH);
		}
	}

	buffer.value = identity->password;
	buffer.length = strlen(identity->password);

	cred = GSS_C_NO_CREDENTIAL;

	major_status = gss_acquire_cred_ext(&minor_status,
					    desired_name,
					    GSS_C_CRED_PASSWORD,
					    &buffer,
					    time_req,
					    desired_mech,
					    cred_usage,
					    &cred);
	if (name)
		gss_release_name(&junk, &name);
	if (major_status)
		return major_status;

	usercomplete(userctx, major_status, status, 
		     cred, GSS_C_NO_OID_SET, GSS_C_INDEFINITE);

	return GSS_S_COMPLETE;
}
예제 #14
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;
}
예제 #15
0
static bool mag_auth_basic(request_rec *req,
                           struct mag_config *cfg,
                           gss_buffer_desc ba_user,
                           gss_buffer_desc ba_pwd,
                           gss_name_t *client,
                           gss_OID *mech_type,
                           gss_cred_id_t *delegated_cred,
                           uint32_t *vtime)
{
#ifdef HAVE_GSS_KRB5_CCACHE_NAME
    const char *user_ccache = NULL;
    const char *orig_ccache = NULL;
    long long unsigned int rndname;
    apr_status_t rs;
#endif
    gss_name_t user = GSS_C_NO_NAME;
    gss_cred_id_t user_cred = GSS_C_NO_CREDENTIAL;
    gss_ctx_id_t user_ctx = GSS_C_NO_CONTEXT;
    gss_name_t server = GSS_C_NO_NAME;
    gss_cred_id_t server_cred = GSS_C_NO_CREDENTIAL;
    gss_ctx_id_t server_ctx = GSS_C_NO_CONTEXT;
    gss_buffer_desc input = GSS_C_EMPTY_BUFFER;
    gss_buffer_desc output = GSS_C_EMPTY_BUFFER;
    gss_OID_set allowed_mechs;
    gss_OID_set filtered_mechs;
    gss_OID_set actual_mechs = GSS_C_NO_OID_SET;
    uint32_t init_flags = 0;
    uint32_t maj, min;
    int present = 0;
    bool ret = false;

    maj = gss_import_name(&min, &ba_user, GSS_C_NT_USER_NAME, &user);
    if (GSS_ERROR(maj)) {
        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, req,
                      "In Basic Auth, %s",
                      mag_error(req, "gss_import_name() failed",
                                maj, min));
        goto done;
    }

    if (cfg->basic_mechs) {
        allowed_mechs = cfg->basic_mechs;
    } else if (cfg->allowed_mechs) {
        allowed_mechs = cfg->allowed_mechs;
    } else {
        struct mag_server_config *scfg;
        /* Try to fetch the default set if not explicitly configured,
         * We need to do this because gss_acquire_cred_with_password()
         * is currently limited to acquire creds for a single "default"
         * mechanism if no desired mechanisms are passed in. This causes
         * authentication to fail for secondary mechanisms as no user
         * credentials are generated for those. */
        scfg = ap_get_module_config(req->server->module_config,
                                    &auth_gssapi_module);
        /* In the worst case scenario default_mechs equals to GSS_C_NO_OID_SET.
         * This generally causes only the krb5 mechanism to be tried due
         * to implementation constraints, but may change in future. */
        allowed_mechs = scfg->default_mechs;
    }

    /* Remove Spnego if present, or we'd repeat failed authentiations
     * multiple times, one within Spnego and then again with an explicit
     * mechanism. We would normally just force Spnego and use
     * gss_set_neg_mechs, but due to the way we source the server name
     * and the fact MIT up to 1.14 at least does no handle union names,
     * we can't provide spnego with a server name that can be used by
     * multiple mechanisms, causing any but the first mechanism to fail.
     * Also remove unwanted krb mechs, or AS requests will be repeated
     * multiple times uselessly.
     */
    filtered_mechs = mag_filter_unwanted_mechs(allowed_mechs);
    if (filtered_mechs == allowed_mechs) {
        /* in case filtered_mechs was not allocated here don't free it */
        filtered_mechs = GSS_C_NO_OID_SET;
    } else if (filtered_mechs == GSS_C_NO_OID_SET) {
        ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, req, "Fatal "
                      "failure while filtering mechs, aborting");
        goto done;
    } else {
        /* use the filtered list */
        allowed_mechs = filtered_mechs;
    }

#ifdef HAVE_GSS_KRB5_CCACHE_NAME
    /* If we are using the krb5 mechanism make sure to set a per thread
     * memory ccache so that there can't be interferences between threads.
     * Also make sure we have  new cache so no cached results end up being
     * used. Some implementations of gss_acquire_cred_with_password() do
     * not reacquire creds if cached ones are around, failing to check
     * again for the password. */
    maj = gss_test_oid_set_member(&min, discard_const(gss_mech_krb5),
                                  allowed_mechs, &present);
    if (GSS_ERROR(maj)) {
        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, req,
                      "In Basic Auth, %s",
                      mag_error(req, "gss_test_oid_set_member() failed",
                                maj, min));
        goto done;
    }
    if (present) {
        rs = apr_generate_random_bytes((unsigned char *)(&rndname),
                                       sizeof(long long unsigned int));
        if (rs != APR_SUCCESS) {
            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, req,
                          "Failed to generate random ccache name");
            goto done;
        }
        user_ccache = apr_psprintf(req->pool, "MEMORY:user_%qu", rndname);
        maj = gss_krb5_ccache_name(&min, user_ccache, &orig_ccache);
        if (GSS_ERROR(maj)) {
            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, req,
                          "In Basic Auth, %s",
                          mag_error(req, "gss_krb5_ccache_name() "
                                    "failed", maj, min));
            goto done;
        }
    }
#endif

    maj = gss_acquire_cred_with_password(&min, user, &ba_pwd,
                                         GSS_C_INDEFINITE,
                                         allowed_mechs,
                                         GSS_C_INITIATE,
                                         &user_cred, &actual_mechs, NULL);
    if (GSS_ERROR(maj)) {
        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, req,
                      "In Basic Auth, %s",
                      mag_error(req, "gss_acquire_cred_with_password() "
                                "failed", maj, min));
        goto done;
    }

    /* must acquire creds based on the actual mechs we want to try */
    if (!mag_acquire_creds(req, cfg, actual_mechs,
                           GSS_C_ACCEPT, &server_cred, NULL)) {
        goto done;
    }

#ifdef HAVE_CRED_STORE
    if (cfg->deleg_ccache_dir) {
        /* delegate ourselves credentials so we store them as requested */
        init_flags |= GSS_C_DELEG_FLAG;
    }
#endif

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

        /* free these if looping */
        gss_release_buffer(&min, &output);
        gss_release_buffer(&min, &input);
        gss_release_name(&min, &server);

        maj = gss_inquire_cred_by_mech(&min, server_cred,
                                       &actual_mechs->elements[i],
                                       &server, NULL, NULL, NULL);
        if (GSS_ERROR(maj)) {
            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, req,
                          "%s", mag_error(req, "gss_inquired_cred_by_mech() "
                                          "failed", maj, min));
            continue;
        }

        do {
            /* output and input are inverted here, this is intentional */
            maj = gss_init_sec_context(&min, user_cred, &user_ctx, server,
                                       &actual_mechs->elements[i], init_flags,
                                       300, GSS_C_NO_CHANNEL_BINDINGS, &output,
                                       NULL, &input, NULL, NULL);
            if (GSS_ERROR(maj)) {
                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, req,
                              "%s", mag_error(req, "gss_init_sec_context() "
                                              "failed", maj, min));
                break;
            }
            gss_release_buffer(&min, &output);
            maj = gss_accept_sec_context(&min, &server_ctx, server_cred,
                                         &input, GSS_C_NO_CHANNEL_BINDINGS,
                                         client, mech_type, &output, NULL,
                                         vtime, delegated_cred);
            if (GSS_ERROR(maj)) {
                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, req,
                              "%s", mag_error(req, "gss_accept_sec_context()"
                                              " failed", maj, min));
                break;
            }
            gss_release_buffer(&min, &input);
        } while (maj == GSS_S_CONTINUE_NEEDED);

        if (maj == GSS_S_COMPLETE) {
            ret = true;
            break;
        }
    }

done:
    gss_release_buffer(&min, &output);
    gss_release_buffer(&min, &input);
    gss_release_name(&min, &server);
    gss_delete_sec_context(&min, &server_ctx, GSS_C_NO_BUFFER);
    gss_release_cred(&min, &server_cred);
    gss_release_name(&min, &user);
    gss_release_cred(&min, &user_cred);
    gss_delete_sec_context(&min, &user_ctx, GSS_C_NO_BUFFER);
    gss_release_oid_set(&min, &actual_mechs);
    gss_release_oid_set(&min, &filtered_mechs);
#ifdef HAVE_GSS_KRB5_CCACHE_NAME
    if (user_ccache != NULL) {
        maj = gss_krb5_ccache_name(&min, orig_ccache, NULL);
        if (maj != GSS_S_COMPLETE) {
            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, req,
                          "Failed to restore per-thread ccache, %s",
                          mag_error(req, "gss_krb5_ccache_name() "
                                    "failed", maj, min));
        }
    }
#endif
    return ret;
}
예제 #16
0
OM_uint32 gss_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
           )
{
    gss_cred_id_t handle;
    OM_uint32 ret;

    if (cred_usage != GSS_C_ACCEPT && cred_usage != GSS_C_INITIATE && cred_usage != GSS_C_BOTH) {
	*minor_status = GSS_KRB5_S_G_BAD_USAGE;
	return GSS_S_FAILURE;
    }

    GSSAPI_KRB5_INIT ();

    *output_cred_handle = NULL;
    if (time_rec)
	*time_rec = 0;
    if (actual_mechs)
	*actual_mechs = GSS_C_NO_OID_SET;

    if (desired_mechs) {
	int present = 0;

	ret = gss_test_oid_set_member(minor_status, GSS_KRB5_MECHANISM,
				      desired_mechs, &present); 
	if (ret)
	    return ret;
	if (!present) {
	    *minor_status = 0;
	    return GSS_S_BAD_MECH;
	}
    }

    handle = (gss_cred_id_t)malloc(sizeof(*handle));
    if (handle == GSS_C_NO_CREDENTIAL) {
	*minor_status = ENOMEM;
        return (GSS_S_FAILURE);
    }

    memset(handle, 0, sizeof (*handle));
    HEIMDAL_MUTEX_init(&handle->cred_id_mutex);

    if (desired_name != GSS_C_NO_NAME) {
	ret = gss_duplicate_name(minor_status, desired_name,
	    &handle->principal);
	if (ret != GSS_S_COMPLETE) {
	    HEIMDAL_MUTEX_destroy(&handle->cred_id_mutex);
	    free(handle);
	    return (ret);
	}
    }
    if (cred_usage == GSS_C_INITIATE || cred_usage == GSS_C_BOTH) {
	ret = acquire_initiator_cred(minor_status, desired_name, time_req,
	    desired_mechs, cred_usage, handle, actual_mechs, time_rec);
    	if (ret != GSS_S_COMPLETE) {
	    HEIMDAL_MUTEX_destroy(&handle->cred_id_mutex);
	    krb5_free_principal(gssapi_krb5_context, handle->principal);
	    free(handle);
	    return (ret);
	}
    }
    if (cred_usage == GSS_C_ACCEPT || cred_usage == GSS_C_BOTH) {
	ret = acquire_acceptor_cred(minor_status, desired_name, time_req,
	    desired_mechs, cred_usage, handle, actual_mechs, time_rec);
	if (ret != GSS_S_COMPLETE) {
	    HEIMDAL_MUTEX_destroy(&handle->cred_id_mutex);
	    krb5_free_principal(gssapi_krb5_context, handle->principal);
	    free(handle);
	    return (ret);
	}
    }
    ret = gss_create_empty_oid_set(minor_status, &handle->mechanisms);
    if (ret == GSS_S_COMPLETE)
    	ret = gss_add_oid_set_member(minor_status, GSS_KRB5_MECHANISM,
				 &handle->mechanisms);
    if (ret == GSS_S_COMPLETE)
    	ret = gss_inquire_cred(minor_status, handle, NULL, time_rec, NULL,
			   actual_mechs);
    if (ret != GSS_S_COMPLETE) {
	if (handle->mechanisms != NULL)
	    gss_release_oid_set(NULL, &handle->mechanisms);
	HEIMDAL_MUTEX_destroy(&handle->cred_id_mutex);
	krb5_free_principal(gssapi_krb5_context, handle->principal);
	free(handle);
	return (ret);
    } 
    *minor_status = 0;
    if (time_rec) {
	ret = gssapi_lifetime_left(minor_status,
				   handle->lifetime,
				   time_rec);

	if (ret)
	    return ret;
    }
    handle->usage = cred_usage;
    *output_cred_handle = handle;
    return (GSS_S_COMPLETE);
}
예제 #17
0
파일: auth2-gss.c 프로젝트: janetuk/openssh
/*
 * We only support those mechanisms that we know about (ie ones that we know
 * how to check local user kuserok and the like)
 */
static int
userauth_gssapi(Authctxt *authctxt)
{
	gss_OID_desc goid = {0, NULL};
	Gssctxt *ctxt = NULL;
	int mechs;
	gss_OID_set supported;
	int present;
	OM_uint32 ms;
	u_int len;
	u_char *doid = NULL;

	/* authctxt->valid may be 0 if we haven't yet determined
	   username from gssapi context. */

	if (authctxt->user == NULL)
		return (0);

	mechs = packet_get_int();
	if (mechs == 0) {
		debug("Mechanism negotiation is not supported");
		return (0);
	}

	ssh_gssapi_supported_oids(&supported);
	do {
		mechs--;

		if (doid)
			xfree(doid);

		present = 0;
		doid = packet_get_string(&len);

		if (len > 2 && doid[0] == SSH_GSS_OIDTYPE &&
		    doid[1] == len - 2) {
			goid.elements = doid + 2;
			goid.length   = len - 2;
			gss_test_oid_set_member(&ms, &goid, supported,
			    &present);
		} else {
			logit("Badly formed OID received");
		}
	} while (mechs > 0 && !present);

	gss_release_oid_set(&ms, &supported);

	if (!present) {
		xfree(doid);
		authctxt->server_caused_failure = 1;
		return (0);
	}

	if (GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctxt, &goid)))) {
		if (ctxt != NULL)
			ssh_gssapi_delete_ctx(&ctxt);
		xfree(doid);
		authctxt->server_caused_failure = 1;
		return (0);
	}

	authctxt->methoddata = (void *)ctxt;

	packet_start(SSH2_MSG_USERAUTH_GSSAPI_RESPONSE);

	/* Return the OID that we received */
	packet_put_string(doid, len);

	packet_send();
	xfree(doid);

	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, &input_gssapi_token);
	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, &input_gssapi_errtok);
	authctxt->postponed = 1;

	return (0);
}
예제 #18
0
파일: gssapi.c 프로젝트: Distrotech/libssh
/** @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]);
}
예제 #19
0
/*
 * We only support those mechanisms that we know about (ie ones that we know
 * how to check local user kuserok and the like
 */
static int
userauth_gssapi(Authctxt *authctxt)
{
	gss_OID_desc oid = {0, NULL};
	Gssctxt *ctxt = NULL;
	int mechs;
	gss_OID_set supported;
	int present;
	OM_uint32 ms;
	u_int len;
	char *doid = NULL;

	if (!authctxt->valid || authctxt->user == NULL)
		return (0);

	mechs = packet_get_int();
	if (mechs == 0) {
		debug("Mechanism negotiation is not supported");
		return (0);
	}

	ssh_gssapi_supported_oids(&supported);
	do {
		mechs--;

		if (doid)
			xfree(doid);

		doid = packet_get_string(&len);

		if (doid[0] != SSH_GSS_OIDTYPE || doid[1] != len-2) {
			logit("Mechanism OID received using the old encoding form");
			oid.elements = doid;
			oid.length = len;
		} else {
			oid.elements = doid + 2;
			oid.length   = len - 2;
		}
		gss_test_oid_set_member(&ms, &oid, supported, &present);
	} while (mechs > 0 && !present);

	gss_release_oid_set(&ms, &supported);

	if (!present) {
		xfree(doid);
		return (0);
	}

	if (GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctxt, &oid)))) {
		xfree(doid);
		return (0);
	}

	authctxt->methoddata=(void *)ctxt;

	packet_start(SSH2_MSG_USERAUTH_GSSAPI_RESPONSE);

	/* Return OID in same format as we received it*/
	packet_put_string(doid, len);

	packet_send();
	xfree(doid);

	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, &input_gssapi_token);
	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, &input_gssapi_errtok);
	authctxt->postponed = 1;

	return (0);
}
예제 #20
0
/**
 * This function is not a public interface and is deprecated anyways, do
 * not use.  Use gss_acquire_cred_with_password() instead for now.
 *
 * @deprecated
 */
OM_uint32
_gss_acquire_cred_ext(OM_uint32 *minor_status,
    gss_const_name_t desired_name,
    gss_const_OID credential_type,
    const void *credential_data,
    OM_uint32 time_req,
    gss_const_OID desired_mech,
    gss_cred_usage_t cred_usage,
    gss_cred_id_t *output_cred_handle)
{
    OM_uint32 major_status;
    struct _gss_name *name = (struct _gss_name *) desired_name;
    gssapi_mech_interface m;
    struct _gss_cred *cred;
    gss_OID_set_desc set, *mechs;
    size_t i;

    *minor_status = 0;
    if (output_cred_handle == NULL)
	return GSS_S_CALL_INACCESSIBLE_READ;

    _gss_load_mech();

    if (desired_mech != GSS_C_NO_OID) {
	int match = 0;

	gss_test_oid_set_member(minor_status, (gss_OID)desired_mech,
				_gss_mech_oids, &match);
	if (!match)
	    return GSS_S_BAD_MECH;

	set.count = 1;
	set.elements = (gss_OID)desired_mech;
	mechs = &set;
    } else
	mechs = _gss_mech_oids;

    cred = calloc(1, sizeof(*cred));
    if (cred == NULL) {
	*minor_status = ENOMEM;
	return GSS_S_FAILURE;
    }

    HEIM_SLIST_INIT(&cred->gc_mc);

    for (i = 0; i < mechs->count; i++) {
	struct _gss_mechanism_name *mn = NULL;
	struct _gss_mechanism_cred *mc = NULL;

	m = __gss_get_mechanism(&mechs->elements[i]);
	if (!m)
	    continue;

	if (desired_name != GSS_C_NO_NAME) {
	    major_status = _gss_find_mn(minor_status, name,
					&mechs->elements[i], &mn);
	    if (major_status != GSS_S_COMPLETE)
		continue;
	}

	major_status = _gss_acquire_mech_cred(minor_status, m, mn,
					      credential_type, credential_data,
					      time_req, desired_mech, cred_usage,
					      &mc);
	if (GSS_ERROR(major_status)) {
            if (mechs->count == 1)
                _gss_mg_error(m, major_status, *minor_status);
	    continue;
        }

	HEIM_SLIST_INSERT_HEAD(&cred->gc_mc, mc, gmc_link);
    }

    /*
     * If we didn't manage to create a single credential, return
     * an error.
     */
    if (!HEIM_SLIST_FIRST(&cred->gc_mc)) {
	free(cred);
        if (mechs->count > 1)
            *minor_status = 0;
	return GSS_S_NO_CRED;
    }

    *output_cred_handle = (gss_cred_id_t) cred;
    *minor_status = 0;
    return GSS_S_COMPLETE;
}
예제 #21
0
static
void
import_names()
{
    OM_uint32                           major_status, minor_status;
    globus_gsi_cred_handle_t            handle;
    gss_buffer_desc                     buffer;
    X509 *                              cert;
    gss_OID_set                         name_types;
    globus_result_t                     result;
    globus_list_t                       *i, *j;
    compare_name_test_case_t *          test_case;
    int                                 present;

    major_status = gss_inquire_names_for_mech(
        &minor_status,
        (gss_OID) globus_i_gss_mech_globus_gssapi_openssl,
        &name_types);

    if (major_status == GSS_S_COMPLETE)
    {
        major_status = gss_test_oid_set_member(
                &minor_status,
                GLOBUS_GSS_C_NT_X509,
                name_types,
                &present);

        if (major_status == GSS_S_COMPLETE && present)
        {
            gss_l_x509_support = GLOBUS_TRUE;
        }

        major_status = gss_test_oid_set_member(
                &minor_status,
                GLOBUS_GSS_C_NT_HOST_IP,
                name_types,
                &present);

        if (major_status == GSS_S_COMPLETE && present)
        {
            gss_l_host_ip_support = GLOBUS_TRUE;
        }

        major_status = gss_release_oid_set(&minor_status, &name_types);
    }

    for (i = test_cases; !globus_list_empty(i); i = globus_list_rest(i))
    {
        test_case = globus_list_first(i);

        if (test_case->name1 == GSS_C_NO_NAME)
        {
            switch (test_case->name_type1)
            {
                case GSS_L_ANONYMOUS:
                    major_status = gss_import_name(&minor_status, &buffer, GSS_C_NT_ANONYMOUS, &test_case->name1);
                    if (major_status != GSS_S_COMPLETE)
                    {
                        fprintf(stderr, "Error importing <anonymous>\n");
                        globus_gsi_gssapi_test_print_error(stderr, major_status, minor_status);
                        exit(-1);
                    }
                    break;
                case GSS_L_NO_OID:
                    buffer.value = test_case->name_token1;
                    buffer.length = strlen(buffer.value);

                    major_status = gss_import_name(&minor_status, &buffer, GSS_C_NO_OID, &test_case->name1);
                    if (major_status != GSS_S_COMPLETE)
                    {
                        fprintf(stderr, "Error importing %s\n", test_case->name_token1);
                        globus_gsi_gssapi_test_print_error(stderr, major_status, minor_status);
                        exit(-1);
                    }
                    break;
                case GSS_L_HOSTBASED_SERVICE:
                    buffer.value = test_case->name_token1;
                    buffer.length = strlen(buffer.value);

                    major_status = gss_import_name(&minor_status, &buffer, GSS_C_NT_HOSTBASED_SERVICE, &test_case->name1);
                    if (major_status != GSS_S_COMPLETE)
                    {
                        fprintf(stderr, "Error importing %s\n", test_case->name_token1);
                        globus_gsi_gssapi_test_print_error(stderr, major_status, minor_status);
                        exit(-1);
                    }
                    break;
                case GSS_L_HOST_IP:
                    if (gss_l_host_ip_support)
                    {
                        buffer.value = test_case->name_token1;
                        buffer.length = strlen(buffer.value);

                        major_status = gss_import_name(&minor_status, &buffer, GLOBUS_GSS_C_NT_HOST_IP, &test_case->name1);
                        if (major_status != GSS_S_COMPLETE)
                        {
                            fprintf(stderr, "Error importing %s\n", test_case->name_token1);
                            globus_gsi_gssapi_test_print_error(stderr, major_status, minor_status);
                            exit(-1);
                        }
                    }
                    break;
                case GSS_L_X509:
                    if (gss_l_x509_support)
                    {
                        result = globus_gsi_cred_handle_init(&handle, NULL);
                        if (result != GLOBUS_SUCCESS)
                        {
                            globus_gsi_gssapi_test_print_result(stderr, result);
                            exit(-1);
                        }

                        result = globus_gsi_cred_read_cert(handle, test_case->name_token1);
                        if (result != GLOBUS_SUCCESS)
                        {
                            globus_gsi_gssapi_test_print_result(stderr, result);
                            exit(-2);
                        }

                        result = globus_gsi_cred_get_cert(handle, &cert);

                        buffer.value = cert;
                        buffer.length = sizeof(X509);

                        major_status = gss_import_name(&minor_status, &buffer, GLOBUS_GSS_C_NT_X509, &test_case->name1);
                        if (major_status != GSS_S_COMPLETE)
                        {
                            fprintf(stderr, "Error importing %s\n", test_case->name_token1);
                            globus_gsi_gssapi_test_print_error(stderr, major_status, minor_status);
                            exit(-1);
                        }
                        X509_free(cert);
                        globus_gsi_cred_handle_destroy(handle);
                    }
                    break;
            }

            for (j = i; !globus_list_empty(j); j = globus_list_rest(j))
            {
                compare_name_test_case_t *test_case2 = globus_list_first(j);

                if (test_case->name_type1 == test_case2->name_type1 &&
                    test_case->name_token1 && test_case2->name_token1 &&
                    strcmp(test_case->name_token1, test_case2->name_token1) == 0 &&
                    test_case2->name1 == GSS_C_NO_NAME)
                {
                    test_case2->name1 = test_case->name1;
                }
                if (test_case->name_type1 == test_case2->name_type2 &&
                    test_case->name_token1 && test_case2->name_token2 &&
                    strcmp(test_case->name_token1, test_case2->name_token2) == 0 &&
                    test_case2->name2 == GSS_C_NO_NAME)
                {
                    test_case2->name2 = test_case->name1;
                }
            }
        }
        if (test_case->name2 == GSS_C_NO_NAME)
        {
            switch (test_case->name_type2)
            {
                case GSS_L_ANONYMOUS:
                    major_status = gss_import_name(&minor_status, &buffer, GSS_C_NT_ANONYMOUS, &test_case->name2);
                    if (major_status != GSS_S_COMPLETE)
                    {
                        fprintf(stderr, "Error importing <anonymous>\n");
                        globus_gsi_gssapi_test_print_error(stderr, major_status, minor_status);
                        exit(-1);
                    }
                    break;
                case GSS_L_NO_OID:
                    buffer.value = test_case->name_token2;
                    buffer.length = strlen(buffer.value);

                    major_status = gss_import_name(&minor_status, &buffer, GSS_C_NO_OID, &test_case->name2);
                    if (major_status != GSS_S_COMPLETE)
                    {
                        fprintf(stderr, "Error importing %s\n", test_case->name_token2);
                        globus_gsi_gssapi_test_print_error(stderr, major_status, minor_status);
                        exit(-1);
                    }
                    break;
                case GSS_L_HOSTBASED_SERVICE:
                    buffer.value = test_case->name_token2;
                    buffer.length = strlen(buffer.value);

                    major_status = gss_import_name(&minor_status, &buffer, GSS_C_NT_HOSTBASED_SERVICE, &test_case->name2);
                    if (major_status != GSS_S_COMPLETE)
                    {
                        fprintf(stderr, "Error importing %s\n", test_case->name_token2);
                        globus_gsi_gssapi_test_print_error(stderr, major_status, minor_status);
                        exit(-1);
                    }
                    break;
                case GSS_L_HOST_IP:
                    if (gss_l_host_ip_support)
                    {
                        buffer.value = test_case->name_token2;
                        buffer.length = strlen(buffer.value);

                        major_status = gss_import_name(&minor_status, &buffer, GLOBUS_GSS_C_NT_HOST_IP, &test_case->name2);
                        if (major_status != GSS_S_COMPLETE)
                        {
                            fprintf(stderr, "Error importing %s\n", test_case->name_token2);
                            globus_gsi_gssapi_test_print_error(stderr, major_status, minor_status);
                            exit(-1);
                        }
                    }
                    break;
                case GSS_L_X509:
                    if (gss_l_x509_support)
                    {
                        result = globus_gsi_cred_handle_init(&handle, NULL);
                        if (result != GLOBUS_SUCCESS)
                        {
                            globus_gsi_gssapi_test_print_result(stderr, result);
                            exit(-1);
                        }

                        result = globus_gsi_cred_read_cert(handle, test_case->name_token2);
                        if (result != GLOBUS_SUCCESS)
                        {
                            globus_gsi_gssapi_test_print_result(stderr, result);
                            exit(-2);
                        }

                        result = globus_gsi_cred_get_cert(handle, &cert);

                        buffer.value = cert;
                        buffer.length = sizeof(X509);

                        major_status = gss_import_name(&minor_status, &buffer, GLOBUS_GSS_C_NT_X509, &test_case->name2);
                        if (major_status != GSS_S_COMPLETE)
                        {
                            fprintf(stderr, "Error importing %s\n", test_case->name_token2);
                            globus_gsi_gssapi_test_print_error(stderr, major_status, minor_status);
                            exit(-1);
                        }
                        X509_free(cert);
                        globus_gsi_cred_handle_destroy(handle);
                    }
                    break;
            }
            for (j = i; !globus_list_empty(j); j = globus_list_rest(j))
            {
                compare_name_test_case_t *test_case2 = globus_list_first(j);

                if (test_case->name_type2 == test_case2->name_type1 &&
                    test_case->name_token2 && test_case2->name_token1 &&
                    strcmp(test_case->name_token2, test_case2->name_token1) == 0 &&
                    test_case2->name1 == GSS_C_NO_NAME)
                {
                    test_case2->name1 = test_case->name2;
                }
                if (test_case->name_type2 == test_case2->name_type2 &&
                    test_case->name_token2 && test_case2->name_token2 &&
                    strcmp(test_case->name_token2, test_case2->name_token2) == 0 &&
                    test_case2->name2 == GSS_C_NO_NAME)
                {
                    test_case2->name2 = test_case->name2;
                }
            }
        }
    }
}