krb5_enc_tkt_part enc_tkt_reply;
krb5_error_code errcode;
int c_nprincs = 0, s_nprincs = 0;
- int pa_id, pa_flags;
krb5_boolean more;
krb5_timestamp kdc_time, authtime;
krb5_keyblock *session_key = 0;
krb5_keyblock encrypting_key;
- krb5_pa_data *padat_tmp[2], padat_local;
- krb5_data salt_data;
const char *status;
krb5_encrypt_block eblock;
krb5_key_data *server_key, *client_key;
char *cname = 0, *sname = 0, *fromstring = 0;
ticket_reply.enc_part.ciphertext.data = 0;
- salt_data.data = 0;
e_data.data = 0;
+ encrypting_key.contents = 0;
#ifdef KRB5_USE_INET
if (from->address->addrtype == ADDRTYPE_INET)
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);
+ encrypting_key.contents = 0;
if (errcode) {
status = "ENCRYPTING_TICKET";
goto errout;
goto errout;
}
+ /* convert client.key_data into a real key */
+ if ((errcode = krb5_dbekd_decrypt_key_data(kdc_context, &master_encblock,
+ client_key, &encrypting_key,
+ NULL))) {
+ status = "DECRYPT_CLIENT_KEY";
+ goto errout;
+ }
+ encrypting_key.enctype = useenctype;
+
/* Start assembling the response */
reply.msg_type = KRB5_AS_REP;
-
reply.padata = 0;
-
- if (client_key->key_data_ver > 1) {
- padat_tmp[0] = &padat_local;
- padat_tmp[1] = 0;
-
- padat_tmp[0]->pa_type = KRB5_PADATA_PW_SALT;
-
- /* WARNING: sharing substructure here, but it's not a real problem,
- since nothing below will "pull out the rug" */
-
- switch (client_key->key_data_type[1]) {
- krb5_data *data_foo;
- case KRB5_KDB_SALTTYPE_NORMAL:
- reply.padata = (krb5_pa_data **) NULL;
- break;
- case KRB5_KDB_SALTTYPE_V4:
- /* send an empty (V4) salt */
- padat_tmp[0]->contents = 0;
- padat_tmp[0]->length = 0;
- reply.padata = padat_tmp;
- break;
- case KRB5_KDB_SALTTYPE_NOREALM:
- if ((errcode = krb5_principal2salt_norealm(kdc_context,
- request->client,
- &salt_data))) {
- status = "SALT_NOREALM";
- goto errout;
- }
- padat_tmp[0]->contents = (krb5_octet *)salt_data.data;
- padat_tmp[0]->length = salt_data.length;
- reply.padata = padat_tmp;
- break;
- case KRB5_KDB_SALTTYPE_ONLYREALM:
- data_foo = krb5_princ_realm(kdc_context, request->client);
- padat_tmp[0]->contents = (krb5_octet *)data_foo->data;
- padat_tmp[0]->length = data_foo->length;
- reply.padata = padat_tmp;
- break;
- case KRB5_KDB_SALTTYPE_SPECIAL:
- padat_tmp[0]->contents = client_key->key_data_contents[1];
- padat_tmp[0]->length = client_key->key_data_length[1];
- reply.padata = padat_tmp;
- break;
- }
- }
-
reply.client = request->client;
-
reply.ticket = &ticket_reply;
-
reply_encpart.session = session_key;
if ((errcode = fetch_last_req_info(&client, &reply_encpart.last_req))) {
status = "FETCH_LAST_REQ";
goto errout;
}
-
reply_encpart.nonce = request->nonce;
reply_encpart.key_exp = client.expiration;
reply_encpart.flags = enc_tkt_reply.flags;
reply_encpart.times.authtime = authtime = kdc_time;
reply_encpart.caddrs = enc_tkt_reply.caddrs;
-
- /* now encode/encrypt the response */
-
- reply.enc_part.enctype = useenctype;
reply.enc_part.kvno = client_key->key_data_kvno;
- /* convert client.key_data into a real key */
- if ((errcode = krb5_dbekd_decrypt_key_data(kdc_context, &master_encblock,
- client_key, &encrypting_key,
- NULL))) {
- status = "DECRYPT_CLIENT_KEY";
+ /* Fetch the padata info to be returned */
+ errcode = return_padata(kdc_context, &client, request, &reply, client_key,
+ &encrypting_key);
+ if (errcode) {
+ status = "KDC_RETURN_PADATA";
goto errout;
}
- encrypting_key.enctype = useenctype;
+
+ /* now encode/encrypt the response */
+
+ reply.enc_part.enctype = encrypting_key.enctype;
errcode = krb5_encode_kdc_rep(kdc_context, KRB5_AS_REP, &reply_encpart,
&eblock, &encrypting_key, &reply, response);
errcode = prepare_error_as(request, errcode, &e_data, response);
}
+ if (encrypting_key.contents) {
+ memset((char *)encrypting_key.contents, 0, encrypting_key.length);
+ krb5_xfree(encrypting_key.contents);
+ }
if (cname)
free(cname);
if (sname)
ticket_reply.enc_part.ciphertext.length);
free(ticket_reply.enc_part.ciphertext.data);
}
- if (salt_data.data)
- krb5_xfree(salt_data.data);
if (e_data.data)
krb5_xfree(e_data.data);
krb5_db_entry *client, krb5_db_entry *server,
krb5_pa_data *data));
+typedef krb5_error_code (return_proc)
+ KRB5_PROTOTYPE((krb5_context, krb5_pa_data * padata,
+ krb5_db_entry *client,
+ krb5_kdc_req *request, krb5_kdc_rep *reply,
+ krb5_key_data *client_key,
+ krb5_keyblock *encrypting_key,
+ krb5_pa_data **send_pa));
+
typedef struct _krb5_preauth_systems {
int type;
int flags;
edata_proc *get_edata;
- verify_proc *verify;
+ verify_proc *verify_padata;
+ return_proc *return_padata;
} krb5_preauth_systems;
static verify_proc verify_enc_timestamp;
static edata_proc get_etype_info;
+static return_proc return_pw_salt;
/*
* Preauth property flags
0,
0,
verify_enc_timestamp,
+ 0
},
{
KRB5_PADATA_ETYPE_INFO,
0,
get_etype_info,
+ 0,
0
},
+ {
+ KRB5_PADATA_PW_SALT,
+ 0,
+ 0,
+ 0,
+ return_pw_salt
+ },
{ -1,}
};
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;
for (padata = request->padata; *padata; padata++) {
if (find_pa_system((*padata)->pa_type, &pa_sys))
continue;
- if (pa_sys->verify == 0)
+ if (pa_sys->verify_padata == 0)
continue;
- retval = pa_sys->verify(context, client, request,
- enc_tkt_reply, *padata);
+ retval = pa_sys->verify_padata(context, client, request,
+ enc_tkt_reply, *padata);
if (retval) {
if (pa_sys->flags & PA_REQUIRED)
break;
return retval;
}
+/*
+ * return_padata creates any necessary preauthentication
+ * structures which should be returned by the KDC to the client
+ */
+krb5_error_code
+return_padata(context, client, request, reply,
+ client_key, encrypting_key)
+ krb5_context context;
+ krb5_db_entry * client;
+ krb5_kdc_req * request;
+ krb5_kdc_rep * reply;
+ krb5_key_data * client_key;
+ krb5_keyblock * encrypting_key;
+{
+ krb5_error_code retval;
+ krb5_pa_data ** padata;
+ krb5_pa_data ** send_pa_list;
+ krb5_pa_data ** send_pa;
+ krb5_pa_data * pa = 0;
+ krb5_preauth_systems * ap;
+ int size;
+
+ for (ap = preauth_systems; ap->type != -1; ap++) {
+ if (ap->return_padata)
+ size++;
+ }
+
+ if ((send_pa_list = malloc((size+1) * sizeof(krb5_pa_data *))) == NULL)
+ return ENOMEM;
+
+ send_pa = send_pa_list;
+ *send_pa = 0;
+
+ for (ap = preauth_systems; ap->type != -1; ap++) {
+ if (ap->return_padata == 0)
+ continue;
+ pa = 0;
+ if (request->padata) {
+ for (padata = request->padata; *padata; padata++) {
+ if ((*padata)->pa_type == ap->type) {
+ pa = *padata;
+ break;
+ }
+ }
+ }
+ if ((retval = ap->return_padata(context, pa, client, request, reply,
+ client_key, encrypting_key, send_pa)))
+ goto cleanup;
+
+ if (*send_pa)
+ send_pa++;
+ *send_pa = 0;
+ }
+
+ retval = 0;
+
+ if (send_pa_list[0]) {
+ reply->padata = send_pa_list;
+ send_pa_list = 0;
+ }
+
+cleanup:
+ if (send_pa_list)
+ krb5_free_pa_data(context, send_pa_list);
+ return (retval);
+}
+
static krb5_error_code
verify_enc_timestamp(context, client, request, enc_tkt_reply, pa)
krb5_context context;
goto cleanup;
key.enctype = enc_data->enctype;
- retval = krb5_decrypt_data(context, key, 0, enc_data, &enc_ts_data);
+ retval = krb5_decrypt_data(context, &key, 0, enc_data, &enc_ts_data);
memset((char *)key.contents, 0, key.length);
krb5_xfree(key.contents);
return retval;
}
+static krb5_error_code
+return_pw_salt(context, in_padata, client, request, reply, client_key,
+ encrypting_key, send_pa)
+ krb5_context context;
+ krb5_pa_data * in_padata;
+ krb5_db_entry * client;
+ krb5_kdc_req * request;
+ krb5_kdc_rep * reply;
+ krb5_key_data * client_key;
+ krb5_keyblock * encrypting_key;
+ krb5_pa_data ** send_pa;
+{
+ krb5_error_code retval;
+ krb5_pa_data * padata;
+ krb5_data * scratch;
+ krb5_data salt_data;
+
+ if (client_key->key_data_ver == 1 ||
+ client_key->key_data_type[1] == KRB5_KDB_SALTTYPE_NORMAL)
+ return 0;
+
+ if ((padata = malloc(sizeof(krb5_pa_data))) == NULL)
+ return ENOMEM;
+ padata->magic = KV5M_PA_DATA;
+ padata->pa_type = KRB5_PADATA_PW_SALT;
+
+ switch (client_key->key_data_type[1]) {
+ case KRB5_KDB_SALTTYPE_V4:
+ /* send an empty (V4) salt */
+ padata->contents = 0;
+ padata->length = 0;
+ break;
+ case KRB5_KDB_SALTTYPE_NOREALM:
+ if ((retval = krb5_principal2salt_norealm(kdc_context,
+ request->client,
+ &salt_data)))
+ goto cleanup;
+ padata->contents = (krb5_octet *)salt_data.data;
+ padata->length = salt_data.length;
+ break;
+ case KRB5_KDB_SALTTYPE_ONLYREALM:
+ scratch = krb5_princ_realm(kdc_context, request->client);
+ if ((padata->contents = malloc(scratch->length)) == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+ memcpy(padata->contents, scratch->data, scratch->length);
+ padata->length = scratch->length;
+ break;
+ case KRB5_KDB_SALTTYPE_SPECIAL:
+ if ((padata->contents = malloc(client_key->key_data_length[1]))
+ == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+ memcpy(padata->contents, client_key->key_data_contents[1],
+ client_key->key_data_length[1]);
+ padata->length = client_key->key_data_length[1];
+ break;
+ default:
+ free(padata);
+ return 0;
+ }
+
+ *send_pa = padata;
+ return 0;
+
+cleanup:
+ free(padata);
+ return retval;
+}
+
+
+