summaryrefslogtreecommitdiff
path: root/source4/heimdal
diff options
context:
space:
mode:
authorAndrew Bartlett <abartlet@samba.org>2005-11-06 14:15:34 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 13:45:50 -0500
commitfb2394d309f33bdccde3a4e17f6fd994d452b425 (patch)
treef1caf0a70e1fb2729b15f03564d1b68dbaa412e3 /source4/heimdal
parentdf5b70db2c228bd781d8472440858dcdf502f9f9 (diff)
downloadsamba-fb2394d309f33bdccde3a4e17f6fd994d452b425.tar.gz
samba-fb2394d309f33bdccde3a4e17f6fd994d452b425.tar.bz2
samba-fb2394d309f33bdccde3a4e17f6fd994d452b425.zip
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)
Diffstat (limited to 'source4/heimdal')
-rw-r--r--source4/heimdal/kdc/kdc_locl.h9
-rw-r--r--source4/heimdal/kdc/kerberos5.c72
-rw-r--r--source4/heimdal/kdc/misc.c56
-rw-r--r--source4/heimdal/lib/hdb/hdb-protos.h3
-rw-r--r--source4/heimdal/lib/hdb/hdb.c10
-rw-r--r--source4/heimdal/lib/hdb/hdb.h21
6 files changed, 138 insertions, 33 deletions
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,10 +71,19 @@ 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);
krb5_error_code
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
@@ -120,6 +120,9 @@ hdb_free_entry (
hdb_entry */*ent*/);
void
+hdb_free_entry_ex(krb5_context context, hdb_entry_ex *ent);
+
+void
hdb_free_key (Key */*key*/);
void
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;