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:

committed by
Viktor Dukhovni

parent
fb9a78223c
commit
7d353d0557
@@ -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>
|
||||
|
||||
|
13
kdc/fast.c
13
kdc/fast.c
@@ -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;
|
||||
|
12
kdc/kdc.h
12
kdc/kdc.h
@@ -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>
|
||||
|
@@ -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;
|
||||
|
466
kdc/kerberos5.c
466
kdc/kerberos5.c
@@ -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)
|
||||
|
125
kdc/krb5tgs.c
125
kdc/krb5tgs.c
@@ -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,
|
||||
|
38
kdc/pkinit.c
38
kdc/pkinit.c
@@ -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;
|
||||
|
374
kdc/process.c
374
kdc/process.c
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
|
13
kdc/windc.c
13
kdc/windc.c
@@ -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;
|
||||
|
||||
|
Reference in New Issue
Block a user