aboutsummaryrefslogtreecommitdiff
path: root/src/kdc
diff options
context:
space:
mode:
Diffstat (limited to 'src/kdc')
-rw-r--r--src/kdc/ChangeLog102
-rw-r--r--src/kdc/dispatch.c4
-rw-r--r--src/kdc/do_as_req.c2
-rw-r--r--src/kdc/do_tgs_req.c7
-rw-r--r--src/kdc/kdc_preauth.c22
-rw-r--r--src/kdc/kdc_util.c176
-rw-r--r--src/kdc/kdc_util.h6
-rw-r--r--src/kdc/kerberos_v4.c32
-rw-r--r--src/kdc/main.c6
-rw-r--r--src/kdc/replay.c42
10 files changed, 337 insertions, 62 deletions
diff --git a/src/kdc/ChangeLog b/src/kdc/ChangeLog
index dd74460..29a7f66 100644
--- a/src/kdc/ChangeLog
+++ b/src/kdc/ChangeLog
@@ -1,3 +1,105 @@
+Tue Jul 21 20:29:38 1998 Tom Yu <tlyu@mit.edu>
+
+ * replay.c (kdc_check_lookaside):
+ (kdc_insert_lookaside): Add code to originating address of packet,
+ as krb4 initial ticket requests don't contain an address. This
+ would cause a subtle problem wherein two simultaneous krb4 initial
+ ticket requests for the same principal originating from different
+ addresses would result in both replies containing the same
+ address.
+
+ * kdc_util.h: Modify prototype for lookaside functions.
+
+ * dispatch.c (dispatch): Update to new calling conventions of the
+ lookaside functions.
+
+Fri May 8 18:46:59 1998 Theodore Y. Ts'o <tytso@mit.edu>
+
+ * kerberos_v4.c (krb4_stime): Print 4 digit years in Krb4 log
+ entries to avoid Y2K issues.
+
+Fri Mar 20 17:13:46 1998 Tom Yu <tlyu@mit.edu>
+
+ * kdc_util.c (add_to_transited): Check lengths, fix up comma
+ quoting somewhat (though things are still way broken).
+
+Thu Feb 5 19:09:06 1998 Tom Yu <tlyu@mit.edu>
+
+ * kerberos_v4.c: Fix up call to klog, also delete logic to check
+ whether v4 processing is disabled (relies on code that is only in
+ the mainline).
+
+Wed Feb 4 14:15:20 1998 Theodore Y. Ts'o <tytso@mit.edu>
+
+ * kerberos_v4.c (process_v4): Check the length of the incoming V4
+ packet before copying it into the KTEXT_ST variable.
+ (kerberos_v4): Make sure the strings in the V4 request
+ structures aren't no longer than they are allowed to be.
+
+Fri Jan 16 03:33:50 1998 Tom Yu <tlyu@mit.edu>
+
+ * do_tgs_req.c: Add some explicit settings of errcode so that the
+ cleanup code doesn't try to construct a bogus error reply, which
+ was causing coredumps in the lookaside code.
+
+Mon Nov 24 19:57:48 1997 Theodore Y. Ts'o <tytso@mit.edu>
+
+ * do_tgs_req.c (process_tgs_req): Add check to make sure cname and
+ sname are non-NULL when syslogging an error because the
+ principals don't match.
+
+ * kdc_util.c (limit_string): Check to make sure the input string
+ is non-NULL before operating on it.
+
+Wed Sep 24 11:56:50 1997 Ezra Peisach <epeisach@kangaroo.mit.edu>
+
+ * kdc_util.c (add_to_transited): Fix up memory leaks, clean out
+ new memory allocated, allocate buffers to max size
+ needed. [based on krb5-kdc/461 by Ken Hornstein].
+
+Wed Jul 30 18:29:19 1997 Tom Yu <tlyu@mit.edu>
+
+ * kdc_util.c:
+ * main.c: Don't use an rcache.
+
+Tue Jul 15 01:55:56 1997 Tom Yu <tlyu@mit.edu>
+
+ * kdc_preauth.c (get_sam_edata): Don't goto cleanup if SAM is not
+ used; this prevents freeing an unallocated keyblock.
+
+Thu May 29 21:08:24 1997 Theodore Y. Ts'o <tytso@mit.edu>
+
+ * do_as_req.c (process_as_req), do_tgs_req (process_tgs_req): Use
+ limit_string() to make sure the length of cname and sname
+ are reasonable.
+
+ * kdc_util.c (limit_string): New function which limits the strings
+ that will end up in log files to "reasonable" lengths.
+
+Wed Jan 1 22:56:16 1997 Ezra Peisach <epeisach@mit.edu>
+
+ * kdc_preauth.c (get_sam_edata): Use proper interface to
+ krb5_db_get_principal. Also if SAM is not an option, do
+ not return as a possible type to client. [krb5-kdc/310]
+
+Sat Nov 23 17:26:22 1996 Mark Eichin <eichin@kitten.gen.ma.us>
+
+ * [krb5-libs/149] only generate requests that you can actually
+ handle.
+
+ Tue Sep 3 22:53:56 1996 Mark Eichin <eichin@cygnus.com>
+
+ * kdc_preauth.c (get_preauth_hint_list): detect ap->get_edata
+ return status and don't pass back hint if it failed.
+ (get_etype_info): malloc one more word in entry for end marker.
+
+Wed Nov 20 11:25:05 1996 Barry Jaspan <bjaspan@mit.edu>
+
+ * main.c (initialize_realms): krb5_aprof_init can succeed while
+ leaving aprof == NULL, but krb5_aprof_finish will fail. This is
+ just more grossness that needs to be redone when the kdc.conf
+ interface is reworked.
+
Thu Nov 7 12:27:21 1996 Theodore Ts'o <tytso@rsts-11.mit.edu>
* kdc_preauth.c (check_padata): Fixed error handling; in order for
diff --git a/src/kdc/dispatch.c b/src/kdc/dispatch.c
index a94173c..7446ea5 100644
--- a/src/kdc/dispatch.c
+++ b/src/kdc/dispatch.c
@@ -43,7 +43,7 @@ dispatch(pkt, from, portnum, response)
/* decode incoming packet, and dispatch */
/* try the replay lookaside buffer */
- if (kdc_check_lookaside(pkt, response)) {
+ if (kdc_check_lookaside(pkt, from, response)) {
/* a hit! */
krb5_klog_syslog(LOG_INFO, "DISPATCH: replay found and re-transmitted");
return 0;
@@ -72,7 +72,7 @@ dispatch(pkt, from, portnum, response)
retval = KRB5KRB_AP_ERR_MSG_TYPE;
/* put the response into the lookaside buffer */
if (!retval)
- kdc_insert_lookaside(pkt, *response);
+ kdc_insert_lookaside(pkt, from, *response);
return retval;
}
diff --git a/src/kdc/do_as_req.c b/src/kdc/do_as_req.c
index cf999fe..bb2ca80 100644
--- a/src/kdc/do_as_req.c
+++ b/src/kdc/do_as_req.c
@@ -99,6 +99,7 @@ krb5_data **response; /* filled in with a response packet */
status = "UNPARSING_CLIENT";
goto errout;
}
+ limit_string(cname);
if (!request->server) {
status = "NULL_SERVER";
errcode = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
@@ -108,6 +109,7 @@ krb5_data **response; /* filled in with a response packet */
status = "UNPARSING_SERVER";
goto errout;
}
+ limit_string(sname);
c_nprincs = 1;
if ((errcode = krb5_db_get_principal(kdc_context, request->client,
diff --git a/src/kdc/do_tgs_req.c b/src/kdc/do_tgs_req.c
index 0ea2df1..242a6c3 100644
--- a/src/kdc/do_tgs_req.c
+++ b/src/kdc/do_tgs_req.c
@@ -130,6 +130,7 @@ krb5_data **response; /* filled in with a response packet */
}
if (!header_ticket) {
+ errcode = KRB5_NO_TKT_SUPPLIED; /* XXX? */
status="UNEXPECTED NULL in header_ticket";
goto cleanup;
}
@@ -419,6 +420,7 @@ tgt_again:
if (!(scratch.data =
malloc(request->authorization_data.ciphertext.length))) {
status = "AUTH_NOMEM";
+ errcode = ENOMEM;
goto cleanup;
}
/* do any necessary key pre-processing */
@@ -525,8 +527,11 @@ tgt_again:
&tmp)))
tmp = 0;
krb5_klog_syslog(LOG_INFO, "TGS_REQ %s(%d): 2ND_TKT_MISMATCH: authtime %d, %s for %s, 2nd tkt client %s",
- fromstring, portnum, authtime, cname, sname,
+ fromstring, portnum, authtime,
+ cname ? cname : "<unknown client>",
+ sname ? sname : "<unknown server>",
tmp ? tmp : "<unknown>");
+ errcode = KRB5KDC_ERR_SERVER_NOMATCH;
goto cleanup;
}
diff --git a/src/kdc/kdc_preauth.c b/src/kdc/kdc_preauth.c
index 0350068..4c28b0b 100644
--- a/src/kdc/kdc_preauth.c
+++ b/src/kdc/kdc_preauth.c
@@ -203,8 +203,15 @@ void get_preauth_hint_list(request, client, server, e_data)
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, request, client, server, *pa);
+ if (ap->get_edata) {
+ retval = (ap->get_edata)(kdc_context, request, client, server, *pa);
+ if (retval) {
+ /* just failed on this type, continue */
+ free(*pa);
+ *pa = 0;
+ continue;
+ }
+ }
pa++;
}
retval = encode_krb5_padata_sequence((const krb5_pa_data **) pa_data,
@@ -433,7 +440,7 @@ get_etype_info(context, request, client, server, pa_data)
salt.data = 0;
- entry = malloc((client->n_key_data * 2) * sizeof(krb5_etype_info_entry *));
+ entry = malloc((client->n_key_data * 2 + 1) * sizeof(krb5_etype_info_entry *));
if (entry == NULL)
return ENOMEM;
entry[0] = NULL;
@@ -630,7 +637,8 @@ get_sam_edata(context, request, client, server, pa_data)
{
char *uname;
- int npr = 1, more;
+ int npr = 1;
+ krb5_boolean more;
krb5_db_entry assoc;
krb5_key_data *assoc_key;
krb5_principal newp;
@@ -656,7 +664,7 @@ get_sam_edata(context, request, client, server, pa_data)
strlen(sam_ptr->name);
npr = 1;
retval = krb5_db_get_principal(kdc_context, newp, &assoc, &npr, &more);
- if(!retval) {
+ if(!retval && npr) {
sc.sam_type = sam_ptr->sam_type;
break;
}
@@ -690,7 +698,9 @@ get_sam_edata(context, request, client, server, pa_data)
}
/* now we can use encrypting_key... */
}
- }
+ } else
+ /* SAM is not an option - so don't return as hint */
+ return KRB5_PREAUTH_BAD_TYPE;
krb5_princ_component(kdc_context,newp,probeslot)->data = 0;
krb5_princ_component(kdc_context,newp,probeslot)->length = 0;
diff --git a/src/kdc/kdc_util.c b/src/kdc/kdc_util.c
index a711a27..f93b3d2 100644
--- a/src/kdc/kdc_util.c
+++ b/src/kdc/kdc_util.c
@@ -207,10 +207,11 @@ kdc_process_tgs_req(request, from, pkt, ticket, subkey)
if ((retval = krb5_auth_con_setaddrs(kdc_context, auth_context, NULL,
from->address)) )
goto cleanup_auth_context;
-
+#ifdef USE_RCACHE
if ((retval = krb5_auth_con_setrcache(kdc_context, auth_context,
kdc_rcache)))
goto cleanup_auth_context;
+#endif
/*
if ((retval = kdc_get_server_key(apreq->ticket, &key, &kvno)))
@@ -232,6 +233,7 @@ kdc_process_tgs_req(request, from, pkt, ticket, subkey)
apreq->ticket->server,
kdc_active_realm->realm_keytab,
NULL, ticket))) {
+#ifdef USE_RCACHE
/*
* I'm not so sure that this is right, but it's better than nothing
* at all.
@@ -256,6 +258,7 @@ kdc_process_tgs_req(request, from, pkt, ticket, subkey)
}
} else
goto cleanup_auth_context;
+#endif
}
/* "invalid flag" tickets can must be used to validate */
@@ -315,7 +318,9 @@ cleanup_authenticator:
cleanup_auth_context:
/* We do not want the free of the auth_context to close the rcache */
+#ifdef USE_RCACHE
(void) krb5_auth_con_setrcache(kdc_context, auth_context, 0);
+#endif
krb5_auth_con_free(kdc_context, auth_context);
cleanup:
@@ -530,9 +535,10 @@ add_to_transited(tgt_trans, new_trans, tgs, client, server)
krb5_principal client;
krb5_principal server;
{
+ krb5_error_code retval;
char *realm;
char *trans;
- char *otrans;
+ char *otrans, *otrans_ptr;
/* The following are for stepping through the transited field */
@@ -541,6 +547,7 @@ add_to_transited(tgt_trans, new_trans, tgs, client, server)
char current[MAX_REALM_LN];
char exp[MAX_REALM_LN]; /* Expanded current realm name */
+ int i;
int clst, nlst; /* count of last character in current and next */
int pl, pl1; /* prefix length */
int added; /* TRUE = new realm has been added */
@@ -553,35 +560,52 @@ add_to_transited(tgt_trans, new_trans, tgs, client, server)
realm[krb5_princ_realm(kdc_context, tgs)->length] = '\0';
if (!(otrans = (char *) malloc(tgt_trans->length+1))) {
+ free(realm);
return(ENOMEM);
}
memcpy(otrans, tgt_trans->data, tgt_trans->length);
otrans[tgt_trans->length] = '\0';
-
- if (!(trans = (char *) malloc(strlen(realm) + strlen(otrans) + 1))) {
- return(ENOMEM);
+ /* Keep track of start so we can free */
+ otrans_ptr = otrans;
+
+ /* +1 for null,
+ +1 for extra comma which may be added between
+ +1 for potential space when leading slash in realm */
+ if (!(trans = (char *) malloc(strlen(realm) + strlen(otrans) + 3))) {
+ retval = ENOMEM;
+ goto fail;
}
if (new_trans->data) free(new_trans->data);
new_trans->data = trans;
+ new_trans->length = 0;
+
+ trans[0] = '\0';
/* For the purpose of appending, the realm preceding the first */
/* realm in the transited field is considered the null realm */
prev[0] = '\0';
- /***** In next statement, need to keep reading if the , was quoted *****/
/* read field into current */
-
- if (sscanf(otrans, "%[^,]", current) == 1) {
- otrans += strlen(current);
- }
- else {
- current[0] = '\0';
+ for (i = 0; *otrans != '\0';) {
+ if (*otrans == '\\')
+ if (*(++otrans) == '\0')
+ break;
+ else
+ continue;
+ if (*otrans == ',') {
+ otrans++;
+ break;
+ }
+ current[i++] = *otrans++;
+ if (i >= MAX_REALM_LN) {
+ retval = KRB5KRB_AP_ERR_ILL_CR_TKT;
+ goto fail;
+ }
}
+ current[i] = '\0';
- if (otrans[0] == ',') otrans++;
-
added = (krb5_princ_realm(kdc_context, client)->length == strlen(realm) &&
!strncmp(krb5_princ_realm(kdc_context, client)->data, realm, strlen(realm))) ||
(krb5_princ_realm(kdc_context, server)->length == strlen(realm) &&
@@ -597,29 +621,43 @@ add_to_transited(tgt_trans, new_trans, tgs, client, server)
}
else if ((current[0] == '/') && (prev[0] == '/')) {
strcpy(exp, prev);
+ if (strlen(exp) + strlen(current) + 1 >= MAX_REALM_LN) {
+ retval = KRB5KRB_AP_ERR_ILL_CR_TKT;
+ goto fail;
+ }
strcat(exp, current);
}
else if (current[clst] == '.') {
strcpy(exp, current);
+ if (strlen(exp) + strlen(current) + 1 >= MAX_REALM_LN) {
+ retval = KRB5KRB_AP_ERR_ILL_CR_TKT;
+ goto fail;
+ }
strcat(exp, prev);
}
else {
strcpy(exp, current);
}
- /***** next statement, need to keep reading if the , was quoted *****/
/* read field into next */
-
- if (sscanf(otrans, "%[^,]", next) == 1) {
- otrans += strlen(next);
- nlst = strlen(next) - 1;
- }
- else {
- next[0] = '\0';
- nlst = 0;
+ for (i = 0; *otrans != '\0';) {
+ if (*otrans == '\\')
+ if (*(++otrans) == '\0')
+ break;
+ else
+ continue;
+ if (*otrans == ',') {
+ otrans++;
+ break;
+ }
+ next[i++] = *otrans++;
+ if (i >= MAX_REALM_LN) {
+ retval = KRB5KRB_AP_ERR_ILL_CR_TKT;
+ goto fail;
+ }
}
-
- if (otrans[0] == ',') otrans++;
+ next[i] = '\0';
+ nlst = i - 1;
if (!strcmp(exp, realm)) added = TRUE;
@@ -640,6 +678,10 @@ add_to_transited(tgt_trans, new_trans, tgs, client, server)
if ((next[nlst] != '.') && (next[0] != '/') &&
(pl = subrealm(exp, realm))) {
added = TRUE;
+ if (strlen(current) + (pl>0?pl:-pl) + 2 >= MAX_REALM_LN) {
+ retval = KRB5KRB_AP_ERR_ILL_CR_TKT;
+ goto fail;
+ }
strcat(current, ",");
if (pl > 0) {
strncat(current, realm, pl);
@@ -663,6 +705,10 @@ add_to_transited(tgt_trans, new_trans, tgs, client, server)
added = TRUE;
current[0] = '\0';
if ((pl1 = subrealm(prev,realm))) {
+ if (strlen(current) + (pl1>0?pl1:-pl1) + 1 >= MAX_REALM_LN) {
+ retval = KRB5KRB_AP_ERR_ILL_CR_TKT;
+ goto fail;
+ }
if (pl1 > 0) {
strncat(current, realm, pl1);
}
@@ -672,10 +718,22 @@ add_to_transited(tgt_trans, new_trans, tgs, client, server)
}
else { /* If not a subrealm */
if ((realm[0] == '/') && prev[0]) {
- strcat(current, " ");
+ if (strlen(current) + 2 >= MAX_REALM_LN) {
+ retval = KRB5KRB_AP_ERR_ILL_CR_TKT;
+ goto fail;
+ }
+ strcat(current, " ");
}
+ if (strlen(current) + strlen(realm) + 1 >= MAX_REALM_LN) {
+ retval = KRB5KRB_AP_ERR_ILL_CR_TKT;
+ goto fail;
+ }
strcat(current, realm);
}
+ if (strlen(current) + (pl>0?pl:-pl) + 2 >= MAX_REALM_LN) {
+ retval = KRB5KRB_AP_ERR_ILL_CR_TKT;
+ goto fail;
+ }
strcat(current,",");
if (pl > 0) {
strncat(current, exp, pl);
@@ -686,7 +744,17 @@ add_to_transited(tgt_trans, new_trans, tgs, client, server)
}
}
- if (new_trans->length != 0) strcat(trans, ",");
+ if (new_trans->length != 0) {
+ if (strlen(trans) + 2 >= MAX_REALM_LN) {
+ retval = KRB5KRB_AP_ERR_ILL_CR_TKT;
+ goto fail;
+ }
+ strcat(trans, ",");
+ }
+ if (strlen(trans) + strlen(current) + 1 >= MAX_REALM_LN) {
+ retval = KRB5KRB_AP_ERR_ILL_CR_TKT;
+ goto fail;
+ }
strcat(trans, current);
new_trans->length = strlen(trans) + 1;
@@ -695,13 +763,33 @@ add_to_transited(tgt_trans, new_trans, tgs, client, server)
}
if (!added) {
- if (new_trans->length != 0) strcat(trans, ",");
- if((realm[0] == '/') && trans[0]) strcat(trans, " ");
+ if (new_trans->length != 0) {
+ if (strlen(trans) + 2 >= MAX_REALM_LN) {
+ retval = KRB5KRB_AP_ERR_ILL_CR_TKT;
+ goto fail;
+ }
+ strcat(trans, ",");
+ }
+ if((realm[0] == '/') && trans[0]) {
+ if (strlen(trans) + 2 >= MAX_REALM_LN) {
+ retval = KRB5KRB_AP_ERR_ILL_CR_TKT;
+ goto fail;
+ }
+ strcat(trans, " ");
+ }
+ if (strlen(trans) + strlen(realm) + 1 >= MAX_REALM_LN) {
+ retval = KRB5KRB_AP_ERR_ILL_CR_TKT;
+ goto fail;
+ }
strcat(trans, realm);
new_trans->length = strlen(trans) + 1;
}
- return(0);
+ retval = 0;
+fail:
+ free(realm);
+ free(otrans_ptr);
+ return (retval);
}
/*
@@ -912,7 +1000,7 @@ krb5_data *data;
{
unsigned char *estream; /* end of stream */
int classes; /* # classes seen so far this level */
- int levels = 0; /* levels seen so far */
+ unsigned int levels = 0; /* levels seen so far */
int lastlevel = 1000; /* last level seen */
int length; /* various lengths */
int tag; /* tag number */
@@ -1375,8 +1463,26 @@ get_salt_from_key(context, client, client_key, salt)
return 0;
}
+/*
+ * Limit strings to a "reasonable" length to prevent crowding out of
+ * other useful information in the log entry
+ */
+#define NAME_LENGTH_LIMIT 128
-
-
-
-
+void limit_string(char *name)
+{
+ int i;
+
+ if (!name)
+ return;
+
+ if (strlen(name) < NAME_LENGTH_LIMIT)
+ return;
+
+ i = NAME_LENGTH_LIMIT-4;
+ name[i++] = '.';
+ name[i++] = '.';
+ name[i++] = '.';
+ name[i] = '\0';
+ return;
+}
diff --git a/src/kdc/kdc_util.h b/src/kdc/kdc_util.h
index b869f6f..c9e0d23 100644
--- a/src/kdc/kdc_util.h
+++ b/src/kdc/kdc_util.h
@@ -145,8 +145,10 @@ krb5_error_code return_padata
krb5_key_data *client_key, krb5_keyblock *encrypting_key));
/* replay.c */
-krb5_boolean kdc_check_lookaside PROTOTYPE((krb5_data *, krb5_data **));
-void kdc_insert_lookaside PROTOTYPE((krb5_data *, krb5_data *));
+krb5_boolean kdc_check_lookaside PROTOTYPE((krb5_data *, krb5_fulladdr *,
+ krb5_data **));
+void kdc_insert_lookaside PROTOTYPE((krb5_data *, krb5_fulladdr *,
+ krb5_data *));
/* which way to convert key? */
#define CONVERT_INTO_DB 0
diff --git a/src/kdc/kerberos_v4.c b/src/kdc/kerberos_v4.c
index db074d9..cea4bf0 100644
--- a/src/kdc/kerberos_v4.c
+++ b/src/kdc/kerberos_v4.c
@@ -82,6 +82,7 @@ char * v4_klog KRB5_PROTOTYPE((int, const char *, ...));
#else
char * v4_klog KRB5_PROTOTYPE((int, char *, va_dcl));
#endif
+#define klog v4_klog
/* take this out when we don't need it anymore */
int krbONE = 1;
@@ -104,7 +105,7 @@ static Principal a_name_data; /* for requesting user */
static Principal s_name_data; /* for services requested */
static C_Block session_key;
-static char log_text[128];
+static char log_text[512];
static char *lt;
static int more;
@@ -190,6 +191,10 @@ krb5_data **resp;
/* convert v5 packet structure to v5's.
* this copy is gross, but necessary:
*/
+ if (pkt->length > MAX_KTXT_LEN) {
+ (void) klog(L_KRB_PERR, "V4 request too long.");
+ return KRB5KRB_ERR_FIELD_TOOLONG;
+ }
v4_pkt.length = pkt->length;
memcpy( v4_pkt.dat, pkt->data, pkt->length);
@@ -218,7 +223,6 @@ int type_2_v5err[] = { 0, /* 0 No error */
KRB_AP_ERR_BADVERSION /* L_KRB_PWARN 16 Protocol warning messages */
};
#endif
-#define klog v4_klog
#ifdef HAVE_STDARG_H
char * v4_klog( int type, const char *format, ...)
#else
@@ -448,6 +452,21 @@ kerb_get_principal(name, inst, principal, maxn, more)
*more = (int) more5 || (nprinc > maxn);
return( nprinc);
}
+
+static void str_length_check(str, max_size)
+ char *str;
+ int max_size;
+{
+ int i;
+ char *cp;
+
+ for (i=0, cp = str; i < max_size-1; i++, cp++) {
+ if (*cp == 0)
+ return;
+ }
+ *cp = 0;
+}
+
void
kerberos_v4(client, pkt)
struct sockaddr_in *client;
@@ -528,8 +547,11 @@ kerberos_v4(client, pkt)
/* set up and correct for byte order and alignment */
req_name_ptr = (char *) pkt_a_name(pkt);
+ str_length_check(req_name_ptr, ANAME_SZ);
req_inst_ptr = (char *) pkt_a_inst(pkt);
+ str_length_check(req_inst_ptr, INST_SZ);
req_realm_ptr = (char *) pkt_a_realm(pkt);
+ str_length_check(req_realm_ptr, REALM_SZ);
memcpy(&req_time_ws, pkt_time_ws(pkt), sizeof(req_time_ws));
/* time has to be diddled */
if (swap_bytes) {
@@ -540,7 +562,9 @@ kerberos_v4(client, pkt)
req_life = (u_long) (*ptr++);
service = ptr;
+ str_length_check(service, SNAME_SZ);
instance = ptr + strlen(service) + 1;
+ str_length_check(instance, INST_SZ);
rpkt = &rpkt_st;
@@ -672,7 +696,9 @@ kerberos_v4(client, pkt)
req_life = (u_long) (*ptr++);
service = ptr;
+ str_length_check(service, SNAME_SZ);
instance = ptr + strlen(service) + 1;
+ str_length_check(instance, INST_SZ);
klog(L_APPL_REQ, "APPL Request %s.%s@%s on %s for %s.%s",
ad->pname, ad->pinst, ad->prealm,
@@ -872,7 +898,7 @@ static char *krb4_stime(t)
adjusted_time = *t /* - CONVERT_TIME_EPOCH */;
tm = localtime(&adjusted_time);
- (void) sprintf(st,"%2d-%s-%02d %02d:%02d:%02d",tm->tm_mday,
+ (void) sprintf(st,"%4d-%s-%02d %02d:%02d:%02d",tm->tm_mday+1900,
month_sname(tm->tm_mon + 1),tm->tm_year,
tm->tm_hour, tm->tm_min, tm->tm_sec);
return st;
diff --git a/src/kdc/main.c b/src/kdc/main.c
index dd4ae76..2dff8fc 100644
--- a/src/kdc/main.c
+++ b/src/kdc/main.c
@@ -721,7 +721,9 @@ initialize_realms(kcontext, argc, argv)
hierarchy[2] = (char *) NULL;
if (krb5_aprof_get_string(aprof, hierarchy, TRUE, &default_ports))
default_ports = 0;
- krb5_aprof_finish(aprof);
+ /* aprof_init can return 0 with aprof == NULL */
+ if (aprof)
+ krb5_aprof_finish(aprof);
}
if (default_ports == 0)
default_ports = strdup(DEFAULT_KDC_PORTLIST);
@@ -803,6 +805,7 @@ initialize_realms(kcontext, argc, argv)
}
}
+#ifdef USE_RCACHE
/*
* Now handle the replay cache.
*/
@@ -810,6 +813,7 @@ initialize_realms(kcontext, argc, argv)
com_err(argv[0], retval, "while initializing KDC replay cache");
exit(1);
}
+#endif
/* Ensure that this is set for our first request. */
kdc_active_realm = kdc_realmlist[0];
diff --git a/src/kdc/replay.c b/src/kdc/replay.c
index 1ec38a3..ffd14fe 100644
--- a/src/kdc/replay.c
+++ b/src/kdc/replay.c
@@ -36,6 +36,7 @@ typedef struct _krb5_kdc_replay_ent {
time_t db_age;
krb5_data *req_packet;
krb5_data *reply_packet;
+ krb5_address *addr; /* XXX should these not be pointers? */
} krb5_kdc_replay_ent;
static krb5_kdc_replay_ent root_ptr = {0};
@@ -46,13 +47,16 @@ static int max_hits_per_entry = 0;
static int num_entries = 0;
#define STALE_TIME 2*60 /* two minutes */
-#define STALE(ptr) ((abs((ptr)->timein - timenow) >= STALE_TIME) || \
+#define STALE(ptr) ((abs((ptr)->timein - timenow) >= STALE_TIME) || \
((ptr)->db_age != db_age))
-#define MATCH(ptr) (((ptr)->req_packet->length == inpkt->length) && \
- !memcmp((ptr)->req_packet->data, inpkt->data, inpkt->length) && \
+#define MATCH(ptr) (((ptr)->req_packet->length == inpkt->length) && \
+ !memcmp((ptr)->req_packet->data, inpkt->data, \
+ inpkt->length) && \
+ ((ptr)->addr->length == from->address->length) && \
+ !memcmp((ptr)->addr->contents, from->address, \
+ from->address->length)&& \
((ptr)->db_age == db_age))
-
/* XXX
Todo: quench the size of the queue...
*/
@@ -61,9 +65,10 @@ static int num_entries = 0;
FALSE if the caller should do the work */
krb5_boolean
-kdc_check_lookaside(inpkt, outpkt)
-register krb5_data *inpkt;
-register krb5_data **outpkt;
+kdc_check_lookaside(inpkt, from, outpkt)
+ register krb5_data *inpkt;
+ register krb5_fulladdr *from;
+ register krb5_data **outpkt;
{
krb5_int32 timenow;
register krb5_kdc_replay_ent *eptr, *last, *hold;
@@ -71,7 +76,7 @@ register krb5_data **outpkt;
if (krb5_timeofday(kdc_context, &timenow) ||
krb5_db_get_age(kdc_context, 0, &db_age))
- return FALSE;
+ return FALSE;
calls++;
@@ -98,6 +103,7 @@ register krb5_data **outpkt;
max_hits_per_entry = max(max_hits_per_entry, eptr->num_hits);
krb5_free_data(kdc_context, eptr->req_packet);
krb5_free_data(kdc_context, eptr->reply_packet);
+ krb5_free_address(kdc_context, eptr->addr);
hold = eptr;
last->next = eptr->next;
eptr = last;
@@ -115,9 +121,10 @@ register krb5_data **outpkt;
already there, and can fail softly due to other weird errors. */
void
-kdc_insert_lookaside(inpkt, outpkt)
-register krb5_data *inpkt;
-register krb5_data *outpkt;
+kdc_insert_lookaside(inpkt, from, outpkt)
+ register krb5_data *inpkt;
+ register krb5_fulladdr *from;
+ register krb5_data *outpkt;
{
register krb5_kdc_replay_ent *eptr;
krb5_int32 timenow;
@@ -125,7 +132,7 @@ register krb5_data *outpkt;
if (krb5_timeofday(kdc_context, &timenow) ||
krb5_db_get_age(kdc_context, 0, &db_age))
- return;
+ return;
/* this is a new entry */
eptr = (krb5_kdc_replay_ent *)calloc(1, sizeof(*eptr));
@@ -133,6 +140,11 @@ register krb5_data *outpkt;
return;
eptr->timein = timenow;
eptr->db_age = db_age;
+ /*
+ * This is going to hurt a lot malloc()-wise due to the need to
+ * allocate memory for the krb5_data and krb5_address elements.
+ * ARGH!
+ */
if (krb5_copy_data(kdc_context, inpkt, &eptr->req_packet)) {
krb5_xfree(eptr);
return;
@@ -142,6 +154,12 @@ register krb5_data *outpkt;
krb5_xfree(eptr);
return;
}
+ if (krb5_copy_addr(kdc_context, from->address, &eptr->addr)) {
+ krb5_free_data(kdc_context, eptr->req_packet);
+ krb5_free_data(kdc_context, eptr->reply_packet);
+ free(eptr);
+ return;
+ }
eptr->next = root_ptr.next;
root_ptr.next = eptr;
num_entries++;