/*
 * Equality based local login authorization.
 */
static OM_uint32
compare_names_authorize_localname(OM_uint32 *minor,
                                  const gss_union_name_t unionName,
                                  const gss_name_t user)
{

    OM_uint32 status, tmpMinor;
    gss_name_t canonName;
    int match = 0;

    status = gss_canonicalize_name(minor,
                                   user,
                                   unionName->mech_type,
                                   &canonName);
    if (status != GSS_S_COMPLETE)
        return (status);

    status = gss_compare_name(minor,
                              (gss_name_t)unionName,
                              canonName,
                              &match);
    if (status == GSS_S_COMPLETE && match == 0)
        status = GSS_S_UNAUTHORIZED;

    (void) gss_release_name(&tmpMinor, &canonName);

    return (status);
}
Example #2
0
uint32_t
sapgss_compare_name(
    uint32_t *minor_status,
    gss_name_t name1,
    gss_name_t name2,
    int *name_equal)
{
    return gss_compare_name(minor_status, name1, name2, name_equal);
}
Example #3
0
int
ssh_gssapi_credentials_updated(Gssctxt *ctxt) {
	static gss_name_t saved_name = GSS_C_NO_NAME;
	static OM_uint32 saved_lifetime = 0;
	static gss_OID saved_mech = GSS_C_NO_OID;
	static gss_name_t name;
	static OM_uint32 last_call = 0;
	OM_uint32 lifetime, now, major, minor;
	int equal;
	gss_cred_usage_t usage = GSS_C_INITIATE;
	
	now = time(NULL);

	if (ctxt) {
		debug("Rekey has happened - updating saved versions");

		if (saved_name != GSS_C_NO_NAME)
			gss_release_name(&minor, &saved_name);

		major = gss_inquire_cred(&minor, GSS_C_NO_CREDENTIAL,
		    &saved_name, &saved_lifetime, NULL, NULL);

		if (!GSS_ERROR(major)) {
			saved_mech = ctxt->oid;
		        saved_lifetime+= now;
		} else {
			/* Handle the error */
		}
		return 0;
	}

	if (now - last_call < 10)
		return 0;

	last_call = now;

	if (saved_mech == GSS_C_NO_OID)
		return 0;
	
	major = gss_inquire_cred(&minor, GSS_C_NO_CREDENTIAL, 
	    &name, &lifetime, NULL, NULL);
	if (major == GSS_S_CREDENTIALS_EXPIRED)
		return 0;
	else if (GSS_ERROR(major))
		return 0;

	major = gss_compare_name(&minor, saved_name, name, &equal);
	gss_release_name(&minor, &name);
	if (GSS_ERROR(major))
		return 0;

	if (equal && (saved_lifetime < lifetime + now - 10))
		return 1;

	return 0;
}
Example #4
0
static OM_uint32
compare_names(OM_uint32 *minor,
	    const gss_OID mech_type,
	    const gss_name_t name,
	    const char *user,
	    int *user_ok)
{

	OM_uint32 status, tmpMinor;
	gss_name_t imported_name;
	gss_name_t canon_name;
	gss_buffer_desc gss_user;
	int match = 0;

	*user_ok = 0;

	gss_user.value = (void *)user;
	if (!gss_user.value || !name || !mech_type)
		return (GSS_S_BAD_NAME);
	gss_user.length = strlen(gss_user.value);

	status = gss_import_name(minor,
				&gss_user,
				GSS_C_NT_USER_NAME,
				&imported_name);
	if (status != GSS_S_COMPLETE) {
		goto out;
	}

	status = gss_canonicalize_name(minor,
				    imported_name,
				    mech_type,
				    &canon_name);
	if (status != GSS_S_COMPLETE) {
		(void) gss_release_name(&tmpMinor, &imported_name);
		goto out;
	}

	status = gss_compare_name(minor,
				canon_name,
				name,
				&match);
	(void) gss_release_name(&tmpMinor, &canon_name);
	(void) gss_release_name(&tmpMinor, &imported_name);
	if (status == GSS_S_COMPLETE) {
		if (match)
			*user_ok = 1; /* remote user is a-ok */
	}

out:
	return (status);
}
Example #5
0
/*ARGSUSED*/
OM_uint32
ntlm_gss_compare_name(
			OM_uint32 *minor_status,
			const gss_name_t name1,
			const gss_name_t name2,
			int *name_equal)
{
	OM_uint32 status = GSS_S_COMPLETE;
	dsyslog("Entering compare_name\n");

	status = gss_compare_name(minor_status, name1, name2, name_equal);

	dsyslog("Leaving compare_name\n");
	return (status);
}
Example #6
0
/**
 * @brief Compares two RPC creds
 *
 * @param[in] cred1 First RPC cred
 * @param[in] cred2 Second RPC cred
 *
 * @return true if same, false otherwise
 */
bool nfs_compare_clientcred(nfs_client_cred_t *cred1,
			    nfs_client_cred_t *cred2)
{
#ifdef _HAVE_GSSAPI
	gss_name_t cred1_cred_name;
	gss_name_t cred2_cred_name;
	OM_uint32 maj_stat, min_stat;
	int status;
#endif


	if (cred1 == NULL)
		return false;
	if (cred2 == NULL)
		return false;

	if (cred1->flavor != cred2->flavor)
		return false;

	switch (cred1->flavor) {
	case AUTH_UNIX:
		if (cred1->auth_union.auth_unix.aup_uid !=
		    cred2->auth_union.auth_unix.aup_uid)
			return false;
		if (cred1->auth_union.auth_unix.aup_gid !=
		    cred2->auth_union.auth_unix.aup_gid)
			return false;
		break;

#ifdef _HAVE_GSSAPI
	case RPCSEC_GSS:
		maj_stat = gss_inquire_context(&min_stat,
			cred1->auth_union.auth_gss.gss_context_id,
			&cred1_cred_name, NULL, NULL, NULL, NULL, NULL, NULL);

		if (maj_stat != GSS_S_COMPLETE &&
		    maj_stat != GSS_S_CONTEXT_EXPIRED)
			return false;

		 maj_stat = gss_inquire_context(&min_stat,
			cred2->auth_union.auth_gss.gss_context_id,
			&cred2_cred_name, NULL, NULL, NULL, NULL, NULL, NULL);

		if (maj_stat != GSS_S_COMPLETE &&
		    maj_stat != GSS_S_CONTEXT_EXPIRED)
			return false;

		maj_stat = gss_compare_name(&min_stat, cred1_cred_name,
					    cred2_cred_name, &status);
		if (maj_stat != GSS_S_COMPLETE)
			return false;

		if (status == 0)
			return false;

		break;
#endif

	default:
		if (memcmp
		    (&cred1->auth_union, &cred2->auth_union, cred1->length))
			return false;
		break;
	}

	/* If this point is reached, structures are the same */
	return true;
}
/**
 * @brief Init Sec Context
 * @ingroup globus_gsi_gssapi
 */
OM_uint32 
GSS_CALLCONV gss_init_sec_context(
    OM_uint32 *                         minor_status,
    const gss_cred_id_t                 initiator_cred_handle,
    gss_ctx_id_t *                      context_handle_P,
    const gss_name_t                    target_name,
    const gss_OID                       mech_type,
    OM_uint32                           req_flags,
    OM_uint32                           time_req,
    const gss_channel_bindings_t        input_chan_bindings,
    const gss_buffer_t                  input_token,
    gss_OID *                           actual_mech_type,
    gss_buffer_t                        output_token,
    OM_uint32 *                         ret_flags,
    OM_uint32 *                         time_rec) 
{
    gss_ctx_id_desc *                   context = NULL;
    OM_uint32                           major_status = GSS_S_COMPLETE;
    OM_uint32                           local_minor_status;
    OM_uint32                           local_major_status;
    globus_result_t                     local_result;
    int                                 rc;
    char                                cbuf[1];
    globus_gsi_cert_utils_cert_type_t   cert_type;

    GLOBUS_I_GSI_GSSAPI_DEBUG_ENTER;

    *minor_status = (OM_uint32) GLOBUS_SUCCESS;
    output_token->length = 0;

    context = *context_handle_P;

    /* module activation if not already done by calling
     * globus_module_activate
     */
    
    globus_thread_once(
        &once_control,
        globus_l_gsi_gssapi_activate_once);

    globus_mutex_lock(&globus_i_gssapi_activate_mutex);
    if (!globus_i_gssapi_active)
    {
        globus_module_activate(GLOBUS_GSI_GSSAPI_MODULE);
    }
    globus_mutex_unlock(&globus_i_gssapi_activate_mutex);
    
    if(req_flags & GSS_C_ANON_FLAG &&
       req_flags & GSS_C_DELEG_FLAG)
    {
        major_status = GSS_S_FAILURE;
        GLOBUS_GSI_GSSAPI_ERROR_RESULT(
            minor_status,
            GLOBUS_GSI_GSSAPI_ERROR_BAD_ARGUMENT,
            (_GGSL("Can't initialize a context to be both anonymous and "
             "provide delegation")));
        goto error_exit;
    }

    if(req_flags & GSS_C_GLOBUS_SSL_COMPATIBLE &&
       req_flags & GSS_C_DELEG_FLAG)
    {
        major_status = GSS_S_FAILURE;
        GLOBUS_GSI_GSSAPI_ERROR_RESULT(
            minor_status,
            GLOBUS_GSI_GSSAPI_ERROR_BAD_ARGUMENT,
            (_GGSL("Can't initialize a context to both use SSL compatible "
             "context establishment and provide delegation")));
        goto error_exit;
    }

    if(req_flags & GSS_C_DELEG_FLAG &&
       target_name == GSS_C_NO_NAME)
    {
        major_status = GSS_S_FAILURE;
        GLOBUS_GSI_GSSAPI_ERROR_RESULT(
            minor_status,
            GLOBUS_GSI_GSSAPI_ERROR_BAD_ARGUMENT,
            (_GGSL("Need a target name for authorization prior "
             "to doing delegation")));
        goto error_exit;
    }

    
    if ((context == (gss_ctx_id_t) GSS_C_NO_CONTEXT) ||
        !(context->ctx_flags & GSS_I_CTX_INITIALIZED))
    {
        GLOBUS_I_GSI_GSSAPI_DEBUG_FPRINTF(
            2, (globus_i_gsi_gssapi_debug_fstream, 
                "Creating context w/ %s.\n",
                (initiator_cred_handle == GSS_C_NO_CREDENTIAL) ?
                "GSS_C_NO_CREDENTIAL" :
                "Credentials provided"));

        major_status = 
            globus_i_gsi_gss_create_and_fill_context(&local_minor_status,
                                                     &context,
                                                     initiator_cred_handle,
                                                     GSS_C_INITIATE,
                                                     req_flags);
        if (GSS_ERROR(major_status))
        {
            GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT(
                minor_status, local_minor_status,
                GLOBUS_GSI_GSSAPI_ERROR_WITH_GSS_CONTEXT);
            goto error_exit;
        }

        *context_handle_P = context;

        if (actual_mech_type != NULL)
        {
            *actual_mech_type = (gss_OID) gss_mech_globus_gssapi_openssl;
        }

        if (ret_flags != NULL)
        {
            *ret_flags = 0 ;
        }
    }
    else
    {
        /* first time there is no input token, but after that
         * there will always be one
         */
    	major_status = globus_i_gsi_gss_put_token(&local_minor_status,
                                                  context, 
                                                  NULL, 
                                                  input_token);
    	if (GSS_ERROR(major_status))
        {
            GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT(
                minor_status, local_minor_status,
                GLOBUS_GSI_GSSAPI_ERROR_TOKEN_FAIL);
            goto error_exit;
        }
    }

    switch (context->gss_state)
    {
    case(GSS_CON_ST_HANDSHAKE):
        
        /* do the handshake work */
        
        major_status = globus_i_gsi_gss_handshake(&local_minor_status,
                                                  context);
        
        if (major_status == GSS_S_CONTINUE_NEEDED)
        {
            break;
        }

        if(GSS_ERROR(major_status))
        {
            GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT(
                minor_status, local_minor_status,
                GLOBUS_GSI_GSSAPI_ERROR_HANDSHAKE);
            context->gss_state = GSS_CON_ST_DONE;
            break;
        }

        /* make sure we are talking to the correct server */
        major_status = globus_i_gsi_gss_retrieve_peer(&local_minor_status,
                                                      context,
                                                      GSS_C_INITIATE);
        if (GSS_ERROR(major_status))
        {
            GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT(
                minor_status, local_minor_status,
                GLOBUS_GSI_GSSAPI_ERROR_WITH_GSS_CONTEXT);
            context->gss_state = GSS_CON_ST_DONE;
            break;
        }

        local_result = globus_gsi_callback_get_cert_type(
            context->callback_data,
            &cert_type);
        if(local_result != GLOBUS_SUCCESS)
        {
            GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT(
                minor_status, local_minor_status,
                GLOBUS_GSI_GSSAPI_ERROR_WITH_CALLBACK_DATA);
            major_status = GSS_S_FAILURE;
            goto error_exit;
        }

        /* 
         * Need to check if the server is using a limited proxy. 
         * And if that is acceptable here. 
         * Caller tells us if it is not acceptable to 
         * use a limited proxy. 
         */
        if ((context->req_flags & 
             GSS_C_GLOBUS_DONT_ACCEPT_LIMITED_PROXY_FLAG)
            && GLOBUS_GSI_CERT_UTILS_IS_LIMITED_PROXY(cert_type))
        {
            major_status = GSS_S_UNAUTHORIZED;
            GLOBUS_GSI_GSSAPI_ERROR_RESULT(
                minor_status,
                GLOBUS_GSI_GSSAPI_ERROR_PROXY_VIOLATION,
                (_GGSL("Function set to not accept limited proxies")));
            context->gss_state = GSS_CON_ST_DONE;
            break;
        }

        /* this is the mutual authentication test */
        if (target_name != NULL)
        {
            major_status = 
                gss_compare_name(&local_minor_status,
                                 context->peer_cred_handle->globusid,
                                 target_name,
                                 &rc);
            if (GSS_ERROR(major_status))
            {
                GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT(
                    minor_status, local_minor_status,
                    GLOBUS_GSI_GSSAPI_ERROR_BAD_NAME);
                context->gss_state = GSS_CON_ST_DONE;
                break;
            }
            else if(rc == GSS_NAMES_NOT_EQUAL)
            {
                char *                  expected_name;
                char *                  actual_name;
                    
                if(g_OID_equal(((gss_name_desc*)  target_name)->name_oid,
                               GSS_C_NT_HOSTBASED_SERVICE))
                {
                    GLOBUS_GSI_GSSAPI_ERROR_RESULT(
                        minor_status,
                        GLOBUS_GSI_GSSAPI_ERROR_AUTHZ_DENIED,
                        (_GGSL("The expected name for the remote host (%s%s%s) does not match the authenticated "
                               "name of the remote host (%s%s%s). This happens when the name in the host certificate does not match the information obtained from DNS and is often a DNS configuration problem."),
                         target_name->service_name
                            ? target_name->service_name : "",
                         target_name->service_name
                            ? "@" : "",
                         target_name->host_name
                            ? target_name->host_name : "unknown",
                         context->peer_cred_handle->globusid->service_name 
                            ? context->peer_cred_handle->globusid->service_name
                            : "",
                         context->peer_cred_handle->globusid->service_name 
                            ? "@" : "",
                         context->peer_cred_handle->globusid->host_name 
                            ?  context->peer_cred_handle->globusid->host_name 
                            : "unknown"));
                }
                else
                { 
                    expected_name =
                        ((gss_name_desc*)  target_name)->x509n_oneline;
                    actual_name = 
                        ((gss_name_desc*)
                         context->peer_cred_handle->globusid)->x509n_oneline;
                    
                    GLOBUS_GSI_GSSAPI_ERROR_RESULT(
                        minor_status,
                        GLOBUS_GSI_GSSAPI_ERROR_AUTHZ_DENIED,
                        (_GGSL("The name of the remote entity (%s), and the expected "
                               "name for the remote entity (%s) do not match"),
                         actual_name, expected_name));
                }

                major_status = GSS_S_UNAUTHORIZED;
                context->gss_state = GSS_CON_ST_DONE;
                break;
            }
        }
    
        context->ret_flags |= GSS_C_MUTUAL_FLAG;
        context->ret_flags |= GSS_C_PROT_READY_FLAG; 
        context->ret_flags |= GSS_C_INTEG_FLAG
            | GSS_C_REPLAY_FLAG
            | GSS_C_SEQUENCE_FLAG
            | GSS_C_ANON_FLAG
            | GSS_C_DELEG_FLAG;
        if (GLOBUS_GSI_CERT_UTILS_IS_LIMITED_PROXY(cert_type))
        {
            context->ret_flags |= GSS_C_GLOBUS_RECEIVED_LIMITED_PROXY_FLAG;
        }
#       if LINK_WITH_INTERNAL_OPENSSL_API
        context->ret_flags |= GSS_C_TRANS_FLAG;
#       endif

        /* 
         * IF we are talking to a real SSL server,
         * we don't want to do delegation, so we are done
         */

        if (context->req_flags & GSS_C_GLOBUS_SSL_COMPATIBLE)
        {
            context->gss_state = GSS_CON_ST_DONE;
            break;
        }
            
        /*
         * If we have completed the handshake, but don't
         * have any more data to send, we can send the flag
         * now. i.e. fall through without break,
         * Otherwise, we will wait for the null byte
         * to get back in sync which we will ignore
         */

        if (output_token->length != 0)
        {
            context->gss_state=GSS_CON_ST_FLAGS;
            break;
        }

    case(GSS_CON_ST_FLAGS):

        if (input_token->length > 0)
        {   
            BIO_read(context->gss_sslbio, cbuf, 1);
        }

        /* send D if we want delegation, 0 otherwise */
        
        if (context->req_flags & GSS_C_DELEG_FLAG)
        {
            BIO_write(context->gss_sslbio, "D", 1); 
            context->gss_state = GSS_CON_ST_REQ;
        }
        else
        {
            BIO_write(context->gss_sslbio, "0", 1);
            context->gss_state = GSS_CON_ST_DONE;
        } 
        break;
            
    case(GSS_CON_ST_REQ):

        local_result = globus_gsi_proxy_inquire_req(
            context->proxy_handle,
            context->gss_sslbio);
        if(local_result != GLOBUS_SUCCESS)
        {
            GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT(
                minor_status, local_result,
                GLOBUS_GSI_GSSAPI_ERROR_PROXY_NOT_RECEIVED);
            major_status = GSS_S_FAILURE;
            context->gss_state = GSS_CON_ST_DONE;
            goto error_exit;
        }
        
        local_result = globus_gsi_cred_get_cert_type(
            context->cred_handle->cred_handle,
            &cert_type);
        
        if(local_result != GLOBUS_SUCCESS)
        {
            GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT(
                minor_status, local_result,
                GLOBUS_GSI_GSSAPI_ERROR_WITH_GSI_CREDENTIAL);
            major_status = GSS_S_FAILURE;
            context->gss_state = GSS_CON_ST_DONE;
            goto error_exit;
        }
        
        local_result =
            globus_gsi_proxy_handle_set_type(
                context->proxy_handle,
                (context->req_flags & GSS_C_GLOBUS_DELEGATE_LIMITED_PROXY_FLAG)
                ? GLOBUS_GSI_CERT_UTILS_TYPE_LIMITED_PROXY
                : GLOBUS_GSI_CERT_UTILS_TYPE_IMPERSONATION_PROXY);

        if(local_result != GLOBUS_SUCCESS)
        {
            GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT(
                minor_status, local_result,
                GLOBUS_GSI_GSSAPI_ERROR_WITH_GSI_PROXY);
            major_status = GSS_S_FAILURE;
            context->gss_state = GSS_CON_ST_DONE;
            goto exit;
        }

        
        local_result = globus_gsi_proxy_sign_req(
            context->proxy_handle,
            context->cred_handle->cred_handle,
            context->gss_sslbio);
        if(local_result != GLOBUS_SUCCESS)
        {
            GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT(
                minor_status, local_result,
                GLOBUS_GSI_GSSAPI_ERROR_WITH_GSI_PROXY);
            major_status = GSS_S_FAILURE;
            context->gss_state = GSS_CON_ST_DONE;
            goto error_exit;
        }

        context->gss_state = GSS_CON_ST_DONE;
        break;
            
    case(GSS_CON_ST_CERT): ;
    case(GSS_CON_ST_DONE): ;
    } /* end of switch for gss_con_st */

    local_major_status = globus_i_gsi_gss_get_token(&local_minor_status,
                                                    context, 
                                                    NULL, 
                                                    output_token);

    if(GSS_ERROR(local_major_status))
    {
        GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT(
            minor_status, local_minor_status,
            GLOBUS_GSI_GSSAPI_ERROR_TOKEN_FAIL);
        major_status = GSS_S_FAILURE;
        context->gss_state = GSS_CON_ST_DONE;
        goto error_exit;
    }

    /* some error occurred during switch */
    if(GSS_ERROR(major_status))
    {
        goto error_exit;
    }

    if (context->gss_state != GSS_CON_ST_DONE)
    {
        major_status |= GSS_S_CONTINUE_NEEDED;
    }
    else if(time_rec != NULL)
    {
        time_t                          lifetime;
        time_t                          current_time;
        
        major_status = globus_i_gsi_gss_get_context_goodtill(
            &local_minor_status,
            context,
            &lifetime);
        if(GSS_ERROR(major_status))
        {
            GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT(
                minor_status, local_minor_status,
                GLOBUS_GSI_GSSAPI_ERROR_WITH_GSS_CONTEXT);
            goto exit;
        }

        current_time = time(NULL);

        if(current_time > lifetime)
        {
            *time_rec = 0;
        }
        else
        {
            *time_rec = (OM_uint32) (lifetime - current_time);
        }
    }
       
    if (ret_flags != NULL)
    {
        *ret_flags = context->ret_flags;
    }

    GLOBUS_I_GSI_GSSAPI_DEBUG_FPRINTF(
        2, (globus_i_gsi_gssapi_debug_fstream,
            "init_sec_context:major_status:%08x"
            ":gss_state:%d req_flags=%08x:ret_flags=%08x\n",
            (unsigned int) major_status, 
            context->gss_state,
            (unsigned int) req_flags, 
            (unsigned int) context->ret_flags));

    goto exit;

 error_exit:

    gss_delete_sec_context(&local_minor_status, 
                           (gss_ctx_id_t *) &context,
                           output_token);
    *context_handle_P = (gss_ctx_id_t) context;
 
 exit:

    GLOBUS_I_GSI_GSSAPI_DEBUG_EXIT;
    return major_status;
}
int
GSI_SOCKET_authentication_init(GSI_SOCKET *self, char *accepted_peer_names[])
{
    int				token_status;
    gss_cred_id_t		creds = GSS_C_NO_CREDENTIAL;
    gss_name_t			server_gss_name = GSS_C_NO_NAME;
    OM_uint32			req_flags = 0, ret_flags = 0;
    int				return_value = GSI_SOCKET_ERROR;
    gss_buffer_desc		gss_buffer = { 0 }, tmp_gss_buffer = { 0 };
    gss_name_t			target_name = GSS_C_NO_NAME;
    gss_OID			target_name_type = GSS_C_NO_OID;
    int				i, rc=0, sock;
    FILE			*fp = NULL;
    char                        *cert_dir = NULL;
    globus_result_t res;
    
    if (self == NULL)
    {
	return GSI_SOCKET_ERROR;
    }

    if (accepted_peer_names == NULL ||
	accepted_peer_names[0] == NULL) {
	return GSI_SOCKET_ERROR;
    }

    if (self->gss_context != GSS_C_NO_CONTEXT)
    {
	GSI_SOCKET_set_error_string(self, "GSI_SOCKET already authenticated");
	goto error;
    }

    res = GLOBUS_GSI_SYSCONFIG_GET_CERT_DIR(&cert_dir);
    if (res == GLOBUS_SUCCESS) {
        myproxy_debug("using trusted certificates directory %s", cert_dir);
    } else {
        verror_put_string("error getting trusted certificates directory");
        globus_error_to_verror(res);
        goto error;
    }

    self->major_status = globus_gss_assist_acquire_cred(&self->minor_status,
							GSS_C_INITIATE,
							&creds);

    if (self->major_status != GSS_S_COMPLETE) {
	if (self->allow_anonymous) {
	    req_flags |= GSS_C_ANON_FLAG;
	    myproxy_debug("no valid credentials found -- "
			  "performing anonymous authentication");
	} else {
	    goto error;
	}
    }

    req_flags |= GSS_C_REPLAY_FLAG;
    req_flags |= GSS_C_MUTUAL_FLAG;
    req_flags |= GSS_C_CONF_FLAG;
    req_flags |= GSS_C_INTEG_FLAG;

    if ((sock = dup(self->sock)) < 0) {
	GSI_SOCKET_set_error_string(self, "dup() of socket fd failed");
	self->error_number = errno;
	goto error;
    }
    if ((fp = fdopen(sock, "r")) == NULL) {
	GSI_SOCKET_set_error_string(self, "fdopen() of socket failed");
	self->error_number = errno;
	goto error;
    }
    if (setvbuf(fp, NULL, _IONBF, 0) != 0) {
	GSI_SOCKET_set_error_string(self, "setvbuf() for socket failed");
	self->error_number = errno;
	goto error;
    }
    
    self->major_status =
	globus_gss_assist_init_sec_context(&self->minor_status,
					   creds,
					   &self->gss_context,
					   "GSI-NO-TARGET",
					   req_flags,
					   &ret_flags,
					   &token_status,
					   globus_gss_assist_token_get_fd,
					   (void *)fp,
					   assist_write_token,
					   (void *)&self->sock);

    if (self->major_status != GSS_S_COMPLETE) {
        goto error;
    }

    
    /* Verify that all service requests were honored. */
    req_flags &= ~(GSS_C_ANON_FLAG); /* GSI GSSAPI doesn't set this flag */
    if ((req_flags & ret_flags) != req_flags) {
      GSI_SOCKET_set_error_string(self,
                                  "requested GSSAPI service not supported");
      goto error;
    }

    if (ret_flags & GSS_C_GLOBUS_LIMITED_PROXY_FLAG) {
        self->limited_proxy = 1;
    }

    /* Check the authenticated identity of the server. */
    self->major_status = gss_inquire_context(&self->minor_status,
					     self->gss_context,
					     NULL,
					     &server_gss_name,
					     NULL, NULL, NULL, NULL, NULL);
    if (self->major_status != GSS_S_COMPLETE) {
	GSI_SOCKET_set_error_string(self, "gss_inquire_context() failed");
	goto error;
    }

    self->major_status = gss_display_name(&self->minor_status,
					  server_gss_name, &gss_buffer, NULL);
    if (self->major_status != GSS_S_COMPLETE) {
	GSI_SOCKET_set_error_string(self, "gss_display_name() failed");
	goto error;
    }

    self->peer_name = strdup(gss_buffer.value);
    myproxy_debug("server name: %s", self->peer_name);
    myproxy_debug("checking that server name is acceptable...");

    /* We told gss_assist_init_sec_context() not to check the server
       name so we can check it manually here. */
    for (i=0; accepted_peer_names[i] != NULL; i++) {
	tmp_gss_buffer.value = (void *)accepted_peer_names[i];
	tmp_gss_buffer.length = strlen(accepted_peer_names[i]);
	if (strchr(accepted_peer_names[i],'@') && 
	    !strstr(accepted_peer_names[i],"CN=")) { 
	    target_name_type = GSS_C_NT_HOSTBASED_SERVICE;
	} else {
	    target_name_type = GSS_C_NO_OID;
	}
	self->major_status = gss_import_name(&self->minor_status,
					     &tmp_gss_buffer,
					     target_name_type,
					     &target_name);
	if (self->major_status != GSS_S_COMPLETE) {
	    char error_string[550];
	    sprintf(error_string, "failed to import GSS name \"%.500s\"",
		    accepted_peer_names[i]);
	    GSI_SOCKET_set_error_string(self, error_string);
	    goto error;
	}
	self->major_status = gss_compare_name(&self->minor_status,
					      server_gss_name,
					      target_name, &rc);
        gss_release_name(&self->minor_status, &target_name);
	if (self->major_status != GSS_S_COMPLETE) {
	    char error_string[1050];
	    sprintf(error_string,
		    "gss_compare_name(\"%.500s\",\"%.500s\") failed",
		    self->peer_name, accepted_peer_names[i]);
	    GSI_SOCKET_set_error_string(self, error_string);
	    goto error;
	}

	if (rc) {
	    myproxy_debug("server name matches \"%s\"",
                      accepted_peer_names[i]);
	    break;
	} else {
	    myproxy_debug("server name does not match \"%s\"",
                      accepted_peer_names[i]);
	}
    }
    if (!rc) {		/* no match with acceptable target names */
	GSI_SOCKET_set_error_string(self, "authenticated peer name does not match");
	return_value = GSI_SOCKET_UNAUTHORIZED;
	goto error;
    }
    myproxy_debug("authenticated server name is acceptable");

    /* Success */
    return_value = GSI_SOCKET_SUCCESS;
    
  error:
    {
	OM_uint32 minor_status;
	gss_release_cred(&minor_status, &creds);
	gss_release_buffer(&minor_status, &gss_buffer);
	gss_release_name(&minor_status, &server_gss_name);
    }
    if (cert_dir) free(cert_dir);
    if (fp) fclose(fp);
    
    return return_value;
}
int
gsslib_put_credentials(gss_cred_id_t server_creds,
                       gss_buffer_desc *cred,
                       char *username)
{
   gss_ctx_id_t context = GSS_C_NO_CONTEXT;
   gss_buffer_desc client_name;
   OM_uint32 maj_stat, min_stat;
   GSSAPI_INT ret_flags;
   gss_buffer_desc send_tok;
   gss_name_t client = NULL;
   gss_OID doid;
   int cc=0;
   gss_cred_id_t delegated_cred = GSS_C_NO_CREDENTIAL;

   gsslib_reset_error();

   send_tok.length = 0;
   client_name.length = 0;

   if (cred->length <= 0) {
      gsslib_print_error(MSG_GSS_PRINTERROR_CREDENTIALBUFFERLENGTHISZERO );
      cc = -1;
      goto error;
   }

   /*
    * establish and forward client credentials
    */

   maj_stat = gss_accept_sec_context(&min_stat,
                                     &context,
                                     server_creds,
                                     cred,
                                     GSS_C_NO_CHANNEL_BINDINGS,
                                     &client,
                                     &doid,
                                     &send_tok,
                                     &ret_flags,
                                     NULL,     /* ignore time_rec */
                                     &delegated_cred);    /* ignore del_cred_handle */

   if (maj_stat!=GSS_S_COMPLETE && maj_stat!=GSS_S_CONTINUE_NEEDED) {
      gsslib_display_status(MSG_GSS_DISPLAYSTATUS_ACCEPTINGCONTEXT, maj_stat, min_stat);
      cc = -1;
      goto error;
   }

   if (send_tok.length != 0) {
      fprintf(stderr, "%s\n", MSG_GSS_ACCEPTSECCONTEXTREQUIRESTOKENTOBESENTBACK );
      /* cc = -1;
      goto error; */
   }

   maj_stat = gss_display_name(&min_stat, client, &client_name, &doid);
   if (maj_stat != GSS_S_COMPLETE) {
      gsslib_display_status(MSG_GSS_DISPLAYSTATUS_DISPLAYINGNAME, maj_stat, min_stat);
      cc = -1;
      goto error;
   }

#ifdef KRBGSS
#ifdef KRB5_EXPORTVAR /* this is required for later Kerberos versions */

   /* check for delegated credential */
   if (delegated_cred == GSS_C_NO_CREDENTIAL) {
      fprintf(stderr, "WARNING: Credentials were not forwarded\n");
#ifdef REQUIRE_FORWARDED_CREDENTIALS
      cc = 3;
      goto error;
#endif
   }

   if (username && (ret_flags & GSS_C_DELEG_FLAG)) {
      char *principal = malloc(client_name.length + 1);
      strncpy(principal, client_name.value, client_name.length);
      principal[client_name.length] = 0;
      put_creds_in_ccache(principal, delegated_cred);
      free(principal);
   }

#endif
#endif

   /* display the flags */
   if (verbose)
      gsslib_display_ctx_flags(ret_flags);

   if (verbose)
      printf("client: \"%.*s\"\n",
             (int) client_name.length, (char *) client_name.value);

   if (username) {
      gss_buffer_desc tok;
      gss_name_t user_name;
      int str_equal;

      tok.value = username;
      tok.length = strlen(tok.value)+1;
      maj_stat = gss_import_name(&min_stat, &tok, GSS_C_NULL_OID, &user_name);
      if (maj_stat != GSS_S_COMPLETE) {
	 gsslib_display_status(MSG_GSS_DISPLAYSTATUS_PARSINGNAME, maj_stat, min_stat);
         cc = -1;
         goto error;
      }
      maj_stat = gss_compare_name(&min_stat, client, user_name, &str_equal);
      if (maj_stat != GSS_S_COMPLETE) {
	 gsslib_display_status( MSG_GSS_DISPLAYSTATUS_DISPLAYINGNAME, maj_stat, min_stat);
         cc = 6;
         goto error;
      }

#ifdef KRBGSS

      if (!str_equal) {
         krb5_context context;

         maj_stat = krb5_init_context(&context);
         if (maj_stat != GSS_S_COMPLETE) {
            gsslib_display_status(MSG_GSS_DISPLAYSTATUS_GETTINGKRB5CONTEXT,
                                  maj_stat, GSS_S_COMPLETE);
            cc = -1;
            goto error;
         }

         /* see if this user is authorized by the krb5 client */
         if (krb5_kuserok(context, (krb5_principal)client, username))
            str_equal = 1;
      }

      /* Users from Kerberos cross-authenticated realms will not match,
         so we manually compare the user names */
      if (!str_equal) {
         char *s;
         if ((s=strchr((char *)client_name.value, '@')))
            str_equal = !strncmp(username, (char *)client_name.value, 
                                 s-(char *)client_name.value);
      }

#endif
      if (!str_equal) {
         char buf[1024];
         snprintf(buf, sizeof(buf), MSG_GSS_CLIENTNAMEXDOESNOTMATCHUNAMEY_SS,
                  (int)client_name.length, (char *)client_name.value, username);
         gsslib_print_error(buf);
         cc = 5;
         goto error;
      }
   }

#ifdef DCE

   while (delegated_cred) {
      sec_login_handle_t login_context;
      error_status_t st;
      dce_error_string_t err_string;
      int lst;
      sec_login_auth_src_t auth_src=NULL;
      boolean32 reset_passwd=0;
      char errbuf[1024];
      unsigned32 num_groups=0;
      signed32 *groups=NULL;
      unsigned32 flags;

      maj_stat = gssdce_set_cred_context_ownership(&min_stat, delegated_cred, GSSDCE_C_OWNERSHIP_APPLICATION);
      if (maj_stat != GSS_S_COMPLETE) {
	 gsslib_display_status(MSG_GSS_DISPLAYSTATUS_GSSDCESETCREDCONTEXTOWNERSHIP, maj_stat, min_stat);
	 break;
      }

#if 0
      gsslib_print_error(MSG_GSS_PRINTERROR_CREDENTIALDUMP);
      gsslib_print_error(dump_cred(delegated_cred));
#endif

      maj_stat = gssdce_cred_to_login_context(&min_stat, delegated_cred,
					      &login_context);
      if (maj_stat != GSS_S_COMPLETE) {
	 gsslib_display_status(MSG_GSS_DISPLAYSTATUS_GSSDCECREDTOLOGINCONTEXT, maj_stat,
			       min_stat);
	 break;
      }

#ifdef TURN_OFF_DELEGATION
      {
         sec_login_handle_t *new_login_context;

         new_login_context = sec_login_disable_delegation(login_context, &st);
         if (st != error_status_ok) {
            dce_error_inq_text(st, err_string, &lst);
            snprintf(errbuf, sizeof errbuf,
                     MSG_GSS_PRINTERROR_COULDNOTDISABLEDELEGATIONX_S, err_string);
            gsslib_print_error(errbuf);
         } else {
            login_context = *new_login_context;
         }
      }
#endif

      flags = sec_login_get_context_flags(login_context, &st);
      sec_login_set_context_flags(login_context,
				  flags & ~sec_login_credentials_private,
				  &st);


      if (!sec_login_certify_identity(login_context, &st)) {
	 dce_error_inq_text(st, err_string, &lst);
	 snprintf(errbuf, sizeof errbuf,
                  MSG_GSS_PRINTERROR_COULDNOTCERTIFYIDENTITYX_S, err_string);
         gsslib_print_error(errbuf);
	 break;
      }

      sec_login_set_context(login_context, &st);
      if (st != error_status_ok) {
         dce_error_inq_text(st, err_string, &lst);
	 snprintf(errbuf, sizeof errbuf,
                  MSG_GSS_PRINTERROR_COULDNOTSETUPLOGINCONTEXTX_S, err_string);
         gsslib_print_error(errbuf);
	 break;
      }

      {
	 char *cp;
	 cp = getenv("KRB5CCNAME");
	 if (cp) {
            snprintf(errbuf, sizeof errbuf, MSG_GSS_PRINTERROR_NEWKRB5CCNAMEISX_S , cp);
	    gsslib_print_error(errbuf);
	 } else {
	    gsslib_print_error(MSG_GSS_PRINTERROR_KRB5CCNAMENOTFOUND );
	 }
      }

      break;
   }

#endif /* DCE */

 error:

   if (client) {
      maj_stat = gss_release_name(&min_stat, &client);
      if (maj_stat != GSS_S_COMPLETE) {
         gsslib_display_status(MSG_GSS_DISPLAYSTATUS_RELEASINGNAME, maj_stat, min_stat);
         cc = -1;
      }
   }

   if (send_tok.length)
      (void) gss_release_buffer(&min_stat, &send_tok);

   if (client_name.length)
      (void) gss_release_buffer(&min_stat, &client_name);

   return cc;
}
static void
copy_import(void)
{
    gss_cred_id_t cred1, cred2;
    OM_uint32 maj_stat, min_stat;
    gss_name_t name1, name2;
    OM_uint32 lifetime1, lifetime2;
    gss_cred_usage_t usage1, usage2;
    gss_OID_set mechs1, mechs2;
    krb5_ccache id;
    krb5_error_code ret;
    krb5_context context;
    int equal;

    maj_stat = gss_acquire_cred(&min_stat, GSS_C_NO_NAME, GSS_C_INDEFINITE,
				GSS_C_NO_OID_SET, GSS_C_INITIATE,
				&cred1, NULL, NULL);
    if (maj_stat != GSS_S_COMPLETE)
	errx(1, "gss_acquire_cred");

    maj_stat = gss_inquire_cred(&min_stat, cred1, &name1, &lifetime1,
				&usage1, &mechs1);
    if (maj_stat != GSS_S_COMPLETE)
	errx(1, "gss_inquire_cred");

    ret = krb5_init_context(&context);
    if (ret)
	errx(1, "krb5_init_context");

    ret = krb5_cc_new_unique(context, krb5_cc_type_memory, NULL, &id);
    if (ret)
	krb5_err(context, 1, ret, "krb5_cc_new_unique");

    maj_stat = gss_krb5_copy_ccache(&min_stat, cred1, id);
    if (maj_stat != GSS_S_COMPLETE)
	errx(1, "gss_krb5_copy_ccache");

    maj_stat = gss_krb5_import_cred(&min_stat, id, NULL, NULL, &cred2);
    if (maj_stat != GSS_S_COMPLETE)
	errx(1, "gss_krb5_import_cred");

    maj_stat = gss_inquire_cred(&min_stat, cred2, &name2, &lifetime2,
				&usage2, &mechs2);
    if (maj_stat != GSS_S_COMPLETE)
	errx(1, "gss_inquire_cred 2");

    maj_stat = gss_compare_name(&min_stat, name1, name2, &equal);
    if (maj_stat != GSS_S_COMPLETE)
	errx(1, "gss_compare_name");
    if (!equal)
	errx(1, "names not equal");

    if (lifetime1 != lifetime2)
	errx(1, "lifetime not equal %lu != %lu",
	     (unsigned long)lifetime1, (unsigned long)lifetime2);

    if (usage1 != usage2) {
	/* as long any of them is both are everything it ok */
	if (usage1 != GSS_C_BOTH && usage2 != GSS_C_BOTH)
	    errx(1, "usages disjoined");
    }

    gss_release_name(&min_stat, &name2);
    gss_release_oid_set(&min_stat, &mechs2);

    maj_stat = gss_inquire_cred(&min_stat, cred2, &name2, &lifetime2,
				&usage2, &mechs2);
    if (maj_stat != GSS_S_COMPLETE)
	errx(1, "gss_inquire_cred");

    maj_stat = gss_compare_name(&min_stat, name1, name2, &equal);
    if (maj_stat != GSS_S_COMPLETE)
	errx(1, "gss_compare_name");
    if (!equal)
	errx(1, "names not equal");

    if (lifetime1 != lifetime2)
	errx(1, "lifetime not equal %lu != %lu",
	     (unsigned long)lifetime1, (unsigned long)lifetime2);

    gss_release_cred(&min_stat, &cred1);
    gss_release_cred(&min_stat, &cred2);

    gss_release_name(&min_stat, &name1);
    gss_release_name(&min_stat, &name2);

#if 0
    compare(mechs1, mechs2);
#endif

    gss_release_oid_set(&min_stat, &mechs1);
    gss_release_oid_set(&min_stat, &mechs2);

    krb5_cc_destroy(context, id);
    krb5_free_context(context);
}
int main(int argc, char * argv[])
{
    int                                 rc = 0, c = 0, failed = 0;
    OM_uint32                           major_status, minor_status;
    int                                 name_equal;
    globus_list_t                       *i;
    compare_name_test_case_t *          test_case;
    globus_module_descriptor_t          *modules[] =
    {
        GLOBUS_COMMON_MODULE,
        GLOBUS_GSI_GSSAPI_MODULE,
        GLOBUS_GSI_CREDENTIAL_MODULE,
        NULL
    }, *failed_module = NULL;

    if (argc != 2)
    {
        fprintf(stderr, "%s test-case-file\n", argv[0]);
        exit(-1);
    }

    rc = globus_module_activate_array(modules, &failed_module);
    if (rc != 0)
    {
        exit(-1);
    }

    globus_l_gss_read_test_cases(argv[1]);
    import_names();

    printf("1..%d\n", globus_list_size(test_cases));

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

        if ((!gss_l_host_ip_support) &&
            (test_case->name_type1 == GSS_L_HOST_IP ||
             test_case->name_type2 == GSS_L_HOST_IP))
        {
            printf("ok %d # skip !gss_l_host_ip_support\n", ++c);
            fflush(stdout);
            continue;
        }
        if ((!gss_l_x509_support) &&
            (test_case->name_type1 == GSS_L_X509 ||
             test_case->name_type2 == GSS_L_X509))
        {
            printf("ok %d # skip !gss_l_x509_support\n", ++c);
            fflush(stdout);
            continue;
        }

        rc = 0;
        major_status = gss_compare_name(
                &minor_status, test_case->name1, test_case->name2, &name_equal);

        if (GSS_ERROR(major_status))
        {
            globus_gsi_gssapi_test_print_error(
                stderr, major_status, minor_status);
            rc = 1;
        }
        else if (name_equal != test_case->expectation)
        {
            globus_l_gss_test_print_name_error(
                    stderr,
                    test_case->name1, test_case->name_type1,
                    test_case->name2, test_case->name_type2,
                    test_case->expectation);
            rc = 2;
        }
        major_status = gss_compare_name(
                &minor_status, test_case->name2, test_case->name1, &name_equal);
        if (GSS_ERROR(major_status))
        {
            globus_gsi_gssapi_test_print_error(
                stderr, major_status, minor_status);
            rc = 3;
        }
        else if (name_equal != test_case->expectation)
        {
            globus_l_gss_test_print_name_error(
                    stderr,
                    test_case->name2, test_case->name_type2,
                    test_case->name1, test_case->name_type1,
                    test_case->expectation);
            rc = 4;
        }

        c++;
        if (rc == 0)
        {
            printf("ok %s\n", test_case->test_name);
        }
        else
        {
            failed++;
            printf("not ok %d %s\n", c, test_case->test_name);
        }
        fflush(stdout);
    }
    globus_l_gss_free_test_cases();

    return failed;
}
bool Condor_Auth_X509::CheckServerName(char const *fqh,char const *ip,ReliSock *sock,CondorError *errstack)
{
	if( param_boolean("GSI_SKIP_HOST_CHECK",false) ) {
		return true;
	}

	char const *server_dn = getAuthenticatedName();
	if( !server_dn ) {
		std::string msg;
		formatstr(msg,"Failed to find certificate DN for server on GSI connection to %s",ip);
		errstack->push("GSI", GSI_ERR_DNS_CHECK_ERROR, msg.c_str());
		return false;
	}

	std::string skip_check_pattern;
	if( param(skip_check_pattern,"GSI_SKIP_HOST_CHECK_CERT_REGEX") ) {
		Regex re;
		const char *errptr=NULL;
		int erroffset=0;
		std::string full_pattern;
		formatstr(full_pattern,"^(%s)$",skip_check_pattern.c_str());
		if( !re.compile(full_pattern.c_str(),&errptr,&erroffset) ) {
			dprintf(D_ALWAYS,"GSI_SKIP_HOST_CHECK_CERT_REGEX is not a valid regular expression: %s\n",skip_check_pattern.c_str());
			return false;
		}
		if( re.match(server_dn,NULL) ) {
			return true;
		}
	}

	ASSERT( errstack );
	ASSERT( m_gss_server_name );
	ASSERT( ip );
	if( !fqh || !fqh[0] ) {
		std::string msg;
		formatstr(msg,"Failed to look up server host address for GSI connection to server with IP %s and DN %s.  Is DNS correctly configured?  This server name check can be bypassed by making GSI_SKIP_HOST_CHECK_CERT_REGEX match the DN, or by disabling all hostname checks by setting GSI_SKIP_HOST_CHECK=true or defining GSI_DAEMON_NAME.",ip,server_dn);
		errstack->push("GSI", GSI_ERR_DNS_CHECK_ERROR, msg.c_str());
		return false;
	}

	std::string connect_name;
	gss_buffer_desc gss_connect_name_buf;
	gss_name_t gss_connect_name;
	OM_uint32 major_status = 0;
	OM_uint32 minor_status = 0;

	char const *connect_addr = sock->get_connect_addr();
	std::string alias_buf;
	if( connect_addr ) {
		Sinful s(connect_addr);
		char const *alias = s.getAlias();
		if( alias ) {
			dprintf(D_FULLDEBUG,"GSI host check: using host alias %s for %s %s\n",alias,fqh,sock->peer_ip_str());
			alias_buf = alias;
			fqh = alias_buf.c_str();
		}
	}

	formatstr(connect_name,"%s/%s",fqh,sock->peer_ip_str());

	gss_connect_name_buf.value = strdup(connect_name.c_str());
	gss_connect_name_buf.length = connect_name.size()+1;

	major_status = gss_import_name(&minor_status,
								   &gss_connect_name_buf,
								   GLOBUS_GSS_C_NT_HOST_IP,
								   &gss_connect_name);

	free( gss_connect_name_buf.value );

	if( major_status != GSS_S_COMPLETE ) {
		std::string comment;
		formatstr(comment,"Failed to create gss connection name data structure for %s.\n",connect_name.c_str());
		print_log( major_status, minor_status, 0, comment.c_str() );
		return false;
	}

	int name_equal = 0;
	major_status = gss_compare_name( &minor_status,
									 m_gss_server_name,
									 gss_connect_name,
									 &name_equal );

	gss_release_name( &major_status, &gss_connect_name );

	if( !name_equal ) {
		std::string msg;
		formatstr(msg,"We are trying to connect to a daemon with certificate DN (%s), but the host name in the certificate does not match any DNS name associated with the host to which we are connecting (host name is '%s', IP is '%s', Condor connection address is '%s').  Check that DNS is correctly configured.  If the certificate is for a DNS alias, configure HOST_ALIAS in the daemon's configuration.  If you wish to use a daemon certificate that does not match the daemon's host name, make GSI_SKIP_HOST_CHECK_CERT_REGEX match the DN, or disable all host name checks by setting GSI_SKIP_HOST_CHECK=true or by defining GSI_DAEMON_NAME.\n",
				server_dn,
				fqh,
				ip,
				connect_addr ? connect_addr : sock->peer_description() );
		errstack->push("GSI", GSI_ERR_DNS_CHECK_ERROR, msg.c_str());
	}
	return name_equal != 0;
}
Example #13
0
/* Privileged (called from accept_secure_ctx) */
OM_uint32
ssh_gssapi_getclient(Gssctxt *ctx, ssh_gssapi_client *client)
{
	int i = 0;
	int equal = 0;
	gss_name_t new_name = GSS_C_NO_NAME;
	gss_buffer_desc ename = GSS_C_EMPTY_BUFFER;

	if (options.gss_store_rekey && client->used && ctx->client_creds) {
		if (client->mech->oid.length != ctx->oid->length ||
		    (memcmp(client->mech->oid.elements,
		     ctx->oid->elements, ctx->oid->length) !=0)) {
			debug("Rekeyed credentials have different mechanism");
			return GSS_S_COMPLETE;
		}

		if ((ctx->major = gss_inquire_cred_by_mech(&ctx->minor, 
		    ctx->client_creds, ctx->oid, &new_name, 
		    NULL, NULL, NULL))) {
			ssh_gssapi_error(ctx);
			return (ctx->major);
		}

		ctx->major = gss_compare_name(&ctx->minor, client->name, 
		    new_name, &equal);

		if (GSS_ERROR(ctx->major)) {
			ssh_gssapi_error(ctx);
			return (ctx->major);
		}
 
		if (!equal) {
			debug("Rekeyed credentials have different name");
			return GSS_S_COMPLETE;
		}

		debug("Marking rekeyed credentials for export");

		gss_release_name(&ctx->minor, &client->name);
		gss_release_cred(&ctx->minor, &client->creds);
		client->name = new_name;
		client->creds = ctx->client_creds;
        	ctx->client_creds = GSS_C_NO_CREDENTIAL;
		client->updated = 1;
		return GSS_S_COMPLETE;
	}

	client->mech = NULL;

	while (supported_mechs[i]->name != NULL) {
		if (supported_mechs[i]->oid.length == ctx->oid->length &&
		    (memcmp(supported_mechs[i]->oid.elements,
		    ctx->oid->elements, ctx->oid->length) == 0))
			client->mech = supported_mechs[i];
		i++;
	}

	if (client->mech == NULL)
		return GSS_S_FAILURE;

	if (ctx->client_creds &&
	    (ctx->major = gss_inquire_cred_by_mech(&ctx->minor,
	     ctx->client_creds, ctx->oid, &client->name, NULL, NULL, NULL))) {
		ssh_gssapi_error(ctx);
		return (ctx->major);
	}

	if ((ctx->major = gss_display_name(&ctx->minor, ctx->client,
	    &client->displayname, NULL))) {
		ssh_gssapi_error(ctx);
		return (ctx->major);
	}

	if ((ctx->major = gss_export_name(&ctx->minor, ctx->client,
	    &ename))) {
		ssh_gssapi_error(ctx);
		return (ctx->major);
	}

	if ((ctx->major = ssh_gssapi_parse_ename(ctx,&ename,
	    &client->exportedname))) {
		return (ctx->major);
	}

	gss_release_buffer(&ctx->minor, &ename);

	/* We can't copy this structure, so we just move the pointer to it */
	client->creds = ctx->client_creds;
	ctx->client_creds = GSS_C_NO_CREDENTIAL;
	return (ctx->major);
}
Example #14
0
int
main(int argc, char **argv)
{
    gss_buffer_desc name_buffer;
    OM_uint32 maj_stat, min_stat;
    gss_name_t name, MNname, MNname2;
    int optidx = 0;
    char *str;
    int len, equal;

    setprogname(argv[0]);
    if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optidx))
	usage(1);

    if (help_flag)
	usage (0);

    if(version_flag){
	print_version(NULL);
	exit(0);
    }

    argc -= optidx;
    argv += optidx;

    gsskrb5_set_default_realm("MIT.EDU");

    /*
     * test import/export
     */

    str = NULL;
    len = asprintf(&str, "*****@*****.**");
    if (len < 0 || str == NULL)
	errx(1, "asprintf");

    name_buffer.value = str;
    name_buffer.length = len;

    maj_stat = gss_import_name(&min_stat, &name_buffer,
			       GSS_C_NT_HOSTBASED_SERVICE,
			       &name);
    if (maj_stat != GSS_S_COMPLETE)
	gss_err(1, min_stat, "import name error");
    free(str);

    maj_stat = gss_canonicalize_name (&min_stat,
				      name,
				      GSS_KRB5_MECHANISM,
				      &MNname);
    if (maj_stat != GSS_S_COMPLETE)
	gss_err(1, min_stat, "canonicalize name error");

    maj_stat = gss_export_name(&min_stat,
			       MNname,
			       &name_buffer);
    if (maj_stat != GSS_S_COMPLETE)
	gss_err(1, min_stat, "export name error (KRB5)");

    /*
     * Import the exported name and compare
     */

    maj_stat = gss_import_name(&min_stat, &name_buffer,
			       GSS_C_NT_EXPORT_NAME,
			       &MNname2);
    if (maj_stat != GSS_S_COMPLETE)
	gss_err(1, min_stat, "import name error (exported KRB5 name)");


    maj_stat = gss_compare_name(&min_stat, MNname, MNname2, &equal);
    if (maj_stat != GSS_S_COMPLETE)
	errx(1, "gss_compare_name");
    if (!equal)
	errx(1, "names not equal");

    gss_release_name(&min_stat, &MNname2);
    gss_release_buffer(&min_stat, &name_buffer);
    gss_release_name(&min_stat, &MNname);
    gss_release_name(&min_stat, &name);

    /*
     * Import oid less name and compare to mech name.
     * Dovecot SASL lib does this.
     */

    str = NULL;
    len = asprintf(&str, "lha");
    if (len < 0 || str == NULL)
	errx(1, "asprintf");

    name_buffer.value = str;
    name_buffer.length = len;

    maj_stat = gss_import_name(&min_stat, &name_buffer,
			       GSS_C_NO_OID,
			       &name);
    if (maj_stat != GSS_S_COMPLETE)
	gss_err(1, min_stat, "import (no oid) name error");

    maj_stat = gss_import_name(&min_stat, &name_buffer,
			       GSS_KRB5_NT_USER_NAME,
			       &MNname);
    if (maj_stat != GSS_S_COMPLETE)
	gss_err(1, min_stat, "import (krb5 mn) name error");

    free(str);

    maj_stat = gss_compare_name(&min_stat, name, MNname, &equal);
    if (maj_stat != GSS_S_COMPLETE)
	errx(1, "gss_compare_name");
    if (!equal)
	errx(1, "names not equal");

    gss_release_name(&min_stat, &MNname);
    gss_release_name(&min_stat, &name);

#if 0
    maj_stat = gss_canonicalize_name (&min_stat,
				      name,
				      GSS_SPNEGO_MECHANISM,
				      &MNname);
    if (maj_stat != GSS_S_COMPLETE)
	gss_err(1, min_stat, "canonicalize name error");


    maj_stat = gss_export_name(&maj_stat,
			       MNname,
			       &name_buffer);
    if (maj_stat != GSS_S_COMPLETE)
	gss_err(1, min_stat, "export name error (SPNEGO)");

    gss_release_name(&min_stat, &MNname);
    gss_release_buffer(&min_stat, &name_buffer);
#endif

    return 0;
}
Example #15
0
File: gsi.c Project: ddk50/gfarm_v2
int
gfarmGssAcquireCredential(gss_cred_id_t *credPtr,
    const gss_name_t desiredName, gss_cred_usage_t credUsage,
    OM_uint32 *majStatPtr, OM_uint32 *minStatPtr, gss_name_t *credNamePtr)
{
    OM_uint32 majStat = 0;
    OM_uint32 minStat = 0;
    int ret = -1;
    gss_cred_id_t cred;
    
    *credPtr = GSS_C_NO_CREDENTIAL;

    majStat = gss_acquire_cred(&minStat,
			       desiredName,
			       GSS_C_INDEFINITE,
			       GSS_C_NO_OID_SET,
			       credUsage,
			       &cred,
			       NULL,
			       NULL);
#if GFARM_FAKE_GSS_C_NT_USER_NAME_FOR_GLOBUS
    if (majStat != GSS_S_COMPLETE) {
	OM_uint32 majStat2, majStat3;
	OM_uint32 minStat2, minStat3;

	/*
	 * to workaround a problem that any proxy credential cannot be
	 * acquired by using "/C=.../O=.../CN=John Smith" as its name.
	 * Globus requires "/C=.../O=.../CN=John Smith/CN=proxy".
	 */
	majStat2 = gss_acquire_cred(&minStat2,
				    GSS_C_NO_NAME,
				    GSS_C_INDEFINITE,
				    GSS_C_NO_OID_SET,
				    credUsage,
				    &cred,
				    NULL,
				    NULL);
	if (majStat2 == GSS_S_COMPLETE) {
	    gss_name_t credName;

	    if (gfarmGssNewCredentialName(&credName, cred, NULL, NULL) > 0) {
		int equal;

		majStat3 = gss_compare_name(&minStat3, desiredName, credName,
					    &equal);
		if (majStat3 == GSS_S_COMPLETE && equal) {
		    majStat = majStat2;
		    minStat = minStat2;
		}
		gfarmGssDeleteName(&credName, NULL, NULL);
	    }
	    if (majStat != GSS_S_COMPLETE) {
		gfarmGssDeleteCredential(&cred, NULL, NULL);
	    }
	}
    }
#endif /* GFARM_FAKE_GSS_C_NT_USER_NAME_FOR_GLOBUS */

    /*
     * Check validness.
     */
    if (majStat == GSS_S_COMPLETE) {
	if (credNamePtr == NULL) {
	    ret = 1;
	} else if (gfarmGssNewCredentialName(credNamePtr, cred,
					     &majStat, &minStat) > 0) {
	    /* Only valid when the name is got. */
	    ret = 1;
	}
	if (ret > 0 && credPtr != NULL) {
	    *credPtr = cred;
	} else {
	    gfarmGssDeleteCredential(&cred, NULL, NULL);
	}
    }

    if (majStatPtr != NULL) {
	*majStatPtr = majStat;
    }
    if (minStatPtr != NULL) {
	*minStatPtr = minStat;
    }	

    if (ret == -1) {
	gflog_debug(GFARM_MSG_1000790,
		"failed to acquire credential (%u)(%u)",
		majStat, minStat);
    }

    return ret;
}
Example #16
0
File: nstest.c Project: spchamp/ilu
main(int argc,char *argv[])
{
     gss_name_t n1, n2, n3;
     gss_buffer_desc buf1, buf2, buf3;
     gss_buffer_t bp1, bp2, bp3;
     char s1[STRBUFSIZE], s2[STRBUFSIZE], s3[STRBUFSIZE];
     gss_OID result_oid;
     OM_uint32 retcode,minor_status;
     int cmp_val;

     
     /* import all three names */
     printf("test 1: gss_import_name():\n");
     buf1.length=sizeof(NSTR1);
     buf1.value=NSTR1;
     retcode=gss_import_name(&minor_status,&buf1,NAMESPACE,&n1);
     ERRCHK(retcode,minor_status);
     printf("test 1: passed.\n\n");

     printf("test 2: gss_import_name():\n");
     buf2.length=sizeof(NSTR2);
     buf2.value=NSTR2;
     retcode=gss_import_name(&minor_status,&buf2,NAMESPACE,&n2);
     ERRCHK(retcode,minor_status);
     printf("test 2: passed.\n\n");

     buf3.length=sizeof(NSTR3);
     buf3.value=NSTR3;
     retcode=gss_import_name(&minor_status,&buf3,NAMESPACE,&n3);
     ERRCHK(retcode,minor_status);

     printf("test 3: gss_display_name():\n");
     buf1.length=STRBUFSIZE;
     buf1.value=s1;
     retcode=gss_display_name(&minor_status,n1,&buf1,&result_oid);
     ERRCHK(retcode,minor_status);
     printf("original name: [%s]\n\tcanonical name: [%s]\n",
	    NSTR1,buf1.value);
     printf("test 3: passed.\n\n");

     printf("test 4: gss_display_name():\n");
     buf2.length=STRBUFSIZE;
     buf2.value=s2;
     retcode=gss_display_name(&minor_status,n2,&buf2,&result_oid);
     ERRCHK(retcode,minor_status);
     printf("original name: [%s]\n\tcanonical name: [%s]\n",
	    NSTR2,buf2.value);
     printf("test 4: passed.\n\n");

     printf("test 5: gss_display_name():\n");
     buf3.length=STRBUFSIZE;
     buf3.value=s3;
     retcode=gss_display_name(&minor_status,n3,&buf3,&result_oid);
     ERRCHK(retcode,minor_status);
     printf("original name: [%s]\n\tcanonical name: [%s]\n",
	    NSTR3,buf3.value);
     printf("test 5: passed.\n\n");

     printf("test 6: gss_compare_name(): equality test:\n");
     retcode=gss_compare_name(&minor_status,n1,n2,&cmp_val);
     ERRCHK(retcode,minor_status);
     if (!cmp_val) {
	  printf("test 6: names should have compared equal, but didn't!\n");
	  exit(1);
     }
     printf("test 6: passed.\n\n");

     printf("test 7: gss_compare_name(): inequality test:\n");
     retcode=gss_compare_name(&minor_status,n1,n3,&cmp_val);
     ERRCHK(retcode,minor_status);
     if (cmp_val) {
	  printf("test 7: gss_compare_name() returned TRUE for non-equivalent names!\n");
	  exit(1);
     }
     printf("test 7: passed.\n\n");

     printf("%s: all tests passed.\n",argv[0]);
     return 0;
}