diff options
author | Greg Hudson <ghudson@mit.edu> | 2009-10-27 14:24:01 +0000 |
---|---|---|
committer | Greg Hudson <ghudson@mit.edu> | 2009-10-27 14:24:01 +0000 |
commit | 2a5ccaf5a2456e8cfc3f774df307386404bfbec3 (patch) | |
tree | 73f2ca8f5b0860aef61fac578a21370e5c34e98e /src/kdc | |
parent | 8552d685d38e6d664186ac671f6bcd2269f41398 (diff) | |
download | krb5-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.c | 19 | ||||
-rw-r--r-- | src/kdc/do_tgs_req.c | 40 | ||||
-rw-r--r-- | src/kdc/kdc_authdata.c | 9 | ||||
-rw-r--r-- | src/kdc/kdc_util.c | 67 | ||||
-rw-r--r-- | src/kdc/kdc_util.h | 23 | ||||
-rw-r--r-- | src/kdc/policy.c | 7 |
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; |