Generate a single summary audit line for AS/TGS.

We refactor the code a bit to extend kdc_request_t which until now
was only used for the AS.  We make the structure extensible and
start using it for the TGS as well.  We leave digest and kx509
alone for the time being.

We also define the concept of kv-pairs in our audit trail which
allows us to define a rigorous but extensible format:

type error from-addr client server key1=val1 key2=val2 ...
This commit is contained in:
Roland C. Dowdeswell
2019-11-18 21:34:35 +00:00
committed by Viktor Dukhovni
parent fb9a78223c
commit 7d353d0557
9 changed files with 670 additions and 423 deletions

View File

@@ -44,7 +44,6 @@
typedef struct pk_client_params pk_client_params;
struct DigestREQ;
struct Kx509Request;
typedef struct kdc_request_desc *kdc_request_t;
#include <kdc-private.h>

View File

@@ -36,7 +36,8 @@
#include "kdc_locl.h"
static krb5_error_code
get_fastuser_crypto(kdc_request_t r, krb5_enctype enctype, krb5_crypto *crypto)
get_fastuser_crypto(astgs_request_t r, krb5_enctype enctype,
krb5_crypto *crypto)
{
krb5_principal fast_princ;
hdb_entry_ex *fast_user = NULL;
@@ -79,7 +80,7 @@ get_fastuser_crypto(kdc_request_t r, krb5_enctype enctype, krb5_crypto *crypto)
static krb5_error_code
fast_parse_cookie(kdc_request_t r, const PA_DATA *pa)
fast_parse_cookie(astgs_request_t r, const PA_DATA *pa)
{
krb5_crypto crypto = NULL;
krb5_error_code ret;
@@ -127,7 +128,7 @@ fast_parse_cookie(kdc_request_t r, const PA_DATA *pa)
}
static krb5_error_code
fast_add_cookie(kdc_request_t r, METHOD_DATA *method_data)
fast_add_cookie(astgs_request_t r, METHOD_DATA *method_data)
{
krb5_crypto crypto = NULL;
KDCFastCookie shell;
@@ -237,8 +238,7 @@ _kdc_fast_mk_response(krb5_context context,
krb5_error_code
_kdc_fast_mk_error(krb5_context context,
kdc_request_t r,
_kdc_fast_mk_error(astgs_request_t r,
METHOD_DATA *error_method,
krb5_crypto armor_crypto,
const KDC_REQ_BODY *req_body,
@@ -250,6 +250,7 @@ _kdc_fast_mk_error(krb5_context context,
time_t *csec, int *cusec,
krb5_data *error_msg)
{
krb5_context context = r->context;
krb5_error_code ret;
krb5_data e_data;
size_t size;
@@ -342,7 +343,7 @@ _kdc_fast_mk_error(krb5_context context,
}
krb5_error_code
_kdc_fast_unwrap_request(kdc_request_t r)
_kdc_fast_unwrap_request(astgs_request_t r)
{
krb5_principal armor_server = NULL;
hdb_entry_ex *armor_user = NULL;

View File

@@ -101,18 +101,14 @@ typedef struct krb5_kdc_configuration {
const char *app;
} krb5_kdc_configuration;
typedef struct kdc_request_desc *kdc_request_t;
typedef struct astgs_request_desc *astgs_request_t;
struct krb5_kdc_service {
unsigned int flags;
#define KS_KRB5 1
#define KS_NO_LENGTH 2
krb5_error_code (*process)(krb5_context context,
krb5_kdc_configuration *config,
krb5_data *req_buffer,
krb5_data *reply,
const char *from,
struct sockaddr *addr,
int datagram_reply,
int *claim);
krb5_error_code (*process)(kdc_request_t *, int *claim);
};
#include <kdc-protos.h>

View File

@@ -43,24 +43,54 @@
typedef struct pk_client_params pk_client_params;
struct DigestREQ;
struct Kx509Request;
typedef struct kdc_request_desc *kdc_request_t;
#include <kdc-private.h>
#define FAST_EXPIRATION_TIME (3 * 60)
#define KDC_AUDIT_EATWHITE 0x1
#define KDC_AUDIT_VIS 0x2
/* KFE == KDC_FIND_ETYPE */
#define KFE_IS_TGS 0x1
#define KFE_IS_PREAUTH 0x2
#define KFE_USE_CLIENT 0x4
#define KDC_REQUEST_DESC_COMMON_ELEMENTS \
/* Input */ \
krb5_context context; \
krb5_kdc_configuration *config; \
const char *from; \
struct sockaddr *addr; \
int datagram_reply; \
krb5_data request; \
\
/* Output */ \
krb5_data *reply; \
krb5_boolean use_request_t; \
\
/* Common state, to be freed in process.c */ \
struct timeval tv_start; \
struct timeval tv_end; \
const char *reqtype; \
char *cname; \
char *sname; \
const char *e_text; \
char *e_text_buf; \
heim_array_t kv
struct kdc_request_desc {
krb5_context context;
krb5_kdc_configuration *config;
KDC_REQUEST_DESC_COMMON_ELEMENTS;
};
/* */
struct astgs_request_desc {
KDC_REQUEST_DESC_COMMON_ELEMENTS;
krb5_data request;
/* Both AS and TGS */
KDC_REQ req;
/* Only AS */
METHOD_DATA *padata;
/* out */
METHOD_DATA outpadata;
KDC_REP rep;
@@ -72,16 +102,12 @@ struct kdc_request_desc {
krb5_keyblock reply_key;
krb5_keyblock session_key;
const char *e_text;
/* state */
krb5_principal client_princ;
char *client_name;
hdb_entry_ex *client;
HDB *clientdb;
krb5_principal server_princ;
char *server_name;
hdb_entry_ex *server;
krb5_crypto armor_crypto;
@@ -89,7 +115,6 @@ struct kdc_request_desc {
KDCFastState fast;
};
extern sig_atomic_t exit_flag;
extern size_t max_request_udp;
extern size_t max_request_tcp;

View File

@@ -35,6 +35,9 @@
#define MAX_TIME ((time_t)((1U << 31) - 1))
#undef __attribute__
#define __attribute__(X)
void
_kdc_fix_time(time_t **t)
{
@@ -140,12 +143,17 @@ _kdc_is_anon_request(const KDC_REQ *req)
*/
krb5_error_code
_kdc_find_etype(krb5_context context, krb5_boolean use_strongest_session_key,
krb5_boolean is_preauth, hdb_entry_ex *princ,
krb5_principal request_princ, krb5_enctype *etypes, unsigned len,
_kdc_find_etype(astgs_request_t r, uint32_t flags,
krb5_enctype *etypes, unsigned len,
krb5_enctype *ret_enctype, Key **ret_key,
krb5_boolean *ret_default_salt)
{
krb5_context context = r->context;
krb5_boolean use_strongest_session_key;
krb5_boolean is_preauth = flags & KFE_IS_PREAUTH;
krb5_boolean is_tgs = flags & KFE_IS_TGS;
hdb_entry_ex *princ;
krb5_principal request_princ;
krb5_error_code ret;
krb5_salt def_salt;
krb5_enctype enctype = (krb5_enctype)ETYPE_NULL;
@@ -153,6 +161,19 @@ _kdc_find_etype(krb5_context context, krb5_boolean use_strongest_session_key,
Key *key = NULL;
int i, k;
if (flags & KFE_USE_CLIENT) {
princ = r->client;
request_princ = r->client_princ;
} else {
princ = r->server;
request_princ = r->server->entry.principal;
}
use_strongest_session_key =
is_preauth ? r->config->preauth_use_strongest_session_key
: (is_tgs ? r->config->tgt_use_strongest_session_key :
r->config->svc_use_strongest_session_key);
/* We'll want to avoid keys with v4 salted keys in the pre-auth case... */
ret = krb5_get_pw_salt(context, request_princ, &def_salt);
if (ret)
@@ -295,7 +316,8 @@ failed:
}
static void
_kdc_r_log(kdc_request_t r, int level, const char *fmt, ...)
_kdc_r_log(astgs_request_t r, int level, const char *fmt, ...)
__attribute__ ((__format__ (__printf__, 3, 4)))
{
va_list ap;
char *s;
@@ -305,23 +327,55 @@ _kdc_r_log(kdc_request_t r, int level, const char *fmt, ...)
va_end(ap);
}
static void
_kdc_set_e_text(kdc_request_t r, const char *e_text)
void
_kdc_set_e_text(astgs_request_t r, char *fmt, ...)
__attribute__ ((__format__ (__printf__, 2, 3)))
{
va_list ap;
char *e_text;
va_start(ap, fmt);
vasprintf(&e_text, fmt, ap);
va_end(ap);
if (!e_text)
/* not much else to do... */
return;
/* We should never see this */
if (r->e_text) {
kdc_log(r->context, r->config, 1, "trying to replace e-text: %s\n",
e_text);
free(e_text);
return;
}
r->e_text = e_text;
r->e_text_buf = e_text;
kdc_log(r->context, r->config, 0, "%s", e_text);
}
void
_kdc_log_timestamp(krb5_context context,
krb5_kdc_configuration *config,
const char *type,
_kdc_log_timestamp(astgs_request_t r, const char *type,
KerberosTime authtime, KerberosTime *starttime,
KerberosTime endtime, KerberosTime *renew_till)
{
krb5_context context = r->context;
krb5_kdc_configuration *config = r->config;
char authtime_str[100], starttime_str[100],
endtime_str[100], renewtime_str[100];
if (authtime)
_kdc_audit_addkv((kdc_request_t)r, 0, "auth", "%ld", (long)authtime);
if (starttime && *starttime)
_kdc_audit_addkv((kdc_request_t)r, 0, "start", "%ld",
(long)*starttime);
if (endtime)
_kdc_audit_addkv((kdc_request_t)r, 0, "end", "%ld", (long)endtime);
if (renew_till && *renew_till)
_kdc_audit_addkv((kdc_request_t)r, 0, "renew", "%ld",
(long)*renew_till);
krb5_format_time(context, authtime,
authtime_str, sizeof(authtime_str), TRUE);
if (starttime)
@@ -349,39 +403,32 @@ _kdc_log_timestamp(krb5_context context,
#ifdef PKINIT
static krb5_error_code
pa_pkinit_validate(kdc_request_t r, const PA_DATA *pa)
pa_pkinit_validate(astgs_request_t r, const PA_DATA *pa)
{
pk_client_params *pkp = NULL;
char *client_cert = NULL;
krb5_error_code ret;
ret = _kdc_pk_rd_padata(r->context, r->config, &r->req, pa, r->client, &pkp);
ret = _kdc_pk_rd_padata(r, pa, &pkp);
if (ret || pkp == NULL) {
ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
_kdc_r_log(r, 2, "Failed to decode PKINIT PA-DATA -- %s",
r->client_name);
_kdc_r_log(r, 4, "Failed to decode PKINIT PA-DATA -- %s",
r->cname);
goto out;
}
ret = _kdc_pk_check_client(r->context,
r->config,
r->clientdb,
r->client,
pkp,
&client_cert);
ret = _kdc_pk_check_client(r, pkp, &client_cert);
if (ret) {
_kdc_set_e_text(r, "PKINIT certificate not allowed to "
"impersonate principal");
goto out;
}
_kdc_r_log(r, 3, "PKINIT pre-authentication succeeded -- %s using %s",
r->client_name, client_cert);
_kdc_r_log(r, 4, "PKINIT pre-authentication succeeded -- %s using %s",
r->cname, client_cert);
free(client_cert);
ret = _kdc_pk_mk_pa_reply(r->context, r->config, pkp, r->client,
r->sessionetype, &r->req, &r->request,
&r->reply_key, &r->session_key, &r->outpadata);
ret = _kdc_pk_mk_pa_reply(r, pkp);
if (ret) {
_kdc_set_e_text(r, "Failed to build PK-INIT reply");
goto out;
@@ -404,9 +451,10 @@ pa_pkinit_validate(kdc_request_t r, const PA_DATA *pa)
*/
static krb5_error_code
make_pa_enc_challange(krb5_context context, METHOD_DATA *md,
krb5_crypto crypto)
make_pa_enc_challange(astgs_request_t r, krb5_crypto crypto)
{
krb5_context context = r->context;
METHOD_DATA *md = &r->outpadata;
PA_ENC_TS_ENC p;
unsigned char *buf;
size_t buf_size;
@@ -451,7 +499,7 @@ make_pa_enc_challange(krb5_context context, METHOD_DATA *md,
}
static krb5_error_code
pa_enc_chal_validate(kdc_request_t r, const PA_DATA *pa)
pa_enc_chal_validate(astgs_request_t r, const PA_DATA *pa)
{
krb5_data pepper1, pepper2, ts_data;
int invalidPassword = 0;
@@ -476,8 +524,8 @@ pa_enc_chal_validate(kdc_request_t r, const PA_DATA *pa)
&size);
if (ret) {
ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
_kdc_r_log(r, 2, "Failed to decode PA-DATA -- %s",
r->client_name);
_kdc_r_log(r, 4, "Failed to decode PA-DATA -- %s",
r->cname);
return ret;
}
@@ -527,7 +575,7 @@ pa_enc_chal_validate(kdc_request_t r, const PA_DATA *pa)
str = NULL;
_kdc_r_log(r, 2, "Failed to decrypt ENC-CHAL -- %s "
"(enctype %s) error %s",
r->client_name, str ? str : "unknown enctype", msg);
r->cname, str ? str : "unknown enctype", msg);
krb5_free_error_message(r->context, msg);
free(str);
@@ -542,8 +590,8 @@ pa_enc_chal_validate(kdc_request_t r, const PA_DATA *pa)
if(ret){
krb5_crypto_destroy(r->context, challangecrypto);
ret = KRB5KDC_ERR_PREAUTH_FAILED;
_kdc_r_log(r, 2, "Failed to decode PA-ENC-TS_ENC -- %s",
r->client_name);
_kdc_r_log(r, 4, "Failed to decode PA-ENC-TS_ENC -- %s",
r->cname);
continue;
}
@@ -561,7 +609,7 @@ pa_enc_chal_validate(kdc_request_t r, const PA_DATA *pa)
client_time,
(unsigned)labs(kdc_time - p.patimestamp),
r->context->max_skew,
r->client_name);
r->cname);
free_PA_ENC_TS_ENC(&p);
goto out;
@@ -569,8 +617,7 @@ pa_enc_chal_validate(kdc_request_t r, const PA_DATA *pa)
free_PA_ENC_TS_ENC(&p);
ret = make_pa_enc_challange(r->context, &r->outpadata,
challangecrypto);
ret = make_pa_enc_challange(r, challangecrypto);
krb5_crypto_destroy(r->context, challangecrypto);
if (ret)
goto out;
@@ -602,7 +649,7 @@ pa_enc_chal_validate(kdc_request_t r, const PA_DATA *pa)
}
static krb5_error_code
pa_enc_ts_validate(kdc_request_t r, const PA_DATA *pa)
pa_enc_ts_validate(astgs_request_t r, const PA_DATA *pa)
{
EncryptedData enc_data;
krb5_error_code ret;
@@ -619,8 +666,8 @@ pa_enc_ts_validate(kdc_request_t r, const PA_DATA *pa)
&len);
if (ret) {
ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
_kdc_r_log(r, 2, "Failed to decode PA-DATA -- %s",
r->client_name);
_kdc_r_log(r, 4, "Failed to decode PA-DATA -- %s",
r->cname);
goto out;
}
@@ -635,11 +682,11 @@ pa_enc_ts_validate(kdc_request_t r, const PA_DATA *pa)
if(estr == NULL)
_kdc_r_log(r, 2,
"No client key matching pa-data (%d) -- %s",
enc_data.etype, r->client_name);
enc_data.etype, r->cname);
else
_kdc_r_log(r, 2,
"No client key matching pa-data (%s) -- %s",
estr, r->client_name);
estr, r->cname);
free(estr);
free_EncryptedData(&enc_data);
goto out;
@@ -676,7 +723,7 @@ pa_enc_ts_validate(kdc_request_t r, const PA_DATA *pa)
str = NULL;
_kdc_r_log(r, 2, "Failed to decrypt PA-DATA -- %s "
"(enctype %s) error %s",
r->client_name, str ? str : "unknown enctype", msg);
r->cname, str ? str : "unknown enctype", msg);
krb5_free_error_message(r->context, msg);
free(str);
@@ -701,8 +748,8 @@ pa_enc_ts_validate(kdc_request_t r, const PA_DATA *pa)
krb5_data_free(&ts_data);
if(ret){
ret = KRB5KDC_ERR_PREAUTH_FAILED;
_kdc_r_log(r, 2, "Failed to decode PA-ENC-TS_ENC -- %s",
r->client_name);
_kdc_r_log(r, 4, "Failed to decode PA-ENC-TS_ENC -- %s",
r->cname);
goto out;
}
if (labs(kdc_time - p.patimestamp) > r->context->max_skew) {
@@ -717,7 +764,7 @@ pa_enc_ts_validate(kdc_request_t r, const PA_DATA *pa)
client_time,
(unsigned)labs(kdc_time - p.patimestamp),
r->context->max_skew,
r->client_name);
r->cname);
/*
* The following is needed to make windows clients to
@@ -739,8 +786,10 @@ pa_enc_ts_validate(kdc_request_t r, const PA_DATA *pa)
ret = krb5_enctype_to_string(r->context, pa_key->key.keytype, &str);
if (ret)
str = NULL;
_kdc_r_log(r, 3, "ENC-TS Pre-authentication succeeded -- %s using %s",
r->client_name, str ? str : "unknown enctype");
_kdc_r_log(r, 4, "ENC-TS Pre-authentication succeeded -- %s using %s",
r->cname, str ? str : "unknown enctype");
_kdc_audit_addkv((kdc_request_t)r, 0, "pa-etype", "%d",
(int)pa_key->key.keytype);
free(str);
ret = 0;
@@ -756,7 +805,7 @@ struct kdc_patypes {
unsigned int flags;
#define PA_ANNOUNCE 1
#define PA_REQ_FAST 2 /* only use inside fast */
krb5_error_code (*validate)(kdc_request_t, const PA_DATA *pa);
krb5_error_code (*validate)(astgs_request_t, const PA_DATA *pa);
};
static const struct kdc_patypes pat[] = {
@@ -796,10 +845,10 @@ static const struct kdc_patypes pat[] = {
};
static void
log_patypes(krb5_context context,
krb5_kdc_configuration *config,
METHOD_DATA *padata)
log_patypes(astgs_request_t r, METHOD_DATA *padata)
{
krb5_context context = r->context;
krb5_kdc_configuration *config = r->config;
struct rk_strpool *p = NULL;
char *str;
size_t n, m;
@@ -825,6 +874,8 @@ log_patypes(krb5_context context,
str = rk_strpoolcollect(p);
kdc_log(context, config, 4, "Client sent patypes: %s", str);
_kdc_audit_addkv((kdc_request_t)r, KDC_AUDIT_EATWHITE,
"client-pa", "%s", str);
free(str);
}
@@ -1309,18 +1360,28 @@ get_pa_etype_info_both(krb5_context context,
*
*/
static void
log_as_req(krb5_context context,
krb5_kdc_configuration *config,
krb5_enctype cetype,
krb5_enctype setype,
const KDC_REQ_BODY *b)
void
_log_astgs_req(astgs_request_t r, krb5_enctype setype)
{
krb5_context context = r->context;
const KDC_REQ_BODY *b = &r->req.req_body;
krb5_enctype cetype = r->reply_key.keytype;
krb5_error_code ret;
struct rk_strpool *p;
struct rk_strpool *s = NULL;
char *str;
char *cet;
char *set;
size_t i;
/*
* we are collecting ``p'' and ``s''. The former is a textual
* representation of the enctypes as strings which will be used
* for debugging. The latter is a terse comma separated list of
* the %d's of the enctypes to emit into our audit trail to
* conserve space in the logs.
*/
p = rk_strpoolprintf(NULL, "%s", "Client supported enctypes: ");
for (i = 0; i < b->etype.len; i++) {
@@ -1330,44 +1391,55 @@ log_as_req(krb5_context context,
free(str);
} else
p = rk_strpoolprintf(p, "%d", b->etype.val[i]);
if (p && i + 1 < b->etype.len)
p = rk_strpoolprintf(p, ", ");
if (p == NULL) {
kdc_log(context, config, 1, "out of memory");
rk_strpoolfree(s);
_kdc_r_log(r, 4, "out of memory");
return;
}
s = rk_strpoolprintf(s, "%d", b->etype.val[i]);
if (i + 1 < b->etype.len) {
p = rk_strpoolprintf(p, ", ");
s = rk_strpoolprintf(s, ",");
}
}
if (p == NULL)
p = rk_strpoolprintf(p, "no encryption types");
{
char *cet;
char *set;
str = rk_strpoolcollect(s);
if (str)
_kdc_audit_addkv((kdc_request_t)r, 0, "etypes", "%s", str);
free(str);
ret = krb5_enctype_to_string(context, cetype, &cet);
if(ret == 0) {
ret = krb5_enctype_to_string(context, setype, &set);
if (ret == 0) {
p = rk_strpoolprintf(p, ", using %s/%s", cet, set);
free(set);
}
free(cet);
ret = krb5_enctype_to_string(context, cetype, &cet);
if(ret == 0) {
ret = krb5_enctype_to_string(context, setype, &set);
if (ret == 0) {
p = rk_strpoolprintf(p, ", using %s/%s", cet, set);
free(set);
}
if (ret != 0)
p = rk_strpoolprintf(p, ", using enctypes %d/%d",
cetype, setype);
free(cet);
}
if (ret != 0)
p = rk_strpoolprintf(p, ", using enctypes %d/%d",
cetype, setype);
str = rk_strpoolcollect(p);
kdc_log(context, config, 3, "%s", str);
if (str)
_kdc_r_log(r, 4, "%s", str);
free(str);
_kdc_audit_addkv((kdc_request_t)r, 0, "etype", "%d/%d", cetype, setype);
{
char fixedstr[128];
unparse_flags(KDCOptions2int(b->kdc_options), asn1_KDCOptions_units(),
fixedstr, sizeof(fixedstr));
if(*fixedstr)
kdc_log(context, config, 3, "Requested flags: %s", fixedstr);
if (*fixedstr) {
_kdc_r_log(r, 4, "Requested flags: %s", fixedstr);
_kdc_audit_addkv((kdc_request_t)r, KDC_AUDIT_EATWHITE,
"flags", "%s", fixedstr);
}
}
}
@@ -1513,10 +1585,11 @@ kdc_check_flags(krb5_context context,
*/
krb5_boolean
_kdc_check_addresses(krb5_context context,
krb5_kdc_configuration *config,
HostAddresses *addresses, const struct sockaddr *from)
_kdc_check_addresses(astgs_request_t r, HostAddresses *addresses,
const struct sockaddr *from)
{
krb5_context context = r->context;
krb5_kdc_configuration *config = r->config;
krb5_error_code ret;
krb5_address addr;
krb5_boolean result;
@@ -1557,14 +1630,11 @@ _kdc_check_addresses(krb5_context context,
*
*/
krb5_error_code
_kdc_check_anon_policy (krb5_context context,
krb5_kdc_configuration *config,
hdb_entry_ex *client,
hdb_entry_ex *server)
_kdc_check_anon_policy(astgs_request_t r)
{
if (!config->allow_anonymous){
kdc_log(context, config, 2,
"Request for anonymous ticket denied by local policy");
if (!r->config->allow_anonymous) {
_kdc_r_log(r, 2,
"Request for anonymous ticket denied by local policy");
return KRB5KDC_ERR_POLICY;
}
@@ -1605,7 +1675,7 @@ send_pac_p(krb5_context context, KDC_REQ *req)
*/
static krb5_error_code
generate_pac(kdc_request_t r, Key *skey)
generate_pac(astgs_request_t r, Key *skey)
{
krb5_error_code ret;
krb5_pac p = NULL;
@@ -1613,8 +1683,8 @@ generate_pac(kdc_request_t r, Key *skey)
ret = _kdc_pac_generate(r->context, r->client, &p);
if (ret) {
_kdc_r_log(r, 1, "PAC generation failed for -- %s",
r->client_name);
_kdc_r_log(r, 4, "PAC generation failed for -- %s",
r->cname);
return ret;
}
if (p == NULL)
@@ -1627,8 +1697,8 @@ generate_pac(kdc_request_t r, Key *skey)
&data);
krb5_pac_free(r->context, p);
if (ret) {
_kdc_r_log(r, 1, "PAC signing failed for -- %s",
r->client_name);
_kdc_r_log(r, 4, "PAC signing failed for -- %s",
r->cname);
return ret;
}
@@ -1651,7 +1721,7 @@ _kdc_is_anonymous(krb5_context context, krb5_const_principal principal)
}
static int
require_preauth_p(kdc_request_t r)
require_preauth_p(astgs_request_t r)
{
return r->config->require_preauth
|| r->client->entry.flags.require_preauth
@@ -1664,7 +1734,7 @@ require_preauth_p(kdc_request_t r)
*/
static krb5_error_code
add_enc_pa_rep(kdc_request_t r)
add_enc_pa_rep(astgs_request_t r)
{
krb5_error_code ret;
krb5_crypto crypto;
@@ -1710,15 +1780,12 @@ add_enc_pa_rep(kdc_request_t r)
*/
krb5_error_code
_kdc_as_rep(kdc_request_t r,
krb5_data *reply,
const char *from,
struct sockaddr *from_addr,
int datagram_reply)
_kdc_as_rep(astgs_request_t r)
{
krb5_context context = r->context;
krb5_kdc_configuration *config = r->config;
KDC_REQ *req = &r->req;
const char *from = r->from;
KDC_REQ_BODY *b = NULL;
AS_REP rep;
KDCOptions f;
@@ -1730,6 +1797,7 @@ _kdc_as_rep(kdc_request_t r,
METHOD_DATA error_method;
const PA_DATA *pa;
krb5_boolean is_tgs;
const char *msg;
memset(&rep, 0, sizeof(rep));
error_method.len = 0;
@@ -1750,69 +1818,61 @@ _kdc_as_rep(kdc_request_t r,
if (f.canonicalize)
flags |= HDB_F_CANON;
if(b->sname == NULL){
if (b->sname == NULL) {
ret = KRB5KRB_ERR_GENERIC;
_kdc_set_e_text(r, "No server in request");
} else{
ret = _krb5_principalname2krb5_principal (context,
&r->server_princ,
*(b->sname),
b->realm);
if (ret == 0)
ret = krb5_unparse_name(context, r->server_princ, &r->server_name);
}
if (ret) {
kdc_log(context, config, 2,
"AS-REQ malformed server name from %s", from);
goto out;
}
if(b->cname == NULL){
ret = _krb5_principalname2krb5_principal(context, &r->server_princ,
*(b->sname), b->realm);
if (!ret)
ret = krb5_unparse_name(context, r->server_princ, &r->sname);
if (ret) {
kdc_log(context, config, 2,
"AS_REQ malformed server name from %s", from);
goto out;
}
if (b->cname == NULL) {
ret = KRB5KRB_ERR_GENERIC;
_kdc_set_e_text(r, "No client in request");
} else {
ret = _krb5_principalname2krb5_principal (context,
&r->client_princ,
*(b->cname),
b->realm);
if (ret)
goto out;
ret = krb5_unparse_name(context, r->client_princ, &r->client_name);
goto out;
}
ret = _krb5_principalname2krb5_principal(context, &r->client_princ,
*(b->cname), b->realm);
if (!ret)
ret = krb5_unparse_name(context, r->client_princ, &r->cname);
if (ret) {
kdc_log(context, config, 2,
"AS-REQ malformed client name from %s", from);
goto out;
}
kdc_log(context, config, 3, "AS-REQ %s from %s for %s",
r->client_name, from, r->server_name);
kdc_log(context, config, 4, "AS-REQ %s from %s for %s",
r->cname, r->from, r->sname);
is_tgs = krb5_principal_is_krbtgt(context, r->server_princ);
/*
*
*/
if (_kdc_is_anonymous(context, r->client_princ) &&
!_kdc_is_anon_request(&r->req)) {
!_kdc_is_anon_request(req)) {
kdc_log(context, config, 2, "Anonymous client w/o anonymous flag");
ret = KRB5KDC_ERR_BADOPTION;
goto out;
}
/*
*
*/
ret = _kdc_db_fetch(context, config, r->client_princ,
HDB_F_GET_CLIENT | flags, NULL,
&r->clientdb, &r->client);
if(ret == HDB_ERR_NOT_FOUND_HERE) {
switch (ret) {
case 0: /* Success */
break;
case HDB_ERR_NOT_FOUND_HERE:
kdc_log(context, config, 5, "client %s does not have secrets at this KDC, need to proxy",
r->client_name);
r->cname);
goto out;
} else if (ret == HDB_ERR_WRONG_REALM) {
case HDB_ERR_WRONG_REALM: {
char *fixed_client_name = NULL;
ret = krb5_unparse_name(context, r->client->entry.principal,
@@ -1821,25 +1881,20 @@ _kdc_as_rep(kdc_request_t r,
goto out;
}
kdc_log(context, config, 2, "WRONG_REALM - %s -> %s",
r->client_name, fixed_client_name);
kdc_log(context, config, 4, "WRONG_REALM - %s -> %s",
r->cname, fixed_client_name);
free(fixed_client_name);
ret = _kdc_fast_mk_error(context, r,
&error_method,
r->armor_crypto,
&req->req_body,
KRB5_KDC_ERR_WRONG_REALM,
NULL,
r->server_princ,
NULL,
ret = _kdc_fast_mk_error(r, &error_method, r->armor_crypto,
&req->req_body, KRB5_KDC_ERR_WRONG_REALM,
NULL, r->server_princ, NULL,
&r->client->entry.principal->realm,
NULL, NULL,
reply);
NULL, NULL, r->reply);
goto out;
} else if(ret){
const char *msg = krb5_get_error_message(context, ret);
kdc_log(context, config, 2, "UNKNOWN -- %s: %s", r->client_name, msg);
}
default:
msg = krb5_get_error_message(context, ret);
kdc_log(context, config, 4, "UNKNOWN -- %s: %s", r->cname, msg);
krb5_free_error_message(context, msg);
ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
goto out;
@@ -1847,13 +1902,16 @@ _kdc_as_rep(kdc_request_t r,
ret = _kdc_db_fetch(context, config, r->server_princ,
HDB_F_GET_SERVER | flags | (is_tgs ? HDB_F_GET_KRBTGT : 0),
NULL, NULL, &r->server);
if(ret == HDB_ERR_NOT_FOUND_HERE) {
switch (ret) {
case 0: /* Success */
break;
case HDB_ERR_NOT_FOUND_HERE:
kdc_log(context, config, 5, "target %s does not have secrets at this KDC, need to proxy",
r->server_name);
r->sname);
goto out;
} else if(ret){
const char *msg = krb5_get_error_message(context, ret);
kdc_log(context, config, 2, "UNKNOWN -- %s: %s", r->server_name, msg);
default:
msg = krb5_get_error_message(context, ret);
kdc_log(context, config, 4, "UNKNOWN -- %s: %s", r->sname, msg);
krb5_free_error_message(context, msg);
ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
goto out;
@@ -1870,17 +1928,14 @@ _kdc_as_rep(kdc_request_t r,
* decrypt.
*/
ret = _kdc_find_etype(context,
is_tgs ? config->tgt_use_strongest_session_key
: config->svc_use_strongest_session_key,
FALSE, r->client, r->client_princ,
ret = _kdc_find_etype(r, (is_tgs ? KFE_IS_TGS:0) | KFE_USE_CLIENT,
b->etype.val, b->etype.len,
&r->sessionetype, NULL, NULL);
if (ret) {
kdc_log(context, config, 2,
"Client (%s) from %s has no common enctypes with KDC "
"to use for the session key",
r->client_name, from);
r->cname, from);
goto out;
}
@@ -1891,7 +1946,7 @@ _kdc_as_rep(kdc_request_t r,
if(req->padata){
unsigned int n;
log_patypes(context, config, req->padata);
log_patypes(r, req->padata);
/* Check if preauth matching */
@@ -1902,10 +1957,11 @@ _kdc_as_rep(kdc_request_t r,
continue;
kdc_log(context, config, 5,
"Looking for %s pa-data -- %s", pat[n].name, r->client_name);
"Looking for %s pa-data -- %s", pat[n].name, r->cname);
i = 0;
pa = _kdc_find_padata(req, &i, pat[n].type);
if (pa) {
_kdc_audit_addkv((kdc_request_t)r, 0, "pa", "%s", pat[n].name);
ret = pat[n].validate(r, pa);
if (ret != 0) {
krb5_error_code ret2;
@@ -1915,10 +1971,9 @@ _kdc_as_rep(kdc_request_t r,
/*
* If there is a client key, send ETYPE_INFO{,2}
*/
ret2 = _kdc_find_etype(context,
config->preauth_use_strongest_session_key,
TRUE, r->client, r->client_princ, b->etype.val,
b->etype.len, NULL, &ckey, &default_salt);
ret2 = _kdc_find_etype(r, KFE_IS_PREAUTH|KFE_USE_CLIENT,
b->etype.val, b->etype.len,
NULL, &ckey, &default_salt);
if (ret2 == 0) {
ret2 = get_pa_etype_info_both(context, config, &b->etype,
&error_method, ckey, !default_salt);
@@ -1929,7 +1984,7 @@ _kdc_as_rep(kdc_request_t r,
}
kdc_log(context, config, 3,
"%s pre-authentication succeeded -- %s",
pat[n].name, r->client_name);
pat[n].name, r->cname);
found_pa = 1;
r->et.flags.pre_authent = 1;
}
@@ -1953,11 +2008,9 @@ _kdc_as_rep(kdc_request_t r,
/*
* If there is a client key, send ETYPE_INFO{,2}
*/
ret = _kdc_find_etype(context,
config->preauth_use_strongest_session_key, TRUE,
r->client, r->client_princ,
b->etype.val, b->etype.len, NULL,
&ckey, &default_salt);
ret = _kdc_find_etype(r, KFE_IS_PREAUTH|KFE_USE_CLIENT,
b->etype.val, b->etype.len,
NULL, &ckey, &default_salt);
if (ret == 0) {
ret = get_pa_etype_info_both(context, config, &b->etype,
&error_method, ckey, !default_salt);
@@ -1987,7 +2040,7 @@ _kdc_as_rep(kdc_request_t r,
}
if (r->clientdb->hdb_auth_status) {
r->clientdb->hdb_auth_status(context, r->clientdb, r->client,
r->clientdb->hdb_auth_status(context, r->clientdb, r->client,
HDB_AUTH_SUCCESS);
}
@@ -1996,14 +2049,12 @@ _kdc_as_rep(kdc_request_t r,
* with in a preauth mech.
*/
ret = _kdc_check_access(context, config, r->client, r->client_name,
r->server, r->server_name,
req, &error_method);
ret = _kdc_check_access(r, req, &error_method);
if(ret)
goto out;
if (_kdc_is_anon_request(&r->req)) {
ret = _kdc_check_anon_policy(context, config, r->client, r->server);
ret = _kdc_check_anon_policy(r);
if (ret) {
_kdc_set_e_text(r, "Anonymous ticket requests are disabled");
goto out;
@@ -2018,7 +2069,7 @@ _kdc_as_rep(kdc_request_t r,
*/
ret = _kdc_get_preferred_key(context, config,
r->server, r->server_name,
r->server, r->sname,
&setype, &skey);
if(ret)
goto out;
@@ -2094,7 +2145,7 @@ _kdc_as_rep(kdc_request_t r,
}
/* check for valid set of addresses */
if(!_kdc_check_addresses(context, config, b->addresses, from_addr)) {
if (!_kdc_check_addresses(r, b->addresses, r->addr)) {
_kdc_set_e_text(r, "Bad address list in requested");
ret = KRB5KRB_AP_ERR_BADADDR;
goto out;
@@ -2274,8 +2325,9 @@ _kdc_as_rep(kdc_request_t r,
generate_pac(r, skey);
}
_kdc_log_timestamp(context, config, "AS-REQ", r->et.authtime, r->et.starttime,
r->et.endtime, r->et.renew_till);
_kdc_log_timestamp(r, "AS-REQ", r->et.authtime,
r->et.starttime, r->et.endtime,
r->et.renew_till);
{
krb5_principal client_principal;
@@ -2299,7 +2351,7 @@ _kdc_as_rep(kdc_request_t r,
goto out;
}
log_as_req(context, config, r->reply_key.keytype, setype, b);
_log_astgs_req(r, setype);
/*
* We always say we support FAST/enc-pa-rep
@@ -2317,7 +2369,7 @@ _kdc_as_rep(kdc_request_t r,
ret = add_enc_pa_rep(r);
if (ret) {
const char *msg = krb5_get_error_message(r->context, ret);
msg = krb5_get_error_message(r->context, ret);
_kdc_r_log(r, 1, "add_enc_pa_rep failed: %s: %d", msg, ret);
krb5_free_error_message(r->context, msg);
goto out;
@@ -2330,17 +2382,18 @@ _kdc_as_rep(kdc_request_t r,
ret = _kdc_encode_reply(context, config,
r->armor_crypto, req->req_body.nonce,
&rep, &r->et, &r->ek, setype, r->server->entry.kvno,
&skey->key, r->client->entry.kvno,
&r->reply_key, 0, &r->e_text, reply);
&rep, &r->et, &r->ek, setype,
r->server->entry.kvno, &skey->key,
r->client->entry.kvno,
&r->reply_key, 0, &r->e_text, r->reply);
if (ret)
goto out;
/*
* Check if message too large
*/
if (datagram_reply && reply->length > config->max_datagram_reply_length) {
krb5_data_free(reply);
if (r->datagram_reply && r->reply->length > config->max_datagram_reply_length) {
krb5_data_free(r->reply);
ret = KRB5KRB_ERR_RESPONSE_TOO_BIG;
_kdc_set_e_text(r, "Reply packet too large");
}
@@ -2351,23 +2404,20 @@ out:
/*
* In case of a non proxy error, build an error message.
*/
if (ret != 0 && ret != HDB_ERR_NOT_FOUND_HERE && reply->length == 0) {
ret = _kdc_fast_mk_error(context, r,
&error_method,
r->armor_crypto,
&req->req_body,
ret, r->e_text,
r->server_princ,
r->client_princ ?
&r->client_princ->name : NULL,
r->client_princ ?
&r->client_princ->realm : NULL,
NULL, NULL,
reply);
if (ret)
goto out2;
}
out2:
if (ret != 0 && ret != HDB_ERR_NOT_FOUND_HERE && r->reply->length == 0)
/* We don't want to clobber the original error here... */
_kdc_fast_mk_error(r, &error_method,
r->armor_crypto,
&req->req_body,
ret, r->e_text,
r->server_princ,
r->client_princ ?
&r->client_princ->name : NULL,
r->client_princ ?
&r->client_princ->realm : NULL,
NULL, NULL,
r->reply);
free_EncTicketPart(&r->et);
free_EncKDCRepPart(&r->ek);
free_KDCFastState(&r->fast);
@@ -2380,18 +2430,10 @@ out2:
krb5_free_principal(context, r->client_princ);
r->client_princ = NULL;
}
if (r->client_name) {
free(r->client_name);
r->client_name = NULL;
}
if (r->server_princ){
krb5_free_principal(context, r->server_princ);
r->server_princ = NULL;
}
if (r->server_name) {
free(r->server_name);
r->server_name = NULL;
}
if (r->client)
_kdc_free_ent(context, r->client);
if (r->server)

View File

@@ -757,9 +757,7 @@ fix_transited_encoding(krb5_context context,
static krb5_error_code
tgs_make_reply(krb5_context context,
krb5_kdc_configuration *config,
KDC_REQ_BODY *b,
tgs_make_reply(astgs_request_t r,
krb5_const_principal tgt_name,
const EncTicketPart *tgt,
const krb5_keyblock *replykey,
@@ -770,7 +768,6 @@ tgs_make_reply(krb5_context context,
AuthorizationData *auth_data,
hdb_entry_ex *server,
krb5_principal server_principal,
const char *server_name,
hdb_entry_ex *client,
krb5_principal client_principal,
const char *tgt_realm,
@@ -778,10 +775,13 @@ tgs_make_reply(krb5_context context,
krb5_enctype krbtgt_etype,
krb5_principals spp,
const krb5_data *rspac,
const METHOD_DATA *enc_pa_data,
const char **e_text,
krb5_data *reply)
const METHOD_DATA *enc_pa_data)
{
krb5_context context = r->context;
krb5_kdc_configuration *config = r->config;
KDC_REQ_BODY *b = &r->req.req_body;
const char **e_text = &r->e_text;
krb5_data *reply = r->reply;
KDC_REP rep;
EncKDCRepPart ek;
EncTicketPart et;
@@ -988,14 +988,14 @@ tgs_make_reply(krb5_context context,
ek.srealm = rep.ticket.realm;
ek.sname = rep.ticket.sname;
_kdc_log_timestamp(context, config, "TGS-REQ", et.authtime, et.starttime,
_kdc_log_timestamp(r, "TGS-REQ", et.authtime, et.starttime,
et.endtime, et.renew_till);
/* Don't sign cross realm tickets, they can't be checked anyway */
{
char *r = get_krbtgt_realm(&ek.sname);
char *realm = get_krbtgt_realm(&ek.sname);
if (r == NULL || strcmp(r, ek.srealm) == 0) {
if (realm == NULL || strcmp(realm, ek.srealm) == 0) {
ret = _kdc_add_KRB5SignedPath(context,
config,
krbtgt,
@@ -1046,6 +1046,9 @@ tgs_make_reply(krb5_context context,
if (is_weak)
krb5_enctype_disable(context, serverkey->keytype);
r->reply_key.keytype = replykey->keytype;
_log_astgs_req(r, serverkey->keytype);
out:
free_TGS_REP(&rep);
free_TransitedEncoding(&et.transited);
@@ -1182,9 +1185,7 @@ need_referral(krb5_context context, krb5_kdc_configuration *config,
}
static krb5_error_code
tgs_parse_request(krb5_context context,
krb5_kdc_configuration *config,
KDC_REQ_BODY *b,
tgs_parse_request(astgs_request_t r,
const PA_DATA *tgs_req,
hdb_entry_ex **krbtgt,
krb5_enctype *krbtgt_etype,
@@ -1198,6 +1199,9 @@ tgs_parse_request(krb5_context context,
krb5_keyblock **replykey,
int *rk_is_subkey)
{
krb5_context context = r->context;
krb5_kdc_configuration *config = r->config;
KDC_REQ_BODY *b = &r->req.req_body;
static char failed[] = "<unparse_name failed>";
krb5_ap_req ap_req;
krb5_error_code ret;
@@ -1544,21 +1548,21 @@ eout:
}
static krb5_error_code
tgs_build_reply(krb5_context context,
krb5_kdc_configuration *config,
KDC_REQ *req,
KDC_REQ_BODY *b,
tgs_build_reply(astgs_request_t priv,
hdb_entry_ex *krbtgt,
krb5_enctype krbtgt_etype,
const krb5_keyblock *replykey,
int rk_is_subkey,
krb5_ticket *ticket,
krb5_data *reply,
const char *from,
const char **e_text,
AuthorizationData **auth_data,
const struct sockaddr *from_addr)
{
krb5_context context = priv->context;
krb5_kdc_configuration *config = priv->config;
KDC_REQ *req = &priv->req;
KDC_REQ_BODY *b = &priv->req.req_body;
const char *from = priv->from;
krb5_error_code ret, ret2;
krb5_principal cp = NULL, sp = NULL, rsp = NULL, tp = NULL, dp = NULL;
krb5_principal krbtgt_out_principal = NULL;
@@ -1667,13 +1671,15 @@ tgs_build_reply(krb5_context context,
}
_krb5_principalname2krb5_principal(context, &sp, *s, r);
ret = krb5_unparse_name(context, sp, &spn);
ret = krb5_unparse_name(context, sp, &priv->sname);
if (ret)
goto out;
spn = priv->sname;
_krb5_principalname2krb5_principal(context, &cp, tgt->cname, tgt->crealm);
ret = krb5_unparse_name(context, cp, &cpn);
ret = krb5_unparse_name(context, cp, &priv->cname);
if (ret)
goto out;
cpn = priv->cname;
unparse_flags (KDCOptions2int(b->kdc_options),
asn1_KDCOptions_units(),
opt_str, sizeof(opt_str));
@@ -1692,7 +1698,7 @@ tgs_build_reply(krb5_context context,
server_lookup:
ret = _kdc_db_fetch(context, config, sp, HDB_F_GET_SERVER | flags,
NULL, NULL, &server);
priv->server = server;
if (ret == HDB_ERR_NOT_FOUND_HERE) {
kdc_log(context, config, 5, "target %s does not have secrets at this KDC, need to proxy", spn);
goto out;
@@ -1714,11 +1720,12 @@ server_lookup:
ref_realm, NULL);
if (ret)
goto out;
free(spn);
spn = NULL;
ret = krb5_unparse_name(context, sp, &spn);
free(priv->sname);
priv->sname = NULL;
ret = krb5_unparse_name(context, sp, &priv->sname);
if (ret)
goto out;
spn = priv->sname;
goto server_lookup;
} else if (ret) {
@@ -1753,11 +1760,12 @@ server_lookup:
sp = NULL;
krb5_make_principal(context, &sp, r,
KRB5_TGS_NAME, ref_realm, NULL);
free(spn);
spn = NULL;
ret = krb5_unparse_name(context, sp, &spn);
free(priv->sname);
priv->sname = NULL;
ret = krb5_unparse_name(context, sp, &priv->sname);
if (ret)
goto out;
spn = priv->sname;
goto server_lookup;
}
} else if (need_referral(context, config, &b->kdc_options, sp, &realms)) {
@@ -1770,13 +1778,14 @@ server_lookup:
sp = NULL;
krb5_make_principal(context, &sp, r, KRB5_TGS_NAME,
realms[0], NULL);
free(spn);
spn = NULL;
ret = krb5_unparse_name(context, sp, &spn);
free(priv->sname);
priv->sname = NULL;
ret = krb5_unparse_name(context, sp, &priv->sname);
if (ret) {
krb5_free_host_realm(context, realms);
goto out;
}
spn = priv->sname;
free(ref_realm);
ref_realm = strdup(realms[0]);
@@ -1832,13 +1841,9 @@ server_lookup:
} else {
Key *skey;
ret = _kdc_find_etype(context,
krb5_principal_is_krbtgt(context, sp) ?
config->tgt_use_strongest_session_key :
config->svc_use_strongest_session_key, FALSE,
server, server->entry.principal,
b->etype.val, b->etype.len, &etype,
NULL,
ret = _kdc_find_etype(priv, krb5_principal_is_krbtgt(context, sp)
? KFE_IS_TGS : 0,
b->etype.val, b->etype.len, &etype, NULL,
NULL);
if(ret) {
kdc_log(context, config, 2,
@@ -1956,6 +1961,7 @@ server_lookup:
ret = _kdc_db_fetch(context, config, cp, HDB_F_GET_CLIENT | flags,
NULL, &clientdb, &client);
priv->client = client;
if(ret == HDB_ERR_NOT_FOUND_HERE) {
/* This is OK, we are just trying to find out if they have
* been disabled or deleted in the meantime, missing secrets
@@ -2332,6 +2338,7 @@ server_lookup:
goto out;
}
_kdc_audit_addkv((kdc_request_t)priv, 0, "impersonatee", tpn);
kdc_log(context, config, 3, "constrained delegation for %s "
"from %s (%s) to %s", tpn, cpn, dpn, spn);
}
@@ -2357,7 +2364,7 @@ server_lookup:
}
/* check for valid set of addresses */
if(!_kdc_check_addresses(context, config, tgt->caddr, from_addr)) {
if (!_kdc_check_addresses(priv, tgt->caddr, from_addr)) {
ret = KRB5KRB_AP_ERR_BADADDR;
kdc_log(context, config, 2, "Request from wrong address");
goto out;
@@ -2365,7 +2372,7 @@ server_lookup:
/* check local and per-principal anonymous ticket issuance policy */
if (is_anon_tgs_request_p(b, tgt)) {
ret = _kdc_check_anon_policy(context, config, client, server);
ret = _kdc_check_anon_policy(priv);
if (ret)
goto out;
}
@@ -2408,9 +2415,7 @@ server_lookup:
*
*/
ret = tgs_make_reply(context,
config,
b,
ret = tgs_make_reply(priv,
tp,
tgt,
replykey,
@@ -2421,7 +2426,6 @@ server_lookup:
*auth_data,
server,
rsp,
spn,
client,
cp,
tgt_realm,
@@ -2429,15 +2433,11 @@ server_lookup:
tkey_sign->key.keytype,
spp,
&rspac,
&enc_pa_data,
e_text,
reply);
&enc_pa_data);
out:
if (tpn != cpn)
free(tpn);
free(spn);
free(cpn);
free(dpn);
free(krbtgt_out_n);
_krb5_free_capath(context, capath);
@@ -2472,14 +2472,15 @@ out:
*/
krb5_error_code
_kdc_tgs_rep(krb5_context context,
krb5_kdc_configuration *config,
KDC_REQ *req,
krb5_data *data,
const char *from,
struct sockaddr *from_addr,
int datagram_reply)
_kdc_tgs_rep(astgs_request_t r)
{
krb5_context context = r->context;
krb5_kdc_configuration *config = r->config;
KDC_REQ *req = &r->req;
krb5_data *data = r->reply;
const char *from = r->from;
struct sockaddr *from_addr = r->addr;
int datagram_reply = r->datagram_reply;
AuthorizationData *auth_data = NULL;
krb5_error_code ret;
int i = 0;
@@ -2511,8 +2512,7 @@ _kdc_tgs_rep(krb5_context context,
"TGS-REQ from %s without PA-TGS-REQ", from);
goto out;
}
ret = tgs_parse_request(context, config,
&req->req_body, tgs_req,
ret = tgs_parse_request(r, tgs_req,
&krbtgt,
&krbtgt_etype,
&ticket,
@@ -2539,17 +2539,12 @@ _kdc_tgs_rep(krb5_context context,
}
ret = tgs_build_reply(context,
config,
req,
&req->req_body,
ret = tgs_build_reply(r,
krbtgt,
krbtgt_etype,
replykey,
rk_is_subkey,
ticket,
data,
from,
&e_text,
&auth_data,
from_addr);
@@ -2576,7 +2571,7 @@ out:
kdc_log(context, config, 5, "tgs-req: sending error: %d to client", ret);
ret = _kdc_fast_mk_error(context, NULL,
ret = _kdc_fast_mk_error(r,
&error_method,
NULL,
NULL,

View File

@@ -392,13 +392,15 @@ get_dh_param(krb5_context context,
}
krb5_error_code
_kdc_pk_rd_padata(krb5_context context,
krb5_kdc_configuration *config,
const KDC_REQ *req,
_kdc_pk_rd_padata(astgs_request_t priv,
const PA_DATA *pa,
hdb_entry_ex *client,
pk_client_params **ret_params)
{
/* XXXrcd: we use priv vs r due to a conflict */
krb5_context context = priv->context;
krb5_kdc_configuration *config = priv->config;
const KDC_REQ *req = &priv->req;
hdb_entry_ex *client = priv->client;
pk_client_params *cp;
krb5_error_code ret;
heim_oid eContentType = { 0, NULL }, contentInfoOid = { 0, NULL };
@@ -1124,17 +1126,16 @@ pk_mk_pa_reply_dh(krb5_context context,
*/
krb5_error_code
_kdc_pk_mk_pa_reply(krb5_context context,
krb5_kdc_configuration *config,
pk_client_params *cp,
const hdb_entry_ex *client,
krb5_enctype sessionetype,
const KDC_REQ *req,
const krb5_data *req_buffer,
krb5_keyblock *reply_key,
krb5_keyblock *sessionkey,
METHOD_DATA *md)
_kdc_pk_mk_pa_reply(astgs_request_t r, pk_client_params *cp)
{
krb5_context context = r->context;
krb5_kdc_configuration *config = r->config;
krb5_enctype sessionetype = r->sessionetype;
const KDC_REQ *req = &r->req;
const krb5_data *req_buffer = &r->request;
krb5_keyblock *reply_key = &r->reply_key;
krb5_keyblock *sessionkey = &r->session_key;
METHOD_DATA *md = &r->outpadata;
krb5_error_code ret;
void *buf = NULL;
size_t len = 0, size = 0;
@@ -1663,13 +1664,14 @@ out:
}
krb5_error_code
_kdc_pk_check_client(krb5_context context,
krb5_kdc_configuration *config,
HDB *clientdb,
hdb_entry_ex *client,
_kdc_pk_check_client(astgs_request_t r,
pk_client_params *cp,
char **subject_name)
{
krb5_context context = r->context;
krb5_kdc_configuration *config = r->config;
HDB *clientdb = r->clientdb;
hdb_entry_ex *client = r->client;
const HDB_Ext_PKINIT_acl *acl;
const HDB_Ext_PKINIT_cert *pc;
krb5_error_code ret;

View File

@@ -33,11 +33,174 @@
*/
#include "kdc_locl.h"
#include <vis.h>
/*
*
*/
#undef __attribute__
#define __attribute__(x)
/*
* append_token adds a token which is optionally a kv-pair and it
* also optionally eats the whitespace. If k == NULL, then it's
* not a kv-pair.
*/
void
_kdc_audit_addkv(kdc_request_t r, int flags, const char *k,
const char *fmt, ...)
__attribute__ ((__format__ (__printf__, 4, 5)))
{
va_list ap;
heim_string_t str;
size_t i,j;
char *buf1;
char *buf2;
char *buf3;
va_start(ap, fmt);
vasprintf(&buf1, fmt, ap);
va_end(ap);
if (!buf1)
return;
j = asprintf(&buf2, "%s=%s", k, buf1);
free(buf1);
if (!buf2)
return;
/* We optionally eat the whitespace. */
if (flags | KDC_AUDIT_EATWHITE) {
for (i=0, j=0; buf2[i]; i++)
if (buf2[i] != ' ' && buf2[i] != '\t')
buf2[j++] = buf2[i];
buf2[j] = '\0';
}
if (flags | KDC_AUDIT_VIS) {
buf3 = malloc((j + 1) * 4 + 1);
strvisx(buf3, buf2, j, VIS_OCTAL);
free(buf2);
} else
buf3 = buf2;
str = heim_string_create(buf3);
free(buf3);
if (!str)
return;
heim_array_append_value(r->kv, str);
}
void
_kdc_audit_addkv_timediff(kdc_request_t r, const char *k,
const struct timeval *start,
const struct timeval *end)
{
time_t sec;
int usec;
const char *sign = "";
if (end->tv_sec > start->tv_sec ||
(end->tv_sec == start->tv_sec && end->tv_usec >= start->tv_usec)) {
sec = end->tv_sec - start->tv_sec;
usec = end->tv_usec - start->tv_usec;
} else {
sec = start->tv_sec - end->tv_sec;
usec = start->tv_usec - end->tv_usec;
sign = "-";
}
if (usec < 0) {
usec += 1000000;
sec -= 1;
}
_kdc_audit_addkv(r, 0, k, "%s%ld.%06d", sign, sec, usec);
}
void
_kdc_audit_trail(kdc_request_t r, krb5_error_code ret)
{
const char *retval;
char kvbuf[1024];
size_t nelem;
size_t i, j;
#define CASE(x) case x : retval = #x; break
switch (ret) {
CASE(ENOMEM);
CASE(HDB_ERR_NOT_FOUND_HERE);
CASE(HDB_ERR_WRONG_REALM);
CASE(HDB_ERR_EXISTS);
CASE(HDB_ERR_KVNO_NOT_FOUND);
CASE(HDB_ERR_NOENTRY);
CASE(HDB_ERR_NO_MKEY);
CASE(KRB5KDC_ERR_BADOPTION);
CASE(KRB5KDC_ERR_CANNOT_POSTDATE);
CASE(KRB5KDC_ERR_CLIENT_NOTYET);
CASE(KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN);
CASE(KRB5KDC_ERR_ETYPE_NOSUPP);
CASE(KRB5KDC_ERR_KEY_EXPIRED);
CASE(KRB5KDC_ERR_NAME_EXP);
CASE(KRB5KDC_ERR_NEVER_VALID);
CASE(KRB5KDC_ERR_NONE);
CASE(KRB5KDC_ERR_NULL_KEY);
CASE(KRB5KDC_ERR_PADATA_TYPE_NOSUPP);
CASE(KRB5KDC_ERR_POLICY);
CASE(KRB5KDC_ERR_PREAUTH_FAILED);
CASE(KRB5KDC_ERR_PREAUTH_REQUIRED);
CASE(KRB5KDC_ERR_SERVER_NOMATCH);
CASE(KRB5KDC_ERR_SERVICE_EXP);
CASE(KRB5KDC_ERR_SERVICE_NOTYET);
CASE(KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN);
CASE(KRB5KDC_ERR_TRTYPE_NOSUPP);
CASE(KRB5KRB_ERR_RESPONSE_TOO_BIG);
case 0:
retval = "SUCCESS";
break;
default:
retval = "UNKNOWN";
break;
}
/* Let's save a few bytes */
#define PREFIX "KRB5KDC_"
if (!strncmp(PREFIX, retval, strlen(PREFIX)))
retval += strlen(PREFIX);
#undef PREFIX
/* Calculate metrics and add them */
_kdc_audit_addkv_timediff(r, "elapsed", &r->tv_start, &r->tv_end);
if (r->e_text)
_kdc_audit_addkv(r, KDC_AUDIT_VIS, "e-text", r->e_text);
nelem = heim_array_get_length(r->kv);
for (i=0, j=0; i < nelem; i++) {
heim_string_t s;
const char *kvpair;
s = heim_array_get_value(r->kv, i);
/* XXXrcd: in string.c the check? */
kvpair = heim_string_get_utf8(s);
if (j < sizeof(kvbuf) - 1)
kvbuf[j++] = ' ';
for (; *kvpair && j < sizeof(kvbuf) - 1; j++)
kvbuf[j] = *kvpair++;
}
kvbuf[j] = '\0';
kdc_log(r->context, r->config, 3, "%s %s %s %s %s%s",
r->reqtype, retval, r->from, r->cname,
r->sname, kvbuf);
}
void
krb5_kdc_update_time(struct timeval *tv)
{
@@ -47,89 +210,86 @@ krb5_kdc_update_time(struct timeval *tv)
_kdc_now = *tv;
}
#define EXTEND_REQUEST_T(LHS, RHS) do { \
RHS = realloc(LHS, sizeof(*RHS)); \
if (!RHS) \
return krb5_enomem((LHS)->context); \
LHS = (void *)RHS; \
memset(((char *)LHS) + sizeof(*LHS), \
0x0, \
sizeof(*RHS) - sizeof(*LHS)); \
} while (0)
static krb5_error_code
kdc_as_req(krb5_context context,
krb5_kdc_configuration *config,
krb5_data *req_buffer,
krb5_data *reply,
const char *from,
struct sockaddr *addr,
int datagram_reply,
int *claim)
kdc_as_req(kdc_request_t *rptr, int *claim)
{
struct kdc_request_desc r;
astgs_request_t r;
krb5_error_code ret;
size_t len;
memset(&r, 0, sizeof(r));
/* We must free things in the extensions */
EXTEND_REQUEST_T(*rptr, r);
ret = decode_AS_REQ(req_buffer->data, req_buffer->length, &r.req, &len);
ret = decode_AS_REQ(r->request.data, r->request.length, &r->req, &len);
if (ret)
return ret;
r.context = context;
r.config = config;
r.request.data = req_buffer->data;
r.request.length = req_buffer->length;
r->reqtype = "AS-REQ";
r->use_request_t = 1;
*claim = 1;
ret = _kdc_as_rep(&r, reply, from, addr, datagram_reply);
free_AS_REQ(&r.req);
ret = _kdc_as_rep(r);
free_AS_REQ(&r->req);
return ret;
}
static krb5_error_code
kdc_tgs_req(krb5_context context,
krb5_kdc_configuration *config,
krb5_data *req_buffer,
krb5_data *reply,
const char *from,
struct sockaddr *addr,
int datagram_reply,
int *claim)
kdc_tgs_req(kdc_request_t *rptr, int *claim)
{
astgs_request_t r;
krb5_error_code ret;
KDC_REQ req;
size_t len;
ret = decode_TGS_REQ(req_buffer->data, req_buffer->length, &req, &len);
/* We must free things in the extensions */
EXTEND_REQUEST_T(*rptr, r);
ret = decode_TGS_REQ(r->request.data, r->request.length, &r->req, &len);
if (ret)
return ret;
r->reqtype = "TGS-REQ";
r->use_request_t = 1;
*claim = 1;
ret = _kdc_tgs_rep(context, config, &req, reply,
from, addr, datagram_reply);
free_TGS_REQ(&req);
ret = _kdc_tgs_rep(r);
free_TGS_REQ(&r->req);
return ret;
}
#ifdef DIGEST
static krb5_error_code
kdc_digest(krb5_context context,
krb5_kdc_configuration *config,
krb5_data *req_buffer,
krb5_data *reply,
const char *from,
struct sockaddr *addr,
int datagram_reply,
int *claim)
kdc_digest(kdc_request_t *rptr, int *claim)
{
kdc_request_t r;
DigestREQ digestreq;
krb5_error_code ret;
size_t len;
ret = decode_DigestREQ(req_buffer->data, req_buffer->length,
r = *rptr;
ret = decode_DigestREQ(r->request.data, r->request.length,
&digestreq, &len);
if (ret)
return ret;
r->use_request_t = 0;
*claim = 1;
ret = _kdc_do_digest(context, config, &digestreq, reply, from, addr);
ret = _kdc_do_digest(r->context, r->config, &digestreq,
r->reply, r->from, r->addr);
free_DigestREQ(&digestreq);
return ret;
}
@@ -139,15 +299,15 @@ kdc_digest(krb5_context context,
#ifdef KX509
static krb5_error_code
kdc_kx509(krb5_context context,
krb5_kdc_configuration *config,
krb5_data *req_buffer,
krb5_data *reply,
const char *from,
struct sockaddr *addr,
int datagram_reply,
int *claim)
kdc_kx509(kdc_request_t *rptr, int *claim)
{
kdc_request_t r = *rptr;
krb5_context context = r->context;
krb5_kdc_configuration *config = r->config;
krb5_data *req_buffer = &r->request;
krb5_data *reply = r->reply;
const char *from = r->from;
struct sockaddr *addr = r->addr;
Kx509Request kx509req;
krb5_error_code ret;
@@ -156,6 +316,7 @@ kdc_kx509(krb5_context context,
if (ret)
return ret;
r->use_request_t = 0;
*claim = 1;
ret = _kdc_do_kx509(context, config, &kx509req, reply, from, addr);
@@ -178,6 +339,70 @@ static struct krb5_kdc_service services[] = {
{ 0, NULL }
};
static int
process_request(krb5_context context,
krb5_kdc_configuration *config,
unsigned int krb5_only,
unsigned char *buf,
size_t len,
krb5_data *reply,
krb5_boolean *prependlength,
const char *from,
struct sockaddr *addr,
int datagram_reply)
{
kdc_request_t r;
krb5_error_code ret;
unsigned int i;
int claim = 0;
heim_auto_release_t pool = heim_auto_release_create();
r = calloc(sizeof(*r), 1);
if (!r)
return krb5_enomem(context);
r->context = context;
r->config = config;
r->from = from;
r->request.data = buf;
r->request.length = len;
r->datagram_reply = datagram_reply;
r->reply = reply;
r->kv = heim_array_create();
if (!r->kv) {
free(r);
return krb5_enomem(context);
}
gettimeofday(&r->tv_start, NULL);
for (i = 0; services[i].process != NULL; i++) {
if (krb5_only && (services[i].flags & KS_KRB5) == 0)
continue;
ret = (*services[i].process)(&r, &claim);
if (claim) {
if (prependlength && services[i].flags & KS_NO_LENGTH)
*prependlength = 0;
if (r->use_request_t) {
gettimeofday(&r->tv_end, NULL);
_kdc_audit_trail(r, ret);
free(r->cname);
free(r->sname);
free(r->e_text_buf);
heim_release(r->kv);
}
heim_release(pool);
return ret;
}
}
heim_release(pool);
return -1;
}
/*
* handle the request in `buf, len', from `addr' (or `from' as a string),
* sending a reply in `reply'.
@@ -194,33 +419,10 @@ krb5_kdc_process_request(krb5_context context,
struct sockaddr *addr,
int datagram_reply)
{
krb5_error_code ret;
unsigned int i;
krb5_data req_buffer;
int claim = 0;
heim_auto_release_t pool = heim_auto_release_create();
req_buffer.data = buf;
req_buffer.length = len;
for (i = 0; services[i].process != NULL; i++) {
ret = (*services[i].process)(context, config, &req_buffer,
reply, from, addr, datagram_reply,
&claim);
if (claim) {
if (services[i].flags & KS_NO_LENGTH)
*prependlength = 0;
heim_release(pool);
return ret;
}
}
heim_release(pool);
return -1;
return process_request(context, config, 0, buf, len, reply, prependlength,
from, addr, datagram_reply);
}
/*
* handle the request in `buf, len', from `addr' (or `from' as a string),
* sending a reply in `reply'.
@@ -238,27 +440,11 @@ krb5_kdc_process_krb5_request(krb5_context context,
struct sockaddr *addr,
int datagram_reply)
{
krb5_error_code ret;
unsigned int i;
krb5_data req_buffer;
int claim = 0;
req_buffer.data = buf;
req_buffer.length = len;
for (i = 0; services[i].process != NULL; i++) {
if ((services[i].flags & KS_KRB5) == 0)
continue;
ret = (*services[i].process)(context, config, &req_buffer,
reply, from, addr, datagram_reply,
&claim);
if (claim)
return ret;
}
return -1;
return process_request(context, config, 1, buf, len, reply, NULL,
from, addr, datagram_reply);
}
/*
*
*/

View File

@@ -187,13 +187,14 @@ check(krb5_context context, const void *plug, void *plugctx, void *userctx)
krb5_error_code
_kdc_check_access(krb5_context context,
krb5_kdc_configuration *config,
hdb_entry_ex *client_ex, const char *client_name,
hdb_entry_ex *server_ex, const char *server_name,
KDC_REQ *req,
METHOD_DATA *method_data)
_kdc_check_access(astgs_request_t r, KDC_REQ *req, METHOD_DATA *method_data)
{
krb5_context context = r->context;
krb5_kdc_configuration *config = r->config;
hdb_entry_ex *client_ex = r->client;
const char *client_name = r->cname;
hdb_entry_ex *server_ex = r->server;
const char *server_name = r->sname;
krb5_error_code ret = KRB5_PLUGIN_NO_HANDLE;
struct check_uc uc;