long Srv_rpc_srp_verifier_new( handle_t hServer, long alg, long ng_type, char *username, rpc_p_srp_bytes_container bytes_A, rpc_p_srp_bytes_container *ret_B_value, rpc_p_srp_bytes_container *ret_bytes_s, rpc_p_srp_bytes_container *ret_MDA_value, char *n_hex, char *g_hex, srp_verifier_handle_t *hSrp) { long sts = 0; srp_secret_blob_data srp_data = {0}; const char *srp_bytes_B = NULL; int srp_bytes_B_len = 0; struct SRPVerifier *ver = NULL; rpc_p_srp_bytes_container B_value = NULL; rpc_p_srp_bytes_container bytes_s = NULL; rpc_p_srp_bytes_container MDA_value = NULL; /* SRP "V" secret comes from VmDirSRPGetIdentityData() local call */ sts = _get_srp_secret_decoded( username, &srp_data); if (sts) { goto error; } /* * Create response token. This contains (s, B) for I */ ver = srp_verifier_new(alg, ng_type, username, srp_data.salt, (int) srp_data.salt_len, srp_data.v, (int) srp_data.v_len, bytes_A->bytes_B, (int) bytes_A->len_B, &srp_bytes_B, &srp_bytes_B_len, NULL, /* n_hex, */ NULL); /* g_hex */ if (!ver || !srp_bytes_B) { sts = rpc_s_no_memory; goto error; } sts = _srp_bytes_container_allocate(srp_bytes_B, srp_bytes_B_len, &B_value); if (sts) { goto error; } sts = _srp_bytes_container_allocate(srp_data.salt, srp_data.salt_len, &bytes_s); if (sts) { goto error; } sts = _srp_bytes_container_allocate(srp_data.mda, srp_data.mda_len, &MDA_value); if (sts) { goto error; } *ret_B_value = B_value; *ret_bytes_s = bytes_s; *ret_MDA_value = MDA_value; *hSrp = (srp_verifier_handle_t) ver; error: if (sts) { _srp_bytes_container_free(B_value); _srp_bytes_container_free(bytes_s); _srp_bytes_container_free(MDA_value); } _free_srp_secret_decoded(&srp_data); return sts; }
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; }