/* * 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); } }
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); } }
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); }
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; } }
//***************************************************************************** // 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 ); }
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; }
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; }