summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTheodore Tso <tytso@mit.edu>1995-09-02 03:43:05 +0000
committerTheodore Tso <tytso@mit.edu>1995-09-02 03:43:05 +0000
commitc1cfefcfea75466ebfc82120d665f1a5752b7314 (patch)
tree0cf0f0598a39b547d6aeb4cdcf20507de028f968
parenteec1b51a6bf366311659fbeed97ef3c0e2e549a5 (diff)
downloadkrb5-c1cfefcfea75466ebfc82120d665f1a5752b7314.tar.gz
krb5-c1cfefcfea75466ebfc82120d665f1a5752b7314.tar.xz
krb5-c1cfefcfea75466ebfc82120d665f1a5752b7314.zip
kdc_preauth.c: New file, to contain the server-side preauthentication
routines. do_as_req.c (process_as_req): Move preauthentication code to kdc_preauth.c, for better modularity. do_as_req.c (prepare_error_as): Add new argument to this function so that the e_data field may be passed in and included in the KRB_ERROR messsage which is passed back to the user. git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@6656 dc483132-0cff-0310-8789-dd5450dbe970
-rw-r--r--src/kdc/ChangeLog12
-rw-r--r--src/kdc/Makefile.in2
-rw-r--r--src/kdc/do_as_req.c93
-rw-r--r--src/kdc/kdc_preauth.c146
-rw-r--r--src/kdc/kdc_util.h9
5 files changed, 207 insertions, 55 deletions
diff --git a/src/kdc/ChangeLog b/src/kdc/ChangeLog
index 825b30c8b1..ac3ef1c5fb 100644
--- a/src/kdc/ChangeLog
+++ b/src/kdc/ChangeLog
@@ -1,3 +1,15 @@
+Fri Sep 1 23:28:29 1995 Theodore Y. Ts'o <tytso@dcl>
+
+ * kdc_preauth.c: New file, to contain the server-side
+ preauthentication routines.
+
+ * do_as_req.c (process_as_req): Move preauthentication code to
+ kdc_preauth.c, for better modularity.
+
+ * do_as_req.c (prepare_error_as): Add new argument to this
+ function so that the e_data field may be passed in and
+ included in the KRB_ERROR messsage which is passed back to
+ the user.
Mon Aug 21 17:03:53 EDT 1995 Paul Park (pjpark@mit.edu)
* main.c - Interpret -k and -e arguments as strings instead of string
diff --git a/src/kdc/Makefile.in b/src/kdc/Makefile.in
index 99e91114a0..3145e1cac3 100644
--- a/src/kdc/Makefile.in
+++ b/src/kdc/Makefile.in
@@ -13,6 +13,7 @@ SRCS= \
$(srcdir)/do_as_req.c \
$(srcdir)/do_tgs_req.c \
$(srcdir)/kdc_util.c \
+ $(srcdir)/kdc_preauth.c \
$(srcdir)/main.c \
$(srcdir)/network.c \
$(srcdir)/policy.c \
@@ -26,6 +27,7 @@ OBJS= \
do_as_req.o \
do_tgs_req.o \
kdc_util.o \
+ kdc_preauth.o \
main.o \
network.o \
policy.o \
diff --git a/src/kdc/do_as_req.c b/src/kdc/do_as_req.c
index 76086e33c5..a80d282f45 100644
--- a/src/kdc/do_as_req.c
+++ b/src/kdc/do_as_req.c
@@ -44,6 +44,7 @@
static krb5_error_code prepare_error_as PROTOTYPE((krb5_kdc_req *,
int,
+ krb5_data *,
krb5_data **));
/*
* This routine is called to verify the preauthentication information
@@ -105,7 +106,7 @@ krb5_data **response; /* filled in with a response packet */
krb5_enc_tkt_part enc_tkt_reply;
krb5_error_code retval;
int c_nprincs = 0, s_nprincs = 0;
- int pwreq, pa_id, pa_flags;
+ int pa_id, pa_flags;
krb5_boolean more;
krb5_timestamp kdc_time, authtime;
krb5_keyblock *session_key = 0;
@@ -113,7 +114,6 @@ krb5_data **response; /* filled in with a response packet */
krb5_enctype useetype;
krb5_pa_data *padat_tmp[2], padat_local;
krb5_data salt_data;
- static krb5_principal cpw = 0;
char *status;
krb5_encrypt_block eblock;
krb5_key_data *server_key, *client_key;
@@ -131,19 +131,19 @@ krb5_data **response; /* filled in with a response packet */
if (!request->client)
return(prepare_error_as(request, KDC_ERR_C_PRINCIPAL_UNKNOWN,
- response));
+ 0, response));
if ((retval = krb5_unparse_name(kdc_context, request->client, &cname))) {
krb5_klog_syslog(LOG_INFO, "AS_REQ: %s while unparsing client name",
error_message(retval));
return(prepare_error_as(request, KDC_ERR_C_PRINCIPAL_UNKNOWN,
- response));
+ 0, response));
}
if ((retval = krb5_unparse_name(kdc_context, request->server, &sname))) {
free(cname);
krb5_klog_syslog(LOG_INFO, "AS_REQ: %s while unparsing server name",
error_message(retval));
return(prepare_error_as(request, KDC_ERR_S_PRINCIPAL_UNKNOWN,
- response));
+ 0, response));
}
#ifdef KRB5_USE_INET
if (from->address->addrtype == ADDRTYPE_INET)
@@ -152,25 +152,6 @@ krb5_data **response; /* filled in with a response packet */
if (!fromstring)
fromstring = "<unknown>";
- /*
- * Special considerations are allowed when changing passwords. Is
- * this request for changepw?
- *
- * XXX This logic should be moved someplace else, perhaps the
- * site-specific policiy file....
- */
- pwreq = 0;
- if (!cpw) {
- retval = krb5_parse_name(kdc_context, "changepw/kerberos", &cpw);
- if (retval)
- goto errout;
- free(krb5_princ_realm(kdc_context, cpw)->data);
- krb5_princ_realm(kdc_context, cpw)->data = 0;
- }
- krb5_princ_realm(kdc_context, cpw)->data = krb5_princ_realm(kdc_context, request->server)->data;
- if (krb5_principal_compare(kdc_context, request->server, cpw))
- pwreq++;
-
c_nprincs = 1;
if ((retval = krb5_db_get_principal(kdc_context, request->client, &client,
&c_nprincs, &more))) {
@@ -179,14 +160,14 @@ krb5_data **response; /* filled in with a response packet */
}
if (more) {
retval = prepare_error_as(request, KDC_ERR_PRINCIPAL_NOT_UNIQUE,
- response);
+ 0, response);
goto errout;
} else if (c_nprincs != 1) {
#ifdef KRBCONF_VAGUE_ERRORS
- retval = prepare_error_as(request, KRB_ERR_GENERIC, response);
+ retval = prepare_error_as(request, KRB_ERR_GENERIC, 0, response);
#else
retval = prepare_error_as(request, KDC_ERR_C_PRINCIPAL_UNKNOWN,
- response);
+ 0, response);
#endif
goto errout;
}
@@ -199,11 +180,11 @@ krb5_data **response; /* filled in with a response packet */
}
if (more) {
retval = prepare_error_as(request, KDC_ERR_PRINCIPAL_NOT_UNIQUE,
- response);
+ 0, response);
goto errout;
} else if (s_nprincs != 1) {
retval = prepare_error_as(request, KDC_ERR_S_PRINCIPAL_UNKNOWN,
- response);
+ 0, response);
goto errout;
}
@@ -218,7 +199,7 @@ krb5_data **response; /* filled in with a response packet */
kdc_time, &status))) {
krb5_klog_syslog(LOG_INFO, "AS_REQ: %s: host %s, %s for %s", status,
fromstring, cname, sname);
- retval = prepare_error_as(request, retval, response);
+ retval = prepare_error_as(request, retval, 0, response);
goto errout;
}
@@ -248,7 +229,7 @@ krb5_data **response; /* filled in with a response packet */
/* unsupported etype */
krb5_klog_syslog(LOG_INFO,"AS_REQ: BAD ENCRYPTION TYPE: host %s, %s for %s",
fromstring, cname, sname);
- retval = prepare_error_as(request, KDC_ERR_ETYPE_NOSUPP, response);
+ retval = prepare_error_as(request, KDC_ERR_ETYPE_NOSUPP, 0, response);
goto errout;
got_a_key:;
@@ -362,16 +343,15 @@ got_a_key:;
krb5_klog_syslog(LOG_INFO, "AS_REQ: PREAUTH FAILED: host %s, %s for %s (%s)",
fromstring, cname, sname, error_message(retval));
#ifdef KRBCONF_VAGUE_ERRORS
- retval = prepare_error_as(request, KRB_ERR_GENERIC, response);
+ retval = prepare_error_as(request, KRB_ERR_GENERIC, 0, response);
#else
retval -= ERROR_TABLE_BASE_krb5;
if ((retval < 0) || (retval > 127))
retval = KDC_ERR_PREAUTH_FAILED;
- retval = prepare_error_as(request, retval, response);
+ retval = prepare_error_as(request, retval, 0, response);
#endif
goto errout;
}
-
setflag(enc_tkt_reply.flags, TKT_FLG_PRE_AUTH);
/*
* If pa_type is one in which additional hardware authentication
@@ -383,23 +363,23 @@ got_a_key:;
/*
* Final check before handing out ticket: If the client requires
- * Hardware authentication, verify ticket flag is set
- */
-
- if (isflagset(client.attributes, KRB5_KDB_REQUIRES_HW_AUTH) &&
- !isflagset(enc_tkt_reply.flags, TKT_FLG_HW_AUTH)) {
-
- /* Of course their are always exceptions, in this case if the
- service requested is for changing of the key (password), then
- if TKT_FLG_PRE_AUTH is set allow it. */
+ * preauthentication, verify that the proper kind of
+ * preauthentication was carried out.
+ */
+ status = missing_required_preauth(&client, &server, &enc_tkt_reply);
+ if (status) {
+ krb5_data e_data;
- if (!pwreq || !(enc_tkt_reply.flags & TKT_FLG_PRE_AUTH)){
- krb5_klog_syslog(LOG_INFO, "AS_REQ: Needed HW preauth: host %s, %s for %s",
- fromstring, cname, sname);
- retval = prepare_error_as(request, KRB_ERR_GENERIC, response);
- goto errout;
- }
- }
+ krb5_klog_syslog(LOG_INFO, "AS_REQ: Needed %s: host %s, %s for %s",
+ status, fromstring, cname, sname);
+
+ get_preauth_hint_list(&client, &server, &e_data);
+ retval = prepare_error_as(request, KDC_ERR_PREAUTH_REQUIRED,
+ &e_data, response);
+ if (e_data.data)
+ free(e_data.data);
+ goto errout;
+ }
ticket_reply.enc_part2 = &enc_tkt_reply;
@@ -439,7 +419,7 @@ got_a_key:;
krb5_klog_syslog(LOG_INFO,
"AS_REQ: CANNOT FIND CLIENT KEY: host %s, %s for %s",
fromstring, cname, sname);
- retval = prepare_error_as(request, KDC_ERR_ETYPE_NOSUPP, response);
+ retval = prepare_error_as(request, KDC_ERR_ETYPE_NOSUPP, 0, response);
goto errout;
}
@@ -588,9 +568,10 @@ errout:
}
static krb5_error_code
-prepare_error_as (request, error, response)
+prepare_error_as (request, error, e_data, response)
register krb5_kdc_req *request;
int error;
+krb5_data *e_data;
krb5_data **response;
{
krb5_error errpkt;
@@ -632,8 +613,12 @@ krb5_data **response;
free(errpkt.text.data);
return ENOMEM;
}
- errpkt.e_data.length = 0;
- errpkt.e_data.data = 0;
+ if (e_data) {
+ errpkt.e_data = *e_data;
+ } else {
+ errpkt.e_data.length = 0;
+ errpkt.e_data.data = 0;
+ }
retval = krb5_mk_error(kdc_context, &errpkt, scratch);
free(errpkt.text.data);
diff --git a/src/kdc/kdc_preauth.c b/src/kdc/kdc_preauth.c
new file mode 100644
index 0000000000..07018e394f
--- /dev/null
+++ b/src/kdc/kdc_preauth.c
@@ -0,0 +1,146 @@
+/*
+ * kdc/kdc_preauth.c
+ *
+ * Copyright 1995 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. M.I.T. makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ *
+ * Preauthentication routines for the KDC.
+ */
+
+#include "k5-int.h"
+#include "kdc_util.h"
+#include "extern.h"
+#include <stdio.h>
+
+typedef krb5_error_code (verify_proc)
+ KRB5_PROTOTYPE((krb5_context, krb5_principal client,
+ krb5_address **src_addr,
+ krb5_data *data));
+
+typedef krb5_error_code (edata_proc)
+ KRB5_PROTOTYPE((krb5_context, krb5_db_entry *client,
+ krb5_pa_data *data));
+
+typedef struct _krb5_preauth_systems {
+ int type;
+ int flags;
+ edata_proc *get_edata;
+ verify_proc *verify;
+} krb5_preauth_systems;
+
+/*
+ * Preauth property flags
+ */
+#define PA_ENCRYPT 0x00000001
+#define PA_HARDWARE 0x00000002
+
+static krb5_preauth_systems preauth_systems[] = {
+ {
+ KRB5_PADATA_ENC_UNIX_TIME,
+ PA_ENCRYPT,
+ 0,
+ 0,
+ },
+ {
+ KRB5_PADATA_ENC_SANDIA_SECURID,
+ PA_ENCRYPT | PA_HARDWARE,
+ 0,
+ 0,
+ },
+ { -1,}
+};
+
+#define MAX_PREAUTH_SYSTEMS (sizeof(preauth_systems)/sizeof(preauth_systems[0]))
+
+const char *missing_required_preauth(client, server, enc_tkt_reply)
+ krb5_db_entry *client, *server;
+ krb5_enc_tkt_part *enc_tkt_reply;
+{
+#if 0
+ /*
+ * If this is the pwchange service, and the pre-auth bit is set,
+ * allow it even if the HW preauth would normally be required.
+ *
+ * Sandia national labs wanted this for some strange reason... we
+ * leave it disabled normally.
+ */
+ if (isflagset(server->attributes, KRB5_KDB_PWCHANGE_SERVICE) &&
+ isflagset(enc_tkt_reply->flags, TKT_FLG_PRE_AUTH))
+ return 0;
+#endif
+
+ if (isflagset(client->attributes, KRB5_KDB_REQUIRES_PRE_AUTH) &&
+ !isflagset(enc_tkt_reply->flags, TKT_FLG_PRE_AUTH))
+ return "preauth";
+
+ if (isflagset(client->attributes, KRB5_KDB_REQUIRES_HW_AUTH) &&
+ !isflagset(enc_tkt_reply->flags, TKT_FLG_HW_AUTH))
+ return "HW preauth";
+
+ return 0;
+}
+
+void get_preauth_hint_list(client, server, e_data)
+ krb5_db_entry *client, *server;
+ krb5_data *e_data;
+{
+ int hw_only;
+ krb5_preauth_systems *ap;
+ krb5_pa_data **pa_data, **pa;
+ krb5_data *edat;
+ krb5_error_code retval;
+
+ /* Zero these out in case we need to abort */
+ e_data->length = 0;
+ e_data->data = 0;
+
+ hw_only = isflagset(client->attributes, KRB5_KDB_REQUIRES_HW_AUTH);
+ pa_data = malloc(sizeof(krb5_pa_data *) * (MAX_PREAUTH_SYSTEMS+1));
+ if (pa_data == 0)
+ return;
+ memset(pa_data, 0, sizeof(krb5_pa_data *) * (MAX_PREAUTH_SYSTEMS+1));
+ pa = pa_data;
+
+ for (ap = preauth_systems; ap->type != -1; ap++) {
+ if (hw_only && !(ap->flags & PA_HARDWARE))
+ continue;
+ *pa = malloc(sizeof(krb5_pa_data));
+ if (*pa == 0)
+ goto errout;
+ memset(pa, 0, sizeof(krb5_pa_data));
+ (*pa)->magic = KV5M_PA_DATA;
+ (*pa)->pa_type = ap->type;
+ if (ap->get_edata)
+ (ap->get_edata)(kdc_context, client, *pa);
+ pa++;
+ }
+ retval = encode_krb5_padata_sequence((const krb5_pa_data **) pa_data,
+ &edat);
+ if (retval)
+ goto errout;
+ *e_data = *edat;
+ free(edat);
+
+errout:
+ krb5_free_pa_data(kdc_context, pa_data);
+ return;
+}
+
+
+
diff --git a/src/kdc/kdc_util.h b/src/kdc/kdc_util.h
index 5e3960c2f9..6d5e5babda 100644
--- a/src/kdc/kdc_util.h
+++ b/src/kdc/kdc_util.h
@@ -109,7 +109,14 @@ int against_local_policy_as PROTOTYPE((krb5_kdc_req *, krb5_db_entry,
int against_local_policy_tgs PROTOTYPE((krb5_kdc_req *, krb5_db_entry,
krb5_ticket *, char **));
-
+/* kdc_preauth.c */
+const char * missing_required_preauth
+ PROTOTYPE((krb5_db_entry *client, krb5_db_entry *server,
+ krb5_enc_tkt_part *enc_tkt_reply));
+void get_preauth_hint_list PROTOTYPE((krb5_db_entry *client,
+ krb5_db_entry *server,
+ krb5_data *e_data));
+
/* replay.c */
krb5_boolean kdc_check_lookaside PROTOTYPE((krb5_data *, krb5_data **));
void kdc_insert_lookaside PROTOTYPE((krb5_data *, krb5_data *));