void * _gsskrb5_make_header (void *ptr, size_t len, const void *type, const gss_OID mech) { u_char *p = ptr; p = _gssapi_make_mech_header(p, len, mech); memcpy (p, type, 2); p += 2; return p; }
OM_uint32 _gssapi_encapsulate( OM_uint32 *minor_status, const krb5_data *in_data, gss_buffer_t output_token, const gss_OID mech ) { size_t len, outer_len; void *p; _gssapi_encap_length (in_data->length, &len, &outer_len, mech); output_token->length = outer_len; output_token->value = malloc (outer_len); if (output_token->value == NULL) { *minor_status = ENOMEM; return GSS_S_FAILURE; } p = _gssapi_make_mech_header (output_token->value, len, mech); memcpy (p, in_data->data, in_data->length); return GSS_S_COMPLETE; }
OM_uint32 _gssapi_wrap_arcfour(OM_uint32 * minor_status, const gsskrb5_ctx context_handle, krb5_context context, int conf_req_flag, gss_qop_t qop_req, const gss_buffer_t input_message_buffer, int * conf_state, gss_buffer_t output_message_buffer, krb5_keyblock *key) { u_char Klocaldata[16], k6_data[16], *p, *p0; size_t len, total_len, datalen; krb5_keyblock Klocal; krb5_error_code ret; int32_t seq_number; if (conf_state) *conf_state = 0; datalen = input_message_buffer->length; if (IS_DCE_STYLE(context_handle)) { len = GSS_ARCFOUR_WRAP_TOKEN_SIZE; _gssapi_encap_length(len, &len, &total_len, GSS_KRB5_MECHANISM); total_len += datalen; } else { datalen += 1; /* padding */ len = datalen + GSS_ARCFOUR_WRAP_TOKEN_SIZE; _gssapi_encap_length(len, &len, &total_len, GSS_KRB5_MECHANISM); } output_message_buffer->length = total_len; output_message_buffer->value = malloc (total_len); if (output_message_buffer->value == NULL) { *minor_status = ENOMEM; return GSS_S_FAILURE; } p0 = _gssapi_make_mech_header(output_message_buffer->value, len, GSS_KRB5_MECHANISM); p = p0; *p++ = 0x02; /* TOK_ID */ *p++ = 0x01; *p++ = 0x11; /* SGN_ALG */ *p++ = 0x00; if (conf_req_flag) { *p++ = 0x10; /* SEAL_ALG */ *p++ = 0x00; } else { *p++ = 0xff; /* SEAL_ALG */ *p++ = 0xff; } *p++ = 0xff; /* Filler */ *p++ = 0xff; p = NULL; HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex); krb5_auth_con_getlocalseqnumber (context, context_handle->auth_context, &seq_number); _gss_mg_encode_be_uint32(seq_number, p0 + 8); krb5_auth_con_setlocalseqnumber (context, context_handle->auth_context, ++seq_number); HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); memset (p0 + 8 + 4, (context_handle->more_flags & LOCAL) ? 0 : 0xff, 4); krb5_generate_random_block(p0 + 24, 8); /* fill in Confounder */ /* p points to data */ p = p0 + GSS_ARCFOUR_WRAP_TOKEN_SIZE; memcpy(p, input_message_buffer->value, input_message_buffer->length); if (!IS_DCE_STYLE(context_handle)) p[input_message_buffer->length] = 1; /* padding */ ret = arcfour_mic_cksum(context, key, KRB5_KU_USAGE_SEAL, p0 + 16, 8, /* SGN_CKSUM */ p0, 8, /* TOK_ID, SGN_ALG, SEAL_ALG, Filler */ p0 + 24, 8, /* Confounder */ p0 + GSS_ARCFOUR_WRAP_TOKEN_SIZE, datalen); if (ret) { *minor_status = ret; _gsskrb5_release_buffer(minor_status, output_message_buffer); return GSS_S_FAILURE; } { int i; Klocal.keytype = key->keytype; Klocal.keyvalue.data = Klocaldata; Klocal.keyvalue.length = sizeof(Klocaldata); for (i = 0; i < 16; i++) Klocaldata[i] = ((u_char *)key->keyvalue.data)[i] ^ 0xF0; } ret = arcfour_mic_key(context, &Klocal, p0 + 8, 4, /* SND_SEQ */ k6_data, sizeof(k6_data)); memset(Klocaldata, 0, sizeof(Klocaldata)); if (ret) { _gsskrb5_release_buffer(minor_status, output_message_buffer); *minor_status = ret; return GSS_S_FAILURE; } if(conf_req_flag) { EVP_CIPHER_CTX rc4_key; EVP_CIPHER_CTX_init(&rc4_key); EVP_CipherInit_ex(&rc4_key, EVP_rc4(), NULL, k6_data, NULL, 1); EVP_Cipher(&rc4_key, p0 + 24, p0 + 24, 8 + datalen); EVP_CIPHER_CTX_cleanup(&rc4_key); } memset(k6_data, 0, sizeof(k6_data)); ret = arcfour_mic_key(context, key, p0 + 16, 8, /* SGN_CKSUM */ k6_data, sizeof(k6_data)); if (ret) { _gsskrb5_release_buffer(minor_status, output_message_buffer); *minor_status = ret; return GSS_S_FAILURE; } { EVP_CIPHER_CTX rc4_key; EVP_CIPHER_CTX_init(&rc4_key); EVP_CipherInit_ex(&rc4_key, EVP_rc4(), NULL, k6_data, NULL, 1); EVP_Cipher(&rc4_key, p0 + 8, p0 + 8 /* SND_SEQ */, 8); EVP_CIPHER_CTX_cleanup(&rc4_key); memset(k6_data, 0, sizeof(k6_data)); } if (conf_state) *conf_state = conf_req_flag; *minor_status = 0; return GSS_S_COMPLETE; }
OM_uint32 _gssapi_get_mic_arcfour(OM_uint32 * minor_status, const gsskrb5_ctx context_handle, krb5_context context, gss_qop_t qop_req, const gss_buffer_t message_buffer, gss_buffer_t message_token, krb5_keyblock *key) { krb5_error_code ret; int32_t seq_number; size_t len, total_len; u_char k6_data[16], *p0, *p; EVP_CIPHER_CTX rc4_key; _gsskrb5_encap_length (22, &len, &total_len, GSS_KRB5_MECHANISM); message_token->length = total_len; message_token->value = malloc (total_len); if (message_token->value == NULL) { *minor_status = ENOMEM; return GSS_S_FAILURE; } p0 = _gssapi_make_mech_header(message_token->value, len, GSS_KRB5_MECHANISM); p = p0; *p++ = 0x01; /* TOK_ID */ *p++ = 0x01; *p++ = 0x11; /* SGN_ALG */ *p++ = 0x00; *p++ = 0xff; /* Filler */ *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; p = NULL; ret = arcfour_mic_cksum(context, key, KRB5_KU_USAGE_SIGN, p0 + 16, 8, /* SGN_CKSUM */ p0, 8, /* TOK_ID, SGN_ALG, Filer */ message_buffer->value, message_buffer->length, NULL, 0); if (ret) { _gsskrb5_release_buffer(minor_status, message_token); *minor_status = ret; return GSS_S_FAILURE; } ret = arcfour_mic_key(context, key, p0 + 16, 8, /* SGN_CKSUM */ k6_data, sizeof(k6_data)); if (ret) { _gsskrb5_release_buffer(minor_status, message_token); *minor_status = ret; return GSS_S_FAILURE; } HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex); krb5_auth_con_getlocalseqnumber (context, context_handle->auth_context, &seq_number); p = p0 + 8; /* SND_SEQ */ _gss_mg_encode_be_uint32(seq_number, p); krb5_auth_con_setlocalseqnumber (context, context_handle->auth_context, ++seq_number); HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); memset (p + 4, (context_handle->more_flags & LOCAL) ? 0 : 0xff, 4); EVP_CIPHER_CTX_init(&rc4_key); EVP_CipherInit_ex(&rc4_key, EVP_rc4(), NULL, k6_data, NULL, 1); EVP_Cipher(&rc4_key, p, p, 8); EVP_CIPHER_CTX_cleanup(&rc4_key); memset(k6_data, 0, sizeof(k6_data)); *minor_status = 0; return GSS_S_COMPLETE; }