From fb2394d309f33bdccde3a4e17f6fd994d452b425 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sun, 6 Nov 2005 14:15:34 +0000 Subject: r11536: Add a hook for client-principal access control to hdb-ldb, re-using the code in auth/auth_sam.c for consistancy. This will also allow us to have one place for a backend directory hook. I will use a very similar hook to add the PAC. Andrew Bartlett (This used to be commit 4315836cd8c94eb8340c4050804face4d0066810) --- source4/heimdal/kdc/kdc_locl.h | 9 +++++ source4/heimdal/kdc/kerberos5.c | 72 ++++++++++++++++++++---------------- source4/heimdal/kdc/misc.c | 56 ++++++++++++++++++++++++++++ source4/heimdal/lib/hdb/hdb-protos.h | 3 ++ source4/heimdal/lib/hdb/hdb.c | 10 +++++ source4/heimdal/lib/hdb/hdb.h | 21 ++++++++++- 6 files changed, 138 insertions(+), 33 deletions(-) (limited to 'source4/heimdal') diff --git a/source4/heimdal/kdc/kdc_locl.h b/source4/heimdal/kdc/kdc_locl.h index b0501abb8d..8658d33b68 100644 --- a/source4/heimdal/kdc/kdc_locl.h +++ b/source4/heimdal/kdc/kdc_locl.h @@ -71,9 +71,18 @@ krb5_error_code _kdc_db_fetch(krb5_context, krb5_kdc_configuration *, krb5_principal, enum hdb_ent_type, hdb_entry **); +krb5_error_code +_kdc_db_fetch_ex(krb5_context context, + krb5_kdc_configuration *config, + krb5_principal principal, enum hdb_ent_type ent_type, + hdb_entry_ex **h); + void _kdc_free_ent(krb5_context context, hdb_entry *); +void +_kdc_free_ent_ex(krb5_context context, hdb_entry_ex *ent); + void loop(krb5_context context, krb5_kdc_configuration *config); diff --git a/source4/heimdal/kdc/kerberos5.c b/source4/heimdal/kdc/kerberos5.c index 1c02e66211..0df090eef3 100644 --- a/source4/heimdal/kdc/kerberos5.c +++ b/source4/heimdal/kdc/kerberos5.c @@ -767,7 +767,8 @@ _kdc_as_rep(krb5_context context, KDC_REQ_BODY *b = &req->req_body; AS_REP rep; KDCOptions f = b->kdc_options; - hdb_entry *client = NULL, *server = NULL; + hdb_entry_ex *client = NULL; + hdb_entry *server = NULL; krb5_enctype cetype, setype; EncTicketPart et; EncKDCRepPart ek; @@ -813,7 +814,7 @@ _kdc_as_rep(krb5_context context, kdc_log(context, config, 0, "AS-REQ %s from %s for %s", client_name, from, server_name); - ret = _kdc_db_fetch(context, config, client_princ, HDB_ENT_TYPE_CLIENT, &client); + ret = _kdc_db_fetch_ex(context, config, client_princ, HDB_ENT_TYPE_CLIENT, &client); if(ret){ kdc_log(context, config, 0, "UNKNOWN -- %s: %s", client_name, krb5_get_err_text(context, ret)); @@ -830,12 +831,19 @@ _kdc_as_rep(krb5_context context, } ret = _kdc_check_flags(context, config, - client, client_name, + &client->entry, client_name, server, server_name, TRUE); if(ret) goto out; + if (client->check_client_access) { + ret = client->check_client_access(context, client, + b->addresses); + if(ret) + goto out; + } + memset(&et, 0, sizeof(et)); memset(&ek, 0, sizeof(ek)); @@ -875,7 +883,7 @@ _kdc_as_rep(krb5_context context, ret = _kdc_pk_check_client(context, config, client_princ, - client, + &client->entry, pkp, &client_cert); if (ret) { @@ -924,7 +932,7 @@ _kdc_as_rep(krb5_context context, goto out; } - ret = hdb_enctype2key(context, client, enc_data.etype, &pa_key); + ret = hdb_enctype2key(context, &client->entry, enc_data.etype, &pa_key); if(ret){ char *estr; e_text = "No key matches pa-data"; @@ -974,7 +982,7 @@ _kdc_as_rep(krb5_context context, krb5_get_err_text(context, ret)); free(str); - if(hdb_next_enctype2key(context, client, + if(hdb_next_enctype2key(context, &client->entry, enc_data.etype, &pa_key) == 0) goto try_next_key; e_text = "Failed to decrypt PA-DATA"; @@ -1030,7 +1038,7 @@ _kdc_as_rep(krb5_context context, goto out; } }else if (config->require_preauth - || client->flags.require_preauth + || client->entry.flags.require_preauth || server->flags.require_preauth) { METHOD_DATA method_data; PA_DATA *pa; @@ -1058,10 +1066,10 @@ _kdc_as_rep(krb5_context context, /* XXX check ret */ if (only_older_enctype_p(req)) - ret = get_pa_etype_info(context, config, &method_data, client, + ret = get_pa_etype_info(context, config, &method_data, &client->entry, b->etype.val, b->etype.len); /* XXX check ret */ - ret = get_pa_etype_info2(context, config, &method_data, client, + ret = get_pa_etype_info2(context, config, &method_data, &client->entry, b->etype.val, b->etype.len); @@ -1089,7 +1097,7 @@ _kdc_as_rep(krb5_context context, } ret = find_keys(context, config, - client, server, &ckey, &cetype, &skey, &setype, + &client->entry, server, &ckey, &cetype, &skey, &setype, b->etype.val, b->etype.len); if(ret) { kdc_log(context, config, 0, "Server/client has no support for etypes"); @@ -1154,19 +1162,19 @@ _kdc_as_rep(krb5_context context, rep.pvno = 5; rep.msg_type = krb_as_rep; - copy_Realm(&client->principal->realm, &rep.crealm); + copy_Realm(&client->entry.principal->realm, &rep.crealm); if (f.request_anonymous) make_anonymous_principalname (&rep.cname); else _krb5_principal2principalname(&rep.cname, - client->principal); + client->entry.principal); rep.ticket.tkt_vno = 5; copy_Realm(&server->principal->realm, &rep.ticket.realm); _krb5_principal2principalname(&rep.ticket.sname, server->principal); et.flags.initial = 1; - if(client->flags.forwardable && server->flags.forwardable) + if(client->entry.flags.forwardable && server->flags.forwardable) et.flags.forwardable = f.forwardable; else if (f.forwardable) { ret = KRB5KDC_ERR_POLICY; @@ -1174,7 +1182,7 @@ _kdc_as_rep(krb5_context context, "Ticket may not be forwardable -- %s", client_name); goto out; } - if(client->flags.proxiable && server->flags.proxiable) + if(client->entry.flags.proxiable && server->flags.proxiable) et.flags.proxiable = f.proxiable; else if (f.proxiable) { ret = KRB5KDC_ERR_POLICY; @@ -1182,7 +1190,7 @@ _kdc_as_rep(krb5_context context, "Ticket may not be proxiable -- %s", client_name); goto out; } - if(client->flags.postdate && server->flags.postdate) + if(client->entry.flags.postdate && server->flags.postdate) et.flags.may_postdate = f.allow_postdate; else if (f.allow_postdate){ ret = KRB5KDC_ERR_POLICY; @@ -1220,8 +1228,8 @@ _kdc_as_rep(krb5_context context, /* be careful not overflowing */ - if(client->max_life) - t = start + min(t - start, *client->max_life); + if(client->entry.max_life) + t = start + min(t - start, *client->entry.max_life); if(server->max_life) t = start + min(t - start, *server->max_life); #if 0 @@ -1241,8 +1249,8 @@ _kdc_as_rep(krb5_context context, t = *b->rtime; if(t == 0) t = MAX_TIME; - if(client->max_renew) - t = start + min(t - start, *client->max_renew); + if(client->entry.max_renew) + t = start + min(t - start, *client->entry.max_renew); if(server->max_renew) t = start + min(t - start, *server->max_renew); #if 0 @@ -1278,16 +1286,16 @@ _kdc_as_rep(krb5_context context, */ ek.last_req.val = malloc(2 * sizeof(*ek.last_req.val)); ek.last_req.len = 0; - if (client->pw_end + if (client->entry.pw_end && (config->kdc_warn_pwexpire == 0 - || kdc_time + config->kdc_warn_pwexpire <= *client->pw_end)) { + || kdc_time + config->kdc_warn_pwexpire <= *client->entry.pw_end)) { ek.last_req.val[ek.last_req.len].lr_type = LR_PW_EXPTIME; - ek.last_req.val[ek.last_req.len].lr_value = *client->pw_end; + ek.last_req.val[ek.last_req.len].lr_value = *client->entry.pw_end; ++ek.last_req.len; } - if (client->valid_end) { + if (client->entry.valid_end) { ek.last_req.val[ek.last_req.len].lr_type = LR_ACCT_EXPTIME; - ek.last_req.val[ek.last_req.len].lr_value = *client->valid_end; + ek.last_req.val[ek.last_req.len].lr_value = *client->entry.valid_end; ++ek.last_req.len; } if (ek.last_req.len == 0) { @@ -1296,15 +1304,15 @@ _kdc_as_rep(krb5_context context, ++ek.last_req.len; } ek.nonce = b->nonce; - if (client->valid_end || client->pw_end) { + if (client->entry.valid_end || client->entry.pw_end) { ALLOC(ek.key_expiration); - if (client->valid_end) { - if (client->pw_end) - *ek.key_expiration = min(*client->valid_end, *client->pw_end); + if (client->entry.valid_end) { + if (client->entry.pw_end) + *ek.key_expiration = min(*client->entry.valid_end, *client->entry.pw_end); else - *ek.key_expiration = *client->valid_end; + *ek.key_expiration = *client->entry.valid_end; } else - *ek.key_expiration = *client->pw_end; + *ek.key_expiration = *client->entry.pw_end; } else ek.key_expiration = NULL; ek.flags = et.flags; @@ -1352,7 +1360,7 @@ _kdc_as_rep(krb5_context context, ret = encode_reply(context, config, &rep, &et, &ek, setype, server->kvno, &skey->key, - client->kvno, reply_key, &e_text, reply); + client->entry.kvno, reply_key, &e_text, reply); free_EncTicketPart(&et); free_EncKDCRepPart(&ek); out: @@ -1381,7 +1389,7 @@ _kdc_as_rep(krb5_context context, krb5_free_principal(context, server_princ); free(server_name); if(client) - _kdc_free_ent(context, client); + _kdc_free_ent_ex(context, client); if(server) _kdc_free_ent(context, server); return ret; diff --git a/source4/heimdal/kdc/misc.c b/source4/heimdal/kdc/misc.c index 5a251607b6..b14bb50ea5 100644 --- a/source4/heimdal/kdc/misc.c +++ b/source4/heimdal/kdc/misc.c @@ -82,3 +82,59 @@ _kdc_free_ent(krb5_context context, hdb_entry *ent) free (ent); } +krb5_error_code +_kdc_db_fetch_ex(krb5_context context, + krb5_kdc_configuration *config, + krb5_principal principal, enum hdb_ent_type ent_type, + hdb_entry_ex **h) +{ + hdb_entry_ex *ent; + krb5_error_code ret = HDB_ERR_NOENTRY; + int i; + + ent = malloc (sizeof (*ent)); + if (ent == NULL) + return ENOMEM; + memset(ent, '\0', sizeof(*ent)); + + ent->entry.principal = principal; + + for(i = 0; i < config->num_db; i++) { + ret = config->db[i]->hdb_open(context, config->db[i], O_RDONLY, 0); + if (ret) { + kdc_log(context, config, 0, "Failed to open database: %s", + krb5_get_err_text(context, ret)); + continue; + } + if (config->db[i]->hdb_fetch_ex) { + ret = config->db[i]->hdb_fetch_ex(context, + config->db[i], + HDB_F_DECRYPT, + principal, + ent_type, + ent); + } else { + ret = config->db[i]->hdb_fetch(context, + config->db[i], + HDB_F_DECRYPT, + principal, + ent_type, + &ent->entry); + } + config->db[i]->hdb_close(context, config->db[i]); + if(ret == 0) { + *h = ent; + return 0; + } + } + free(ent); + return ret; +} + +void +_kdc_free_ent_ex(krb5_context context, hdb_entry_ex *ent) +{ + hdb_free_entry_ex (context, ent); + free (ent); +} + diff --git a/source4/heimdal/lib/hdb/hdb-protos.h b/source4/heimdal/lib/hdb/hdb-protos.h index 799f013eba..7557b46bff 100644 --- a/source4/heimdal/lib/hdb/hdb-protos.h +++ b/source4/heimdal/lib/hdb/hdb-protos.h @@ -119,6 +119,9 @@ hdb_free_entry ( krb5_context /*context*/, hdb_entry */*ent*/); +void +hdb_free_entry_ex(krb5_context context, hdb_entry_ex *ent); + void hdb_free_key (Key */*key*/); diff --git a/source4/heimdal/lib/hdb/hdb.c b/source4/heimdal/lib/hdb/hdb.c index c66579fab0..e8161afbc1 100644 --- a/source4/heimdal/lib/hdb/hdb.c +++ b/source4/heimdal/lib/hdb/hdb.c @@ -144,6 +144,16 @@ hdb_free_entry(krb5_context context, hdb_entry *ent) free_hdb_entry(ent); } +void +hdb_free_entry_ex(krb5_context context, hdb_entry_ex *ent) +{ + if (ent->free_private) { + ent->free_private(context, ent); + } + + free_hdb_entry(&ent->entry); +} + krb5_error_code hdb_foreach(krb5_context context, HDB *db, diff --git a/source4/heimdal/lib/hdb/hdb.h b/source4/heimdal/lib/hdb/hdb.h index fe86f0ae72..41cc03cf36 100644 --- a/source4/heimdal/lib/hdb/hdb.h +++ b/source4/heimdal/lib/hdb/hdb.h @@ -54,6 +54,23 @@ enum hdb_ent_type{ HDB_ENT_TYPE_CLIENT, HDB_ENT_TYPE_SERVER, HDB_ENT_TYPE_ANY }; typedef struct hdb_master_key_data *hdb_master_key; +typedef struct hdb_entry_ex { + struct hdb_entry entry; + void *private; + + krb5_error_code (*free_private)(krb5_context, struct hdb_entry_ex *); + krb5_error_code (*check_client_access)(krb5_context, struct hdb_entry_ex *, HostAddresses *); + krb5_error_code (*authz_data_as_req)(krb5_context, struct hdb_entry_ex *, + AuthorizationData *in, + EncryptionKey *tgtkey, + AuthorizationData *out); + krb5_error_code (*authz_data_tgs_req)(krb5_context, struct hdb_entry_ex *, + AuthorizationData *in, + EncryptionKey *tgtkey, + EncryptionKey *servicekey, + AuthorizationData *out); +} hdb_entry_ex; + typedef struct HDB{ void *hdb_db; void *hdb_dbc; @@ -66,6 +83,8 @@ typedef struct HDB{ krb5_error_code (*hdb_close)(krb5_context, struct HDB*); krb5_error_code (*hdb_fetch)(krb5_context,struct HDB*,unsigned hdb_flags, krb5_const_principal principal, enum hdb_ent_type ent_type, hdb_entry*); + krb5_error_code (*hdb_fetch_ex)(krb5_context,struct HDB*,unsigned hdb_flags, krb5_const_principal principal, + enum hdb_ent_type ent_type, hdb_entry_ex*); krb5_error_code (*hdb_store)(krb5_context,struct HDB*,unsigned,hdb_entry*); krb5_error_code (*hdb_remove)(krb5_context, struct HDB*, hdb_entry*); krb5_error_code (*hdb_firstkey)(krb5_context, struct HDB*, @@ -82,7 +101,7 @@ typedef struct HDB{ krb5_error_code (*hdb_destroy)(krb5_context, struct HDB*); }HDB; -#define HDB_INTERFACE_VERSION 2 +#define HDB_INTERFACE_VERSION 3 struct hdb_so_method { int version; -- cgit