diff options
author | Garming Sam <garming@catalyst.net.nz> | 2016-05-09 16:14:51 +1200 |
---|---|---|
committer | Andrew Bartlett <abartlet@samba.org> | 2016-07-05 10:52:32 +0200 |
commit | 978bc8681e74ffa17f96fd5d4355094c4a26691c (patch) | |
tree | 701d5325b968df1b009d781dce30f1c583494ec4 /source4/heimdal | |
parent | 965361aa929ab6798e03e71d3800027a32896c7d (diff) | |
download | samba-978bc8681e74ffa17f96fd5d4355094c4a26691c.tar.gz |
kerberos: Return enc data on PREAUTH_FAILED
Without the enc data, Windows clients will perform two AS-REQ causing the password
lockout count to increase by two instead of one.
Signed-off-by: Garming Sam <garming@catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
BUG: https://bugzilla.samba.org/show_bug.cgi?id=11539
Autobuild-User(master): Andrew Bartlett <abartlet@samba.org>
Autobuild-Date(master): Tue Jul 5 10:52:32 CEST 2016 on sn-devel-144
Diffstat (limited to 'source4/heimdal')
-rw-r--r-- | source4/heimdal/kdc/kerberos5.c | 178 |
1 files changed, 99 insertions, 79 deletions
diff --git a/source4/heimdal/kdc/kerberos5.c b/source4/heimdal/kdc/kerberos5.c index 3762abe0120..b8bb5fa6609 100644 --- a/source4/heimdal/kdc/kerberos5.c +++ b/source4/heimdal/kdc/kerberos5.c @@ -976,7 +976,7 @@ _kdc_as_rep(krb5_context context, krb5_error_code ret = 0; const char *e_text = NULL; krb5_crypto crypto; - Key *ckey, *skey; + Key *skey; EncryptionKey *reply_key = NULL, session_key; int flags = HDB_F_FOR_AS_REQ; #ifdef PKINIT @@ -1373,6 +1373,9 @@ _kdc_as_rep(krb5_context context, was some problem with it, other than too large skew */ if(found_pa && et.flags.pre_authent == 0){ kdc_log(context, config, 0, "%s -- %s", e_text, client_name); + if (!prepare_enc_data(context, config, &e_data, b, client)) { + goto out; + } e_text = NULL; goto out; } @@ -1380,88 +1383,11 @@ _kdc_as_rep(krb5_context context, || b->kdc_options.request_anonymous /* hack to force anon */ || client->entry.flags.require_preauth || server->entry.flags.require_preauth) { - METHOD_DATA method_data; - PA_DATA *pa; - unsigned char *buf; - size_t len; - use_pa: - method_data.len = 0; - method_data.val = NULL; - - ret = realloc_method_data(&method_data); - if (ret) { - free_METHOD_DATA(&method_data); - goto out; - } - pa = &method_data.val[method_data.len-1]; - pa->padata_type = KRB5_PADATA_ENC_TIMESTAMP; - pa->padata_value.length = 0; - pa->padata_value.data = NULL; - -#ifdef PKINIT - ret = realloc_method_data(&method_data); - if (ret) { - free_METHOD_DATA(&method_data); - goto out; - } - pa = &method_data.val[method_data.len-1]; - pa->padata_type = KRB5_PADATA_PK_AS_REQ; - pa->padata_value.length = 0; - pa->padata_value.data = NULL; - - ret = realloc_method_data(&method_data); - if (ret) { - free_METHOD_DATA(&method_data); - goto out; - } - pa = &method_data.val[method_data.len-1]; - pa->padata_type = KRB5_PADATA_PK_AS_REQ_WIN; - pa->padata_value.length = 0; - pa->padata_value.data = NULL; -#endif - - /* - * If there is a client key, send ETYPE_INFO{,2} - */ - ret = _kdc_find_etype(context, - config->preauth_use_strongest_session_key, TRUE, - client, b->etype.val, b->etype.len, NULL, &ckey); - if (ret == 0) { - - /* - * RFC4120 requires: - * - If the client only knows about old enctypes, then send - * both info replies (we send 'info' first in the list). - * - If the client is 'modern', because it knows about 'new' - * enctype types, then only send the 'info2' reply. - * - * Before we send the full list of etype-info data, we pick - * the client key we would have used anyway below, just pick - * that instead. - */ - - if (older_enctype(ckey->key.keytype)) { - ret = get_pa_etype_info(context, config, - &method_data, ckey); - if (ret) { - free_METHOD_DATA(&method_data); - goto out; - } - } - ret = get_pa_etype_info2(context, config, - &method_data, ckey); - if (ret) { - free_METHOD_DATA(&method_data); + if (!prepare_enc_data(context, config, &e_data, b, client)) { goto out; - } } - ASN1_MALLOC_ENCODE(METHOD_DATA, buf, len, &method_data, &len, ret); - free_METHOD_DATA(&method_data); - - e_data.data = buf; - e_data.length = len; e_text ="Need to use PA-ENC-TIMESTAMP/PA-PK-AS-REQ", ret = KRB5KDC_ERR_PREAUTH_REQUIRED; @@ -1834,6 +1760,100 @@ out: return ret; } +krb5_boolean +prepare_enc_data(krb5_context context, + krb5_kdc_configuration *config, + krb5_data *e_data, + KDC_REQ_BODY *b, + hdb_entry_ex *client) +{ + METHOD_DATA method_data; + PA_DATA *pa; + unsigned char *buf; + size_t len; + Key *ckey; + krb5_error_code ret; + + method_data.len = 0; + method_data.val = NULL; + + ret = realloc_method_data(&method_data); + if (ret) { + free_METHOD_DATA(&method_data); + return FALSE; + } + pa = &method_data.val[method_data.len-1]; + pa->padata_type = KRB5_PADATA_ENC_TIMESTAMP; + pa->padata_value.length = 0; + pa->padata_value.data = NULL; + +#ifdef PKINIT + ret = realloc_method_data(&method_data); + if (ret) { + free_METHOD_DATA(&method_data); + return FALSE; + } + pa = &method_data.val[method_data.len-1]; + pa->padata_type = KRB5_PADATA_PK_AS_REQ; + pa->padata_value.length = 0; + pa->padata_value.data = NULL; + + ret = realloc_method_data(&method_data); + if (ret) { + free_METHOD_DATA(&method_data); + return FALSE; + } + pa = &method_data.val[method_data.len-1]; + pa->padata_type = KRB5_PADATA_PK_AS_REQ_WIN; + pa->padata_value.length = 0; + pa->padata_value.data = NULL; +#endif + + /* + * If there is a client key, send ETYPE_INFO{,2} + */ + ret = _kdc_find_etype(context, + config->preauth_use_strongest_session_key, TRUE, + client, b->etype.val, b->etype.len, NULL, &ckey); + if (ret == 0) { + + /* + * RFC4120 requires: + * - If the client only knows about old enctypes, then send + * both info replies (we send 'info' first in the list). + * - If the client is 'modern', because it knows about 'new' + * enctype types, then only send the 'info2' reply. + * + * Before we send the full list of etype-info data, we pick + * the client key we would have used anyway below, just pick + * that instead. + */ + + if (older_enctype(ckey->key.keytype)) { + ret = get_pa_etype_info(context, config, + &method_data, ckey); + if (ret) { + free_METHOD_DATA(&method_data); + return FALSE; + } + } + ret = get_pa_etype_info2(context, config, + &method_data, ckey); + if (ret) { + free_METHOD_DATA(&method_data); + return FALSE; + } + } + + ASN1_MALLOC_ENCODE(METHOD_DATA, buf, len, &method_data, &len, ret); + free_METHOD_DATA(&method_data); + + e_data->data = buf; + e_data->length = len; + + return TRUE; +} + /* * Add the AuthorizationData `data´ of `type´ to the last element in * the sequence of authorization_data in `tkt´ wrapped in an IF_RELEVANT |