aboutsummaryrefslogtreecommitdiff
path: root/src/kdc
diff options
context:
space:
mode:
authorGreg Hudson <ghudson@mit.edu>2009-10-27 14:24:01 +0000
committerGreg Hudson <ghudson@mit.edu>2009-10-27 14:24:01 +0000
commit2a5ccaf5a2456e8cfc3f774df307386404bfbec3 (patch)
tree73f2ca8f5b0860aef61fac578a21370e5c34e98e /src/kdc
parent8552d685d38e6d664186ac671f6bcd2269f41398 (diff)
downloadkrb5-2a5ccaf5a2456e8cfc3f774df307386404bfbec3.zip
krb5-2a5ccaf5a2456e8cfc3f774df307386404bfbec3.tar.gz
krb5-2a5ccaf5a2456e8cfc3f774df307386404bfbec3.tar.bz2
Heimdal DB bridge plugin for KDC back end
Merge Luke's users/lhoward/heimmig branch to trunk. Implements a KDC back-end plugin which interfaces to a Heimdal HDB plugin. ticket: 6578 git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@23073 dc483132-0cff-0310-8789-dd5450dbe970
Diffstat (limited to 'src/kdc')
-rw-r--r--src/kdc/do_as_req.c19
-rw-r--r--src/kdc/do_tgs_req.c40
-rw-r--r--src/kdc/kdc_authdata.c9
-rw-r--r--src/kdc/kdc_util.c67
-rw-r--r--src/kdc/kdc_util.h23
-rw-r--r--src/kdc/policy.c7
6 files changed, 121 insertions, 44 deletions
diff --git a/src/kdc/do_as_req.c b/src/kdc/do_as_req.c
index 737def8..1feb468 100644
--- a/src/kdc/do_as_req.c
+++ b/src/kdc/do_as_req.c
@@ -108,7 +108,7 @@ process_as_req(krb5_kdc_req *request, krb5_data *req_pkt,
krb5_enctype useenctype;
krb5_data e_data;
register int i;
- krb5_timestamp until, rtime;
+ krb5_timestamp rtime;
char *cname = 0, *sname = 0;
unsigned int c_flags = 0, s_flags = 0;
krb5_principal_data client_princ;
@@ -265,7 +265,7 @@ process_as_req(krb5_kdc_req *request, krb5_data *req_pkt,
authtime = kdc_time; /* for audit_as_request() */
if ((errcode = validate_as_request(request, client, server,
- kdc_time, &status))) {
+ kdc_time, &status, &e_data))) {
if (!status)
status = "UNKNOWN_REASON";
errcode += ERROR_TABLE_BASE_krb5;
@@ -339,14 +339,14 @@ process_as_req(krb5_kdc_req *request, krb5_data *req_pkt,
enc_tkt_reply.times.starttime = request->from;
} else
enc_tkt_reply.times.starttime = kdc_time;
-
- until = (request->till == 0) ? kdc_infinity : request->till;
- enc_tkt_reply.times.endtime =
- min(until,
- min(enc_tkt_reply.times.starttime + client.max_life,
- min(enc_tkt_reply.times.starttime + server.max_life,
- enc_tkt_reply.times.starttime + max_life_for_realm)));
+ kdc_get_ticket_endtime(kdc_context,
+ enc_tkt_reply.times.starttime,
+ kdc_infinity,
+ request->till,
+ &client,
+ &server,
+ &enc_tkt_reply.times.endtime);
if (isflagset(request->kdc_options, KDC_OPT_RENEWABLE_OK) &&
!isflagset(client.attributes, KRB5_KDB_DISALLOW_RENEWABLE) &&
@@ -559,6 +559,7 @@ process_as_req(krb5_kdc_req *request, krb5_data *req_pkt,
&server,
&client_keyblock,
&server_keyblock,
+ &server_keyblock,
req_pkt,
request,
NULL, /* for_user_princ */
diff --git a/src/kdc/do_tgs_req.c b/src/kdc/do_tgs_req.c
index f05d25a..71013b5 100644
--- a/src/kdc/do_tgs_req.c
+++ b/src/kdc/do_tgs_req.c
@@ -77,7 +77,7 @@ find_alternate_tgs(krb5_kdc_req *,krb5_db_entry *,
static krb5_error_code
prepare_error_tgs(struct kdc_request_state *, krb5_kdc_req *,krb5_ticket *,int,
- krb5_principal,krb5_data **,const char *);
+ krb5_principal,krb5_data **,const char *, krb5_data *);
static krb5_int32
prep_reprocess_req(krb5_kdc_req *,krb5_principal *);
@@ -88,6 +88,7 @@ process_tgs_req(krb5_data *pkt, const krb5_fulladdr *from,
krb5_data **response)
{
krb5_keyblock * subkey = 0;
+ krb5_keyblock * tgskey = 0;
krb5_kdc_req *request = 0;
krb5_db_entry server;
krb5_kdc_rep reply;
@@ -103,7 +104,7 @@ process_tgs_req(krb5_data *pkt, const krb5_fulladdr *from,
krb5_boolean more;
krb5_timestamp kdc_time, authtime=0;
krb5_keyblock session_key;
- krb5_timestamp until, rtime;
+ krb5_timestamp rtime;
krb5_keyblock *reply_key = NULL;
krb5_keyblock *mkey_ptr;
krb5_key_data *server_key;
@@ -129,9 +130,11 @@ process_tgs_req(krb5_data *pkt, const krb5_fulladdr *from,
struct kdc_request_state *state = NULL;
krb5_pa_data *pa_tgs_req; /*points into request*/
krb5_data scratch;
+ krb5_data e_data; /* backend-provided error data */
reply.padata = 0; /* For cleanup handler */
reply_encpart.enc_padata = 0;
+ e_data.data = NULL;
session_key.contents = NULL;
@@ -147,7 +150,8 @@ process_tgs_req(krb5_data *pkt, const krb5_fulladdr *from,
return retval;
}
errcode = kdc_process_tgs_req(request, from, pkt, &header_ticket,
- &krbtgt, &k_nprincs, &subkey, &pa_tgs_req);
+ &krbtgt, &k_nprincs, &tgskey,
+ &subkey, &pa_tgs_req);
if (header_ticket && header_ticket->enc_part2 &&
(errcode2 = krb5_unparse_name(kdc_context,
header_ticket->enc_part2->client,
@@ -281,7 +285,7 @@ tgt_again:
}
if ((retval = validate_tgs_request(request, server, header_ticket,
- kdc_time, &status))) {
+ kdc_time, &status, &e_data))) {
if (!status)
status = "UNKNOWN_REASON";
errcode = retval + ERROR_TABLE_BASE_krb5;
@@ -540,18 +544,22 @@ tgt_again:
} else {
/* not a renew request */
enc_tkt_reply.times.starttime = kdc_time;
- until = (request->till == 0) ? kdc_infinity : request->till;
- enc_tkt_reply.times.endtime =
- min(until, min(enc_tkt_reply.times.starttime + server.max_life,
- min(enc_tkt_reply.times.starttime + max_life_for_realm,
- header_enc_tkt->times.endtime)));
+
+ kdc_get_ticket_endtime(kdc_context,
+ enc_tkt_reply.times.starttime,
+ header_enc_tkt->times.endtime,
+ request->till,
+ &client,
+ &server,
+ &enc_tkt_reply.times.endtime);
+
if (isflagset(request->kdc_options, KDC_OPT_RENEWABLE_OK) &&
(enc_tkt_reply.times.endtime < request->till) &&
isflagset(header_enc_tkt->flags, TKT_FLG_RENEWABLE)) {
setflag(request->kdc_options, KDC_OPT_RENEWABLE);
request->rtime =
min(request->till, header_enc_tkt->times.renew_till);
- }
+ }
}
rtime = (request->rtime == 0) ? kdc_infinity : request->rtime;
@@ -716,6 +724,7 @@ tgt_again:
subkey != NULL ? subkey :
header_ticket->enc_part2->session,
&encrypting_key, /* U2U or server key */
+ tgskey,
pkt,
request,
s4u_x509_user ?
@@ -974,7 +983,7 @@ cleanup:
retval = prepare_error_tgs(state, request, header_ticket, errcode,
nprincs ? server.princ : NULL,
- response, status);
+ response, status, &e_data);
if (got_err) {
krb5_free_error_message (kdc_context, status);
status = 0;
@@ -1009,10 +1018,13 @@ cleanup:
free(s4u_name);
if (subkey != NULL)
krb5_free_keyblock(kdc_context, subkey);
+ if (tgskey != NULL)
+ krb5_free_keyblock(kdc_context, tgskey);
if (reply.padata)
krb5_free_pa_data(kdc_context, reply.padata);
if (reply_encpart.enc_padata)
krb5_free_pa_data(kdc_context, reply_encpart.enc_padata);
+ krb5_free_data_contents(kdc_context, &e_data);
return retval;
}
@@ -1021,7 +1033,8 @@ static krb5_error_code
prepare_error_tgs (struct kdc_request_state *state,
krb5_kdc_req *request, krb5_ticket *ticket, int error,
krb5_principal canon_server,
- krb5_data **response, const char *status)
+ krb5_data **response, const char *status,
+ krb5_data *e_data)
{
krb5_error errpkt;
krb5_error_code retval = 0;
@@ -1047,8 +1060,7 @@ prepare_error_tgs (struct kdc_request_state *state,
free(errpkt.text.data);
return ENOMEM;
}
- errpkt.e_data.length = 0;
- errpkt.e_data.data = NULL;
+ errpkt.e_data = *e_data;
if (state)
retval = kdc_fast_handle_error(kdc_context, state, request, NULL, &errpkt);
if (retval) {
diff --git a/src/kdc/kdc_authdata.c b/src/kdc/kdc_authdata.c
index d598894..4ccfcb9 100644
--- a/src/kdc/kdc_authdata.c
+++ b/src/kdc/kdc_authdata.c
@@ -56,6 +56,7 @@ typedef krb5_error_code (*authdata_proc_2)
krb5_db_entry *krbtgt,
krb5_keyblock *client_key,
krb5_keyblock *server_key,
+ krb5_keyblock *krbtgt_key,
krb5_data *req_pkt,
krb5_kdc_req *request,
krb5_const_principal for_user_princ,
@@ -75,6 +76,7 @@ static krb5_error_code handle_request_authdata
krb5_db_entry *krbtgt,
krb5_keyblock *client_key,
krb5_keyblock *server_key,
+ krb5_keyblock *krbtgt_key,
krb5_data *req_pkt,
krb5_kdc_req *request,
krb5_const_principal for_user_princ,
@@ -90,6 +92,7 @@ static krb5_error_code handle_tgt_authdata
krb5_db_entry *krbtgt,
krb5_keyblock *client_key,
krb5_keyblock *server_key,
+ krb5_keyblock *krbtgt_key,
krb5_data *req_pkt,
krb5_kdc_req *request,
krb5_const_principal for_user_princ,
@@ -382,6 +385,7 @@ handle_request_authdata (krb5_context context,
krb5_db_entry *krbtgt,
krb5_keyblock *client_key,
krb5_keyblock *server_key,
+ krb5_keyblock *krbtgt_key,
krb5_data *req_pkt,
krb5_kdc_req *request,
krb5_const_principal for_user_princ,
@@ -455,6 +459,7 @@ handle_tgt_authdata (krb5_context context,
krb5_db_entry *krbtgt,
krb5_keyblock *client_key,
krb5_keyblock *server_key,
+ krb5_keyblock *krbtgt_key,
krb5_data *req_pkt,
krb5_kdc_req *request,
krb5_const_principal for_user_princ,
@@ -526,6 +531,7 @@ handle_tgt_authdata (krb5_context context,
krbtgt,
client_key,
server_key, /* U2U or server key */
+ krbtgt_key,
enc_tkt_reply->times.authtime,
tgs_req ? enc_tkt_request->authorization_data : NULL,
enc_tkt_reply->session,
@@ -562,6 +568,7 @@ handle_authdata (krb5_context context,
krb5_db_entry *krbtgt,
krb5_keyblock *client_key,
krb5_keyblock *server_key,
+ krb5_keyblock *krbtgt_key,
krb5_data *req_pkt,
krb5_kdc_req *request,
krb5_const_principal for_user_princ,
@@ -586,7 +593,7 @@ handle_authdata (krb5_context context,
case AUTHDATA_SYSTEM_V2:
code = (*asys->handle_authdata.v2)(context, flags,
client, server, krbtgt,
- client_key, server_key,
+ client_key, server_key, krbtgt_key,
req_pkt, request, for_user_princ,
enc_tkt_request,
enc_tkt_reply);
diff --git a/src/kdc/kdc_util.c b/src/kdc/kdc_util.c
index 9ad832e..b2d8d13 100644
--- a/src/kdc/kdc_util.c
+++ b/src/kdc/kdc_util.c
@@ -230,6 +230,7 @@ krb5_error_code
kdc_process_tgs_req(krb5_kdc_req *request, const krb5_fulladdr *from,
krb5_data *pkt, krb5_ticket **ticket,
krb5_db_entry *krbtgt, int *nprincs,
+ krb5_keyblock **tgskey,
krb5_keyblock **subkey,
krb5_pa_data **pa_tgs_req)
{
@@ -243,10 +244,10 @@ kdc_process_tgs_req(krb5_kdc_req *request, const krb5_fulladdr *from,
krb5_auth_context auth_context = NULL;
krb5_authenticator * authenticator = NULL;
krb5_checksum * his_cksum = NULL;
- krb5_keyblock * key = NULL;
krb5_kvno kvno = 0;
*nprincs = 0;
+ *tgskey = NULL;
tmppa = find_pa_data(request->padata, KRB5_PADATA_AP_REQ);
if (!tmppa)
@@ -289,13 +290,12 @@ kdc_process_tgs_req(krb5_kdc_req *request, const krb5_fulladdr *from,
#endif
if ((retval = kdc_get_server_key(apreq->ticket, 0, foreign_server,
- krbtgt, nprincs, &key, &kvno)))
+ krbtgt, nprincs, tgskey, &kvno)))
goto cleanup_auth_context;
/*
* We do not use the KDB keytab because other parts of the TGS need the TGT key.
*/
- retval = krb5_auth_con_setuseruserkey(kdc_context, auth_context, key);
- krb5_free_keyblock(kdc_context, key);
+ retval = krb5_auth_con_setuseruserkey(kdc_context, auth_context, *tgskey);
if (retval)
goto cleanup_auth_context;
@@ -411,6 +411,10 @@ cleanup_auth_context:
krb5_auth_con_free(kdc_context, auth_context);
cleanup:
+ if (retval != 0) {
+ krb5_free_keyblock(kdc_context, *tgskey);
+ *tgskey = NULL;
+ }
krb5_free_ap_req(kdc_context, apreq);
return retval;
}
@@ -932,7 +936,7 @@ fail:
int
validate_as_request(register krb5_kdc_req *request, krb5_db_entry client,
krb5_db_entry server, krb5_timestamp kdc_time,
- const char **status)
+ const char **status, krb5_data *e_data)
{
int errcode;
@@ -1042,7 +1046,7 @@ validate_as_request(register krb5_kdc_req *request, krb5_db_entry client,
* Check against local policy
*/
errcode = against_local_policy_as(request, client, server,
- kdc_time, status);
+ kdc_time, status, e_data);
if (errcode)
return errcode;
@@ -1225,7 +1229,7 @@ fetch_asn1_field(unsigned char *astream, unsigned int level,
int
validate_tgs_request(register krb5_kdc_req *request, krb5_db_entry server,
krb5_ticket *ticket, krb5_timestamp kdc_time,
- const char **status)
+ const char **status, krb5_data *e_data)
{
int errcode;
int st_idx = 0;
@@ -1458,7 +1462,8 @@ validate_tgs_request(register krb5_kdc_req *request, krb5_db_entry server,
/*
* Check local policy
*/
- errcode = against_local_policy_tgs(request, server, ticket, status);
+ errcode = against_local_policy_tgs(request, server, ticket,
+ status, e_data);
if (errcode)
return errcode;
@@ -1737,6 +1742,7 @@ sign_db_authdata (krb5_context context,
krb5_db_entry *krbtgt,
krb5_keyblock *client_key,
krb5_keyblock *server_key,
+ krb5_keyblock *krbtgt_key,
krb5_timestamp authtime,
krb5_authdata **tgs_authdata,
krb5_keyblock *session_key,
@@ -1763,6 +1769,7 @@ sign_db_authdata (krb5_context context,
req.authtime = authtime;
req.auth_data = tgs_authdata;
req.session_key = session_key;
+ req.krbtgt_key = krbtgt_key;
req_data.data = (void *)&req;
req_data.length = sizeof(req);
@@ -2166,9 +2173,9 @@ kdc_process_s4u2self_req(krb5_context context,
* the TGT and that we have a global name service.
*/
flags = 0;
- switch (krb5_princ_type(kdc_context, request->server)) {
+ switch (krb5_princ_type(context, request->server)) {
case KRB5_NT_SRV_HST: /* (1) */
- if (krb5_princ_size(kdc_context, request->server) == 2)
+ if (krb5_princ_size(context, request->server) == 2)
flags |= KRB5_PRINCIPAL_COMPARE_IGNORE_REALM;
break;
case KRB5_NT_ENTERPRISE_PRINCIPAL: /* (2) */
@@ -2204,9 +2211,11 @@ kdc_process_s4u2self_req(krb5_context context,
*/
if (is_local_principal((*s4u_x509_user)->user_id.user)) {
krb5_db_entry no_server;
+ krb5_data e_data;
+ e_data.data = NULL;
*nprincs = 1;
- code = krb5_db_get_principal_ext(kdc_context,
+ code = krb5_db_get_principal_ext(context,
(*s4u_x509_user)->user_id.user,
KRB5_KDB_FLAG_INCLUDE_PAC,
princ, nprincs, &more);
@@ -2227,8 +2236,9 @@ kdc_process_s4u2self_req(krb5_context context,
memset(&no_server, 0, sizeof(no_server));
code = validate_as_request(request, *princ,
- no_server, kdc_time, status);
+ no_server, kdc_time, status, &e_data);
if (code) {
+ krb5_free_data_contents(context, &e_data);
return code;
}
}
@@ -2613,3 +2623,36 @@ add_pa_data_element(krb5_context context,
return 0;
}
+void
+kdc_get_ticket_endtime(krb5_context context,
+ krb5_timestamp starttime,
+ krb5_timestamp endtime,
+ krb5_timestamp till,
+ krb5_db_entry *client,
+ krb5_db_entry *server,
+ krb5_timestamp *out_endtime)
+{
+ krb5_timestamp until, life;
+
+ if (till == 0)
+ till = kdc_infinity;
+
+ until = min(till, endtime);
+
+ /* check for underflow */
+ life = (until < starttime) ? 0 : until - starttime;
+
+ if (client->max_life != 0)
+ life = min(life, client->max_life);
+ if (server->max_life != 0)
+ life = min(life, server->max_life);
+ if (max_life_for_realm != 0)
+ life = min(life, max_life_for_realm);
+
+ /* check for overflow */
+ if (starttime > kdc_infinity - life)
+ *out_endtime = kdc_infinity;
+ else
+ *out_endtime = starttime + life;
+}
+
diff --git a/src/kdc/kdc_util.h b/src/kdc/kdc_util.h
index 0794922..84319f7 100644
--- a/src/kdc/kdc_util.h
+++ b/src/kdc/kdc_util.h
@@ -66,7 +66,8 @@ krb5_error_code kdc_process_tgs_req
krb5_ticket **,
krb5_db_entry *krbtgt,
int *nprincs,
- krb5_keyblock **, krb5_pa_data **pa_tgs_req);
+ krb5_keyblock **, krb5_keyblock **,
+ krb5_pa_data **pa_tgs_req);
krb5_error_code kdc_get_server_key (krb5_ticket *, unsigned int,
krb5_boolean match_enctype,
@@ -75,7 +76,7 @@ krb5_error_code kdc_get_server_key (krb5_ticket *, unsigned int,
int validate_as_request (krb5_kdc_req *, krb5_db_entry,
krb5_db_entry, krb5_timestamp,
- const char **);
+ const char **, krb5_data *);
int validate_forwardable(krb5_kdc_req *, krb5_db_entry,
krb5_db_entry, krb5_timestamp,
@@ -83,7 +84,7 @@ int validate_forwardable(krb5_kdc_req *, krb5_db_entry,
int validate_tgs_request (krb5_kdc_req *, krb5_db_entry,
krb5_ticket *, krb5_timestamp,
- const char **);
+ const char **, krb5_data *);
int fetch_asn1_field (unsigned char *, unsigned int, unsigned int,
krb5_data *);
@@ -144,10 +145,11 @@ krb5_error_code closedown_network (void);
/* policy.c */
int against_local_policy_as (krb5_kdc_req *, krb5_db_entry,
krb5_db_entry, krb5_timestamp,
- const char **);
+ const char **, krb5_data *);
int against_local_policy_tgs (krb5_kdc_req *, krb5_db_entry,
- krb5_ticket *, const char **);
+ krb5_ticket *, const char **,
+ krb5_data *);
/* kdc_preauth.c */
krb5_boolean enctype_requires_etype_info_2(krb5_enctype enctype);
@@ -197,6 +199,7 @@ handle_authdata (krb5_context context,
krb5_db_entry *krbtgt,
krb5_keyblock *client_key,
krb5_keyblock *server_key,
+ krb5_keyblock *krbtgt_key,
krb5_data *req_pkt,
krb5_kdc_req *request,
krb5_const_principal for_user_princ,
@@ -236,6 +239,7 @@ krb5_error_code sign_db_authdata
krb5_db_entry *krbtgt,
krb5_keyblock *client_key,
krb5_keyblock *server_key,
+ krb5_keyblock *krbtgt_key,
krb5_timestamp authtime,
krb5_authdata **tgs_authdata,
krb5_keyblock *session_key,
@@ -296,7 +300,14 @@ validate_transit_path(krb5_context context,
krb5_const_principal client,
krb5_db_entry *server,
krb5_db_entry *krbtgt);
-
+void
+kdc_get_ticket_endtime(krb5_context context,
+ krb5_timestamp now,
+ krb5_timestamp endtime,
+ krb5_timestamp till,
+ krb5_db_entry *client,
+ krb5_db_entry *server,
+ krb5_timestamp *out_endtime);
void
log_as_req(const krb5_fulladdr *from,
diff --git a/src/kdc/policy.c b/src/kdc/policy.c
index 58b26f7..d4a70fe 100644
--- a/src/kdc/policy.c
+++ b/src/kdc/policy.c
@@ -60,7 +60,7 @@
int
against_local_policy_as(register krb5_kdc_req *request, krb5_db_entry client,
krb5_db_entry server, krb5_timestamp kdc_time,
- const char **status)
+ const char **status, krb5_data *e_data)
{
krb5_error_code code;
kdb_check_policy_as_req req;
@@ -98,6 +98,7 @@ against_local_policy_as(register krb5_kdc_req *request, krb5_db_entry client,
return 0;
*status = rep.status;
+ *e_data = rep.e_data;
if (code != 0) {
code -= ERROR_TABLE_BASE_krb5;
@@ -113,7 +114,8 @@ against_local_policy_as(register krb5_kdc_req *request, krb5_db_entry client,
*/
krb5_error_code
against_local_policy_tgs(register krb5_kdc_req *request, krb5_db_entry server,
- krb5_ticket *ticket, const char **status)
+ krb5_ticket *ticket, const char **status,
+ krb5_data *e_data)
{
krb5_error_code code;
kdb_check_policy_tgs_req req;
@@ -154,6 +156,7 @@ against_local_policy_tgs(register krb5_kdc_req *request, krb5_db_entry server,
return 0;
*status = rep.status;
+ *e_data = rep.e_data;
if (code != 0) {
code -= ERROR_TABLE_BASE_krb5;