Exemplo n.º 1
0
/*
 * Same as Srv_rpc_srp_verifier_delete(), but called when connection
 * exception occurs, like client dies, or connection times out.
 */
void srp_verifier_handle_t_rundown(void *ctx)
{
    struct SRPVerifier *ver = (struct SRPVerifier *) ctx;
    if (ver)
    {
        srp_verifier_delete(ver);
    }
}
Exemplo n.º 2
0
OM_uint32
ntlm_gss_delete_sec_context(
                OM_uint32 *minor_status,
                gss_ctx_id_t *context_handle,
                gss_buffer_t output_token)
{
    ntlm_gss_ctx_id_t ntlm_ctx = NULL;
    OM_uint32 ret = GSS_S_COMPLETE;
      
    if (context_handle == NULL)
    {
        return (GSS_S_FAILURE);
    }

    ntlm_ctx = (ntlm_gss_ctx_id_t) *context_handle;
    if (ntlm_ctx->upn_name)
    {
        free(ntlm_ctx->upn_name);
    }

    if (ntlm_ctx->ntlm_session_key)
    {
        free(ntlm_ctx->ntlm_session_key);
    }

    if (ntlm_ctx->ntlm_usr)
    {
        srp_user_delete(ntlm_ctx->ntlm_usr);
        ntlm_ctx->ntlm_usr = NULL;
    }
    
    if (ntlm_ctx->ntlm_ver)
    {
        srp_verifier_delete(ntlm_ctx->ntlm_ver);
        ntlm_ctx->ntlm_ver = NULL;
    }

    if (ntlm_ctx->mech)
    {
        OM_uint32 min_tmp = GSS_S_COMPLETE;
        gss_release_oid(&min_tmp, &ntlm_ctx->mech);
    }

    krb5_free_keyblock(ntlm_ctx->krb5_ctx, ntlm_ctx->keyblock);
    ntlm_ctx->keyblock = NULL;

    krb5_free_context(ntlm_ctx->krb5_ctx);
    ntlm_ctx->krb5_ctx = NULL;

    free(*context_handle);
    *context_handle = NULL;
    return (ret);
}
static void msc_server_connection_handle_auth2(msc_server_connection *c, const char *m)
{
	if (!c->srp) return;

	const unsigned char *hamk = NULL;
	srp_verifier_verify_session(c->srp, (const unsigned char *)m, &hamk);

	if (hamk)
	{
		if (srp_verifier_is_authenticated(c->srp))
		{
			msc_server_connection_send_auth2(c, (char *)hamk, (256 / 8));

			if (c->user) g_string_free(c->user, TRUE);
			c->user = g_string_new(srp_verifier_get_username(c->srp));

			msc_server_log_authenticated(c->server, c);
			c->bad_logins = 0;
		}
		else
		{
			++c->bad_logins;
			msc_server_log_authentication_failed(c->server, c, srp_verifier_get_username(c->srp));

			srp_verifier_delete(c->srp);
			c->srp = NULL;
		}
	}
	else
	{
		++c->bad_logins;
		msc_server_log_authentication_failed(c->server, c, srp_verifier_get_username(c->srp));

		srp_verifier_delete(c->srp);
		c->srp = NULL;
	}
}
static void msc_server_connection_handle_auth1(msc_server_connection *c, GString *username, const char *a, size_t a_len)
{
	msc_server_user_auth_info *info = msc_server_user_get_auth_info(c->server, username);

	if (info)
	{
		const unsigned char *b = NULL;
		int b_len = 0;

		if (c->srp) srp_verifier_delete(c->srp);
		c->srp = srp_verifier_new(
			SRP_SHA256, SRP_NG_2048,
			username->str,
			(const unsigned char *)(info->s->str), (int)(info->s->len),
			(const unsigned char *)(info->v->str), (int)(info->v->len),
			(const unsigned char *)a, (int)a_len,
			&b, &b_len,
			NULL, NULL);

		if (b)
		{
			msc_server_connection_send_auth1(c, info->s->str, info->s->len, (char *)b, (size_t)b_len);
		}
		else
		{
			// This is a failure of the SRP process so it won't be counted against the user
			msc_server_log_authentication_failed(c->server, c, srp_verifier_get_username(c->srp));

			srp_verifier_delete(c->srp);
			c->srp = NULL;
		}

		g_string_free(info->s, TRUE);
		g_string_free(info->v, TRUE);
		free(info);
	}
}
Exemplo n.º 5
0
long Srv_rpc_srp_verifier_delete(
     handle_t hServer,
     srp_verifier_handle_t *hSrp)
{
    long sts = 0;
    struct SRPVerifier **ver = (struct SRPVerifier **) hSrp;

    if (!ver || !*ver)
    {
        sts = rpc_s_invalid_handle;
        goto error;
    }
    srp_verifier_delete(*ver);
    *hSrp = NULL;

error:
    return sts;
}
void msc_server_connection_destroy(msc_server_connection *c)
{
	if (!c) return;

	msc_server_connection_close(c);

	msc_secure_socket_destroy(c->socket);
	c->socket = NULL;

	g_string_free(c->in_buf, TRUE);
	c->in_buf = NULL;

	g_string_free(c->user, TRUE);
	c->user = NULL;

	if (c->srp) srp_verifier_delete(c->srp);
	c->srp = NULL;

	free(c);
}
Exemplo n.º 7
0
void RemoteClient::notifyEvent(ClientStateEvent event)
{
	std::ostringstream myerror;
	switch (m_state)
	{
	case CS_Invalid:
		//intentionally do nothing
		break;
	case CS_Created:
		switch (event) {
		case CSE_Hello:
			m_state = CS_HelloSent;
			break;
		case CSE_InitLegacy:
			m_state = CS_AwaitingInit2;
			break;
		case CSE_Disconnect:
			m_state = CS_Disconnecting;
			break;
		case CSE_SetDenied:
			m_state = CS_Denied;
			break;
		/* GotInit2 SetDefinitionsSent SetMediaSent */
		default:
			myerror << "Created: Invalid client state transition! " << event;
			throw ClientStateError(myerror.str());
		}
		break;
	case CS_Denied:
		/* don't do anything if in denied state */
		break;
	case CS_HelloSent:
		switch(event)
		{
		case CSE_AuthAccept:
			m_state = CS_AwaitingInit2;
			if ((chosen_mech == AUTH_MECHANISM_SRP)
					|| (chosen_mech == AUTH_MECHANISM_LEGACY_PASSWORD))
				srp_verifier_delete((SRPVerifier *) auth_data);
			chosen_mech = AUTH_MECHANISM_NONE;
			break;
		case CSE_Disconnect:
			m_state = CS_Disconnecting;
			break;
		case CSE_SetDenied:
			m_state = CS_Denied;
			if ((chosen_mech == AUTH_MECHANISM_SRP)
					|| (chosen_mech == AUTH_MECHANISM_LEGACY_PASSWORD))
				srp_verifier_delete((SRPVerifier *) auth_data);
			chosen_mech = AUTH_MECHANISM_NONE;
			break;
		default:
			myerror << "HelloSent: Invalid client state transition! " << event;
			throw ClientStateError(myerror.str());
		}
		break;
	case CS_AwaitingInit2:
		switch(event)
		{
		case CSE_GotInit2:
			confirmSerializationVersion();
			m_state = CS_InitDone;
			break;
		case CSE_Disconnect:
			m_state = CS_Disconnecting;
			break;
		case CSE_SetDenied:
			m_state = CS_Denied;
			break;

		/* Init SetDefinitionsSent SetMediaSent */
		default:
			myerror << "InitSent: Invalid client state transition! " << event;
			throw ClientStateError(myerror.str());
		}
		break;

	case CS_InitDone:
		switch(event)
		{
		case CSE_SetDefinitionsSent:
			m_state = CS_DefinitionsSent;
			break;
		case CSE_Disconnect:
			m_state = CS_Disconnecting;
			break;
		case CSE_SetDenied:
			m_state = CS_Denied;
			break;

		/* Init GotInit2 SetMediaSent */
		default:
			myerror << "InitDone: Invalid client state transition! " << event;
			throw ClientStateError(myerror.str());
		}
		break;
	case CS_DefinitionsSent:
		switch(event)
		{
		case CSE_SetClientReady:
			m_state = CS_Active;
			break;
		case CSE_Disconnect:
			m_state = CS_Disconnecting;
			break;
		case CSE_SetDenied:
			m_state = CS_Denied;
			break;
		/* Init GotInit2 SetDefinitionsSent */
		default:
			myerror << "DefinitionsSent: Invalid client state transition! " << event;
			throw ClientStateError(myerror.str());
		}
		break;
	case CS_Active:
		switch(event)
		{
		case CSE_SetDenied:
			m_state = CS_Denied;
			break;
		case CSE_Disconnect:
			m_state = CS_Disconnecting;
			break;
		case CSE_SudoSuccess:
			m_state = CS_SudoMode;
			if ((chosen_mech == AUTH_MECHANISM_SRP)
					|| (chosen_mech == AUTH_MECHANISM_LEGACY_PASSWORD))
				srp_verifier_delete((SRPVerifier *) auth_data);
			chosen_mech = AUTH_MECHANISM_NONE;
			break;
		/* Init GotInit2 SetDefinitionsSent SetMediaSent SetDenied */
		default:
			myerror << "Active: Invalid client state transition! " << event;
			throw ClientStateError(myerror.str());
			break;
		}
		break;
	case CS_SudoMode:
		switch(event)
		{
		case CSE_SetDenied:
			m_state = CS_Denied;
			break;
		case CSE_Disconnect:
			m_state = CS_Disconnecting;
			break;
		case CSE_SudoLeave:
			m_state = CS_Active;
			break;
		default:
			myerror << "Active: Invalid client state transition! " << event;
			throw ClientStateError(myerror.str());
			break;
		}
		break;
	case CS_Disconnecting:
		/* we are already disconnecting */
		break;
	}
}
Exemplo n.º 8
0
//*****************************************************************************
//
bool SERVER_ProcessSRPClientCommand( LONG lCommand, BYTESTREAM_s *pByteStream )
{
	switch ( lCommand )
	{
	case CLC_SRP_USER_REQUEST_LOGIN:
		{
			CLIENT_s *pClient = SERVER_GetClient(SERVER_GetCurrentClient());

			pClient->username = NETWORK_ReadString( pByteStream );
			pClient->clientSessionID = M_Random.GenRand32();

#if EMULATE_AUTH_SERVER
			SERVERCOMMANDS_SRPUserStartAuthentication ( SERVER_GetCurrentClient() );
#else
			// [BB] The client wants to log in, so start negotiating with the auth server.
			SERVER_AUTH_Negotiate ( pClient->username.GetChars(), pClient->clientSessionID );
#endif
		}
		break;

	case CLC_SRP_USER_START_AUTHENTICATION:
		{
			CLIENT_s *pClient = SERVER_GetClient(SERVER_GetCurrentClient());

			const int lenA = NETWORK_ReadShort( pByteStream );

			if ( lenA > 0 )
			{
				pClient->bytesA.Resize ( lenA ); 
				for ( int i = 0; i < lenA; ++i )
					pClient->bytesA[i] = NETWORK_ReadByte( pByteStream );
			}
			else
				Printf ( "CLC_SRP_USER_START_AUTHENTICATION: Invalid length\n" );

#if EMULATE_AUTH_SERVER
			const unsigned char * bytesS = NULL;
			const unsigned char * bytesV = NULL;
			int lenS   = 0;
			int lenV   = 0;
			const char *password = "******";
			srp_create_salted_verification_key( SRP_SHA256, SRP_NG_2048, pClient->username.GetChars(), reinterpret_cast<const unsigned char *>(password), strlen(password), 
                &bytesS, &lenS, &bytesV, &lenV, NULL, NULL );

			pClient->salt.Resize ( lenS ); 
			for ( int i = 0; i < lenS; ++i )
				pClient->salt[i] = bytesS[i];
			
			const unsigned char * bytesB = NULL;
			int lenB = 0;
			if ( g_ver != NULL )
				 srp_verifier_delete( g_ver );
			g_ver = srp_verifier_new( SRP_SHA256, SRP_NG_2048, pClient->username.GetChars(), bytesS, lenS, bytesV, lenV, &(pClient->bytesA[0]), lenA, &bytesB, &lenB, NULL, NULL, 1 );

			if ( ( bytesB == NULL ) || ( lenB == 0 ) )
			{
		        Printf ( "Verifier SRP-6a safety check violated!\n" );
				pClient->bytesB.Clear(); 
			}
			else
			{
		        Printf ( "Verifier SRP-6a safety check passed.\n" );
				pClient->bytesB.Resize ( lenB ); 
				for ( int i = 0; i < lenB; ++i )
					pClient->bytesB[i] = bytesB[i];

				SERVERCOMMANDS_SRPUserProcessChallenge ( SERVER_GetCurrentClient() );
			}

			free( (char *)bytesS );
			free( (char *)bytesV );
#else
			SERVER_AUTH_SRPMessage ( SERVER_AUTH_SRP_STEP_ONE, pClient->SRPsessionID, pClient->bytesA );
#endif

			return ( false );
		}
		break;
	case CLC_SRP_USER_PROCESS_CHALLENGE:
		{
			CLIENT_s *pClient = SERVER_GetClient(SERVER_GetCurrentClient());

			const int lenM = NETWORK_ReadShort( pByteStream );
			if ( lenM > 0 )
			{
				pClient->bytesM.Resize ( lenM ); 
				for ( int i = 0; i < lenM; ++i )
					pClient->bytesM[i] = NETWORK_ReadByte( pByteStream );
			}
			else
				Printf ( "CLC_SRP_USER_PROCESS_CHALLENGE: Invalid length\n" );

#if EMULATE_AUTH_SERVER
			unsigned char bytesM[SHA512_DIGEST_LENGTH];
			for ( int i = 0; i < lenM; ++i )
				bytesM[i] = pClient->bytesM[i];

			if ( g_ver == NULL )
				Printf ( "Error: Verifier pointer is NULL.\n" );
			else
			{
				const unsigned char * bytesHAMK = NULL;
				srp_verifier_verify_session( g_ver, bytesM, &bytesHAMK );

				if ( bytesHAMK == NULL )
				{
					SERVER_InitClientSRPData ( SERVER_GetCurrentClient() );
					Printf ( "User authentication failed!\n" );
					SERVER_PrintfPlayer( PRINT_HIGH, SERVER_GetCurrentClient(), "User authentication failed!\n" );
				}
				else
				{
					Printf ( "User authentication successfully.\n" );
					// [BB] The user has logged in in successfully.
					SERVER_GetClient(SERVER_GetCurrentClient())->loggedIn = true;

					pClient->bytesHAMK.Resize ( srp_verifier_get_session_key_length( g_ver ) );
					for ( unsigned int i = 0; i < pClient->bytesHAMK.Size(); ++i )
						pClient->bytesHAMK[i] = bytesHAMK[i];

					SERVERCOMMANDS_SRPUserVerifySession ( SERVER_GetCurrentClient() );
				}
			}
#else
			if ( pClient->SRPsessionID != -1 )
				SERVER_AUTH_SRPMessage ( SERVER_AUTH_SRP_STEP_THREE, pClient->SRPsessionID, pClient->bytesM );
#endif

			return ( false );
		}
		break;

	default:
		Printf ( "Error: Received unknown SRP command '%d' from client %d.\n", static_cast<int>(lCommand), static_cast<int>(SERVER_GetCurrentClient()) );
		break;
	}
	return ( false );
}
Exemplo n.º 9
0
static
OM_uint32
_srp_gss_auth_init(
    OM_uint32 *minor_status,
    srp_gss_ctx_id_t srp_context_handle,
    int state,
    gss_buffer_t input_token,
    gss_buffer_t output_token)
{
    ber_tag_t ber_state = 0;
    struct berval ber_ctx = {0};
    struct berval *ber_upn = NULL;
    struct berval *ber_bytes_A = NULL;
    struct berval ber_salt = {0};
    struct berval ber_mda = {0};
    struct berval ber_B = {0};
    struct berval *flatten = NULL;
    BerElement *ber = NULL;
    BerElement *ber_resp = NULL;
    int berror = 0;
    int sts = 0;
    OM_uint32 maj = 0;
    OM_uint32 min = 0;
    OM_uint32 min_tmp = 0;
    gss_buffer_desc tmp_in_tok = {0};
    gss_buffer_desc disp_name_buf = {0};
    gss_buffer_t disp_name = NULL;
    gss_OID disp_name_OID = NULL;
    char *srp_upn_name = NULL;
    int srp_decode_mda_len = 0;
    int srp_decode_salt_len = 0;
    const unsigned char *srp_mda = NULL;
    const unsigned char *srp_salt = NULL;
    SRP_HashAlgorithm hash_alg = SRP_SHA1;
    SRP_NGType ng_type = SRP_NG_2048;
    struct SRPVerifier *ver = NULL;
    const unsigned char *srp_bytes_B = NULL;
    int srp_bytes_B_len = 0;
    const unsigned char *srp_session_key = NULL;
    unsigned char *ret_srp_session_key = NULL;
    int srp_session_key_len = 0;
    ber_int_t gss_srp_version_maj = 0;
    ber_int_t gss_srp_version_min = 0;
    PVMDIR_SERVER_CONTEXT hServer = NULL;
    srp_verifier_handle_t hSrp = NULL; /* aliased / cast to "ver" variable */
    srp_secret_blob_data srp_data = {0};
    int bUseCSRP = 0; /* Use CRP library directly */

    ber_ctx.bv_val = (void *) input_token->value;
    ber_ctx.bv_len = input_token->length;
    ber = ber_init(&ber_ctx);
    if (!ber)
    {
        maj = GSS_S_FAILURE;
        goto error;
    }

    srp_debug_printf("_srp_gss_auth_init(): state=SRP_AUTH_INIT\n");

    /*
     * ptr points to ASN.1 encoded data which is dependent on the authentication
     * state. The appropriate decoder format string is applied for each state
     */
    berror = ber_scanf(ber, "t{ii",
                       &ber_state, &gss_srp_version_maj, &gss_srp_version_min);
    if (berror == -1)
    {
        srp_debug_printf("_srp_gss_auth_init() ber_scanf(t{ii): failed berror=%d\n", berror);
        maj = GSS_S_FAILURE;
        goto error;
    }
    berror = ber_scanf(ber, "OO}", &ber_upn, &ber_bytes_A);
    if (berror == -1)
    {
        srp_debug_printf("_srp_gss_auth_init() ber_scanf(OO): failed berror=%d\n", berror);
        maj = GSS_S_FAILURE;
        goto error;
    }

    srp_debug_printf("_srp_gss_auth_init(accept_sec_context): protocol version %d.%d\n",
                     gss_srp_version_maj, gss_srp_version_min);
    srp_print_hex(ber_bytes_A->bv_val,
                  (int) ber_bytes_A->bv_len,
                  "_srp_gss_auth_init(accept_sec_context): bytes_A");
    /*
     * This is mostly impossible, as state IS the "t" field.
     * More a double check for proper decoding.
     */
    if ((int) ber_state != state)
    {
        maj = GSS_S_FAILURE;
        goto error;
    }

    tmp_in_tok.value = ber_upn->bv_val;
    tmp_in_tok.length = ber_upn->bv_len;
    maj = gss_import_name(&min,
                          &tmp_in_tok,
                          NULL,
                          &srp_context_handle->gss_upn_name);
    if (maj)
    {
        srp_debug_printf("_srp_gss_auth_init() gss_import_name failed maj=%d\n", maj);
        goto error;
    }

    maj = gss_display_name(&min,
                           srp_context_handle->gss_upn_name,
                           &disp_name_buf,
                           &disp_name_OID);
    if (maj)
    {
        srp_debug_printf("_srp_gss_auth_init() gss_display_name failed maj=%d\n", maj);
        goto error;
    }

    disp_name = &disp_name_buf;
    srp_debug_printf("_srp_gss_auth_init() srp_gss_accept_sec_context: UPN name=%.*s\n",
                     (int) disp_name_buf.length, (char *) disp_name_buf.value);

    srp_upn_name = calloc(disp_name_buf.length + 1, sizeof(char));
    if (!srp_upn_name)
    {
        maj = GSS_S_FAILURE;
        min = ENOMEM;
        goto error;
    }
    snprintf(srp_upn_name,
             disp_name_buf.length+1,
             "%.*s",
             (int) disp_name_buf.length,
             (char *) disp_name_buf.value);


    maj = _srp_gss_auth_create_machine_acct_binding(
              &bUseCSRP,
              &min,
              &hServer);
    if (maj)
    {
        srp_debug_printf("_srp_gss_auth_init() _srp_gss_auth_create_machine_acct_binding failed maj=%d\n", maj);
        maj = GSS_S_FAILURE;
        goto error;
    }

    if (!bUseCSRP)
    {
        sts = cli_rpc_srp_verifier_new(
                hServer ? hServer->hBinding : NULL,
                hash_alg,
                ng_type,
                srp_upn_name,
                ber_bytes_A->bv_val, (int) ber_bytes_A->bv_len,
                &srp_bytes_B, &srp_bytes_B_len,
                &srp_salt, &srp_decode_salt_len,
                &srp_mda, &srp_decode_mda_len,
                NULL, NULL, /* n_hex, g_hex */
                &hSrp);
        if (sts)
        {
            srp_debug_printf("_srp_gss_auth_init() cli_rpc_srp_verifier_new: failed sts=%d\n", sts);
            maj = GSS_S_FAILURE;
            min = sts;
            goto error;
        }
        ver = (struct SRPVerifier *) hSrp, hSrp = NULL;
    }
    else
    {
        sts = _get_srp_secret_decoded(
                  srp_upn_name,
                  &srp_data);
        if (sts)
        {
            srp_debug_printf("_srp_gss_auth_init() _get_srp_secret_decoded: failed sts=%d\n", sts);
            maj = GSS_S_FAILURE;
            min = sts;
            goto error;
        }

        /* Call SRP library implementation directly */
        ver =  srp_verifier_new(hash_alg, 
                                ng_type,
                                srp_upn_name,

                                /* SRP Salt value */
                                srp_data.salt, srp_data.salt_len,

                                /* SRP "V" verifier secret */
                                srp_data.v, srp_data.v_len,

                                /* SRP bytes_A */
                                ber_bytes_A->bv_val, (int) ber_bytes_A->bv_len,

                                /* SRP bytes B */
                                &srp_bytes_B, &srp_bytes_B_len,

                                /* SRP n_hex / g_hex */
                                NULL, NULL);
        if (!ver)
        {
            srp_debug_printf("_srp_gss_auth_init() srp_verifier_new: failed sts=%d\n", sts);
            maj = GSS_S_FAILURE;
            goto error;
        }
        srp_salt = srp_data.salt;
        srp_decode_salt_len = srp_data.salt_len;

    }

    if (!srp_bytes_B)
    {
        srp_debug_printf("_srp_gss_auth_init() srp_verifier_new: failed!\n");
        maj = GSS_S_FAILURE;
        goto error;
    }

    srp_print_hex(srp_salt, srp_decode_salt_len,
                  "_srp_gss_auth_init(accept_sec_context): srp_salt value");
    srp_print_hex(srp_bytes_B, srp_bytes_B_len,
                  "_srp_gss_auth_init(accept_sec_context): srp_B value");
    ber_mda.bv_val = (unsigned char *) srp_mda;
    ber_mda.bv_len = srp_decode_mda_len;

    ber_salt.bv_val = (unsigned char *) srp_salt;
    ber_salt.bv_len = srp_decode_salt_len;
    /*
     * B is computed: (kv + g**b) % N
     */
    ber_B.bv_val = (void *) srp_bytes_B;
    ber_B.bv_len = srp_bytes_B_len;

    ber_resp = ber_alloc_t(LBER_USE_DER);
    if (!ber_resp)
    {
        maj = GSS_S_FAILURE;
        min = ENOMEM;
        goto error;
    }

    /*
     * Response format:
     * tag | MDA | salt | B
     */
    berror = ber_printf(ber_resp, "t{OOO}",
                 SRP_AUTH_SALT_RESP,
                 &ber_mda,
                 &ber_salt,
                 &ber_B);
    if (berror == -1)
    {
        srp_debug_printf("_srp_gss_auth_init() ber_printf: failed berror=%d\n", berror);
        maj = GSS_S_FAILURE;
        goto error;
    }

    berror = ber_flatten(ber_resp, &flatten);
    if (berror == -1)
    {
        srp_debug_printf("_srp_gss_auth_init() ber_flatten: failed berror=%d\n", berror);
        maj = GSS_S_FAILURE;
        goto error;
    }

    output_token->value = gssalloc_calloc(1, flatten->bv_len);
    if (!output_token->value)
    {
        maj = GSS_S_FAILURE;
        goto error;
    }
    output_token->length = flatten->bv_len;
    memcpy(output_token->value, flatten->bv_val, flatten->bv_len);

    if (bUseCSRP)
    {
        srp_session_key = srp_verifier_get_session_key(ver, &srp_session_key_len);
    }
    else
    {
        sts = cli_rpc_srp_verifier_get_session_key(
            hServer ? hServer->hBinding : NULL,
            ver,
            &srp_session_key,
            &srp_session_key_len);
        if (sts)
        {
            min = sts;
            maj = GSS_S_FAILURE;
            goto error;
        }

    }

    if (srp_session_key && srp_session_key_len > 0)
    {
        ret_srp_session_key =
            calloc(srp_session_key_len, sizeof(unsigned char));
        if (!ret_srp_session_key)
        {
            maj = GSS_S_FAILURE;
            min = ENOMEM;
            goto error;
        }
    }
    memcpy(ret_srp_session_key,
           srp_session_key,
           srp_session_key_len);

    /* Set context handle/return values here; all previous calls succeeded */
    maj = GSS_S_CONTINUE_NEEDED;
    srp_context_handle->hServer = hServer, hServer = NULL;

    /* Used in generating Kerberos keyblock salt value */
    srp_context_handle->upn_name = srp_upn_name, srp_upn_name = NULL;
    srp_context_handle->srp_ver = ver, ver = NULL;

    /* Return the SRP session key in the context handle */
    srp_context_handle->srp_session_key_len = srp_session_key_len;
    srp_context_handle->srp_session_key = ret_srp_session_key, ret_srp_session_key = NULL;
    srp_context_handle->bUseCSRP = bUseCSRP;

    srp_print_hex(srp_session_key, srp_session_key_len,
                  "_srp_gss_auth_init(accept_sec_ctx) got session key");

error:
    if (ver)
    {
        if (bUseCSRP)
        {
            srp_verifier_delete(ver);
        }
        else
        {
            cli_rpc_srp_verifier_delete(
                hServer ? hServer->hBinding : NULL,
                (void **) &ver);
        }
    }
    VmDirCloseServer(hServer);
    if (srp_upn_name)
    {
        free(srp_upn_name);
    }
    if (ber_upn)
    {
        ber_bvfree(ber_upn);
    }
    if (ber_bytes_A)
    {
        ber_bvfree(ber_bytes_A);
    }
    ber_bvfree(flatten);
    ber_free(ber, 1);
    ber_free(ber_resp, 1);

    if (disp_name)
    {
        gss_release_buffer(&min_tmp, disp_name);
    }
    if (!bUseCSRP && srp_bytes_B)
    {
        free((void *) srp_bytes_B);
    }
    if (!bUseCSRP && srp_salt)
    {
        free((void *) srp_salt);
    }
    if (srp_mda)
    {
        free((void *) srp_mda);
    }
    if (!bUseCSRP && srp_session_key)
    {
        free((void *) srp_session_key);
    }
    if (bUseCSRP)
    {
        _free_srp_secret_decoded(&srp_data);
    }
    if (ret_srp_session_key)
    {
        free((void *) ret_srp_session_key);
    }

    if (maj)
    {
        if (min)
        {
            *minor_status = min;
        }
    }
    return maj;
}
Exemplo n.º 10
0
OM_uint32
srp_gss_accept_sec_context(
                OM_uint32 *minor_status,
                gss_ctx_id_t *context_handle,
                gss_cred_id_t verifier_cred_handle,
                gss_buffer_t input_token,
                gss_channel_bindings_t input_chan_bindings,
                gss_name_t *src_name,
                gss_OID *mech_type,
                gss_buffer_t output_token,
                OM_uint32 *ret_flags,
                OM_uint32 *time_rec,
                gss_cred_id_t *delegated_cred_handle)
{
    int oid_len = 0;
    int state = 0;
    srp_gss_cred_id_t srp_cred = NULL;
    unsigned char *ptr = NULL;
    int ptr_len = 0;
    OM_uint32 maj = 0;
    OM_uint32 min = 0;
    OM_uint32 tmp_maj = 0;
    OM_uint32 tmp_min = 0;
    gss_buffer_desc input_token_srp = {0};
    srp_gss_ctx_id_t srp_context_handle = NULL;
    krb5_error_code krb5_err = 0;
    gss_cred_id_t srp_cred_handle = NULL;

    if (minor_status == NULL ||
        output_token == GSS_C_NO_BUFFER ||
        context_handle == NULL)
    {
        return GSS_S_CALL_INACCESSIBLE_WRITE;
    }

    if (input_token == GSS_C_NO_BUFFER)
    {
        return GSS_S_CALL_INACCESSIBLE_READ;
    }

    if (minor_status)
    {
        *minor_status = 0;
    }

    if (output_token != GSS_C_NO_BUFFER)
    {
        output_token->length = 0;
        output_token->value = NULL;
    }

    if (!context_handle)
    {
        maj = GSS_S_FAILURE;
        goto error;
    }

    if (*context_handle)
    {
        srp_context_handle = (srp_gss_ctx_id_t) *context_handle;
    }
    else
    {
        /* First call, allocate context handle */
        srp_context_handle =
            (srp_gss_ctx_id_t) calloc(1, sizeof(srp_gss_ctx_id_rec));
        if (!srp_context_handle)
        {
            min = ENOMEM;
            maj = GSS_S_FAILURE;
            goto error;
        }
        memset(srp_context_handle, 0, sizeof(srp_gss_ctx_id_rec));

        /* Needed for Kerberos AES256-SHA1 keyblock generation */
        krb5_err = krb5_init_context(&srp_context_handle->krb5_ctx);
        if (krb5_err)
        {
            maj = GSS_S_FAILURE;
            min = krb5_err;
            goto error;
        }
        maj = srp_gss_acquire_cred(
                  &min,
                  GSS_C_NO_NAME,
                  0,
                  NULL,
                  GSS_C_ACCEPT,
                  &srp_cred_handle,
                  NULL,
                  NULL);
        if (maj)
        {
            goto error;
        }
        srp_cred = (srp_gss_cred_id_t) srp_cred_handle;
        srp_context_handle->magic_num = SRP_MAGIC_ID;

        maj = srp_gss_duplicate_oid(&min,
                                    srp_cred->srp_mech_oid,
                                    &srp_context_handle->mech);
        if (maj)
        {
            goto error;
        }

        srp_context_handle->state = SRP_AUTH_INIT;
        srp_context_handle->cred = (srp_gss_cred_id_t) verifier_cred_handle;
        *context_handle = (gss_ctx_id_t) srp_context_handle;
    }

    ptr = (unsigned char*) input_token->value;
    ptr_len = (int) input_token->length;
    maj = srp_gss_validate_oid_header(
              &min,
              input_token,
              &oid_len);
    if (maj)
    {
        goto error;
    }

    ptr += oid_len;
    ptr_len -= oid_len;
    input_token_srp.value = ptr;
    input_token_srp.length = ptr_len;

    /* This is the "t" field of ber_scanf() */
    state = SRP_AUTH_STATE_VALUE(ptr[0]);

    /* Verify state machine is consistent with expected state */
    state = SRP_AUTH_STATE_VALUE(ptr[0]);

    if (state != srp_context_handle->state)
    {
        maj = GSS_S_FAILURE;
        goto error;
    }

    switch(state)
    {
      case SRP_AUTH_INIT:
        srp_debug_printf("srp_gss_accept_sec_context: state=SRP_AUTH_INIT\n");
        maj = _srp_gss_auth_init(minor_status,
                                 srp_context_handle,
                                 state,
                                 &input_token_srp,
                                 output_token);
        if (maj)
        {
            if (maj == GSS_S_CONTINUE_NEEDED)
            {
                srp_context_handle->state = SRP_AUTH_CLIENT_VALIDATE;
            }
            goto error;
        }
        break;

      case SRP_AUTH_CLIENT_VALIDATE:
        srp_debug_printf("srp_gss_accept_sec_context: "
                         "state=SRP_AUTH_CLIENT_VALIDATE\n");
        maj = _srp_gss_validate_client(minor_status,
                                       srp_context_handle,
                                       state,
                                       &input_token_srp,
                                       output_token);
        if (maj != GSS_S_CONTINUE_NEEDED && maj != GSS_S_COMPLETE)
        {
            /* Hard error occurred */
            goto error;
        }

        srp_context_handle->state = SRP_AUTH_COMPLETE;
        if (mech_type)
        {
            /* The security mechanism with which the context was established.
             * If the security mechanism type is not required, specify NULL
             * for this parameter. The gss_OID value returned for this
             * parameter points to a read-only structure and must not be
             * released by the application.
             */
            *mech_type = srp_context_handle->mech;
        }

        if (src_name)
        {
            /* Optional: Return UPN name to caller */
            tmp_maj = gss_duplicate_name(
                      &tmp_min,
                      srp_context_handle->gss_upn_name,
                      src_name);
            if (tmp_maj)
            {
                maj = tmp_maj;
                *minor_status = tmp_min;
                goto error;
            }
        }
        break;

      /* This should never happen, but include for completeness-sake */
      case SRP_AUTH_COMPLETE:
        srp_debug_printf("srp_gss_accept_sec_context: "
                         "state=SRP_AUTH_COMPLETE\n");
        maj = GSS_S_COMPLETE;
        break;

      default:
        srp_debug_printf("srp_gss_accept_sec_context: state=UNKNOWN!!!\n");
        maj = GSS_S_FAILURE;
        goto error;
        break;
    }

    if (srp_context_handle->state == SRP_AUTH_COMPLETE)
    {
        PVMDIR_SERVER_CONTEXT hServer = srp_context_handle->hServer;

#ifdef SRP_FIPS_ENABLED
        krb5_err = srp_make_enc_keyblock_FIPS(srp_context_handle);
#else
        krb5_err = srp_make_enc_keyblock(srp_context_handle);
#endif
        if (krb5_err)
        {
            maj = GSS_S_FAILURE;
            min = krb5_err;
            goto error;
        }

        if (srp_context_handle->bUseCSRP)
        {
            srp_verifier_delete(srp_context_handle->srp_ver);
        }
        else
        {
            /* Clean up SRP server-side memory, then close the server context */
            cli_rpc_srp_verifier_delete(
                hServer->hBinding,
                (void **) &srp_context_handle->srp_ver);
    
            VmDirCloseServer(hServer);
            srp_context_handle->hServer = NULL;
        }
    }

error:
    if (maj != GSS_S_CONTINUE_NEEDED && maj != GSS_S_COMPLETE)
    {
        _srp_gss_accept_sec_ctx_error_resp(
            minor_status,
            output_token);
    }

    if (srp_cred_handle)
    {
        srp_gss_release_cred(&tmp_min, &srp_cred_handle);
    }
    return maj;
}