diff --git a/lib/krb5/Makefile.am b/lib/krb5/Makefile.am index 38df2df3a..39b7b4ca3 100644 --- a/lib/krb5/Makefile.am +++ b/lib/krb5/Makefile.am @@ -12,7 +12,7 @@ libkrb5_a_SOURCES = cache.c config_file.y constants.c context.c data.c \ get_addrs.c get_cred.c get_in_tkt.c get_in_tkt_pw.c get_port.c \ krbhst.c misc.c principal.c principal_p.c send_to_kdc.c str2key.c \ crc.c build_ap_req.c build_auth.c mk_req.c get_host_realm.c \ - auth_context.c rd_rep.c keytab.c + auth_context.c rd_rep.c keytab.c store.c rd_req.c mk_rep.c config_file.c: config_file.y $(YACC) -p __k5cf_ $< diff --git a/lib/krb5/mk_rep.c b/lib/krb5/mk_rep.c new file mode 100644 index 000000000..90e80f863 --- /dev/null +++ b/lib/krb5/mk_rep.c @@ -0,0 +1,49 @@ +#include +#include + +krb5_error_code +krb5_mk_rep(krb5_context context, + krb5_auth_context *auth_context, + krb5_data *outbuf) +{ + krb5_error_code ret; + AP_REP ap; + EncAPRepPart body; + u_char buf[1024], *p; + size_t len; + des_cblock key; + des_key_schedule schedule; + + ap.pvno = 5; + ap.msg_type = krb_ap_rep; + + body.ctime = (*auth_context)->authenticator->ctime; + body.cusec = (*auth_context)->authenticator->cusec; + body.subkey = NULL; + body.seq_number = NULL; + + ap.enc_part.etype = 1; /* XXX */ + ap.enc_part.kvno = NULL; + len = encode_EncAPRepPart (buf + sizeof(buf) - 1, + sizeof(buf), &body); + len += 12; /* XXX */ + ap.enc_part.cipher.length = len; + ap.enc_part.cipher.data = malloc(len); + memcpy(ap.enc_part.cipher.data, buf +sizeof(buf) - len, len); + + memcpy(&key, (*auth_context)->key.contents.data, sizeof(key)); + des_set_key (&key, schedule); + + des_cbc_encrypt (ap.enc_part.cipher.data, + ap.enc_part.cipher.data, + ap.enc_part.cipher.length, + schedule, &key, DES_ENCRYPT); + + len = encode_AP_REP (buf + sizeof(buf) - 1, + sizeof(buf), &ap); + free (ap.enc_part.cipher.data); + outbuf->length = len; + outbuf->data = malloc(len); + memcpy(outbuf->data, buf + sizeof(buf) - len, len); + return 0; +} diff --git a/lib/krb5/rd_req.c b/lib/krb5/rd_req.c new file mode 100644 index 000000000..18bd34fb2 --- /dev/null +++ b/lib/krb5/rd_req.c @@ -0,0 +1,168 @@ +#include +#include + +static krb5_error_code +decrypt_tkt_enc_part (krb5_context context, + const krb5_keyblock *key, + EncryptedData *enc_part, + EncTicketPart *decr_part) +{ + des_key_schedule sched; + char *buf; + int i; + int len = enc_part->cipher.length; + + des_set_key (key->contents.data, sched); + buf = malloc (len); + if (buf == NULL) + return ENOMEM; + des_cbc_encrypt ((des_cblock *)enc_part->cipher.data, + (des_cblock *)buf, + len, + sched, + key->contents.data, + DES_DECRYPT); + /* XXX: Check CRC */ + + i = decode_EncTicketPart((unsigned char*)buf + 12, len - 12, + decr_part); + free (buf); + if (i < 0) + return ASN1_PARSE_ERROR; + return 0; +} + +static krb5_error_code +decrypt_authenticator (krb5_context context, + EncryptionKey *key, + EncryptedData *enc_part, + Authenticator *authenticator) +{ + des_key_schedule sched; + char *buf; + int i; + int len = enc_part->cipher.length; + + des_set_key (key->keyvalue.data, sched); + buf = malloc (len); + if (buf == NULL) + return ENOMEM; + des_cbc_encrypt ((des_cblock *)enc_part->cipher.data, + (des_cblock *)buf, + len, + sched, + key->keyvalue.data, + DES_DECRYPT); + /* XXX: Check CRC */ + + i = decode_Authenticator((unsigned char*)buf + 12, len - 12, + authenticator); + free(buf); + if (i < 0) + return ASN1_PARSE_ERROR; + return 0; +} + +krb5_error_code +krb5_rd_req(krb5_context context, + krb5_auth_context *auth_context, + const krb5_data *inbuf, + krb5_const_principal server, + krb5_keytab keytab, + krb5_flags *ap_req_options, + krb5_ticket **ticket) +{ + krb5_error_code ret; + AP_REQ ap_req; + int len; + + if (*auth_context == NULL) { + ret = krb5_auth_con_init(context, auth_context); + if (ret) + return ret; + } + + len = decode_AP_REQ(inbuf->data, inbuf->length, &ap_req); + if (len < 0) + return ASN1_PARSE_ERROR; + if (ap_req.pvno != 5) + return KRB_AP_ERR_BADVERSION; + if (ap_req.msg_type != krb_ap_req) + return KRB_AP_ERR_MSG_TYPE; + if (ap_req.ticket.tkt_vno != 5) + return KRB_AP_ERR_BADVERSION; + if (ap_req.ap_options.use_session_key) + abort (); + else { + krb5_keytab_entry entry; + EncTicketPart decr_part; + Authenticator authenticator; + + if (keytab == NULL) + krb5_kt_default (context, &keytab); + + ret = krb5_kt_get_entry(context, + keytab, + server, + 0, + KEYTYPE_DES, + &entry); + if (ret) + return ret; + ret = decrypt_tkt_enc_part (context, + &entry.keyblock, + &ap_req.ticket.enc_part, + &decr_part); + if (ret) + return ret; + + if (ticket) { + *ticket = malloc(sizeof(**ticket)); + + principalname2krb5_principal(&(*ticket)->enc_part2.client, + decr_part.cname, + decr_part.crealm); + } + + /* save key */ + + (*auth_context)->key.keytype = decr_part.key.keytype; + krb5_data_copy(&(*auth_context)->key.contents, + decr_part.key.keyvalue.data, + decr_part.key.keyvalue.length); + + ret = decrypt_authenticator (context, + &decr_part.key, + &ap_req.authenticator, + &authenticator); + if (ret) + return ret; + + if (strcmp (authenticator.crealm, decr_part.crealm) != 0) + return KRB_AP_ERR_BADMATCH; + { + krb5_principal p1, p2; + + principalname2krb5_principal(&p1, authenticator.cname, + authenticator.crealm); + principalname2krb5_principal(&p2, decr_part.cname, + decr_part.crealm); + if (!krb5_principal_compare (context, p1, p2)) + return KRB_AP_ERR_BADMATCH; + } + (*auth_context)->authenticator->cusec = authenticator.cusec; + (*auth_context)->authenticator->ctime = authenticator.ctime; + + if (ap_req_options) { + *ap_req_options = 0; + if (ap_req.ap_options.use_session_key) + *ap_req_options |= AP_OPTS_USE_SESSION_KEY; + if (ap_req.ap_options.mutual_required) + *ap_req_options |= AP_OPTS_MUTUAL_REQUIRED; + } + + /* Check adress and time */ + + return 0; + } +} diff --git a/lib/krb5/store.c b/lib/krb5/store.c new file mode 100644 index 000000000..c8eb60b31 --- /dev/null +++ b/lib/krb5/store.c @@ -0,0 +1,273 @@ +#include "krb5_locl.h" + +krb5_error_code +krb5_store_int32(int fd, + int32_t value) +{ + int ret; + + value = htonl(value); + ret = write(fd, &value, sizeof(value)); + if (ret != sizeof(value)) + return (ret<0)?errno:KRB5_CC_END; + return 0; +} + +krb5_error_code +krb5_ret_int32(int fd, + int32_t *value) +{ + int32_t v; + int ret; + ret = read(fd, &v, sizeof(v)); + if(ret != sizeof(v)) + return (ret<0)?errno:KRB5_CC_END; + + *value = ntohl(v); + return 0; +} + +krb5_error_code +krb5_store_int16(int fd, + int16_t value) +{ + int ret; + + value = htons(value); + ret = write(fd, &value, sizeof(value)); + if (ret != sizeof(value)) + return (ret<0)?errno:KRB5_CC_END; + return 0; +} + +krb5_error_code +krb5_ret_int16(int fd, + int16_t *value) +{ + int16_t v; + int ret; + ret = read(fd, &v, sizeof(v)); + if(ret != sizeof(v)) + return (ret<0)?errno:KRB5_CC_END; /* XXX */ + + *value = ntohs(v); + return 0; +} + +krb5_error_code +krb5_store_int8(int fd, + int8_t value) +{ + int ret; + + ret = write(fd, &value, sizeof(value)); + if (ret != sizeof(value)) + return (ret<0)?errno:KRB5_CC_END; + return 0; +} + +krb5_error_code +krb5_ret_int8(int fd, + int8_t *value) +{ + int ret; + + ret = read (fd, value, sizeof(*value)); + if (ret != sizeof(*value)) + return (ret<0)?errno:KRB5_CC_END; + return 0; +} + +krb5_error_code +krb5_store_data(int fd, + krb5_data data) +{ + int ret; + ret = krb5_store_int32(fd, data.length); + if(ret < 0) + return ret; + ret = write(fd, data.data, data.length); + if(ret != data.length){ + if(ret < 0) + return errno; + return KRB5_CC_END; + } + return 0; +} + +krb5_error_code +krb5_ret_data(int fd, + krb5_data *data) +{ + int ret; + int size; + ret = krb5_ret_int32(fd, &size); + if(ret) + return ret; + data->length = size; + data->data = malloc(size); + ret = read(fd, data->data, size); + if(ret != size) + return (ret < 0)? errno : KRB5_CC_END; + return 0; +} + +krb5_error_code +krb5_store_principal(int fd, + krb5_principal p) +{ + int i; + int ret; + ret = krb5_store_int32(fd, p->type); + if(ret) return ret; + ret = krb5_store_int32(fd, p->ncomp); + if(ret) return ret; + ret = krb5_store_data(fd, p->realm); + if(ret) return ret; + for(i = 0; i < p->ncomp; i++){ + ret = krb5_store_data(fd, p->comp[i]); + if(ret) return ret; + } + return 0; +} + +krb5_error_code +krb5_ret_principal(int fd, + krb5_principal *princ) +{ + int i; + int ret; + krb5_principal p; + + p = ALLOC(1, krb5_principal_data); + if(p == NULL) + return ENOMEM; + + if((ret = krb5_ret_int32(fd, &p->type))) + return ret; + ret = krb5_ret_int32(fd, &p->ncomp); + if(ret) return ret; + ret = krb5_ret_data(fd, &p->realm); + if(ret) return ret; + p->comp = ALLOC(p->ncomp, krb5_data); + if(p->comp == NULL){ + return ENOMEM; + } + for(i = 0; i < p->ncomp; i++){ + ret = krb5_ret_data(fd, &p->comp[i]); + if(ret) return ret; + } + *princ = p; + return 0; +} + +krb5_error_code +krb5_store_keyblock(int fd, krb5_keyblock p) +{ + int ret; + ret =krb5_store_int32(fd, p.keytype); + if(ret) return ret; + ret = krb5_store_data(fd, p.contents); + return ret; +} + +krb5_error_code +krb5_ret_keyblock(int fd, krb5_keyblock *p) +{ + int ret; + ret = krb5_ret_int32(fd, (int32_t*)&p->keytype); /* keytype + etype */ + if(ret) return ret; + ret = krb5_ret_data(fd, &p->contents); + return ret; +} + +krb5_error_code +krb5_store_times(int fd, krb5_times times) +{ + int ret; + ret = krb5_store_int32(fd, times.authtime); + if(ret) return ret; + ret = krb5_store_int32(fd, times.starttime); + if(ret) return ret; + ret = krb5_store_int32(fd, times.endtime); + if(ret) return ret; + ret = krb5_store_int32(fd, times.renew_till); + return ret; +} + +krb5_error_code +krb5_ret_times(int fd, krb5_times *times) +{ + int ret; + ret = krb5_ret_int32(fd, ×->authtime); + if(ret) return ret; + ret = krb5_ret_int32(fd, ×->starttime); + if(ret) return ret; + ret = krb5_ret_int32(fd, ×->endtime); + if(ret) return ret; + ret = krb5_ret_int32(fd, ×->renew_till); + return ret; +} + +krb5_error_code +krb5_store_address(int fd, krb5_address p) +{ + int ret; + ret = krb5_store_int16(fd, p.type); + if(ret) return ret; + ret = krb5_store_data(fd, p.address); + return ret; +} + +krb5_error_code +krb5_ret_address(int fd, krb5_address *adr) +{ + int16_t t; + int ret; + ret = krb5_ret_int16(fd, &t); + if(ret) return ret; + adr->type = t; + ret = krb5_ret_data(fd, &adr->address); + return ret; +} + +krb5_error_code +krb5_store_addrs(int fd, krb5_addresses p) +{ + int i; + int ret; + ret = krb5_store_int32(fd, p.number); + if(ret) return ret; + for(i = 0; inumber); + if(ret) return ret; + adr->addrs = ALLOC(adr->number, krb5_address); + for(i = 0; i < adr->number; i++){ + ret = krb5_ret_address(fd, &adr->addrs[i]); + if(ret) break; + } + return ret; +} + +krb5_error_code +krb5_store_authdata(int fd, krb5_data p) +{ + return krb5_store_data(fd, p); +} + +krb5_error_code +krb5_ret_authdata(int fd, krb5_data *auth) +{ + return krb5_ret_data(fd, auth); +} diff --git a/lib/krb5/store.h b/lib/krb5/store.h new file mode 100644 index 000000000..8c96db43a --- /dev/null +++ b/lib/krb5/store.h @@ -0,0 +1,74 @@ +#ifndef __STORE_H__ +#define __STORE_H__ + +krb5_error_code +krb5_store_int32(int fd, + int32_t value); + +krb5_error_code +krb5_ret_int32(int fd, + int32_t *value); + +krb5_error_code +krb5_store_int16(int fd, + int16_t value); + +krb5_error_code +krb5_ret_int16(int fd, + int16_t *value); + +krb5_error_code +krb5_store_int8(int fd, + int8_t value); + +krb5_error_code +krb5_ret_int8(int fd, + int8_t *value); + +krb5_error_code +krb5_store_data(int fd, + krb5_data data); + +krb5_error_code +krb5_ret_data(int fd, + krb5_data *data); + +krb5_error_code +krb5_store_principal(int fd, + krb5_principal p); + +krb5_error_code +krb5_ret_principal(int fd, + krb5_principal *princ); + +krb5_error_code +krb5_store_keyblock(int fd, krb5_keyblock p); + +krb5_error_code +krb5_ret_keyblock(int fd, krb5_keyblock *p); + +krb5_error_code +krb5_store_times(int fd, krb5_times times); + +krb5_error_code +krb5_ret_times(int fd, krb5_times *times); + +krb5_error_code +krb5_store_address(int fd, krb5_address p); + +krb5_error_code +krb5_ret_address(int fd, krb5_address *adr); + +krb5_error_code +krb5_store_addrs(int fd, krb5_addresses p); + +krb5_error_code +krb5_ret_addrs(int fd, krb5_addresses *adr); + +krb5_error_code +krb5_store_authdata(int fd, krb5_data p); + +krb5_error_code +krb5_ret_authdata(int fd, krb5_data *auth); + +#endif /* __STORE_H__ */