+Wed Nov 8 02:57:15 1995 Theodore Y. Ts'o <tytso@dcl>
+
+ * kdc_util.c (): Added new helper functions
+ dbentry_has_key_for_enctype(), dbentry_supports_enctype(),
+ and select_session_keytype().
+
+ * kdc_preauth.c: Added support for the ENC_TIMESTAMP
+ preauthentication scheme.
+
+ * do_tgs_req.c (process_tgs_req): Fixed the keytype/enctype
+ selection criteria for the server key, and the ticket
+ session key.
+
+ * do_as_req.c (process_as_req): Added calls to the kdc
+ preauthentication verification routines. Fixed the
+ keytype/enctype selection criteria for the client key, the
+ server key, and the ticket session key.
+
+ * main.c (finish_realm): Make sure all parts of the realm
+ structure are freed properly.
+ (main): Free the kcontext krb5_context.
+
Fri Oct 6 00:07:49 1995 Theodore Y. Ts'o <tytso@dcl>
* kdc_preauth.c (get_preauth_hint_list): Fix missing indirection
int,
krb5_data *,
krb5_data **));
-/*
- * This routine is called to verify the preauthentication information
- * for a V5 request. Client contains information about the principal
- * from the database. Padata contains pre-auth info received from
- * the network.
- *
- * Returns 0 if the pre-authentication is valid, non-zero to indicate
- * an error code of some sort.
- */
-
-static krb5_error_code
-check_padata (client, src_addr, padata, pa_id, flags)
- krb5_db_entry *client;
- krb5_address **src_addr;
- krb5_pa_data **padata;
- int *pa_id; /* Unique id which can be used for replay
- of padata. */
- int *flags;
-{
- krb5_error_code retval;
- krb5_keyblock tmpkey;
- int i;
-
- /* Extract a client key from master key */
- retval = 0;
- for (i = 0; i < client->n_key_data; i++) {
- if ((retval = krb5_dbekd_decrypt_key_data(kdc_context,
- &master_encblock,
- &client->key_data[i],
- &tmpkey, NULL))) {
- krb5_klog_syslog(LOG_ERR,"AS_REQ: Unable to extract client key: %s",
- error_message(retval));
- return retval;
- }
- retval = krb5_verify_padata(kdc_context, *padata, client->princ,
- src_addr, &tmpkey, pa_id, flags);
- memset((char *)tmpkey.contents, 0, tmpkey.length);
- krb5_xfree(tmpkey.contents);
- if (!retval)
- break;
- }
- return retval;
-}
/*ARGSUSED*/
krb5_error_code
goto errout;
}
- for (i = 0; i < request->nktypes; i++) {
- if (!valid_enctype(request->ktype[i]))
- continue;
-
- if (request->ktype[i] == ENCTYPE_DES_CBC_MD5 &&
- !isflagset(server.attributes, KRB5_KDB_SUPPORT_DESMD5))
- continue;
-
- /*
- * Find the server key of the appropriate type. If we could specify
- * a kvno, it would be supplied here.
- */
- if (!krb5_dbe_find_enctype(kdc_context, &server, request->ktype[i],
- -1, /* Ignore salttype */
- -1, /* Get highest kvno */
- &server_key))
- goto got_a_key;
+ /*
+ * Select the keytype for the ticket session key.
+ */
+ if ((useenctype = select_session_keytype(kdc_context, &server,
+ request->nktypes,
+ request->ktype)) == 0) {
+ /* unsupported ktype */
+ status = "BAD_ENCRYPTION_TYPE";
+ errcode = KRB5KDC_ERR_ETYPE_NOSUPP;
+ goto errout;
}
-
- /* unsupported ktype */
- status = "BAD_ENCRYPTION_TYPE";
- errcode = KRB5KDC_ERR_ETYPE_NOSUPP;
- goto errout;
-
-got_a_key:;
- useenctype = request->ktype[i];
- krb5_use_enctype(kdc_context, &eblock, request->ktype[i]);
+ krb5_use_enctype(kdc_context, &eblock, useenctype);
if ((errcode = krb5_random_key(kdc_context, &eblock,
krb5_enctype_array[useenctype]->random_sequence,
* Check the preauthentication if it is there.
*/
if (request->padata) {
- errcode = check_padata(&client,request->addresses,
- request->padata, &pa_id, &pa_flags);
+ errcode = check_padata(kdc_context, &client, request, &enc_tkt_reply);
if (errcode) {
#ifdef KRBCONF_KDC_MODIFIES_KDB
/*
#endif
goto errout;
}
- setflag(enc_tkt_reply.flags, TKT_FLG_PRE_AUTH);
- /*
- * If pa_type is one in which additional hardware authentication
- * was performed set TKT_FLG_HW_AUTH too.
- */
- if (pa_flags & KRB5_PREAUTH_FLAGS_HARDWARE)
- setflag(enc_tkt_reply.flags, TKT_FLG_HW_AUTH);
}
/*
ticket_reply.enc_part2 = &enc_tkt_reply;
+ /*
+ * Find the server key
+ */
+ if ((errcode = krb5_dbe_find_enctype(kdc_context, &server,
+ -1, /* ignore keytype */
+ -1, /* Ignore salttype */
+ 0, /* Get highest kvno */
+ &server_key))) {
+ status = "FINDING_SERVER_KEY";
+ goto errout;
+ }
+
/* convert server.key into a real key (it may be encrypted
in the database) */
if ((errcode = krb5_dbekd_decrypt_key_data(kdc_context, &master_encblock,
- server_key,
- &encrypting_key, NULL))) {
+ server_key, &encrypting_key,
+ NULL))) {
status = "DECRYPT_SERVER_KEY";
goto errout;
}
- errcode = krb5_encrypt_tkt_part(kdc_context, &eblock, &encrypting_key,
- &ticket_reply);
+ if ((encrypting_key.enctype == ENCTYPE_DES_CBC_CRC) &&
+ (isflagset(server.attributes, KRB5_KDB_SUPPORT_DESMD5)))
+ encrypting_key.enctype = ENCTYPE_DES_CBC_MD5;
+
+ errcode = krb5_encrypt_tkt_part(kdc_context, &encrypting_key, &ticket_reply);
memset((char *)encrypting_key.contents, 0, encrypting_key.length);
krb5_xfree(encrypting_key.contents);
if (errcode) {
/*
* Find the appropriate client key. We search in the order specified
- * by the key/salt list.
+ * by request keytype list.
*/
client_key = (krb5_key_data *) NULL;
- for (i=0; i<kdc_active_realm->realm_nkstypes; i++) {
- krb5_key_salt_tuple *kslist;
-
- kslist = (krb5_key_salt_tuple *) kdc_active_realm->realm_kstypes;
- if (!krb5_dbe_find_enctype(kdc_context,
- &client,
- kslist[i].ks_enctype,
- kslist[i].ks_salttype,
- -1,
- &client_key))
+ for (i = 0; i < request->nktypes; i++) {
+ useenctype = request->ktype[i];
+ if (!valid_enctype(useenctype))
+ continue;
+
+ if (!krb5_dbe_find_enctype(kdc_context, &client, useenctype, -1,
+ 0, &client_key))
break;
}
if (!(client_key)) {
/* convert client.key_data into a real key */
if ((errcode = krb5_dbekd_decrypt_key_data(kdc_context, &master_encblock,
- client_key,
- &encrypting_key, NULL))) {
+ client_key, &encrypting_key,
+ NULL))) {
status = "DECRYPT_CLIENT_KEY";
goto errout;
}
+ encrypting_key.enctype = useenctype;
errcode = krb5_encode_kdc_rep(kdc_context, KRB5_AS_REP, &reply_encpart,
&eblock, &encrypting_key, &reply, response);
{
krb5_keyblock * subkey;
krb5_encrypt_block eblock;
- krb5_enctype second_ticket_ktype = ENCTYPE_UNKNOWN;
krb5_kdc_req *request = 0;
krb5_db_entry server;
krb5_kdc_rep reply;
krb5_keyblock *session_key = 0;
krb5_timestamp until, rtime;
krb5_keyblock encrypting_key;
+ krb5_key_data *server_key;
char *cname = 0, *sname = 0, *tmp = 0, *fromstring = 0;
krb5_last_req_entry *nolrarray[2], nolrentry;
/* krb5_address *noaddrarray[1]; */
int errcode, errcode2;
register int i;
int firstpass = 1;
- int ok_key_data = 0;
const char *status = 0;
retval = decode_krb5_tgs_req(pkt, &request);
goto cleanup;
}
- if ((retval = krb5_timeofday(kdc_context, &kdc_time))) {
+ if ((errcode = krb5_timeofday(kdc_context, &kdc_time))) {
status = "TIME_OF_DAY";
goto cleanup;
}
}
/*
- * If we are using user-to-user authentication, then the resulting
- * ticket has to use the same encryption system as was used to
- * encrypt the ticket, since that's the same encryption system
- * that's used for the ticket session key --- and that's what we
- * use to encrypt the ticket!
+ * We pick the session keytype here....
+ *
+ * Some special care needs to be taken in the user-to-user
+ * case, since we don't know what keytypes the application server
+ * which is doing user-to-user authentication can support. We
+ * know that it at least must be able to support the encryption
+ * type of the session key in the TGT, since otherwise it won't be
+ * able to decrypt the U2U ticket! So we use that in preference
+ * to anything else.
*/
- if (isflagset(request->kdc_options, KDC_OPT_ENC_TKT_IN_SKEY))
- second_ticket_ktype = request->second_ticket[st_idx]->enc_part.enctype;
-
- for (i = 0; i < request->nktypes; i++) {
- krb5_enctype ok_enctype;
-
- if (!valid_enctype(request->ktype[i]))
- continue;
-
- if (second_ticket_ktype != ENCTYPE_UNKNOWN &&
- second_ticket_ktype != request->ktype[i])
- continue;
-
- if (request->ktype[i] == ENCTYPE_DES_CBC_MD5 &&
- !isflagset(server.attributes, KRB5_KDB_SUPPORT_DESMD5))
- continue;
+ useenctype = 0;
+ if (isflagset(request->kdc_options, KDC_OPT_ENC_TKT_IN_SKEY)) {
+ krb5_keyblock * st_sealing_key;
+ krb5_kvno st_srv_kvno;
+ krb5_enctype etype;
- ok_enctype = request->ktype[i];
+ /*
+ * Get the key for the second ticket, and decrypt it.
+ */
+ if ((errcode = kdc_get_server_key(request->second_ticket[st_idx],
+ &st_sealing_key,
+ &st_srv_kvno))) {
+ status = "2ND_TKT_SERVER";
+ goto cleanup;
+ }
+ errcode = krb5_decrypt_tkt_part(kdc_context, st_sealing_key,
+ request->second_ticket[st_idx]);
+ krb5_free_keyblock(kdc_context, st_sealing_key);
+ if (errcode) {
+ status = "2ND_TKT_DECRYPT";
+ goto cleanup;
+ }
+
+ etype = request->second_ticket[st_idx]->enc_part2->session->enctype;
+ if (!valid_enctype(etype)) {
+ status = "BAD_ETYPE_IN_2ND_TKT";
+ errcode = KRB5KDC_ERR_ETYPE_NOSUPP;
+ goto cleanup;
+ }
+
+ for (i = 0; i < request->nktypes; i++) {
+ if (request->ktype[i] == etype) {
+ useenctype = etype;
+ break;
+ }
+ }
+ }
- for (ok_key_data = 0; ok_key_data < server.n_key_data; ok_key_data++)
- if (server.key_data[ok_key_data].key_data_type[0] == ok_enctype)
- goto got_a_key;
+ /*
+ * Select the keytype for the ticket session key.
+ */
+ if ((useenctype == 0) &&
+ (useenctype = select_session_keytype(kdc_context, &server,
+ request->nktypes,
+ request->ktype)) == 0) {
+ /* unsupported ktype */
+ status = "BAD_ENCRYPTION_TYPE";
+ errcode = KRB5KDC_ERR_ETYPE_NOSUPP;
+ goto cleanup;
}
- /* unsupported ktype */
- errcode = KRB5KDC_ERR_ETYPE_NOSUPP;
- status = "BAD_ENCRYPTION_TYPE";
- goto cleanup;
-
-got_a_key:;
- useenctype = request->ktype[i];
krb5_use_enctype(kdc_context, &eblock, useenctype);
- retval = krb5_random_key(kdc_context, &eblock,
+ errcode = krb5_random_key(kdc_context, &eblock,
krb5_enctype_array[useenctype]->random_sequence,
&session_key);
- if (retval) {
+ if (errcode) {
/* random key failed */
status = "RANDOM_KEY_FAILED";
goto cleanup;
goto cleanup;
}
/* do any necessary key pre-processing */
- if ((retval = krb5_process_key(kdc_context, &eblock,
+ if ((errcode = krb5_process_key(kdc_context, &eblock,
header_ticket->enc_part2->session))) {
status = "AUTH_PROCESS_KEY";
free(scratch.data);
}
/* call the encryption routine */
- if ((retval = krb5_decrypt(kdc_context, (krb5_pointer) request->authorization_data.ciphertext.data,
+ if ((errcode = krb5_decrypt(kdc_context, (krb5_pointer) request->authorization_data.ciphertext.data,
(krb5_pointer) scratch.data,
scratch.length, &eblock, 0))) {
status = "AUTH_ENCRYPT_FAIL";
free(scratch.data);
goto cleanup;
}
- if ((retval = krb5_finish_key(kdc_context, &eblock))) {
+ if ((errcode = krb5_finish_key(kdc_context, &eblock))) {
status = "AUTH_FINISH_KEY";
free(scratch.data);
goto cleanup;
}
/* scratch now has the authorization data, so we decode it */
- retval = decode_krb5_authdata(&scratch, &(request->unenc_authdata));
+ errcode = decode_krb5_authdata(&scratch, &(request->unenc_authdata));
free(scratch.data);
- if (retval) {
+ if (errcode) {
status = "AUTH_DECODE";
goto cleanup;
}
- if ((retval =
+ if ((errcode =
concat_authorization_data(request->unenc_authdata,
header_ticket->enc_part2->authorization_data,
&enc_tkt_reply.authorization_data))) {
enc_tkt_transited.tr_contents.data = 0;
enc_tkt_transited.tr_contents.length = 0;
enc_tkt_reply.transited = enc_tkt_transited;
- if ((retval =
+ if ((errcode =
add_to_transited(&header_ticket->enc_part2->transited.tr_contents,
&enc_tkt_reply.transited.tr_contents,
header_ticket->server,
* the second ticket.
*/
if (isflagset(request->kdc_options, KDC_OPT_ENC_TKT_IN_SKEY)) {
- krb5_keyblock *st_sealing_key;
- krb5_kvno st_srv_kvno;
-
- if ((retval = kdc_get_server_key(request->second_ticket[st_idx],
- &st_sealing_key,
- &st_srv_kvno))) {
- status = "2ND_TKT_SERVER";
- goto cleanup;
- }
-
- /* decrypt the ticket */
- retval = krb5_decrypt_tkt_part(kdc_context, st_sealing_key,
- request->second_ticket[st_idx]);
- krb5_free_keyblock(kdc_context, st_sealing_key);
- if (retval) {
- status = "2ND_TKT_DECRYPT";
- goto cleanup;
- }
-
/*
* Make sure the client for the second ticket matches
* requested server.
*/
if (!krb5_principal_compare(kdc_context, request->server,
request->second_ticket[st_idx]->enc_part2->client)) {
- if ((retval = krb5_unparse_name(kdc_context,
+ if ((errcode = krb5_unparse_name(kdc_context,
request->second_ticket[st_idx]->enc_part2->client,
&tmp)))
tmp = 0;
ticket_reply.enc_part.enctype =
request->second_ticket[st_idx]->enc_part2->session->enctype;
krb5_use_enctype(kdc_context, &eblock, ticket_reply.enc_part.enctype);
- if ((retval = krb5_encrypt_tkt_part(kdc_context, &eblock,
+ if ((errcode = krb5_encrypt_tkt_part(kdc_context,
request->second_ticket[st_idx]->enc_part2->session,
&ticket_reply))) {
status = "2ND_TKT_ENCRYPT";
}
st_idx++;
} else {
+ /*
+ * Find the server key
+ */
+ if ((errcode = krb5_dbe_find_enctype(kdc_context, &server,
+ -1, /* ignore keytype */
+ -1, /* Ignore salttype */
+ 0, /* Get highest kvno */
+ &server_key))) {
+ status = "FINDING_SERVER_KEY";
+ goto cleanup;
+ }
/* convert server.key into a real key (it may be encrypted
- in the database) */
- if ((retval = krb5_dbekd_decrypt_key_data(kdc_context, &master_encblock,
- &server.key_data[ok_key_data],
- &encrypting_key, NULL))) {
- status = "CONV_KEY";
+ * in the database) */
+ if ((errcode = krb5_dbekd_decrypt_key_data(kdc_context,
+ &master_encblock,
+ server_key, &encrypting_key,
+ NULL))) {
+ status = "DECRYPT_SERVER_KEY";
goto cleanup;
}
-
- ticket_reply.enc_part.kvno = server.key_data[ok_key_data].key_data_kvno;
- ticket_reply.enc_part.enctype = useenctype;
- krb5_use_enctype(kdc_context, &eblock, ticket_reply.enc_part.enctype);
- retval = krb5_encrypt_tkt_part(kdc_context, &eblock, &encrypting_key,
- &ticket_reply);
-
+ if ((encrypting_key.enctype == ENCTYPE_DES_CBC_CRC) &&
+ (isflagset(server.attributes, KRB5_KDB_SUPPORT_DESMD5)))
+ encrypting_key.enctype = ENCTYPE_DES_CBC_MD5;
+ ticket_reply.enc_part.kvno = server_key->key_data_kvno;
+ errcode = krb5_encrypt_tkt_part(kdc_context, &encrypting_key,
+ &ticket_reply);
memset((char *)encrypting_key.contents, 0, encrypting_key.length);
krb5_xfree(encrypting_key.contents);
-
- if (retval) {
+ if (errcode) {
status = "TKT_ENCRYPT";
goto cleanup;
}
header_ticket->enc_part2->session->enctype;
krb5_use_enctype(kdc_context, &eblock, reply.enc_part.enctype);
- retval = krb5_encode_kdc_rep(kdc_context, KRB5_TGS_REP, &reply_encpart,
+ errcode = krb5_encode_kdc_rep(kdc_context, KRB5_TGS_REP, &reply_encpart,
&eblock, subkey ? subkey :
header_ticket->enc_part2->session,
&reply, response);
- if (retval) {
+ if (errcode) {
status = "ENCODE_KDC_REP";
} else {
status = "ISSUE";
#include <stdio.h>
typedef krb5_error_code (verify_proc)
- KRB5_PROTOTYPE((krb5_context, krb5_principal client,
- krb5_address **src_addr,
- krb5_data *data));
+ KRB5_PROTOTYPE((krb5_context, krb5_db_entry *client,
+ krb5_kdc_req *request,
+ krb5_enc_tkt_part * enc_tkt_reply, krb5_pa_data *data));
typedef krb5_error_code (edata_proc)
- KRB5_PROTOTYPE((krb5_context, krb5_db_entry *client,
- krb5_pa_data *data));
+ KRB5_PROTOTYPE((krb5_context, krb5_db_entry *client, krb5_pa_data *data));
typedef struct _krb5_preauth_systems {
int type;
verify_proc *verify;
} krb5_preauth_systems;
+static verify_proc verify_enc_timestamp;
+
/*
* Preauth property flags
*/
-#define PA_ENCRYPT 0x00000001
-#define PA_HARDWARE 0x00000002
+#define PA_HARDWARE 0x00000001
+#define PA_REQUIRED 0x00000002
+#define PA_SUFFICIENT 0x00000004
static krb5_preauth_systems preauth_systems[] = {
{
- KRB5_PADATA_ENC_UNIX_TIME,
- PA_ENCRYPT,
+ KRB5_PADATA_ENC_TIMESTAMP,
0,
- 0,
- },
- {
- KRB5_PADATA_ENC_SANDIA_SECURID,
- PA_ENCRYPT | PA_HARDWARE,
- 0,
- 0,
+ 0,
+ verify_enc_timestamp,
},
{ -1,}
};
#define MAX_PREAUTH_SYSTEMS (sizeof(preauth_systems)/sizeof(preauth_systems[0]))
+static krb5_error_code
+find_pa_system(type, preauth)
+ int type;
+ krb5_preauth_systems **preauth;
+{
+ krb5_preauth_systems *ap = preauth_systems;
+
+ while ((ap->type != -1) && (ap->type != type))
+ ap++;
+ if (ap->type == -1)
+ return(KRB5_PREAUTH_BAD_TYPE);
+ *preauth = ap;
+ return 0;
+}
+
+krb5_error_code
+krb5_decrypt_data(context, key, ivec, enc_data, data)
+ krb5_context context;
+ krb5_keyblock * key;
+ krb5_pointer ivec;
+ krb5_enc_data * enc_data;
+ krb5_data * data;
+{
+ krb5_error_code retval;
+ krb5_encrypt_block eblock;
+
+ krb5_use_enctype(context, &eblock, key->enctype);
+ data->length = enc_data->ciphertext.length;
+ if (!(data->data = malloc(data->length)))
+ return ENOMEM;
+
+ if ((retval = krb5_process_key(context, &eblock, key)) != 0)
+ goto cleanup;
+
+ if ((retval = krb5_decrypt(context,
+ (krb5_pointer) enc_data->ciphertext.data,
+ (krb5_pointer) data->data,
+ enc_data->ciphertext.length, &eblock, ivec))) {
+ krb5_finish_key(context, &eblock);
+ goto cleanup;
+ }
+ (void) krb5_finish_key(context, &eblock);
+
+ return 0;
+
+cleanup:
+ if (data->data) {
+ free(data->data);
+ data->data = 0;
+ }
+ return retval;
+}
+
+
const char *missing_required_preauth(client, server, enc_tkt_reply)
krb5_db_entry *client, *server;
krb5_enc_tkt_part *enc_tkt_reply;
return;
}
+/*
+ * This routine is called to verify the preauthentication information
+ * for a V5 request.
+ *
+ * Returns 0 if the pre-authentication is valid, non-zero to indicate
+ * an error code of some sort.
+ */
+
+krb5_error_code
+check_padata (context, client, request, enc_tkt_reply)
+ krb5_context context;
+ krb5_db_entry * client;
+ krb5_kdc_req * request;
+ krb5_enc_tkt_part * enc_tkt_reply;
+{
+ krb5_error_code retval;
+ krb5_pa_data **padata;
+ krb5_preauth_systems *pa_sys;
+
+ if (request->padata == 0)
+ return 0;
+
+ for (padata = request->padata; *padata; padata++) {
+ if (find_pa_system((*padata)->pa_type, &pa_sys))
+ continue;
+ if (pa_sys->verify == 0)
+ continue;
+ retval = pa_sys->verify(context, client, request,
+ enc_tkt_reply, *padata);
+ if (retval) {
+ if (pa_sys->flags & PA_REQUIRED)
+ break;
+ } else {
+ if (pa_sys->flags & PA_SUFFICIENT)
+ break;
+ }
+ }
+ return retval;
+}
+
+static krb5_error_code
+verify_enc_timestamp(context, client, request, enc_tkt_reply, pa)
+ krb5_context context;
+ krb5_db_entry * client;
+ krb5_kdc_req * request;
+ krb5_enc_tkt_part * enc_tkt_reply;
+ krb5_pa_data * pa;
+{
+ krb5_pa_enc_ts * pa_enc = 0;
+ krb5_error_code retval;
+ krb5_data scratch;
+ krb5_data enc_ts_data;
+ krb5_enc_data *enc_data = 0;
+ krb5_keyblock key;
+ krb5_key_data * client_key;
+ krb5_int32 start;
+ krb5_timestamp timenow;
+
+ enc_ts_data.data = 0;
+ scratch.data = pa->contents;
+ scratch.length = pa->length;
+
+ if ((retval = decode_krb5_enc_data(&scratch, &enc_data)) != 0)
+ goto cleanup;
+
+ start = 0;
+ while (1) {
+ if ((retval = krb5_dbe_search_enctype(context, client,
+ &start, enc_data->enctype,
+ -1, 0, &client_key)))
+ goto cleanup;
+
+ if ((retval = krb5_dbekd_decrypt_key_data(context, &master_encblock,
+ client_key, &key, NULL)))
+ goto cleanup;
+ key.enctype = enc_data->enctype;
+
+ retval = krb5_decrypt_data(context, key, 0, enc_data, &enc_ts_data);
+ memset((char *)key.contents, 0, key.length);
+ krb5_xfree(key.contents);
+
+ if (retval == 0)
+ break;
+ }
+
+ if ((retval = decode_krb5_pa_enc_ts(&enc_ts_data, &pa_enc)) != 0)
+ goto cleanup;
+
+ if ((retval = krb5_timeofday(context, &timenow)) != 0)
+ goto cleanup;
+
+ if (labs(timenow - pa_enc->patimestamp) > context->clockskew) {
+ retval = KRB5KRB_AP_ERR_SKEW;
+ goto cleanup;
+ }
+
+ setflag(enc_tkt_reply->flags, TKT_FLG_PRE_AUTH);
+
+ retval = 0;
+
+cleanup:
+ if (enc_data) {
+ if (enc_data->ciphertext.data)
+ krb5_xfree(enc_data->ciphertext.data);
+ free(enc_data);
+ }
+ if (enc_ts_data.data)
+ krb5_xfree(enc_ts_data.data);
+ if (pa_enc)
+ krb5_xfree(pa_enc);
+ return retval;
+}
+
-
+#if 0
+
+ setflag(enc_tkt_reply.flags, TKT_FLG_PRE_AUTH);
+ /*
+ * If pa_type is one in which additional hardware authentication
+ * was performed set TKT_FLG_HW_AUTH too.
+ */
+ if (pa_flags & KRB5_PREAUTH_FLAGS_HARDWARE)
+ setflag(enc_tkt_reply.flags, TKT_FLG_HW_AUTH);
+
+#endif
return 0;
}
+
+/*
+ * This function returns 1 if the dbentry has a key for a specified
+ * keytype, and 0 if not.
+ */
+int
+dbentry_has_key_for_enctype(context, client, enctype)
+ krb5_context context;
+ krb5_db_entry * client;
+ krb5_enctype enctype;
+{
+ krb5_error_code retval;
+ krb5_key_data *datap;
+
+ retval = krb5_dbe_find_enctype(context, client, enctype,
+ -1, 0, &datap);
+ if (retval)
+ return 0;
+ else
+ return 1;
+}
+
+/*
+ * This function returns 1 if the entity referenced by this
+ * structure can support the a particular encryption system, and 0 if
+ * not.
+ *
+ * XXX eventually this information should be looked up in the
+ * database. Since it isn't, we use some hueristics and attribute
+ * options bits for now.
+ */
+int
+dbentry_supports_enctype(context, client, enctype)
+ krb5_context context;
+ krb5_db_entry * client;
+ krb5_enctype enctype;
+{
+ /*
+ * If it's DES_CBC_MD5, there's a bit in the attribute mask which
+ * checks to see if we support it.
+ *
+ * In theory everything's supposed to support DES_CBC_MD5, but
+ * that's not the reality....
+ */
+ if (enctype == ENCTYPE_DES_CBC_MD5)
+ return isflagset(client->attributes, KRB5_KDB_SUPPORT_DESMD5);
+
+ /*
+ * XXX we assume everything can understand DES_CBC_CRC
+ */
+ if (enctype == ENCTYPE_DES_CBC_CRC)
+ return 1;
+
+ /*
+ * If we have a key for the encryption system, we assume it's
+ * supported.
+ */
+ return dbentry_has_key_for_enctype(context, client, enctype);
+}
+
+/*
+ * This function returns the keytype which should be selected for the
+ * session key. It is based on the ordered list which the user
+ * requested, and what the KDC and the application server can support.
+ */
+krb5_enctype
+select_session_keytype(context, server, nktypes, ktype)
+ krb5_context context;
+ krb5_db_entry * server;
+ int nktypes;
+ krb5_enctype *ktype;
+{
+ int i;
+
+ for (i = 0; i < nktypes; i++) {
+ if (!valid_enctype(ktype[i]))
+ continue;
+
+ if (dbentry_supports_enctype(context, server, ktype[i]))
+ return (ktype[i]);
+ }
+ return 0;
+}
+
+
+
+
+
int fetch_asn1_field PROTOTYPE((unsigned char *, unsigned int, unsigned int,
krb5_data *));
+int
+dbentry_has_key_for_enctype PROTOTYPE((krb5_context context,
+ krb5_db_entry *client,
+ krb5_enctype enctype));
+
+int
+dbentry_supports_enctype PROTOTYPE((krb5_context context,
+ krb5_db_entry *client,
+ krb5_enctype enctype));
+
+krb5_enctype
+select_session_keytype PROTOTYPE((krb5_context context,
+ krb5_db_entry *server,
+ int nktypes,
+ krb5_enctype *ktypes));
+
/* do_as_req.c */
krb5_error_code process_as_req PROTOTYPE((krb5_kdc_req *,
const krb5_fulladdr *,
free(rdp->realm_mpname);
if (rdp->realm_stash)
free(rdp->realm_stash);
+ if (rdp->realm_ports)
+ free(rdp->realm_ports);
+ if (rdp->realm_kstypes)
+ free(rdp->realm_kstypes);
if (rdp->realm_context) {
if (rdp->realm_mprinc)
krb5_free_principal(rdp->realm_context, rdp->realm_mprinc);
- if (rdp->realm_mkey.length && rdp->realm_mkey.contents)
- krb5_free_keyblock(rdp->realm_context, &rdp->realm_mkey);
+ if (rdp->realm_mkey.length && rdp->realm_mkey.contents) {
+ memset(rdp->realm_mkey.contents, 0, rdp->realm_mkey.length);
+ free(rdp->realm_mkey.contents);
+ }
+ if (rdp->realm_tgskey.length && rdp->realm_tgskey.contents) {
+ memset(rdp->realm_tgskey.contents, 0, rdp->realm_tgskey.length);
+ free(rdp->realm_tgskey.contents);
+ }
+ krb5_finish_key(rdp->realm_context, &rdp->realm_encblock);
krb5_db_fini(rdp->realm_context);
if (rdp->realm_tgsprinc)
krb5_free_principal(rdp->realm_context, rdp->realm_tgsprinc);
krb5_klog_syslog(LOG_INFO, "shutting down");
krb5_klog_close(kdc_context);
finish_realms(argv[0]);
+ krb5_free_context(kcontext);
return errout;
}