int srp_decrypt_aes256_hmac_sha1( srp_gss_ctx_id_t srp_context_handle, unsigned char *in_hmacbuf, int in_hmacbuf_len, unsigned char *in_ciphertext, int in_ciphertext_len, unsigned char *ret_plaintext) { int sts = 0; unsigned char *cipherhmac_buf = NULL; unsigned char *plaintext = NULL; unsigned char *ciphertext_start = NULL; int cipherhmac_buf_len = 0; int ciphertext_len = 0; int hmac_computed_len = 0; unsigned char hmac[SRP_SHA1_HMAC_BUFSIZ] = {0}; unsigned char hmac_computed[SRP_SHA1_HMAC_BUFSIZ] = {0}; /* Splice in_hmacbuf + in_ciphertext together, this is the ciphertext */ cipherhmac_buf_len = in_hmacbuf_len + in_ciphertext_len; /* Buffer must adhere to AES-256 padding requirements */ ciphertext_len = AES256PAD((cipherhmac_buf_len - SRP_SHA1_HMAC_BUFSIZ)); cipherhmac_buf = (unsigned char *) calloc(cipherhmac_buf_len, sizeof(unsigned char)); if (!cipherhmac_buf) { sts = ENOMEM; goto error; } plaintext = (unsigned char *) calloc(ciphertext_len, sizeof(unsigned char)); if (!plaintext ) { sts = ENOMEM; goto error; } memcpy(cipherhmac_buf, in_hmacbuf, in_hmacbuf_len); memcpy(cipherhmac_buf + in_hmacbuf_len, in_ciphertext, in_ciphertext_len); /* Save the HMAC-SHA1 verifier from client */ memcpy(hmac, cipherhmac_buf, SRP_SHA1_HMAC_BUFSIZ); srp_print_hex(hmac, SRP_SHA1_HMAC_BUFSIZ, "srp_decrypt_aes256_hmac_sha1: client hmac"); /* Perform hmac-sha validation over the ciphertext */ ciphertext_start = cipherhmac_buf + SRP_SHA1_HMAC_BUFSIZ; if (!srp_compute_hmac( srp_context_handle->hmac_ctx, ciphertext_start, ciphertext_len, hmac_computed, &hmac_computed_len)) { sts = EINVAL; goto error; } /* Verify computed verifier matches client verifier */ if (hmac_computed_len != SRP_SHA1_HMAC_BUFSIZ || memcmp(hmac, hmac_computed, hmac_computed_len) != 0) { srp_print_hex(hmac_computed, SRP_SHA1_HMAC_BUFSIZ, "srp_decrypt_aes256_hmac_sha1: ERROR computed hmac"); /* verifier failed, return error */ sts = GSS_S_DEFECTIVE_TOKEN; goto error; } /* This is the full ciphertext, which can then be decrypted. */ AES_cbc_encrypt(ciphertext_start, plaintext, ciphertext_len, &srp_context_handle->aes_decrypt_key, srp_context_handle->aes_decrypt_iv, AES_DECRYPT); memcpy(ret_plaintext, plaintext, ciphertext_len); error: if (plaintext) { free(plaintext); } if (cipherhmac_buf) { free(cipherhmac_buf); } return sts; }
int srp_encrypt_aes256_hmac_sha1( srp_gss_ctx_id_t srp_context_handle, unsigned char *plaintext, int plaintext_len, unsigned char *out_ciphertext, unsigned char **out_hmacbuf, int *out_hmacbuf_len) { int sts = 0; int hmacbuf_len = 0; int hmac_bufpad_len = 0; int ciphertext_len = 0; int ciphertext_pad_len = 0; int verifier_len = 0; unsigned char *hmacbuf = NULL; unsigned char *hmacbuf_end = NULL; unsigned char *ciphertext = NULL; unsigned char *ret_hmacbuf = NULL; /* * Message format: * ciphertext = AES256(key, plaintext) * |-- HMAC-SHA1(ciphertext) (20) --|-- ciphertext --|) * * Result: * Contiguous ciphertext buffer is split into two pieces across * iov, as iov[1] cannot be resized, but iov[0] can. * * iov[0] data: |-- AES256 (verifier-len) --| * iov[1] data: |-- AES256 (plaintext-len) --| */ ciphertext_pad_len = AES256PAD(plaintext_len); /* * Note: The below padding may cause buffer expansion which cannot fit into * the original iov[1] payload buffer. The "residual data" from this * expansion is returned in iov[0], semantically the hmac verifier. */ hmac_bufpad_len = ciphertext_pad_len + SRP_SHA1_HMAC_BUFSIZ; hmacbuf = (unsigned char *) calloc(hmac_bufpad_len, sizeof(unsigned char)); if (!hmacbuf) { sts = ENOMEM; goto error; } hmacbuf_end = hmacbuf; /* Same size as the input buffer; holds the output cipher text */ ciphertext_len = ciphertext_pad_len; ciphertext = (unsigned char *) calloc(ciphertext_len, sizeof(unsigned char)); if (!ciphertext) { sts = ENOMEM; goto error; } /* AES256 encrypt the plaintext payload data */ AES_cbc_encrypt( plaintext, ciphertext, ciphertext_len, &srp_context_handle->aes_encrypt_key, srp_context_handle->aes_encrypt_iv, AES_ENCRYPT); /* Perform hmac-sha validation over ciphertext payload */ if (!srp_compute_hmac( srp_context_handle->hmac_ctx, ciphertext, ciphertext_len, hmacbuf, &hmacbuf_len)) { sts = EINVAL; goto error; } if (hmacbuf_len > SRP_SHA1_HMAC_BUFSIZ) { hmacbuf_len = SRP_SHA1_HMAC_BUFSIZ; } hmacbuf_end += hmacbuf_len; srp_print_hex(hmacbuf, hmacbuf_len, "srp_encrypt_aes256_hmac_sha1: hmac ="); /* Copy the ciphertext message after the HMAC data */ memcpy(hmacbuf_end, ciphertext, ciphertext_len); /* Verifier data: what cannot fit into iov[1] */ verifier_len = hmac_bufpad_len - ciphertext_len; ret_hmacbuf = (unsigned char *) calloc(verifier_len, sizeof(unsigned char)); if (!ret_hmacbuf) { sts = ENOMEM; goto error; } /* Split cipher text into two iov values: iov[0] = HMAC code */ memcpy(ret_hmacbuf, hmacbuf, verifier_len); /* iov[1] = cipher text */ memcpy(out_ciphertext, hmacbuf + verifier_len, plaintext_len); /* Additional iov[0] length due to padding expansion */ *out_hmacbuf = ret_hmacbuf; *out_hmacbuf_len = verifier_len; error: if (sts) { if (ret_hmacbuf) { free(ret_hmacbuf); } } if (hmacbuf) { free(hmacbuf); } if (ciphertext) { free(ciphertext); } return sts; }
static OM_uint32 _srp_gss_validate_client( OM_uint32 *minor_status, srp_gss_ctx_id_t srp_context_handle, int state, gss_buffer_t input_token, gss_buffer_t output_token) { OM_uint32 maj = 0; OM_uint32 min = 0; int berror = 0; ber_tag_t ber_state = 0; BerElement *ber = NULL; BerElement *ber_resp = NULL; struct berval ber_HAMK = {0}; struct berval *ber_srp_bytes_M = NULL; struct berval ber_ctx = {0}; const unsigned char *bytes_HAMK = NULL; int bytes_HAMK_len = 0; struct berval *flatten = NULL; PVMDIR_SERVER_CONTEXT hServer = NULL; 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_validate_client(): " "state=SRP_AUTH_CLIENT_VALIDATE\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{O}", &ber_state, &ber_srp_bytes_M); if (berror == -1) { maj = GSS_S_FAILURE; min = GSS_S_DEFECTIVE_TOKEN; goto error; } /* * This is mostly impossible, as state IS the "t" field. * More a double check for proper decoding. */ if ((int) ber_state != state || ber_srp_bytes_M->bv_len == 0) { maj = GSS_S_FAILURE; goto error; } srp_print_hex(ber_srp_bytes_M->bv_val, (int) ber_srp_bytes_M->bv_len, "_srp_gss_validate_client(accept_sec_ctx) received bytes_M"); if (srp_context_handle->bUseCSRP) { srp_verifier_verify_session( srp_context_handle->srp_ver, ber_srp_bytes_M->bv_val, &bytes_HAMK); if (!bytes_HAMK) { min = rpc_s_auth_mut_fail; } } else { hServer = srp_context_handle->hServer; min = cli_rpc_srp_verifier_verify_session( hServer->hBinding, srp_context_handle->srp_ver, ber_srp_bytes_M->bv_val, (int) ber_srp_bytes_M->bv_len, &bytes_HAMK, &bytes_HAMK_len); } if (min || !bytes_HAMK) { /* * Bad password will cause this to fail. Do not bail on error here. * Merely generate a NULL HAMK response below, to complete the * SRP protocol exchange with the client. The client tests for an * empty HAMK token, and formulates the proper error. */ srp_debug_printf("_srp_gss_validate_client: " "srp_verifier_verify_session() failed!!!\n"); } /* * ASN.1 encode the bytes_HAMK value, sending it back to the client * for validation. That will complete the authentication process if that * succeeds. */ ber_resp = ber_alloc_t(LBER_USE_DER); if (!ber_resp) { maj = GSS_S_FAILURE; min = ENOMEM; goto error; } if (min == 0) { if (srp_context_handle->bUseCSRP) { bytes_HAMK_len = srp_verifier_get_session_key_length(srp_context_handle->srp_ver); } else { /* * Generate HAMK response. When min is an error code, * an empty HAMK response (zero length) is created. */ min = cli_rpc_srp_verifier_get_session_key_length( hServer->hBinding, srp_context_handle->srp_ver, (long *) &ber_HAMK.bv_len); if (min) { maj = GSS_S_FAILURE; goto error; } } } ber_HAMK.bv_val = (void *) bytes_HAMK; ber_HAMK.bv_len = bytes_HAMK_len; berror = ber_printf(ber_resp, "t{O}", (int) SRP_AUTH_SERVER_VALIDATE, &ber_HAMK); if (berror == -1) { maj = GSS_S_FAILURE; goto error; } berror = ber_flatten(ber_resp, &flatten); if (berror == -1) { 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); /* * From server's perspective, authentication is done. However, * there is a final output_token to process by gss_init_sec_context(). */ maj = GSS_S_COMPLETE; error: if (ber_srp_bytes_M) { ber_bvfree(ber_srp_bytes_M); } if (!srp_context_handle->bUseCSRP && bytes_HAMK) { free((void *) bytes_HAMK); } ber_bvfree(flatten); ber_free(ber, 1); ber_free(ber_resp, 1); if (maj) { if (min) { *minor_status = min; } } return maj; }
krb5_error_code srp_make_enc_keyblock( srp_gss_ctx_id_t srp_context_handle) { char *srp_session_key_str = NULL; unsigned char *hmac_key = NULL; int b64_alloc_len = 0; unsigned char *ptr_expanded_key = NULL; unsigned char expanded_session_key[SRP_EXPAND_KEY_LEN] = {0}; unsigned char srp_session_key[SRP_EXPAND_SESSION_KEY_LEN] = {0}; int srp_session_key_len = sizeof(srp_session_key); unsigned char iv_data[AES_BLOCK_SIZE] = {0}; int iv_data_len = sizeof(iv_data); int b64_session_key_len = 0; krb5_error_code krb5_err = KRB5_BAD_ENCTYPE; if (!srp_context_handle->srp_session_key || srp_context_handle->srp_session_key_len == 0) { krb5_err = GSS_S_DEFECTIVE_TOKEN; goto error; } srp_print_hex(srp_context_handle->srp_session_key, srp_context_handle->srp_session_key_len, "srp_make_enc_keyblock: SRP-negotiated session key "); /* Expand SRP session key to obtain more bytes for IV/session key */ krb5_err = srp_expand_session_key( srp_context_handle->srp_session_key, srp_context_handle->srp_session_key_len, srp_context_handle->upn_name, /* salt */ (int) strlen(srp_context_handle->upn_name), /* salt length */ SRP_EXPAND_KEY_ITER, sizeof(expanded_session_key), expanded_session_key); if (krb5_err) { goto error; } /* Carve up parts of the expanded key for various purposes */ ptr_expanded_key = expanded_session_key; /* Initialization vector */ memcpy(iv_data, ptr_expanded_key, iv_data_len); ptr_expanded_key += iv_data_len; srp_print_hex(iv_data, iv_data_len, "srp_make_enc_keyblock: got initialization vector "); /* SRP "derived session" key */ memcpy(srp_session_key, ptr_expanded_key, srp_session_key_len); ptr_expanded_key += sizeof(srp_session_key); /* HMAC key, remaining 16 bytes */ hmac_key = ptr_expanded_key; srp_print_hex(srp_session_key, srp_session_key_len, "srp_make_enc_keyblock: got derived session key"); /* Build b64 encoded string of SRP session key */ b64_alloc_len = (srp_session_key_len + 2) / 3 * 4 + 1; srp_session_key_str = calloc(b64_alloc_len, sizeof(char)); if (!srp_session_key_str) { krb5_err = ENOMEM; goto error; } krb5_err = sasl_encode64( srp_session_key, srp_session_key_len, srp_session_key_str, b64_alloc_len, &b64_session_key_len); if (krb5_err) { krb5_err = ENOMEM; goto error; } srp_session_key_str[b64_session_key_len] = '\0'; srp_context_handle->keyblock = calloc(1, sizeof(krb5_keyblock)); if (!srp_context_handle->keyblock) { krb5_err = ENOMEM; goto error; } /* Generate encryption key from SRP shared key */ krb5_err = srp_gen_keyblock( srp_context_handle->krb5_ctx, SRP_ENC_KEYTYPE, srp_session_key_str, srp_context_handle->upn_name, srp_context_handle->keyblock); if (krb5_err) { goto error; } srp_print_hex(srp_context_handle->keyblock->contents, srp_context_handle->keyblock->length, "srp_make_enc_keyblock: keyblock value"); memset(srp_context_handle->aes_encrypt_iv, 0, iv_data_len); memcpy(srp_context_handle->aes_encrypt_iv, iv_data, iv_data_len); memset(srp_context_handle->aes_decrypt_iv, 0, iv_data_len); memcpy(srp_context_handle->aes_decrypt_iv, iv_data, iv_data_len); AES_set_encrypt_key( srp_context_handle->keyblock->contents, srp_context_handle->keyblock->length * 8, &srp_context_handle->aes_encrypt_key); AES_set_decrypt_key( srp_context_handle->keyblock->contents, srp_context_handle->keyblock->length * 8, &srp_context_handle->aes_decrypt_key); if (srp_init_hmac(&srp_context_handle->hmac_ctx, hmac_key, SRP_EXPAND_HMAC_KEY)) { krb5_err = ENOMEM; goto error; } error: if (krb5_err) { if (srp_context_handle->keyblock) { free(srp_context_handle->keyblock); } } if (srp_session_key_str) { free(srp_session_key_str); } return krb5_err; }
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; }