diff options
67 files changed, 1210 insertions, 590 deletions
diff --git a/source4/heimdal/kdc/kaserver.c b/source4/heimdal/kdc/kaserver.c index 3702ab9281..69b5bb1d6e 100644 --- a/source4/heimdal/kdc/kaserver.c +++ b/source4/heimdal/kdc/kaserver.c @@ -493,10 +493,10 @@ do_authenticate (krb5_context context, goto out; } - ret = _kdc_check_flags (context, config, - client_entry, client_name, - server_entry, server_name, - TRUE); + ret = kdc_check_flags (context, config, + client_entry, client_name, + server_entry, server_name, + TRUE); if (ret) { make_error_reply (hdr, KAPWEXPIRED, reply); goto out; @@ -790,10 +790,10 @@ do_getticket (krb5_context context, goto out; } - ret = _kdc_check_flags (context, config, - client_entry, client_name, - server_entry, server_name, - FALSE); + ret = kdc_check_flags (context, config, + client_entry, client_name, + server_entry, server_name, + FALSE); if (ret) { make_error_reply (hdr, KAPWEXPIRED, reply); goto out; diff --git a/source4/heimdal/kdc/kerberos5.c b/source4/heimdal/kdc/kerberos5.c index e364dcc1d1..43d54bf702 100644 --- a/source4/heimdal/kdc/kerberos5.c +++ b/source4/heimdal/kdc/kerberos5.c @@ -678,6 +678,12 @@ kdc_check_flags(krb5_context context, hdb_entry *client = &client_ex->entry; /* check client */ + if (client->flags.locked_out) { + kdc_log(context, config, 0, + "Client (%s) is locked out", client_name); + return KRB5KDC_ERR_POLICY; + } + if (client->flags.invalid) { kdc_log(context, config, 0, "Client (%s) has invalid bit set", client_name); @@ -727,6 +733,11 @@ kdc_check_flags(krb5_context context, if (server_ex != NULL) { hdb_entry *server = &server_ex->entry; + if (server->flags.locked_out) { + kdc_log(context, config, 0, + "Client server locked out -- %s", server_name); + return KRB5KDC_ERR_POLICY; + } if (server->flags.invalid) { kdc_log(context, config, 0, "Server has invalid flag set -- %s", server_name); @@ -883,6 +894,7 @@ _kdc_as_rep(krb5_context context, AS_REP rep; KDCOptions f = b->kdc_options; hdb_entry_ex *client = NULL, *server = NULL; + HDB *clientdb; krb5_enctype cetype, setype, sessionetype; krb5_data e_data; EncTicketPart et; @@ -966,7 +978,7 @@ _kdc_as_rep(krb5_context context, */ ret = _kdc_db_fetch(context, config, client_princ, - HDB_F_GET_CLIENT | flags, NULL, &client); + HDB_F_GET_CLIENT | flags, &clientdb, &client); if(ret){ kdc_log(context, config, 0, "UNKNOWN -- %s: %s", client_name, krb5_get_err_text(context, ret)); @@ -1114,8 +1126,8 @@ _kdc_as_rep(krb5_context context, "No client key matching pa-data (%s) -- %s", estr, client_name); free(estr); - free_EncryptedData(&enc_data); + continue; } @@ -1159,6 +1171,10 @@ _kdc_as_rep(krb5_context context, e_text = "Failed to decrypt PA-DATA"; free_EncryptedData(&enc_data); + + if (clientdb->hdb_auth_status) + (clientdb->hdb_auth_status)(context, clientdb, client, HDB_AUTH_WRONG_PASSWORD); + ret = KRB5KDC_ERR_PREAUTH_FAILED; continue; } @@ -1323,6 +1339,10 @@ _kdc_as_rep(krb5_context context, goto out; } + if (clientdb->hdb_auth_status) + (clientdb->hdb_auth_status)(context, clientdb, client, + HDB_AUTH_SUCCESS); + /* * Verify flags after the user been required to prove its identity * with in a preauth mech. diff --git a/source4/heimdal/kdc/krb5tgs.c b/source4/heimdal/kdc/krb5tgs.c index 59104da3d6..6b98506e81 100644 --- a/source4/heimdal/kdc/krb5tgs.c +++ b/source4/heimdal/kdc/krb5tgs.c @@ -492,6 +492,7 @@ check_tgs_flags(krb5_context context, static krb5_error_code check_constrained_delegation(krb5_context context, krb5_kdc_configuration *config, + HDB *clientdb, hdb_entry_ex *client, krb5_const_principal server) { @@ -499,21 +500,32 @@ check_constrained_delegation(krb5_context context, krb5_error_code ret; int i; - ret = hdb_entry_get_ConstrainedDelegACL(&client->entry, &acl); - if (ret) { - krb5_clear_error_message(context); - return ret; - } + /* if client delegates to itself, that ok */ + if (krb5_principal_compare(context, client->entry.principal, server) == TRUE) + return 0; - if (acl) { - for (i = 0; i < acl->len; i++) { - if (krb5_principal_compare(context, server, &acl->val[i]) == TRUE) - return 0; + if (clientdb->hdb_check_constrained_delegation) { + ret = clientdb->hdb_check_constrained_delegation(context, clientdb, client, server); + if (ret == 0) + return 0; + } else { + ret = hdb_entry_get_ConstrainedDelegACL(&client->entry, &acl); + if (ret) { + krb5_clear_error_message(context); + return ret; + } + + if (acl) { + for (i = 0; i < acl->len; i++) { + if (krb5_principal_compare(context, server, &acl->val[i]) == TRUE) + return 0; + } } + ret = KRB5KDC_ERR_BADOPTION; } kdc_log(context, config, 0, "Bad request for constrained delegation"); - return KRB5KDC_ERR_BADOPTION; + return ret; } /* @@ -1369,6 +1381,7 @@ tgs_build_reply(krb5_context context, krb5_principal client_principal = NULL; char *spn = NULL, *cpn = NULL; hdb_entry_ex *server = NULL, *client = NULL; + HDB *clientdb; krb5_realm ref_realm = NULL; EncTicketPart *tgt = &ticket->ticket; krb5_principals spp = NULL; @@ -1531,7 +1544,7 @@ server_lookup: } ret = _kdc_db_fetch(context, config, cp, HDB_F_GET_CLIENT | HDB_F_CANON, - NULL, &client); + &clientdb, &client); if(ret) { const char *krbtgt_realm; @@ -1792,7 +1805,7 @@ server_lookup: if (ret) { kdc_log(context, config, 0, "failed to decrypt ticket for " - "constrained delegation from %s to %s ", spn, cpn); + "constrained delegation from %s to %s ", cpn, spn); goto out; } @@ -1800,16 +1813,17 @@ server_lookup: if (adtkt.flags.forwardable == 0) { kdc_log(context, config, 0, "Missing forwardable flag on ticket for " - "constrained delegation from %s to %s ", spn, cpn); + "constrained delegation from %s to %s ", cpn, spn); ret = KRB5KDC_ERR_BADOPTION; goto out; } - ret = check_constrained_delegation(context, config, client, sp); + ret = check_constrained_delegation(context, config, clientdb, + client, sp); if (ret) { kdc_log(context, config, 0, "constrained delegation from %s to %s not allowed", - spn, cpn); + cpn, spn); goto out; } diff --git a/source4/heimdal/lib/gssapi/gssapi/gssapi.h b/source4/heimdal/lib/gssapi/gssapi/gssapi.h index 9fe2bb8b46..07c4b36325 100644 --- a/source4/heimdal/lib/gssapi/gssapi/gssapi.h +++ b/source4/heimdal/lib/gssapi/gssapi/gssapi.h @@ -768,42 +768,6 @@ gss_pseudo_random gss_buffer_t prf_out ); -/* - * AEAD support - */ - -OM_uint32 GSSAPI_LIB_FUNCTION -gss_wrap_iov(OM_uint32 * /* minor_status */, - gss_ctx_id_t /* context_handle */, - int /* conf_req_flag */, - gss_qop_t /* qop_req */, - int * /* conf_state */, - gss_iov_buffer_desc * /*iov */, - int /* iov_count */); - -OM_uint32 GSSAPI_LIB_FUNCTION -gss_unwrap_iov(OM_uint32 * /* minor_status */, - gss_ctx_id_t /* context_handle */, - int * /* conf_state */, - gss_qop_t * /* qop_state */, - gss_iov_buffer_desc * /* iov */, - int /* iov_count */); - -OM_uint32 GSSAPI_LIB_FUNCTION -gss_wrap_iov_length(OM_uint32 * /* minor_status */, - gss_ctx_id_t /* context_handle */, - int /* conf_req_flag */, - gss_qop_t /* qop_req */, - int * /* conf_state */, - gss_iov_buffer_desc * /* iov */, - int /* iov_count */); - -OM_uint32 GSSAPI_LIB_FUNCTION -gss_release_iov_buffer(OM_uint32 * /* minor_status */, - gss_iov_buffer_desc * /* iov */, - int /* iov_count */); - - OM_uint32 gss_store_cred(OM_uint32 * /* minor_status */, gss_cred_id_t /* input_cred_handle */, @@ -899,6 +863,31 @@ gss_decapsulate_token(gss_buffer_t /* input_token */, +/* + * AEAD support + */ + +/* + * GSS_IOV + */ + +OM_uint32 GSSAPI_LIB_FUNCTION +gss_wrap_iov(OM_uint32 *, gss_ctx_id_t, int, gss_qop_t, int *, + gss_iov_buffer_desc *, int); + + +OM_uint32 GSSAPI_LIB_FUNCTION +gss_unwrap_iov(OM_uint32 *, gss_ctx_id_t, int *, gss_qop_t *, + gss_iov_buffer_desc *, int); + +OM_uint32 GSSAPI_LIB_FUNCTION +gss_wrap_iov_length(OM_uint32 *, gss_ctx_id_t, int, gss_qop_t, int *, + gss_iov_buffer_desc *, int); + +OM_uint32 GSSAPI_LIB_FUNCTION +gss_release_iov_buffer(OM_uint32 *, gss_iov_buffer_desc *, int); + + #ifdef __cplusplus } #endif diff --git a/source4/heimdal/lib/gssapi/krb5/8003.c b/source4/heimdal/lib/gssapi/krb5/8003.c index f5181cc311..a6f0165e72 100644 --- a/source4/heimdal/lib/gssapi/krb5/8003.c +++ b/source4/heimdal/lib/gssapi/krb5/8003.c @@ -33,8 +33,6 @@ #include "gsskrb5_locl.h" -RCSID("$Id$"); - krb5_error_code _gsskrb5_encode_om_uint32(OM_uint32 n, u_char *p) { diff --git a/source4/heimdal/lib/gssapi/krb5/accept_sec_context.c b/source4/heimdal/lib/gssapi/krb5/accept_sec_context.c index 8ead2bdf75..8d998ed098 100644 --- a/source4/heimdal/lib/gssapi/krb5/accept_sec_context.c +++ b/source4/heimdal/lib/gssapi/krb5/accept_sec_context.c @@ -33,8 +33,6 @@ #include "gsskrb5_locl.h" -RCSID("$Id$"); - HEIMDAL_MUTEX gssapi_keytab_mutex = HEIMDAL_MUTEX_INITIALIZER; krb5_keytab _gsskrb5_keytab; @@ -519,13 +517,12 @@ gsskrb5_acceptor_start(OM_uint32 * minor_status, } /* - * Samba style get some flags (but not DCE-STYLE) + * Samba style get some flags (but not DCE-STYLE), use + * ap_options to guess the mutual flag. */ - ctx->flags = - GSS_C_REPLAY_FLAG | GSS_C_SEQUENCE_FLAG; - if (ap_options & AP_OPTS_MUTUAL_REQUIRED) { - ctx->flags |= GSS_C_MUTUAL_FLAG; - } + ctx->flags = GSS_C_REPLAY_FLAG | GSS_C_SEQUENCE_FLAG; + if (ap_options & AP_OPTS_MUTUAL_REQUIRED) + ctx->flags |= GSS_C_MUTUAL_FLAG; } } diff --git a/source4/heimdal/lib/gssapi/krb5/acquire_cred.c b/source4/heimdal/lib/gssapi/krb5/acquire_cred.c index bfab5667be..4f6f38e674 100644 --- a/source4/heimdal/lib/gssapi/krb5/acquire_cred.c +++ b/source4/heimdal/lib/gssapi/krb5/acquire_cred.c @@ -33,8 +33,6 @@ #include "gsskrb5_locl.h" -RCSID("$Id$"); - OM_uint32 __gsskrb5_ccache_lifetime(OM_uint32 *minor_status, krb5_context context, diff --git a/source4/heimdal/lib/gssapi/krb5/add_cred.c b/source4/heimdal/lib/gssapi/krb5/add_cred.c index aa96a45e45..adc8a09fa4 100644 --- a/source4/heimdal/lib/gssapi/krb5/add_cred.c +++ b/source4/heimdal/lib/gssapi/krb5/add_cred.c @@ -33,8 +33,6 @@ #include "gsskrb5_locl.h" -RCSID("$Id$"); - OM_uint32 _gsskrb5_add_cred ( OM_uint32 *minor_status, const gss_cred_id_t input_cred_handle, diff --git a/source4/heimdal/lib/gssapi/krb5/aeap.c b/source4/heimdal/lib/gssapi/krb5/aeap.c index 7dab7877d7..38a5ac2dbe 100644 --- a/source4/heimdal/lib/gssapi/krb5/aeap.c +++ b/source4/heimdal/lib/gssapi/krb5/aeap.c @@ -35,66 +35,6 @@ #include <roken.h> -static OM_uint32 -iov_allocate(OM_uint32 *minor_status, gss_iov_buffer_desc *iov, int iov_count) -{ - unsigned int i; - - for (i = 0; i < iov_count; i++) { - if (GSS_IOV_BUFFER_FLAGS(iov[i].type) & GSS_IOV_BUFFER_TYPE_FLAG_ALLOCATE){ - void *ptr = malloc(iov[i].buffer.length); - if (ptr == NULL) - abort(); - if (iov[i].buffer.value) - memcpy(ptr, iov[i].buffer.value, iov[i].buffer.length); - iov[i].buffer.value = ptr; - iov[i].type |= GSS_IOV_BUFFER_TYPE_FLAG_ALLOCATED; - } - } - return GSS_S_COMPLETE; -} - -static OM_uint32 -iov_map(OM_uint32 *minor_status, - const gss_iov_buffer_desc *iov, - int iov_count, - krb5_crypto_iov *data) -{ - unsigned int i; - - for (i = 0; i < iov_count; i++) { - switch(GSS_IOV_BUFFER_TYPE(iov[i].type)) { - case GSS_IOV_BUFFER_TYPE_EMPTY: - data[i].flags = KRB5_CRYPTO_TYPE_EMPTY; - break; - case GSS_IOV_BUFFER_TYPE_DATA: - data[i].flags = KRB5_CRYPTO_TYPE_DATA; - break; - case GSS_IOV_BUFFER_TYPE_SIGN_ONLY: - data[i].flags = KRB5_CRYPTO_TYPE_SIGN_ONLY; - break; - case GSS_IOV_BUFFER_TYPE_HEADER: - data[i].flags = KRB5_CRYPTO_TYPE_HEADER; - break; - case GSS_IOV_BUFFER_TYPE_TRAILER: - data[i].flags = KRB5_CRYPTO_TYPE_TRAILER; - break; - case GSS_IOV_BUFFER_TYPE_PADDING: - data[i].flags = KRB5_CRYPTO_TYPE_PADDING; - break; - case GSS_IOV_BUFFER_TYPE_STREAM: - abort(); - break; - default: - *minor_status = EINVAL; - return GSS_S_FAILURE; - } - data[i].data.data = iov[i].buffer.value; - data[i].data.length = iov[i].buffer.length; - } - return GSS_S_COMPLETE; -} - OM_uint32 GSSAPI_LIB_FUNCTION _gk_wrap_iov(OM_uint32 * minor_status, gss_ctx_id_t context_handle, @@ -104,50 +44,17 @@ _gk_wrap_iov(OM_uint32 * minor_status, gss_iov_buffer_desc *iov, int iov_count) { - gsskrb5_ctx ctx = (gsskrb5_ctx) context_handle; - krb5_context context; - OM_uint32 major_status, junk; - krb5_crypto_iov *data; - krb5_error_code ret; - unsigned usage; - - GSSAPI_KRB5_INIT (&context); - - major_status = iov_allocate(minor_status, iov, iov_count); - if (major_status != GSS_S_COMPLETE) - return major_status; - - data = calloc(iov_count, sizeof(data[0])); - if (data == NULL) { - gss_release_iov_buffer(&junk, iov, iov_count); - *minor_status = ENOMEM; - return GSS_S_FAILURE; - } - - major_status = iov_map(minor_status, iov, iov_count, data); - if (major_status != GSS_S_COMPLETE) { - gss_release_iov_buffer(&junk, iov, iov_count); - free(data); - return major_status; - } + const gsskrb5_ctx ctx = (const gsskrb5_ctx) context_handle; + krb5_context context; - if (ctx->more_flags & LOCAL) { - usage = KRB5_KU_USAGE_ACCEPTOR_SIGN; - } else { - usage = KRB5_KU_USAGE_INITIATOR_SIGN; - } + GSSAPI_KRB5_INIT (&context); - ret = krb5_encrypt_iov_ivec(context, ctx->crypto, usage, - data, iov_count, NULL); - free(data); - if (ret) { - gss_release_iov_buffer(&junk, iov, iov_count); - *minor_status = ret; - return GSS_S_FAILURE; - } + if (ctx->more_flags & IS_CFX) + return _gssapi_wrap_cfx_iov(minor_status, ctx, context, + conf_req_flag, conf_state, + iov, iov_count); - *minor_status = 0; - return GSS_S_COMPLETE; + return GSS_S_FAILURE; } OM_uint32 GSSAPI_LIB_FUNCTION @@ -158,50 +65,16 @@ _gk_unwrap_iov(OM_uint32 *minor_status, gss_iov_buffer_desc *iov, int iov_count) { - gsskrb5_ctx ctx = (gsskrb5_ctx) context_handle; + const gsskrb5_ctx ctx = (const gsskrb5_ctx) context_handle; krb5_context context; - krb5_error_code ret; - OM_uint32 major_status, junk; - krb5_crypto_iov *data; - unsigned usage; GSSAPI_KRB5_INIT (&context); - - major_status = iov_allocate(minor_status, iov, iov_count); - if (major_status != GSS_S_COMPLETE) - return major_status; - - data = calloc(iov_count, sizeof(data[0])); - if (data == NULL) { - gss_release_iov_buffer(&junk, iov, iov_count); - *minor_status = ENOMEM; - return GSS_S_FAILURE; - } - - major_status = iov_map(minor_status, iov, iov_count, data); - if (major_status != GSS_S_COMPLETE) { - gss_release_iov_buffer(&junk, iov, iov_count); - free(data); - return major_status; - } - - if (ctx->more_flags & LOCAL) { - usage = KRB5_KU_USAGE_INITIATOR_SIGN; - } else { - usage = KRB5_KU_USAGE_ACCEPTOR_SIGN; - } - - ret = krb5_decrypt_iov_ivec(context, ctx->crypto, usage, - data, iov_count, NULL); - free(data); - if (ret) { - *minor_status = ret; - gss_release_iov_buffer(&junk, iov, iov_count); - return GSS_S_FAILURE; - } - - *minor_status = 0; - return GSS_S_COMPLETE; + + if (ctx->more_flags & IS_CFX) + return _gssapi_unwrap_cfx_iov(minor_status, ctx, context, + conf_state, qop_state, iov, iov_count); + + return GSS_S_FAILURE; } OM_uint32 GSSAPI_LIB_FUNCTION @@ -213,59 +86,15 @@ _gk_wrap_iov_length(OM_uint32 * minor_status, gss_iov_buffer_desc *iov, int iov_count) { - gsskrb5_ctx ctx = (gsskrb5_ctx) context_handle; + const gsskrb5_ctx ctx = (const gsskrb5_ctx) context_handle; krb5_context context; - unsigned int i; - size_t size; - size_t *padding = NULL; - + GSSAPI_KRB5_INIT (&context); - *minor_status = 0; - - for (size = 0, i = 0; i < iov_count; i++) { - switch(GSS_IOV_BUFFER_TYPE(iov[i].type)) { - case GSS_IOV_BUFFER_TYPE_EMPTY: - break; - case GSS_IOV_BUFFER_TYPE_DATA: - size += iov[i].buffer.length; - break; - case GSS_IOV_BUFFER_TYPE_HEADER: - iov[i].buffer.length = - krb5_crypto_length(context, ctx->crypto, KRB5_CRYPTO_TYPE_HEADER); - size += iov[i].buffer.length; - break; - case GSS_IOV_BUFFER_TYPE_TRAILER: - iov[i].buffer.length = - krb5_crypto_length(context, ctx->crypto, KRB5_CRYPTO_TYPE_TRAILER); - size += iov[i].buffer.length; - break; - case GSS_IOV_BUFFER_TYPE_PADDING: - if (padding != NULL) { - *minor_status = 0; - return GSS_S_FAILURE; - } - padding = &iov[i].buffer.length; - break; - case GSS_IOV_BUFFER_TYPE_STREAM: - size += iov[i].buffer.length; - break; - case GSS_IOV_BUFFER_TYPE_SIGN_ONLY: - break; - default: - *minor_status = EINVAL; - return GSS_S_FAILURE; - } - } - if (padding) { - size_t pad = krb5_crypto_length(context, ctx->crypto, - KRB5_CRYPTO_TYPE_PADDING); - if (pad > 1) { - *padding = pad - (size % pad); - if (*padding == pad) - *padding = 0; - } else - *padding = 0; - } - - return GSS_S_COMPLETE; + + if (ctx->more_flags & IS_CFX) + return _gssapi_wrap_iov_length_cfx(minor_status, ctx, context, + conf_req_flag, qop_req, conf_state, + iov, iov_count); + + return GSS_S_FAILURE; } diff --git a/source4/heimdal/lib/gssapi/krb5/arcfour.c b/source4/heimdal/lib/gssapi/krb5/arcfour.c index b48cfebcf1..e7331b0119 100644 --- a/source4/heimdal/lib/gssapi/krb5/arcfour.c +++ b/source4/heimdal/lib/gssapi/krb5/arcfour.c @@ -33,8 +33,6 @@ #include "gsskrb5_locl.h" -RCSID("$Id$"); - /* * Implements draft-brezak-win2k-krb-rc4-hmac-04.txt * diff --git a/source4/heimdal/lib/gssapi/krb5/canonicalize_name.c b/source4/heimdal/lib/gssapi/krb5/canonicalize_name.c index 3a206b1be1..7e0c3fe727 100644 --- a/source4/heimdal/lib/gssapi/krb5/canonicalize_name.c +++ b/source4/heimdal/lib/gssapi/krb5/canonicalize_name.c @@ -33,8 +33,6 @@ #include "gsskrb5_locl.h" -RCSID("$Id$"); - OM_uint32 _gsskrb5_canonicalize_name ( OM_uint32 * minor_status, const gss_name_t input_name, diff --git a/source4/heimdal/lib/gssapi/krb5/cfx.c b/source4/heimdal/lib/gssapi/krb5/cfx.c index 7ae26e2e7a..35e5a9e45a 100755 --- a/source4/heimdal/lib/gssapi/krb5/cfx.c +++ b/source4/heimdal/lib/gssapi/krb5/cfx.c @@ -32,10 +32,8 @@ #include "gsskrb5_locl.h" -RCSID("$Id$"); - /* - * Implementation of draft-ietf-krb-wg-gssapi-cfx-06.txt + * Implementation of RFC 4121 */ #define CFXSentByAcceptor (1 << 0) @@ -101,13 +99,14 @@ _gsskrb5cfx_wrap_length_cfx(const gsskrb5_ctx context_handle, return 0; } -OM_uint32 _gssapi_wrap_size_cfx(OM_uint32 *minor_status, - const gsskrb5_ctx ctx, - krb5_context context, - int conf_req_flag, - gss_qop_t qop_req, - OM_uint32 req_output_size, - OM_uint32 *max_input_size) +OM_uint32 +_gssapi_wrap_size_cfx(OM_uint32 *minor_status, + const gsskrb5_ctx ctx, + krb5_context context, + int conf_req_flag, + gss_qop_t qop_req, + OM_uint32 req_output_size, + OM_uint32 *max_input_size) { krb5_error_code ret; @@ -203,11 +202,763 @@ rrc_rotate(void *data, size_t len, uint16_t rrc, krb5_boolean unrotate) return 0; } +gss_iov_buffer_desc * +_gk_find_buffer(gss_iov_buffer_desc *iov, int iov_count, OM_uint32 type) +{ + int i; + + for (i = 0; i < iov_count; i++) + if (type == GSS_IOV_BUFFER_TYPE(iov[i].type)) + return &iov[i]; + return NULL; +} + +static OM_uint32 +allocate_buffer(OM_uint32 *minor_status, gss_iov_buffer_desc *buffer, size_t size) +{ + if (buffer->type & GSS_IOV_BUFFER_TYPE_FLAG_ALLOCATED) { + if (buffer->buffer.length == size) + return GSS_S_COMPLETE; + free(buffer->buffer.value); + } + + buffer->buffer.value = malloc(size); + buffer->buffer.length = size; + if (buffer->buffer.value == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + buffer->type |= GSS_IOV_BUFFER_TYPE_FLAG_ALLOCATED; + + return GSS_S_COMPLETE; +} + + + +OM_uint32 +_gssapi_wrap_cfx_iov(OM_uint32 *minor_status, + gsskrb5_ctx ctx, + krb5_context context, + int conf_req_flag, + int *conf_state, + gss_iov_buffer_desc *iov, + int iov_count) +{ + OM_uint32 major_status, junk; + gss_iov_buffer_desc *header, *trailer, *padding; + size_t gsshsize, k5hsize; + size_t gsstsize, k5tsize; + size_t i, padlength, rrc = 0, ec = 0; + gss_cfx_wrap_token token; + krb5_error_code ret; + int32_t seq_number; + unsigned usage; + krb5_crypto_iov *data = NULL; + int paddingoffset = 0; + + header = _gk_find_buffer(iov, iov_count, GSS_IOV_BUFFER_TYPE_HEADER); + if (header == NULL) { + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + + krb5_crypto_length(context, ctx->crypto, KRB5_CRYPTO_TYPE_PADDING, &padlength); + + padding = _gk_find_buffer(iov, iov_count, GSS_IOV_BUFFER_TYPE_PADDING); + if (padlength != 0 && padding == NULL) { + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + + trailer = _gk_find_buffer(iov, iov_count, GSS_IOV_BUFFER_TYPE_TRAILER); + + if (conf_req_flag) { + ec = padlength; + + krb5_crypto_length(context, ctx->crypto, KRB5_CRYPTO_TYPE_TRAILER, &k5tsize); + krb5_crypto_length(context, ctx->crypto, KRB5_CRYPTO_TYPE_HEADER, &k5hsize); + + gsshsize = k5hsize + sizeof(*token); + gsstsize = k5tsize + sizeof(*token); /* encrypted token stored in trailer */ + + } else { + + krb5_crypto_length(context, ctx->crypto, KRB5_CRYPTO_TYPE_CHECKSUM, &k5tsize); + + gsshsize = sizeof(*token); + gsstsize = k5tsize; + } + + /* + * + */ + + if (trailer == NULL) { + /* conf_req_flag=0 doesn't support DCE_STYLE */ + if (conf_req_flag == 0) { + *minor_status = EINVAL; + major_status = GSS_S_FAILURE; + goto failure; + } + rrc = gsstsize; + if (IS_DCE_STYLE(ctx)) + rrc -= ec; + gsshsize += gsstsize; + gsstsize = 0; + } else if (GSS_IOV_BUFFER_FLAGS(trailer->type) & GSS_IOV_BUFFER_TYPE_FLAG_ALLOCATE) { + major_status = allocate_buffer(minor_status, trailer, gsstsize); + if (major_status) + goto failure; + } else if (trailer->buffer.length < gsstsize) { + *minor_status = KRB5_BAD_MSIZE; + major_status = GSS_S_FAILURE; + goto failure; + } else + trailer->buffer.length = gsstsize; + + /* + * + */ + + if (GSS_IOV_BUFFER_FLAGS(header->type) & GSS_IOV_BUFFER_TYPE_FLAG_ALLOCATE) { + major_status = allocate_buffer(minor_status, header, gsshsize); + if (major_status != GSS_S_COMPLETE) + goto failure; + } else if (header->buffer.length < gsshsize) { + *minor_status = KRB5_BAD_MSIZE; + major_status = GSS_S_FAILURE; + goto failure; + } else + header->buffer.length = gsshsize; + + token = (gss_cfx_wrap_token)header->buffer.value; + + token->TOK_ID[0] = 0x05; + token->TOK_ID[1] = 0x04; + token->Flags = 0; + token->Filler = 0xFF; + + if (ctx->more_flags & ACCEPTOR_SUBKEY) + token->Flags |= CFXAcceptorSubkey; + + if (ctx->more_flags & LOCAL) + usage = KRB5_KU_USAGE_INITIATOR_SEAL; + else + usage = KRB5_KU_USAGE_ACCEPTOR_SEAL; + + 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(&ctx->ctx_id_mutex); + krb5_auth_con_getlocalseqnumber(context, + ctx->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(context, + ctx->auth_context, + ++seq_number); + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + + data = calloc(iov_count + 3, sizeof(data[0])); + if (data == NULL) { + *minor_status = ENOMEM; + major_status = GSS_S_FAILURE; + goto failure; + } + + if (conf_req_flag) { + /* + plain packet: + + {"header" | encrypt(plaintext-data | padding | E"header")} + + Expanded, this is with with RRC = 0: + + {"header" | krb5-header | plaintext-data | padding | E"header" | krb5-trailer } + + In DCE-RPC mode == no trailer: RRC = gss "trailer" == length(padding | E"header" | krb5-trailer) + + {"header" | padding | E"header" | krb5-trailer | krb5-header | plaintext-data } + */ + + i = 0; + data[i].flags = KRB5_CRYPTO_TYPE_HEADER; + data[i].data.data = ((uint8_t *)header->buffer.value) + header->buffer.length - k5hsize; + data[i].data.length = k5hsize; + + for (i = 1; i < iov_count + 1; i++) { + switch (GSS_IOV_BUFFER_TYPE(iov[i - 1].type)) { + case GSS_IOV_BUFFER_TYPE_DATA: + data[i].flags = KRB5_CRYPTO_TYPE_DATA; + break; + case GSS_IOV_BUFFER_TYPE_PADDING: + data[i].flags = KRB5_CRYPTO_TYPE_PADDING; + paddingoffset = i; + break; + case GSS_IOV_BUFFER_TYPE_SIGN_ONLY: + data[i].flags = KRB5_CRYPTO_TYPE_SIGN_ONLY; + break; + default: + data[i].flags = KRB5_CRYPTO_TYPE_EMPTY; + break; + } + data[i].data.length = iov[i - 1].buffer.length; + data[i].data.data = iov[i - 1].buffer.value; + } + + /* + * Any necessary padding is added here to ensure that the + * encrypted token header is always at the end of the + * ciphertext. + */ + + /* XXX KRB5_CRYPTO_TYPE_PADDING */ + + /* encrypted CFX header in trailer (or after the header if in + DCE mode). Copy in header into E"header" + */ + data[i].flags = KRB5_CRYPTO_TYPE_DATA; + if (trailer) + data[i].data.data = trailer->buffer.value; + else + data[i].data.data = ((uint8_t *)header->buffer.value) + header->buffer.length - k5hsize - k5tsize - sizeof(*token); + + data[i].data.length = sizeof(*token); + memcpy(data[i].data.data, token, sizeof(*token)); + i++; + + /* Kerberos trailer comes after the gss trailer */ + data[i].flags = KRB5_CRYPTO_TYPE_TRAILER; + data[i].data.data = ((uint8_t *)data[i-1].data.data) + sizeof(*token); + data[i].data.length = k5tsize; + i++; + + ret = krb5_encrypt_iov_ivec(context, ctx->crypto, usage, data, i, NULL); + if (ret != 0) { + *minor_status = ret; + major_status = GSS_S_FAILURE; + goto failure; + } + + if (rrc) { + token->RRC[0] = (rrc >> 8) & 0xFF; + token->RRC[1] = (rrc >> 0) & 0xFF; + } + + if (paddingoffset) + padding->buffer.length = data[paddingoffset].data.length; + + } else { + /* + plain packet: + + {data | "header" | gss-trailer (krb5 checksum) + + don't do RRC != 0 + + */ + + for (i = 0; i < iov_count; i++) { + switch (GSS_IOV_BUFFER_TYPE(iov[i].type)) { + case GSS_IOV_BUFFER_TYPE_DATA: + case GSS_IOV_BUFFER_TYPE_PADDING: + data[i].flags = KRB5_CRYPTO_TYPE_DATA; + break; + case GSS_IOV_BUFFER_TYPE_SIGN_ONLY: + data[i].flags = KRB5_CRYPTO_TYPE_SIGN_ONLY; + break; + default: + data[i].flags = KRB5_CRYPTO_TYPE_EMPTY; + break; + } + data[i].data.length = iov[i].buffer.length; + data[i].data.data = iov[i].buffer.value; + } + + data[i].flags = KRB5_CRYPTO_TYPE_DATA; + data[i].data.data = header->buffer.value; + data[i].data.length = header->buffer.length; + i++; + + data[i].flags = KRB5_CRYPTO_TYPE_CHECKSUM; + data[i].data.data = trailer->buffer.value; + data[i].data.length = trailer->buffer.length; + i++; + + ret = krb5_create_checksum_iov(context, ctx->crypto, usage, data, i, NULL); + if (ret) { + *minor_status = ret; + major_status = GSS_S_FAILURE; + goto failure; + } + + token->EC[0] = (trailer->buffer.length >> 8) & 0xFF; + token->EC[1] = (trailer->buffer.length >> 0) & 0xFF; + } + + if (conf_state != NULL) + *conf_state = conf_req_flag; + + free(data); + + *minor_status = 0; + return GSS_S_COMPLETE; + + failure: + if (data) + free(data); + + gss_release_iov_buffer(&junk, iov, iov_count); + + return major_status; +} + +/* This is slowpath */ +static OM_uint32 +unrotate_iov(OM_uint32 *minor_status, size_t rrc, gss_iov_buffer_desc *iov, int iov_count) +{ + uint8_t *p, *q; + size_t len = 0, skip; + int i; + + for (i = 0; i < iov_count; i++) + if (GSS_IOV_BUFFER_TYPE(iov[i].type) == GSS_IOV_BUFFER_TYPE_DATA || + GSS_IOV_BUFFER_TYPE(iov[i].type) == GSS_IOV_BUFFER_TYPE_PADDING || + GSS_IOV_BUFFER_TYPE(iov[i].type) == GSS_IOV_BUFFER_TYPE_TRAILER) + len += iov[i].buffer.length; + + p = malloc(len); + if (p == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + q = p; + + /* copy up */ + + for (i = 0; i < iov_count; i++) { + if (GSS_IOV_BUFFER_TYPE(iov[i].type) == GSS_IOV_BUFFER_TYPE_DATA || + GSS_IOV_BUFFER_TYPE(iov[i].type) == GSS_IOV_BUFFER_TYPE_PADDING || + GSS_IOV_BUFFER_TYPE(iov[i].type) == GSS_IOV_BUFFER_TYPE_TRAILER) + { + memcpy(q, iov[i].buffer.value, iov[i].buffer.length); + q += iov[i].buffer.length; + } + } + assert((q - p) == len); + + /* unrotate first part */ + q = p + rrc; + skip = rrc; + for (i = 0; i < iov_count; i++) { + if (GSS_IOV_BUFFER_TYPE(iov[i].type) == GSS_IOV_BUFFER_TYPE_DATA || + GSS_IOV_BUFFER_TYPE(iov[i].type) == GSS_IOV_BUFFER_TYPE_PADDING || + GSS_IOV_BUFFER_TYPE(iov[i].type) == GSS_IOV_BUFFER_TYPE_TRAILER) + { + if (iov[i].buffer.length <= skip) { + skip -= iov[i].buffer.length; + } else { + memcpy(((uint8_t *)iov[i].buffer.value) + skip, q, iov[i].buffer.length - skip); + q += iov[i].buffer.length - skip; + skip = 0; + } + } + } + /* copy trailer */ + q = p; + skip = rrc; + for (i = 0; i < iov_count; i++) { + if (GSS_IOV_BUFFER_TYPE(iov[i].type) == GSS_IOV_BUFFER_TYPE_DATA || + GSS_IOV_BUFFER_TYPE(iov[i].type) == GSS_IOV_BUFFER_TYPE_PADDING || + GSS_IOV_BUFFER_TYPE(iov[i].type) == GSS_IOV_BUFFER_TYPE_TRAILER) + { + memcpy(q, iov[i].buffer.value, MIN(iov[i].buffer.length, skip)); + if (iov[i].buffer.length > skip) + break; + skip -= iov[i].buffer.length; + q += iov[i].buffer.length; + } + } + return GSS_S_COMPLETE; +} + + +OM_uint32 +_gssapi_unwrap_cfx_iov(OM_uint32 *minor_status, + gsskrb5_ctx ctx, + krb5_context context, + int *conf_state, + gss_qop_t *qop_state, + gss_iov_buffer_desc *iov, + int iov_count) +{ + OM_uint32 seq_number_lo, seq_number_hi, major_status, junk; + gss_iov_buffer_desc *header, *trailer; + gss_cfx_wrap_token token, ttoken; + u_char token_flags; + krb5_error_code ret; + unsigned usage; + uint16_t ec, rrc; + krb5_crypto_iov *data = NULL; + int i, j; + + *minor_status = 0; + + header = _gk_find_buffer(iov, iov_count, GSS_IOV_BUFFER_TYPE_HEADER); + if (header == NULL) { + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + + if (header->buffer.length < sizeof(*token)) /* we check exact below */ + return GSS_S_DEFECTIVE_TOKEN; + + trailer = _gk_find_buffer(iov, iov_count, GSS_IOV_BUFFER_TYPE_TRAILER); + + token = (gss_cfx_wrap_token)header->buffer.value; + + 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 ((ctx->more_flags & LOCAL) == 0) + return GSS_S_DEFECTIVE_TOKEN; + } + + if (ctx->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(&ctx->ctx_id_mutex); + ret = _gssapi_msg_order_check(ctx->order, seq_number_lo); + if (ret != 0) { + *minor_status = 0; + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + return ret; + } + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + + /* + * Decrypt and/or verify checksum + */ + + if (ctx->more_flags & LOCAL) { + usage = KRB5_KU_USAGE_ACCEPTOR_SEAL; + } else { + usage = KRB5_KU_USAGE_INITIATOR_SEAL; + } + + data = calloc(iov_count + 3, sizeof(data[0])); + if (data == NULL) { + *minor_status = ENOMEM; + major_status = GSS_S_FAILURE; + goto failure; + } + + if (token_flags & CFXSealed) { + size_t k5tsize, k5hsize; + + krb5_crypto_length(context, ctx->crypto, KRB5_CRYPTO_TYPE_HEADER, &k5hsize); + krb5_crypto_length(context, ctx->crypto, KRB5_CRYPTO_TYPE_TRAILER, &k5tsize); + + /* Rotate by RRC; bogus to do this in-place XXX */ + /* Check RRC */ + + if (trailer == NULL) { + size_t gsstsize = k5tsize + sizeof(*token); + size_t gsshsize = k5hsize + sizeof(*token); + + if (IS_DCE_STYLE(ctx)) + gsstsize += ec; + gsshsize += gsstsize; + + if (rrc != gsstsize) { + major_status = GSS_S_DEFECTIVE_TOKEN; + goto failure; + } + if (header->buffer.length != gsshsize) { + major_status = GSS_S_DEFECTIVE_TOKEN; + goto failure; + } + } else if (trailer->buffer.length != sizeof(*token) + k5tsize) { + major_status = GSS_S_DEFECTIVE_TOKEN; + goto failure; + } else if (header->buffer.length != sizeof(*token) + k5hsize) { + major_status = GSS_S_DEFECTIVE_TOKEN; + goto failure; + } else if (rrc != 0) { + /* go though slowpath */ + major_status = unrotate_iov(minor_status, rrc, iov, iov_count); + if (major_status) + goto failure; + } + + i = 0; + data[i].flags = KRB5_CRYPTO_TYPE_HEADER; + data[i].data.data = ((uint8_t *)header->buffer.value) + header->buffer.length - k5hsize; + data[i].data.length = k5hsize; + i++; + + for (j = 0; j < iov_count; i++, j++) { + switch (GSS_IOV_BUFFER_TYPE(iov[j].type)) { + case GSS_IOV_BUFFER_TYPE_DATA: + case GSS_IOV_BUFFER_TYPE_PADDING: + data[i].flags = KRB5_CRYPTO_TYPE_DATA; + break; + case GSS_IOV_BUFFER_TYPE_SIGN_ONLY: + data[i].flags = KRB5_CRYPTO_TYPE_SIGN_ONLY; + break; + default: + data[i].flags = KRB5_CRYPTO_TYPE_EMPTY; + break; + } + data[i].data.length = iov[j].buffer.length; + data[i].data.data = iov[j].buffer.value; + } + + /* encrypted CFX header in trailer (or after the header if in + DCE mode). Copy in header into E"header" + */ + data[i].flags = KRB5_CRYPTO_TYPE_DATA; + if (trailer) + data[i].data.data = trailer->buffer.value; + else + data[i].data.data = ((uint8_t *)header->buffer.value) + header->buffer.length - k5hsize - k5tsize - sizeof(*token); + data[i].data.length = sizeof(*token); + ttoken = (gss_cfx_wrap_token)data[i].data.data; + i++; + + /* Kerberos trailer comes after the gss trailer */ + data[i].flags = KRB5_CRYPTO_TYPE_TRAILER; + data[i].data.data = ((uint8_t *)data[i-1].data.data) + sizeof(*token); + data[i].data.length = k5tsize; + i++; + + ret = krb5_decrypt_iov_ivec(context, ctx->crypto, usage, data, i, NULL); + if (ret != 0) { + *minor_status = ret; + major_status = GSS_S_FAILURE; + goto failure; + } + + ttoken->RRC[0] = token->RRC[0]; + ttoken->RRC[1] = token->RRC[1]; + + /* Check the integrity of the header */ + if (memcmp(ttoken, token, sizeof(*token)) != 0) { + major_status = GSS_S_BAD_MIC; + goto failure; + } + } else { + /* Check RRC */ + if (rrc != 0) { + *minor_status = EINVAL; + major_status = GSS_S_FAILURE; + goto failure; + } + + if (trailer == NULL) { + *minor_status = EINVAL; + major_status = GSS_S_FAILURE; + goto failure; + } + + if (trailer->buffer.length != ec) { + *minor_status = EINVAL; + major_status = GSS_S_FAILURE; + goto failure; + } + + for (i = 0; i < iov_count; i++) { + switch (GSS_IOV_BUFFER_TYPE(iov[i].type)) { + case GSS_IOV_BUFFER_TYPE_DATA: + case GSS_IOV_BUFFER_TYPE_PADDING: + data[i].flags = KRB5_CRYPTO_TYPE_DATA; + break; + case GSS_IOV_BUFFER_TYPE_SIGN_ONLY: + data[i].flags = KRB5_CRYPTO_TYPE_SIGN_ONLY; + break; + default: + data[i].flags = KRB5_CRYPTO_TYPE_EMPTY; + break; + } + data[i].data.length = iov[i].buffer.length; + data[i].data.data = iov[i].buffer.value; + } + + data[i].flags = KRB5_CRYPTO_TYPE_DATA; + data[i].data.data = header->buffer.value; + data[i].data.length = header->buffer.length; + i++; + + data[i].flags = KRB5_CRYPTO_TYPE_CHECKSUM; + data[i].data.data = trailer->buffer.value; + data[i].data.length = trailer->buffer.length; + i++; + + token = (gss_cfx_wrap_token)header->buffer.value; + token->EC[0] = 0; + token->EC[1] = 0; + token->RRC[0] = 0; + token->RRC[1] = 0; + + ret = krb5_verify_checksum_iov(context, ctx->crypto, usage, data, i, NULL); + if (ret) { + *minor_status = ret; + major_status = GSS_S_FAILURE; + goto failure; + } + } + + if (qop_state != NULL) { + *qop_state = GSS_C_QOP_DEFAULT; + } + + free(data); + + *minor_status = 0; + return GSS_S_COMPLETE; + + failure: + if (data) + free(data); + + gss_release_iov_buffer(&junk, iov, iov_count); + + return major_status; +} + +OM_uint32 +_gssapi_wrap_iov_length_cfx(OM_uint32 *minor_status, + gsskrb5_ctx ctx, + krb5_context context, + int conf_req_flag, + gss_qop_t qop_req, + int *conf_state, + gss_iov_buffer_desc *iov, + int iov_count) +{ + size_t size; + int i; + size_t *padding = NULL; + + GSSAPI_KRB5_INIT (&context); + *minor_status = 0; + + for (size = 0, i = 0; i < iov_count; i++) { + switch(GSS_IOV_BUFFER_TYPE(iov[i].type)) { + case GSS_IOV_BUFFER_TYPE_EMPTY: + break; + case GSS_IOV_BUFFER_TYPE_DATA: + size += iov[i].buffer.length; + break; + case GSS_IOV_BUFFER_TYPE_HEADER: + *minor_status = krb5_crypto_length(context, ctx->crypto, KRB5_CRYPTO_TYPE_HEADER, &iov[i].buffer.length); + if (*minor_status) + return GSS_S_FAILURE; + break; + case GSS_IOV_BUFFER_TYPE_TRAILER: + *minor_status = krb5_crypto_length(context, ctx->crypto, KRB5_CRYPTO_TYPE_TRAILER, &iov[i].buffer.length); + if (*minor_status) + return GSS_S_FAILURE; + break; + case GSS_IOV_BUFFER_TYPE_PADDING: + if (padding != NULL) { + *minor_status = 0; + return GSS_S_FAILURE; + } + padding = &iov[i].buffer.length; + break; + case GSS_IOV_BUFFER_TYPE_SIGN_ONLY: + break; + default: + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + } + if (padding) { + size_t pad; + krb5_crypto_length(context, ctx->crypto, KRB5_CRYPTO_TYPE_PADDING, &pad); + if (pad > 1) { + *padding = pad - (size % pad); + if (*padding == pad) + *padding = 0; + } else + *padding = 0; + } + + return GSS_S_COMPLETE; +} + + + + OM_uint32 _gssapi_wrap_cfx(OM_uint32 *minor_status, const gsskrb5_ctx ctx, krb5_context context, int conf_req_flag, - gss_qop_t qop_req, const gss_buffer_t input_message_buffer, int *conf_state, gss_buffer_t output_message_buffer) diff --git a/source4/heimdal/lib/gssapi/krb5/compare_name.c b/source4/heimdal/lib/gssapi/krb5/compare_name.c index fbb0f0218e..f45e4df3e2 100644 --- a/source4/heimdal/lib/gssapi/krb5/compare_name.c +++ b/source4/heimdal/lib/gssapi/krb5/compare_name.c @@ -33,8 +33,6 @@ #include "gsskrb5_locl.h" -RCSID("$Id$"); - OM_uint32 _gsskrb5_compare_name (OM_uint32 * minor_status, const gss_name_t name1, diff --git a/source4/heimdal/lib/gssapi/krb5/compat.c b/source4/heimdal/lib/gssapi/krb5/compat.c index 012602c074..221d219c69 100644 --- a/source4/heimdal/lib/gssapi/krb5/compat.c +++ b/source4/heimdal/lib/gssapi/krb5/compat.c @@ -33,9 +33,6 @@ #include "gsskrb5_locl.h" -RCSID("$Id$"); - - static krb5_error_code check_compat(OM_uint32 *minor_status, krb5_context context, krb5_const_principal name, diff --git a/source4/heimdal/lib/gssapi/krb5/context_time.c b/source4/heimdal/lib/gssapi/krb5/context_time.c index 3230389938..987ceea4aa 100644 --- a/source4/heimdal/lib/gssapi/krb5/context_time.c +++ b/source4/heimdal/lib/gssapi/krb5/context_time.c @@ -33,8 +33,6 @@ #include "gsskrb5_locl.h" -RCSID("$Id$"); - OM_uint32 _gsskrb5_lifetime_left(OM_uint32 *minor_status, krb5_context context, diff --git a/source4/heimdal/lib/gssapi/krb5/copy_ccache.c b/source4/heimdal/lib/gssapi/krb5/copy_ccache.c index 40a8fab1b7..a4b28f91ed 100644 --- a/source4/heimdal/lib/gssapi/krb5/copy_ccache.c +++ b/source4/heimdal/lib/gssapi/krb5/copy_ccache.c @@ -33,8 +33,6 @@ #include "gsskrb5_locl.h" -RCSID("$Id$"); - #if 0 OM_uint32 gss_krb5_copy_ccache(OM_uint32 *minor_status, diff --git a/source4/heimdal/lib/gssapi/krb5/decapsulate.c b/source4/heimdal/lib/gssapi/krb5/decapsulate.c index a2a5de9fe7..7ccf0b0f79 100644 --- a/source4/heimdal/lib/gssapi/krb5/decapsulate.c +++ b/source4/heimdal/lib/gssapi/krb5/decapsulate.c @@ -33,8 +33,6 @@ #include "gsskrb5_locl.h" -RCSID("$Id$"); - /* * return the length of the mechanism in token or -1 * (which implies that the token was bad - GSS_S_DEFECTIVE_TOKEN diff --git a/source4/heimdal/lib/gssapi/krb5/delete_sec_context.c b/source4/heimdal/lib/gssapi/krb5/delete_sec_context.c index ea0831815a..b3d436ea01 100644 --- a/source4/heimdal/lib/gssapi/krb5/delete_sec_context.c +++ b/source4/heimdal/lib/gssapi/krb5/delete_sec_context.c @@ -33,8 +33,6 @@ #include "gsskrb5_locl.h" -RCSID("$Id$"); - OM_uint32 _gsskrb5_delete_sec_context(OM_uint32 * minor_status, gss_ctx_id_t * context_handle, diff --git a/source4/heimdal/lib/gssapi/krb5/display_name.c b/source4/heimdal/lib/gssapi/krb5/display_name.c index 0b37731510..6487d84880 100644 --- a/source4/heimdal/lib/gssapi/krb5/display_name.c +++ b/source4/heimdal/lib/gssapi/krb5/display_name.c @@ -33,8 +33,6 @@ #include "gsskrb5_locl.h" -RCSID("$Id$"); - OM_uint32 _gsskrb5_display_name (OM_uint32 * minor_status, const gss_name_t input_name, diff --git a/source4/heimdal/lib/gssapi/krb5/display_status.c b/source4/heimdal/lib/gssapi/krb5/display_status.c index 4136c25e53..f9d84fc762 100644 --- a/source4/heimdal/lib/gssapi/krb5/display_status.c +++ b/source4/heimdal/lib/gssapi/krb5/display_status.c @@ -33,8 +33,6 @@ #include "gsskrb5_locl.h" -RCSID("$Id$"); - static const char * calling_error(OM_uint32 v) { diff --git a/source4/heimdal/lib/gssapi/krb5/duplicate_name.c b/source4/heimdal/lib/gssapi/krb5/duplicate_name.c index 2b5e5c0ef4..b0188acd51 100644 --- a/source4/heimdal/lib/gssapi/krb5/duplicate_name.c +++ b/source4/heimdal/lib/gssapi/krb5/duplicate_name.c @@ -33,8 +33,6 @@ #include "gsskrb5_locl.h" -RCSID("$Id$"); - OM_uint32 _gsskrb5_duplicate_name ( OM_uint32 * minor_status, const gss_name_t src_name, diff --git a/source4/heimdal/lib/gssapi/krb5/encapsulate.c b/source4/heimdal/lib/gssapi/krb5/encapsulate.c index 838a34d7db..79cd9232e1 100644 --- a/source4/heimdal/lib/gssapi/krb5/encapsulate.c +++ b/source4/heimdal/lib/gssapi/krb5/encapsulate.c @@ -33,8 +33,6 @@ #include "gsskrb5_locl.h" -RCSID("$Id$"); - void _gssapi_encap_length (size_t data_len, size_t *len, diff --git a/source4/heimdal/lib/gssapi/krb5/export_name.c b/source4/heimdal/lib/gssapi/krb5/export_name.c index bad73611dc..705bb70d91 100644 --- a/source4/heimdal/lib/gssapi/krb5/export_name.c +++ b/source4/heimdal/lib/gssapi/krb5/export_name.c @@ -33,8 +33,6 @@ #include "gsskrb5_locl.h" -RCSID("$Id$"); - OM_uint32 _gsskrb5_export_name (OM_uint32 * minor_status, const gss_name_t input_name, diff --git a/source4/heimdal/lib/gssapi/krb5/export_sec_context.c b/source4/heimdal/lib/gssapi/krb5/export_sec_context.c index 305d5c334e..3d3870a6b4 100644 --- a/source4/heimdal/lib/gssapi/krb5/export_sec_context.c +++ b/source4/heimdal/lib/gssapi/krb5/export_sec_context.c @@ -33,8 +33,6 @@ #include "gsskrb5_locl.h" -RCSID("$Id$"); - OM_uint32 _gsskrb5_export_sec_context ( OM_uint32 * minor_status, diff --git a/source4/heimdal/lib/gssapi/krb5/external.c b/source4/heimdal/lib/gssapi/krb5/external.c index 1c28f7c141..df23776a63 100644 --- a/source4/heimdal/lib/gssapi/krb5/external.c +++ b/source4/heimdal/lib/gssapi/krb5/external.c @@ -34,8 +34,6 @@ #include "gsskrb5_locl.h" #include <gssapi_mech.h> -RCSID("$Id$"); - /* * The implementation must reserve static storage for a * gss_OID_desc object containing the value diff --git a/source4/heimdal/lib/gssapi/krb5/get_mic.c b/source4/heimdal/lib/gssapi/krb5/get_mic.c index 66aaba44d6..ad3009c73e 100644 --- a/source4/heimdal/lib/gssapi/krb5/get_mic.c +++ b/source4/heimdal/lib/gssapi/krb5/get_mic.c @@ -33,8 +33,6 @@ #include "gsskrb5_locl.h" -RCSID("$Id$"); - static OM_uint32 mic_des (OM_uint32 * minor_status, diff --git a/source4/heimdal/lib/gssapi/krb5/import_name.c b/source4/heimdal/lib/gssapi/krb5/import_name.c index 8f5387fe2b..d488ce754b 100644 --- a/source4/heimdal/lib/gssapi/krb5/import_name.c +++ b/source4/heimdal/lib/gssapi/krb5/import_name.c @@ -33,8 +33,6 @@ #include "gsskrb5_locl.h" -RCSID("$Id$"); - static OM_uint32 parse_krb5_name (OM_uint32 *minor_status, krb5_context context, diff --git a/source4/heimdal/lib/gssapi/krb5/import_sec_context.c b/source4/heimdal/lib/gssapi/krb5/import_sec_context.c index ba1a977d2d..2af942338f 100644 --- a/source4/heimdal/lib/gssapi/krb5/import_sec_context.c +++ b/source4/heimdal/lib/gssapi/krb5/import_sec_context.c @@ -33,8 +33,6 @@ #include "gsskrb5_locl.h" -RCSID("$Id$"); - OM_uint32 _gsskrb5_import_sec_context ( OM_uint32 * minor_status, diff --git a/source4/heimdal/lib/gssapi/krb5/indicate_mechs.c b/source4/heimdal/lib/gssapi/krb5/indicate_mechs.c index 3702106e79..b1d18bd244 100644 --- a/source4/heimdal/lib/gssapi/krb5/indicate_mechs.c +++ b/source4/heimdal/lib/gssapi/krb5/indicate_mechs.c @@ -33,8 +33,6 @@ #include "gsskrb5_locl.h" -RCSID("$Id$"); - OM_uint32 _gsskrb5_indicate_mechs (OM_uint32 * minor_status, gss_OID_set * mech_set diff --git a/source4/heimdal/lib/gssapi/krb5/init.c b/source4/heimdal/lib/gssapi/krb5/init.c index b28e6a4c12..3a22c33ed6 100644 --- a/source4/heimdal/lib/gssapi/krb5/init.c +++ b/source4/heimdal/lib/gssapi/krb5/init.c @@ -33,8 +33,6 @@ #include "gsskrb5_locl.h" -RCSID("$Id$"); - static HEIMDAL_MUTEX context_mutex = HEIMDAL_MUTEX_INITIALIZER; static int created_key; static HEIMDAL_thread_key context_key; diff --git a/source4/heimdal/lib/gssapi/krb5/init_sec_context.c b/source4/heimdal/lib/gssapi/krb5/init_sec_context.c index 4b632bd95a..35ab9dd88d 100644 --- a/source4/heimdal/lib/gssapi/krb5/init_sec_context.c +++ b/source4/heimdal/lib/gssapi/krb5/init_sec_context.c @@ -33,8 +33,6 @@ #include "gsskrb5_locl.h" -RCSID("$Id$"); - /* * copy the addresses from `input_chan_bindings' (if any) to * the auth context `ac' @@ -697,7 +695,7 @@ repl_mutual if (actual_mech_type) *actual_mech_type = GSS_KRB5_MECHANISM; - if (ctx->flags & GSS_C_DCE_STYLE) { + if (IS_DCE_STYLE(ctx)) { /* There is no OID wrapping. */ indata.length = input_token->length; indata.data = input_token->value; diff --git a/source4/heimdal/lib/gssapi/krb5/inquire_context.c b/source4/heimdal/lib/gssapi/krb5/inquire_context.c index 188a6135a4..381ffc9e6f 100644 --- a/source4/heimdal/lib/gssapi/krb5/inquire_context.c +++ b/source4/heimdal/lib/gssapi/krb5/inquire_context.c @@ -33,8 +33,6 @@ #include "gsskrb5_locl.h" -RCSID("$Id$"); - OM_uint32 _gsskrb5_inquire_context ( OM_uint32 * minor_status, const gss_ctx_id_t context_handle, diff --git a/source4/heimdal/lib/gssapi/krb5/inquire_cred.c b/source4/heimdal/lib/gssapi/krb5/inquire_cred.c index 27e3014923..518736d78e 100644 --- a/source4/heimdal/lib/gssapi/krb5/inquire_cred.c +++ b/source4/heimdal/lib/gssapi/krb5/inquire_cred.c @@ -33,8 +33,6 @@ #include "gsskrb5_locl.h" -RCSID("$Id$"); - OM_uint32 _gsskrb5_inquire_cred (OM_uint32 * minor_status, const gss_cred_id_t cred_handle, diff --git a/source4/heimdal/lib/gssapi/krb5/inquire_cred_by_mech.c b/source4/heimdal/lib/gssapi/krb5/inquire_cred_by_mech.c index 1fd9733940..9da1ac43f1 100644 --- a/source4/heimdal/lib/gssapi/krb5/inquire_cred_by_mech.c +++ b/source4/heimdal/lib/gssapi/krb5/inquire_cred_by_mech.c @@ -33,8 +33,6 @@ #include "gsskrb5_locl.h" -RCSID("$Id$"); - OM_uint32 _gsskrb5_inquire_cred_by_mech ( OM_uint32 * minor_status, const gss_cred_id_t cred_handle, diff --git a/source4/heimdal/lib/gssapi/krb5/inquire_cred_by_oid.c b/source4/heimdal/lib/gssapi/krb5/inquire_cred_by_oid.c index 5a35202a6a..f32342f1d8 100644 --- a/source4/heimdal/lib/gssapi/krb5/inquire_cred_by_oid.c +++ b/source4/heimdal/lib/gssapi/krb5/inquire_cred_by_oid.c @@ -32,8 +32,6 @@ #include "gsskrb5_locl.h" -RCSID("$Id$"); - OM_uint32 _gsskrb5_inquire_cred_by_oid (OM_uint32 * minor_status, const gss_cred_id_t cred_handle, diff --git a/source4/heimdal/lib/gssapi/krb5/inquire_mechs_for_name.c b/source4/heimdal/lib/gssapi/krb5/inquire_mechs_for_name.c index 5d54bd6508..5fa3c302a2 100644 --- a/source4/heimdal/lib/gssapi/krb5/inquire_mechs_for_name.c +++ b/source4/heimdal/lib/gssapi/krb5/inquire_mechs_for_name.c @@ -33,8 +33,6 @@ #include "gsskrb5_locl.h" -RCSID("$Id$"); - OM_uint32 _gsskrb5_inquire_mechs_for_name ( OM_uint32 * minor_status, const gss_name_t input_name, diff --git a/source4/heimdal/lib/gssapi/krb5/inquire_names_for_mech.c b/source4/heimdal/lib/gssapi/krb5/inquire_names_for_mech.c index 9eba7b7f4d..591343307e 100644 --- a/source4/heimdal/lib/gssapi/krb5/inquire_names_for_mech.c +++ b/source4/heimdal/lib/gssapi/krb5/inquire_names_for_mech.c @@ -33,9 +33,6 @@ #include "gsskrb5_locl.h" -RCSID("$Id$"); - - static gss_OID *name_list[] = { &GSS_C_NT_HOSTBASED_SERVICE, &GSS_C_NT_USER_NAME, 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 index f8ef2a3aa4..ce01e666fa 100644 --- a/source4/heimdal/lib/gssapi/krb5/inquire_sec_context_by_oid.c +++ b/source4/heimdal/lib/gssapi/krb5/inquire_sec_context_by_oid.c @@ -32,8 +32,6 @@ #include "gsskrb5_locl.h" -RCSID("$Id$"); - static int oid_prefix_equal(gss_OID oid_enc, gss_OID prefix_enc, unsigned *suffix) { diff --git a/source4/heimdal/lib/gssapi/krb5/prf.c b/source4/heimdal/lib/gssapi/krb5/prf.c index 9fd13f51bd..76ae3b78ed 100644 --- a/source4/heimdal/lib/gssapi/krb5/prf.c +++ b/source4/heimdal/lib/gssapi/krb5/prf.c @@ -33,8 +33,6 @@ #include "gsskrb5_locl.h" -RCSID("$Id$"); - OM_uint32 _gsskrb5_pseudo_random(OM_uint32 *minor_status, gss_ctx_id_t context_handle, diff --git a/source4/heimdal/lib/gssapi/krb5/process_context_token.c b/source4/heimdal/lib/gssapi/krb5/process_context_token.c index 3229b36292..1c9d44588f 100644 --- a/source4/heimdal/lib/gssapi/krb5/process_context_token.c +++ b/source4/heimdal/lib/gssapi/krb5/process_context_token.c @@ -33,8 +33,6 @@ #include "gsskrb5_locl.h" -RCSID("$Id$"); - OM_uint32 _gsskrb5_process_context_token ( OM_uint32 *minor_status, const gss_ctx_id_t context_handle, diff --git a/source4/heimdal/lib/gssapi/krb5/release_buffer.c b/source4/heimdal/lib/gssapi/krb5/release_buffer.c index 18e0279939..b704e001eb 100644 --- a/source4/heimdal/lib/gssapi/krb5/release_buffer.c +++ b/source4/heimdal/lib/gssapi/krb5/release_buffer.c @@ -33,8 +33,6 @@ #include "gsskrb5_locl.h" -RCSID("$Id$"); - OM_uint32 _gsskrb5_release_buffer (OM_uint32 * minor_status, gss_buffer_t buffer diff --git a/source4/heimdal/lib/gssapi/krb5/release_cred.c b/source4/heimdal/lib/gssapi/krb5/release_cred.c index 62674a1d53..5eec3c48cb 100644 --- a/source4/heimdal/lib/gssapi/krb5/release_cred.c +++ b/source4/heimdal/lib/gssapi/krb5/release_cred.c @@ -33,8 +33,6 @@ #include "gsskrb5_locl.h" -RCSID("$Id$"); - OM_uint32 _gsskrb5_release_cred (OM_uint32 * minor_status, gss_cred_id_t * cred_handle diff --git a/source4/heimdal/lib/gssapi/krb5/release_name.c b/source4/heimdal/lib/gssapi/krb5/release_name.c index 5491052c59..0fafc275d0 100644 --- a/source4/heimdal/lib/gssapi/krb5/release_name.c +++ b/source4/heimdal/lib/gssapi/krb5/release_name.c @@ -33,8 +33,6 @@ #include "gsskrb5_locl.h" -RCSID("$Id$"); - OM_uint32 _gsskrb5_release_name (OM_uint32 * minor_status, gss_name_t * input_name diff --git a/source4/heimdal/lib/gssapi/krb5/sequence.c b/source4/heimdal/lib/gssapi/krb5/sequence.c index 6391d44429..fbbc5b6c70 100644 --- a/source4/heimdal/lib/gssapi/krb5/sequence.c +++ b/source4/heimdal/lib/gssapi/krb5/sequence.c @@ -33,8 +33,6 @@ #include "gsskrb5_locl.h" -RCSID("$Id$"); - #define DEFAULT_JITTER_WINDOW 20 struct gss_msg_order { diff --git a/source4/heimdal/lib/gssapi/krb5/set_cred_option.c b/source4/heimdal/lib/gssapi/krb5/set_cred_option.c index 2a2390f8d1..15d7632e4c 100644 --- a/source4/heimdal/lib/gssapi/krb5/set_cred_option.c +++ b/source4/heimdal/lib/gssapi/krb5/set_cred_option.c @@ -32,8 +32,6 @@ #include "gsskrb5_locl.h" -RCSID("$Id$"); - /* 1.2.752.43.13.17 */ static gss_OID_desc gss_krb5_cred_no_ci_flags_x_oid_desc = {6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x11")}; diff --git a/source4/heimdal/lib/gssapi/krb5/set_sec_context_option.c b/source4/heimdal/lib/gssapi/krb5/set_sec_context_option.c index 460cfe942a..096e835045 100644 --- a/source4/heimdal/lib/gssapi/krb5/set_sec_context_option.c +++ b/source4/heimdal/lib/gssapi/krb5/set_sec_context_option.c @@ -36,8 +36,6 @@ #include "gsskrb5_locl.h" -RCSID("$Id$"); - static OM_uint32 get_bool(OM_uint32 *minor_status, const gss_buffer_t value, diff --git a/source4/heimdal/lib/gssapi/krb5/unwrap.c b/source4/heimdal/lib/gssapi/krb5/unwrap.c index 0e87cb88b7..20cf952b4e 100644 --- a/source4/heimdal/lib/gssapi/krb5/unwrap.c +++ b/source4/heimdal/lib/gssapi/krb5/unwrap.c @@ -33,8 +33,6 @@ #include "gsskrb5_locl.h" -RCSID("$Id$"); - static OM_uint32 unwrap_des (OM_uint32 * minor_status, diff --git a/source4/heimdal/lib/gssapi/krb5/verify_mic.c b/source4/heimdal/lib/gssapi/krb5/verify_mic.c index 6eb7ae4b08..c7e16e81f7 100644 --- a/source4/heimdal/lib/gssapi/krb5/verify_mic.c +++ b/source4/heimdal/lib/gssapi/krb5/verify_mic.c @@ -33,8 +33,6 @@ #include "gsskrb5_locl.h" -RCSID("$Id$"); - static OM_uint32 verify_mic_des (OM_uint32 * minor_status, diff --git a/source4/heimdal/lib/gssapi/krb5/wrap.c b/source4/heimdal/lib/gssapi/krb5/wrap.c index b9f4c237c7..3de13f908f 100644 --- a/source4/heimdal/lib/gssapi/krb5/wrap.c +++ b/source4/heimdal/lib/gssapi/krb5/wrap.c @@ -33,8 +33,6 @@ #include "gsskrb5_locl.h" -RCSID("$Id$"); - /* * Return initiator subkey, or if that doesn't exists, the subkey. */ @@ -540,7 +538,7 @@ OM_uint32 _gsskrb5_wrap if (ctx->more_flags & IS_CFX) return _gssapi_wrap_cfx (minor_status, ctx, context, conf_req_flag, - qop_req, input_message_buffer, conf_state, + input_message_buffer, conf_state, output_message_buffer); HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); diff --git a/source4/heimdal/lib/gssapi/mech/gss_acquire_cred.c b/source4/heimdal/lib/gssapi/mech/gss_acquire_cred.c index a8ebe644ab..b1bc7dd981 100644 --- a/source4/heimdal/lib/gssapi/mech/gss_acquire_cred.c +++ b/source4/heimdal/lib/gssapi/mech/gss_acquire_cred.c @@ -50,7 +50,7 @@ gss_acquire_cred(OM_uint32 *minor_status, int i; *minor_status = 0; - if (output_cred_handle) + if (output_cred_handle == NULL) return GSS_S_CALL_INACCESSIBLE_READ; if (actual_mechs) *actual_mechs = GSS_C_NO_OID_SET; diff --git a/source4/heimdal/lib/gssapi/mech/gss_aeap.c b/source4/heimdal/lib/gssapi/mech/gss_aeap.c index cbe0cd1460..9c784f42de 100644 --- a/source4/heimdal/lib/gssapi/mech/gss_aeap.c +++ b/source4/heimdal/lib/gssapi/mech/gss_aeap.c @@ -3,27 +3,39 @@ */ #include "mech_locl.h" -RCSID("$Id$"); /** * Encrypts or sign the data. * + * This is a more complicated version of gss_wrap(), it allows the + * caller to use AEAD data (signed header/trailer) and allow greater + * controll over where the encrypted data is placed. + * * The maximum packet size is gss_context_stream_sizes.max_msg_size. * - * The caller needs provide the folloing buffers: + * The caller needs provide the folloing buffers when using in conf_req_flag=1 mode: * * - HEADER (of size gss_context_stream_sizes.header) - * SIGN_ONLY (optional, zero or more) - * DATA - * SIGN_ONLY (optional, zero or more) - * PADDING (of size gss_context_stream_sizes.blocksize) + * { DATA or SIGN_ONLY } (optional, zero or more) + * PADDING (of size gss_context_stream_sizes.blocksize, if zero padding is zero, can be omitted) * TRAILER (of size gss_context_stream_sizes.trailer) * * - on DCE-RPC mode, the caller can skip PADDING and TRAILER if the - * DATA elements is padded to a block bountry. + * DATA elements is padded to a block bountry and header is of at + * least size gss_context_stream_sizes.header + gss_context_stream_sizes.trailer. + * + * HEADER, PADDING, TRAILER will be shrunken to the size required to transmit any of them too large. * * To generate gss_wrap() compatible packets, use: HEADER | DATA | PADDING | TRAILER * + * When used in conf_req_flag=0, + * + * - HEADER (of size gss_context_stream_sizes.header) + * { DATA or SIGN_ONLY } (optional, zero or more) + * PADDING (of size gss_context_stream_sizes.blocksize, if zero padding is zero, can be omitted) + * TRAILER (of size gss_context_stream_sizes.trailer) + * + * * The input sizes of HEADER, PADDING and TRAILER can be fetched using gss_wrap_iov_length() or * gss_context_query_attributes(). * @@ -65,6 +77,13 @@ gss_wrap_iov(OM_uint32 * minor_status, iov, iov_count); } +/** + * Decrypt or verifies the signature on the data. + * + * + * @ingroup gssapi + */ + OM_uint32 GSSAPI_LIB_FUNCTION gss_unwrap_iov(OM_uint32 *minor_status, gss_ctx_id_t context_handle, @@ -99,7 +118,18 @@ gss_unwrap_iov(OM_uint32 *minor_status, iov, iov_count); } -OM_uint32 GSSAPI_LIB_FUNCTION +/** + * Update the length fields in iov buffer for the types: + * - GSS_IOV_BUFFER_TYPE_HEADER + * - GSS_IOV_BUFFER_TYPE_PADDING + * - GSS_IOV_BUFFER_TYPE_TRAILER + * + * Consider using gss_context_query_attributes() to fetch the data instead. + * + * @ingroup gssapi + */ + +OM_uint32 GSSAPI_LIB_FUNCTION gss_wrap_iov_length(OM_uint32 * minor_status, gss_ctx_id_t context_handle, int conf_req_flag, @@ -132,6 +162,13 @@ gss_wrap_iov_length(OM_uint32 * minor_status, iov, iov_count); } +/** + * Free all buffer allocated by gss_wrap_iov() or gss_unwrap_iov() by + * looking at the GSS_IOV_BUFFER_TYPE_FLAG_ALLOCATED flag. + * + * @ingroup gssapi + */ + OM_uint32 GSSAPI_LIB_FUNCTION gss_release_iov_buffer(OM_uint32 *minor_status, gss_iov_buffer_desc *iov, @@ -146,9 +183,10 @@ gss_release_iov_buffer(OM_uint32 *minor_status, return GSS_S_CALL_INACCESSIBLE_READ; for (i = 0; i < iov_count; i++) { - if (iov[i].type & GSS_IOV_BUFFER_TYPE_FLAG_ALLOCATED) + if ((iov[i].type & GSS_IOV_BUFFER_TYPE_FLAG_ALLOCATED) == 0) continue; gss_release_buffer(&junk, &iov[i].buffer); + iov[i].type &= ~GSS_IOV_BUFFER_TYPE_FLAG_ALLOCATED; } return GSS_S_COMPLETE; } @@ -159,6 +197,8 @@ gss_release_iov_buffer(OM_uint32 *minor_status, * SSPI equivalent if this function is QueryContextAttributes. * * - GSS_C_ATTR_STREAM_SIZES data is a gss_context_stream_sizes. + * + * @ingroup gssapi */ static gss_OID_desc gss_c_attr_stream_sizes_desc = diff --git a/source4/heimdal/lib/gssapi/spnego/accept_sec_context.c b/source4/heimdal/lib/gssapi/spnego/accept_sec_context.c index 158126d99f..2bdfc28ebf 100644 --- a/source4/heimdal/lib/gssapi/spnego/accept_sec_context.c +++ b/source4/heimdal/lib/gssapi/spnego/accept_sec_context.c @@ -92,12 +92,6 @@ send_supported_mechs (OM_uint32 *minor_status, gss_buffer_t output_token) { NegotiationTokenWin nt; - char hostname[MAXHOSTNAMELEN + 1], *p; - gss_buffer_desc name_buf; - gss_OID name_type; - gss_name_t target_princ; - gss_name_t canon_princ; - OM_uint32 minor; size_t buf_len; gss_buffer_desc data; OM_uint32 ret; @@ -116,62 +110,9 @@ send_supported_mechs (OM_uint32 *minor_status, return ret; } - memset(&target_princ, 0, sizeof(target_princ)); - if (gethostname(hostname, sizeof(hostname) - 2) != 0) { - *minor_status = errno; - free_NegotiationTokenWin(&nt); - return GSS_S_FAILURE; - } - hostname[sizeof(hostname) - 1] = '\0'; - - /* Send the constructed SAM name for this host */ - for (p = hostname; *p != '\0' && *p != '.'; p++) { - *p = toupper((unsigned char)*p); - } - *p++ = '$'; - *p = '\0'; - - name_buf.length = strlen(hostname); - name_buf.value = hostname; - - ret = gss_import_name(minor_status, &name_buf, - GSS_C_NO_OID, - &target_princ); - if (ret != GSS_S_COMPLETE) { - free_NegotiationTokenWin(&nt); - return ret; - } - - name_buf.length = 0; - name_buf.value = NULL; - - /* Canonicalize the name using the preferred mechanism */ - ret = gss_canonicalize_name(minor_status, - target_princ, - GSS_C_NO_OID, - &canon_princ); - if (ret != GSS_S_COMPLETE) { - free_NegotiationTokenWin(&nt); - gss_release_name(&minor, &target_princ); - return ret; - } - - ret = gss_display_name(minor_status, canon_princ, - &name_buf, &name_type); - if (ret != GSS_S_COMPLETE) { - free_NegotiationTokenWin(&nt); - gss_release_name(&minor, &canon_princ); - gss_release_name(&minor, &target_princ); - return ret; - } - - gss_release_name(&minor, &canon_princ); - gss_release_name(&minor, &target_princ); - ALLOC(nt.u.negTokenInit.negHints, 1); if (nt.u.negTokenInit.negHints == NULL) { *minor_status = ENOMEM; - gss_release_buffer(&minor, &name_buf); free_NegotiationTokenWin(&nt); return GSS_S_FAILURE; } @@ -179,20 +120,19 @@ send_supported_mechs (OM_uint32 *minor_status, ALLOC(nt.u.negTokenInit.negHints->hintName, 1); if (nt.u.negTokenInit.negHints->hintName == NULL) { *minor_status = ENOMEM; - gss_release_buffer(&minor, &name_buf); free_NegotiationTokenWin(&nt); return GSS_S_FAILURE; } - *(nt.u.negTokenInit.negHints->hintName) = name_buf.value; - name_buf.value = NULL; + *nt.u.negTokenInit.negHints->hintName = strdup("not_defined_in_RFC4178@please_ignore"); nt.u.negTokenInit.negHints->hintAddress = NULL; ASN1_MALLOC_ENCODE(NegotiationTokenWin, data.value, data.length, &nt, &buf_len, ret); free_NegotiationTokenWin(&nt); if (ret) { - return ret; + *minor_status = ret; + return GSS_S_FAILURE; } if (data.length != buf_len) abort(); diff --git a/source4/heimdal/lib/hdb/db.c b/source4/heimdal/lib/hdb/db.c index 556833d1c4..9de0a04a1f 100644 --- a/source4/heimdal/lib/hdb/db.c +++ b/source4/heimdal/lib/hdb/db.c @@ -33,8 +33,6 @@ #include "hdb_locl.h" -RCSID("$Id$"); - #if HAVE_DB1 #if defined(HAVE_DB_185_H) @@ -317,6 +315,7 @@ hdb_db_create(krb5_context context, HDB **db, } (*db)->hdb_master_key_set = 0; (*db)->hdb_openp = 0; + (*db)->hdb_capability_flags = HDB_CAP_F_HANDLE_ENTERPRISE_PRINCIPAL; (*db)->hdb_open = DB_open; (*db)->hdb_close = DB_close; (*db)->hdb_fetch = _hdb_fetch; diff --git a/source4/heimdal/lib/hdb/dbinfo.c b/source4/heimdal/lib/hdb/dbinfo.c index 7e2961c614..a399ab0a5c 100644 --- a/source4/heimdal/lib/hdb/dbinfo.c +++ b/source4/heimdal/lib/hdb/dbinfo.c @@ -33,8 +33,6 @@ #include "hdb_locl.h" -RCSID("$Id$"); - struct hdb_dbinfo { char *label; char *realm; diff --git a/source4/heimdal/lib/hdb/ext.c b/source4/heimdal/lib/hdb/ext.c index 9053fd6633..faf0b6bdf2 100644 --- a/source4/heimdal/lib/hdb/ext.c +++ b/source4/heimdal/lib/hdb/ext.c @@ -34,8 +34,6 @@ #include "hdb_locl.h" #include <der.h> -RCSID("$Id$"); - krb5_error_code hdb_entry_check_mandatory(krb5_context context, const hdb_entry *ent) { diff --git a/source4/heimdal/lib/hdb/hdb.asn1 b/source4/heimdal/lib/hdb/hdb.asn1 index c2abd4af73..a72851c9f2 100644 --- a/source4/heimdal/lib/hdb/hdb.asn1 +++ b/source4/heimdal/lib/hdb/hdb.asn1 @@ -45,7 +45,9 @@ HDBFlags ::= BIT STRING { immutable(13), -- may not be deleted trusted-for-delegation(14), -- Trusted to print forwardabled tickets allow-kerberos4(15), -- Allow Kerberos 4 requests - allow-digest(16) -- Allow digest requests + allow-digest(16), -- Allow digest requests + locked-out(17) -- Account is locked out, + -- authentication will be denied } GENERATION ::= SEQUENCE { diff --git a/source4/heimdal/lib/hdb/hdb.c b/source4/heimdal/lib/hdb/hdb.c index e55b0bed03..9795f8b255 100644 --- a/source4/heimdal/lib/hdb/hdb.c +++ b/source4/heimdal/lib/hdb/hdb.c @@ -33,7 +33,6 @@ #include "krb5_locl.h" #include "hdb_locl.h" -RCSID("$Id$"); #ifdef HAVE_DLFCN_H #include <dlfcn.h> diff --git a/source4/heimdal/lib/hdb/hdb.h b/source4/heimdal/lib/hdb/hdb.h index a5e6514e6c..f490dbf2f0 100644 --- a/source4/heimdal/lib/hdb/hdb.h +++ b/source4/heimdal/lib/hdb/hdb.h @@ -54,7 +54,15 @@ enum hdb_lockop{ HDB_RLOCK, HDB_WLOCK }; #define HDB_F_GET_ANY 28 /* fetch any of client,server,krbtgt */ #define HDB_F_CANON 32 /* want canonicalition */ +/* hdb_capability_flags */ #define HDB_CAP_F_HANDLE_ENTERPRISE_PRINCIPAL 1 +#define HDB_CAP_F_HANDLE_PASSWORDS 2 +#define HDB_CAP_F_PASSWORD_UPDATE_KEYS 4 + +/* auth status values */ +#define HDB_AUTH_SUCCESS 0 +#define HDB_AUTH_WRONG_PASSWORD 1 +#define HDB_AUTH_INVALID_SIGNATURE 2 /* key usage for master key */ #define HDB_KU_MKEY 0x484442 @@ -184,6 +192,34 @@ typedef struct HDB{ * point for the module. */ krb5_error_code (*hdb_destroy)(krb5_context, struct HDB*); + /** + * Change password. + * + * Will update keys for the entry when given password. The new + * keys must be written into the entry and and will then later be + * ->hdb_store() into the database. The backend will still perform + * all other operations, increasing the kvno, and update + * modification timestamp. + * + * The backen need to call _kadm5_set_keys() and perform password + * quality checks. + */ + krb5_error_code (*hdb_password)(krb5_context, struct HDB*, hdb_entry_ex*, const char *, int); + + /** + * Auth feedback + * + * This is a feedback call that allows backends that provides + * lockout functionality to register failure and/or successes. + * + * In case the entry is locked out, the backend should set the + * hdb_entry.flags.locked-out flag. + */ + krb5_error_code (*hdb_auth_status)(krb5_context, struct HDB *, hdb_entry_ex *, int); + /** + * Check is delegation is allowed. + */ + krb5_error_code (*hdb_check_constrained_delegation)(krb5_context, struct HDB *, hdb_entry_ex *, krb5_const_principal); }HDB; #define HDB_INTERFACE_VERSION 5 diff --git a/source4/heimdal/lib/hdb/keys.c b/source4/heimdal/lib/hdb/keys.c index 50fe7d7fda..63f254d002 100644 --- a/source4/heimdal/lib/hdb/keys.c +++ b/source4/heimdal/lib/hdb/keys.c @@ -34,8 +34,6 @@ #include "hdb_locl.h" -RCSID("$Id$"); - /* * free all the memory used by (len, keys) */ diff --git a/source4/heimdal/lib/hdb/keytab.c b/source4/heimdal/lib/hdb/keytab.c index 97989a9764..9b36a268cf 100644 --- a/source4/heimdal/lib/hdb/keytab.c +++ b/source4/heimdal/lib/hdb/keytab.c @@ -35,8 +35,6 @@ /* keytab backend for HDB databases */ -RCSID("$Id$"); - struct hdb_data { char *dbname; char *mkey; @@ -123,61 +121,43 @@ hdb_get_name(krb5_context context, return 0; } -static void -set_config (krb5_context context, - const krb5_config_binding *binding, - const char **dbname, - const char **mkey) -{ - *dbname = krb5_config_get_string(context, binding, "dbname", NULL); - *mkey = krb5_config_get_string(context, binding, "mkey_file", NULL); -} - /* * try to figure out the database (`dbname') and master-key (`mkey') * that should be used for `principal'. */ -static void +static krb5_error_code find_db (krb5_context context, - const char **dbname, - const char **mkey, + char **dbname, + char **mkey, krb5_const_principal principal) { - const krb5_config_binding *top_bind = NULL; - const krb5_config_binding *default_binding = NULL; - const krb5_config_binding *db; krb5_const_realm realm = krb5_principal_get_realm(context, principal); + krb5_error_code ret; + struct hdb_dbinfo *head, *dbinfo = NULL; *dbname = *mkey = NULL; - while ((db = - krb5_config_get_next(context, - NULL, - &top_bind, - krb5_config_list, - "kdc", - "database", - NULL)) != NULL) { - const char *p; - - p = krb5_config_get_string (context, db, "realm", NULL); - if (p == NULL) { - if(default_binding) { - krb5_warnx(context, "WARNING: more than one realm-less " - "database specification"); - krb5_warnx(context, "WARNING: using the first encountered"); - } else - default_binding = db; - } else if (strcmp (realm, p) == 0) { - set_config (context, db, dbname, mkey); + ret = hdb_get_dbinfo(context, &head); + if (ret) + return ret; + + while ((dbinfo = hdb_dbinfo_get_next(head, dbinfo)) != NULL) { + const char *p = hdb_dbinfo_get_realm(context, dbinfo); + if (p && strcmp (realm, p) == 0) { + p = hdb_dbinfo_get_dbname(context, dbinfo); + if (p) + *dbname = strdup(p); + p = hdb_dbinfo_get_mkey_file(context, dbinfo); + if (p) + *mkey = strdup(p); break; } } - if (*dbname == NULL && default_binding != NULL) - set_config (context, default_binding, dbname, mkey); + hdb_free_dbinfo(context, &head); if (*dbname == NULL) - *dbname = HDB_DEFAULT_DB; + *dbname = strdup(HDB_DEFAULT_DB); + return 0; } /* @@ -196,29 +176,35 @@ hdb_get_entry(krb5_context context, hdb_entry_ex ent; krb5_error_code ret; struct hdb_data *d = id->data; - int i; - HDB *db; const char *dbname = d->dbname; const char *mkey = d->mkey; + char *fdbname = NULL, *fmkey = NULL; + HDB *db; + int i; memset(&ent, 0, sizeof(ent)); - if (dbname == NULL) - find_db (context, &dbname, &mkey, principal); + if (dbname == NULL) { + ret = find_db(context, &fdbname, &fmkey, principal); + if (ret) + return ret; + dbname = fdbname; + mkey = fmkey; + } ret = hdb_create (context, &db, dbname); if (ret) - return ret; + goto out2; ret = hdb_set_master_keyfile (context, db, mkey); if (ret) { (*db->hdb_destroy)(context, db); - return ret; + goto out2; } ret = (*db->hdb_open)(context, db, O_RDONLY, 0); if (ret) { (*db->hdb_destroy)(context, db); - return ret; + goto out2; } ret = (*db->hdb_fetch)(context, db, principal, HDB_F_DECRYPT| @@ -252,9 +238,12 @@ hdb_get_entry(krb5_context context, } } hdb_free_entry(context, &ent); -out: + out: (*db->hdb_close)(context, db); (*db->hdb_destroy)(context, db); + out2: + free(fdbname); + free(fmkey); return ret; } diff --git a/source4/heimdal/lib/hdb/mkey.c b/source4/heimdal/lib/hdb/mkey.c index 1520c4f7e9..35323cf100 100644 --- a/source4/heimdal/lib/hdb/mkey.c +++ b/source4/heimdal/lib/hdb/mkey.c @@ -36,8 +36,6 @@ #define O_BINARY 0 #endif -RCSID("$Id$"); - struct hdb_master_key_data { krb5_keytab_entry keytab; krb5_crypto crypto; diff --git a/source4/heimdal/lib/hdb/ndbm.c b/source4/heimdal/lib/hdb/ndbm.c index 1e9df81652..d97a98ed6b 100644 --- a/source4/heimdal/lib/hdb/ndbm.c +++ b/source4/heimdal/lib/hdb/ndbm.c @@ -33,8 +33,6 @@ #include "hdb_locl.h" -RCSID("$Id$"); - #if HAVE_NDBM #if defined(HAVE_GDBM_NDBM_H) @@ -348,6 +346,7 @@ hdb_ndbm_create(krb5_context context, HDB **db, } (*db)->hdb_master_key_set = 0; (*db)->hdb_openp = 0; + (*db)->hdb_capability_flags = HDB_CAP_F_HANDLE_ENTERPRISE_PRINCIPAL; (*db)->hdb_open = NDBM_open; (*db)->hdb_close = NDBM_close; (*db)->hdb_fetch = _hdb_fetch; diff --git a/source4/heimdal/lib/hx509/crypto.c b/source4/heimdal/lib/hx509/crypto.c index 8063100717..f4667c6e31 100644 --- a/source4/heimdal/lib/hx509/crypto.c +++ b/source4/heimdal/lib/hx509/crypto.c @@ -37,10 +37,6 @@ struct hx509_crypto; struct signature_alg; -enum crypto_op_type { - COT_SIGN -}; - struct hx509_generate_private_context { const heim_oid *key_oid; int isCA; diff --git a/source4/heimdal/lib/krb5/crypto.c b/source4/heimdal/lib/krb5/crypto.c index 9fd2117345..a30780d1ed 100644 --- a/source4/heimdal/lib/krb5/crypto.c +++ b/source4/heimdal/lib/krb5/crypto.c @@ -3182,7 +3182,7 @@ krb5_encrypt_iov_ivec(krb5_context context, krb5_error_code ret; struct key_data *dkey; const struct encryption_type *et = crypto->et; - krb5_crypto_iov *tiv, *piv, *hiv, *div; + krb5_crypto_iov *tiv, *piv, *hiv; if (num_data < 0) { krb5_clear_error_message(context); @@ -3197,11 +3197,11 @@ krb5_encrypt_iov_ivec(krb5_context context, headersz = et->confoundersize; trailersz = CHECKSUMSIZE(et->keyed_checksum); - div = find_iv(data, num_data, KRB5_CRYPTO_TYPE_DATA); - if (div == NULL) - return KRB5_CRYPTO_INTERNAL; - - len = div->data.length; + for (len = 0, i = 0; i < num_data; i++) { + if (data[i].flags != KRB5_CRYPTO_TYPE_DATA) + continue; + len += data[i].data.length; + } sz = headersz + len; block_sz = (sz + et->padsize - 1) &~ (et->padsize - 1); /* pad */ @@ -3217,7 +3217,6 @@ krb5_encrypt_iov_ivec(krb5_context context, krb5_generate_random_block(hiv->data.data, hiv->data.length); /* padding */ - piv = find_iv(data, num_data, KRB5_CRYPTO_TYPE_PADDING); /* its ok to have no TYPE_PADDING if there is no padding */ if (piv == NULL && pad_sz != 0) @@ -3226,26 +3225,26 @@ krb5_encrypt_iov_ivec(krb5_context context, if (piv->data.length < pad_sz) return KRB5_BAD_MSIZE; piv->data.length = pad_sz; + if (pad_sz) + memset(piv->data.data, pad_sz, pad_sz); + else + piv = NULL; } - /* trailer */ - tiv = find_iv(data, num_data, KRB5_CRYPTO_TYPE_TRAILER); if (tiv == NULL || tiv->data.length != trailersz) return KRB5_BAD_MSIZE; - /* * XXX replace with EVP_Sign? at least make create_checksum an iov * function. * XXX CTS EVP is broken, can't handle multi buffers :( */ - len = hiv->data.length; + len = block_sz; for (i = 0; i < num_data; i++) { - if (data[i].flags != KRB5_CRYPTO_TYPE_DATA && - data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY) + if (data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY) continue; len += data[i].data.length; } @@ -3261,6 +3260,10 @@ krb5_encrypt_iov_ivec(krb5_context context, memcpy(q, data[i].data.data, data[i].data.length); q += data[i].data.length; } + if (piv) { + memset(q, 0, piv->data.length); + q += piv->data.length; + } ret = create_checksum(context, et->keyed_checksum, @@ -3282,30 +3285,24 @@ krb5_encrypt_iov_ivec(krb5_context context, memcpy(tiv->data.data, cksum.checksum.data, cksum.checksum.length); free_Checksum (&cksum); - /* now encrypt data */ - - ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey); - if(ret) - return ret; - ret = _key_schedule(context, dkey); - if(ret) - return ret; - /* XXX replace with EVP_Cipher */ - - len = hiv->data.length + div->data.length; - if (piv) - len += piv->data.length; - - p = q = malloc(len); + p = q = malloc(block_sz); if(p == NULL) return ENOMEM; memcpy(q, hiv->data.data, hiv->data.length); q += hiv->data.length; - memcpy(q, div->data.data, div->data.length); - q += div->data.length; - memset(q, 0, pad_sz); + + for (i = 0; i < num_data; i++) { + if (data[i].flags != KRB5_CRYPTO_TYPE_DATA) + continue; + memcpy(q, data[i].data.data, data[i].data.length); + q += data[i].data.length; + } + if (piv) { + memset(q, 0, piv->data.length); + q += piv->data.length; + } ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey); if(ret) { @@ -3318,7 +3315,7 @@ krb5_encrypt_iov_ivec(krb5_context context, return ret; } - ret = (*et->encrypt)(context, dkey, p, len, 1, usage, ivec); + ret = (*et->encrypt)(context, dkey, p, block_sz, 1, usage, ivec); if (ret) { free(p); return ret; @@ -3330,11 +3327,17 @@ krb5_encrypt_iov_ivec(krb5_context context, memcpy(hiv->data.data, q, hiv->data.length); q += hiv->data.length; - memcpy(div->data.data, q, div->data.length); - q += div->data.length; - - if (piv) + for (i = 0; i < num_data; i++) { + if (data[i].flags != KRB5_CRYPTO_TYPE_DATA) + continue; + memcpy(data[i].data.data, q, data[i].data.length); + q += data[i].data.length; + } + if (piv) { memcpy(piv->data.data, q, pad_sz); + q += pad_sz; + } + free(p); return ret; @@ -3371,13 +3374,12 @@ krb5_decrypt_iov_ivec(krb5_context context, { unsigned int i; size_t headersz, trailersz, len; - size_t sz, block_sz, pad_sz; Checksum cksum; unsigned char *p, *q; krb5_error_code ret; struct key_data *dkey; struct encryption_type *et = crypto->et; - krb5_crypto_iov *tiv, *hiv, *div; + krb5_crypto_iov *tiv, *hiv; if (num_data < 0) { krb5_clear_error_message(context); @@ -3390,56 +3392,47 @@ krb5_decrypt_iov_ivec(krb5_context context, } headersz = et->confoundersize; - trailersz = CHECKSUMSIZE(et->keyed_checksum); - - for (len = 0, i = 0; i < num_data; i++) { - if (data[i].flags == KRB5_CRYPTO_TYPE_DATA) { - if (len != 0) - return KRB5_CRYPTO_INTERNAL; - len += data[i].data.length; - } - } - - sz = headersz + len; - block_sz = (sz + et->padsize - 1) &~ (et->padsize - 1); /* pad */ - - pad_sz = block_sz - sz; - trailersz += pad_sz; - - /* header */ hiv = find_iv(data, num_data, KRB5_CRYPTO_TYPE_HEADER); - if (hiv == NULL || hiv->data.length < headersz) + if (hiv == NULL || hiv->data.length != headersz) return KRB5_BAD_MSIZE; - hiv->data.length = headersz; /* trailer */ + trailersz = CHECKSUMSIZE(et->keyed_checksum); tiv = find_iv(data, num_data, KRB5_CRYPTO_TYPE_TRAILER); - if (tiv == NULL || tiv->data.length < trailersz) + if (tiv->data.length != trailersz) return KRB5_BAD_MSIZE; - tiv->data.length = trailersz; - - div = find_iv(data, num_data, KRB5_CRYPTO_TYPE_DATA); - if (div == NULL) - return KRB5_CRYPTO_INTERNAL; - /* XXX replace with EVP_Cipher */ + /* Find length of data we will decrypt */ - for (len = 0, i = 0; i < num_data; i++) { - if (data[i].flags != KRB5_CRYPTO_TYPE_HEADER && - data[i].flags != KRB5_CRYPTO_TYPE_DATA) + len = headersz; + for (i = 0; i < num_data; i++) { + if (data[i].flags != KRB5_CRYPTO_TYPE_DATA) continue; len += data[i].data.length; } + if ((len % et->padsize) != 0) { + krb5_clear_error_message(context); + return KRB5_BAD_MSIZE; + } + + /* XXX replace with EVP_Cipher */ + p = q = malloc(len); if (p == NULL) return ENOMEM; memcpy(q, hiv->data.data, hiv->data.length); q += hiv->data.length; - memcpy(q, div->data.data, div->data.length); + + for (i = 0; i < num_data; i++) { + if (data[i].flags != KRB5_CRYPTO_TYPE_DATA) + continue; + memcpy(q, data[i].data.data, data[i].data.length); + q += data[i].data.length; + } ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey); if(ret) { @@ -3460,20 +3453,26 @@ krb5_decrypt_iov_ivec(krb5_context context, /* copy data back to buffers */ memcpy(hiv->data.data, p, hiv->data.length); - memcpy(div->data.data, p + hiv->data.length, len - hiv->data.length); + q = p + hiv->data.length; + for (i = 0; i < num_data; i++) { + if (data[i].flags != KRB5_CRYPTO_TYPE_DATA) + continue; + memcpy(data[i].data.data, q, data[i].data.length); + q += data[i].data.length; + } + free(p); /* check signature */ - - len = hiv->data.length; for (i = 0; i < num_data; i++) { - if (data[i].flags != KRB5_CRYPTO_TYPE_DATA && - data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY) + if (data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY) continue; len += data[i].data.length; } p = q = malloc(len); + if (p == NULL) + return ENOMEM; memcpy(q, hiv->data.data, hiv->data.length); q += hiv->data.length; @@ -3582,33 +3581,145 @@ krb5_create_checksum_iov(krb5_context context, return 0; } +/** + * Verify a Kerberos message checksum. + * + * @param context Kerberos context + * @param crypto Kerberos crypto context + * @param usage Key usage for this buffer + * @param data array of buffers to process + * @param num_data length of array + * + * @return Return an error code or 0. + * @ingroup krb5_crypto + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_verify_checksum_iov(krb5_context context, + krb5_crypto crypto, + unsigned usage, + krb5_crypto_iov *data, + unsigned int num_data, + krb5_cksumtype *type) +{ + struct encryption_type *et = crypto->et; + Checksum cksum; + krb5_crypto_iov *civ; + krb5_error_code ret; + int i; + size_t len; + char *p, *q; + + if (num_data < 0) { + krb5_clear_error_message(context); + return KRB5_CRYPTO_INTERNAL; + } + + if(!derived_crypto(context, crypto)) { + krb5_clear_error_message(context); + return KRB5_CRYPTO_INTERNAL; + } + + civ = find_iv(data, num_data, KRB5_CRYPTO_TYPE_CHECKSUM); + if (civ == NULL) + return KRB5_BAD_MSIZE; + + len = 0; + for (i = 0; i < num_data; i++) { + if (data[i].flags != KRB5_CRYPTO_TYPE_DATA && + data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY) + continue; + len += data[i].data.length; + } + + p = q = malloc(len); + + for (i = 0; i < num_data; i++) { + if (data[i].flags != KRB5_CRYPTO_TYPE_DATA && + data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY) + continue; + memcpy(q, data[i].data.data, data[i].data.length); + q += data[i].data.length; + } + + cksum.cksumtype = CHECKSUMTYPE(et->keyed_checksum); + cksum.checksum.length = civ->data.length; + cksum.checksum.data = civ->data.data; + + ret = krb5_verify_checksum(context, crypto, usage, p, len, &cksum); + free(p); + + if (ret == 0 && type) + *type = cksum.cksumtype; + + return ret; +} + -size_t KRB5_LIB_FUNCTION +krb5_error_code KRB5_LIB_FUNCTION krb5_crypto_length(krb5_context context, krb5_crypto crypto, - int type) + int type, + size_t *len) { - if (!derived_crypto(context, crypto)) - return (size_t)-1; + if (!derived_crypto(context, crypto)) { + krb5_set_error_message(context, EINVAL, "not a derived crypto"); + return EINVAL; + } + switch(type) { case KRB5_CRYPTO_TYPE_EMPTY: + *len = 0; return 0; case KRB5_CRYPTO_TYPE_HEADER: - return crypto->et->blocksize; + *len = crypto->et->blocksize; + return 0; + case KRB5_CRYPTO_TYPE_DATA: + case KRB5_CRYPTO_TYPE_SIGN_ONLY: + /* len must already been filled in */ + return 0; case KRB5_CRYPTO_TYPE_PADDING: if (crypto->et->padsize > 1) - return crypto->et->padsize; + *len = crypto->et->padsize; + else + *len = 0; return 0; case KRB5_CRYPTO_TYPE_TRAILER: - return CHECKSUMSIZE(crypto->et->keyed_checksum); + *len = CHECKSUMSIZE(crypto->et->keyed_checksum); + return 0; case KRB5_CRYPTO_TYPE_CHECKSUM: if (crypto->et->keyed_checksum) - return CHECKSUMSIZE(crypto->et->keyed_checksum); - return CHECKSUMSIZE(crypto->et->checksum); + *len = CHECKSUMSIZE(crypto->et->keyed_checksum); + else + *len = CHECKSUMSIZE(crypto->et->checksum); + return 0; + } + krb5_set_error_message(context, EINVAL, + "%d not a supported type", type); + return EINVAL; +} + + +krb5_error_code KRB5_LIB_FUNCTION +krb5_crypto_length_iov(krb5_context context, + krb5_crypto crypto, + krb5_crypto_iov *data, + unsigned int num_data) +{ + krb5_error_code ret; + int i; + + for (i = 0; i < num_data; i++) { + ret = krb5_crypto_length(context, crypto, + data[i].flags, + &data[i].data.length); + if (ret) + return ret; } - return (size_t)-1; + return 0; } + krb5_error_code KRB5_LIB_FUNCTION krb5_encrypt_ivec(krb5_context context, krb5_crypto crypto, diff --git a/source4/heimdal/lib/krb5/get_addrs.c b/source4/heimdal/lib/krb5/get_addrs.c index 96571af531..8f366fa148 100644 --- a/source4/heimdal/lib/krb5/get_addrs.c +++ b/source4/heimdal/lib/krb5/get_addrs.c @@ -41,9 +41,7 @@ struct mbuf; #ifdef HAVE_NET_IF_H #include <net/if.h> #endif -#ifdef HAVE_IFADDR_H #include <ifaddrs.h> -#endif static krb5_error_code gethostname_fallback (krb5_context context, krb5_addresses *res) diff --git a/source4/heimdal/lib/krb5/init_creds_pw.c b/source4/heimdal/lib/krb5/init_creds_pw.c index 0435ab5d3b..ff89a90d55 100644 --- a/source4/heimdal/lib/krb5/init_creds_pw.c +++ b/source4/heimdal/lib/krb5/init_creds_pw.c @@ -1601,7 +1601,7 @@ krb5_init_creds_step(krb5_context context, ret = 0; } else if (ret == KRB5_KDC_ERR_WRONG_REALM && ctx->flags.canonicalize) { /* client referal to a new realm */ - if (ctx->error.crealm) { + if (ctx->error.crealm == NULL) { krb5_set_error_message(context, ret, N_("Got a client referral, not but no realm", "")); goto out; diff --git a/source4/heimdal/lib/krb5/store_emem.c b/source4/heimdal/lib/krb5/store_emem.c index 4be89b6564..acf984280e 100644 --- a/source4/heimdal/lib/krb5/store_emem.c +++ b/source4/heimdal/lib/krb5/store_emem.c @@ -110,7 +110,12 @@ emem_trunc(krb5_storage *sp, off_t offset) * If offset is larget then current size, or current size is * shrunk more then half of the current size, adjust buffer. */ - if (offset > s->size || (s->size / 2) > offset) { + if (offset == 0) { + free(s->base); + s->size = 0; + s->base = NULL; + s->ptr = NULL; + } else if (offset > s->size || (s->size / 2) > offset) { void *base; size_t off; off = s->ptr - s->base; |