diff options
Diffstat (limited to 'source4/heimdal/lib/gssapi/krb5')
51 files changed, 11572 insertions, 0 deletions
diff --git a/source4/heimdal/lib/gssapi/krb5/8003.c b/source4/heimdal/lib/gssapi/krb5/8003.c new file mode 100644 index 0000000000..0123f67e09 --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/8003.c @@ -0,0 +1,248 @@ +/* + * Copyright (c) 1997 - 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id: 8003.c,v 1.20 2006/10/07 22:13:51 lha Exp $"); + +krb5_error_code +_gsskrb5_encode_om_uint32(OM_uint32 n, u_char *p) +{ + p[0] = (n >> 0) & 0xFF; + p[1] = (n >> 8) & 0xFF; + p[2] = (n >> 16) & 0xFF; + p[3] = (n >> 24) & 0xFF; + return 0; +} + +krb5_error_code +_gsskrb5_encode_be_om_uint32(OM_uint32 n, u_char *p) +{ + p[0] = (n >> 24) & 0xFF; + p[1] = (n >> 16) & 0xFF; + p[2] = (n >> 8) & 0xFF; + p[3] = (n >> 0) & 0xFF; + return 0; +} + +krb5_error_code +_gsskrb5_decode_om_uint32(const void *ptr, OM_uint32 *n) +{ + const u_char *p = ptr; + *n = (p[0] << 0) | (p[1] << 8) | (p[2] << 16) | (p[3] << 24); + return 0; +} + +krb5_error_code +_gsskrb5_decode_be_om_uint32(const void *ptr, OM_uint32 *n) +{ + const u_char *p = ptr; + *n = (p[0] <<24) | (p[1] << 16) | (p[2] << 8) | (p[3] << 0); + return 0; +} + +static krb5_error_code +hash_input_chan_bindings (const gss_channel_bindings_t b, + u_char *p) +{ + u_char num[4]; + MD5_CTX md5; + + MD5_Init(&md5); + _gsskrb5_encode_om_uint32 (b->initiator_addrtype, num); + MD5_Update (&md5, num, sizeof(num)); + _gsskrb5_encode_om_uint32 (b->initiator_address.length, num); + MD5_Update (&md5, num, sizeof(num)); + if (b->initiator_address.length) + MD5_Update (&md5, + b->initiator_address.value, + b->initiator_address.length); + _gsskrb5_encode_om_uint32 (b->acceptor_addrtype, num); + MD5_Update (&md5, num, sizeof(num)); + _gsskrb5_encode_om_uint32 (b->acceptor_address.length, num); + MD5_Update (&md5, num, sizeof(num)); + if (b->acceptor_address.length) + MD5_Update (&md5, + b->acceptor_address.value, + b->acceptor_address.length); + _gsskrb5_encode_om_uint32 (b->application_data.length, num); + MD5_Update (&md5, num, sizeof(num)); + if (b->application_data.length) + MD5_Update (&md5, + b->application_data.value, + b->application_data.length); + MD5_Final (p, &md5); + return 0; +} + +/* + * create a checksum over the chanel bindings in + * `input_chan_bindings', `flags' and `fwd_data' and return it in + * `result' + */ + +OM_uint32 +_gsskrb5_create_8003_checksum ( + OM_uint32 *minor_status, + const gss_channel_bindings_t input_chan_bindings, + OM_uint32 flags, + const krb5_data *fwd_data, + Checksum *result) +{ + u_char *p; + + /* + * see rfc1964 (section 1.1.1 (Initial Token), and the checksum value + * field's format) */ + result->cksumtype = CKSUMTYPE_GSSAPI; + if (fwd_data->length > 0 && (flags & GSS_C_DELEG_FLAG)) + result->checksum.length = 24 + 4 + fwd_data->length; + else + result->checksum.length = 24; + result->checksum.data = malloc (result->checksum.length); + if (result->checksum.data == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + p = result->checksum.data; + _gsskrb5_encode_om_uint32 (16, p); + p += 4; + if (input_chan_bindings == GSS_C_NO_CHANNEL_BINDINGS) { + memset (p, 0, 16); + } else { + hash_input_chan_bindings (input_chan_bindings, p); + } + p += 16; + _gsskrb5_encode_om_uint32 (flags, p); + p += 4; + + if (fwd_data->length > 0 && (flags & GSS_C_DELEG_FLAG)) { + + *p++ = (1 >> 0) & 0xFF; /* DlgOpt */ /* == 1 */ + *p++ = (1 >> 8) & 0xFF; /* DlgOpt */ /* == 0 */ + *p++ = (fwd_data->length >> 0) & 0xFF; /* Dlgth */ + *p++ = (fwd_data->length >> 8) & 0xFF; /* Dlgth */ + memcpy(p, (unsigned char *) fwd_data->data, fwd_data->length); + + p += fwd_data->length; + } + + return GSS_S_COMPLETE; +} + +/* + * verify the checksum in `cksum' over `input_chan_bindings' + * returning `flags' and `fwd_data' + */ + +OM_uint32 +_gsskrb5_verify_8003_checksum( + OM_uint32 *minor_status, + const gss_channel_bindings_t input_chan_bindings, + const Checksum *cksum, + OM_uint32 *flags, + krb5_data *fwd_data) +{ + unsigned char hash[16]; + unsigned char *p; + OM_uint32 length; + int DlgOpt; + static unsigned char zeros[16]; + + if (cksum == NULL) { + *minor_status = 0; + return GSS_S_BAD_BINDINGS; + } + + /* XXX should handle checksums > 24 bytes */ + if(cksum->cksumtype != CKSUMTYPE_GSSAPI || cksum->checksum.length < 24) { + *minor_status = 0; + return GSS_S_BAD_BINDINGS; + } + + p = cksum->checksum.data; + _gsskrb5_decode_om_uint32(p, &length); + if(length != sizeof(hash)) { + *minor_status = 0; + return GSS_S_BAD_BINDINGS; + } + + p += 4; + + if (input_chan_bindings != GSS_C_NO_CHANNEL_BINDINGS + && memcmp(p, zeros, sizeof(zeros)) != 0) { + if(hash_input_chan_bindings(input_chan_bindings, hash) != 0) { + *minor_status = 0; + return GSS_S_BAD_BINDINGS; + } + if(memcmp(hash, p, sizeof(hash)) != 0) { + *minor_status = 0; + return GSS_S_BAD_BINDINGS; + } + } + + p += sizeof(hash); + + _gsskrb5_decode_om_uint32(p, flags); + p += 4; + + if (cksum->checksum.length > 24 && (*flags & GSS_C_DELEG_FLAG)) { + if(cksum->checksum.length < 28) { + *minor_status = 0; + return GSS_S_BAD_BINDINGS; + } + + DlgOpt = (p[0] << 0) | (p[1] << 8); + p += 2; + if (DlgOpt != 1) { + *minor_status = 0; + return GSS_S_BAD_BINDINGS; + } + + fwd_data->length = (p[0] << 0) | (p[1] << 8); + p += 2; + if(cksum->checksum.length < 28 + fwd_data->length) { + *minor_status = 0; + return GSS_S_BAD_BINDINGS; + } + fwd_data->data = malloc(fwd_data->length); + if (fwd_data->data == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + memcpy(fwd_data->data, p, fwd_data->length); + } + + return GSS_S_COMPLETE; +} diff --git a/source4/heimdal/lib/gssapi/krb5/accept_sec_context.c b/source4/heimdal/lib/gssapi/krb5/accept_sec_context.c new file mode 100644 index 0000000000..e42bb11b85 --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/accept_sec_context.c @@ -0,0 +1,774 @@ +/* + * Copyright (c) 1997 - 2006 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id: accept_sec_context.c,v 1.64 2006/10/25 04:19:45 lha Exp $"); + +HEIMDAL_MUTEX gssapi_keytab_mutex = HEIMDAL_MUTEX_INITIALIZER; +krb5_keytab _gsskrb5_keytab; + +OM_uint32 +_gsskrb5_register_acceptor_identity (const char *identity) +{ + krb5_error_code ret; + + ret = _gsskrb5_init(); + if(ret) + return GSS_S_FAILURE; + + HEIMDAL_MUTEX_lock(&gssapi_keytab_mutex); + + if(_gsskrb5_keytab != NULL) { + krb5_kt_close(_gsskrb5_context, _gsskrb5_keytab); + _gsskrb5_keytab = NULL; + } + if (identity == NULL) { + ret = krb5_kt_default(_gsskrb5_context, &_gsskrb5_keytab); + } else { + char *p; + + asprintf(&p, "FILE:%s", identity); + if(p == NULL) { + HEIMDAL_MUTEX_unlock(&gssapi_keytab_mutex); + return GSS_S_FAILURE; + } + ret = krb5_kt_resolve(_gsskrb5_context, p, &_gsskrb5_keytab); + free(p); + } + HEIMDAL_MUTEX_unlock(&gssapi_keytab_mutex); + if(ret) + return GSS_S_FAILURE; + return GSS_S_COMPLETE; +} + +void +_gsskrb5i_is_cfx(gsskrb5_ctx ctx, int *is_cfx) +{ + krb5_keyblock *key; + int acceptor = (ctx->more_flags & LOCAL) == 0; + + *is_cfx = 0; + + if (acceptor) { + if (ctx->auth_context->local_subkey) + key = ctx->auth_context->local_subkey; + else + key = ctx->auth_context->remote_subkey; + } else { + if (ctx->auth_context->remote_subkey) + key = ctx->auth_context->remote_subkey; + else + key = ctx->auth_context->local_subkey; + } + if (key == NULL) + key = ctx->auth_context->keyblock; + + if (key == NULL) + return; + + switch (key->keytype) { + case ETYPE_DES_CBC_CRC: + case ETYPE_DES_CBC_MD4: + case ETYPE_DES_CBC_MD5: + case ETYPE_DES3_CBC_MD5: + case ETYPE_DES3_CBC_SHA1: + case ETYPE_ARCFOUR_HMAC_MD5: + case ETYPE_ARCFOUR_HMAC_MD5_56: + break; + default : + *is_cfx = 1; + if ((acceptor && ctx->auth_context->local_subkey) || + (!acceptor && ctx->auth_context->remote_subkey)) + ctx->more_flags |= ACCEPTOR_SUBKEY; + break; + } +} + + +static OM_uint32 +gsskrb5_accept_delegated_token +(OM_uint32 * minor_status, + gsskrb5_ctx ctx, + gss_cred_id_t * delegated_cred_handle + ) +{ + krb5_ccache ccache = NULL; + krb5_error_code kret; + int32_t ac_flags, ret = GSS_S_COMPLETE; + + *minor_status = 0; + + /* XXX Create a new delegated_cred_handle? */ + if (delegated_cred_handle == NULL) { + kret = krb5_cc_default (_gsskrb5_context, &ccache); + } else { + *delegated_cred_handle = NULL; + kret = krb5_cc_gen_new (_gsskrb5_context, &krb5_mcc_ops, &ccache); + } + if (kret) { + ctx->flags &= ~GSS_C_DELEG_FLAG; + goto out; + } + + kret = krb5_cc_initialize(_gsskrb5_context, ccache, ctx->source); + if (kret) { + ctx->flags &= ~GSS_C_DELEG_FLAG; + goto out; + } + + krb5_auth_con_removeflags(_gsskrb5_context, + ctx->auth_context, + KRB5_AUTH_CONTEXT_DO_TIME, + &ac_flags); + kret = krb5_rd_cred2(_gsskrb5_context, + ctx->auth_context, + ccache, + &ctx->fwd_data); + if (kret) + _gsskrb5_set_error_string(); + krb5_auth_con_setflags(_gsskrb5_context, + ctx->auth_context, + ac_flags); + if (kret) { + ctx->flags &= ~GSS_C_DELEG_FLAG; + ret = GSS_S_FAILURE; + *minor_status = kret; + goto out; + } + + if (delegated_cred_handle) { + gsskrb5_cred handle; + + ret = _gsskrb5_import_cred(minor_status, + ccache, + NULL, + NULL, + delegated_cred_handle); + if (ret != GSS_S_COMPLETE) + goto out; + + handle = (gsskrb5_cred) *delegated_cred_handle; + + handle->cred_flags |= GSS_CF_DESTROY_CRED_ON_RELEASE; + krb5_cc_close(_gsskrb5_context, ccache); + ccache = NULL; + } + +out: + if (ccache) { + if (delegated_cred_handle == NULL) + krb5_cc_close(_gsskrb5_context, ccache); + else + krb5_cc_destroy(_gsskrb5_context, ccache); + } + return ret; +} + +static OM_uint32 +gsskrb5_acceptor_ready(OM_uint32 * minor_status, + gsskrb5_ctx ctx, + gss_cred_id_t *delegated_cred_handle) +{ + OM_uint32 ret; + int32_t seq_number; + int is_cfx = 0; + + krb5_auth_getremoteseqnumber (_gsskrb5_context, + ctx->auth_context, + &seq_number); + + _gsskrb5i_is_cfx(ctx, &is_cfx); + + ret = _gssapi_msg_order_create(minor_status, + &ctx->order, + _gssapi_msg_order_f(ctx->flags), + seq_number, 0, is_cfx); + if (ret) + return ret; + + /* + * If requested, set local sequence num to remote sequence if this + * isn't a mutual authentication context + */ + if (!(ctx->flags & GSS_C_MUTUAL_FLAG) && _gssapi_msg_order_f(ctx->flags)) { + krb5_auth_con_setlocalseqnumber(_gsskrb5_context, + ctx->auth_context, + seq_number); + } + + /* + * We should handle the delegation ticket, in case it's there + */ + if (ctx->fwd_data.length > 0 && (ctx->flags & GSS_C_DELEG_FLAG)) { + ret = gsskrb5_accept_delegated_token(minor_status, + ctx, + delegated_cred_handle); + if (ret) + return ret; + } else { + /* Well, looks like it wasn't there after all */ + ctx->flags &= ~GSS_C_DELEG_FLAG; + } + + ctx->state = ACCEPTOR_READY; + ctx->more_flags |= OPEN; + + return GSS_S_COMPLETE; +} + +static OM_uint32 +gsskrb5_acceptor_start(OM_uint32 * minor_status, + gsskrb5_ctx ctx, + const gss_cred_id_t acceptor_cred_handle, + const gss_buffer_t input_token_buffer, + const 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) +{ + krb5_error_code kret; + OM_uint32 ret = GSS_S_COMPLETE; + krb5_data indata; + krb5_flags ap_options; + krb5_ticket *ticket = NULL; + krb5_keytab keytab = NULL; + krb5_keyblock *keyblock = NULL; + int is_cfx = 0; + const gsskrb5_cred acceptor_cred = (gsskrb5_cred)acceptor_cred_handle; + + /* + * We may, or may not, have an escapsulation. + */ + ret = _gsskrb5_decapsulate (minor_status, + input_token_buffer, + &indata, + "\x01\x00", + GSS_KRB5_MECHANISM); + + if (ret) { + /* Assume that there is no OID wrapping. */ + indata.length = input_token_buffer->length; + indata.data = input_token_buffer->value; + } + + /* + * We need to get our keytab + */ + if (acceptor_cred == NULL) { + if (_gsskrb5_keytab != NULL) + keytab = _gsskrb5_keytab; + } else if (acceptor_cred->keytab != NULL) { + keytab = acceptor_cred->keytab; + } + + /* + * We need to check the ticket and create the AP-REP packet + */ + kret = krb5_rd_req_return_keyblock(_gsskrb5_context, + &ctx->auth_context, + &indata, + (acceptor_cred == NULL) ? NULL : acceptor_cred->principal, + keytab, + &ap_options, + &ticket, + &keyblock); + if (kret) { + ret = GSS_S_FAILURE; + *minor_status = kret; + _gsskrb5_set_error_string (); + return ret; + } + + /* + * We need to remember some data on the context_handle. + */ + ctx->ticket = ticket; + ctx->service_keyblock = keyblock; + ctx->lifetime = ticket->ticket.endtime; + + /* + * We need to copy the principal names to the context and the + * calling layer. + */ + kret = krb5_copy_principal(_gsskrb5_context, + ticket->client, + &ctx->source); + if (kret) { + ret = GSS_S_FAILURE; + *minor_status = kret; + _gsskrb5_set_error_string (); + } + + kret = krb5_copy_principal(_gsskrb5_context, ticket->server, &ctx->target); + if (kret) { + ret = GSS_S_FAILURE; + *minor_status = kret; + _gsskrb5_set_error_string (); + return ret; + } + + /* + * We need to setup some compat stuff, this assumes that + * context_handle->target is already set. + */ + ret = _gss_DES3_get_mic_compat(minor_status, ctx); + if (ret) + return ret; + + if (src_name != NULL) { + kret = krb5_copy_principal (_gsskrb5_context, + ticket->client, + (gsskrb5_name*)src_name); + if (kret) { + ret = GSS_S_FAILURE; + *minor_status = kret; + _gsskrb5_set_error_string (); + return ret; + } + } + + /* + * We need to get the flags out of the 8003 checksum. + */ + { + krb5_authenticator authenticator; + + kret = krb5_auth_con_getauthenticator(_gsskrb5_context, + ctx->auth_context, + &authenticator); + if(kret) { + ret = GSS_S_FAILURE; + *minor_status = kret; + _gsskrb5_set_error_string (); + return ret; + } + + if (authenticator->cksum->cksumtype == CKSUMTYPE_GSSAPI) { + ret = _gsskrb5_verify_8003_checksum(minor_status, + input_chan_bindings, + authenticator->cksum, + &ctx->flags, + &ctx->fwd_data); + + krb5_free_authenticator(_gsskrb5_context, &authenticator); + if (ret) { + return ret; + } + } else { + krb5_crypto crypto; + + kret = krb5_crypto_init(_gsskrb5_context, + ctx->auth_context->keyblock, + 0, &crypto); + if(kret) { + krb5_free_authenticator(_gsskrb5_context, &authenticator); + + ret = GSS_S_FAILURE; + *minor_status = kret; + _gsskrb5_set_error_string (); + return ret; + } + + /* + * Windows accepts Samba3's use of a kerberos, rather than + * GSSAPI checksum here + */ + + kret = krb5_verify_checksum(_gsskrb5_context, + crypto, KRB5_KU_AP_REQ_AUTH_CKSUM, NULL, 0, + authenticator->cksum); + krb5_free_authenticator(_gsskrb5_context, &authenticator); + krb5_crypto_destroy(_gsskrb5_context, crypto); + + if(kret) { + ret = GSS_S_BAD_SIG; + *minor_status = kret; + _gsskrb5_set_error_string (); + return ret; + } + + /* + * Samba style get some flags (but not DCE-STYLE) + */ + ctx->flags = + GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG | GSS_C_SEQUENCE_FLAG; + } + } + + if(ctx->flags & GSS_C_MUTUAL_FLAG) { + krb5_data outbuf; + + _gsskrb5i_is_cfx(ctx, &is_cfx); + + if (is_cfx != 0 + || (ap_options & AP_OPTS_USE_SUBKEY)) { + kret = krb5_auth_con_addflags(_gsskrb5_context, + ctx->auth_context, + KRB5_AUTH_CONTEXT_USE_SUBKEY, + NULL); + ctx->more_flags |= ACCEPTOR_SUBKEY; + } + + kret = krb5_mk_rep(_gsskrb5_context, + ctx->auth_context, + &outbuf); + if (kret) { + *minor_status = kret; + _gsskrb5_set_error_string (); + return GSS_S_FAILURE; + } + + if (ctx->flags & GSS_C_DCE_STYLE) { + output_token->length = outbuf.length; + output_token->value = outbuf.data; + } else { + ret = _gsskrb5_encapsulate(minor_status, + &outbuf, + output_token, + "\x02\x00", + GSS_KRB5_MECHANISM); + krb5_data_free (&outbuf); + if (ret) + return ret; + } + } + + ctx->flags |= GSS_C_TRANS_FLAG; + + /* Remember the flags */ + + ctx->lifetime = ticket->ticket.endtime; + ctx->more_flags |= OPEN; + + if (mech_type) + *mech_type = GSS_KRB5_MECHANISM; + + if (time_rec) { + ret = _gsskrb5_lifetime_left(minor_status, + ctx->lifetime, + time_rec); + if (ret) { + return ret; + } + } + + /* + * When GSS_C_DCE_STYLE is in use, we need ask for a AP-REP from + * the client. + */ + if (ctx->flags & GSS_C_DCE_STYLE) { + /* + * Return flags to caller, but we haven't processed + * delgations yet + */ + if (ret_flags) + *ret_flags = (ctx->flags & ~GSS_C_DELEG_FLAG); + + ctx->state = ACCEPTOR_WAIT_FOR_DCESTYLE; + return GSS_S_CONTINUE_NEEDED; + } + + ret = gsskrb5_acceptor_ready(minor_status, ctx, delegated_cred_handle); + + if (ret_flags) + *ret_flags = ctx->flags; + + return ret; +} + +static OM_uint32 +acceptor_wait_for_dcestyle(OM_uint32 * minor_status, + gsskrb5_ctx ctx, + const gss_cred_id_t acceptor_cred_handle, + const gss_buffer_t input_token_buffer, + const 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) +{ + OM_uint32 ret; + krb5_error_code kret; + krb5_data inbuf; + int32_t r_seq_number, l_seq_number; + + /* + * We know it's GSS_C_DCE_STYLE so we don't need to decapsulate the AP_REP + */ + + inbuf.length = input_token_buffer->length; + inbuf.data = input_token_buffer->value; + + /* + * We need to remeber the old remote seq_number, then check if the + * client has replied with our local seq_number, and then reset + * the remote seq_number to the old value + */ + { + kret = krb5_auth_con_getlocalseqnumber(_gsskrb5_context, + ctx->auth_context, + &l_seq_number); + if (kret) { + _gsskrb5_set_error_string (); + *minor_status = kret; + return GSS_S_FAILURE; + } + + kret = krb5_auth_getremoteseqnumber(_gsskrb5_context, + ctx->auth_context, + &r_seq_number); + if (kret) { + _gsskrb5_set_error_string (); + *minor_status = kret; + return GSS_S_FAILURE; + } + + kret = krb5_auth_con_setremoteseqnumber(_gsskrb5_context, + ctx->auth_context, + l_seq_number); + if (kret) { + _gsskrb5_set_error_string (); + *minor_status = kret; + return GSS_S_FAILURE; + } + } + + /* + * We need to verify the AP_REP, but we need to flag that this is + * DCE_STYLE, so don't check the timestamps this time, but put the + * flag DO_TIME back afterward. + */ + { + krb5_ap_rep_enc_part *repl; + int32_t auth_flags; + + krb5_auth_con_removeflags(_gsskrb5_context, + ctx->auth_context, + KRB5_AUTH_CONTEXT_DO_TIME, + &auth_flags); + + kret = krb5_rd_rep(_gsskrb5_context, ctx->auth_context, &inbuf, &repl); + if (kret) { + _gsskrb5_set_error_string (); + *minor_status = kret; + return GSS_S_FAILURE; + } + krb5_free_ap_rep_enc_part(_gsskrb5_context, repl); + krb5_auth_con_setflags(_gsskrb5_context, ctx->auth_context, auth_flags); + } + + /* We need to check the liftime */ + { + OM_uint32 lifetime_rec; + + ret = _gsskrb5_lifetime_left(minor_status, + ctx->lifetime, + &lifetime_rec); + if (ret) { + return ret; + } + if (lifetime_rec == 0) { + return GSS_S_CONTEXT_EXPIRED; + } + + if (time_rec) *time_rec = lifetime_rec; + } + + /* We need to give the caller the flags which are in use */ + if (ret_flags) *ret_flags = ctx->flags; + + if (src_name) { + kret = krb5_copy_principal(_gsskrb5_context, + ctx->source, + (gsskrb5_name*)src_name); + if (kret) { + *minor_status = kret; + _gsskrb5_set_error_string (); + return GSS_S_FAILURE; + } + } + + /* + * After the krb5_rd_rep() the remote and local seq_number should + * be the same, because the client just replies the seq_number + * from our AP-REP in its AP-REP, but then the client uses the + * seq_number from its AP-REQ for GSS_wrap() + */ + { + int32_t tmp_r_seq_number, tmp_l_seq_number; + + kret = krb5_auth_getremoteseqnumber(_gsskrb5_context, + ctx->auth_context, + &tmp_r_seq_number); + if (kret) { + _gsskrb5_set_error_string (); + *minor_status = kret; + return GSS_S_FAILURE; + } + + kret = krb5_auth_con_getlocalseqnumber(_gsskrb5_context, + ctx->auth_context, + &tmp_l_seq_number); + if (kret) { + _gsskrb5_set_error_string (); + *minor_status = kret; + return GSS_S_FAILURE; + } + + /* + * Here we check if the client has responsed with our local seq_number, + */ + if (tmp_r_seq_number != tmp_l_seq_number) { + return GSS_S_UNSEQ_TOKEN; + } + } + + /* + * We need to reset the remote seq_number, because the client will use, + * the old one for the GSS_wrap() calls + */ + { + kret = krb5_auth_con_setremoteseqnumber(_gsskrb5_context, + ctx->auth_context, + r_seq_number); + if (kret) { + _gsskrb5_set_error_string (); + *minor_status = kret; + return GSS_S_FAILURE; + } + } + + return gsskrb5_acceptor_ready(minor_status, ctx, delegated_cred_handle); +} + + +OM_uint32 +_gsskrb5_accept_sec_context(OM_uint32 * minor_status, + gss_ctx_id_t * context_handle, + const gss_cred_id_t acceptor_cred_handle, + const gss_buffer_t input_token_buffer, + const 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) +{ + OM_uint32 ret; + gsskrb5_ctx ctx; + + GSSAPI_KRB5_INIT(); + + output_token->length = 0; + output_token->value = NULL; + + if (src_name != NULL) + *src_name = NULL; + if (mech_type) + *mech_type = GSS_KRB5_MECHANISM; + + if (*context_handle == GSS_C_NO_CONTEXT) { + ret = _gsskrb5_create_ctx(minor_status, + context_handle, + input_chan_bindings, + ACCEPTOR_START); + if (ret) + return ret; + } + + ctx = (gsskrb5_ctx)*context_handle; + + + /* + * TODO: check the channel_bindings + * (above just sets them to krb5 layer) + */ + + HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); + + switch (ctx->state) { + case ACCEPTOR_START: + ret = gsskrb5_acceptor_start(minor_status, + ctx, + acceptor_cred_handle, + input_token_buffer, + input_chan_bindings, + src_name, + mech_type, + output_token, + ret_flags, + time_rec, + delegated_cred_handle); + break; + case ACCEPTOR_WAIT_FOR_DCESTYLE: + ret = acceptor_wait_for_dcestyle(minor_status, + ctx, + acceptor_cred_handle, + input_token_buffer, + input_chan_bindings, + src_name, + mech_type, + output_token, + ret_flags, + time_rec, + delegated_cred_handle); + break; + case ACCEPTOR_READY: + /* + * If we get there, the caller have called + * gss_accept_sec_context() one time too many. + */ + ret = GSS_S_BAD_STATUS; + break; + default: + /* TODO: is this correct here? --metze */ + ret = GSS_S_BAD_STATUS; + break; + } + + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + + if (GSS_ERROR(ret)) { + OM_uint32 min2; + _gsskrb5_delete_sec_context(&min2, context_handle, GSS_C_NO_BUFFER); + } + + return ret; +} diff --git a/source4/heimdal/lib/gssapi/krb5/acquire_cred.c b/source4/heimdal/lib/gssapi/krb5/acquire_cred.c new file mode 100644 index 0000000000..df6e137402 --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/acquire_cred.c @@ -0,0 +1,379 @@ +/* + * Copyright (c) 1997 - 2005 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id: acquire_cred.c,v 1.31 2006/10/07 22:13:55 lha Exp $"); + +OM_uint32 +__gsskrb5_ccache_lifetime(OM_uint32 *minor_status, + krb5_ccache id, + krb5_principal principal, + OM_uint32 *lifetime) +{ + krb5_creds in_cred, *out_cred; + krb5_const_realm realm; + krb5_error_code kret; + + memset(&in_cred, 0, sizeof(in_cred)); + in_cred.client = principal; + + realm = krb5_principal_get_realm(_gsskrb5_context, principal); + if (realm == NULL) { + _gsskrb5_clear_status (); + *minor_status = KRB5_PRINC_NOMATCH; /* XXX */ + return GSS_S_FAILURE; + } + + kret = krb5_make_principal(_gsskrb5_context, &in_cred.server, + realm, KRB5_TGS_NAME, realm, NULL); + if (kret) { + _gsskrb5_set_error_string(); + *minor_status = kret; + return GSS_S_FAILURE; + } + + kret = krb5_get_credentials(_gsskrb5_context, 0, + id, &in_cred, &out_cred); + krb5_free_principal(_gsskrb5_context, in_cred.server); + if (kret) { + _gsskrb5_set_error_string(); + *minor_status = kret; + return GSS_S_FAILURE; + } + + *lifetime = out_cred->times.endtime; + krb5_free_creds(_gsskrb5_context, out_cred); + + return GSS_S_COMPLETE; +} + + + + +static krb5_error_code +get_keytab(krb5_keytab *keytab) +{ + char kt_name[256]; + krb5_error_code kret; + + HEIMDAL_MUTEX_lock(&gssapi_keytab_mutex); + + if (_gsskrb5_keytab != NULL) { + kret = krb5_kt_get_name(_gsskrb5_context, + _gsskrb5_keytab, + kt_name, sizeof(kt_name)); + if (kret == 0) + kret = krb5_kt_resolve(_gsskrb5_context, kt_name, keytab); + } else + kret = krb5_kt_default(_gsskrb5_context, keytab); + + HEIMDAL_MUTEX_unlock(&gssapi_keytab_mutex); + + return (kret); +} + +static OM_uint32 acquire_initiator_cred + (OM_uint32 * minor_status, + const gss_name_t desired_name, + OM_uint32 time_req, + const gss_OID_set desired_mechs, + gss_cred_usage_t cred_usage, + gsskrb5_cred handle, + gss_OID_set * actual_mechs, + OM_uint32 * time_rec + ) +{ + OM_uint32 ret; + krb5_creds cred; + krb5_principal def_princ; + krb5_get_init_creds_opt *opt; + krb5_ccache ccache; + krb5_keytab keytab; + krb5_error_code kret; + + keytab = NULL; + ccache = NULL; + def_princ = NULL; + ret = GSS_S_FAILURE; + memset(&cred, 0, sizeof(cred)); + + /* If we have a preferred principal, lets try to find it in all + * caches, otherwise, fall back to default cache. Ignore + * errors. */ + if (handle->principal) + kret = krb5_cc_cache_match (_gsskrb5_context, + handle->principal, + NULL, + &ccache); + + if (ccache == NULL) { + kret = krb5_cc_default(_gsskrb5_context, &ccache); + if (kret) + goto end; + } + kret = krb5_cc_get_principal(_gsskrb5_context, ccache, + &def_princ); + if (kret != 0) { + /* we'll try to use a keytab below */ + krb5_cc_destroy(_gsskrb5_context, ccache); + ccache = NULL; + kret = 0; + } else if (handle->principal == NULL) { + kret = krb5_copy_principal(_gsskrb5_context, def_princ, + &handle->principal); + if (kret) + goto end; + } else if (handle->principal != NULL && + krb5_principal_compare(_gsskrb5_context, handle->principal, + def_princ) == FALSE) { + /* Before failing, lets check the keytab */ + krb5_free_principal(_gsskrb5_context, def_princ); + def_princ = NULL; + } + if (def_princ == NULL) { + /* We have no existing credentials cache, + * so attempt to get a TGT using a keytab. + */ + if (handle->principal == NULL) { + kret = krb5_get_default_principal(_gsskrb5_context, + &handle->principal); + if (kret) + goto end; + } + kret = get_keytab(&keytab); + if (kret) + goto end; + kret = krb5_get_init_creds_opt_alloc(_gsskrb5_context, &opt); + if (kret) + goto end; + kret = krb5_get_init_creds_keytab(_gsskrb5_context, &cred, + handle->principal, keytab, 0, NULL, opt); + krb5_get_init_creds_opt_free(opt); + if (kret) + goto end; + kret = krb5_cc_gen_new(_gsskrb5_context, &krb5_mcc_ops, + &ccache); + if (kret) + goto end; + kret = krb5_cc_initialize(_gsskrb5_context, ccache, cred.client); + if (kret) + goto end; + kret = krb5_cc_store_cred(_gsskrb5_context, ccache, &cred); + if (kret) + goto end; + handle->lifetime = cred.times.endtime; + handle->cred_flags |= GSS_CF_DESTROY_CRED_ON_RELEASE; + } else { + + ret = __gsskrb5_ccache_lifetime(minor_status, + ccache, + handle->principal, + &handle->lifetime); + if (ret != GSS_S_COMPLETE) + goto end; + kret = 0; + } + + handle->ccache = ccache; + ret = GSS_S_COMPLETE; + +end: + if (cred.client != NULL) + krb5_free_cred_contents(_gsskrb5_context, &cred); + if (def_princ != NULL) + krb5_free_principal(_gsskrb5_context, def_princ); + if (keytab != NULL) + krb5_kt_close(_gsskrb5_context, keytab); + if (ret != GSS_S_COMPLETE) { + if (ccache != NULL) + krb5_cc_close(_gsskrb5_context, ccache); + if (kret != 0) { + *minor_status = kret; + _gsskrb5_set_error_string (); + } + } + return (ret); +} + +static OM_uint32 acquire_acceptor_cred + (OM_uint32 * minor_status, + const gss_name_t desired_name, + OM_uint32 time_req, + const gss_OID_set desired_mechs, + gss_cred_usage_t cred_usage, + gsskrb5_cred handle, + gss_OID_set * actual_mechs, + OM_uint32 * time_rec + ) +{ + OM_uint32 ret; + krb5_error_code kret; + + kret = 0; + ret = GSS_S_FAILURE; + kret = get_keytab(&handle->keytab); + if (kret) + goto end; + + /* check that the requested principal exists in the keytab */ + if (handle->principal) { + krb5_keytab_entry entry; + + kret = krb5_kt_get_entry(_gsskrb5_context, handle->keytab, + handle->principal, 0, 0, &entry); + if (kret) + goto end; + krb5_kt_free_entry(_gsskrb5_context, &entry); + } + ret = GSS_S_COMPLETE; + +end: + if (ret != GSS_S_COMPLETE) { + if (handle->keytab != NULL) + krb5_kt_close(_gsskrb5_context, handle->keytab); + if (kret != 0) { + *minor_status = kret; + _gsskrb5_set_error_string (); + } + } + return (ret); +} + +OM_uint32 _gsskrb5_acquire_cred +(OM_uint32 * minor_status, + const gss_name_t desired_name, + OM_uint32 time_req, + const gss_OID_set desired_mechs, + gss_cred_usage_t cred_usage, + gss_cred_id_t * output_cred_handle, + gss_OID_set * actual_mechs, + OM_uint32 * time_rec + ) +{ + gsskrb5_cred handle; + OM_uint32 ret; + + if (cred_usage != GSS_C_ACCEPT && cred_usage != GSS_C_INITIATE && cred_usage != GSS_C_BOTH) { + *minor_status = GSS_KRB5_S_G_BAD_USAGE; + return GSS_S_FAILURE; + } + + GSSAPI_KRB5_INIT (); + + *output_cred_handle = NULL; + if (time_rec) + *time_rec = 0; + if (actual_mechs) + *actual_mechs = GSS_C_NO_OID_SET; + + if (desired_mechs) { + int present = 0; + + ret = _gsskrb5_test_oid_set_member(minor_status, GSS_KRB5_MECHANISM, + desired_mechs, &present); + if (ret) + return ret; + if (!present) { + *minor_status = 0; + return GSS_S_BAD_MECH; + } + } + + handle = calloc(1, sizeof(*handle)); + if (handle == NULL) { + *minor_status = ENOMEM; + return (GSS_S_FAILURE); + } + + HEIMDAL_MUTEX_init(&handle->cred_id_mutex); + + if (desired_name != GSS_C_NO_NAME) { + krb5_principal name = (krb5_principal)desired_name; + ret = krb5_copy_principal(_gsskrb5_context, name, &handle->principal); + if (ret) { + HEIMDAL_MUTEX_destroy(&handle->cred_id_mutex); + _gsskrb5_set_error_string(); + *minor_status = ret; + free(handle); + return GSS_S_FAILURE; + } + } + if (cred_usage == GSS_C_INITIATE || cred_usage == GSS_C_BOTH) { + ret = acquire_initiator_cred(minor_status, desired_name, time_req, + desired_mechs, cred_usage, handle, actual_mechs, time_rec); + if (ret != GSS_S_COMPLETE) { + HEIMDAL_MUTEX_destroy(&handle->cred_id_mutex); + krb5_free_principal(_gsskrb5_context, handle->principal); + free(handle); + return (ret); + } + } + if (cred_usage == GSS_C_ACCEPT || cred_usage == GSS_C_BOTH) { + ret = acquire_acceptor_cred(minor_status, desired_name, time_req, + desired_mechs, cred_usage, handle, actual_mechs, time_rec); + if (ret != GSS_S_COMPLETE) { + HEIMDAL_MUTEX_destroy(&handle->cred_id_mutex); + krb5_free_principal(_gsskrb5_context, handle->principal); + free(handle); + return (ret); + } + } + ret = _gsskrb5_create_empty_oid_set(minor_status, &handle->mechanisms); + if (ret == GSS_S_COMPLETE) + ret = _gsskrb5_add_oid_set_member(minor_status, GSS_KRB5_MECHANISM, + &handle->mechanisms); + if (ret == GSS_S_COMPLETE) + ret = _gsskrb5_inquire_cred(minor_status, (gss_cred_id_t)handle, + NULL, time_rec, NULL, actual_mechs); + if (ret != GSS_S_COMPLETE) { + if (handle->mechanisms != NULL) + _gsskrb5_release_oid_set(NULL, &handle->mechanisms); + HEIMDAL_MUTEX_destroy(&handle->cred_id_mutex); + krb5_free_principal(_gsskrb5_context, handle->principal); + free(handle); + return (ret); + } + *minor_status = 0; + if (time_rec) { + ret = _gsskrb5_lifetime_left(minor_status, + handle->lifetime, + time_rec); + + if (ret) + return ret; + } + handle->usage = cred_usage; + *output_cred_handle = (gss_cred_id_t)handle; + return (GSS_S_COMPLETE); +} diff --git a/source4/heimdal/lib/gssapi/krb5/add_cred.c b/source4/heimdal/lib/gssapi/krb5/add_cred.c new file mode 100644 index 0000000000..4892e84798 --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/add_cred.c @@ -0,0 +1,249 @@ +/* + * Copyright (c) 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id: add_cred.c,v 1.9 2006/10/07 22:13:58 lha Exp $"); + +OM_uint32 _gsskrb5_add_cred ( + OM_uint32 *minor_status, + const gss_cred_id_t input_cred_handle, + const gss_name_t desired_name, + const gss_OID desired_mech, + gss_cred_usage_t cred_usage, + OM_uint32 initiator_time_req, + OM_uint32 acceptor_time_req, + gss_cred_id_t *output_cred_handle, + gss_OID_set *actual_mechs, + OM_uint32 *initiator_time_rec, + OM_uint32 *acceptor_time_rec) +{ + OM_uint32 ret, lifetime; + gsskrb5_cred cred, handle; + krb5_const_principal dname; + + handle = NULL; + cred = (gsskrb5_cred)input_cred_handle; + dname = (krb5_const_principal)desired_name; + + if (gss_oid_equal(desired_mech, GSS_KRB5_MECHANISM) == 0) { + *minor_status = 0; + return GSS_S_BAD_MECH; + } + + if (cred == NULL && output_cred_handle == NULL) { + *minor_status = 0; + return GSS_S_NO_CRED; + } + + if (cred == NULL) { /* XXX standard conformance failure */ + *minor_status = 0; + return GSS_S_NO_CRED; + } + + /* check if requested output usage is compatible with output usage */ + if (output_cred_handle != NULL) { + HEIMDAL_MUTEX_lock(&cred->cred_id_mutex); + if (cred->usage != cred_usage && cred->usage != GSS_C_BOTH) { + HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex); + *minor_status = GSS_KRB5_S_G_BAD_USAGE; + return(GSS_S_FAILURE); + } + } + + /* check that we have the same name */ + if (dname != NULL && + krb5_principal_compare(_gsskrb5_context, dname, + cred->principal) != FALSE) { + if (output_cred_handle) + HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex); + *minor_status = 0; + return GSS_S_BAD_NAME; + } + + /* make a copy */ + if (output_cred_handle) { + krb5_error_code kret; + + handle = calloc(1, sizeof(*handle)); + if (handle == NULL) { + HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex); + *minor_status = ENOMEM; + return (GSS_S_FAILURE); + } + + handle->usage = cred_usage; + handle->lifetime = cred->lifetime; + handle->principal = NULL; + handle->keytab = NULL; + handle->ccache = NULL; + handle->mechanisms = NULL; + HEIMDAL_MUTEX_init(&handle->cred_id_mutex); + + ret = GSS_S_FAILURE; + + kret = krb5_copy_principal(_gsskrb5_context, cred->principal, + &handle->principal); + if (kret) { + HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex); + free(handle); + *minor_status = kret; + return GSS_S_FAILURE; + } + + if (cred->keytab) { + char name[KRB5_KT_PREFIX_MAX_LEN + MAXPATHLEN]; + int len; + + ret = GSS_S_FAILURE; + + kret = krb5_kt_get_type(_gsskrb5_context, cred->keytab, + name, KRB5_KT_PREFIX_MAX_LEN); + if (kret) { + *minor_status = kret; + goto failure; + } + len = strlen(name); + name[len++] = ':'; + + kret = krb5_kt_get_name(_gsskrb5_context, cred->keytab, + name + len, + sizeof(name) - len); + if (kret) { + *minor_status = kret; + goto failure; + } + + kret = krb5_kt_resolve(_gsskrb5_context, name, + &handle->keytab); + if (kret){ + *minor_status = kret; + goto failure; + } + } + + if (cred->ccache) { + const char *type, *name; + char *type_name; + + ret = GSS_S_FAILURE; + + type = krb5_cc_get_type(_gsskrb5_context, cred->ccache); + if (type == NULL){ + *minor_status = ENOMEM; + goto failure; + } + + if (strcmp(type, "MEMORY") == 0) { + ret = krb5_cc_gen_new(_gsskrb5_context, &krb5_mcc_ops, + &handle->ccache); + if (ret) { + *minor_status = ret; + goto failure; + } + + ret = krb5_cc_copy_cache(_gsskrb5_context, cred->ccache, + handle->ccache); + if (ret) { + *minor_status = ret; + goto failure; + } + + } else { + name = krb5_cc_get_name(_gsskrb5_context, cred->ccache); + if (name == NULL) { + *minor_status = ENOMEM; + goto failure; + } + + asprintf(&type_name, "%s:%s", type, name); + if (type_name == NULL) { + *minor_status = ENOMEM; + goto failure; + } + + kret = krb5_cc_resolve(_gsskrb5_context, type_name, + &handle->ccache); + free(type_name); + if (kret) { + *minor_status = kret; + goto failure; + } + } + } + ret = _gsskrb5_create_empty_oid_set(minor_status, &handle->mechanisms); + if (ret) + goto failure; + + ret = _gsskrb5_add_oid_set_member(minor_status, GSS_KRB5_MECHANISM, + &handle->mechanisms); + if (ret) + goto failure; + } + + HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex); + + ret = _gsskrb5_inquire_cred(minor_status, (gss_cred_id_t)cred, + NULL, &lifetime, NULL, actual_mechs); + if (ret) + goto failure; + + if (initiator_time_rec) + *initiator_time_rec = lifetime; + if (acceptor_time_rec) + *acceptor_time_rec = lifetime; + + if (output_cred_handle) { + *output_cred_handle = (gss_cred_id_t)handle; + } + + *minor_status = 0; + return ret; + + failure: + + if (handle) { + if (handle->principal) + krb5_free_principal(_gsskrb5_context, handle->principal); + if (handle->keytab) + krb5_kt_close(_gsskrb5_context, handle->keytab); + if (handle->ccache) + krb5_cc_destroy(_gsskrb5_context, handle->ccache); + if (handle->mechanisms) + _gsskrb5_release_oid_set(NULL, &handle->mechanisms); + free(handle); + } + if (output_cred_handle) + HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex); + return ret; +} diff --git a/source4/heimdal/lib/gssapi/krb5/add_oid_set_member.c b/source4/heimdal/lib/gssapi/krb5/add_oid_set_member.c new file mode 100644 index 0000000000..b0ec2c60d8 --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/add_oid_set_member.c @@ -0,0 +1,70 @@ +/* + * Copyright (c) 1997 - 2001, 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id: add_oid_set_member.c,v 1.10 2006/10/07 22:14:00 lha Exp $"); + +OM_uint32 _gsskrb5_add_oid_set_member ( + OM_uint32 * minor_status, + const gss_OID member_oid, + gss_OID_set * oid_set + ) +{ + gss_OID tmp; + size_t n; + OM_uint32 res; + int present; + + res = _gsskrb5_test_oid_set_member(minor_status, member_oid, + *oid_set, &present); + if (res != GSS_S_COMPLETE) + return res; + + if (present) { + *minor_status = 0; + return GSS_S_COMPLETE; + } + + n = (*oid_set)->count + 1; + tmp = realloc ((*oid_set)->elements, n * sizeof(gss_OID_desc)); + if (tmp == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + (*oid_set)->elements = tmp; + (*oid_set)->count = n; + (*oid_set)->elements[n-1] = *member_oid; + *minor_status = 0; + return GSS_S_COMPLETE; +} diff --git a/source4/heimdal/lib/gssapi/krb5/address_to_krb5addr.c b/source4/heimdal/lib/gssapi/krb5/address_to_krb5addr.c new file mode 100644 index 0000000000..9aec53faaa --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/address_to_krb5addr.c @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2000 - 2001 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5/gsskrb5_locl.h" + +#include <roken.h> + +krb5_error_code +_gsskrb5i_address_to_krb5addr(OM_uint32 gss_addr_type, + gss_buffer_desc *gss_addr, + int16_t port, + krb5_address *address) +{ + int addr_type; + struct sockaddr sa; + krb5_socklen_t sa_size = sizeof(sa); + krb5_error_code problem; + + if (gss_addr == NULL) + return GSS_S_FAILURE; + + switch (gss_addr_type) { +#ifdef HAVE_IPV6 + case GSS_C_AF_INET6: addr_type = AF_INET6; + break; +#endif /* HAVE_IPV6 */ + + case GSS_C_AF_INET: addr_type = AF_INET; + break; + default: + return GSS_S_FAILURE; + } + + problem = krb5_h_addr2sockaddr (_gsskrb5_context, + addr_type, + gss_addr->value, + &sa, + &sa_size, + port); + if (problem) + return GSS_S_FAILURE; + + problem = krb5_sockaddr2address (_gsskrb5_context, &sa, address); + + return problem; +} diff --git a/source4/heimdal/lib/gssapi/krb5/arcfour.c b/source4/heimdal/lib/gssapi/krb5/arcfour.c new file mode 100644 index 0000000000..82851f5a78 --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/arcfour.c @@ -0,0 +1,754 @@ +/* + * Copyright (c) 2003 - 2006 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id: arcfour.c,v 1.29 2006/10/07 22:14:05 lha Exp $"); + +/* + * Implements draft-brezak-win2k-krb-rc4-hmac-04.txt + * + * The arcfour message have the following formats: + * + * MIC token + * TOK_ID[2] = 01 01 + * SGN_ALG[2] = 11 00 + * Filler[4] + * SND_SEQ[8] + * SGN_CKSUM[8] + * + * WRAP token + * TOK_ID[2] = 02 01 + * SGN_ALG[2]; + * SEAL_ALG[2] + * Filler[2] + * SND_SEQ[2] + * SGN_CKSUM[8] + * Confounder[8] + */ + +/* + * WRAP in DCE-style have a fixed size header, the oid and length over + * the WRAP header is a total of + * GSS_ARCFOUR_WRAP_TOKEN_DCE_DER_HEADER_SIZE + + * GSS_ARCFOUR_WRAP_TOKEN_SIZE byte (ie total of 45 bytes overhead, + * remember the 2 bytes from APPL [0] SEQ). + */ + +#define GSS_ARCFOUR_WRAP_TOKEN_SIZE 32 +#define GSS_ARCFOUR_WRAP_TOKEN_DCE_DER_HEADER_SIZE 13 + + +static krb5_error_code +arcfour_mic_key(krb5_context context, krb5_keyblock *key, + void *cksum_data, size_t cksum_size, + void *key6_data, size_t key6_size) +{ + krb5_error_code ret; + + Checksum cksum_k5; + krb5_keyblock key5; + char k5_data[16]; + + Checksum cksum_k6; + + char T[4]; + + memset(T, 0, 4); + cksum_k5.checksum.data = k5_data; + cksum_k5.checksum.length = sizeof(k5_data); + + if (key->keytype == KEYTYPE_ARCFOUR_56) { + char L40[14] = "fortybits"; + + memcpy(L40 + 10, T, sizeof(T)); + ret = krb5_hmac(context, CKSUMTYPE_RSA_MD5, + L40, 14, 0, key, &cksum_k5); + memset(&k5_data[7], 0xAB, 9); + } else { + ret = krb5_hmac(context, CKSUMTYPE_RSA_MD5, + T, 4, 0, key, &cksum_k5); + } + if (ret) + return ret; + + key5.keytype = KEYTYPE_ARCFOUR; + key5.keyvalue = cksum_k5.checksum; + + cksum_k6.checksum.data = key6_data; + cksum_k6.checksum.length = key6_size; + + return krb5_hmac(context, CKSUMTYPE_RSA_MD5, + cksum_data, cksum_size, 0, &key5, &cksum_k6); +} + + +static krb5_error_code +arcfour_mic_cksum(krb5_keyblock *key, unsigned usage, + u_char *sgn_cksum, size_t sgn_cksum_sz, + const u_char *v1, size_t l1, + const void *v2, size_t l2, + const void *v3, size_t l3) +{ + Checksum CKSUM; + u_char *ptr; + size_t len; + krb5_crypto crypto; + krb5_error_code ret; + + assert(sgn_cksum_sz == 8); + + len = l1 + l2 + l3; + + ptr = malloc(len); + if (ptr == NULL) + return ENOMEM; + + memcpy(ptr, v1, l1); + memcpy(ptr + l1, v2, l2); + memcpy(ptr + l1 + l2, v3, l3); + + ret = krb5_crypto_init(_gsskrb5_context, key, 0, &crypto); + if (ret) { + free(ptr); + return ret; + } + + ret = krb5_create_checksum(_gsskrb5_context, + crypto, + usage, + 0, + ptr, len, + &CKSUM); + free(ptr); + if (ret == 0) { + memcpy(sgn_cksum, CKSUM.checksum.data, sgn_cksum_sz); + free_Checksum(&CKSUM); + } + krb5_crypto_destroy(_gsskrb5_context, crypto); + + return ret; +} + + +OM_uint32 +_gssapi_get_mic_arcfour(OM_uint32 * minor_status, + const gsskrb5_ctx context_handle, + 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; + RC4_KEY 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(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(_gsskrb5_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 (_gsskrb5_context, + context_handle->auth_context, + &seq_number); + p = p0 + 8; /* SND_SEQ */ + _gsskrb5_encode_be_om_uint32(seq_number, p); + + krb5_auth_con_setlocalseqnumber (_gsskrb5_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); + + RC4_set_key (&rc4_key, sizeof(k6_data), k6_data); + RC4 (&rc4_key, 8, p, p); + + memset(&rc4_key, 0, sizeof(rc4_key)); + memset(k6_data, 0, sizeof(k6_data)); + + *minor_status = 0; + return GSS_S_COMPLETE; +} + + +OM_uint32 +_gssapi_verify_mic_arcfour(OM_uint32 * minor_status, + const gsskrb5_ctx context_handle, + const gss_buffer_t message_buffer, + const gss_buffer_t token_buffer, + gss_qop_t * qop_state, + krb5_keyblock *key, + char *type) +{ + krb5_error_code ret; + uint32_t seq_number; + OM_uint32 omret; + u_char SND_SEQ[8], cksum_data[8], *p; + char k6_data[16]; + int cmp; + + if (qop_state) + *qop_state = 0; + + p = token_buffer->value; + omret = _gsskrb5_verify_header (&p, + token_buffer->length, + (u_char *)type, + GSS_KRB5_MECHANISM); + if (omret) + return omret; + + if (memcmp(p, "\x11\x00", 2) != 0) /* SGN_ALG = HMAC MD5 ARCFOUR */ + return GSS_S_BAD_SIG; + p += 2; + if (memcmp (p, "\xff\xff\xff\xff", 4) != 0) + return GSS_S_BAD_MIC; + p += 4; + + ret = arcfour_mic_cksum(key, KRB5_KU_USAGE_SIGN, + cksum_data, sizeof(cksum_data), + p - 8, 8, + message_buffer->value, message_buffer->length, + NULL, 0); + if (ret) { + *minor_status = ret; + return GSS_S_FAILURE; + } + + ret = arcfour_mic_key(_gsskrb5_context, key, + cksum_data, sizeof(cksum_data), + k6_data, sizeof(k6_data)); + if (ret) { + *minor_status = ret; + return GSS_S_FAILURE; + } + + cmp = memcmp(cksum_data, p + 8, 8); + if (cmp) { + *minor_status = 0; + return GSS_S_BAD_MIC; + } + + { + RC4_KEY rc4_key; + + RC4_set_key (&rc4_key, sizeof(k6_data), (void*)k6_data); + RC4 (&rc4_key, 8, p, SND_SEQ); + + memset(&rc4_key, 0, sizeof(rc4_key)); + memset(k6_data, 0, sizeof(k6_data)); + } + + _gsskrb5_decode_be_om_uint32(SND_SEQ, &seq_number); + + if (context_handle->more_flags & LOCAL) + cmp = memcmp(&SND_SEQ[4], "\xff\xff\xff\xff", 4); + else + cmp = memcmp(&SND_SEQ[4], "\x00\x00\x00\x00", 4); + + memset(SND_SEQ, 0, sizeof(SND_SEQ)); + if (cmp != 0) { + *minor_status = 0; + return GSS_S_BAD_MIC; + } + + HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex); + omret = _gssapi_msg_order_check(context_handle->order, seq_number); + HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); + if (omret) + return omret; + + *minor_status = 0; + return GSS_S_COMPLETE; +} + +OM_uint32 +_gssapi_wrap_arcfour(OM_uint32 * minor_status, + const gsskrb5_ctx context_handle, + 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; + + if ((context_handle->flags & GSS_C_DCE_STYLE) == 0) { + datalen = input_message_buffer->length + 1 /* padding */; + + len = datalen + GSS_ARCFOUR_WRAP_TOKEN_SIZE; + _gssapi_encap_length(len, &len, &total_len, GSS_KRB5_MECHANISM); + } else { + datalen = input_message_buffer->length; + + len = GSS_ARCFOUR_WRAP_TOKEN_SIZE; + _gssapi_encap_length(len, &len, &total_len, GSS_KRB5_MECHANISM); + total_len += datalen; + } + + 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 (_gsskrb5_context, + context_handle->auth_context, + &seq_number); + + _gsskrb5_encode_be_om_uint32(seq_number, p0 + 8); + + krb5_auth_con_setlocalseqnumber (_gsskrb5_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 ((context_handle->flags & GSS_C_DCE_STYLE) == 0) { + p[input_message_buffer->length] = 1; /* PADDING */ + } + + ret = arcfour_mic_cksum(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(_gsskrb5_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) { + RC4_KEY rc4_key; + + RC4_set_key (&rc4_key, sizeof(k6_data), (void *)k6_data); + /* XXX ? */ + RC4 (&rc4_key, 8 + datalen, p0 + 24, p0 + 24); /* Confounder + data */ + memset(&rc4_key, 0, sizeof(rc4_key)); + } + memset(k6_data, 0, sizeof(k6_data)); + + ret = arcfour_mic_key(_gsskrb5_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; + } + + { + RC4_KEY rc4_key; + + RC4_set_key (&rc4_key, sizeof(k6_data), k6_data); + RC4 (&rc4_key, 8, p0 + 8, p0 + 8); /* SND_SEQ */ + memset(&rc4_key, 0, sizeof(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_unwrap_arcfour(OM_uint32 *minor_status, + const gsskrb5_ctx context_handle, + const gss_buffer_t input_message_buffer, + gss_buffer_t output_message_buffer, + int *conf_state, + gss_qop_t *qop_state, + krb5_keyblock *key) +{ + u_char Klocaldata[16]; + krb5_keyblock Klocal; + krb5_error_code ret; + uint32_t seq_number; + size_t datalen; + OM_uint32 omret; + u_char k6_data[16], SND_SEQ[8], Confounder[8]; + u_char cksum_data[8]; + u_char *p, *p0; + int cmp; + int conf_flag; + size_t padlen = 0, len; + + if (conf_state) + *conf_state = 0; + if (qop_state) + *qop_state = 0; + + p0 = input_message_buffer->value; + + if ((context_handle->flags & GSS_C_DCE_STYLE) == 0) { + len = input_message_buffer->length; + } else { + len = GSS_ARCFOUR_WRAP_TOKEN_SIZE + + GSS_ARCFOUR_WRAP_TOKEN_DCE_DER_HEADER_SIZE; + if (input_message_buffer->length < len) + return GSS_S_BAD_MECH; + } + + omret = _gssapi_verify_mech_header(&p0, + len, + GSS_KRB5_MECHANISM); + if (omret) + return omret; + + /* length of mech header */ + len = (p0 - (u_char *)input_message_buffer->value) + + GSS_ARCFOUR_WRAP_TOKEN_SIZE; + + if (len > input_message_buffer->length) + return GSS_S_BAD_MECH; + + /* length of data */ + datalen = input_message_buffer->length - len; + + p = p0; + + if (memcmp(p, "\x02\x01", 2) != 0) + return GSS_S_BAD_SIG; + p += 2; + if (memcmp(p, "\x11\x00", 2) != 0) /* SGN_ALG = HMAC MD5 ARCFOUR */ + return GSS_S_BAD_SIG; + p += 2; + + if (memcmp (p, "\x10\x00", 2) == 0) + conf_flag = 1; + else if (memcmp (p, "\xff\xff", 2) == 0) + conf_flag = 0; + else + return GSS_S_BAD_SIG; + + p += 2; + if (memcmp (p, "\xff\xff", 2) != 0) + return GSS_S_BAD_MIC; + p = NULL; + + ret = arcfour_mic_key(_gsskrb5_context, key, + p0 + 16, 8, /* SGN_CKSUM */ + k6_data, sizeof(k6_data)); + if (ret) { + *minor_status = ret; + return GSS_S_FAILURE; + } + + { + RC4_KEY rc4_key; + + RC4_set_key (&rc4_key, sizeof(k6_data), k6_data); + RC4 (&rc4_key, 8, p0 + 8, SND_SEQ); /* SND_SEQ */ + memset(&rc4_key, 0, sizeof(rc4_key)); + memset(k6_data, 0, sizeof(k6_data)); + } + + _gsskrb5_decode_be_om_uint32(SND_SEQ, &seq_number); + + if (context_handle->more_flags & LOCAL) + cmp = memcmp(&SND_SEQ[4], "\xff\xff\xff\xff", 4); + else + cmp = memcmp(&SND_SEQ[4], "\x00\x00\x00\x00", 4); + + if (cmp != 0) { + *minor_status = 0; + return GSS_S_BAD_MIC; + } + + { + 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(_gsskrb5_context, &Klocal, + SND_SEQ, 4, + k6_data, sizeof(k6_data)); + memset(Klocaldata, 0, sizeof(Klocaldata)); + if (ret) { + *minor_status = ret; + return GSS_S_FAILURE; + } + + output_message_buffer->value = malloc(datalen); + if (output_message_buffer->value == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + output_message_buffer->length = datalen; + + if(conf_flag) { + RC4_KEY rc4_key; + + RC4_set_key (&rc4_key, sizeof(k6_data), k6_data); + RC4 (&rc4_key, 8, p0 + 24, Confounder); /* Confounder */ + RC4 (&rc4_key, datalen, p0 + GSS_ARCFOUR_WRAP_TOKEN_SIZE, + output_message_buffer->value); + memset(&rc4_key, 0, sizeof(rc4_key)); + } else { + memcpy(Confounder, p0 + 24, 8); /* Confounder */ + memcpy(output_message_buffer->value, + p0 + GSS_ARCFOUR_WRAP_TOKEN_SIZE, + datalen); + } + memset(k6_data, 0, sizeof(k6_data)); + + if ((context_handle->flags & GSS_C_DCE_STYLE) == 0) { + ret = _gssapi_verify_pad(output_message_buffer, datalen, &padlen); + if (ret) { + _gsskrb5_release_buffer(minor_status, output_message_buffer); + *minor_status = 0; + return ret; + } + output_message_buffer->length -= padlen; + } + + ret = arcfour_mic_cksum(key, KRB5_KU_USAGE_SEAL, + cksum_data, sizeof(cksum_data), + p0, 8, + Confounder, sizeof(Confounder), + output_message_buffer->value, + output_message_buffer->length + padlen); + if (ret) { + _gsskrb5_release_buffer(minor_status, output_message_buffer); + *minor_status = ret; + return GSS_S_FAILURE; + } + + cmp = memcmp(cksum_data, p0 + 16, 8); /* SGN_CKSUM */ + if (cmp) { + _gsskrb5_release_buffer(minor_status, output_message_buffer); + *minor_status = 0; + return GSS_S_BAD_MIC; + } + + HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex); + omret = _gssapi_msg_order_check(context_handle->order, seq_number); + HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); + if (omret) + return omret; + + if (conf_state) + *conf_state = conf_flag; + + *minor_status = 0; + return GSS_S_COMPLETE; +} + +static OM_uint32 +max_wrap_length_arcfour(const gsskrb5_ctx ctx, + krb5_crypto crypto, + size_t input_length, + OM_uint32 *max_input_size) +{ + /* + * if GSS_C_DCE_STYLE is in use: + * - we only need to encapsulate the WRAP token + * However, since this is a fixed since, we just + */ + if (ctx->flags & GSS_C_DCE_STYLE) { + size_t len, total_len; + + len = GSS_ARCFOUR_WRAP_TOKEN_SIZE; + _gssapi_encap_length(len, &len, &total_len, GSS_KRB5_MECHANISM); + + if (input_length < len) + *max_input_size = 0; + else + *max_input_size = input_length - len; + + } else { + size_t extrasize = GSS_ARCFOUR_WRAP_TOKEN_SIZE; + size_t blocksize = 8; + size_t len, total_len; + + len = 8 + input_length + blocksize + extrasize; + + _gsskrb5_encap_length(len, &len, &total_len, GSS_KRB5_MECHANISM); + + total_len -= input_length; /* token length */ + if (total_len < input_length) { + *max_input_size = (input_length - total_len); + (*max_input_size) &= (~(OM_uint32)(blocksize - 1)); + } else { + *max_input_size = 0; + } + } + + return GSS_S_COMPLETE; +} + +OM_uint32 +_gssapi_wrap_size_arcfour(OM_uint32 *minor_status, + const gsskrb5_ctx ctx, + int conf_req_flag, + gss_qop_t qop_req, + OM_uint32 req_output_size, + OM_uint32 *max_input_size, + krb5_keyblock *key) +{ + krb5_error_code ret; + krb5_crypto crypto; + + ret = krb5_crypto_init(_gsskrb5_context, key, 0, &crypto); + if (ret != 0) { + _gsskrb5_set_error_string(); + *minor_status = ret; + return GSS_S_FAILURE; + } + + ret = max_wrap_length_arcfour(ctx, crypto, + req_output_size, max_input_size); + if (ret != 0) { + _gsskrb5_set_error_string(); + *minor_status = ret; + krb5_crypto_destroy(_gsskrb5_context, crypto); + return GSS_S_FAILURE; + } + + krb5_crypto_destroy(_gsskrb5_context, crypto); + + return GSS_S_COMPLETE; +} diff --git a/source4/heimdal/lib/gssapi/krb5/canonicalize_name.c b/source4/heimdal/lib/gssapi/krb5/canonicalize_name.c new file mode 100644 index 0000000000..f69300b590 --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/canonicalize_name.c @@ -0,0 +1,46 @@ +/* + * Copyright (c) 1997 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id: canonicalize_name.c,v 1.4 2006/10/07 22:14:08 lha Exp $"); + +OM_uint32 _gsskrb5_canonicalize_name ( + OM_uint32 * minor_status, + const gss_name_t input_name, + const gss_OID mech_type, + gss_name_t * output_name + ) +{ + return _gsskrb5_duplicate_name (minor_status, input_name, output_name); +} diff --git a/source4/heimdal/lib/gssapi/krb5/cfx.c b/source4/heimdal/lib/gssapi/krb5/cfx.c new file mode 100755 index 0000000000..cb3f9ee5d3 --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/cfx.c @@ -0,0 +1,887 @@ +/* + * Copyright (c) 2003, PADL Software Pty Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of PADL Software nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id: cfx.c,v 1.24 2006/10/24 21:13:22 lha Exp $"); + +/* + * Implementation of draft-ietf-krb-wg-gssapi-cfx-06.txt + */ + +#define CFXSentByAcceptor (1 << 0) +#define CFXSealed (1 << 1) +#define CFXAcceptorSubkey (1 << 2) + +krb5_error_code +_gsskrb5cfx_wrap_length_cfx(krb5_crypto crypto, + int conf_req_flag, + size_t input_length, + size_t *output_length, + size_t *cksumsize, + uint16_t *padlength) +{ + krb5_error_code ret; + krb5_cksumtype type; + + /* 16-byte header is always first */ + *output_length = sizeof(gss_cfx_wrap_token_desc); + *padlength = 0; + + ret = krb5_crypto_get_checksum_type(_gsskrb5_context, crypto, &type); + if (ret) + return ret; + + ret = krb5_checksumsize(_gsskrb5_context, type, cksumsize); + if (ret) + return ret; + + if (conf_req_flag) { + size_t padsize; + + /* Header is concatenated with data before encryption */ + input_length += sizeof(gss_cfx_wrap_token_desc); + + ret = krb5_crypto_getpadsize(_gsskrb5_context, crypto, &padsize); + if (ret) { + return ret; + } + if (padsize > 1) { + /* XXX check this */ + *padlength = padsize - (input_length % padsize); + + /* We add the pad ourselves (noted here for completeness only) */ + input_length += *padlength; + } + + *output_length += krb5_get_wrapped_length(_gsskrb5_context, + crypto, input_length); + } else { + /* Checksum is concatenated with data */ + *output_length += input_length + *cksumsize; + } + + assert(*output_length > input_length); + + return 0; +} + +krb5_error_code +_gsskrb5cfx_max_wrap_length_cfx(krb5_crypto crypto, + int conf_req_flag, + size_t input_length, + OM_uint32 *output_length) +{ + krb5_error_code ret; + + *output_length = 0; + + /* 16-byte header is always first */ + if (input_length < 16) + return 0; + input_length -= 16; + + if (conf_req_flag) { + size_t wrapped_size, sz; + + wrapped_size = input_length + 1; + do { + wrapped_size--; + sz = krb5_get_wrapped_length(_gsskrb5_context, + crypto, wrapped_size); + } while (wrapped_size && sz > input_length); + if (wrapped_size == 0) { + *output_length = 0; + return 0; + } + + /* inner header */ + if (wrapped_size < 16) { + *output_length = 0; + return 0; + } + wrapped_size -= 16; + + *output_length = wrapped_size; + } else { + krb5_cksumtype type; + size_t cksumsize; + + ret = krb5_crypto_get_checksum_type(_gsskrb5_context, crypto, &type); + if (ret) + return ret; + + ret = krb5_checksumsize(_gsskrb5_context, type, &cksumsize); + if (ret) + return ret; + + if (input_length < cksumsize) + return 0; + + /* Checksum is concatenated with data */ + *output_length = input_length - cksumsize; + } + + return 0; +} + + +OM_uint32 _gssapi_wrap_size_cfx(OM_uint32 *minor_status, + const gsskrb5_ctx context_handle, + int conf_req_flag, + gss_qop_t qop_req, + OM_uint32 req_output_size, + OM_uint32 *max_input_size, + krb5_keyblock *key) +{ + krb5_error_code ret; + krb5_crypto crypto; + + ret = krb5_crypto_init(_gsskrb5_context, key, 0, &crypto); + if (ret != 0) { + _gsskrb5_set_error_string(); + *minor_status = ret; + return GSS_S_FAILURE; + } + + ret = _gsskrb5cfx_max_wrap_length_cfx(crypto, conf_req_flag, + req_output_size, max_input_size); + if (ret != 0) { + _gsskrb5_set_error_string(); + *minor_status = ret; + krb5_crypto_destroy(_gsskrb5_context, crypto); + return GSS_S_FAILURE; + } + + krb5_crypto_destroy(_gsskrb5_context, crypto); + + return GSS_S_COMPLETE; +} + +/* + * Rotate "rrc" bytes to the front or back + */ + +static krb5_error_code +rrc_rotate(void *data, size_t len, uint16_t rrc, krb5_boolean unrotate) +{ + u_char *tmp, buf[256]; + size_t left; + + if (len == 0) + return 0; + + rrc %= len; + + if (rrc == 0) + return 0; + + left = len - rrc; + + if (rrc <= sizeof(buf)) { + tmp = buf; + } else { + tmp = malloc(rrc); + if (tmp == NULL) + return ENOMEM; + } + + if (unrotate) { + memcpy(tmp, data, rrc); + memmove(data, (u_char *)data + rrc, left); + memcpy((u_char *)data + left, tmp, rrc); + } else { + memcpy(tmp, (u_char *)data + left, rrc); + memmove((u_char *)data + rrc, data, left); + memcpy(data, tmp, rrc); + } + + if (rrc > sizeof(buf)) + free(tmp); + + return 0; +} + +OM_uint32 _gssapi_wrap_cfx(OM_uint32 *minor_status, + const gsskrb5_ctx context_handle, + 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) +{ + krb5_crypto crypto; + gss_cfx_wrap_token token; + krb5_error_code ret; + unsigned usage; + krb5_data cipher; + size_t wrapped_len, cksumsize; + uint16_t padlength, rrc = 0; + int32_t seq_number; + u_char *p; + + ret = krb5_crypto_init(_gsskrb5_context, key, 0, &crypto); + if (ret != 0) { + _gsskrb5_set_error_string(); + *minor_status = ret; + return GSS_S_FAILURE; + } + + ret = _gsskrb5cfx_wrap_length_cfx(crypto, conf_req_flag, + input_message_buffer->length, + &wrapped_len, &cksumsize, &padlength); + if (ret != 0) { + _gsskrb5_set_error_string(); + *minor_status = ret; + krb5_crypto_destroy(_gsskrb5_context, crypto); + return GSS_S_FAILURE; + } + + /* Always rotate encrypted token (if any) and checksum to header */ + rrc = (conf_req_flag ? sizeof(*token) : 0) + (uint16_t)cksumsize; + + output_message_buffer->length = wrapped_len; + output_message_buffer->value = malloc(output_message_buffer->length); + if (output_message_buffer->value == NULL) { + *minor_status = ENOMEM; + krb5_crypto_destroy(_gsskrb5_context, crypto); + return GSS_S_FAILURE; + } + + p = output_message_buffer->value; + token = (gss_cfx_wrap_token)p; + token->TOK_ID[0] = 0x05; + token->TOK_ID[1] = 0x04; + token->Flags = 0; + token->Filler = 0xFF; + if ((context_handle->more_flags & LOCAL) == 0) + token->Flags |= CFXSentByAcceptor; + if (context_handle->more_flags & ACCEPTOR_SUBKEY) + token->Flags |= CFXAcceptorSubkey; + if (conf_req_flag) { + /* + * In Wrap tokens with confidentiality, the EC field is + * used to encode the size (in bytes) of the random filler. + */ + token->Flags |= CFXSealed; + token->EC[0] = (padlength >> 8) & 0xFF; + token->EC[1] = (padlength >> 0) & 0xFF; + } else { + /* + * In Wrap tokens without confidentiality, the EC field is + * used to encode the size (in bytes) of the trailing + * checksum. + * + * This is not used in the checksum calcuation itself, + * because the checksum length could potentially vary + * depending on the data length. + */ + token->EC[0] = 0; + token->EC[1] = 0; + } + + /* + * In Wrap tokens that provide for confidentiality, the RRC + * field in the header contains the hex value 00 00 before + * encryption. + * + * In Wrap tokens that do not provide for confidentiality, + * both the EC and RRC fields in the appended checksum + * contain the hex value 00 00 for the purpose of calculating + * the checksum. + */ + token->RRC[0] = 0; + token->RRC[1] = 0; + + HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex); + krb5_auth_con_getlocalseqnumber(_gsskrb5_context, + context_handle->auth_context, + &seq_number); + _gsskrb5_encode_be_om_uint32(0, &token->SND_SEQ[0]); + _gsskrb5_encode_be_om_uint32(seq_number, &token->SND_SEQ[4]); + krb5_auth_con_setlocalseqnumber(_gsskrb5_context, + context_handle->auth_context, + ++seq_number); + HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); + + /* + * If confidentiality is requested, the token header is + * appended to the plaintext before encryption; the resulting + * token is {"header" | encrypt(plaintext | pad | "header")}. + * + * If no confidentiality is requested, the checksum is + * calculated over the plaintext concatenated with the + * token header. + */ + if (context_handle->more_flags & LOCAL) { + usage = KRB5_KU_USAGE_INITIATOR_SEAL; + } else { + usage = KRB5_KU_USAGE_ACCEPTOR_SEAL; + } + + if (conf_req_flag) { + /* + * Any necessary padding is added here to ensure that the + * encrypted token header is always at the end of the + * ciphertext. + * + * The specification does not require that the padding + * bytes are initialized. + */ + p += sizeof(*token); + memcpy(p, input_message_buffer->value, input_message_buffer->length); + memset(p + input_message_buffer->length, 0xFF, padlength); + memcpy(p + input_message_buffer->length + padlength, + token, sizeof(*token)); + + ret = krb5_encrypt(_gsskrb5_context, crypto, + usage, p, + input_message_buffer->length + padlength + + sizeof(*token), + &cipher); + if (ret != 0) { + _gsskrb5_set_error_string(); + *minor_status = ret; + krb5_crypto_destroy(_gsskrb5_context, crypto); + _gsskrb5_release_buffer(minor_status, output_message_buffer); + return GSS_S_FAILURE; + } + assert(sizeof(*token) + cipher.length == wrapped_len); + token->RRC[0] = (rrc >> 8) & 0xFF; + token->RRC[1] = (rrc >> 0) & 0xFF; + + ret = rrc_rotate(cipher.data, cipher.length, rrc, FALSE); + if (ret != 0) { + _gsskrb5_set_error_string(); + *minor_status = ret; + krb5_crypto_destroy(_gsskrb5_context, crypto); + _gsskrb5_release_buffer(minor_status, output_message_buffer); + return GSS_S_FAILURE; + } + memcpy(p, cipher.data, cipher.length); + krb5_data_free(&cipher); + } else { + char *buf; + Checksum cksum; + + buf = malloc(input_message_buffer->length + sizeof(*token)); + if (buf == NULL) { + *minor_status = ENOMEM; + krb5_crypto_destroy(_gsskrb5_context, crypto); + _gsskrb5_release_buffer(minor_status, output_message_buffer); + return GSS_S_FAILURE; + } + memcpy(buf, input_message_buffer->value, input_message_buffer->length); + memcpy(buf + input_message_buffer->length, token, sizeof(*token)); + + ret = krb5_create_checksum(_gsskrb5_context, crypto, + usage, 0, buf, + input_message_buffer->length + + sizeof(*token), + &cksum); + if (ret != 0) { + _gsskrb5_set_error_string(); + *minor_status = ret; + krb5_crypto_destroy(_gsskrb5_context, crypto); + _gsskrb5_release_buffer(minor_status, output_message_buffer); + free(buf); + return GSS_S_FAILURE; + } + + free(buf); + + assert(cksum.checksum.length == cksumsize); + token->EC[0] = (cksum.checksum.length >> 8) & 0xFF; + token->EC[1] = (cksum.checksum.length >> 0) & 0xFF; + token->RRC[0] = (rrc >> 8) & 0xFF; + token->RRC[1] = (rrc >> 0) & 0xFF; + + p += sizeof(*token); + memcpy(p, input_message_buffer->value, input_message_buffer->length); + memcpy(p + input_message_buffer->length, + cksum.checksum.data, cksum.checksum.length); + + ret = rrc_rotate(p, + input_message_buffer->length + cksum.checksum.length, rrc, FALSE); + if (ret != 0) { + _gsskrb5_set_error_string(); + *minor_status = ret; + krb5_crypto_destroy(_gsskrb5_context, crypto); + _gsskrb5_release_buffer(minor_status, output_message_buffer); + free_Checksum(&cksum); + return GSS_S_FAILURE; + } + free_Checksum(&cksum); + } + + krb5_crypto_destroy(_gsskrb5_context, crypto); + + if (conf_state != NULL) { + *conf_state = conf_req_flag; + } + + *minor_status = 0; + return GSS_S_COMPLETE; +} + +OM_uint32 _gssapi_unwrap_cfx(OM_uint32 *minor_status, + const gsskrb5_ctx context_handle, + const gss_buffer_t input_message_buffer, + gss_buffer_t output_message_buffer, + int *conf_state, + gss_qop_t *qop_state, + krb5_keyblock *key) +{ + krb5_crypto crypto; + gss_cfx_wrap_token token; + u_char token_flags; + krb5_error_code ret; + unsigned usage; + krb5_data data; + uint16_t ec, rrc; + OM_uint32 seq_number_lo, seq_number_hi; + size_t len; + u_char *p; + + *minor_status = 0; + + if (input_message_buffer->length < sizeof(*token)) { + return GSS_S_DEFECTIVE_TOKEN; + } + + p = input_message_buffer->value; + + token = (gss_cfx_wrap_token)p; + + if (token->TOK_ID[0] != 0x05 || token->TOK_ID[1] != 0x04) { + return GSS_S_DEFECTIVE_TOKEN; + } + + /* Ignore unknown flags */ + token_flags = token->Flags & + (CFXSentByAcceptor | CFXSealed | CFXAcceptorSubkey); + + if (token_flags & CFXSentByAcceptor) { + if ((context_handle->more_flags & LOCAL) == 0) + return GSS_S_DEFECTIVE_TOKEN; + } + + if (context_handle->more_flags & ACCEPTOR_SUBKEY) { + if ((token_flags & CFXAcceptorSubkey) == 0) + return GSS_S_DEFECTIVE_TOKEN; + } else { + if (token_flags & CFXAcceptorSubkey) + return GSS_S_DEFECTIVE_TOKEN; + } + + if (token->Filler != 0xFF) { + return GSS_S_DEFECTIVE_TOKEN; + } + + if (conf_state != NULL) { + *conf_state = (token_flags & CFXSealed) ? 1 : 0; + } + + ec = (token->EC[0] << 8) | token->EC[1]; + rrc = (token->RRC[0] << 8) | token->RRC[1]; + + /* + * Check sequence number + */ + _gsskrb5_decode_be_om_uint32(&token->SND_SEQ[0], &seq_number_hi); + _gsskrb5_decode_be_om_uint32(&token->SND_SEQ[4], &seq_number_lo); + if (seq_number_hi) { + /* no support for 64-bit sequence numbers */ + *minor_status = ERANGE; + return GSS_S_UNSEQ_TOKEN; + } + + HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex); + ret = _gssapi_msg_order_check(context_handle->order, seq_number_lo); + if (ret != 0) { + *minor_status = 0; + HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); + _gsskrb5_release_buffer(minor_status, output_message_buffer); + return ret; + } + HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); + + /* + * Decrypt and/or verify checksum + */ + ret = krb5_crypto_init(_gsskrb5_context, key, 0, &crypto); + if (ret != 0) { + _gsskrb5_set_error_string(); + *minor_status = ret; + return GSS_S_FAILURE; + } + + if (context_handle->more_flags & LOCAL) { + usage = KRB5_KU_USAGE_ACCEPTOR_SEAL; + } else { + usage = KRB5_KU_USAGE_INITIATOR_SEAL; + } + + p += sizeof(*token); + len = input_message_buffer->length; + len -= (p - (u_char *)input_message_buffer->value); + + /* Rotate by RRC; bogus to do this in-place XXX */ + *minor_status = rrc_rotate(p, len, rrc, TRUE); + if (*minor_status != 0) { + krb5_crypto_destroy(_gsskrb5_context, crypto); + return GSS_S_FAILURE; + } + + if (token_flags & CFXSealed) { + ret = krb5_decrypt(_gsskrb5_context, crypto, usage, + p, len, &data); + if (ret != 0) { + _gsskrb5_set_error_string(); + *minor_status = ret; + krb5_crypto_destroy(_gsskrb5_context, crypto); + return GSS_S_BAD_MIC; + } + + /* Check that there is room for the pad and token header */ + if (data.length < ec + sizeof(*token)) { + krb5_crypto_destroy(_gsskrb5_context, crypto); + krb5_data_free(&data); + return GSS_S_DEFECTIVE_TOKEN; + } + p = data.data; + p += data.length - sizeof(*token); + + /* RRC is unprotected; don't modify input buffer */ + ((gss_cfx_wrap_token)p)->RRC[0] = token->RRC[0]; + ((gss_cfx_wrap_token)p)->RRC[1] = token->RRC[1]; + + /* Check the integrity of the header */ + if (memcmp(p, token, sizeof(*token)) != 0) { + krb5_crypto_destroy(_gsskrb5_context, crypto); + krb5_data_free(&data); + return GSS_S_BAD_MIC; + } + + output_message_buffer->value = data.data; + output_message_buffer->length = data.length - ec - sizeof(*token); + } else { + Checksum cksum; + + /* Determine checksum type */ + ret = krb5_crypto_get_checksum_type(_gsskrb5_context, + crypto, &cksum.cksumtype); + if (ret != 0) { + _gsskrb5_set_error_string(); + *minor_status = ret; + krb5_crypto_destroy(_gsskrb5_context, crypto); + return GSS_S_FAILURE; + } + + cksum.checksum.length = ec; + + /* Check we have at least as much data as the checksum */ + if (len < cksum.checksum.length) { + *minor_status = ERANGE; + krb5_crypto_destroy(_gsskrb5_context, crypto); + return GSS_S_BAD_MIC; + } + + /* Length now is of the plaintext only, no checksum */ + len -= cksum.checksum.length; + cksum.checksum.data = p + len; + + output_message_buffer->length = len; /* for later */ + output_message_buffer->value = malloc(len + sizeof(*token)); + if (output_message_buffer->value == NULL) { + *minor_status = ENOMEM; + krb5_crypto_destroy(_gsskrb5_context, crypto); + return GSS_S_FAILURE; + } + + /* Checksum is over (plaintext-data | "header") */ + memcpy(output_message_buffer->value, p, len); + memcpy((u_char *)output_message_buffer->value + len, + token, sizeof(*token)); + + /* EC is not included in checksum calculation */ + token = (gss_cfx_wrap_token)((u_char *)output_message_buffer->value + + len); + token->EC[0] = 0; + token->EC[1] = 0; + token->RRC[0] = 0; + token->RRC[1] = 0; + + ret = krb5_verify_checksum(_gsskrb5_context, crypto, + usage, + output_message_buffer->value, + len + sizeof(*token), + &cksum); + if (ret != 0) { + _gsskrb5_set_error_string(); + *minor_status = ret; + krb5_crypto_destroy(_gsskrb5_context, crypto); + _gsskrb5_release_buffer(minor_status, output_message_buffer); + return GSS_S_BAD_MIC; + } + } + + krb5_crypto_destroy(_gsskrb5_context, crypto); + + if (qop_state != NULL) { + *qop_state = GSS_C_QOP_DEFAULT; + } + + *minor_status = 0; + return GSS_S_COMPLETE; +} + +OM_uint32 _gssapi_mic_cfx(OM_uint32 *minor_status, + const gsskrb5_ctx context_handle, + gss_qop_t qop_req, + const gss_buffer_t message_buffer, + gss_buffer_t message_token, + krb5_keyblock *key) +{ + krb5_crypto crypto; + gss_cfx_mic_token token; + krb5_error_code ret; + unsigned usage; + Checksum cksum; + u_char *buf; + size_t len; + int32_t seq_number; + + ret = krb5_crypto_init(_gsskrb5_context, key, 0, &crypto); + if (ret != 0) { + _gsskrb5_set_error_string(); + *minor_status = ret; + return GSS_S_FAILURE; + } + + len = message_buffer->length + sizeof(*token); + buf = malloc(len); + if (buf == NULL) { + *minor_status = ENOMEM; + krb5_crypto_destroy(_gsskrb5_context, crypto); + return GSS_S_FAILURE; + } + + memcpy(buf, message_buffer->value, message_buffer->length); + + token = (gss_cfx_mic_token)(buf + message_buffer->length); + token->TOK_ID[0] = 0x04; + token->TOK_ID[1] = 0x04; + token->Flags = 0; + if ((context_handle->more_flags & LOCAL) == 0) + token->Flags |= CFXSentByAcceptor; + if (context_handle->more_flags & ACCEPTOR_SUBKEY) + token->Flags |= CFXAcceptorSubkey; + memset(token->Filler, 0xFF, 5); + + HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex); + krb5_auth_con_getlocalseqnumber(_gsskrb5_context, + context_handle->auth_context, + &seq_number); + _gsskrb5_encode_be_om_uint32(0, &token->SND_SEQ[0]); + _gsskrb5_encode_be_om_uint32(seq_number, &token->SND_SEQ[4]); + krb5_auth_con_setlocalseqnumber(_gsskrb5_context, + context_handle->auth_context, + ++seq_number); + HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); + + if (context_handle->more_flags & LOCAL) { + usage = KRB5_KU_USAGE_INITIATOR_SIGN; + } else { + usage = KRB5_KU_USAGE_ACCEPTOR_SIGN; + } + + ret = krb5_create_checksum(_gsskrb5_context, crypto, + usage, 0, buf, len, &cksum); + if (ret != 0) { + _gsskrb5_set_error_string(); + *minor_status = ret; + krb5_crypto_destroy(_gsskrb5_context, crypto); + free(buf); + return GSS_S_FAILURE; + } + krb5_crypto_destroy(_gsskrb5_context, crypto); + + /* Determine MIC length */ + message_token->length = sizeof(*token) + cksum.checksum.length; + message_token->value = malloc(message_token->length); + if (message_token->value == NULL) { + *minor_status = ENOMEM; + free_Checksum(&cksum); + free(buf); + return GSS_S_FAILURE; + } + + /* Token is { "header" | get_mic("header" | plaintext-data) } */ + memcpy(message_token->value, token, sizeof(*token)); + memcpy((u_char *)message_token->value + sizeof(*token), + cksum.checksum.data, cksum.checksum.length); + + free_Checksum(&cksum); + free(buf); + + *minor_status = 0; + return GSS_S_COMPLETE; +} + +OM_uint32 _gssapi_verify_mic_cfx(OM_uint32 *minor_status, + const gsskrb5_ctx context_handle, + const gss_buffer_t message_buffer, + const gss_buffer_t token_buffer, + gss_qop_t *qop_state, + krb5_keyblock *key) +{ + krb5_crypto crypto; + gss_cfx_mic_token token; + u_char token_flags; + krb5_error_code ret; + unsigned usage; + OM_uint32 seq_number_lo, seq_number_hi; + u_char *buf, *p; + Checksum cksum; + + *minor_status = 0; + + if (token_buffer->length < sizeof(*token)) { + return GSS_S_DEFECTIVE_TOKEN; + } + + p = token_buffer->value; + + token = (gss_cfx_mic_token)p; + + if (token->TOK_ID[0] != 0x04 || token->TOK_ID[1] != 0x04) { + return GSS_S_DEFECTIVE_TOKEN; + } + + /* Ignore unknown flags */ + token_flags = token->Flags & (CFXSentByAcceptor | CFXAcceptorSubkey); + + if (token_flags & CFXSentByAcceptor) { + if ((context_handle->more_flags & LOCAL) == 0) + return GSS_S_DEFECTIVE_TOKEN; + } + if (context_handle->more_flags & ACCEPTOR_SUBKEY) { + if ((token_flags & CFXAcceptorSubkey) == 0) + return GSS_S_DEFECTIVE_TOKEN; + } else { + if (token_flags & CFXAcceptorSubkey) + return GSS_S_DEFECTIVE_TOKEN; + } + + if (memcmp(token->Filler, "\xff\xff\xff\xff\xff", 5) != 0) { + return GSS_S_DEFECTIVE_TOKEN; + } + + /* + * Check sequence number + */ + _gsskrb5_decode_be_om_uint32(&token->SND_SEQ[0], &seq_number_hi); + _gsskrb5_decode_be_om_uint32(&token->SND_SEQ[4], &seq_number_lo); + if (seq_number_hi) { + *minor_status = ERANGE; + return GSS_S_UNSEQ_TOKEN; + } + + HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex); + ret = _gssapi_msg_order_check(context_handle->order, seq_number_lo); + if (ret != 0) { + *minor_status = 0; + HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); + return ret; + } + HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); + + /* + * Verify checksum + */ + ret = krb5_crypto_init(_gsskrb5_context, key, 0, &crypto); + if (ret != 0) { + _gsskrb5_set_error_string(); + *minor_status = ret; + return GSS_S_FAILURE; + } + + ret = krb5_crypto_get_checksum_type(_gsskrb5_context, crypto, + &cksum.cksumtype); + if (ret != 0) { + _gsskrb5_set_error_string(); + *minor_status = ret; + krb5_crypto_destroy(_gsskrb5_context, crypto); + return GSS_S_FAILURE; + } + + cksum.checksum.data = p + sizeof(*token); + cksum.checksum.length = token_buffer->length - sizeof(*token); + + if (context_handle->more_flags & LOCAL) { + usage = KRB5_KU_USAGE_ACCEPTOR_SIGN; + } else { + usage = KRB5_KU_USAGE_INITIATOR_SIGN; + } + + buf = malloc(message_buffer->length + sizeof(*token)); + if (buf == NULL) { + *minor_status = ENOMEM; + krb5_crypto_destroy(_gsskrb5_context, crypto); + return GSS_S_FAILURE; + } + memcpy(buf, message_buffer->value, message_buffer->length); + memcpy(buf + message_buffer->length, token, sizeof(*token)); + + ret = krb5_verify_checksum(_gsskrb5_context, crypto, + usage, + buf, + sizeof(*token) + message_buffer->length, + &cksum); + krb5_crypto_destroy(_gsskrb5_context, crypto); + if (ret != 0) { + _gsskrb5_set_error_string(); + *minor_status = ret; + free(buf); + return GSS_S_BAD_MIC; + } + + free(buf); + + if (qop_state != NULL) { + *qop_state = GSS_C_QOP_DEFAULT; + } + + return GSS_S_COMPLETE; +} diff --git a/source4/heimdal/lib/gssapi/krb5/cfx.h b/source4/heimdal/lib/gssapi/krb5/cfx.h new file mode 100755 index 0000000000..1120544fbe --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/cfx.h @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2003, PADL Software Pty Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of PADL Software nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* $Id: cfx.h,v 1.7 2006/07/19 14:16:33 lha Exp $ */ + +#ifndef GSSAPI_CFX_H_ +#define GSSAPI_CFX_H_ 1 + +/* + * Implementation of draft-ietf-krb-wg-gssapi-cfx-01.txt + */ + +typedef struct gss_cfx_mic_token_desc_struct { + u_char TOK_ID[2]; /* 04 04 */ + u_char Flags; + u_char Filler[5]; + u_char SND_SEQ[8]; +} gss_cfx_mic_token_desc, *gss_cfx_mic_token; + +typedef struct gss_cfx_wrap_token_desc_struct { + u_char TOK_ID[2]; /* 04 05 */ + u_char Flags; + u_char Filler; + u_char EC[2]; + u_char RRC[2]; + u_char SND_SEQ[8]; +} gss_cfx_wrap_token_desc, *gss_cfx_wrap_token; + +typedef struct gss_cfx_delete_token_desc_struct { + u_char TOK_ID[2]; /* 05 04 */ + u_char Flags; + u_char Filler[5]; + u_char SND_SEQ[8]; +} gss_cfx_delete_token_desc, *gss_cfx_delete_token; + +krb5_error_code +_gsskrb5cfx_wrap_length_cfx(krb5_crypto crypto, + int conf_req_flag, + size_t input_length, + size_t *output_length, + size_t *cksumsize, + uint16_t *padlength); + +krb5_error_code +_gsskrb5cfx_max_wrap_length_cfx(krb5_crypto crypto, + int conf_req_flag, + size_t input_length, + OM_uint32 *output_length); + + +#endif /* GSSAPI_CFX_H_ */ diff --git a/source4/heimdal/lib/gssapi/krb5/compare_name.c b/source4/heimdal/lib/gssapi/krb5/compare_name.c new file mode 100644 index 0000000000..3e0f7edfee --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/compare_name.c @@ -0,0 +1,54 @@ +/* + * Copyright (c) 1997-2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id: compare_name.c,v 1.7 2006/10/07 22:14:15 lha Exp $"); + +OM_uint32 _gsskrb5_compare_name + (OM_uint32 * minor_status, + const gss_name_t name1, + const gss_name_t name2, + int * name_equal + ) +{ + krb5_const_principal princ1 = (krb5_const_principal)name1; + krb5_const_principal princ2 = (krb5_const_principal)name2; + + GSSAPI_KRB5_INIT(); + + *name_equal = krb5_principal_compare (_gsskrb5_context, + princ1, princ2); + *minor_status = 0; + return GSS_S_COMPLETE; +} diff --git a/source4/heimdal/lib/gssapi/krb5/compat.c b/source4/heimdal/lib/gssapi/krb5/compat.c new file mode 100644 index 0000000000..0ea2fce0e8 --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/compat.c @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2003 - 2005 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id: compat.c,v 1.13 2006/10/07 22:14:17 lha Exp $"); + + +static krb5_error_code +check_compat(OM_uint32 *minor_status, krb5_const_principal name, + const char *option, krb5_boolean *compat, + krb5_boolean match_val) +{ + krb5_error_code ret = 0; + char **p, **q; + krb5_principal match; + + + p = krb5_config_get_strings(_gsskrb5_context, NULL, "gssapi", + option, NULL); + if(p == NULL) + return 0; + + match = NULL; + for(q = p; *q; q++) { + ret = krb5_parse_name(_gsskrb5_context, *q, &match); + if (ret) + break; + + if (krb5_principal_match(_gsskrb5_context, name, match)) { + *compat = match_val; + break; + } + + krb5_free_principal(_gsskrb5_context, match); + match = NULL; + } + if (match) + krb5_free_principal(_gsskrb5_context, match); + krb5_config_free_strings(p); + + if (ret) { + if (minor_status) + *minor_status = ret; + return GSS_S_FAILURE; + } + + return 0; +} + +/* + * ctx->ctx_id_mutex is assumed to be locked + */ + +OM_uint32 +_gss_DES3_get_mic_compat(OM_uint32 *minor_status, gsskrb5_ctx ctx) +{ + krb5_boolean use_compat = FALSE; + OM_uint32 ret; + + if ((ctx->more_flags & COMPAT_OLD_DES3_SELECTED) == 0) { + ret = check_compat(minor_status, ctx->target, + "broken_des3_mic", &use_compat, TRUE); + if (ret) + return ret; + ret = check_compat(minor_status, ctx->target, + "correct_des3_mic", &use_compat, FALSE); + if (ret) + return ret; + + if (use_compat) + ctx->more_flags |= COMPAT_OLD_DES3; + ctx->more_flags |= COMPAT_OLD_DES3_SELECTED; + } + return 0; +} + +#if 0 +OM_uint32 +gss_krb5_compat_des3_mic(OM_uint32 *minor_status, gss_ctx_id_t ctx, int on) +{ + *minor_status = 0; + + HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); + if (on) { + ctx->more_flags |= COMPAT_OLD_DES3; + } else { + ctx->more_flags &= ~COMPAT_OLD_DES3; + } + ctx->more_flags |= COMPAT_OLD_DES3_SELECTED; + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + + return 0; +} +#endif diff --git a/source4/heimdal/lib/gssapi/krb5/context_time.c b/source4/heimdal/lib/gssapi/krb5/context_time.c new file mode 100644 index 0000000000..4e9d9f5d1d --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/context_time.c @@ -0,0 +1,93 @@ +/* + * Copyright (c) 1997 - 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id: context_time.c,v 1.13 2006/10/07 22:14:19 lha Exp $"); + +OM_uint32 +_gsskrb5_lifetime_left(OM_uint32 *minor_status, + OM_uint32 lifetime, + OM_uint32 *lifetime_rec) +{ + krb5_timestamp timeret; + krb5_error_code kret; + + if (lifetime == 0) { + *lifetime_rec = GSS_C_INDEFINITE; + return GSS_S_COMPLETE; + } + + kret = krb5_timeofday(_gsskrb5_context, &timeret); + if (kret) { + *minor_status = kret; + _gsskrb5_set_error_string (); + return GSS_S_FAILURE; + } + + if (lifetime < timeret) + *lifetime_rec = 0; + else + *lifetime_rec = lifetime - timeret; + + return GSS_S_COMPLETE; +} + + +OM_uint32 _gsskrb5_context_time + (OM_uint32 * minor_status, + const gss_ctx_id_t context_handle, + OM_uint32 * time_rec + ) +{ + OM_uint32 lifetime; + OM_uint32 major_status; + const gsskrb5_ctx ctx = (const gsskrb5_ctx) context_handle; + + GSSAPI_KRB5_INIT (); + + HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); + lifetime = ctx->lifetime; + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + + major_status = _gsskrb5_lifetime_left(minor_status, lifetime, time_rec); + if (major_status != GSS_S_COMPLETE) + return major_status; + + *minor_status = 0; + + if (*time_rec == 0) + return GSS_S_CONTEXT_EXPIRED; + + return GSS_S_COMPLETE; +} diff --git a/source4/heimdal/lib/gssapi/krb5/copy_ccache.c b/source4/heimdal/lib/gssapi/krb5/copy_ccache.c new file mode 100644 index 0000000000..99aa2ccb43 --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/copy_ccache.c @@ -0,0 +1,191 @@ +/* + * Copyright (c) 2000 - 2001, 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id: copy_ccache.c,v 1.15 2006/10/07 22:14:22 lha Exp $"); + +#if 0 +OM_uint32 +gss_krb5_copy_ccache(OM_uint32 *minor_status, + gss_cred_id_t cred, + krb5_ccache out) +{ + krb5_error_code kret; + + HEIMDAL_MUTEX_lock(&cred->cred_id_mutex); + + if (cred->ccache == NULL) { + HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex); + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + + kret = krb5_cc_copy_cache(_gsskrb5_context, cred->ccache, out); + HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex); + if (kret) { + *minor_status = kret; + _gsskrb5_set_error_string (); + return GSS_S_FAILURE; + } + *minor_status = 0; + return GSS_S_COMPLETE; +} +#endif + + +OM_uint32 +_gsskrb5_import_cred(OM_uint32 *minor_status, + krb5_ccache id, + krb5_principal keytab_principal, + krb5_keytab keytab, + gss_cred_id_t *cred) +{ + krb5_error_code kret; + gsskrb5_cred handle; + OM_uint32 ret; + + *cred = NULL; + + GSSAPI_KRB5_INIT (); + + handle = calloc(1, sizeof(*handle)); + if (handle == NULL) { + _gsskrb5_clear_status (); + *minor_status = ENOMEM; + return (GSS_S_FAILURE); + } + HEIMDAL_MUTEX_init(&handle->cred_id_mutex); + + handle->usage = 0; + + if (id) { + char *str; + + handle->usage |= GSS_C_INITIATE; + + kret = krb5_cc_get_principal(_gsskrb5_context, id, + &handle->principal); + if (kret) { + free(handle); + _gsskrb5_set_error_string (); + *minor_status = kret; + return GSS_S_FAILURE; + } + + if (keytab_principal) { + krb5_boolean match; + + match = krb5_principal_compare(_gsskrb5_context, + handle->principal, + keytab_principal); + if (match == FALSE) { + krb5_free_principal(_gsskrb5_context, handle->principal); + free(handle); + _gsskrb5_clear_status (); + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + } + + ret = __gsskrb5_ccache_lifetime(minor_status, + id, + handle->principal, + &handle->lifetime); + if (ret != GSS_S_COMPLETE) { + krb5_free_principal(_gsskrb5_context, handle->principal); + free(handle); + return ret; + } + + + kret = krb5_cc_get_full_name(_gsskrb5_context, id, &str); + if (kret) + goto out; + + kret = krb5_cc_resolve(_gsskrb5_context, str, &handle->ccache); + free(str); + if (kret) + goto out; + } + + + if (keytab) { + char *str; + + handle->usage |= GSS_C_ACCEPT; + + if (keytab_principal && handle->principal == NULL) { + kret = krb5_copy_principal(_gsskrb5_context, + keytab_principal, + &handle->principal); + if (kret) + goto out; + } + + kret = krb5_kt_get_full_name(_gsskrb5_context, keytab, &str); + if (kret) + goto out; + + kret = krb5_kt_resolve(_gsskrb5_context, str, &handle->keytab); + free(str); + if (kret) + goto out; + } + + + if (id || keytab) { + ret = _gsskrb5_create_empty_oid_set(minor_status, &handle->mechanisms); + if (ret == GSS_S_COMPLETE) + ret = _gsskrb5_add_oid_set_member(minor_status, GSS_KRB5_MECHANISM, + &handle->mechanisms); + if (ret != GSS_S_COMPLETE) { + kret = *minor_status; + goto out; + } + } + + *minor_status = 0; + *cred = (gss_cred_id_t)handle; + return GSS_S_COMPLETE; + +out: + _gsskrb5_set_error_string (); + if (handle->principal) + krb5_free_principal(_gsskrb5_context, handle->principal); + HEIMDAL_MUTEX_destroy(&handle->cred_id_mutex); + free(handle); + *minor_status = kret; + return GSS_S_FAILURE; +} + diff --git a/source4/heimdal/lib/gssapi/krb5/create_emtpy_oid_set.c b/source4/heimdal/lib/gssapi/krb5/create_emtpy_oid_set.c new file mode 100644 index 0000000000..550995125a --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/create_emtpy_oid_set.c @@ -0,0 +1,52 @@ +/* + * Copyright (c) 1997 - 2001, 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id: create_emtpy_oid_set.c,v 1.7 2006/10/07 22:14:24 lha Exp $"); + +OM_uint32 _gsskrb5_create_empty_oid_set ( + OM_uint32 * minor_status, + gss_OID_set * oid_set + ) +{ + *oid_set = malloc(sizeof(**oid_set)); + if (*oid_set == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + (*oid_set)->count = 0; + (*oid_set)->elements = NULL; + *minor_status = 0; + return GSS_S_COMPLETE; +} diff --git a/source4/heimdal/lib/gssapi/krb5/decapsulate.c b/source4/heimdal/lib/gssapi/krb5/decapsulate.c new file mode 100644 index 0000000000..eadec1ef03 --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/decapsulate.c @@ -0,0 +1,209 @@ +/* + * Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id: decapsulate.c,v 1.16 2006/10/07 22:14:26 lha Exp $"); + +/* + * return the length of the mechanism in token or -1 + * (which implies that the token was bad - GSS_S_DEFECTIVE_TOKEN + */ + +ssize_t +_gsskrb5_get_mech (const u_char *ptr, + size_t total_len, + const u_char **mech_ret) +{ + size_t len, len_len, mech_len, foo; + const u_char *p = ptr; + int e; + + if (total_len < 1) + return -1; + if (*p++ != 0x60) + return -1; + e = der_get_length (p, total_len - 1, &len, &len_len); + if (e || 1 + len_len + len != total_len) + return -1; + p += len_len; + if (*p++ != 0x06) + return -1; + e = der_get_length (p, total_len - 1 - len_len - 1, + &mech_len, &foo); + if (e) + return -1; + p += foo; + *mech_ret = p; + return mech_len; +} + +OM_uint32 +_gssapi_verify_mech_header(u_char **str, + size_t total_len, + gss_OID mech) +{ + const u_char *p; + ssize_t mech_len; + + mech_len = _gsskrb5_get_mech (*str, total_len, &p); + if (mech_len < 0) + return GSS_S_DEFECTIVE_TOKEN; + + if (mech_len != mech->length) + return GSS_S_BAD_MECH; + if (memcmp(p, + mech->elements, + mech->length) != 0) + return GSS_S_BAD_MECH; + p += mech_len; + *str = rk_UNCONST(p); + return GSS_S_COMPLETE; +} + +OM_uint32 +_gsskrb5_verify_header(u_char **str, + size_t total_len, + const void *type, + gss_OID oid) +{ + OM_uint32 ret; + size_t len; + u_char *p = *str; + + ret = _gssapi_verify_mech_header(str, total_len, oid); + if (ret) + return ret; + + len = total_len - (*str - p); + + if (len < 2) + return GSS_S_DEFECTIVE_TOKEN; + + if (memcmp (*str, type, 2) != 0) + return GSS_S_DEFECTIVE_TOKEN; + *str += 2; + + return 0; +} + +/* + * Remove the GSS-API wrapping from `in_token' giving `out_data. + * Does not copy data, so just free `in_token'. + */ + +OM_uint32 +_gssapi_decapsulate( + OM_uint32 *minor_status, + gss_buffer_t input_token_buffer, + krb5_data *out_data, + const gss_OID mech +) +{ + u_char *p; + OM_uint32 ret; + + p = input_token_buffer->value; + ret = _gssapi_verify_mech_header(&p, + input_token_buffer->length, + mech); + if (ret) { + *minor_status = 0; + return ret; + } + + out_data->length = input_token_buffer->length - + (p - (u_char *)input_token_buffer->value); + out_data->data = p; + return GSS_S_COMPLETE; +} + +/* + * Remove the GSS-API wrapping from `in_token' giving `out_data. + * Does not copy data, so just free `in_token'. + */ + +OM_uint32 +_gsskrb5_decapsulate(OM_uint32 *minor_status, + gss_buffer_t input_token_buffer, + krb5_data *out_data, + const void *type, + gss_OID oid) +{ + u_char *p; + OM_uint32 ret; + + p = input_token_buffer->value; + ret = _gsskrb5_verify_header(&p, + input_token_buffer->length, + type, + oid); + if (ret) { + *minor_status = 0; + return ret; + } + + out_data->length = input_token_buffer->length - + (p - (u_char *)input_token_buffer->value); + out_data->data = p; + return GSS_S_COMPLETE; +} + +/* + * Verify padding of a gss wrapped message and return its length. + */ + +OM_uint32 +_gssapi_verify_pad(gss_buffer_t wrapped_token, + size_t datalen, + size_t *padlen) +{ + u_char *pad; + size_t padlength; + int i; + + pad = (u_char *)wrapped_token->value + wrapped_token->length - 1; + padlength = *pad; + + if (padlength > datalen) + return GSS_S_BAD_MECH; + + for (i = padlength; i > 0 && *pad == padlength; i--, pad--) + ; + if (i != 0) + return GSS_S_BAD_MIC; + + *padlen = padlength; + + return 0; +} diff --git a/source4/heimdal/lib/gssapi/krb5/delete_sec_context.c b/source4/heimdal/lib/gssapi/krb5/delete_sec_context.c new file mode 100644 index 0000000000..e890d7d2c2 --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/delete_sec_context.c @@ -0,0 +1,80 @@ +/* + * Copyright (c) 1997 - 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id: delete_sec_context.c,v 1.19 2006/10/07 22:14:28 lha Exp $"); + +OM_uint32 +_gsskrb5_delete_sec_context(OM_uint32 * minor_status, + gss_ctx_id_t * context_handle, + gss_buffer_t output_token) +{ + gsskrb5_ctx ctx; + + GSSAPI_KRB5_INIT (); + + *minor_status = 0; + + if (output_token) { + output_token->length = 0; + output_token->value = NULL; + } + + if (*context_handle == GSS_C_NO_CONTEXT) + return GSS_S_COMPLETE; + + ctx = (gsskrb5_ctx) *context_handle; + *context_handle = GSS_C_NO_CONTEXT; + + HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); + + krb5_auth_con_free (_gsskrb5_context, ctx->auth_context); + if(ctx->source) + krb5_free_principal (_gsskrb5_context, ctx->source); + if(ctx->target) + krb5_free_principal (_gsskrb5_context, ctx->target); + if (ctx->ticket) + krb5_free_ticket (_gsskrb5_context, ctx->ticket); + if(ctx->order) + _gssapi_msg_order_destroy(&ctx->order); + if (ctx->service_keyblock) + krb5_free_keyblock (_gsskrb5_context, ctx->service_keyblock); + krb5_data_free(&ctx->fwd_data); + + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + HEIMDAL_MUTEX_destroy(&ctx->ctx_id_mutex); + memset(ctx, 0, sizeof(*ctx)); + free (ctx); + return GSS_S_COMPLETE; +} diff --git a/source4/heimdal/lib/gssapi/krb5/display_name.c b/source4/heimdal/lib/gssapi/krb5/display_name.c new file mode 100644 index 0000000000..8fce7d8572 --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/display_name.c @@ -0,0 +1,72 @@ +/* + * Copyright (c) 1997 - 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id: display_name.c,v 1.12 2006/10/07 22:14:31 lha Exp $"); + +OM_uint32 _gsskrb5_display_name + (OM_uint32 * minor_status, + const gss_name_t input_name, + gss_buffer_t output_name_buffer, + gss_OID * output_name_type + ) +{ + krb5_const_principal name = (krb5_const_principal)input_name; + krb5_error_code kret; + char *buf; + size_t len; + + GSSAPI_KRB5_INIT (); + kret = krb5_unparse_name (_gsskrb5_context, name, &buf); + if (kret) { + *minor_status = kret; + _gsskrb5_set_error_string (); + return GSS_S_FAILURE; + } + len = strlen (buf); + output_name_buffer->length = len; + output_name_buffer->value = malloc(len + 1); + if (output_name_buffer->value == NULL) { + free (buf); + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + memcpy (output_name_buffer->value, buf, len); + ((char *)output_name_buffer->value)[len] = '\0'; + free (buf); + if (output_name_type) + *output_name_type = GSS_KRB5_NT_PRINCIPAL_NAME; + *minor_status = 0; + return GSS_S_COMPLETE; +} diff --git a/source4/heimdal/lib/gssapi/krb5/display_status.c b/source4/heimdal/lib/gssapi/krb5/display_status.c new file mode 100644 index 0000000000..11926ca557 --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/display_status.c @@ -0,0 +1,230 @@ +/* + * Copyright (c) 1998 - 2005 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id: display_status.c,v 1.16 2006/10/07 22:14:33 lha Exp $"); + +static const char * +calling_error(OM_uint32 v) +{ + static const char *msgs[] = { + NULL, /* 0 */ + "A required input parameter could not be read.", /* */ + "A required output parameter could not be written.", /* */ + "A parameter was malformed" + }; + + v >>= GSS_C_CALLING_ERROR_OFFSET; + + if (v == 0) + return ""; + else if (v >= sizeof(msgs)/sizeof(*msgs)) + return "unknown calling error"; + else + return msgs[v]; +} + +static const char * +routine_error(OM_uint32 v) +{ + static const char *msgs[] = { + NULL, /* 0 */ + "An unsupported mechanism was requested", + "An invalid name was supplied", + "A supplied name was of an unsupported type", + "Incorrect channel bindings were supplied", + "An invalid status code was supplied", + "A token had an invalid MIC", + "No credentials were supplied, " + "or the credentials were unavailable or inaccessible.", + "No context has been established", + "A token was invalid", + "A credential was invalid", + "The referenced credentials have expired", + "The context has expired", + "Miscellaneous failure (see text)", + "The quality-of-protection requested could not be provide", + "The operation is forbidden by local security policy", + "The operation or option is not available", + "The requested credential element already exists", + "The provided name was not a mechanism name.", + }; + + v >>= GSS_C_ROUTINE_ERROR_OFFSET; + + if (v == 0) + return ""; + else if (v >= sizeof(msgs)/sizeof(*msgs)) + return "unknown routine error"; + else + return msgs[v]; +} + +static const char * +supplementary_error(OM_uint32 v) +{ + static const char *msgs[] = { + "normal completion", + "continuation call to routine required", + "duplicate per-message token detected", + "timed-out per-message token detected", + "reordered (early) per-message token detected", + "skipped predecessor token(s) detected" + }; + + v >>= GSS_C_SUPPLEMENTARY_OFFSET; + + if (v >= sizeof(msgs)/sizeof(*msgs)) + return "unknown routine error"; + else + return msgs[v]; +} + +void +_gsskrb5_clear_status (void) +{ + struct gssapi_thr_context *ctx = _gsskrb5_get_thread_context(1); + if (ctx == NULL) + return; + HEIMDAL_MUTEX_lock(&ctx->mutex); + if (ctx->error_string) + free(ctx->error_string); + ctx->error_string = NULL; + HEIMDAL_MUTEX_unlock(&ctx->mutex); +} + +void +_gsskrb5_set_status (const char *fmt, ...) +{ + struct gssapi_thr_context *ctx = _gsskrb5_get_thread_context(1); + va_list args; + + if (ctx == NULL) + return; + HEIMDAL_MUTEX_lock(&ctx->mutex); + va_start(args, fmt); + if (ctx->error_string) + free(ctx->error_string); + /* ignore failures, will use status code instead */ + vasprintf(&ctx->error_string, fmt, args); + va_end(args); + HEIMDAL_MUTEX_unlock(&ctx->mutex); +} + +void +_gsskrb5_set_error_string (void) +{ + char *e; + + e = krb5_get_error_string(_gsskrb5_context); + if (e) { + _gsskrb5_set_status("%s", e); + krb5_free_error_string(_gsskrb5_context, e); + } else + _gsskrb5_clear_status(); +} + +char * +_gsskrb5_get_error_string (void) +{ + struct gssapi_thr_context *ctx = _gsskrb5_get_thread_context(0); + char *ret; + + if (ctx == NULL) + return NULL; + HEIMDAL_MUTEX_lock(&ctx->mutex); + ret = ctx->error_string; + ctx->error_string = NULL; + HEIMDAL_MUTEX_unlock(&ctx->mutex); + return ret; +} + +OM_uint32 _gsskrb5_display_status + (OM_uint32 *minor_status, + OM_uint32 status_value, + int status_type, + const gss_OID mech_type, + OM_uint32 *message_context, + gss_buffer_t status_string) +{ + char *buf; + + GSSAPI_KRB5_INIT (); + + status_string->length = 0; + status_string->value = NULL; + + if (gss_oid_equal(mech_type, GSS_C_NO_OID) == 0 && + gss_oid_equal(mech_type, GSS_KRB5_MECHANISM) == 0) { + *minor_status = 0; + return GSS_C_GSS_CODE; + } + + if (status_type == GSS_C_GSS_CODE) { + if (GSS_SUPPLEMENTARY_INFO(status_value)) + asprintf(&buf, "%s", + supplementary_error(GSS_SUPPLEMENTARY_INFO(status_value))); + else + asprintf (&buf, "%s %s", + calling_error(GSS_CALLING_ERROR(status_value)), + routine_error(GSS_ROUTINE_ERROR(status_value))); + } else if (status_type == GSS_C_MECH_CODE) { + buf = _gsskrb5_get_error_string (); + if (buf == NULL) { + const char *tmp = krb5_get_err_text (_gsskrb5_context, + status_value); + if (tmp == NULL) + asprintf(&buf, "unknown mech error-code %u", + (unsigned)status_value); + else + buf = strdup(tmp); + } + } else { + *minor_status = EINVAL; + return GSS_S_BAD_STATUS; + } + + if (buf == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + *message_context = 0; + *minor_status = 0; + + status_string->length = strlen(buf); + status_string->value = buf; + + return GSS_S_COMPLETE; +} diff --git a/source4/heimdal/lib/gssapi/krb5/duplicate_name.c b/source4/heimdal/lib/gssapi/krb5/duplicate_name.c new file mode 100644 index 0000000000..475ae61efc --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/duplicate_name.c @@ -0,0 +1,59 @@ +/* + * Copyright (c) 1997 - 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id: duplicate_name.c,v 1.10 2006/10/07 22:14:35 lha Exp $"); + +OM_uint32 _gsskrb5_duplicate_name ( + OM_uint32 * minor_status, + const gss_name_t src_name, + gss_name_t * dest_name + ) +{ + krb5_const_principal src = (krb5_const_principal)src_name; + krb5_principal *dest = (krb5_principal *)dest_name; + krb5_error_code kret; + + GSSAPI_KRB5_INIT (); + + kret = krb5_copy_principal (_gsskrb5_context, src, dest); + if (kret) { + *minor_status = kret; + _gsskrb5_set_error_string (); + return GSS_S_FAILURE; + } else { + *minor_status = 0; + return GSS_S_COMPLETE; + } +} diff --git a/source4/heimdal/lib/gssapi/krb5/encapsulate.c b/source4/heimdal/lib/gssapi/krb5/encapsulate.c new file mode 100644 index 0000000000..a015a95103 --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/encapsulate.c @@ -0,0 +1,155 @@ +/* + * Copyright (c) 1997 - 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id: encapsulate.c,v 1.12 2006/10/14 10:02:56 lha Exp $"); + +void +_gssapi_encap_length (size_t data_len, + size_t *len, + size_t *total_len, + const gss_OID mech) +{ + size_t len_len; + + *len = 1 + 1 + mech->length + data_len; + + len_len = der_length_len(*len); + + *total_len = 1 + len_len + *len; +} + +void +_gsskrb5_encap_length (size_t data_len, + size_t *len, + size_t *total_len, + const gss_OID mech) +{ + _gssapi_encap_length(data_len + 2, len, total_len, mech); +} + +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; +} + +void * +_gssapi_make_mech_header(void *ptr, + size_t len, + const gss_OID mech) +{ + u_char *p = ptr; + int e; + size_t len_len, foo; + + *p++ = 0x60; + len_len = der_length_len(len); + e = der_put_length (p + len_len - 1, len_len, len, &foo); + if(e || foo != len_len) + abort (); + p += len_len; + *p++ = 0x06; + *p++ = mech->length; + memcpy (p, mech->elements, mech->length); + p += mech->length; + return p; +} + +/* + * Give it a krb5_data and it will encapsulate with extra GSS-API wrappings. + */ + +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; +} + +/* + * Give it a krb5_data and it will encapsulate with extra GSS-API krb5 + * wrappings. + */ + +OM_uint32 +_gsskrb5_encapsulate( + OM_uint32 *minor_status, + const krb5_data *in_data, + gss_buffer_t output_token, + const void *type, + const gss_OID mech +) +{ + size_t len, outer_len; + u_char *p; + + _gsskrb5_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 = _gsskrb5_make_header (output_token->value, len, type, mech); + memcpy (p, in_data->data, in_data->length); + return GSS_S_COMPLETE; +} diff --git a/source4/heimdal/lib/gssapi/krb5/export_name.c b/source4/heimdal/lib/gssapi/krb5/export_name.c new file mode 100644 index 0000000000..d00c458898 --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/export_name.c @@ -0,0 +1,93 @@ +/* + * Copyright (c) 1997, 1999, 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id: export_name.c,v 1.8 2006/10/07 22:14:40 lha Exp $"); + +OM_uint32 _gsskrb5_export_name + (OM_uint32 * minor_status, + const gss_name_t input_name, + gss_buffer_t exported_name + ) +{ + krb5_const_principal princ = (krb5_const_principal)input_name; + krb5_error_code kret; + char *buf, *name; + size_t len; + + GSSAPI_KRB5_INIT (); + kret = krb5_unparse_name (_gsskrb5_context, princ, &name); + if (kret) { + *minor_status = kret; + _gsskrb5_set_error_string (); + return GSS_S_FAILURE; + } + len = strlen (name); + + exported_name->length = 10 + len + GSS_KRB5_MECHANISM->length; + exported_name->value = malloc(exported_name->length); + if (exported_name->value == NULL) { + free (name); + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + /* TOK, MECH_OID_LEN, DER(MECH_OID), NAME_LEN, NAME */ + + buf = exported_name->value; + memcpy(buf, "\x04\x01", 2); + buf += 2; + buf[0] = ((GSS_KRB5_MECHANISM->length + 2) >> 8) & 0xff; + buf[1] = (GSS_KRB5_MECHANISM->length + 2) & 0xff; + buf+= 2; + buf[0] = 0x06; + buf[1] = (GSS_KRB5_MECHANISM->length) & 0xFF; + buf+= 2; + + memcpy(buf, GSS_KRB5_MECHANISM->elements, GSS_KRB5_MECHANISM->length); + buf += GSS_KRB5_MECHANISM->length; + + buf[0] = (len >> 24) & 0xff; + buf[1] = (len >> 16) & 0xff; + buf[2] = (len >> 8) & 0xff; + buf[3] = (len) & 0xff; + buf += 4; + + memcpy (buf, name, len); + + free (name); + + *minor_status = 0; + return GSS_S_COMPLETE; +} diff --git a/source4/heimdal/lib/gssapi/krb5/export_sec_context.c b/source4/heimdal/lib/gssapi/krb5/export_sec_context.c new file mode 100644 index 0000000000..aff03a0b67 --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/export_sec_context.c @@ -0,0 +1,239 @@ +/* + * Copyright (c) 1999 - 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id: export_sec_context.c,v 1.11 2006/10/07 22:14:42 lha Exp $"); + +OM_uint32 +_gsskrb5_export_sec_context ( + OM_uint32 * minor_status, + gss_ctx_id_t * context_handle, + gss_buffer_t interprocess_token + ) +{ + const gsskrb5_ctx ctx = (const gsskrb5_ctx) *context_handle; + krb5_storage *sp; + krb5_auth_context ac; + OM_uint32 ret = GSS_S_COMPLETE; + krb5_data data; + gss_buffer_desc buffer; + int flags; + OM_uint32 minor; + krb5_error_code kret; + + GSSAPI_KRB5_INIT (); + + HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); + + if (!(ctx->flags & GSS_C_TRANS_FLAG)) { + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + *minor_status = 0; + return GSS_S_UNAVAILABLE; + } + + sp = krb5_storage_emem (); + if (sp == NULL) { + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + ac = ctx->auth_context; + + /* flagging included fields */ + + flags = 0; + if (ac->local_address) + flags |= SC_LOCAL_ADDRESS; + if (ac->remote_address) + flags |= SC_REMOTE_ADDRESS; + if (ac->keyblock) + flags |= SC_KEYBLOCK; + if (ac->local_subkey) + flags |= SC_LOCAL_SUBKEY; + if (ac->remote_subkey) + flags |= SC_REMOTE_SUBKEY; + + kret = krb5_store_int32 (sp, flags); + if (kret) { + *minor_status = kret; + goto failure; + } + + /* marshall auth context */ + + kret = krb5_store_int32 (sp, ac->flags); + if (kret) { + *minor_status = kret; + goto failure; + } + if (ac->local_address) { + kret = krb5_store_address (sp, *ac->local_address); + if (kret) { + *minor_status = kret; + goto failure; + } + } + if (ac->remote_address) { + kret = krb5_store_address (sp, *ac->remote_address); + if (kret) { + *minor_status = kret; + goto failure; + } + } + kret = krb5_store_int16 (sp, ac->local_port); + if (kret) { + *minor_status = kret; + goto failure; + } + kret = krb5_store_int16 (sp, ac->remote_port); + if (kret) { + *minor_status = kret; + goto failure; + } + if (ac->keyblock) { + kret = krb5_store_keyblock (sp, *ac->keyblock); + if (kret) { + *minor_status = kret; + goto failure; + } + } + if (ac->local_subkey) { + kret = krb5_store_keyblock (sp, *ac->local_subkey); + if (kret) { + *minor_status = kret; + goto failure; + } + } + if (ac->remote_subkey) { + kret = krb5_store_keyblock (sp, *ac->remote_subkey); + if (kret) { + *minor_status = kret; + goto failure; + } + } + kret = krb5_store_int32 (sp, ac->local_seqnumber); + if (kret) { + *minor_status = kret; + goto failure; + } + kret = krb5_store_int32 (sp, ac->remote_seqnumber); + if (kret) { + *minor_status = kret; + goto failure; + } + + kret = krb5_store_int32 (sp, ac->keytype); + if (kret) { + *minor_status = kret; + goto failure; + } + kret = krb5_store_int32 (sp, ac->cksumtype); + if (kret) { + *minor_status = kret; + goto failure; + } + + /* names */ + + ret = _gsskrb5_export_name (minor_status, + (gss_name_t)ctx->source, &buffer); + if (ret) + goto failure; + data.data = buffer.value; + data.length = buffer.length; + kret = krb5_store_data (sp, data); + _gsskrb5_release_buffer (&minor, &buffer); + if (kret) { + *minor_status = kret; + goto failure; + } + + ret = _gsskrb5_export_name (minor_status, + (gss_name_t)ctx->target, &buffer); + if (ret) + goto failure; + data.data = buffer.value; + data.length = buffer.length; + + ret = GSS_S_FAILURE; + + kret = krb5_store_data (sp, data); + _gsskrb5_release_buffer (&minor, &buffer); + if (kret) { + *minor_status = kret; + goto failure; + } + + kret = krb5_store_int32 (sp, ctx->flags); + if (kret) { + *minor_status = kret; + goto failure; + } + kret = krb5_store_int32 (sp, ctx->more_flags); + if (kret) { + *minor_status = kret; + goto failure; + } + kret = krb5_store_int32 (sp, ctx->lifetime); + if (kret) { + *minor_status = kret; + goto failure; + } + kret = _gssapi_msg_order_export(sp, ctx->order); + if (kret ) { + *minor_status = kret; + goto failure; + } + + kret = krb5_storage_to_data (sp, &data); + krb5_storage_free (sp); + if (kret) { + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + *minor_status = kret; + return GSS_S_FAILURE; + } + interprocess_token->length = data.length; + interprocess_token->value = data.data; + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + ret = _gsskrb5_delete_sec_context (minor_status, context_handle, + GSS_C_NO_BUFFER); + if (ret != GSS_S_COMPLETE) + _gsskrb5_release_buffer (NULL, interprocess_token); + *minor_status = 0; + return ret; + failure: + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + krb5_storage_free (sp); + return ret; +} diff --git a/source4/heimdal/lib/gssapi/krb5/external.c b/source4/heimdal/lib/gssapi/krb5/external.c new file mode 100644 index 0000000000..7419bc2fe8 --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/external.c @@ -0,0 +1,408 @@ +/* + * Copyright (c) 1997 - 2000 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5/gsskrb5_locl.h" +#include <gssapi_mech.h> + +RCSID("$Id: external.c,v 1.18 2006/10/20 21:50:24 lha Exp $"); + +/* + * The implementation must reserve static storage for a + * gss_OID_desc object containing the value + * {10, (void *)"\x2a\x86\x48\x86\xf7\x12" + * "\x01\x02\x01\x01"}, + * corresponding to an object-identifier value of + * {iso(1) member-body(2) United States(840) mit(113554) + * infosys(1) gssapi(2) generic(1) user_name(1)}. The constant + * GSS_C_NT_USER_NAME should be initialized to point + * to that gss_OID_desc. + */ + +static gss_OID_desc gss_c_nt_user_name_oid_desc = +{10, rk_UNCONST("\x2a\x86\x48\x86\xf7\x12" "\x01\x02\x01\x01")}; + +gss_OID GSS_C_NT_USER_NAME = &gss_c_nt_user_name_oid_desc; + +/* + * The implementation must reserve static storage for a + * gss_OID_desc object containing the value + * {10, (void *)"\x2a\x86\x48\x86\xf7\x12" + * "\x01\x02\x01\x02"}, + * corresponding to an object-identifier value of + * {iso(1) member-body(2) United States(840) mit(113554) + * infosys(1) gssapi(2) generic(1) machine_uid_name(2)}. + * The constant GSS_C_NT_MACHINE_UID_NAME should be + * initialized to point to that gss_OID_desc. + */ + +static gss_OID_desc gss_c_nt_machine_uid_name_oid_desc = +{10, rk_UNCONST("\x2a\x86\x48\x86\xf7\x12" "\x01\x02\x01\x02")}; + +gss_OID GSS_C_NT_MACHINE_UID_NAME = &gss_c_nt_machine_uid_name_oid_desc; + +/* + * The implementation must reserve static storage for a + * gss_OID_desc object containing the value + * {10, (void *)"\x2a\x86\x48\x86\xf7\x12" + * "\x01\x02\x01\x03"}, + * corresponding to an object-identifier value of + * {iso(1) member-body(2) United States(840) mit(113554) + * infosys(1) gssapi(2) generic(1) string_uid_name(3)}. + * The constant GSS_C_NT_STRING_UID_NAME should be + * initialized to point to that gss_OID_desc. + */ + +static gss_OID_desc gss_c_nt_string_uid_name_oid_desc = +{10, rk_UNCONST("\x2a\x86\x48\x86\xf7\x12" "\x01\x02\x01\x03")}; + +gss_OID GSS_C_NT_STRING_UID_NAME = &gss_c_nt_string_uid_name_oid_desc; + +/* + * The implementation must reserve static storage for a + * gss_OID_desc object containing the value + * {6, (void *)"\x2b\x06\x01\x05\x06\x02"}, + * corresponding to an object-identifier value of + * {iso(1) org(3) dod(6) internet(1) security(5) + * nametypes(6) gss-host-based-services(2)). The constant + * GSS_C_NT_HOSTBASED_SERVICE_X should be initialized to point + * to that gss_OID_desc. This is a deprecated OID value, and + * implementations wishing to support hostbased-service names + * should instead use the GSS_C_NT_HOSTBASED_SERVICE OID, + * defined below, to identify such names; + * GSS_C_NT_HOSTBASED_SERVICE_X should be accepted a synonym + * for GSS_C_NT_HOSTBASED_SERVICE when presented as an input + * parameter, but should not be emitted by GSS-API + * implementations + */ + +static gss_OID_desc gss_c_nt_hostbased_service_x_oid_desc = +{6, rk_UNCONST("\x2b\x06\x01\x05\x06\x02")}; + +gss_OID GSS_C_NT_HOSTBASED_SERVICE_X = &gss_c_nt_hostbased_service_x_oid_desc; + +/* + * The implementation must reserve static storage for a + * gss_OID_desc object containing the value + * {10, (void *)"\x2a\x86\x48\x86\xf7\x12" + * "\x01\x02\x01\x04"}, corresponding to an + * object-identifier value of {iso(1) member-body(2) + * Unites States(840) mit(113554) infosys(1) gssapi(2) + * generic(1) service_name(4)}. The constant + * GSS_C_NT_HOSTBASED_SERVICE should be initialized + * to point to that gss_OID_desc. + */ +static gss_OID_desc gss_c_nt_hostbased_service_oid_desc = +{10, rk_UNCONST("\x2a\x86\x48\x86\xf7\x12" "\x01\x02\x01\x04")}; + +gss_OID GSS_C_NT_HOSTBASED_SERVICE = &gss_c_nt_hostbased_service_oid_desc; + +/* + * The implementation must reserve static storage for a + * gss_OID_desc object containing the value + * {6, (void *)"\x2b\x06\01\x05\x06\x03"}, + * corresponding to an object identifier value of + * {1(iso), 3(org), 6(dod), 1(internet), 5(security), + * 6(nametypes), 3(gss-anonymous-name)}. The constant + * and GSS_C_NT_ANONYMOUS should be initialized to point + * to that gss_OID_desc. + */ + +static gss_OID_desc gss_c_nt_anonymous_oid_desc = +{6, rk_UNCONST("\x2b\x06\01\x05\x06\x03")}; + +gss_OID GSS_C_NT_ANONYMOUS = &gss_c_nt_anonymous_oid_desc; + +/* + * The implementation must reserve static storage for a + * gss_OID_desc object containing the value + * {6, (void *)"\x2b\x06\x01\x05\x06\x04"}, + * corresponding to an object-identifier value of + * {1(iso), 3(org), 6(dod), 1(internet), 5(security), + * 6(nametypes), 4(gss-api-exported-name)}. The constant + * GSS_C_NT_EXPORT_NAME should be initialized to point + * to that gss_OID_desc. + */ + +static gss_OID_desc gss_c_nt_export_name_oid_desc = +{6, rk_UNCONST("\x2b\x06\x01\x05\x06\x04") }; + +gss_OID GSS_C_NT_EXPORT_NAME = &gss_c_nt_export_name_oid_desc; + +/* + * This name form shall be represented by the Object Identifier {iso(1) + * member-body(2) United States(840) mit(113554) infosys(1) gssapi(2) + * krb5(2) krb5_name(1)}. The recommended symbolic name for this type + * is "GSS_KRB5_NT_PRINCIPAL_NAME". + */ + +static gss_OID_desc gss_krb5_nt_principal_name_oid_desc = +{10, rk_UNCONST("\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x01") }; + +gss_OID GSS_KRB5_NT_PRINCIPAL_NAME = &gss_krb5_nt_principal_name_oid_desc; + +/* + * This name form shall be represented by the Object Identifier {iso(1) + * member-body(2) United States(840) mit(113554) infosys(1) gssapi(2) + * generic(1) user_name(1)}. The recommended symbolic name for this + * type is "GSS_KRB5_NT_USER_NAME". + */ + +gss_OID GSS_KRB5_NT_USER_NAME = &gss_c_nt_user_name_oid_desc; + +/* + * This name form shall be represented by the Object Identifier {iso(1) + * member-body(2) United States(840) mit(113554) infosys(1) gssapi(2) + * generic(1) machine_uid_name(2)}. The recommended symbolic name for + * this type is "GSS_KRB5_NT_MACHINE_UID_NAME". + */ + +gss_OID GSS_KRB5_NT_MACHINE_UID_NAME = &gss_c_nt_machine_uid_name_oid_desc; + +/* + * This name form shall be represented by the Object Identifier {iso(1) + * member-body(2) United States(840) mit(113554) infosys(1) gssapi(2) + * generic(1) string_uid_name(3)}. The recommended symbolic name for + * this type is "GSS_KRB5_NT_STRING_UID_NAME". + */ + +gss_OID GSS_KRB5_NT_STRING_UID_NAME = &gss_c_nt_string_uid_name_oid_desc; + +/* + * To support ongoing experimentation, testing, and evolution of the + * specification, the Kerberos V5 GSS-API mechanism as defined in this + * and any successor memos will be identified with the following Object + * Identifier, as defined in RFC-1510, until the specification is + * advanced to the level of Proposed Standard RFC: + * + * {iso(1), org(3), dod(5), internet(1), security(5), kerberosv5(2)} + * + * Upon advancement to the level of Proposed Standard RFC, the Kerberos + * V5 GSS-API mechanism will be identified by an Object Identifier + * having the value: + * + * {iso(1) member-body(2) United States(840) mit(113554) infosys(1) + * gssapi(2) krb5(2)} + */ + +#if 0 /* This is the old OID */ + +static gss_OID_desc gss_krb5_mechanism_oid_desc = +{5, rk_UNCONST("\x2b\x05\x01\x05\x02")}; + +#endif + +static gss_OID_desc gss_krb5_mechanism_oid_desc = +{9, rk_UNCONST("\x2a\x86\x48\x86\xf7\x12\x01\x02\x02") }; + +gss_OID GSS_KRB5_MECHANISM = &gss_krb5_mechanism_oid_desc; + +/* + * draft-ietf-cat-iakerb-09, IAKERB: + * The mechanism ID for IAKERB proxy GSS-API Kerberos, in accordance + * with the mechanism proposed by SPNEGO [7] for negotiating protocol + * variations, is: {iso(1) org(3) dod(6) internet(1) security(5) + * mechanisms(5) iakerb(10) iakerbProxyProtocol(1)}. The proposed + * mechanism ID for IAKERB minimum messages GSS-API Kerberos, in + * accordance with the mechanism proposed by SPNEGO for negotiating + * protocol variations, is: {iso(1) org(3) dod(6) internet(1) + * security(5) mechanisms(5) iakerb(10) + * iakerbMinimumMessagesProtocol(2)}. + */ + +static gss_OID_desc gss_iakerb_proxy_mechanism_oid_desc = +{7, rk_UNCONST("\x2b\x06\x01\x05\x05\x0a\x01")}; + +gss_OID GSS_IAKERB_PROXY_MECHANISM = &gss_iakerb_proxy_mechanism_oid_desc; + +static gss_OID_desc gss_iakerb_min_msg_mechanism_oid_desc = +{7, rk_UNCONST("\x2b\x06\x01\x05\x05\x0a\x02") }; + +gss_OID GSS_IAKERB_MIN_MSG_MECHANISM = &gss_iakerb_min_msg_mechanism_oid_desc; + +/* + * + */ + +static gss_OID_desc gss_c_peer_has_updated_spnego_oid_desc = +{9, (void *)"\x2b\x06\x01\x04\x01\xa9\x4a\x13\x05"}; + +gss_OID GSS_C_PEER_HAS_UPDATED_SPNEGO = &gss_c_peer_has_updated_spnego_oid_desc; + +/* + * 1.2.752.43.13 Heimdal GSS-API Extentions + */ + +/* 1.2.752.43.13.1 */ +static gss_OID_desc gss_krb5_copy_ccache_x_oid_desc = +{6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x01")}; + +gss_OID GSS_KRB5_COPY_CCACHE_X = &gss_krb5_copy_ccache_x_oid_desc; + +/* 1.2.752.43.13.2 */ +static gss_OID_desc gss_krb5_get_tkt_flags_x_oid_desc = +{6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x02")}; + +gss_OID GSS_KRB5_GET_TKT_FLAGS_X = &gss_krb5_get_tkt_flags_x_oid_desc; + +/* 1.2.752.43.13.3 */ +static gss_OID_desc gss_krb5_extract_authz_data_from_sec_context_x_oid_desc = +{6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x03")}; + +gss_OID GSS_KRB5_EXTRACT_AUTHZ_DATA_FROM_SEC_CONTEXT_X = &gss_krb5_extract_authz_data_from_sec_context_x_oid_desc; + +/* 1.2.752.43.13.4 */ +static gss_OID_desc gss_krb5_compat_des3_mic_x_oid_desc = +{6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x04")}; + +gss_OID GSS_KRB5_COMPAT_DES3_MIC_X = &gss_krb5_compat_des3_mic_x_oid_desc; + +/* 1.2.752.43.13.5 */ +static gss_OID_desc gss_krb5_register_acceptor_identity_x_desc = +{6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x05")}; + +gss_OID GSS_KRB5_REGISTER_ACCEPTOR_IDENTITY_X = &gss_krb5_register_acceptor_identity_x_desc; + +/* 1.2.752.43.13.6 */ +static gss_OID_desc gss_krb5_export_lucid_context_x_desc = +{6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x06")}; + +gss_OID GSS_KRB5_EXPORT_LUCID_CONTEXT_X = &gss_krb5_export_lucid_context_x_desc; + +/* 1.2.752.43.13.6.1 */ +static gss_OID_desc gss_krb5_export_lucid_context_v1_x_desc = +{7, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x06\x01")}; + +gss_OID GSS_KRB5_EXPORT_LUCID_CONTEXT_V1_X = &gss_krb5_export_lucid_context_v1_x_desc; + +/* 1.2.752.43.13.7 */ +static gss_OID_desc gss_krb5_set_dns_canonicalize_x_desc = +{6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x07")}; + +gss_OID GSS_KRB5_SET_DNS_CANONICALIZE_X = &gss_krb5_set_dns_canonicalize_x_desc; + +/* 1.2.752.43.13.8 */ +static gss_OID_desc gss_krb5_get_subkey_x_desc = +{6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x08")}; + +gss_OID GSS_KRB5_GET_SUBKEY_X = &gss_krb5_get_subkey_x_desc; + +/* 1.2.752.43.13.9 */ +static gss_OID_desc gss_krb5_get_initiator_subkey_x_desc = +{6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x09")}; + +gss_OID GSS_KRB5_GET_INITIATOR_SUBKEY_X = &gss_krb5_get_initiator_subkey_x_desc; + +/* 1.2.752.43.13.10 */ +static gss_OID_desc gss_krb5_get_acceptor_subkey_x_desc = +{6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x0a")}; + +gss_OID GSS_KRB5_GET_ACCEPTOR_SUBKEY_X = &gss_krb5_get_acceptor_subkey_x_desc; + +/* 1.2.752.43.13.11 */ +static gss_OID_desc gss_krb5_send_to_kdc_x_desc = +{6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x0b")}; + +gss_OID GSS_KRB5_SEND_TO_KDC_X = &gss_krb5_send_to_kdc_x_desc; + +/* 1.2.752.43.13.12 */ +static gss_OID_desc gss_krb5_get_authtime_x_desc = +{6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x0c")}; + +gss_OID GSS_KRB5_GET_AUTHTIME_X = &gss_krb5_get_authtime_x_desc; + +/* 1.2.752.43.13.14 */ +static gss_OID_desc gss_krb5_get_service_keyblock_x_desc = +{6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x0d")}; + +gss_OID GSS_KRB5_GET_SERVICE_KEYBLOCK_X = &gss_krb5_get_service_keyblock_x_desc; + +/* 1.2.752.43.14.1 */ +static gss_OID_desc gss_sasl_digest_md5_mechanism_desc = +{6, rk_UNCONST("\x2a\x85\x70\x2b\x0e\x01") }; + +gss_OID GSS_SASL_DIGEST_MD5_MECHANISM = &gss_sasl_digest_md5_mechanism_desc; + +/* + * Context for krb5 calls. + */ + +krb5_context _gsskrb5_context; + +/* + * + */ + +static gssapi_mech_interface_desc krb5_mech = { + GMI_VERSION, + "kerberos 5", + {9, "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02" }, + _gsskrb5_acquire_cred, + _gsskrb5_release_cred, + _gsskrb5_init_sec_context, + _gsskrb5_accept_sec_context, + _gsskrb5_process_context_token, + _gsskrb5_delete_sec_context, + _gsskrb5_context_time, + _gsskrb5_get_mic, + _gsskrb5_verify_mic, + _gsskrb5_wrap, + _gsskrb5_unwrap, + _gsskrb5_display_status, + _gsskrb5_indicate_mechs, + _gsskrb5_compare_name, + _gsskrb5_display_name, + _gsskrb5_import_name, + _gsskrb5_export_name, + _gsskrb5_release_name, + _gsskrb5_inquire_cred, + _gsskrb5_inquire_context, + _gsskrb5_wrap_size_limit, + _gsskrb5_add_cred, + _gsskrb5_inquire_cred_by_mech, + _gsskrb5_export_sec_context, + _gsskrb5_import_sec_context, + _gsskrb5_inquire_names_for_mech, + _gsskrb5_inquire_mechs_for_name, + _gsskrb5_canonicalize_name, + _gsskrb5_duplicate_name, + _gsskrb5_inquire_sec_context_by_oid, + _gsskrb5_inquire_cred_by_oid, + _gsskrb5_set_sec_context_option, + _gsskrb5_set_cred_option +}; + +gssapi_mech_interface +__gss_krb5_initialize(void) +{ + return &krb5_mech; +} diff --git a/source4/heimdal/lib/gssapi/krb5/get_mic.c b/source4/heimdal/lib/gssapi/krb5/get_mic.c new file mode 100644 index 0000000000..5a078d634d --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/get_mic.c @@ -0,0 +1,317 @@ +/* + * Copyright (c) 1997 - 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id: get_mic.c,v 1.34 2006/10/18 15:59:23 lha Exp $"); + +static OM_uint32 +mic_des + (OM_uint32 * minor_status, + const gsskrb5_ctx ctx, + gss_qop_t qop_req, + const gss_buffer_t message_buffer, + gss_buffer_t message_token, + krb5_keyblock *key + ) +{ + u_char *p; + MD5_CTX md5; + u_char hash[16]; + DES_key_schedule schedule; + DES_cblock deskey; + DES_cblock zero; + int32_t seq_number; + size_t len, total_len; + + _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) { + message_token->length = 0; + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + p = _gsskrb5_make_header(message_token->value, + len, + "\x01\x01", /* TOK_ID */ + GSS_KRB5_MECHANISM); + + memcpy (p, "\x00\x00", 2); /* SGN_ALG = DES MAC MD5 */ + p += 2; + + memcpy (p, "\xff\xff\xff\xff", 4); /* Filler */ + p += 4; + + /* Fill in later (SND-SEQ) */ + memset (p, 0, 16); + p += 16; + + /* checksum */ + MD5_Init (&md5); + MD5_Update (&md5, p - 24, 8); + MD5_Update (&md5, message_buffer->value, message_buffer->length); + MD5_Final (hash, &md5); + + memset (&zero, 0, sizeof(zero)); + memcpy (&deskey, key->keyvalue.data, sizeof(deskey)); + DES_set_key (&deskey, &schedule); + DES_cbc_cksum ((void *)hash, (void *)hash, sizeof(hash), + &schedule, &zero); + memcpy (p - 8, hash, 8); /* SGN_CKSUM */ + + HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); + /* sequence number */ + krb5_auth_con_getlocalseqnumber (_gsskrb5_context, + ctx->auth_context, + &seq_number); + + p -= 16; /* SND_SEQ */ + p[0] = (seq_number >> 0) & 0xFF; + p[1] = (seq_number >> 8) & 0xFF; + p[2] = (seq_number >> 16) & 0xFF; + p[3] = (seq_number >> 24) & 0xFF; + memset (p + 4, + (ctx->more_flags & LOCAL) ? 0 : 0xFF, + 4); + + DES_set_key (&deskey, &schedule); + DES_cbc_encrypt ((void *)p, (void *)p, 8, + &schedule, (DES_cblock *)(p + 8), DES_ENCRYPT); + + krb5_auth_con_setlocalseqnumber (_gsskrb5_context, + ctx->auth_context, + ++seq_number); + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + + memset (deskey, 0, sizeof(deskey)); + memset (&schedule, 0, sizeof(schedule)); + + *minor_status = 0; + return GSS_S_COMPLETE; +} + +static OM_uint32 +mic_des3 + (OM_uint32 * minor_status, + const gsskrb5_ctx ctx, + gss_qop_t qop_req, + const gss_buffer_t message_buffer, + gss_buffer_t message_token, + krb5_keyblock *key + ) +{ + u_char *p; + Checksum cksum; + u_char seq[8]; + + int32_t seq_number; + size_t len, total_len; + + krb5_crypto crypto; + krb5_error_code kret; + krb5_data encdata; + char *tmp; + char ivec[8]; + + _gsskrb5_encap_length (36, &len, &total_len, GSS_KRB5_MECHANISM); + + message_token->length = total_len; + message_token->value = malloc (total_len); + if (message_token->value == NULL) { + message_token->length = 0; + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + p = _gsskrb5_make_header(message_token->value, + len, + "\x01\x01", /* TOK-ID */ + GSS_KRB5_MECHANISM); + + memcpy (p, "\x04\x00", 2); /* SGN_ALG = HMAC SHA1 DES3-KD */ + p += 2; + + memcpy (p, "\xff\xff\xff\xff", 4); /* filler */ + p += 4; + + /* this should be done in parts */ + + tmp = malloc (message_buffer->length + 8); + if (tmp == NULL) { + free (message_token->value); + message_token->value = NULL; + message_token->length = 0; + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + memcpy (tmp, p - 8, 8); + memcpy (tmp + 8, message_buffer->value, message_buffer->length); + + kret = krb5_crypto_init(_gsskrb5_context, key, 0, &crypto); + if (kret) { + free (message_token->value); + message_token->value = NULL; + message_token->length = 0; + free (tmp); + _gsskrb5_set_error_string (); + *minor_status = kret; + return GSS_S_FAILURE; + } + + kret = krb5_create_checksum (_gsskrb5_context, + crypto, + KRB5_KU_USAGE_SIGN, + 0, + tmp, + message_buffer->length + 8, + &cksum); + free (tmp); + krb5_crypto_destroy (_gsskrb5_context, crypto); + if (kret) { + free (message_token->value); + message_token->value = NULL; + message_token->length = 0; + _gsskrb5_set_error_string (); + *minor_status = kret; + return GSS_S_FAILURE; + } + + memcpy (p + 8, cksum.checksum.data, cksum.checksum.length); + + HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); + /* sequence number */ + krb5_auth_con_getlocalseqnumber (_gsskrb5_context, + ctx->auth_context, + &seq_number); + + seq[0] = (seq_number >> 0) & 0xFF; + seq[1] = (seq_number >> 8) & 0xFF; + seq[2] = (seq_number >> 16) & 0xFF; + seq[3] = (seq_number >> 24) & 0xFF; + memset (seq + 4, + (ctx->more_flags & LOCAL) ? 0 : 0xFF, + 4); + + kret = krb5_crypto_init(_gsskrb5_context, key, + ETYPE_DES3_CBC_NONE, &crypto); + if (kret) { + free (message_token->value); + message_token->value = NULL; + message_token->length = 0; + _gsskrb5_set_error_string (); + *minor_status = kret; + return GSS_S_FAILURE; + } + + if (ctx->more_flags & COMPAT_OLD_DES3) + memset(ivec, 0, 8); + else + memcpy(ivec, p + 8, 8); + + kret = krb5_encrypt_ivec (_gsskrb5_context, + crypto, + KRB5_KU_USAGE_SEQ, + seq, 8, &encdata, ivec); + krb5_crypto_destroy (_gsskrb5_context, crypto); + if (kret) { + free (message_token->value); + message_token->value = NULL; + message_token->length = 0; + _gsskrb5_set_error_string (); + *minor_status = kret; + return GSS_S_FAILURE; + } + + assert (encdata.length == 8); + + memcpy (p, encdata.data, encdata.length); + krb5_data_free (&encdata); + + krb5_auth_con_setlocalseqnumber (_gsskrb5_context, + ctx->auth_context, + ++seq_number); + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + + free_Checksum (&cksum); + *minor_status = 0; + return GSS_S_COMPLETE; +} + +OM_uint32 _gsskrb5_get_mic + (OM_uint32 * minor_status, + const gss_ctx_id_t context_handle, + gss_qop_t qop_req, + const gss_buffer_t message_buffer, + gss_buffer_t message_token + ) +{ + const gsskrb5_ctx ctx = (const gsskrb5_ctx) context_handle; + krb5_keyblock *key; + OM_uint32 ret; + krb5_keytype keytype; + + HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); + ret = _gsskrb5i_get_token_key(ctx, &key); + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + if (ret) { + _gsskrb5_set_error_string (); + *minor_status = ret; + return GSS_S_FAILURE; + } + krb5_enctype_to_keytype (_gsskrb5_context, key->keytype, &keytype); + + switch (keytype) { + case KEYTYPE_DES : + ret = mic_des (minor_status, ctx, qop_req, + message_buffer, message_token, key); + break; + case KEYTYPE_DES3 : + ret = mic_des3 (minor_status, ctx, qop_req, + message_buffer, message_token, key); + break; + case KEYTYPE_ARCFOUR: + case KEYTYPE_ARCFOUR_56: + ret = _gssapi_get_mic_arcfour (minor_status, ctx, qop_req, + message_buffer, message_token, key); + break; + default : + ret = _gssapi_mic_cfx (minor_status, ctx, qop_req, + message_buffer, message_token, key); + break; + } + krb5_free_keyblock (_gsskrb5_context, key); + return ret; +} diff --git a/source4/heimdal/lib/gssapi/krb5/gsskrb5-private.h b/source4/heimdal/lib/gssapi/krb5/gsskrb5-private.h new file mode 100644 index 0000000000..426c0ab200 --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/gsskrb5-private.h @@ -0,0 +1,705 @@ +/* This is a generated file */ +#ifndef __gsskrb5_private_h__ +#define __gsskrb5_private_h__ + +#include <stdarg.h> + +gssapi_mech_interface +__gss_krb5_initialize (void); + +OM_uint32 +__gsskrb5_ccache_lifetime ( + OM_uint32 */*minor_status*/, + krb5_ccache /*id*/, + krb5_principal /*principal*/, + OM_uint32 */*lifetime*/); + +OM_uint32 +_gss_DES3_get_mic_compat ( + OM_uint32 */*minor_status*/, + gsskrb5_ctx /*ctx*/); + +OM_uint32 +_gssapi_decapsulate ( + OM_uint32 */*minor_status*/, + gss_buffer_t /*input_token_buffer*/, + krb5_data */*out_data*/, + const gss_OID mech ); + +void +_gssapi_encap_length ( + size_t /*data_len*/, + size_t */*len*/, + size_t */*total_len*/, + const gss_OID /*mech*/); + +OM_uint32 +_gssapi_encapsulate ( + OM_uint32 */*minor_status*/, + const krb5_data */*in_data*/, + gss_buffer_t /*output_token*/, + const gss_OID mech ); + +OM_uint32 +_gssapi_get_mic_arcfour ( + OM_uint32 * /*minor_status*/, + const gsskrb5_ctx /*context_handle*/, + gss_qop_t /*qop_req*/, + const gss_buffer_t /*message_buffer*/, + gss_buffer_t /*message_token*/, + krb5_keyblock */*key*/); + +void * +_gssapi_make_mech_header ( + void */*ptr*/, + size_t /*len*/, + const gss_OID /*mech*/); + +OM_uint32 +_gssapi_mic_cfx ( + OM_uint32 */*minor_status*/, + const gsskrb5_ctx /*context_handle*/, + gss_qop_t /*qop_req*/, + const gss_buffer_t /*message_buffer*/, + gss_buffer_t /*message_token*/, + krb5_keyblock */*key*/); + +OM_uint32 +_gssapi_msg_order_check ( + struct gss_msg_order */*o*/, + OM_uint32 /*seq_num*/); + +OM_uint32 +_gssapi_msg_order_create ( + OM_uint32 */*minor_status*/, + struct gss_msg_order **/*o*/, + OM_uint32 /*flags*/, + OM_uint32 /*seq_num*/, + OM_uint32 /*jitter_window*/, + int /*use_64*/); + +OM_uint32 +_gssapi_msg_order_destroy (struct gss_msg_order **/*m*/); + +krb5_error_code +_gssapi_msg_order_export ( + krb5_storage */*sp*/, + struct gss_msg_order */*o*/); + +OM_uint32 +_gssapi_msg_order_f (OM_uint32 /*flags*/); + +OM_uint32 +_gssapi_msg_order_import ( + OM_uint32 */*minor_status*/, + krb5_storage */*sp*/, + struct gss_msg_order **/*o*/); + +OM_uint32 +_gssapi_unwrap_arcfour ( + OM_uint32 */*minor_status*/, + const gsskrb5_ctx /*context_handle*/, + const gss_buffer_t /*input_message_buffer*/, + gss_buffer_t /*output_message_buffer*/, + int */*conf_state*/, + gss_qop_t */*qop_state*/, + krb5_keyblock */*key*/); + +OM_uint32 +_gssapi_unwrap_cfx ( + OM_uint32 */*minor_status*/, + const gsskrb5_ctx /*context_handle*/, + const gss_buffer_t /*input_message_buffer*/, + gss_buffer_t /*output_message_buffer*/, + int */*conf_state*/, + gss_qop_t */*qop_state*/, + krb5_keyblock */*key*/); + +OM_uint32 +_gssapi_verify_mech_header ( + u_char **/*str*/, + size_t /*total_len*/, + gss_OID /*mech*/); + +OM_uint32 +_gssapi_verify_mic_arcfour ( + OM_uint32 * /*minor_status*/, + const gsskrb5_ctx /*context_handle*/, + const gss_buffer_t /*message_buffer*/, + const gss_buffer_t /*token_buffer*/, + gss_qop_t * /*qop_state*/, + krb5_keyblock */*key*/, + char */*type*/); + +OM_uint32 +_gssapi_verify_mic_cfx ( + OM_uint32 */*minor_status*/, + const gsskrb5_ctx /*context_handle*/, + const gss_buffer_t /*message_buffer*/, + const gss_buffer_t /*token_buffer*/, + gss_qop_t */*qop_state*/, + krb5_keyblock */*key*/); + +OM_uint32 +_gssapi_verify_pad ( + gss_buffer_t /*wrapped_token*/, + size_t /*datalen*/, + size_t */*padlen*/); + +OM_uint32 +_gssapi_wrap_arcfour ( + OM_uint32 * /*minor_status*/, + const gsskrb5_ctx /*context_handle*/, + 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*/); + +OM_uint32 +_gssapi_wrap_cfx ( + OM_uint32 */*minor_status*/, + const gsskrb5_ctx /*context_handle*/, + 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*/); + +OM_uint32 +_gssapi_wrap_size_arcfour ( + OM_uint32 */*minor_status*/, + const gsskrb5_ctx /*ctx*/, + int /*conf_req_flag*/, + gss_qop_t /*qop_req*/, + OM_uint32 /*req_output_size*/, + OM_uint32 */*max_input_size*/, + krb5_keyblock */*key*/); + +OM_uint32 +_gssapi_wrap_size_cfx ( + OM_uint32 */*minor_status*/, + const gsskrb5_ctx /*context_handle*/, + int /*conf_req_flag*/, + gss_qop_t /*qop_req*/, + OM_uint32 /*req_output_size*/, + OM_uint32 */*max_input_size*/, + krb5_keyblock */*key*/); + +OM_uint32 +_gsskrb5_accept_sec_context ( + OM_uint32 * /*minor_status*/, + gss_ctx_id_t * /*context_handle*/, + const gss_cred_id_t /*acceptor_cred_handle*/, + const gss_buffer_t /*input_token_buffer*/, + const 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*/); + +OM_uint32 +_gsskrb5_acquire_cred ( + OM_uint32 * /*minor_status*/, + const gss_name_t /*desired_name*/, + OM_uint32 /*time_req*/, + const gss_OID_set /*desired_mechs*/, + gss_cred_usage_t /*cred_usage*/, + gss_cred_id_t * /*output_cred_handle*/, + gss_OID_set * /*actual_mechs*/, + OM_uint32 * time_rec ); + +OM_uint32 +_gsskrb5_add_cred ( + OM_uint32 */*minor_status*/, + const gss_cred_id_t /*input_cred_handle*/, + const gss_name_t /*desired_name*/, + const gss_OID /*desired_mech*/, + gss_cred_usage_t /*cred_usage*/, + OM_uint32 /*initiator_time_req*/, + OM_uint32 /*acceptor_time_req*/, + gss_cred_id_t */*output_cred_handle*/, + gss_OID_set */*actual_mechs*/, + OM_uint32 */*initiator_time_rec*/, + OM_uint32 */*acceptor_time_rec*/); + +OM_uint32 +_gsskrb5_add_oid_set_member ( + OM_uint32 * /*minor_status*/, + const gss_OID /*member_oid*/, + gss_OID_set * oid_set ); + +OM_uint32 +_gsskrb5_canonicalize_name ( + OM_uint32 * /*minor_status*/, + const gss_name_t /*input_name*/, + const gss_OID /*mech_type*/, + gss_name_t * output_name ); + +void +_gsskrb5_clear_status (void); + +OM_uint32 +_gsskrb5_compare_name ( + OM_uint32 * /*minor_status*/, + const gss_name_t /*name1*/, + const gss_name_t /*name2*/, + int * name_equal ); + +OM_uint32 +_gsskrb5_context_time ( + OM_uint32 * /*minor_status*/, + const gss_ctx_id_t /*context_handle*/, + OM_uint32 * time_rec ); + +OM_uint32 +_gsskrb5_create_8003_checksum ( + OM_uint32 */*minor_status*/, + const gss_channel_bindings_t /*input_chan_bindings*/, + OM_uint32 /*flags*/, + const krb5_data */*fwd_data*/, + Checksum */*result*/); + +OM_uint32 +_gsskrb5_create_ctx ( + OM_uint32 * /*minor_status*/, + gss_ctx_id_t * /*context_handle*/, + const gss_channel_bindings_t /*input_chan_bindings*/, + enum gss_ctx_id_t_state /*state*/); + +OM_uint32 +_gsskrb5_create_empty_oid_set ( + OM_uint32 * /*minor_status*/, + gss_OID_set * oid_set ); + +OM_uint32 +_gsskrb5_decapsulate ( + OM_uint32 */*minor_status*/, + gss_buffer_t /*input_token_buffer*/, + krb5_data */*out_data*/, + const void */*type*/, + gss_OID /*oid*/); + +krb5_error_code +_gsskrb5_decode_be_om_uint32 ( + const void */*ptr*/, + OM_uint32 */*n*/); + +krb5_error_code +_gsskrb5_decode_om_uint32 ( + const void */*ptr*/, + OM_uint32 */*n*/); + +OM_uint32 +_gsskrb5_delete_sec_context ( + OM_uint32 * /*minor_status*/, + gss_ctx_id_t * /*context_handle*/, + gss_buffer_t /*output_token*/); + +OM_uint32 +_gsskrb5_display_name ( + OM_uint32 * /*minor_status*/, + const gss_name_t /*input_name*/, + gss_buffer_t /*output_name_buffer*/, + gss_OID * output_name_type ); + +OM_uint32 +_gsskrb5_display_status ( + OM_uint32 */*minor_status*/, + OM_uint32 /*status_value*/, + int /*status_type*/, + const gss_OID /*mech_type*/, + OM_uint32 */*message_context*/, + gss_buffer_t /*status_string*/); + +OM_uint32 +_gsskrb5_duplicate_name ( + OM_uint32 * /*minor_status*/, + const gss_name_t /*src_name*/, + gss_name_t * dest_name ); + +void +_gsskrb5_encap_length ( + size_t /*data_len*/, + size_t */*len*/, + size_t */*total_len*/, + const gss_OID /*mech*/); + +OM_uint32 +_gsskrb5_encapsulate ( + OM_uint32 */*minor_status*/, + const krb5_data */*in_data*/, + gss_buffer_t /*output_token*/, + const void */*type*/, + const gss_OID mech ); + +krb5_error_code +_gsskrb5_encode_be_om_uint32 ( + OM_uint32 /*n*/, + u_char */*p*/); + +krb5_error_code +_gsskrb5_encode_om_uint32 ( + OM_uint32 /*n*/, + u_char */*p*/); + +OM_uint32 +_gsskrb5_export_name ( + OM_uint32 * /*minor_status*/, + const gss_name_t /*input_name*/, + gss_buffer_t exported_name ); + +OM_uint32 +_gsskrb5_export_sec_context ( + OM_uint32 * /*minor_status*/, + gss_ctx_id_t * /*context_handle*/, + gss_buffer_t interprocess_token ); + +char * +_gsskrb5_get_error_string (void); + +ssize_t +_gsskrb5_get_mech ( + const u_char */*ptr*/, + size_t /*total_len*/, + const u_char **/*mech_ret*/); + +OM_uint32 +_gsskrb5_get_mic ( + OM_uint32 * /*minor_status*/, + const gss_ctx_id_t /*context_handle*/, + gss_qop_t /*qop_req*/, + const gss_buffer_t /*message_buffer*/, + gss_buffer_t message_token ); + +struct gssapi_thr_context * +_gsskrb5_get_thread_context (int /*createp*/); + +OM_uint32 +_gsskrb5_get_tkt_flags ( + OM_uint32 */*minor_status*/, + gsskrb5_ctx /*ctx*/, + OM_uint32 */*tkt_flags*/); + +OM_uint32 +_gsskrb5_import_cred ( + OM_uint32 */*minor_status*/, + krb5_ccache /*id*/, + krb5_principal /*keytab_principal*/, + krb5_keytab /*keytab*/, + gss_cred_id_t */*cred*/); + +OM_uint32 +_gsskrb5_import_name ( + OM_uint32 * /*minor_status*/, + const gss_buffer_t /*input_name_buffer*/, + const gss_OID /*input_name_type*/, + gss_name_t * output_name ); + +OM_uint32 +_gsskrb5_import_sec_context ( + OM_uint32 * /*minor_status*/, + const gss_buffer_t /*interprocess_token*/, + gss_ctx_id_t * context_handle ); + +OM_uint32 +_gsskrb5_indicate_mechs ( + OM_uint32 * /*minor_status*/, + gss_OID_set * mech_set ); + +krb5_error_code +_gsskrb5_init (void); + +OM_uint32 +_gsskrb5_init_sec_context ( + OM_uint32 * /*minor_status*/, + const gss_cred_id_t /*initiator_cred_handle*/, + gss_ctx_id_t * /*context_handle*/, + const gss_name_t /*target_name*/, + const gss_OID /*mech_type*/, + OM_uint32 /*req_flags*/, + OM_uint32 /*time_req*/, + const gss_channel_bindings_t /*input_chan_bindings*/, + const gss_buffer_t /*input_token*/, + gss_OID * /*actual_mech_type*/, + gss_buffer_t /*output_token*/, + OM_uint32 * /*ret_flags*/, + OM_uint32 * time_rec ); + +OM_uint32 +_gsskrb5_inquire_context ( + OM_uint32 * /*minor_status*/, + const gss_ctx_id_t /*context_handle*/, + gss_name_t * /*src_name*/, + gss_name_t * /*targ_name*/, + OM_uint32 * /*lifetime_rec*/, + gss_OID * /*mech_type*/, + OM_uint32 * /*ctx_flags*/, + int * /*locally_initiated*/, + int * open_context ); + +OM_uint32 +_gsskrb5_inquire_cred ( + OM_uint32 * /*minor_status*/, + const gss_cred_id_t /*cred_handle*/, + gss_name_t * /*output_name*/, + OM_uint32 * /*lifetime*/, + gss_cred_usage_t * /*cred_usage*/, + gss_OID_set * mechanisms ); + +OM_uint32 +_gsskrb5_inquire_cred_by_mech ( + OM_uint32 * /*minor_status*/, + const gss_cred_id_t /*cred_handle*/, + const gss_OID /*mech_type*/, + gss_name_t * /*name*/, + OM_uint32 * /*initiator_lifetime*/, + OM_uint32 * /*acceptor_lifetime*/, + gss_cred_usage_t * cred_usage ); + +OM_uint32 +_gsskrb5_inquire_cred_by_oid ( + OM_uint32 * /*minor_status*/, + const gss_cred_id_t /*cred_handle*/, + const gss_OID /*desired_object*/, + gss_buffer_set_t */*data_set*/); + +OM_uint32 +_gsskrb5_inquire_mechs_for_name ( + OM_uint32 * /*minor_status*/, + const gss_name_t /*input_name*/, + gss_OID_set * mech_types ); + +OM_uint32 +_gsskrb5_inquire_names_for_mech ( + OM_uint32 * /*minor_status*/, + const gss_OID /*mechanism*/, + gss_OID_set * name_types ); + +OM_uint32 +_gsskrb5_inquire_sec_context_by_oid ( + OM_uint32 */*minor_status*/, + const gss_ctx_id_t /*context_handle*/, + const gss_OID /*desired_object*/, + gss_buffer_set_t */*data_set*/); + +OM_uint32 +_gsskrb5_krb5_ccache_name ( + OM_uint32 */*minor_status*/, + const char */*name*/, + const char **/*out_name*/); + +OM_uint32 +_gsskrb5_lifetime_left ( + OM_uint32 */*minor_status*/, + OM_uint32 /*lifetime*/, + OM_uint32 */*lifetime_rec*/); + +void * +_gsskrb5_make_header ( + void */*ptr*/, + size_t /*len*/, + const void */*type*/, + const gss_OID /*mech*/); + +OM_uint32 +_gsskrb5_process_context_token ( + OM_uint32 */*minor_status*/, + const gss_ctx_id_t /*context_handle*/, + const gss_buffer_t token_buffer ); + +OM_uint32 +_gsskrb5_register_acceptor_identity (const char */*identity*/); + +OM_uint32 +_gsskrb5_release_buffer ( + OM_uint32 * /*minor_status*/, + gss_buffer_t buffer ); + +OM_uint32 +_gsskrb5_release_cred ( + OM_uint32 * /*minor_status*/, + gss_cred_id_t * cred_handle ); + +OM_uint32 +_gsskrb5_release_name ( + OM_uint32 * /*minor_status*/, + gss_name_t * input_name ); + +OM_uint32 +_gsskrb5_release_oid_set ( + OM_uint32 * /*minor_status*/, + gss_OID_set * set ); + +OM_uint32 +_gsskrb5_seal ( + OM_uint32 * /*minor_status*/, + gss_ctx_id_t /*context_handle*/, + int /*conf_req_flag*/, + int /*qop_req*/, + gss_buffer_t /*input_message_buffer*/, + int * /*conf_state*/, + gss_buffer_t output_message_buffer ); + +OM_uint32 +_gsskrb5_set_cred_option ( + OM_uint32 */*minor_status*/, + gss_cred_id_t */*cred_handle*/, + const gss_OID /*desired_object*/, + const gss_buffer_t /*value*/); + +void +_gsskrb5_set_error_string (void); + +OM_uint32 +_gsskrb5_set_sec_context_option ( + OM_uint32 */*minor_status*/, + gss_ctx_id_t */*context_handle*/, + const gss_OID /*desired_object*/, + const gss_buffer_t /*value*/); + +void +_gsskrb5_set_status ( + const char */*fmt*/, + ...); + +OM_uint32 +_gsskrb5_sign ( + OM_uint32 * /*minor_status*/, + gss_ctx_id_t /*context_handle*/, + int /*qop_req*/, + gss_buffer_t /*message_buffer*/, + gss_buffer_t message_token ); + +OM_uint32 +_gsskrb5_test_oid_set_member ( + OM_uint32 * /*minor_status*/, + const gss_OID /*member*/, + const gss_OID_set /*set*/, + int * present ); + +OM_uint32 +_gsskrb5_unseal ( + OM_uint32 * /*minor_status*/, + gss_ctx_id_t /*context_handle*/, + gss_buffer_t /*input_message_buffer*/, + gss_buffer_t /*output_message_buffer*/, + int * /*conf_state*/, + int * qop_state ); + +OM_uint32 +_gsskrb5_unwrap ( + OM_uint32 * /*minor_status*/, + const gss_ctx_id_t /*context_handle*/, + const gss_buffer_t /*input_message_buffer*/, + gss_buffer_t /*output_message_buffer*/, + int * /*conf_state*/, + gss_qop_t * qop_state ); + +OM_uint32 +_gsskrb5_verify ( + OM_uint32 * /*minor_status*/, + gss_ctx_id_t /*context_handle*/, + gss_buffer_t /*message_buffer*/, + gss_buffer_t /*token_buffer*/, + int * qop_state ); + +OM_uint32 +_gsskrb5_verify_8003_checksum ( + OM_uint32 */*minor_status*/, + const gss_channel_bindings_t /*input_chan_bindings*/, + const Checksum */*cksum*/, + OM_uint32 */*flags*/, + krb5_data */*fwd_data*/); + +OM_uint32 +_gsskrb5_verify_header ( + u_char **/*str*/, + size_t /*total_len*/, + const void */*type*/, + gss_OID /*oid*/); + +OM_uint32 +_gsskrb5_verify_mic ( + OM_uint32 * /*minor_status*/, + const gss_ctx_id_t /*context_handle*/, + const gss_buffer_t /*message_buffer*/, + const gss_buffer_t /*token_buffer*/, + gss_qop_t * qop_state ); + +OM_uint32 +_gsskrb5_verify_mic_internal ( + OM_uint32 * /*minor_status*/, + const gsskrb5_ctx /*context_handle*/, + const gss_buffer_t /*message_buffer*/, + const gss_buffer_t /*token_buffer*/, + gss_qop_t * /*qop_state*/, + char * type ); + +OM_uint32 +_gsskrb5_wrap ( + OM_uint32 * /*minor_status*/, + const gss_ctx_id_t /*context_handle*/, + 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 ); + +OM_uint32 +_gsskrb5_wrap_size_limit ( + OM_uint32 * /*minor_status*/, + const gss_ctx_id_t /*context_handle*/, + int /*conf_req_flag*/, + gss_qop_t /*qop_req*/, + OM_uint32 /*req_output_size*/, + OM_uint32 * max_input_size ); + +krb5_error_code +_gsskrb5cfx_max_wrap_length_cfx ( + krb5_crypto /*crypto*/, + int /*conf_req_flag*/, + size_t /*input_length*/, + OM_uint32 */*output_length*/); + +krb5_error_code +_gsskrb5cfx_wrap_length_cfx ( + krb5_crypto /*crypto*/, + int /*conf_req_flag*/, + size_t /*input_length*/, + size_t */*output_length*/, + size_t */*cksumsize*/, + uint16_t */*padlength*/); + +krb5_error_code +_gsskrb5i_address_to_krb5addr ( + OM_uint32 /*gss_addr_type*/, + gss_buffer_desc */*gss_addr*/, + int16_t /*port*/, + krb5_address */*address*/); + +krb5_error_code +_gsskrb5i_get_acceptor_subkey ( + const gsskrb5_ctx /*ctx*/, + krb5_keyblock **/*key*/); + +krb5_error_code +_gsskrb5i_get_initiator_subkey ( + const gsskrb5_ctx /*ctx*/, + krb5_keyblock **/*key*/); + +OM_uint32 +_gsskrb5i_get_token_key ( + const gsskrb5_ctx /*ctx*/, + krb5_keyblock **/*key*/); + +void +_gsskrb5i_is_cfx ( + gsskrb5_ctx /*ctx*/, + int */*is_cfx*/); + +#endif /* __gsskrb5_private_h__ */ diff --git a/source4/heimdal/lib/gssapi/krb5/gsskrb5_locl.h b/source4/heimdal/lib/gssapi/krb5/gsskrb5_locl.h new file mode 100644 index 0000000000..4d814032c3 --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/gsskrb5_locl.h @@ -0,0 +1,133 @@ +/* + * Copyright (c) 1997 - 2006 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* $Id: gsskrb5_locl.h,v 1.6 2006/10/07 22:14:49 lha Exp $ */ + +#ifndef GSSKRB5_LOCL_H +#define GSSKRB5_LOCL_H + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <krb5_locl.h> +#include <gssapi.h> +#include <gssapi_mech.h> +#include <assert.h> + +#include "cfx.h" + +/* + * + */ + +struct gss_msg_order; + +typedef struct { + struct krb5_auth_context_data *auth_context; + krb5_principal source, target; + OM_uint32 flags; + enum { LOCAL = 1, OPEN = 2, + COMPAT_OLD_DES3 = 4, + COMPAT_OLD_DES3_SELECTED = 8, + ACCEPTOR_SUBKEY = 16 + } more_flags; + enum gss_ctx_id_t_state { + /* initiator states */ + INITIATOR_START, + INITIATOR_WAIT_FOR_MUTAL, + INITIATOR_READY, + /* acceptor states */ + ACCEPTOR_START, + ACCEPTOR_WAIT_FOR_DCESTYLE, + ACCEPTOR_READY + } state; + struct krb5_ticket *ticket; + OM_uint32 lifetime; + HEIMDAL_MUTEX ctx_id_mutex; + struct gss_msg_order *order; + krb5_keyblock *service_keyblock; + krb5_data fwd_data; +} *gsskrb5_ctx; + +typedef struct { + krb5_principal principal; + int cred_flags; +#define GSS_CF_DESTROY_CRED_ON_RELEASE 1 + struct krb5_keytab_data *keytab; + OM_uint32 lifetime; + gss_cred_usage_t usage; + gss_OID_set mechanisms; + struct krb5_ccache_data *ccache; + HEIMDAL_MUTEX cred_id_mutex; +} *gsskrb5_cred; + +typedef struct Principal *gsskrb5_name; + +/* + * + */ + +extern krb5_context _gsskrb5_context; + +extern krb5_keytab _gsskrb5_keytab; +extern HEIMDAL_MUTEX gssapi_keytab_mutex; + +struct gssapi_thr_context { + HEIMDAL_MUTEX mutex; + char *error_string; +}; + +/* + * Prototypes + */ + +#include <krb5/gsskrb5-private.h> + +#define GSSAPI_KRB5_INIT() do { \ + krb5_error_code kret_gss_init; \ + if((kret_gss_init = _gsskrb5_init ()) != 0) { \ + *minor_status = kret_gss_init; \ + return GSS_S_FAILURE; \ + } \ +} while (0) + +/* sec_context flags */ + +#define SC_LOCAL_ADDRESS 0x01 +#define SC_REMOTE_ADDRESS 0x02 +#define SC_KEYBLOCK 0x04 +#define SC_LOCAL_SUBKEY 0x08 +#define SC_REMOTE_SUBKEY 0x10 + +#endif diff --git a/source4/heimdal/lib/gssapi/krb5/import_name.c b/source4/heimdal/lib/gssapi/krb5/import_name.c new file mode 100644 index 0000000000..dc24ed5cf2 --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/import_name.c @@ -0,0 +1,219 @@ +/* + * Copyright (c) 1997 - 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id: import_name.c,v 1.17 2006/10/07 22:14:51 lha Exp $"); + +static OM_uint32 +parse_krb5_name (OM_uint32 *minor_status, + const char *name, + gss_name_t *output_name) +{ + krb5_principal princ; + krb5_error_code kerr; + + kerr = krb5_parse_name (_gsskrb5_context, name, &princ); + + if (kerr == 0) { + *output_name = (gss_name_t)princ; + return GSS_S_COMPLETE; + } + _gsskrb5_set_error_string (); + *minor_status = kerr; + + if (kerr == KRB5_PARSE_ILLCHAR || kerr == KRB5_PARSE_MALFORMED) + return GSS_S_BAD_NAME; + + return GSS_S_FAILURE; +} + +static OM_uint32 +import_krb5_name (OM_uint32 *minor_status, + const gss_buffer_t input_name_buffer, + gss_name_t *output_name) +{ + OM_uint32 ret; + char *tmp; + + tmp = malloc (input_name_buffer->length + 1); + if (tmp == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + memcpy (tmp, + input_name_buffer->value, + input_name_buffer->length); + tmp[input_name_buffer->length] = '\0'; + + ret = parse_krb5_name(minor_status, tmp, output_name); + free(tmp); + + return ret; +} + +static OM_uint32 +import_hostbased_name (OM_uint32 *minor_status, + const gss_buffer_t input_name_buffer, + gss_name_t *output_name) +{ + krb5_error_code kerr; + char *tmp; + char *p; + char *host; + char local_hostname[MAXHOSTNAMELEN]; + krb5_principal princ = NULL; + + tmp = malloc (input_name_buffer->length + 1); + if (tmp == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + memcpy (tmp, + input_name_buffer->value, + input_name_buffer->length); + tmp[input_name_buffer->length] = '\0'; + + p = strchr (tmp, '@'); + if (p != NULL) { + *p = '\0'; + host = p + 1; + } else { + if (gethostname(local_hostname, sizeof(local_hostname)) < 0) { + *minor_status = errno; + free (tmp); + return GSS_S_FAILURE; + } + host = local_hostname; + } + + kerr = krb5_sname_to_principal (_gsskrb5_context, + host, + tmp, + KRB5_NT_SRV_HST, + &princ); + free (tmp); + *minor_status = kerr; + if (kerr == 0) { + *output_name = (gss_name_t)princ; + return GSS_S_COMPLETE; + } + _gsskrb5_set_error_string (); + *minor_status = kerr; + + if (kerr == KRB5_PARSE_ILLCHAR || kerr == KRB5_PARSE_MALFORMED) + return GSS_S_BAD_NAME; + + return GSS_S_FAILURE; +} + +static OM_uint32 +import_export_name (OM_uint32 *minor_status, + const gss_buffer_t input_name_buffer, + gss_name_t *output_name) +{ + unsigned char *p; + uint32_t length; + OM_uint32 ret; + char *name; + + if (input_name_buffer->length < 10 + GSS_KRB5_MECHANISM->length) + return GSS_S_BAD_NAME; + + /* TOK, MECH_OID_LEN, DER(MECH_OID), NAME_LEN, NAME */ + + p = input_name_buffer->value; + + if (memcmp(&p[0], "\x04\x01\x00", 3) != 0 || + p[3] != GSS_KRB5_MECHANISM->length + 2 || + p[4] != 0x06 || + p[5] != GSS_KRB5_MECHANISM->length || + memcmp(&p[6], GSS_KRB5_MECHANISM->elements, + GSS_KRB5_MECHANISM->length) != 0) + return GSS_S_BAD_NAME; + + p += 6 + GSS_KRB5_MECHANISM->length; + + length = p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3]; + p += 4; + + if (length > input_name_buffer->length - 10 - GSS_KRB5_MECHANISM->length) + return GSS_S_BAD_NAME; + + name = malloc(length + 1); + if (name == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + memcpy(name, p, length); + name[length] = '\0'; + + ret = parse_krb5_name(minor_status, name, output_name); + free(name); + + return ret; +} + +OM_uint32 _gsskrb5_import_name + (OM_uint32 * minor_status, + const gss_buffer_t input_name_buffer, + const gss_OID input_name_type, + gss_name_t * output_name + ) +{ + GSSAPI_KRB5_INIT (); + + *minor_status = 0; + *output_name = GSS_C_NO_NAME; + + if (gss_oid_equal(input_name_type, GSS_C_NT_HOSTBASED_SERVICE) || + gss_oid_equal(input_name_type, GSS_C_NT_HOSTBASED_SERVICE_X)) + return import_hostbased_name (minor_status, + input_name_buffer, + output_name); + else if (gss_oid_equal(input_name_type, GSS_C_NO_OID) + || gss_oid_equal(input_name_type, GSS_C_NT_USER_NAME) + || gss_oid_equal(input_name_type, GSS_KRB5_NT_PRINCIPAL_NAME)) + /* default printable syntax */ + return import_krb5_name (minor_status, + input_name_buffer, + output_name); + else if (gss_oid_equal(input_name_type, GSS_C_NT_EXPORT_NAME)) { + return import_export_name(minor_status, + input_name_buffer, + output_name); + } else { + *minor_status = 0; + return GSS_S_BAD_NAMETYPE; + } +} diff --git a/source4/heimdal/lib/gssapi/krb5/import_sec_context.c b/source4/heimdal/lib/gssapi/krb5/import_sec_context.c new file mode 100644 index 0000000000..8131e2621d --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/import_sec_context.c @@ -0,0 +1,229 @@ +/* + * Copyright (c) 1999 - 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id: import_sec_context.c,v 1.17 2006/10/07 22:14:53 lha Exp $"); + +OM_uint32 +_gsskrb5_import_sec_context ( + OM_uint32 * minor_status, + const gss_buffer_t interprocess_token, + gss_ctx_id_t * context_handle + ) +{ + OM_uint32 ret = GSS_S_FAILURE; + krb5_error_code kret; + krb5_storage *sp; + krb5_auth_context ac; + krb5_address local, remote; + krb5_address *localp, *remotep; + krb5_data data; + gss_buffer_desc buffer; + krb5_keyblock keyblock; + int32_t tmp; + int32_t flags; + gsskrb5_ctx ctx; + gss_name_t name; + + GSSAPI_KRB5_INIT (); + + *context_handle = GSS_C_NO_CONTEXT; + + localp = remotep = NULL; + + sp = krb5_storage_from_mem (interprocess_token->value, + interprocess_token->length); + if (sp == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + ctx = calloc(1, sizeof(*ctx)); + if (ctx == NULL) { + *minor_status = ENOMEM; + krb5_storage_free (sp); + return GSS_S_FAILURE; + } + HEIMDAL_MUTEX_init(&ctx->ctx_id_mutex); + + kret = krb5_auth_con_init (_gsskrb5_context, + &ctx->auth_context); + if (kret) { + _gsskrb5_set_error_string (); + *minor_status = kret; + ret = GSS_S_FAILURE; + goto failure; + } + + /* flags */ + + *minor_status = 0; + + if (krb5_ret_int32 (sp, &flags) != 0) + goto failure; + + /* retrieve the auth context */ + + ac = ctx->auth_context; + if (krb5_ret_uint32 (sp, &ac->flags) != 0) + goto failure; + if (flags & SC_LOCAL_ADDRESS) { + if (krb5_ret_address (sp, localp = &local) != 0) + goto failure; + } + + if (flags & SC_REMOTE_ADDRESS) { + if (krb5_ret_address (sp, remotep = &remote) != 0) + goto failure; + } + + krb5_auth_con_setaddrs (_gsskrb5_context, ac, localp, remotep); + if (localp) + krb5_free_address (_gsskrb5_context, localp); + if (remotep) + krb5_free_address (_gsskrb5_context, remotep); + localp = remotep = NULL; + + if (krb5_ret_int16 (sp, &ac->local_port) != 0) + goto failure; + + if (krb5_ret_int16 (sp, &ac->remote_port) != 0) + goto failure; + if (flags & SC_KEYBLOCK) { + if (krb5_ret_keyblock (sp, &keyblock) != 0) + goto failure; + krb5_auth_con_setkey (_gsskrb5_context, ac, &keyblock); + krb5_free_keyblock_contents (_gsskrb5_context, &keyblock); + } + if (flags & SC_LOCAL_SUBKEY) { + if (krb5_ret_keyblock (sp, &keyblock) != 0) + goto failure; + krb5_auth_con_setlocalsubkey (_gsskrb5_context, ac, &keyblock); + krb5_free_keyblock_contents (_gsskrb5_context, &keyblock); + } + if (flags & SC_REMOTE_SUBKEY) { + if (krb5_ret_keyblock (sp, &keyblock) != 0) + goto failure; + krb5_auth_con_setremotesubkey (_gsskrb5_context, ac, &keyblock); + krb5_free_keyblock_contents (_gsskrb5_context, &keyblock); + } + if (krb5_ret_uint32 (sp, &ac->local_seqnumber)) + goto failure; + if (krb5_ret_uint32 (sp, &ac->remote_seqnumber)) + goto failure; + + if (krb5_ret_int32 (sp, &tmp) != 0) + goto failure; + ac->keytype = tmp; + if (krb5_ret_int32 (sp, &tmp) != 0) + goto failure; + ac->cksumtype = tmp; + + /* names */ + + if (krb5_ret_data (sp, &data)) + goto failure; + buffer.value = data.data; + buffer.length = data.length; + + ret = _gsskrb5_import_name (minor_status, &buffer, GSS_C_NT_EXPORT_NAME, + &name); + if (ret) { + ret = _gsskrb5_import_name (minor_status, &buffer, GSS_C_NO_OID, + &name); + if (ret) { + krb5_data_free (&data); + goto failure; + } + } + ctx->source = (krb5_principal)name; + krb5_data_free (&data); + + if (krb5_ret_data (sp, &data) != 0) + goto failure; + buffer.value = data.data; + buffer.length = data.length; + + ret = _gsskrb5_import_name (minor_status, &buffer, GSS_C_NT_EXPORT_NAME, + &name); + if (ret) { + ret = _gsskrb5_import_name (minor_status, &buffer, GSS_C_NO_OID, + &name); + if (ret) { + krb5_data_free (&data); + goto failure; + } + } + ctx->target = (krb5_principal)name; + krb5_data_free (&data); + + if (krb5_ret_int32 (sp, &tmp)) + goto failure; + ctx->flags = tmp; + if (krb5_ret_int32 (sp, &tmp)) + goto failure; + ctx->more_flags = tmp; + if (krb5_ret_int32 (sp, &tmp)) + goto failure; + ctx->lifetime = tmp; + + ret = _gssapi_msg_order_import(minor_status, sp, &ctx->order); + if (ret) + goto failure; + + krb5_storage_free (sp); + + *context_handle = (gss_ctx_id_t)ctx; + + return GSS_S_COMPLETE; + +failure: + krb5_auth_con_free (_gsskrb5_context, + ctx->auth_context); + if (ctx->source != NULL) + krb5_free_principal(_gsskrb5_context, ctx->source); + if (ctx->target != NULL) + krb5_free_principal(_gsskrb5_context, ctx->target); + if (localp) + krb5_free_address (_gsskrb5_context, localp); + if (remotep) + krb5_free_address (_gsskrb5_context, remotep); + if(ctx->order) + _gssapi_msg_order_destroy(&ctx->order); + HEIMDAL_MUTEX_destroy(&ctx->ctx_id_mutex); + krb5_storage_free (sp); + free (ctx); + *context_handle = GSS_C_NO_CONTEXT; + return ret; +} diff --git a/source4/heimdal/lib/gssapi/krb5/indicate_mechs.c b/source4/heimdal/lib/gssapi/krb5/indicate_mechs.c new file mode 100644 index 0000000000..3827533219 --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/indicate_mechs.c @@ -0,0 +1,58 @@ +/* + * Copyright (c) 1997 - 2001, 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id: indicate_mechs.c,v 1.9 2006/10/07 22:14:56 lha Exp $"); + +OM_uint32 _gsskrb5_indicate_mechs + (OM_uint32 * minor_status, + gss_OID_set * mech_set + ) +{ + OM_uint32 ret, junk; + + ret = _gsskrb5_create_empty_oid_set(minor_status, mech_set); + if (ret) + return ret; + + ret = _gsskrb5_add_oid_set_member(minor_status, + GSS_KRB5_MECHANISM, mech_set); + if (ret) { + _gsskrb5_release_oid_set(&junk, mech_set); + return ret; + } + + *minor_status = 0; + return GSS_S_COMPLETE; +} diff --git a/source4/heimdal/lib/gssapi/krb5/init.c b/source4/heimdal/lib/gssapi/krb5/init.c new file mode 100644 index 0000000000..cbef8740b7 --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/init.c @@ -0,0 +1,111 @@ +/* + * Copyright (c) 1997 - 2001, 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id: init.c,v 1.9 2006/10/07 22:14:58 lha Exp $"); + +static HEIMDAL_MUTEX _gsskrb5_context_mutex = HEIMDAL_MUTEX_INITIALIZER; +static int created_key; +static HEIMDAL_thread_key gssapi_context_key; + +static void +gssapi_destroy_thread_context(void *ptr) +{ + struct gssapi_thr_context *ctx = ptr; + + if (ctx == NULL) + return; + if (ctx->error_string) + free(ctx->error_string); + HEIMDAL_MUTEX_destroy(&ctx->mutex); + free(ctx); +} + + +struct gssapi_thr_context * +_gsskrb5_get_thread_context(int createp) +{ + struct gssapi_thr_context *ctx; + int ret; + + HEIMDAL_MUTEX_lock(&_gsskrb5_context_mutex); + + if (!created_key) + abort(); + ctx = HEIMDAL_getspecific(gssapi_context_key); + if (ctx == NULL) { + if (!createp) + goto fail; + ctx = malloc(sizeof(*ctx)); + if (ctx == NULL) + goto fail; + ctx->error_string = NULL; + HEIMDAL_MUTEX_init(&ctx->mutex); + HEIMDAL_setspecific(gssapi_context_key, ctx, ret); + if (ret) + goto fail; + } + HEIMDAL_MUTEX_unlock(&_gsskrb5_context_mutex); + return ctx; + fail: + HEIMDAL_MUTEX_unlock(&_gsskrb5_context_mutex); + if (ctx) + free(ctx); + return NULL; +} + +krb5_error_code +_gsskrb5_init (void) +{ + krb5_error_code ret = 0; + + HEIMDAL_MUTEX_lock(&_gsskrb5_context_mutex); + + if(_gsskrb5_context == NULL) + ret = krb5_init_context (&_gsskrb5_context); + if (ret == 0 && !created_key) { + HEIMDAL_key_create(&gssapi_context_key, + gssapi_destroy_thread_context, + ret); + if (ret) { + krb5_free_context(_gsskrb5_context); + _gsskrb5_context = NULL; + } else + created_key = 1; + } + + HEIMDAL_MUTEX_unlock(&_gsskrb5_context_mutex); + + return ret; +} diff --git a/source4/heimdal/lib/gssapi/krb5/init_sec_context.c b/source4/heimdal/lib/gssapi/krb5/init_sec_context.c new file mode 100644 index 0000000000..00f2543833 --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/init_sec_context.c @@ -0,0 +1,789 @@ +/* + * Copyright (c) 1997 - 2005 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id: init_sec_context.c,v 1.72 2006/10/24 23:03:19 lha Exp $"); + +/* + * copy the addresses from `input_chan_bindings' (if any) to + * the auth context `ac' + */ + +static OM_uint32 +set_addresses (krb5_auth_context ac, + const gss_channel_bindings_t input_chan_bindings) +{ + /* Port numbers are expected to be in application_data.value, + * initator's port first */ + + krb5_address initiator_addr, acceptor_addr; + krb5_error_code kret; + + if (input_chan_bindings == GSS_C_NO_CHANNEL_BINDINGS + || input_chan_bindings->application_data.length != + 2 * sizeof(ac->local_port)) + return 0; + + memset(&initiator_addr, 0, sizeof(initiator_addr)); + memset(&acceptor_addr, 0, sizeof(acceptor_addr)); + + ac->local_port = + *(int16_t *) input_chan_bindings->application_data.value; + + ac->remote_port = + *((int16_t *) input_chan_bindings->application_data.value + 1); + + kret = _gsskrb5i_address_to_krb5addr(input_chan_bindings->acceptor_addrtype, + &input_chan_bindings->acceptor_address, + ac->remote_port, + &acceptor_addr); + if (kret) + return kret; + + kret = _gsskrb5i_address_to_krb5addr(input_chan_bindings->initiator_addrtype, + &input_chan_bindings->initiator_address, + ac->local_port, + &initiator_addr); + if (kret) { + krb5_free_address (_gsskrb5_context, &acceptor_addr); + return kret; + } + + kret = krb5_auth_con_setaddrs(_gsskrb5_context, + ac, + &initiator_addr, /* local address */ + &acceptor_addr); /* remote address */ + + krb5_free_address (_gsskrb5_context, &initiator_addr); + krb5_free_address (_gsskrb5_context, &acceptor_addr); + +#if 0 + free(input_chan_bindings->application_data.value); + input_chan_bindings->application_data.value = NULL; + input_chan_bindings->application_data.length = 0; +#endif + + return kret; +} + +OM_uint32 +_gsskrb5_create_ctx( + OM_uint32 * minor_status, + gss_ctx_id_t * context_handle, + const gss_channel_bindings_t input_chan_bindings, + enum gss_ctx_id_t_state state) +{ + krb5_error_code kret; + gsskrb5_ctx ctx; + + *context_handle = NULL; + + ctx = malloc(sizeof(*ctx)); + if (ctx == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + ctx->auth_context = NULL; + ctx->source = NULL; + ctx->target = NULL; + ctx->state = state; + ctx->flags = 0; + ctx->more_flags = 0; + ctx->service_keyblock = NULL; + ctx->ticket = NULL; + krb5_data_zero(&ctx->fwd_data); + ctx->lifetime = GSS_C_INDEFINITE; + ctx->order = NULL; + HEIMDAL_MUTEX_init(&ctx->ctx_id_mutex); + + kret = krb5_auth_con_init (_gsskrb5_context, &ctx->auth_context); + if (kret) { + *minor_status = kret; + _gsskrb5_set_error_string (); + + HEIMDAL_MUTEX_destroy(&ctx->ctx_id_mutex); + + return GSS_S_FAILURE; + } + + kret = set_addresses(ctx->auth_context, input_chan_bindings); + if (kret) { + *minor_status = kret; + + HEIMDAL_MUTEX_destroy(&ctx->ctx_id_mutex); + + krb5_auth_con_free(_gsskrb5_context, ctx->auth_context); + + return GSS_S_BAD_BINDINGS; + } + + /* + * We need a sequence number + */ + + krb5_auth_con_addflags(_gsskrb5_context, + ctx->auth_context, + KRB5_AUTH_CONTEXT_DO_SEQUENCE | + KRB5_AUTH_CONTEXT_CLEAR_FORWARDED_CRED, + NULL); + + *context_handle = (gss_ctx_id_t)ctx; + + return GSS_S_COMPLETE; +} + + +static OM_uint32 +gsskrb5_get_creds( + OM_uint32 * minor_status, + krb5_ccache ccache, + gsskrb5_ctx ctx, + krb5_const_principal target_name, + OM_uint32 time_req, + OM_uint32 * time_rec, + krb5_creds ** cred) +{ + OM_uint32 ret; + krb5_error_code kret; + krb5_creds this_cred; + OM_uint32 lifetime_rec; + + *cred = NULL; + + memset(&this_cred, 0, sizeof(this_cred)); + this_cred.client = ctx->source; + this_cred.server = ctx->target; + + if (time_req && time_req != GSS_C_INDEFINITE) { + krb5_timestamp ts; + + krb5_timeofday (_gsskrb5_context, &ts); + this_cred.times.endtime = ts + time_req; + } else { + this_cred.times.endtime = 0; + } + + this_cred.session.keytype = KEYTYPE_NULL; + + kret = krb5_get_credentials(_gsskrb5_context, + 0, + ccache, + &this_cred, + cred); + if (kret) { + _gsskrb5_set_error_string (); + *minor_status = kret; + return GSS_S_FAILURE; + } + + ctx->lifetime = (*cred)->times.endtime; + + ret = _gsskrb5_lifetime_left(minor_status, ctx->lifetime, &lifetime_rec); + if (ret) return ret; + + if (lifetime_rec == 0) { + *minor_status = 0; + return GSS_S_CONTEXT_EXPIRED; + } + + if (time_rec) *time_rec = lifetime_rec; + + return GSS_S_COMPLETE; +} + +static OM_uint32 +gsskrb5_initiator_ready( + OM_uint32 * minor_status, + gsskrb5_ctx ctx) +{ + OM_uint32 ret; + int32_t seq_number; + int is_cfx = 0; + OM_uint32 flags = ctx->flags; + + krb5_auth_getremoteseqnumber (_gsskrb5_context, + ctx->auth_context, + &seq_number); + + _gsskrb5i_is_cfx(ctx, &is_cfx); + + ret = _gssapi_msg_order_create(minor_status, + &ctx->order, + _gssapi_msg_order_f(flags), + seq_number, 0, is_cfx); + if (ret) return ret; + + ctx->state = INITIATOR_READY; + ctx->more_flags |= OPEN; + + return GSS_S_COMPLETE; +} + +/* + * handle delegated creds in init-sec-context + */ + +static void +do_delegation (krb5_auth_context ac, + krb5_ccache ccache, + krb5_creds *cred, + krb5_const_principal name, + krb5_data *fwd_data, + uint32_t *flags) +{ + krb5_creds creds; + KDCOptions fwd_flags; + krb5_error_code kret; + + memset (&creds, 0, sizeof(creds)); + krb5_data_zero (fwd_data); + + kret = krb5_cc_get_principal(_gsskrb5_context, ccache, &creds.client); + if (kret) + goto out; + + kret = krb5_build_principal(_gsskrb5_context, + &creds.server, + strlen(creds.client->realm), + creds.client->realm, + KRB5_TGS_NAME, + creds.client->realm, + NULL); + if (kret) + goto out; + + creds.times.endtime = 0; + + memset(&fwd_flags, 0, sizeof(fwd_flags)); + fwd_flags.forwarded = 1; + fwd_flags.forwardable = 1; + + if ( /*target_name->name.name_type != KRB5_NT_SRV_HST ||*/ + name->name.name_string.len < 2) + goto out; + + kret = krb5_get_forwarded_creds(_gsskrb5_context, + ac, + ccache, + KDCOptions2int(fwd_flags), + name->name.name_string.val[1], + &creds, + fwd_data); + + out: + if (kret) + *flags &= ~GSS_C_DELEG_FLAG; + else + *flags |= GSS_C_DELEG_FLAG; + + if (creds.client) + krb5_free_principal(_gsskrb5_context, creds.client); + if (creds.server) + krb5_free_principal(_gsskrb5_context, creds.server); +} + +/* + * first stage of init-sec-context + */ + +static OM_uint32 +init_auth +(OM_uint32 * minor_status, + gsskrb5_cred initiator_cred_handle, + gsskrb5_ctx ctx, + krb5_const_principal name, + const gss_OID mech_type, + OM_uint32 req_flags, + OM_uint32 time_req, + const gss_channel_bindings_t input_chan_bindings, + const gss_buffer_t input_token, + gss_OID * actual_mech_type, + gss_buffer_t output_token, + OM_uint32 * ret_flags, + OM_uint32 * time_rec + ) +{ + OM_uint32 ret = GSS_S_FAILURE; + krb5_error_code kret; + krb5_flags ap_options; + krb5_creds *cred = NULL; + krb5_data outbuf; + krb5_ccache ccache = NULL; + uint32_t flags; + krb5_data authenticator; + Checksum cksum; + krb5_enctype enctype; + krb5_data fwd_data; + OM_uint32 lifetime_rec; + + krb5_data_zero(&outbuf); + krb5_data_zero(&fwd_data); + + *minor_status = 0; + + if (actual_mech_type) + *actual_mech_type = GSS_KRB5_MECHANISM; + + if (initiator_cred_handle == NULL) { + kret = krb5_cc_default (_gsskrb5_context, &ccache); + if (kret) { + _gsskrb5_set_error_string (); + *minor_status = kret; + ret = GSS_S_FAILURE; + goto failure; + } + } else + ccache = initiator_cred_handle->ccache; + + kret = krb5_cc_get_principal (_gsskrb5_context, ccache, &ctx->source); + if (kret) { + _gsskrb5_set_error_string (); + *minor_status = kret; + ret = GSS_S_FAILURE; + goto failure; + } + + kret = krb5_copy_principal (_gsskrb5_context, name, &ctx->target); + if (kret) { + _gsskrb5_set_error_string (); + *minor_status = kret; + ret = GSS_S_FAILURE; + goto failure; + } + + ret = _gss_DES3_get_mic_compat(minor_status, ctx); + if (ret) + goto failure; + + + ret = gsskrb5_get_creds(minor_status, + ccache, + ctx, + ctx->target, + time_req, + time_rec, + &cred); + if (ret) + goto failure; + + ctx->lifetime = cred->times.endtime; + + ret = _gsskrb5_lifetime_left(minor_status, + ctx->lifetime, + &lifetime_rec); + if (ret) { + goto failure; + } + + if (lifetime_rec == 0) { + *minor_status = 0; + ret = GSS_S_CONTEXT_EXPIRED; + goto failure; + } + + krb5_auth_con_setkey(_gsskrb5_context, + ctx->auth_context, + &cred->session); + + kret = krb5_auth_con_generatelocalsubkey(_gsskrb5_context, + ctx->auth_context, + &cred->session); + if(kret) { + _gsskrb5_set_error_string (); + *minor_status = kret; + ret = GSS_S_FAILURE; + goto failure; + } + + /* + * If the credential doesn't have ok-as-delegate, check what local + * policy say about ok-as-delegate, default is FALSE that makes + * code ignore the KDC setting and follow what the application + * requested. If its TRUE, strip of the GSS_C_DELEG_FLAG if the + * KDC doesn't set ok-as-delegate. + */ + if (!cred->flags.b.ok_as_delegate) { + krb5_boolean delegate; + + krb5_appdefault_boolean(_gsskrb5_context, + "gssapi", name->realm, + "ok-as-delegate", FALSE, &delegate); + if (delegate) + req_flags &= ~GSS_C_DELEG_FLAG; + } + + flags = 0; + ap_options = 0; + if (req_flags & GSS_C_DELEG_FLAG) + do_delegation (ctx->auth_context, + ccache, cred, name, &fwd_data, &flags); + + if (req_flags & GSS_C_MUTUAL_FLAG) { + flags |= GSS_C_MUTUAL_FLAG; + ap_options |= AP_OPTS_MUTUAL_REQUIRED; + } + + if (req_flags & GSS_C_REPLAY_FLAG) + flags |= GSS_C_REPLAY_FLAG; + if (req_flags & GSS_C_SEQUENCE_FLAG) + flags |= GSS_C_SEQUENCE_FLAG; + if (req_flags & GSS_C_ANON_FLAG) + ; /* XXX */ + if (req_flags & GSS_C_DCE_STYLE) { + /* GSS_C_DCE_STYLE implies GSS_C_MUTUAL_FLAG */ + flags |= GSS_C_DCE_STYLE | GSS_C_MUTUAL_FLAG; + ap_options |= AP_OPTS_MUTUAL_REQUIRED; + } + if (req_flags & GSS_C_IDENTIFY_FLAG) + flags |= GSS_C_IDENTIFY_FLAG; + if (req_flags & GSS_C_EXTENDED_ERROR_FLAG) + flags |= GSS_C_EXTENDED_ERROR_FLAG; + + flags |= GSS_C_CONF_FLAG; + flags |= GSS_C_INTEG_FLAG; + flags |= GSS_C_TRANS_FLAG; + + if (ret_flags) + *ret_flags = flags; + ctx->flags = flags; + ctx->more_flags |= LOCAL; + + ret = _gsskrb5_create_8003_checksum (minor_status, + input_chan_bindings, + flags, + &fwd_data, + &cksum); + krb5_data_free (&fwd_data); + if (ret) + goto failure; + + enctype = ctx->auth_context->keyblock->keytype; + + kret = krb5_build_authenticator (_gsskrb5_context, + ctx->auth_context, + enctype, + cred, + &cksum, + NULL, + &authenticator, + KRB5_KU_AP_REQ_AUTH); + + if (kret) { + _gsskrb5_set_error_string (); + *minor_status = kret; + ret = GSS_S_FAILURE; + goto failure; + } + + kret = krb5_build_ap_req (_gsskrb5_context, + enctype, + cred, + ap_options, + authenticator, + &outbuf); + + if (kret) { + _gsskrb5_set_error_string (); + *minor_status = kret; + ret = GSS_S_FAILURE; + goto failure; + } + + ret = _gsskrb5_encapsulate (minor_status, &outbuf, output_token, + (u_char *)"\x01\x00", GSS_KRB5_MECHANISM); + if (ret) + goto failure; + + krb5_data_free (&outbuf); + krb5_free_creds(_gsskrb5_context, cred); + free_Checksum(&cksum); + if (initiator_cred_handle == NULL) + krb5_cc_close(_gsskrb5_context, ccache); + + if (flags & GSS_C_MUTUAL_FLAG) { + ctx->state = INITIATOR_WAIT_FOR_MUTAL; + return GSS_S_CONTINUE_NEEDED; + } + + return gsskrb5_initiator_ready(minor_status, ctx); +failure: + if(cred) + krb5_free_creds(_gsskrb5_context, cred); + if (ccache && initiator_cred_handle == NULL) + krb5_cc_close(_gsskrb5_context, ccache); + + return ret; + +} + +static OM_uint32 +repl_mutual + (OM_uint32 * minor_status, + gsskrb5_ctx ctx, + const gss_OID mech_type, + OM_uint32 req_flags, + OM_uint32 time_req, + const gss_channel_bindings_t input_chan_bindings, + const gss_buffer_t input_token, + gss_OID * actual_mech_type, + gss_buffer_t output_token, + OM_uint32 * ret_flags, + OM_uint32 * time_rec + ) +{ + OM_uint32 ret; + krb5_error_code kret; + krb5_data indata; + krb5_ap_rep_enc_part *repl; + int is_cfx = 0; + + output_token->length = 0; + output_token->value = NULL; + + if (actual_mech_type) + *actual_mech_type = GSS_KRB5_MECHANISM; + + if (req_flags & GSS_C_DCE_STYLE) { + /* There is no OID wrapping. */ + indata.length = input_token->length; + indata.data = input_token->value; + } else { + ret = _gsskrb5_decapsulate (minor_status, + input_token, + &indata, + "\x02\x00", + GSS_KRB5_MECHANISM); + if (ret) { + /* XXX - Handle AP_ERROR */ + return ret; + } + } + + kret = krb5_rd_rep (_gsskrb5_context, + ctx->auth_context, + &indata, + &repl); + if (kret) { + _gsskrb5_set_error_string (); + *minor_status = kret; + return GSS_S_FAILURE; + } + krb5_free_ap_rep_enc_part (_gsskrb5_context, + repl); + + _gsskrb5i_is_cfx(ctx, &is_cfx); + if (is_cfx) { + krb5_keyblock *key = NULL; + + kret = krb5_auth_con_getremotesubkey(_gsskrb5_context, + ctx->auth_context, + &key); + if (kret == 0 && key != NULL) { + ctx->more_flags |= ACCEPTOR_SUBKEY; + krb5_free_keyblock (_gsskrb5_context, key); + } + } + + + *minor_status = 0; + if (time_rec) { + ret = _gsskrb5_lifetime_left(minor_status, + ctx->lifetime, + time_rec); + } else { + ret = GSS_S_COMPLETE; + } + if (ret_flags) + *ret_flags = ctx->flags; + + if (req_flags & GSS_C_DCE_STYLE) { + int32_t con_flags; + krb5_data outbuf; + + /* Do don't do sequence number for the mk-rep */ + krb5_auth_con_removeflags(_gsskrb5_context, + ctx->auth_context, + KRB5_AUTH_CONTEXT_DO_SEQUENCE, + &con_flags); + + kret = krb5_mk_rep(_gsskrb5_context, + ctx->auth_context, + &outbuf); + if (kret) { + _gsskrb5_set_error_string (); + *minor_status = kret; + return GSS_S_FAILURE; + } + + output_token->length = outbuf.length; + output_token->value = outbuf.data; + + krb5_auth_con_removeflags(_gsskrb5_context, + ctx->auth_context, + KRB5_AUTH_CONTEXT_DO_SEQUENCE, + NULL); + } + + return gsskrb5_initiator_ready(minor_status, ctx); +} + +/* + * gss_init_sec_context + */ + +OM_uint32 _gsskrb5_init_sec_context +(OM_uint32 * minor_status, + const gss_cred_id_t initiator_cred_handle, + gss_ctx_id_t * context_handle, + const gss_name_t target_name, + const gss_OID mech_type, + OM_uint32 req_flags, + OM_uint32 time_req, + const gss_channel_bindings_t input_chan_bindings, + const gss_buffer_t input_token, + gss_OID * actual_mech_type, + gss_buffer_t output_token, + OM_uint32 * ret_flags, + OM_uint32 * time_rec + ) +{ + gsskrb5_cred cred = (gsskrb5_cred)initiator_cred_handle; + krb5_const_principal name = (krb5_const_principal)target_name; + gsskrb5_ctx ctx; + OM_uint32 ret; + + GSSAPI_KRB5_INIT (); + + output_token->length = 0; + output_token->value = NULL; + + if (context_handle == NULL) { + *minor_status = 0; + return GSS_S_FAILURE | GSS_S_CALL_BAD_STRUCTURE; + } + + if (ret_flags) + *ret_flags = 0; + if (time_rec) + *time_rec = 0; + + if (target_name == GSS_C_NO_NAME) { + if (actual_mech_type) + *actual_mech_type = GSS_C_NO_OID; + *minor_status = 0; + return GSS_S_BAD_NAME; + } + + if (mech_type != GSS_C_NO_OID && + !gss_oid_equal(mech_type, GSS_KRB5_MECHANISM)) + return GSS_S_BAD_MECH; + + if (input_token == GSS_C_NO_BUFFER || input_token->length == 0) { + OM_uint32 ret; + + if (*context_handle != GSS_C_NO_CONTEXT) { + *minor_status = 0; + return GSS_S_FAILURE | GSS_S_CALL_BAD_STRUCTURE; + } + + ret = _gsskrb5_create_ctx(minor_status, + context_handle, + input_chan_bindings, + INITIATOR_START); + if (ret) + return ret; + } + + if (*context_handle == GSS_C_NO_CONTEXT) { + *minor_status = 0; + return GSS_S_FAILURE | GSS_S_CALL_BAD_STRUCTURE; + } + + ctx = (gsskrb5_ctx) *context_handle; + + HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); + + switch (ctx->state) { + case INITIATOR_START: + ret = init_auth(minor_status, + cred, + ctx, + name, + mech_type, + req_flags, + time_req, + input_chan_bindings, + input_token, + actual_mech_type, + output_token, + ret_flags, + time_rec); + break; + case INITIATOR_WAIT_FOR_MUTAL: + ret = repl_mutual(minor_status, + ctx, + mech_type, + req_flags, + time_req, + input_chan_bindings, + input_token, + actual_mech_type, + output_token, + ret_flags, + time_rec); + break; + case INITIATOR_READY: + /* + * If we get there, the caller have called + * gss_init_sec_context() one time too many. + */ + *minor_status = 0; + ret = GSS_S_BAD_STATUS; + break; + default: + *minor_status = 0; + ret = GSS_S_BAD_STATUS; + break; + } + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + + /* destroy context in case of error */ + if (GSS_ERROR(ret)) { + OM_uint32 min2; + _gsskrb5_delete_sec_context(&min2, context_handle, GSS_C_NO_BUFFER); + } + + return ret; + +} diff --git a/source4/heimdal/lib/gssapi/krb5/inquire_context.c b/source4/heimdal/lib/gssapi/krb5/inquire_context.c new file mode 100644 index 0000000000..ef43e6852c --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/inquire_context.c @@ -0,0 +1,108 @@ +/* + * Copyright (c) 1997, 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id: inquire_context.c,v 1.10 2006/10/07 22:15:03 lha Exp $"); + +OM_uint32 _gsskrb5_inquire_context ( + OM_uint32 * minor_status, + const gss_ctx_id_t context_handle, + gss_name_t * src_name, + gss_name_t * targ_name, + OM_uint32 * lifetime_rec, + gss_OID * mech_type, + OM_uint32 * ctx_flags, + int * locally_initiated, + int * open_context + ) +{ + OM_uint32 ret; + gsskrb5_ctx ctx = (gsskrb5_ctx)context_handle; + gss_name_t name; + + if (src_name) + *src_name = GSS_C_NO_NAME; + if (targ_name) + *targ_name = GSS_C_NO_NAME; + + HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); + + if (src_name) { + name = (gss_name_t)ctx->source; + ret = _gsskrb5_duplicate_name (minor_status, name, src_name); + if (ret) + goto failed; + } + + if (targ_name) { + name = (gss_name_t)ctx->target; + ret = _gsskrb5_duplicate_name (minor_status, name, targ_name); + if (ret) + goto failed; + } + + if (lifetime_rec) { + ret = _gsskrb5_lifetime_left(minor_status, + ctx->lifetime, + lifetime_rec); + if (ret) + goto failed; + } + + if (mech_type) + *mech_type = GSS_KRB5_MECHANISM; + + if (ctx_flags) + *ctx_flags = ctx->flags; + + if (locally_initiated) + *locally_initiated = ctx->more_flags & LOCAL; + + if (open_context) + *open_context = ctx->more_flags & OPEN; + + *minor_status = 0; + + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + return GSS_S_COMPLETE; + +failed: + if (src_name) + _gsskrb5_release_name(NULL, src_name); + if (targ_name) + _gsskrb5_release_name(NULL, targ_name); + + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + return ret; +} diff --git a/source4/heimdal/lib/gssapi/krb5/inquire_cred.c b/source4/heimdal/lib/gssapi/krb5/inquire_cred.c new file mode 100644 index 0000000000..0593729365 --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/inquire_cred.c @@ -0,0 +1,178 @@ +/* + * Copyright (c) 1997, 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id: inquire_cred.c,v 1.12 2006/10/07 22:15:06 lha Exp $"); + +OM_uint32 _gsskrb5_inquire_cred +(OM_uint32 * minor_status, + const gss_cred_id_t cred_handle, + gss_name_t * output_name, + OM_uint32 * lifetime, + gss_cred_usage_t * cred_usage, + gss_OID_set * mechanisms + ) +{ + gss_cred_id_t aqcred_init = GSS_C_NO_CREDENTIAL; + gss_cred_id_t aqcred_accept = GSS_C_NO_CREDENTIAL; + gsskrb5_cred acred = NULL, icred = NULL; + OM_uint32 ret; + + *minor_status = 0; + + if (output_name) + *output_name = NULL; + if (mechanisms) + *mechanisms = GSS_C_NO_OID_SET; + + if (cred_handle == GSS_C_NO_CREDENTIAL) { + ret = _gsskrb5_acquire_cred(minor_status, + GSS_C_NO_NAME, + GSS_C_INDEFINITE, + GSS_C_NO_OID_SET, + GSS_C_ACCEPT, + &aqcred_accept, + NULL, + NULL); + if (ret == GSS_S_COMPLETE) + acred = (gsskrb5_cred)aqcred_accept; + + ret = _gsskrb5_acquire_cred(minor_status, + GSS_C_NO_NAME, + GSS_C_INDEFINITE, + GSS_C_NO_OID_SET, + GSS_C_INITIATE, + &aqcred_init, + NULL, + NULL); + if (ret == GSS_S_COMPLETE) + acred = (gsskrb5_cred)aqcred_init; + + if (icred == NULL && acred == NULL) { + *minor_status = 0; + return GSS_S_NO_CRED; + } + } else + acred = (gsskrb5_cred)cred_handle; + + if (acred) + HEIMDAL_MUTEX_lock(&acred->cred_id_mutex); + if (icred) + HEIMDAL_MUTEX_lock(&icred->cred_id_mutex); + + if (output_name != NULL) { + if (icred && icred->principal != NULL) { + gss_name_t name; + + if (acred) + name = (gss_name_t)acred->principal; + else + name = (gss_name_t)icred->principal; + + ret = _gsskrb5_duplicate_name(minor_status, name, output_name); + if (ret) + goto out; + } else if (acred && acred->usage == GSS_C_ACCEPT) { + krb5_principal princ; + *minor_status = krb5_sname_to_principal(_gsskrb5_context, NULL, + NULL, KRB5_NT_SRV_HST, + &princ); + if (*minor_status) { + ret = GSS_S_FAILURE; + goto out; + } + *output_name = (gss_name_t)princ; + } else { + krb5_principal princ; + *minor_status = krb5_get_default_principal(_gsskrb5_context, + &princ); + if (*minor_status) { + ret = GSS_S_FAILURE; + goto out; + } + *output_name = (gss_name_t)princ; + } + } + if (lifetime != NULL) { + OM_uint32 alife = GSS_C_INDEFINITE, ilife = GSS_C_INDEFINITE; + + if (acred) alife = acred->lifetime; + if (icred) ilife = icred->lifetime; + + ret = _gsskrb5_lifetime_left(minor_status, + min(alife,ilife), + lifetime); + if (ret) + goto out; + } + if (cred_usage != NULL) { + if (acred && icred) + *cred_usage = GSS_C_BOTH; + else if (acred) + *cred_usage = GSS_C_ACCEPT; + else if (icred) + *cred_usage = GSS_C_INITIATE; + else + abort(); + } + + if (mechanisms != NULL) { + ret = _gsskrb5_create_empty_oid_set(minor_status, mechanisms); + if (ret) + goto out; + if (acred) + ret = _gsskrb5_add_oid_set_member(minor_status, + &acred->mechanisms->elements[0], + mechanisms); + if (ret == GSS_S_COMPLETE && icred) + ret = _gsskrb5_add_oid_set_member(minor_status, + &icred->mechanisms->elements[0], + mechanisms); + if (ret) + goto out; + } + ret = GSS_S_COMPLETE; +out: + if (acred) + HEIMDAL_MUTEX_unlock(&acred->cred_id_mutex); + if (icred) + HEIMDAL_MUTEX_unlock(&icred->cred_id_mutex); + + if (aqcred_init != GSS_C_NO_CREDENTIAL) + ret = _gsskrb5_release_cred(minor_status, &aqcred_init); + if (aqcred_accept != GSS_C_NO_CREDENTIAL) + ret = _gsskrb5_release_cred(minor_status, &aqcred_accept); + + return ret; +} diff --git a/source4/heimdal/lib/gssapi/krb5/inquire_cred_by_mech.c b/source4/heimdal/lib/gssapi/krb5/inquire_cred_by_mech.c new file mode 100644 index 0000000000..954a5e3119 --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/inquire_cred_by_mech.c @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id: inquire_cred_by_mech.c,v 1.4 2006/10/07 22:15:08 lha Exp $"); + +OM_uint32 _gsskrb5_inquire_cred_by_mech ( + OM_uint32 * minor_status, + const gss_cred_id_t cred_handle, + const gss_OID mech_type, + gss_name_t * name, + OM_uint32 * initiator_lifetime, + OM_uint32 * acceptor_lifetime, + gss_cred_usage_t * cred_usage + ) +{ + OM_uint32 ret; + OM_uint32 lifetime; + + if (gss_oid_equal(mech_type, GSS_C_NO_OID) == 0 && + gss_oid_equal(mech_type, GSS_KRB5_MECHANISM) == 0) { + *minor_status = EINVAL; + return GSS_S_BAD_MECH; + } + + ret = _gsskrb5_inquire_cred (minor_status, + cred_handle, + name, + &lifetime, + cred_usage, + NULL); + + if (ret == 0 && cred_handle != GSS_C_NO_CREDENTIAL) { + gsskrb5_cred cred = (gsskrb5_cred)cred_handle; + gss_cred_usage_t usage; + + HEIMDAL_MUTEX_lock(&cred->cred_id_mutex); + usage = cred->usage; + HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex); + + if (initiator_lifetime) { + if (usage == GSS_C_INITIATE || usage == GSS_C_BOTH) + *initiator_lifetime = lifetime; + } + if (acceptor_lifetime) { + if (usage == GSS_C_ACCEPT || usage == GSS_C_BOTH) + *acceptor_lifetime = lifetime; + } + } + + return ret; +} diff --git a/source4/heimdal/lib/gssapi/krb5/inquire_cred_by_oid.c b/source4/heimdal/lib/gssapi/krb5/inquire_cred_by_oid.c new file mode 100644 index 0000000000..26927c740c --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/inquire_cred_by_oid.c @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2004, PADL Software Pty Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of PADL Software nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id: inquire_cred_by_oid.c,v 1.4 2006/10/07 22:15:10 lha Exp $"); + +OM_uint32 _gsskrb5_inquire_cred_by_oid + (OM_uint32 * minor_status, + const gss_cred_id_t cred_handle, + const gss_OID desired_object, + gss_buffer_set_t *data_set) +{ + gsskrb5_cred cred = (gsskrb5_cred)cred_handle; + krb5_error_code ret; + gss_buffer_desc buffer; + char *str; + + if (gss_oid_equal(desired_object, GSS_KRB5_COPY_CCACHE_X) == 0) { + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + + HEIMDAL_MUTEX_lock(&cred->cred_id_mutex); + + if (cred->ccache == NULL) { + HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex); + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + + ret = krb5_cc_get_full_name(_gsskrb5_context, cred->ccache, &str); + HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex); + if (ret) { + *minor_status = ret; + _gsskrb5_set_error_string (); + return GSS_S_FAILURE; + } + + buffer.value = str; + buffer.length = strlen(str); + + ret = gss_add_buffer_set_member(minor_status, &buffer, data_set); + if (ret != GSS_S_COMPLETE) + _gsskrb5_clear_status (); + + free(str); + + *minor_status = 0; + return GSS_S_COMPLETE; +} + diff --git a/source4/heimdal/lib/gssapi/krb5/inquire_mechs_for_name.c b/source4/heimdal/lib/gssapi/krb5/inquire_mechs_for_name.c new file mode 100644 index 0000000000..5c1f082f45 --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/inquire_mechs_for_name.c @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id: inquire_mechs_for_name.c,v 1.3 2006/10/07 22:15:13 lha Exp $"); + +OM_uint32 _gsskrb5_inquire_mechs_for_name ( + OM_uint32 * minor_status, + const gss_name_t input_name, + gss_OID_set * mech_types + ) +{ + OM_uint32 ret; + + ret = _gsskrb5_create_empty_oid_set(minor_status, mech_types); + if (ret) + return ret; + + ret = _gsskrb5_add_oid_set_member(minor_status, + GSS_KRB5_MECHANISM, + mech_types); + if (ret) + _gsskrb5_release_oid_set(NULL, mech_types); + + return ret; +} diff --git a/source4/heimdal/lib/gssapi/krb5/inquire_names_for_mech.c b/source4/heimdal/lib/gssapi/krb5/inquire_names_for_mech.c new file mode 100644 index 0000000000..5d8aefab1c --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/inquire_names_for_mech.c @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id: inquire_names_for_mech.c,v 1.3 2006/10/07 22:15:15 lha Exp $"); + + +static gss_OID *name_list[] = { + &GSS_C_NT_HOSTBASED_SERVICE, + &GSS_C_NT_USER_NAME, + &GSS_KRB5_NT_PRINCIPAL_NAME, + &GSS_C_NT_EXPORT_NAME, + NULL +}; + +OM_uint32 _gsskrb5_inquire_names_for_mech ( + OM_uint32 * minor_status, + const gss_OID mechanism, + gss_OID_set * name_types + ) +{ + OM_uint32 ret; + int i; + + *minor_status = 0; + + if (gss_oid_equal(mechanism, GSS_KRB5_MECHANISM) == 0 && + gss_oid_equal(mechanism, GSS_C_NULL_OID) == 0) { + *name_types = GSS_C_NO_OID_SET; + return GSS_S_BAD_MECH; + } + + ret = _gsskrb5_create_empty_oid_set(minor_status, name_types); + if (ret != GSS_S_COMPLETE) + return ret; + + for (i = 0; name_list[i] != NULL; i++) { + ret = _gsskrb5_add_oid_set_member(minor_status, + *(name_list[i]), + name_types); + if (ret != GSS_S_COMPLETE) + break; + } + + if (ret != GSS_S_COMPLETE) + _gsskrb5_release_oid_set(NULL, name_types); + + return GSS_S_COMPLETE; +} diff --git a/source4/heimdal/lib/gssapi/krb5/inquire_sec_context_by_oid.c b/source4/heimdal/lib/gssapi/krb5/inquire_sec_context_by_oid.c new file mode 100644 index 0000000000..0b46cc5495 --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/inquire_sec_context_by_oid.c @@ -0,0 +1,559 @@ +/* + * Copyright (c) 2004, PADL Software Pty Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of PADL Software nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id: inquire_sec_context_by_oid.c,v 1.8 2006/10/24 15:55:28 lha Exp $"); + +static int +oid_prefix_equal(gss_OID oid_enc, gss_OID prefix_enc, unsigned *suffix) +{ + int ret; + heim_oid oid; + heim_oid prefix; + + *suffix = 0; + + ret = der_get_oid(oid_enc->elements, oid_enc->length, + &oid, NULL); + if (ret) { + return 0; + } + + ret = der_get_oid(prefix_enc->elements, prefix_enc->length, + &prefix, NULL); + if (ret) { + der_free_oid(&oid); + return 0; + } + + ret = 0; + + if (oid.length - 1 == prefix.length) { + *suffix = oid.components[oid.length - 1]; + oid.length--; + ret = (der_heim_oid_cmp(&oid, &prefix) == 0); + oid.length++; + } + + der_free_oid(&oid); + der_free_oid(&prefix); + + return ret; +} + +static OM_uint32 inquire_sec_context_tkt_flags + (OM_uint32 *minor_status, + const gsskrb5_ctx context_handle, + gss_buffer_set_t *data_set) +{ + OM_uint32 tkt_flags; + unsigned char buf[4]; + gss_buffer_desc value; + + HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex); + + if (context_handle->ticket == NULL) { + HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); + _gsskrb5_set_status("No ticket from which to obtain flags"); + *minor_status = EINVAL; + return GSS_S_BAD_MECH; + } + + tkt_flags = TicketFlags2int(context_handle->ticket->ticket.flags); + HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); + + _gsskrb5_encode_om_uint32(tkt_flags, buf); + value.length = sizeof(buf); + value.value = buf; + + return gss_add_buffer_set_member(minor_status, + &value, + data_set); +} + +enum keytype { ACCEPTOR_KEY, INITIATOR_KEY, TOKEN_KEY }; + +static OM_uint32 inquire_sec_context_get_subkey + (OM_uint32 *minor_status, + const gsskrb5_ctx context_handle, + enum keytype keytype, + gss_buffer_set_t *data_set) +{ + krb5_keyblock *key = NULL; + krb5_storage *sp = NULL; + krb5_data data; + OM_uint32 maj_stat = GSS_S_COMPLETE; + krb5_error_code ret; + + krb5_data_zero(&data); + + sp = krb5_storage_emem(); + if (sp == NULL) { + _gsskrb5_clear_status(); + ret = ENOMEM; + goto out; + } + + HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex); + switch(keytype) { + case ACCEPTOR_KEY: + ret = _gsskrb5i_get_acceptor_subkey(context_handle, &key); + if (ret) + _gsskrb5_set_error_string (); + break; + case INITIATOR_KEY: + ret = _gsskrb5i_get_initiator_subkey(context_handle, &key); + if (ret) + _gsskrb5_set_error_string (); + break; + case TOKEN_KEY: + ret = _gsskrb5i_get_token_key(context_handle, &key); + if (ret) + _gsskrb5_set_error_string (); + break; + default: + _gsskrb5_set_status("%d is not a valid subkey type", keytype); + ret = EINVAL; + break; + } + HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); + if (ret) + goto out; + + ret = krb5_store_keyblock(sp, *key); + krb5_free_keyblock (_gsskrb5_context, key); + if (ret) { + _gsskrb5_set_error_string (); + goto out; + } + + ret = krb5_storage_to_data(sp, &data); + if (ret) { + _gsskrb5_set_error_string (); + goto out; + } + + { + gss_buffer_desc value; + + value.length = data.length; + value.value = data.data; + + maj_stat = gss_add_buffer_set_member(minor_status, + &value, + data_set); + } + +out: + krb5_data_free(&data); + if (sp) + krb5_storage_free(sp); + if (ret) { + *minor_status = ret; + maj_stat = GSS_S_FAILURE; + } + return maj_stat; +} + +static OM_uint32 inquire_sec_context_authz_data + (OM_uint32 *minor_status, + const gsskrb5_ctx context_handle, + unsigned ad_type, + gss_buffer_set_t *data_set) +{ + krb5_data data; + gss_buffer_desc ad_data; + OM_uint32 ret; + + *minor_status = 0; + *data_set = GSS_C_NO_BUFFER_SET; + + HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex); + if (context_handle->ticket == NULL) { + HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); + *minor_status = EINVAL; + _gsskrb5_set_status("No ticket to obtain authz data from"); + return GSS_S_NO_CONTEXT; + } + + ret = krb5_ticket_get_authorization_data_type(_gsskrb5_context, + context_handle->ticket, + ad_type, + &data); + HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); + if (ret) { + _gsskrb5_set_error_string (); + *minor_status = ret; + return GSS_S_FAILURE; + } + + ad_data.value = data.data; + ad_data.length = data.length; + + ret = gss_add_buffer_set_member(minor_status, + &ad_data, + data_set); + + krb5_data_free(&data); + + return ret; +} + +static OM_uint32 inquire_sec_context_has_updated_spnego + (OM_uint32 *minor_status, + const gsskrb5_ctx context_handle, + gss_buffer_set_t *data_set) +{ + int is_updated = 0; + + *minor_status = 0; + *data_set = GSS_C_NO_BUFFER_SET; + + /* + * For Windows SPNEGO implementations, both the initiator and the + * acceptor are assumed to have been updated if a "newer" [CLAR] or + * different enctype is negotiated for use by the Kerberos GSS-API + * mechanism. + */ + HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex); + _gsskrb5i_is_cfx(context_handle, &is_updated); + if (is_updated == 0) { + krb5_keyblock *acceptor_subkey; + + if (context_handle->more_flags & LOCAL) + acceptor_subkey = context_handle->auth_context->remote_subkey; + else + acceptor_subkey = context_handle->auth_context->local_subkey; + + if (acceptor_subkey != NULL) + is_updated = (acceptor_subkey->keytype != + context_handle->auth_context->keyblock->keytype); + } + HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); + + return is_updated ? GSS_S_COMPLETE : GSS_S_FAILURE; +} + +/* + * + */ + +static OM_uint32 +export_lucid_sec_context_v1(OM_uint32 *minor_status, + gsskrb5_ctx context_handle, + gss_buffer_set_t *data_set) +{ + krb5_storage *sp = NULL; + OM_uint32 major_status = GSS_S_COMPLETE; + krb5_error_code ret; + krb5_keyblock *key = NULL; + int32_t number; + int is_cfx; + krb5_data data; + + *minor_status = 0; + + GSSAPI_KRB5_INIT (); + + HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex); + + _gsskrb5i_is_cfx(context_handle, &is_cfx); + + sp = krb5_storage_emem(); + if (sp == NULL) { + _gsskrb5_clear_status(); + ret = ENOMEM; + goto out; + } + + ret = krb5_store_int32(sp, 1); + if (ret) goto out; + ret = krb5_store_int32(sp, (context_handle->more_flags & LOCAL) ? 1 : 0); + if (ret) goto out; + ret = krb5_store_int32(sp, context_handle->lifetime); + if (ret) goto out; + krb5_auth_con_getlocalseqnumber (_gsskrb5_context, + context_handle->auth_context, + &number); + ret = krb5_store_uint32(sp, (uint32_t)0); /* store top half as zero */ + ret = krb5_store_uint32(sp, (uint32_t)number); + krb5_auth_getremoteseqnumber (_gsskrb5_context, + context_handle->auth_context, + &number); + ret = krb5_store_uint32(sp, (uint32_t)0); /* store top half as zero */ + ret = krb5_store_uint32(sp, (uint32_t)number); + ret = krb5_store_int32(sp, (is_cfx) ? 1 : 0); + if (ret) goto out; + + ret = _gsskrb5i_get_token_key(context_handle, &key); + if (ret) goto out; + + if (is_cfx == 0) { + int sign_alg, seal_alg; + + switch (key->keytype) { + case ETYPE_DES_CBC_CRC: + case ETYPE_DES_CBC_MD4: + case ETYPE_DES_CBC_MD5: + sign_alg = 0; + seal_alg = 0; + break; + case ETYPE_DES3_CBC_MD5: + case ETYPE_DES3_CBC_SHA1: + sign_alg = 4; + seal_alg = 2; + break; + case ETYPE_ARCFOUR_HMAC_MD5: + case ETYPE_ARCFOUR_HMAC_MD5_56: + sign_alg = 17; + seal_alg = 16; + break; + default: + sign_alg = -1; + seal_alg = -1; + break; + } + ret = krb5_store_int32(sp, sign_alg); + if (ret) goto out; + ret = krb5_store_int32(sp, seal_alg); + if (ret) goto out; + /* ctx_key */ + ret = krb5_store_keyblock(sp, *key); + if (ret) goto out; + } else { + int subkey_p = (context_handle->more_flags & ACCEPTOR_SUBKEY) ? 1 : 0; + + /* have_acceptor_subkey */ + ret = krb5_store_int32(sp, subkey_p); + if (ret) goto out; + /* ctx_key */ + ret = krb5_store_keyblock(sp, *key); + if (ret) goto out; + /* acceptor_subkey */ + if (subkey_p) { + ret = krb5_store_keyblock(sp, *key); + if (ret) goto out; + } + } + ret = krb5_storage_to_data(sp, &data); + if (ret) goto out; + + { + gss_buffer_desc ad_data; + + ad_data.value = data.data; + ad_data.length = data.length; + + ret = gss_add_buffer_set_member(minor_status, &ad_data, data_set); + krb5_data_free(&data); + if (ret) + goto out; + } + +out: + if (key) + krb5_free_keyblock (_gsskrb5_context, key); + if (sp) + krb5_storage_free(sp); + if (ret) { + *minor_status = ret; + major_status = GSS_S_FAILURE; + } + HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); + return major_status; +} + +static OM_uint32 +get_authtime(OM_uint32 *minor_status, + gsskrb5_ctx ctx, + gss_buffer_set_t *data_set) + +{ + gss_buffer_desc value; + OM_uint32 authtime; + + HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); + if (ctx->ticket == NULL) { + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + _gsskrb5_set_status("No ticket to obtain auth time from"); + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + + authtime = ctx->ticket->ticket.authtime; + + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + + value.length = 4; + value.value = malloc(value.length); + if (!value.value) { + _gsskrb5_clear_status(); + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + _gsskrb5_encode_om_uint32(authtime, value.value); + + return gss_add_buffer_set_member(minor_status, + &value, + data_set); +} + + +static OM_uint32 +get_service_keyblock + (OM_uint32 *minor_status, + gsskrb5_ctx ctx, + gss_buffer_set_t *data_set) +{ + krb5_storage *sp = NULL; + krb5_data data; + OM_uint32 maj_stat = GSS_S_COMPLETE; + krb5_error_code ret = EINVAL; + + sp = krb5_storage_emem(); + if (sp == NULL) { + _gsskrb5_clear_status(); + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); + if (ctx->service_keyblock == NULL) { + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + _gsskrb5_set_status("No service keyblock on gssapi context"); + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + + krb5_data_zero(&data); + + ret = krb5_store_keyblock(sp, *ctx->service_keyblock); + + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + + if (ret) + goto out; + + ret = krb5_storage_to_data(sp, &data); + if (ret) + goto out; + + { + gss_buffer_desc value; + + value.length = data.length; + value.value = data.data; + + maj_stat = gss_add_buffer_set_member(minor_status, + &value, + data_set); + } + +out: + krb5_data_free(&data); + if (sp) + krb5_storage_free(sp); + if (ret) { + _gsskrb5_set_error_string (); + *minor_status = ret; + maj_stat = GSS_S_FAILURE; + } + return maj_stat; +} +/* + * + */ + +OM_uint32 _gsskrb5_inquire_sec_context_by_oid + (OM_uint32 *minor_status, + const gss_ctx_id_t context_handle, + const gss_OID desired_object, + gss_buffer_set_t *data_set) +{ + const gsskrb5_ctx ctx = (const gsskrb5_ctx) context_handle; + unsigned suffix; + + if (ctx == NULL) { + *minor_status = EINVAL; + return GSS_S_NO_CONTEXT; + } + + if (gss_oid_equal(desired_object, GSS_KRB5_GET_TKT_FLAGS_X)) { + return inquire_sec_context_tkt_flags(minor_status, + ctx, + data_set); + } else if (gss_oid_equal(desired_object, GSS_C_PEER_HAS_UPDATED_SPNEGO)) { + return inquire_sec_context_has_updated_spnego(minor_status, + ctx, + data_set); + } else if (gss_oid_equal(desired_object, GSS_KRB5_GET_SUBKEY_X)) { + return inquire_sec_context_get_subkey(minor_status, + ctx, + TOKEN_KEY, + data_set); + } else if (gss_oid_equal(desired_object, GSS_KRB5_GET_INITIATOR_SUBKEY_X)) { + return inquire_sec_context_get_subkey(minor_status, + ctx, + INITIATOR_KEY, + data_set); + } else if (gss_oid_equal(desired_object, GSS_KRB5_GET_ACCEPTOR_SUBKEY_X)) { + return inquire_sec_context_get_subkey(minor_status, + ctx, + ACCEPTOR_KEY, + data_set); + } else if (gss_oid_equal(desired_object, GSS_KRB5_GET_AUTHTIME_X)) { + return get_authtime(minor_status, ctx, data_set); + } else if (oid_prefix_equal(desired_object, + GSS_KRB5_EXTRACT_AUTHZ_DATA_FROM_SEC_CONTEXT_X, + &suffix)) { + return inquire_sec_context_authz_data(minor_status, + ctx, + suffix, + data_set); + } else if (oid_prefix_equal(desired_object, + GSS_KRB5_EXPORT_LUCID_CONTEXT_X, + &suffix)) { + if (suffix == 1) + return export_lucid_sec_context_v1(minor_status, + ctx, + data_set); + *minor_status = 0; + return GSS_S_FAILURE; + } else if (gss_oid_equal(desired_object, GSS_KRB5_GET_SERVICE_KEYBLOCK_X)) { + return get_service_keyblock(minor_status, ctx, data_set); + } else { + *minor_status = 0; + return GSS_S_FAILURE; + } +} + diff --git a/source4/heimdal/lib/gssapi/krb5/process_context_token.c b/source4/heimdal/lib/gssapi/krb5/process_context_token.c new file mode 100644 index 0000000000..99568c9dd0 --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/process_context_token.c @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id: process_context_token.c,v 1.4 2006/10/07 22:15:19 lha Exp $"); + +OM_uint32 _gsskrb5_process_context_token ( + OM_uint32 *minor_status, + const gss_ctx_id_t context_handle, + const gss_buffer_t token_buffer + ) +{ + OM_uint32 ret = GSS_S_FAILURE; + gss_buffer_desc empty_buffer; + gss_qop_t qop_state; + + empty_buffer.length = 0; + empty_buffer.value = NULL; + + qop_state = GSS_C_QOP_DEFAULT; + + ret = _gsskrb5_verify_mic_internal(minor_status, + (gsskrb5_ctx)context_handle, + token_buffer, &empty_buffer, + GSS_C_QOP_DEFAULT, "\x01\x02"); + + if (ret == GSS_S_COMPLETE) + ret = _gsskrb5_delete_sec_context(minor_status, + rk_UNCONST(&context_handle), + GSS_C_NO_BUFFER); + if (ret == GSS_S_COMPLETE) + *minor_status = 0; + + return ret; +} diff --git a/source4/heimdal/lib/gssapi/krb5/release_buffer.c b/source4/heimdal/lib/gssapi/krb5/release_buffer.c new file mode 100644 index 0000000000..b62ad02117 --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/release_buffer.c @@ -0,0 +1,48 @@ +/* + * Copyright (c) 1997 - 2000, 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id: release_buffer.c,v 1.7 2006/10/07 22:15:22 lha Exp $"); + +OM_uint32 _gsskrb5_release_buffer + (OM_uint32 * minor_status, + gss_buffer_t buffer + ) +{ + *minor_status = 0; + free (buffer->value); + buffer->value = NULL; + buffer->length = 0; + return GSS_S_COMPLETE; +} diff --git a/source4/heimdal/lib/gssapi/krb5/release_cred.c b/source4/heimdal/lib/gssapi/krb5/release_cred.c new file mode 100644 index 0000000000..662461ccfd --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/release_cred.c @@ -0,0 +1,76 @@ +/* + * Copyright (c) 1997-2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id: release_cred.c,v 1.13 2006/10/07 22:15:24 lha Exp $"); + +OM_uint32 _gsskrb5_release_cred + (OM_uint32 * minor_status, + gss_cred_id_t * cred_handle + ) +{ + gsskrb5_cred cred; + + *minor_status = 0; + + if (*cred_handle == NULL) + return GSS_S_COMPLETE; + + cred = (gsskrb5_cred)*cred_handle; + *cred_handle = GSS_C_NO_CREDENTIAL; + + GSSAPI_KRB5_INIT (); + + HEIMDAL_MUTEX_lock(&cred->cred_id_mutex); + + if (cred->principal != NULL) + krb5_free_principal(_gsskrb5_context, cred->principal); + if (cred->keytab != NULL) + krb5_kt_close(_gsskrb5_context, cred->keytab); + if (cred->ccache != NULL) { + const krb5_cc_ops *ops; + ops = krb5_cc_get_ops(_gsskrb5_context, cred->ccache); + if (cred->cred_flags & GSS_CF_DESTROY_CRED_ON_RELEASE) + krb5_cc_destroy(_gsskrb5_context, cred->ccache); + else + krb5_cc_close(_gsskrb5_context, cred->ccache); + } + _gsskrb5_release_oid_set(NULL, &cred->mechanisms); + HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex); + HEIMDAL_MUTEX_destroy(&cred->cred_id_mutex); + memset(cred, 0, sizeof(*cred)); + free(cred); + return GSS_S_COMPLETE; +} + diff --git a/source4/heimdal/lib/gssapi/krb5/release_name.c b/source4/heimdal/lib/gssapi/krb5/release_name.c new file mode 100644 index 0000000000..a92ad939a5 --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/release_name.c @@ -0,0 +1,55 @@ +/* + * Copyright (c) 1997 - 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id: release_name.c,v 1.10 2006/10/07 22:15:26 lha Exp $"); + +OM_uint32 _gsskrb5_release_name + (OM_uint32 * minor_status, + gss_name_t * input_name + ) +{ + krb5_principal name = (krb5_principal)*input_name; + + GSSAPI_KRB5_INIT (); + + if (minor_status) + *minor_status = 0; + + *input_name = GSS_C_NO_NAME; + + krb5_free_principal(_gsskrb5_context, name); + + return GSS_S_COMPLETE; +} diff --git a/source4/heimdal/lib/gssapi/krb5/release_oid_set.c b/source4/heimdal/lib/gssapi/krb5/release_oid_set.c new file mode 100644 index 0000000000..a9f79a3082 --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/release_oid_set.c @@ -0,0 +1,49 @@ +/* + * Copyright (c) 1997 - 2000, 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id: release_oid_set.c,v 1.7 2006/10/07 22:15:30 lha Exp $"); + +OM_uint32 _gsskrb5_release_oid_set + (OM_uint32 * minor_status, + gss_OID_set * set + ) +{ + if (minor_status) + *minor_status = 0; + free ((*set)->elements); + free (*set); + *set = GSS_C_NO_OID_SET; + return GSS_S_COMPLETE; +} diff --git a/source4/heimdal/lib/gssapi/krb5/sequence.c b/source4/heimdal/lib/gssapi/krb5/sequence.c new file mode 100755 index 0000000000..3014edd04d --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/sequence.c @@ -0,0 +1,294 @@ +/* + * Copyright (c) 2003 - 2006 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id: sequence.c,v 1.8 2006/10/07 22:15:32 lha Exp $"); + +#define DEFAULT_JITTER_WINDOW 20 + +struct gss_msg_order { + OM_uint32 flags; + OM_uint32 start; + OM_uint32 length; + OM_uint32 jitter_window; + OM_uint32 first_seq; + OM_uint32 elem[1]; +}; + + +/* + * + */ + +static OM_uint32 +msg_order_alloc(OM_uint32 *minor_status, + struct gss_msg_order **o, + OM_uint32 jitter_window) +{ + size_t len; + + len = jitter_window * sizeof((*o)->elem[0]); + len += sizeof(**o); + len -= sizeof((*o)->elem[0]); + + *o = calloc(1, len); + if (*o == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + *minor_status = 0; + return GSS_S_COMPLETE; +} + +/* + * + */ + +OM_uint32 +_gssapi_msg_order_create(OM_uint32 *minor_status, + struct gss_msg_order **o, + OM_uint32 flags, + OM_uint32 seq_num, + OM_uint32 jitter_window, + int use_64) +{ + OM_uint32 ret; + + if (jitter_window == 0) + jitter_window = DEFAULT_JITTER_WINDOW; + + ret = msg_order_alloc(minor_status, o, jitter_window); + if(ret != GSS_S_COMPLETE) + return ret; + + (*o)->flags = flags; + (*o)->length = 0; + (*o)->first_seq = seq_num; + (*o)->jitter_window = jitter_window; + (*o)->elem[0] = seq_num - 1; + + *minor_status = 0; + return GSS_S_COMPLETE; +} + +OM_uint32 +_gssapi_msg_order_destroy(struct gss_msg_order **m) +{ + free(*m); + *m = NULL; + return GSS_S_COMPLETE; +} + +static void +elem_set(struct gss_msg_order *o, unsigned int slot, OM_uint32 val) +{ + o->elem[slot % o->jitter_window] = val; +} + +static void +elem_insert(struct gss_msg_order *o, + unsigned int after_slot, + OM_uint32 seq_num) +{ + assert(o->jitter_window > after_slot); + + if (o->length > after_slot) + memmove(&o->elem[after_slot + 1], &o->elem[after_slot], + (o->length - after_slot - 1) * sizeof(o->elem[0])); + + elem_set(o, after_slot, seq_num); + + if (o->length < o->jitter_window) + o->length++; +} + +/* rule 1: expected sequence number */ +/* rule 2: > expected sequence number */ +/* rule 3: seqnum < seqnum(first) */ +/* rule 4+5: seqnum in [seqnum(first),seqnum(last)] */ + +OM_uint32 +_gssapi_msg_order_check(struct gss_msg_order *o, OM_uint32 seq_num) +{ + OM_uint32 r; + int i; + + if (o == NULL) + return GSS_S_COMPLETE; + + if ((o->flags & (GSS_C_REPLAY_FLAG|GSS_C_SEQUENCE_FLAG)) == 0) + return GSS_S_COMPLETE; + + /* check if the packet is the next in order */ + if (o->elem[0] == seq_num - 1) { + elem_insert(o, 0, seq_num); + return GSS_S_COMPLETE; + } + + r = (o->flags & (GSS_C_REPLAY_FLAG|GSS_C_SEQUENCE_FLAG))==GSS_C_REPLAY_FLAG; + + /* sequence number larger then largest sequence number + * or smaller then the first sequence number */ + if (seq_num > o->elem[0] + || seq_num < o->first_seq + || o->length == 0) + { + elem_insert(o, 0, seq_num); + if (r) { + return GSS_S_COMPLETE; + } else { + return GSS_S_GAP_TOKEN; + } + } + + assert(o->length > 0); + + /* sequence number smaller the first sequence number */ + if (seq_num < o->elem[o->length - 1]) { + if (r) + return(GSS_S_OLD_TOKEN); + else + return(GSS_S_UNSEQ_TOKEN); + } + + if (seq_num == o->elem[o->length - 1]) { + return GSS_S_DUPLICATE_TOKEN; + } + + for (i = 0; i < o->length - 1; i++) { + if (o->elem[i] == seq_num) + return GSS_S_DUPLICATE_TOKEN; + if (o->elem[i + 1] < seq_num && o->elem[i] < seq_num) { + elem_insert(o, i, seq_num); + if (r) + return GSS_S_COMPLETE; + else + return GSS_S_UNSEQ_TOKEN; + } + } + + return GSS_S_FAILURE; +} + +OM_uint32 +_gssapi_msg_order_f(OM_uint32 flags) +{ + return flags & (GSS_C_SEQUENCE_FLAG|GSS_C_REPLAY_FLAG); +} + +/* + * Translate `o` into inter-process format and export in to `sp'. + */ + +krb5_error_code +_gssapi_msg_order_export(krb5_storage *sp, struct gss_msg_order *o) +{ + krb5_error_code kret; + OM_uint32 i; + + kret = krb5_store_int32(sp, o->flags); + if (kret) + return kret; + kret = krb5_store_int32(sp, o->start); + if (kret) + return kret; + kret = krb5_store_int32(sp, o->length); + if (kret) + return kret; + kret = krb5_store_int32(sp, o->jitter_window); + if (kret) + return kret; + kret = krb5_store_int32(sp, o->first_seq); + if (kret) + return kret; + + for (i = 0; i < o->jitter_window; i++) { + kret = krb5_store_int32(sp, o->elem[i]); + if (kret) + return kret; + } + + return 0; +} + +OM_uint32 +_gssapi_msg_order_import(OM_uint32 *minor_status, + krb5_storage *sp, + struct gss_msg_order **o) +{ + OM_uint32 ret; + krb5_error_code kret; + int32_t i, flags, start, length, jitter_window, first_seq; + + kret = krb5_ret_int32(sp, &flags); + if (kret) + goto failed; + ret = krb5_ret_int32(sp, &start); + if (kret) + goto failed; + ret = krb5_ret_int32(sp, &length); + if (kret) + goto failed; + ret = krb5_ret_int32(sp, &jitter_window); + if (kret) + goto failed; + ret = krb5_ret_int32(sp, &first_seq); + if (kret) + goto failed; + + ret = msg_order_alloc(minor_status, o, jitter_window); + if (ret != GSS_S_COMPLETE) + return ret; + + (*o)->flags = flags; + (*o)->start = start; + (*o)->length = length; + (*o)->jitter_window = jitter_window; + (*o)->first_seq = first_seq; + + for( i = 0; i < jitter_window; i++ ) { + kret = krb5_ret_int32(sp, (int32_t*)&((*o)->elem[i])); + if (kret) + goto failed; + } + + *minor_status = 0; + return GSS_S_COMPLETE; + +failed: + _gssapi_msg_order_destroy(o); + *minor_status = kret; + return GSS_S_FAILURE; +} diff --git a/source4/heimdal/lib/gssapi/krb5/set_cred_option.c b/source4/heimdal/lib/gssapi/krb5/set_cred_option.c new file mode 100644 index 0000000000..5807ef0166 --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/set_cred_option.c @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2004, PADL Software Pty Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of PADL Software nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id: set_cred_option.c,v 1.4 2006/10/24 20:14:13 lha Exp $"); + +static gss_OID_desc gss_krb5_import_cred_x_oid_desc = +{9, (void *)"\x2b\x06\x01\x04\x01\xa9\x4a\x13\x04"}; /* XXX */ + +gss_OID GSS_KRB5_IMPORT_CRED_X = &gss_krb5_import_cred_x_oid_desc; + +static OM_uint32 +import_cred(OM_uint32 *minor_status, + gss_cred_id_t *cred_handle, + const gss_buffer_t value) +{ + OM_uint32 major_stat; + krb5_error_code ret; + krb5_principal keytab_principal = NULL; + krb5_keytab keytab = NULL; + krb5_storage *sp = NULL; + krb5_ccache id = NULL; + char *str; + + if (cred_handle == NULL || *cred_handle != GSS_C_NO_CREDENTIAL) { + *minor_status = 0; + return GSS_S_FAILURE; + } + + sp = krb5_storage_from_mem(value->value, value->length); + if (sp == NULL) { + *minor_status = 0; + return GSS_S_FAILURE; + } + + /* credential cache name */ + ret = krb5_ret_string(sp, &str); + if (ret) { + *minor_status = ret; + major_stat = GSS_S_FAILURE; + goto out; + } + if (str[0]) { + ret = krb5_cc_resolve(_gsskrb5_context, str, &id); + if (ret) { + *minor_status = ret; + major_stat = GSS_S_FAILURE; + goto out; + } + } + free(str); + str = NULL; + + /* keytab principal name */ + ret = krb5_ret_string(sp, &str); + if (ret == 0 && str[0]) + ret = krb5_parse_name(_gsskrb5_context, str, &keytab_principal); + if (ret) { + *minor_status = ret; + major_stat = GSS_S_FAILURE; + goto out; + } + free(str); + str = NULL; + + /* keytab principal */ + ret = krb5_ret_string(sp, &str); + if (ret) { + *minor_status = ret; + major_stat = GSS_S_FAILURE; + goto out; + } + if (str[0]) { + ret = krb5_kt_resolve(_gsskrb5_context, str, &keytab); + if (ret) { + *minor_status = ret; + major_stat = GSS_S_FAILURE; + goto out; + } + } + free(str); + str = NULL; + + major_stat = _gsskrb5_import_cred(minor_status, id, keytab_principal, + keytab, cred_handle); +out: + if (id) + krb5_cc_close(_gsskrb5_context, id); + if (keytab_principal) + krb5_free_principal(_gsskrb5_context, keytab_principal); + if (keytab) + krb5_kt_close(_gsskrb5_context, keytab); + if (str) + free(str); + if (sp) + krb5_storage_free(sp); + + return major_stat; +} + + +OM_uint32 +_gsskrb5_set_cred_option + (OM_uint32 *minor_status, + gss_cred_id_t *cred_handle, + const gss_OID desired_object, + const gss_buffer_t value) +{ + GSSAPI_KRB5_INIT (); + + if (value == GSS_C_NO_BUFFER) { + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + + if (gss_oid_equal(desired_object, GSS_KRB5_IMPORT_CRED_X)) { + return import_cred(minor_status, cred_handle, value); + } + + *minor_status = EINVAL; + return GSS_S_FAILURE; +} diff --git a/source4/heimdal/lib/gssapi/krb5/set_sec_context_option.c b/source4/heimdal/lib/gssapi/krb5/set_sec_context_option.c new file mode 100644 index 0000000000..67f5e8e722 --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/set_sec_context_option.c @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2004, PADL Software Pty Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of PADL Software nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * glue routine for _gsskrb5_inquire_sec_context_by_oid + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id: set_sec_context_option.c,v 1.6 2006/10/20 18:58:22 lha Exp $"); + +static OM_uint32 +get_bool(OM_uint32 *minor_status, + const gss_buffer_t value, + int *flag) +{ + if (value->value == NULL || value->length != 1) { + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + *flag = *((const char *)value->value) != 0; + return GSS_S_COMPLETE; +} + +OM_uint32 +_gsskrb5_set_sec_context_option + (OM_uint32 *minor_status, + gss_ctx_id_t *context_handle, + const gss_OID desired_object, + const gss_buffer_t value) +{ + OM_uint32 maj_stat; + + GSSAPI_KRB5_INIT (); + + if (value == GSS_C_NO_BUFFER) { + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + + if (gss_oid_equal(desired_object, GSS_KRB5_COMPAT_DES3_MIC_X)) { + gsskrb5_ctx ctx; + int flag; + + if (*context_handle == GSS_C_NO_CONTEXT) { + *minor_status = EINVAL; + return GSS_S_NO_CONTEXT; + } + + maj_stat = get_bool(minor_status, value, &flag); + if (maj_stat != GSS_S_COMPLETE) + return maj_stat; + + ctx = (gsskrb5_ctx)*context_handle; + HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); + if (flag) + ctx->more_flags |= COMPAT_OLD_DES3; + else + ctx->more_flags &= ~COMPAT_OLD_DES3; + ctx->more_flags |= COMPAT_OLD_DES3_SELECTED; + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + return GSS_S_COMPLETE; + } else if (gss_oid_equal(desired_object, GSS_KRB5_SET_DNS_CANONICALIZE_X)) { + int flag; + + maj_stat = get_bool(minor_status, value, &flag); + if (maj_stat != GSS_S_COMPLETE) + return maj_stat; + + krb5_set_dns_canonicalize_hostname(_gsskrb5_context, flag); + return GSS_S_COMPLETE; + + } else if (gss_oid_equal(desired_object, GSS_KRB5_REGISTER_ACCEPTOR_IDENTITY_X)) { + char *str; + + if (value == NULL || value->length == 0) { + str = NULL; + } else { + str = malloc(value->length + 1); + if (str) { + *minor_status = 0; + return GSS_S_UNAVAILABLE; + } + memcpy(str, value->value, value->length); + str[value->length] = '\0'; + } + + _gsskrb5_register_acceptor_identity(str); + free(str); + + *minor_status = 0; + return GSS_S_COMPLETE; + + } else if (gss_oid_equal(desired_object, GSS_KRB5_SEND_TO_KDC_X)) { + + if (value == NULL || value->length == 0) { + krb5_set_send_to_kdc_func(_gsskrb5_context, NULL, NULL); + } else { + struct gsskrb5_send_to_kdc c; + + if (value->length != sizeof(c)) { + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + memcpy(&c, value->value, sizeof(c)); + krb5_set_send_to_kdc_func(_gsskrb5_context, + (krb5_send_to_kdc_func)c.func, + c.ptr); + } + + *minor_status = 0; + return GSS_S_COMPLETE; + } + + + *minor_status = EINVAL; + return GSS_S_FAILURE; +} diff --git a/source4/heimdal/lib/gssapi/krb5/test_oid_set_member.c b/source4/heimdal/lib/gssapi/krb5/test_oid_set_member.c new file mode 100644 index 0000000000..5a0ac4418f --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/test_oid_set_member.c @@ -0,0 +1,55 @@ +/* + * Copyright (c) 1997, 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id: test_oid_set_member.c,v 1.7 2006/10/07 22:15:50 lha Exp $"); + +OM_uint32 _gsskrb5_test_oid_set_member + (OM_uint32 * minor_status, + const gss_OID member, + const gss_OID_set set, + int * present + ) +{ + size_t i; + + *minor_status = 0; + *present = 0; + for (i = 0; i < set->count; ++i) + if (gss_oid_equal(member, &set->elements[i]) != 0) { + *present = 1; + break; + } + return GSS_S_COMPLETE; +} diff --git a/source4/heimdal/lib/gssapi/krb5/unwrap.c b/source4/heimdal/lib/gssapi/krb5/unwrap.c new file mode 100644 index 0000000000..758390080c --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/unwrap.c @@ -0,0 +1,416 @@ +/* + * Copyright (c) 1997 - 2004 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id: unwrap.c,v 1.38 2006/10/18 15:59:28 lha Exp $"); + +static OM_uint32 +unwrap_des + (OM_uint32 * minor_status, + const gsskrb5_ctx context_handle, + const gss_buffer_t input_message_buffer, + gss_buffer_t output_message_buffer, + int * conf_state, + gss_qop_t * qop_state, + krb5_keyblock *key + ) +{ + u_char *p, *seq; + size_t len; + MD5_CTX md5; + u_char hash[16]; + DES_key_schedule schedule; + DES_cblock deskey; + DES_cblock zero; + int i; + uint32_t seq_number; + size_t padlength; + OM_uint32 ret; + int cstate; + int cmp; + + p = input_message_buffer->value; + ret = _gsskrb5_verify_header (&p, + input_message_buffer->length, + "\x02\x01", + GSS_KRB5_MECHANISM); + if (ret) + return ret; + + if (memcmp (p, "\x00\x00", 2) != 0) + return GSS_S_BAD_SIG; + p += 2; + if (memcmp (p, "\x00\x00", 2) == 0) { + cstate = 1; + } else if (memcmp (p, "\xFF\xFF", 2) == 0) { + cstate = 0; + } else + return GSS_S_BAD_MIC; + p += 2; + if(conf_state != NULL) + *conf_state = cstate; + if (memcmp (p, "\xff\xff", 2) != 0) + return GSS_S_DEFECTIVE_TOKEN; + p += 2; + p += 16; + + len = p - (u_char *)input_message_buffer->value; + + if(cstate) { + /* decrypt data */ + memcpy (&deskey, key->keyvalue.data, sizeof(deskey)); + + for (i = 0; i < sizeof(deskey); ++i) + deskey[i] ^= 0xf0; + DES_set_key (&deskey, &schedule); + memset (&zero, 0, sizeof(zero)); + DES_cbc_encrypt ((void *)p, + (void *)p, + input_message_buffer->length - len, + &schedule, + &zero, + DES_DECRYPT); + + memset (deskey, 0, sizeof(deskey)); + memset (&schedule, 0, sizeof(schedule)); + } + /* check pad */ + ret = _gssapi_verify_pad(input_message_buffer, + input_message_buffer->length - len, + &padlength); + if (ret) + return ret; + + MD5_Init (&md5); + MD5_Update (&md5, p - 24, 8); + MD5_Update (&md5, p, input_message_buffer->length - len); + MD5_Final (hash, &md5); + + memset (&zero, 0, sizeof(zero)); + memcpy (&deskey, key->keyvalue.data, sizeof(deskey)); + DES_set_key (&deskey, &schedule); + DES_cbc_cksum ((void *)hash, (void *)hash, sizeof(hash), + &schedule, &zero); + if (memcmp (p - 8, hash, 8) != 0) + return GSS_S_BAD_MIC; + + /* verify sequence number */ + + HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex); + + p -= 16; + DES_set_key (&deskey, &schedule); + DES_cbc_encrypt ((void *)p, (void *)p, 8, + &schedule, (DES_cblock *)hash, DES_DECRYPT); + + memset (deskey, 0, sizeof(deskey)); + memset (&schedule, 0, sizeof(schedule)); + + seq = p; + _gsskrb5_decode_om_uint32(seq, &seq_number); + + if (context_handle->more_flags & LOCAL) + cmp = memcmp(&seq[4], "\xff\xff\xff\xff", 4); + else + cmp = memcmp(&seq[4], "\x00\x00\x00\x00", 4); + + if (cmp != 0) { + HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); + return GSS_S_BAD_MIC; + } + + ret = _gssapi_msg_order_check(context_handle->order, seq_number); + if (ret) { + HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); + return ret; + } + + HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); + + /* copy out data */ + + output_message_buffer->length = input_message_buffer->length + - len - padlength - 8; + output_message_buffer->value = malloc(output_message_buffer->length); + if(output_message_buffer->length != 0 && output_message_buffer->value == NULL) + return GSS_S_FAILURE; + memcpy (output_message_buffer->value, + p + 24, + output_message_buffer->length); + return GSS_S_COMPLETE; +} + +static OM_uint32 +unwrap_des3 + (OM_uint32 * minor_status, + const gsskrb5_ctx context_handle, + const gss_buffer_t input_message_buffer, + gss_buffer_t output_message_buffer, + int * conf_state, + gss_qop_t * qop_state, + krb5_keyblock *key + ) +{ + u_char *p; + size_t len; + u_char *seq; + krb5_data seq_data; + u_char cksum[20]; + uint32_t seq_number; + size_t padlength; + OM_uint32 ret; + int cstate; + krb5_crypto crypto; + Checksum csum; + int cmp; + + p = input_message_buffer->value; + ret = _gsskrb5_verify_header (&p, + input_message_buffer->length, + "\x02\x01", + GSS_KRB5_MECHANISM); + if (ret) + return ret; + + if (memcmp (p, "\x04\x00", 2) != 0) /* HMAC SHA1 DES3_KD */ + return GSS_S_BAD_SIG; + p += 2; + if (memcmp (p, "\x02\x00", 2) == 0) { + cstate = 1; + } else if (memcmp (p, "\xff\xff", 2) == 0) { + cstate = 0; + } else + return GSS_S_BAD_MIC; + p += 2; + if(conf_state != NULL) + *conf_state = cstate; + if (memcmp (p, "\xff\xff", 2) != 0) + return GSS_S_DEFECTIVE_TOKEN; + p += 2; + p += 28; + + len = p - (u_char *)input_message_buffer->value; + + if(cstate) { + /* decrypt data */ + krb5_data tmp; + + ret = krb5_crypto_init(_gsskrb5_context, key, + ETYPE_DES3_CBC_NONE, &crypto); + if (ret) { + _gsskrb5_set_error_string (); + *minor_status = ret; + return GSS_S_FAILURE; + } + ret = krb5_decrypt(_gsskrb5_context, crypto, KRB5_KU_USAGE_SEAL, + p, input_message_buffer->length - len, &tmp); + krb5_crypto_destroy(_gsskrb5_context, crypto); + if (ret) { + _gsskrb5_set_error_string (); + *minor_status = ret; + return GSS_S_FAILURE; + } + assert (tmp.length == input_message_buffer->length - len); + + memcpy (p, tmp.data, tmp.length); + krb5_data_free(&tmp); + } + /* check pad */ + ret = _gssapi_verify_pad(input_message_buffer, + input_message_buffer->length - len, + &padlength); + if (ret) + return ret; + + /* verify sequence number */ + + HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex); + + p -= 28; + + ret = krb5_crypto_init(_gsskrb5_context, key, + ETYPE_DES3_CBC_NONE, &crypto); + if (ret) { + _gsskrb5_set_error_string (); + *minor_status = ret; + HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); + return GSS_S_FAILURE; + } + { + DES_cblock ivec; + + memcpy(&ivec, p + 8, 8); + ret = krb5_decrypt_ivec (_gsskrb5_context, + crypto, + KRB5_KU_USAGE_SEQ, + p, 8, &seq_data, + &ivec); + } + krb5_crypto_destroy (_gsskrb5_context, crypto); + if (ret) { + _gsskrb5_set_error_string (); + *minor_status = ret; + HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); + return GSS_S_FAILURE; + } + if (seq_data.length != 8) { + krb5_data_free (&seq_data); + *minor_status = 0; + HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); + return GSS_S_BAD_MIC; + } + + seq = seq_data.data; + _gsskrb5_decode_om_uint32(seq, &seq_number); + + if (context_handle->more_flags & LOCAL) + cmp = memcmp(&seq[4], "\xff\xff\xff\xff", 4); + else + cmp = memcmp(&seq[4], "\x00\x00\x00\x00", 4); + + krb5_data_free (&seq_data); + if (cmp != 0) { + *minor_status = 0; + HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); + return GSS_S_BAD_MIC; + } + + ret = _gssapi_msg_order_check(context_handle->order, seq_number); + if (ret) { + *minor_status = 0; + HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); + return ret; + } + + HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); + + /* verify checksum */ + + memcpy (cksum, p + 8, 20); + + memcpy (p + 20, p - 8, 8); + + csum.cksumtype = CKSUMTYPE_HMAC_SHA1_DES3; + csum.checksum.length = 20; + csum.checksum.data = cksum; + + ret = krb5_crypto_init(_gsskrb5_context, key, 0, &crypto); + if (ret) { + _gsskrb5_set_error_string (); + *minor_status = ret; + return GSS_S_FAILURE; + } + + ret = krb5_verify_checksum (_gsskrb5_context, crypto, + KRB5_KU_USAGE_SIGN, + p + 20, + input_message_buffer->length - len + 8, + &csum); + krb5_crypto_destroy (_gsskrb5_context, crypto); + if (ret) { + _gsskrb5_set_error_string (); + *minor_status = ret; + return GSS_S_FAILURE; + } + + /* copy out data */ + + output_message_buffer->length = input_message_buffer->length + - len - padlength - 8; + output_message_buffer->value = malloc(output_message_buffer->length); + if(output_message_buffer->length != 0 && output_message_buffer->value == NULL) + return GSS_S_FAILURE; + memcpy (output_message_buffer->value, + p + 36, + output_message_buffer->length); + return GSS_S_COMPLETE; +} + +OM_uint32 _gsskrb5_unwrap + (OM_uint32 * minor_status, + const gss_ctx_id_t context_handle, + const gss_buffer_t input_message_buffer, + gss_buffer_t output_message_buffer, + int * conf_state, + gss_qop_t * qop_state + ) +{ + krb5_keyblock *key; + OM_uint32 ret; + krb5_keytype keytype; + gsskrb5_ctx ctx = (gsskrb5_ctx) context_handle; + + output_message_buffer->value = NULL; + output_message_buffer->length = 0; + + if (qop_state != NULL) + *qop_state = GSS_C_QOP_DEFAULT; + HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); + ret = _gsskrb5i_get_token_key(ctx, &key); + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + if (ret) { + _gsskrb5_set_error_string (); + *minor_status = ret; + return GSS_S_FAILURE; + } + krb5_enctype_to_keytype (_gsskrb5_context, key->keytype, &keytype); + + *minor_status = 0; + + switch (keytype) { + case KEYTYPE_DES : + ret = unwrap_des (minor_status, ctx, + input_message_buffer, output_message_buffer, + conf_state, qop_state, key); + break; + case KEYTYPE_DES3 : + ret = unwrap_des3 (minor_status, ctx, + input_message_buffer, output_message_buffer, + conf_state, qop_state, key); + break; + case KEYTYPE_ARCFOUR: + case KEYTYPE_ARCFOUR_56: + ret = _gssapi_unwrap_arcfour (minor_status, ctx, + input_message_buffer, output_message_buffer, + conf_state, qop_state, key); + break; + default : + ret = _gssapi_unwrap_cfx (minor_status, ctx, + input_message_buffer, output_message_buffer, + conf_state, qop_state, key); + break; + } + krb5_free_keyblock (_gsskrb5_context, key); + return ret; +} diff --git a/source4/heimdal/lib/gssapi/krb5/verify_mic.c b/source4/heimdal/lib/gssapi/krb5/verify_mic.c new file mode 100644 index 0000000000..920937cafc --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/verify_mic.c @@ -0,0 +1,339 @@ +/* + * Copyright (c) 1997 - 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id: verify_mic.c,v 1.36 2006/10/18 15:59:30 lha Exp $"); + +static OM_uint32 +verify_mic_des + (OM_uint32 * minor_status, + const gsskrb5_ctx context_handle, + const gss_buffer_t message_buffer, + const gss_buffer_t token_buffer, + gss_qop_t * qop_state, + krb5_keyblock *key, + char *type + ) +{ + u_char *p; + MD5_CTX md5; + u_char hash[16], *seq; + DES_key_schedule schedule; + DES_cblock zero; + DES_cblock deskey; + uint32_t seq_number; + OM_uint32 ret; + int cmp; + + p = token_buffer->value; + ret = _gsskrb5_verify_header (&p, + token_buffer->length, + type, + GSS_KRB5_MECHANISM); + if (ret) + return ret; + + if (memcmp(p, "\x00\x00", 2) != 0) + return GSS_S_BAD_SIG; + p += 2; + if (memcmp (p, "\xff\xff\xff\xff", 4) != 0) + return GSS_S_BAD_MIC; + p += 4; + p += 16; + + /* verify checksum */ + MD5_Init (&md5); + MD5_Update (&md5, p - 24, 8); + MD5_Update (&md5, message_buffer->value, + message_buffer->length); + MD5_Final (hash, &md5); + + memset (&zero, 0, sizeof(zero)); + memcpy (&deskey, key->keyvalue.data, sizeof(deskey)); + + DES_set_key (&deskey, &schedule); + DES_cbc_cksum ((void *)hash, (void *)hash, sizeof(hash), + &schedule, &zero); + if (memcmp (p - 8, hash, 8) != 0) { + memset (deskey, 0, sizeof(deskey)); + memset (&schedule, 0, sizeof(schedule)); + return GSS_S_BAD_MIC; + } + + /* verify sequence number */ + + HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex); + + p -= 16; + DES_set_key (&deskey, &schedule); + DES_cbc_encrypt ((void *)p, (void *)p, 8, + &schedule, (DES_cblock *)hash, DES_DECRYPT); + + memset (deskey, 0, sizeof(deskey)); + memset (&schedule, 0, sizeof(schedule)); + + seq = p; + _gsskrb5_decode_om_uint32(seq, &seq_number); + + if (context_handle->more_flags & LOCAL) + cmp = memcmp(&seq[4], "\xff\xff\xff\xff", 4); + else + cmp = memcmp(&seq[4], "\x00\x00\x00\x00", 4); + + if (cmp != 0) { + HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); + return GSS_S_BAD_MIC; + } + + ret = _gssapi_msg_order_check(context_handle->order, seq_number); + if (ret) { + HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); + return ret; + } + + HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); + + return GSS_S_COMPLETE; +} + +static OM_uint32 +verify_mic_des3 + (OM_uint32 * minor_status, + const gsskrb5_ctx context_handle, + const gss_buffer_t message_buffer, + const gss_buffer_t token_buffer, + gss_qop_t * qop_state, + krb5_keyblock *key, + char *type + ) +{ + u_char *p; + u_char *seq; + uint32_t seq_number; + OM_uint32 ret; + krb5_crypto crypto; + krb5_data seq_data; + int cmp, docompat; + Checksum csum; + char *tmp; + char ivec[8]; + + p = token_buffer->value; + ret = _gsskrb5_verify_header (&p, + token_buffer->length, + type, + GSS_KRB5_MECHANISM); + if (ret) + return ret; + + if (memcmp(p, "\x04\x00", 2) != 0) /* SGN_ALG = HMAC SHA1 DES3-KD */ + return GSS_S_BAD_SIG; + p += 2; + if (memcmp (p, "\xff\xff\xff\xff", 4) != 0) + return GSS_S_BAD_MIC; + p += 4; + + ret = krb5_crypto_init(_gsskrb5_context, key, + ETYPE_DES3_CBC_NONE, &crypto); + if (ret){ + _gsskrb5_set_error_string (); + *minor_status = ret; + return GSS_S_FAILURE; + } + + /* verify sequence number */ + docompat = 0; +retry: + if (docompat) + memset(ivec, 0, 8); + else + memcpy(ivec, p + 8, 8); + + ret = krb5_decrypt_ivec (_gsskrb5_context, + crypto, + KRB5_KU_USAGE_SEQ, + p, 8, &seq_data, ivec); + if (ret) { + if (docompat++) { + _gsskrb5_set_error_string (); + krb5_crypto_destroy (_gsskrb5_context, crypto); + *minor_status = ret; + return GSS_S_FAILURE; + } else + goto retry; + } + + if (seq_data.length != 8) { + krb5_data_free (&seq_data); + if (docompat++) { + krb5_crypto_destroy (_gsskrb5_context, crypto); + return GSS_S_BAD_MIC; + } else + goto retry; + } + + HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex); + + seq = seq_data.data; + _gsskrb5_decode_om_uint32(seq, &seq_number); + + if (context_handle->more_flags & LOCAL) + cmp = memcmp(&seq[4], "\xff\xff\xff\xff", 4); + else + cmp = memcmp(&seq[4], "\x00\x00\x00\x00", 4); + + krb5_data_free (&seq_data); + if (cmp != 0) { + krb5_crypto_destroy (_gsskrb5_context, crypto); + *minor_status = 0; + HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); + return GSS_S_BAD_MIC; + } + + ret = _gssapi_msg_order_check(context_handle->order, seq_number); + if (ret) { + krb5_crypto_destroy (_gsskrb5_context, crypto); + *minor_status = 0; + HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); + return ret; + } + + /* verify checksum */ + + tmp = malloc (message_buffer->length + 8); + if (tmp == NULL) { + krb5_crypto_destroy (_gsskrb5_context, crypto); + HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + memcpy (tmp, p - 8, 8); + memcpy (tmp + 8, message_buffer->value, message_buffer->length); + + csum.cksumtype = CKSUMTYPE_HMAC_SHA1_DES3; + csum.checksum.length = 20; + csum.checksum.data = p + 8; + + ret = krb5_verify_checksum (_gsskrb5_context, crypto, + KRB5_KU_USAGE_SIGN, + tmp, message_buffer->length + 8, + &csum); + free (tmp); + if (ret) { + _gsskrb5_set_error_string (); + krb5_crypto_destroy (_gsskrb5_context, crypto); + *minor_status = ret; + HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); + return GSS_S_BAD_MIC; + } + HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); + + krb5_crypto_destroy (_gsskrb5_context, crypto); + return GSS_S_COMPLETE; +} + +OM_uint32 +_gsskrb5_verify_mic_internal + (OM_uint32 * minor_status, + const gsskrb5_ctx context_handle, + const gss_buffer_t message_buffer, + const gss_buffer_t token_buffer, + gss_qop_t * qop_state, + char * type + ) +{ + krb5_keyblock *key; + OM_uint32 ret; + krb5_keytype keytype; + + HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex); + ret = _gsskrb5i_get_token_key(context_handle, &key); + HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); + if (ret) { + _gsskrb5_set_error_string (); + *minor_status = ret; + return GSS_S_FAILURE; + } + *minor_status = 0; + krb5_enctype_to_keytype (_gsskrb5_context, key->keytype, &keytype); + switch (keytype) { + case KEYTYPE_DES : + ret = verify_mic_des (minor_status, context_handle, + message_buffer, token_buffer, qop_state, key, + type); + break; + case KEYTYPE_DES3 : + ret = verify_mic_des3 (minor_status, context_handle, + message_buffer, token_buffer, qop_state, key, + type); + break; + case KEYTYPE_ARCFOUR : + case KEYTYPE_ARCFOUR_56 : + ret = _gssapi_verify_mic_arcfour (minor_status, context_handle, + message_buffer, token_buffer, + qop_state, key, type); + break; + default : + ret = _gssapi_verify_mic_cfx (minor_status, context_handle, + message_buffer, token_buffer, qop_state, + key); + break; + } + krb5_free_keyblock (_gsskrb5_context, key); + + return ret; +} + +OM_uint32 +_gsskrb5_verify_mic + (OM_uint32 * minor_status, + const gss_ctx_id_t context_handle, + const gss_buffer_t message_buffer, + const gss_buffer_t token_buffer, + gss_qop_t * qop_state + ) +{ + OM_uint32 ret; + + if (qop_state != NULL) + *qop_state = GSS_C_QOP_DEFAULT; + + ret = _gsskrb5_verify_mic_internal(minor_status, + (gsskrb5_ctx)context_handle, + message_buffer, token_buffer, + qop_state, "\x01\x01"); + + return ret; +} diff --git a/source4/heimdal/lib/gssapi/krb5/wrap.c b/source4/heimdal/lib/gssapi/krb5/wrap.c new file mode 100644 index 0000000000..8514137999 --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/wrap.c @@ -0,0 +1,545 @@ +/* + * Copyright (c) 1997 - 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id: wrap.c,v 1.37 2006/10/18 15:59:33 lha Exp $"); + +/* + * Return initiator subkey, or if that doesn't exists, the subkey. + */ + +krb5_error_code +_gsskrb5i_get_initiator_subkey(const gsskrb5_ctx ctx, krb5_keyblock **key) +{ + krb5_error_code ret; + *key = NULL; + + if (ctx->more_flags & LOCAL) { + ret = krb5_auth_con_getlocalsubkey(_gsskrb5_context, + ctx->auth_context, + key); + } else { + ret = krb5_auth_con_getremotesubkey(_gsskrb5_context, + ctx->auth_context, + key); + } + if (*key == NULL) + ret = krb5_auth_con_getkey(_gsskrb5_context, + ctx->auth_context, + key); + if (*key == NULL) { + _gsskrb5_set_status("No initiator subkey available"); + return GSS_KRB5_S_KG_NO_SUBKEY; + } + return ret; +} + +krb5_error_code +_gsskrb5i_get_acceptor_subkey(const gsskrb5_ctx ctx, krb5_keyblock **key) +{ + krb5_error_code ret; + *key = NULL; + + if (ctx->more_flags & LOCAL) { + ret = krb5_auth_con_getremotesubkey(_gsskrb5_context, + ctx->auth_context, + key); + } else { + ret = krb5_auth_con_getlocalsubkey(_gsskrb5_context, + ctx->auth_context, + key); + } + if (*key == NULL) { + _gsskrb5_set_status("No acceptor subkey available"); + return GSS_KRB5_S_KG_NO_SUBKEY; + } + return ret; +} + +OM_uint32 +_gsskrb5i_get_token_key(const gsskrb5_ctx ctx, krb5_keyblock **key) +{ + _gsskrb5i_get_acceptor_subkey(ctx, key); + if(*key == NULL) { + /* + * Only use the initiator subkey or ticket session key if an + * acceptor subkey was not required. + */ + if ((ctx->more_flags & ACCEPTOR_SUBKEY) == 0) + _gsskrb5i_get_initiator_subkey(ctx, key); + } + if (*key == NULL) { + _gsskrb5_set_status("No token key available"); + return GSS_KRB5_S_KG_NO_SUBKEY; + } + _gsskrb5_clear_status(); + return 0; +} + +static OM_uint32 +sub_wrap_size ( + OM_uint32 req_output_size, + OM_uint32 * max_input_size, + int blocksize, + int extrasize + ) +{ + size_t len, total_len; + + len = 8 + req_output_size + blocksize + extrasize; + + _gsskrb5_encap_length(len, &len, &total_len, GSS_KRB5_MECHANISM); + + total_len -= req_output_size; /* token length */ + if (total_len < req_output_size) { + *max_input_size = (req_output_size - total_len); + (*max_input_size) &= (~(OM_uint32)(blocksize - 1)); + } else { + *max_input_size = 0; + } + return GSS_S_COMPLETE; +} + +OM_uint32 +_gsskrb5_wrap_size_limit ( + OM_uint32 * minor_status, + const gss_ctx_id_t context_handle, + int conf_req_flag, + gss_qop_t qop_req, + OM_uint32 req_output_size, + OM_uint32 * max_input_size + ) +{ + krb5_keyblock *key; + OM_uint32 ret; + krb5_keytype keytype; + const gsskrb5_ctx ctx = (const gsskrb5_ctx) context_handle; + + HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); + ret = _gsskrb5i_get_token_key(ctx, &key); + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + if (ret) { + _gsskrb5_set_error_string (); + *minor_status = ret; + return GSS_S_FAILURE; + } + krb5_enctype_to_keytype (_gsskrb5_context, key->keytype, &keytype); + + switch (keytype) { + case KEYTYPE_DES : + ret = sub_wrap_size(req_output_size, max_input_size, 8, 22); + break; + case KEYTYPE_ARCFOUR: + case KEYTYPE_ARCFOUR_56: + ret = _gssapi_wrap_size_arcfour(minor_status, ctx, + conf_req_flag, qop_req, + req_output_size, max_input_size, key); + break; + case KEYTYPE_DES3 : + ret = sub_wrap_size(req_output_size, max_input_size, 8, 34); + break; + default : + ret = _gssapi_wrap_size_cfx(minor_status, ctx, + conf_req_flag, qop_req, + req_output_size, max_input_size, key); + break; + } + krb5_free_keyblock (_gsskrb5_context, key); + *minor_status = 0; + return ret; +} + +static OM_uint32 +wrap_des + (OM_uint32 * minor_status, + const gsskrb5_ctx ctx, + 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 *p; + MD5_CTX md5; + u_char hash[16]; + DES_key_schedule schedule; + DES_cblock deskey; + DES_cblock zero; + int i; + int32_t seq_number; + size_t len, total_len, padlength, datalen; + + padlength = 8 - (input_message_buffer->length % 8); + datalen = input_message_buffer->length + padlength + 8; + len = datalen + 22; + _gsskrb5_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) { + output_message_buffer->length = 0; + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + p = _gsskrb5_make_header(output_message_buffer->value, + len, + "\x02\x01", /* TOK_ID */ + GSS_KRB5_MECHANISM); + + /* SGN_ALG */ + memcpy (p, "\x00\x00", 2); + p += 2; + /* SEAL_ALG */ + if(conf_req_flag) + memcpy (p, "\x00\x00", 2); + else + memcpy (p, "\xff\xff", 2); + p += 2; + /* Filler */ + memcpy (p, "\xff\xff", 2); + p += 2; + + /* fill in later */ + memset (p, 0, 16); + p += 16; + + /* confounder + data + pad */ + krb5_generate_random_block(p, 8); + memcpy (p + 8, input_message_buffer->value, + input_message_buffer->length); + memset (p + 8 + input_message_buffer->length, padlength, padlength); + + /* checksum */ + MD5_Init (&md5); + MD5_Update (&md5, p - 24, 8); + MD5_Update (&md5, p, datalen); + MD5_Final (hash, &md5); + + memset (&zero, 0, sizeof(zero)); + memcpy (&deskey, key->keyvalue.data, sizeof(deskey)); + DES_set_key (&deskey, &schedule); + DES_cbc_cksum ((void *)hash, (void *)hash, sizeof(hash), + &schedule, &zero); + memcpy (p - 8, hash, 8); + + /* sequence number */ + HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); + krb5_auth_con_getlocalseqnumber (_gsskrb5_context, + ctx->auth_context, + &seq_number); + + p -= 16; + p[0] = (seq_number >> 0) & 0xFF; + p[1] = (seq_number >> 8) & 0xFF; + p[2] = (seq_number >> 16) & 0xFF; + p[3] = (seq_number >> 24) & 0xFF; + memset (p + 4, + (ctx->more_flags & LOCAL) ? 0 : 0xFF, + 4); + + DES_set_key (&deskey, &schedule); + DES_cbc_encrypt ((void *)p, (void *)p, 8, + &schedule, (DES_cblock *)(p + 8), DES_ENCRYPT); + + krb5_auth_con_setlocalseqnumber (_gsskrb5_context, + ctx->auth_context, + ++seq_number); + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + + /* encrypt the data */ + p += 16; + + if(conf_req_flag) { + memcpy (&deskey, key->keyvalue.data, sizeof(deskey)); + + for (i = 0; i < sizeof(deskey); ++i) + deskey[i] ^= 0xf0; + DES_set_key (&deskey, &schedule); + memset (&zero, 0, sizeof(zero)); + DES_cbc_encrypt ((void *)p, + (void *)p, + datalen, + &schedule, + &zero, + DES_ENCRYPT); + } + memset (deskey, 0, sizeof(deskey)); + memset (&schedule, 0, sizeof(schedule)); + + if(conf_state != NULL) + *conf_state = conf_req_flag; + *minor_status = 0; + return GSS_S_COMPLETE; +} + +static OM_uint32 +wrap_des3 + (OM_uint32 * minor_status, + const gsskrb5_ctx ctx, + 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 *p; + u_char seq[8]; + int32_t seq_number; + size_t len, total_len, padlength, datalen; + uint32_t ret; + krb5_crypto crypto; + Checksum cksum; + krb5_data encdata; + + padlength = 8 - (input_message_buffer->length % 8); + datalen = input_message_buffer->length + padlength + 8; + len = datalen + 34; + _gsskrb5_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) { + output_message_buffer->length = 0; + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + p = _gsskrb5_make_header(output_message_buffer->value, + len, + "\x02\x01", /* TOK_ID */ + GSS_KRB5_MECHANISM); + + /* SGN_ALG */ + memcpy (p, "\x04\x00", 2); /* HMAC SHA1 DES3-KD */ + p += 2; + /* SEAL_ALG */ + if(conf_req_flag) + memcpy (p, "\x02\x00", 2); /* DES3-KD */ + else + memcpy (p, "\xff\xff", 2); + p += 2; + /* Filler */ + memcpy (p, "\xff\xff", 2); + p += 2; + + /* calculate checksum (the above + confounder + data + pad) */ + + memcpy (p + 20, p - 8, 8); + krb5_generate_random_block(p + 28, 8); + memcpy (p + 28 + 8, input_message_buffer->value, + input_message_buffer->length); + memset (p + 28 + 8 + input_message_buffer->length, padlength, padlength); + + ret = krb5_crypto_init(_gsskrb5_context, key, 0, &crypto); + if (ret) { + _gsskrb5_set_error_string (); + free (output_message_buffer->value); + output_message_buffer->length = 0; + output_message_buffer->value = NULL; + *minor_status = ret; + return GSS_S_FAILURE; + } + + ret = krb5_create_checksum (_gsskrb5_context, + crypto, + KRB5_KU_USAGE_SIGN, + 0, + p + 20, + datalen + 8, + &cksum); + krb5_crypto_destroy (_gsskrb5_context, crypto); + if (ret) { + _gsskrb5_set_error_string (); + free (output_message_buffer->value); + output_message_buffer->length = 0; + output_message_buffer->value = NULL; + *minor_status = ret; + return GSS_S_FAILURE; + } + + /* zero out SND_SEQ + SGN_CKSUM in case */ + memset (p, 0, 28); + + memcpy (p + 8, cksum.checksum.data, cksum.checksum.length); + free_Checksum (&cksum); + + HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); + /* sequence number */ + krb5_auth_con_getlocalseqnumber (_gsskrb5_context, + ctx->auth_context, + &seq_number); + + seq[0] = (seq_number >> 0) & 0xFF; + seq[1] = (seq_number >> 8) & 0xFF; + seq[2] = (seq_number >> 16) & 0xFF; + seq[3] = (seq_number >> 24) & 0xFF; + memset (seq + 4, + (ctx->more_flags & LOCAL) ? 0 : 0xFF, + 4); + + + ret = krb5_crypto_init(_gsskrb5_context, key, ETYPE_DES3_CBC_NONE, + &crypto); + if (ret) { + free (output_message_buffer->value); + output_message_buffer->length = 0; + output_message_buffer->value = NULL; + *minor_status = ret; + return GSS_S_FAILURE; + } + + { + DES_cblock ivec; + + memcpy (&ivec, p + 8, 8); + ret = krb5_encrypt_ivec (_gsskrb5_context, + crypto, + KRB5_KU_USAGE_SEQ, + seq, 8, &encdata, + &ivec); + } + krb5_crypto_destroy (_gsskrb5_context, crypto); + if (ret) { + _gsskrb5_set_error_string (); + free (output_message_buffer->value); + output_message_buffer->length = 0; + output_message_buffer->value = NULL; + *minor_status = ret; + return GSS_S_FAILURE; + } + + assert (encdata.length == 8); + + memcpy (p, encdata.data, encdata.length); + krb5_data_free (&encdata); + + krb5_auth_con_setlocalseqnumber (_gsskrb5_context, + ctx->auth_context, + ++seq_number); + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + + /* encrypt the data */ + p += 28; + + if(conf_req_flag) { + krb5_data tmp; + + ret = krb5_crypto_init(_gsskrb5_context, key, + ETYPE_DES3_CBC_NONE, &crypto); + if (ret) { + _gsskrb5_set_error_string (); + free (output_message_buffer->value); + output_message_buffer->length = 0; + output_message_buffer->value = NULL; + *minor_status = ret; + return GSS_S_FAILURE; + } + ret = krb5_encrypt(_gsskrb5_context, crypto, KRB5_KU_USAGE_SEAL, + p, datalen, &tmp); + krb5_crypto_destroy(_gsskrb5_context, crypto); + if (ret) { + _gsskrb5_set_error_string (); + free (output_message_buffer->value); + output_message_buffer->length = 0; + output_message_buffer->value = NULL; + *minor_status = ret; + return GSS_S_FAILURE; + } + assert (tmp.length == datalen); + + memcpy (p, tmp.data, datalen); + krb5_data_free(&tmp); + } + if(conf_state != NULL) + *conf_state = conf_req_flag; + *minor_status = 0; + return GSS_S_COMPLETE; +} + +OM_uint32 _gsskrb5_wrap + (OM_uint32 * minor_status, + const gss_ctx_id_t context_handle, + 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; + OM_uint32 ret; + krb5_keytype keytype; + const gsskrb5_ctx ctx = (const gsskrb5_ctx) context_handle; + + HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); + ret = _gsskrb5i_get_token_key(ctx, &key); + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + if (ret) { + _gsskrb5_set_error_string (); + *minor_status = ret; + return GSS_S_FAILURE; + } + krb5_enctype_to_keytype (_gsskrb5_context, key->keytype, &keytype); + + switch (keytype) { + case KEYTYPE_DES : + ret = wrap_des (minor_status, ctx, conf_req_flag, + qop_req, input_message_buffer, conf_state, + output_message_buffer, key); + break; + case KEYTYPE_DES3 : + ret = wrap_des3 (minor_status, ctx, conf_req_flag, + qop_req, input_message_buffer, conf_state, + output_message_buffer, key); + break; + case KEYTYPE_ARCFOUR: + case KEYTYPE_ARCFOUR_56: + ret = _gssapi_wrap_arcfour (minor_status, ctx, conf_req_flag, + qop_req, input_message_buffer, conf_state, + output_message_buffer, key); + break; + default : + ret = _gssapi_wrap_cfx (minor_status, ctx, conf_req_flag, + qop_req, input_message_buffer, conf_state, + output_message_buffer, key); + break; + } + krb5_free_keyblock (_gsskrb5_context, key); + return ret; +} |