diff options
| author | John Kohl <jtkohl@mit.edu> | 1990-03-09 11:41:52 +0000 |
|---|---|---|
| committer | John Kohl <jtkohl@mit.edu> | 1990-03-09 11:41:52 +0000 |
| commit | 560b7153c8acc85619e580fc51c365837daa27fc (patch) | |
| tree | 9b75fc67026926e871d7e0ccde90b5942567d34e /src | |
| parent | 361ffef8443c7200f1363de8a1353b67b9e4370e (diff) | |
| download | krb5-560b7153c8acc85619e580fc51c365837daa27fc.tar.gz krb5-560b7153c8acc85619e580fc51c365837daa27fc.tar.xz krb5-560b7153c8acc85619e580fc51c365837daa27fc.zip | |
*** empty log message ***
git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@379 dc483132-0cff-0310-8789-dd5450dbe970
Diffstat (limited to 'src')
| -rw-r--r-- | src/lib/krb5/krb/rd_req.c | 83 | ||||
| -rw-r--r-- | src/lib/krb5/krb/rd_req_dec.c | 248 |
2 files changed, 331 insertions, 0 deletions
diff --git a/src/lib/krb5/krb/rd_req.c b/src/lib/krb5/krb/rd_req.c new file mode 100644 index 000000000..8908d4be5 --- /dev/null +++ b/src/lib/krb5/krb/rd_req.c @@ -0,0 +1,83 @@ +/* + * $Source$ + * $Author$ + * + * Copyright 1990 by the Massachusetts Institute of Technology. + * + * For copying and distribution information, please see the file + * <krb5/mit-copyright.h>. + * + * krb5_rd_req() + */ + +#if !defined(lint) && !defined(SABER) +static char rd_req_c[] = +"$Id$"; +#endif /* !lint & !SABER */ + +#include <krb5/copyright.h> +#include <krb5/krb5.h> +#include <krb5/krb5_err.h> +#include <krb5/isode_err.h> + +#include <krb5/asn1.h> +#include <krb5/ext-proto.h> + +/* + Parses a KRB_AP_REQ message, returning its contents. + + server specifies the expected server's name for the ticket. + + sender_addr specifies the address(es) expected to be present in the + ticket. + + rcache specifies a replay detection cache used to store authenticators and + server names + + keyproc specifies a procedure to generate a decryption key for the + ticket. If keyproc is non-NULL, keyprocarg is passed to it, and the result + used as a decryption key. If keyproc is NULL, then fetchfrom is checked; + if it is non-NULL, it specifies a parameter name from which to retrieve the + decryption key. If fetchfrom is NULL, then the default key store is + consulted. + + authdat->ticket and authdat->authenticator are set to allocated storage + structures; the caller should free them when finished. + + returns system errors, encryption errors, replay errors + */ + +krb5_error_code +krb5_rd_req(inbuf, server, sender_addr, fetchfrom, keyproc, keyprocarg, + rcache, authdat) +krb5_data *inbuf; +krb5_principal server; +krb5_address *sender_addr; +krb5_pointer fetchfrom; +krb5_error_code (*keyproc) PROTOTYPE((krb5_pointer, + krb5_principal, + krb5_kvno, + krb5_keyblock **)); +krb5_pointer keyprocarg; +krb5_rcache rcache; +krb5_tkt_authent *authdat; +{ + krb5_error_code retval; + krb5_ap_req *request; + + if (retval = decode_krb5_ap_req(inbuf, &request)) { + switch (retval) { + case ISODE_50_LOCAL_ERR_BADMSGTYPE: + return KRB5KRB_AP_ERR_BADVERSION; /* XXX ? */ + default: + return(retval); + } + + } + + retval = krb5_rd_req_decoded(request, server, sender_addr, fetchfrom, + keyproc, keyprocarg, rcache, authdat); + krb5_free_ap_req(request); + return retval; +} + diff --git a/src/lib/krb5/krb/rd_req_dec.c b/src/lib/krb5/krb/rd_req_dec.c new file mode 100644 index 000000000..3c03b4c9d --- /dev/null +++ b/src/lib/krb5/krb/rd_req_dec.c @@ -0,0 +1,248 @@ +/* + * $Source$ + * $Author$ + * + * Copyright 1990 by the Massachusetts Institute of Technology. + * + * For copying and distribution information, please see the file + * <krb5/mit-copyright.h>. + * + * krb5_rd_req_decoded() + */ + +#if !defined(lint) && !defined(SABER) +static char rd_req_dec_c[] = +"$Id$"; +#endif /* !lint & !SABER */ + +#include <krb5/copyright.h> +#include <krb5/krb5.h> +#include <krb5/krb5_err.h> +#include <errno.h> + +#include <krb5/ext-proto.h> +#include <stdio.h> +#include <krb5/libos-proto.h> +#include <krb5/asn1.h> + +/* + essentially the same as krb_rd_req, but uses a decoded AP_REQ as the input + rather than an encoded input. + */ +/* + Parses a KRB_AP_REQ message, returning its contents. + + server specifies the expected server's name for the ticket. + + sender_addr specifies the address(es) expected to be present in the + ticket. + + rcache specifies a replay detection cache used to store authenticators and + server names + + keyproc specifies a procedure to generate a decryption key for the + ticket. If keyproc is non-NULL, keyprocarg is passed to it, and the result + used as a decryption key. If keyproc is NULL, then fetchfrom is checked; + if it is non-NULL, it specifies a parameter name from which to retrieve the + decryption key. If fetchfrom is NULL, then the default key store is + consulted. + + authdat->ticket and authdat->authenticator are set to allocated storage + structures; the caller should free them when finished. + + returns system errors, encryption errors, replay errors + */ + +static krb5_error_code decrypt_authenticator PROTOTYPE((krb5_ap_req *, + krb5_authenticator **)); +static krb5_error_code copy_ticket PROTOTYPE((krb5_ticket *, krb5_ticket **)); + +extern krb5_deltat krb5_clockskew; +#define in_clock_skew(date) (abs((date)-currenttime) < krb5_clockskew) + +krb5_error_code +krb5_rd_req_decoded(req, server, sender_addr, fetchfrom, keyproc, keyprocarg, + rcache, tktauthent) +krb5_ap_req *req; +krb5_principal server; +krb5_address *sender_addr; +krb5_pointer fetchfrom; +krb5_error_code (*keyproc) PROTOTYPE((krb5_pointer, + krb5_principal, + krb5_kvno, + krb5_keyblock **)); +krb5_pointer keyprocarg; +krb5_rcache rcache; +krb5_tkt_authent *tktauthent; +{ + krb5_error_code retval; + krb5_keyblock *tkt_key; + krb5_keyblock tkt_key_real; + krb5_timestamp currenttime; + + + if (!krb5_principal_compare(server, req->ticket->server)) + return KRB5KRB_AP_WRONG_PRINC; + + /* if (req->ap_options & AP_OPTS_USE_SESSION_KEY) + do we need special processing here ? */ + + /* fetch a server key */ + if (keyproc) { + retval = (*keyproc)(keyprocarg, req->ticket->server, + req->ticket->skvno, &tkt_key); + } else { + krb5_keytab keytabid; + krb5_keytab_entry ktentry; + + if (fetchfrom) { + /* use the named keytab */ + retval = krb5_kt_resolve((char *)fetchfrom, &keytabid); + } else { + /* use default keytab */ + retval = krb5_kt_default(&keytabid); + } + retval = krb5_kt_get_entry(keytabid, req->ticket->server, + req->ticket->skvno, &ktentry); + (void) krb5_kt_close(keytabid); + tkt_key_real = *ktentry.key; + tkt_key = &tkt_key_real; + (void) krb5_kt_free_entry(&ktentry); + } + if (retval) + return retval; /* some error in getting the key */ + + /* decrypt the ticket */ + if (retval = krb5_decrypt_tkt_part(tkt_key, req->ticket)) + return(retval); + +#define clean_ticket() krb5_free_enc_tkt_part(req->ticket->enc_part2) + + if (retval = decrypt_authenticator(req, &tktauthent->authenticator)) { + clean_ticket(); + return retval; + } +#define clean_authenticator() {(void) krb5_free_authenticator(tktauthent->authenticator); tktauthent->authenticator = 0;} + + if (!krb5_principal_compare(tktauthent->authenticator->client, + req->ticket->enc_part2->client)) { + clean_authenticator(); + return KRB5KRB_AP_ERR_BADMATCH; + } + if (sender_addr && !krb5_address_search(sender_addr, req->ticket->enc_part2->caddrs)) { + clean_authenticator(); + return KRB5KRB_AP_ERR_BADADDR; + } + + if (retval = krb5_timeofday(¤ttime)) { + clean_authenticator(); + return retval; + } + if (!in_clock_skew(tktauthent->authenticator->ctime)) { + clean_authenticator(); + return KRB5KRB_AP_ERR_SKEW; + } + + tktauthent->ticket = req->ticket; /* only temporarily...allocated + below */ + + if ((retval = krb5_rc_store(rcache, tktauthent, TRUE))) { + tktauthent->ticket = 0; + clean_authenticator(); + return retval; + } + tktauthent->ticket = 0; + if (req->ticket->enc_part2->times.starttime - currenttime > krb5_clockskew) { + clean_authenticator(); + return KRB5KRB_AP_ERR_TKT_NYV; /* ticket not yet valid */ + } + if (currenttime - req->ticket->enc_part2->times.endtime > krb5_clockskew) { + clean_authenticator(); + return KRB5KRB_AP_ERR_TKT_EXPIRED; /* ticket expired */ + } + if (req->ticket->enc_part2->flags & TKT_FLG_INVALID) { + clean_authenticator(); + return KRB5KRB_AP_ERR_TKT_INVALID; + } + if (retval = copy_ticket(req->ticket, &tktauthent->ticket)) { + clean_authenticator(); + } else + tktauthent->ap_options = req->ap_options; + return retval; +} + +static krb5_error_code +decrypt_authenticator(request, authpp) +krb5_ap_req *request; +krb5_authenticator **authpp; +{ + krb5_authenticator *local_auth; + krb5_error_code retval; + krb5_encrypt_block eblock; + krb5_data scratch; + krb5_enctype etype; + krb5_keyblock *sesskey; + + sesskey = request->ticket->enc_part2->session; + + etype = keytype_to_etype(sesskey->keytype); + + if (!valid_etype(etype)) + return KRB5KDC_ERR_ETYPE_NOSUPP; + + /* put together an eblock for this encryption */ + + eblock.crypto_entry = krb5_csarray[etype]->system; + + scratch.length = request->authenticator.length; + if (!(scratch.data = malloc(scratch.length))) + return(ENOMEM); + + /* do any necessary key pre-processing */ + if (retval = (*eblock.crypto_entry->process_key)(&eblock, sesskey)) { + free(scratch.data); + return(retval); + } + + /* call the encryption routine */ + if (retval = + (*eblock.crypto_entry->decrypt_func)((krb5_pointer) request->authenticator.data, + (krb5_pointer) scratch.data, + scratch.length, &eblock)) { + (void) (*eblock.crypto_entry->finish_key)(&eblock); + free(scratch.data); + return retval; + } +#define clean_scratch() {bzero(scratch.data, scratch.length); free(scratch.data);} + if (retval = (*eblock.crypto_entry->finish_key)(&eblock)) { + + clean_scratch(); + return retval; + } + /* now decode the decrypted stuff */ + if (!(retval = decode_krb5_authenticator(&scratch, &local_auth))) { + *authpp = local_auth; + } + clean_scratch(); + return retval; +} +static krb5_error_code +copy_ticket(from, pto) +krb5_ticket *from; +krb5_ticket **pto; +{ + krb5_error_code retval; + krb5_data *scratch; + + /* use a trick here---encoding a ticket & decoding it will + result in a freshly allocated data structure */ + + if (retval = encode_krb5_ticket(from, &scratch)) + return ENOMEM; /* lie a little, since we cheat */ + retval = decode_krb5_ticket(scratch, pto); + krb5_free_data(scratch); + if (retval) + return ENOMEM; + else + return 0; +} |
