diff --git a/kdc/kdc.c b/kdc/kdc.c deleted file mode 100644 index 73a638e5e..000000000 --- a/kdc/kdc.c +++ /dev/null @@ -1,629 +0,0 @@ -#include "kdc_locl.h" - -RCSID("$Id$"); - -struct timeval now; -#define kdc_time now.tv_sec - -#ifndef MIN -#define MIN(A,B) ((A)<(B)?(A):(B)) -#endif - -#define MAX_TIME ((time_t)((1U << 31) - 1)) - -hdb_entry* -db_fetch(krb5_context context, PrincipalName *principal, char *realm) -{ - HDB *db; - hdb_entry *ent; - - ent = malloc(sizeof(*ent)); - principalname2krb5_principal(&ent->principal, *principal, realm); - hdb_open(context, &db, NULL, O_RDONLY, 0); - db->fetch(context, db, ent); - db->close(context, db); - return ent; -} - -krb5_error_code -krb5_encrypt (krb5_context context, - void *ptr, - size_t len, - krb5_keyblock *keyblock, - krb5_data *result); - -krb5_error_code -krb5_mk_error(krb5_principal princ, - krb5_error_code error_code, - char *e_text, - krb5_data *e_data, - krb5_data *err) -{ - KRB_ERROR msg; - unsigned char buf[1024]; - - memset(&msg, 0, sizeof(msg)); - msg.pvno = 5; - msg.msg_type = krb_error; - msg.stime = time(0); - msg.error_code = error_code; - msg.realm = princ->realm.data; - krb5_principal2principalname(&msg.sname, princ); - if (e_text) - msg.e_text = &e_text; - if (e_data) - msg.e_data = e_data; - err->length = encode_KRB_ERROR(buf + sizeof(buf) - 1, sizeof(buf), &msg); - err->data = malloc(err->length); - memcpy(err->data, buf + sizeof(buf) - err->length, err->length); - return 0; -} - -krb5_error_code -mk_des_keyblock(EncryptionKey *kb) -{ - kb->keytype = KEYTYPE_DES; - kb->keyvalue.data = malloc(sizeof(des_cblock)); - kb->keyvalue.length = sizeof(des_cblock); - des_rand_data_key(kb->keyvalue.data); - return 0; -} - - - -krb5_error_code -as_rep(krb5_context context, - KDC_REQ *req, - krb5_data *data) -{ - KDC_REQ_BODY *b = &req->req_body; - AS_REP rep; - KDCOptions f = b->kdc_options; - hdb_entry *client, *server; - int use_etype; - EncTicketPart *et = calloc(1, sizeof(*et)); - EncKDCRepPart *ek = calloc(1, sizeof(*ek)); - krb5_principal client_princ; - - client = db_fetch(context, b->cname, b->realm); - server = db_fetch(context, b->sname, b->realm); - - if(client == NULL) - return KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN; - if(server == NULL){ - hdb_free_entry(context, client); - free(client); - return KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN; - } - - principalname2krb5_principal (&client_princ, *(b->cname), b->realm); - - /* XXX Check for pa_enc_timestamp */ - - if(req->padata == NULL || req->padata->len < 1 || - req->padata->val->padata_type != pa_enc_timestamp) { - PA_DATA foo; - u_char buf[16]; - int len; - krb5_data foo_data; - - foo.padata_type = pa_enc_timestamp; - foo.padata_value.length = 0; - foo.padata_value.data = NULL; - - len = encode_PA_DATA(buf + sizeof(buf) - 1, - sizeof(buf), - &foo); - foo_data.length = len; - foo_data.data = buf + sizeof(buf) - len; - - krb5_mk_error (client_princ, - KRB5KDC_ERR_PREAUTH_REQUIRED, - "Need to use PA-ENC-TIMESTAMP", - &foo_data, - data); - - return 0; - } else { - krb5_data ts_data; - PA_ENC_TS_ENC p; - int len; - - krb5_decrypt (context, - req->padata->val->padata_value.data, - req->padata->val->padata_value.length, - &client->keyblock, - &ts_data); - len = decode_PA_ENC_TS_ENC(ts_data.data, - ts_data.length, - &p); - if (len < 0) { - krb5_mk_error (client_princ, - KRB5KRB_AP_ERR_BAD_INTEGRITY, - "Couldn't decode", - NULL, - data); - return 0; - } - if (kdc_time - p.patimestamp > 300) { - krb5_mk_error (client_princ, - KRB5KDC_ERR_PREAUTH_FAILED, - "Too large time skew", - NULL, - data); - return 0; - } - - } - - if(b->etype.len == 0) - return KRB5KDC_ERR_ETYPE_NOSUPP; /* XXX */ - use_etype = b->etype.val[0]; - - memset(&rep, 0, sizeof(rep)); - rep.pvno = 5; - rep.msg_type = krb_as_rep; - copy_Realm(&b->realm, &rep.crealm); - copy_PrincipalName(b->cname, &rep.cname); - rep.ticket.tkt_vno = 5; - copy_Realm(&b->realm, &rep.ticket.realm); - copy_PrincipalName(b->sname, &rep.ticket.sname); - - if(f.renew || f.validate || f.proxy || f.forwarded || f.enc_tkt_in_skey) - return KRB5KDC_ERR_BADOPTION; - - et->flags.initial = 1; - et->flags.forwardable = f.forwardable; - et->flags.proxiable = f.proxiable; - et->flags.may_postdate = f.allow_postdate; - - mk_des_keyblock(&et->key); - copy_PrincipalName(b->cname, &et->cname); - copy_Realm(&b->realm, &et->crealm); - - { - time_t start; - time_t t; - - start = et->authtime = kdc_time; - - if(f.postdated && req->req_body.from){ - et->starttime = malloc(sizeof(*et->starttime)); - start = *et->starttime = *req->req_body.from; - et->flags.invalid = 1; - et->flags.postdated = 1; /* XXX ??? */ - } - if(b->till == 0) - b->till = MAX_TIME; - t = b->till; - if(client->max_life) - t = MIN(t, start + client->max_life); - if(server->max_life) - t = MIN(t, start + server->max_life); -#if 0 - t = MIN(t, start + realm->max_life); -#endif - et->endtime = t; - if(f.renewable_ok && et->endtime < b->till){ - f.renewable = 1; - if(b->rtime == NULL){ - b->rtime = malloc(sizeof(*b->rtime)); - *b->rtime = 0; - } - if(*b->rtime < b->till) - *b->rtime = b->till; - } - if(f.renewable && b->rtime){ - t = *b->rtime; - if(t == 0) - t = MAX_TIME; - if(client->max_renew) - t = MIN(t, start + client->max_renew); - if(server->max_renew) - t = MIN(t, start + server->max_renew); -#if 0 - t = MIN(t, start + realm->max_renew); -#endif - et->renew_till = malloc(sizeof(*et->renew_till)); - *et->renew_till = t; - } - } - if(b->addresses){ - et->caddr = malloc(sizeof(*et->caddr)); - copy_HostAddresses(b->addresses, et->caddr); - } - - memset(ek, 0, sizeof(*ek)); - copy_EncryptionKey(&et->key, &ek->key); - /* MIT must have at least one last_req */ - ek->last_req.len = 1; - ek->last_req.val = malloc(sizeof(*ek->last_req.val)); - ek->last_req.val->lr_type = 0; - ek->last_req.val->lr_value = 0; - ek->nonce = b->nonce; - ek->flags = et->flags; - ek->authtime = et->authtime; - ek->starttime = et->starttime; - ek->endtime = et->endtime; - ek->renew_till = et->renew_till; - copy_Realm(&rep.ticket.realm, &ek->srealm); - copy_PrincipalName(&rep.ticket.sname, &ek->sname); - if(et->caddr){ - ek->caddr = malloc(sizeof(*ek->caddr)); - copy_HostAddresses(et->caddr, ek->caddr); - } - - { - unsigned char buf[1024]; /* XXX The data could be indefinite */ - int len; - len = encode_EncTicketPart(buf + sizeof(buf) - 1, sizeof(buf), et); - free_EncTicketPart(et); - free(et); - if(len < 0) - return ASN1_OVERFLOW; - - rep.ticket.enc_part.etype = ETYPE_DES_CBC_CRC; - rep.ticket.enc_part.kvno = NULL; - krb5_encrypt(context, buf + sizeof(buf) - len, len, &server->keyblock, - &rep.ticket.enc_part.cipher); - - len = encode_EncASRepPart(buf + sizeof(buf) - 1, sizeof(buf), ek); - free_EncKDCRepPart(ek); - free(ek); - if(len < 0) - return ASN1_OVERFLOW; - rep.enc_part.etype = ETYPE_DES_CBC_CRC; - rep.enc_part.kvno = NULL; - - krb5_encrypt(context, buf + sizeof(buf) - len, len, &client->keyblock, - &rep.enc_part.cipher); - - len = encode_AS_REP(buf + sizeof(buf) - 1, sizeof(buf), &rep); - if(len < 0) - return ASN1_OVERFLOW; - free_AS_REP(&rep); - - krb5_data_copy(data, buf + sizeof(buf) - len, len); - - } - - return 0; -} - -krb5_error_code -tgs_rep(krb5_context context, - KDC_REQ *req, - krb5_data *data) -{ - KDC_REQ_BODY *b = &req->req_body; - KDCOptions f = req->req_body.kdc_options; - EncTicketPart *tgt; - hdb_entry *server, *krbtgt, *client; - TGS_REP rep; - EncTicketPart *et = calloc(1, sizeof(*et)); - EncKDCRepPart *ek = calloc(1, sizeof(*ek)); - - if(req->padata == NULL || req->padata->len < 1) - return KRB5KDC_ERR_PREAUTH_REQUIRED; /* XXX ??? */ - if(req->padata->val->padata_type != pa_tgs_req) - return KRB5KDC_ERR_PADATA_TYPE_NOSUPP; - - { - krb5_auth_context ac = NULL; - krb5_principal princ; - krb5_flags ap_req_options; - krb5_ticket *ticket; - krb5_error_code err; - hdb_entry *ent; - - err = krb5_build_principal(context, - &princ, - strlen(req->req_body.realm), - req->req_body.realm, - "krbtgt", - req->req_body.realm, - NULL); - if(err) return err; - - { - PrincipalName p; - p.name_string.val = calloc(2, sizeof(*p.name_string.val)); - p.name_string.len = 2; - p.name_string.val[0] = "krbtgt"; - p.name_string.val[1] = req->req_body.realm; - krbtgt = db_fetch(context, &p, req->req_body.realm); - free(p.name_string.val); - } - if(ent == NULL) - return KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN; - - err = krb5_rd_req_with_keyblock(context, &ac, - &req->padata->val->padata_value, - princ, - &krbtgt->keyblock, - &ap_req_options, - &ticket); - if(err) - return err; - - /* XXX Check authenticator */ - - server = db_fetch(context, b->sname, b->realm); - - if(server == NULL) - return KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN; - - tgt = &ticket->tkt; - - client = db_fetch(context, &tgt->cname, tgt->crealm); - if(client == NULL) - return KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN; - - memset(&rep, 0, sizeof(rep)); - rep.pvno = 5; - rep.msg_type = krb_tgs_rep; - rep.crealm = tgt->crealm; - rep.cname = tgt->cname; - rep.ticket.tkt_vno = 5; - rep.ticket.sname = *b->sname; - rep.ticket.realm = b->realm; - - et->caddr = ticket->tkt.caddr; - - if(f.forwardable){ - if(!tgt->flags.forwardable) - return KRB5KDC_ERR_BADOPTION; - et->flags.forwardable = 1; - } - if(f.forwarded){ - if(!tgt->flags.forwardable) - return KRB5KDC_ERR_BADOPTION; - et->flags.forwarded = 1; - et->caddr = req->req_body.addresses; - /* resp.caddr := req.addresses */ - } - et->flags.forwarded = tgt->flags.forwarded; - - if(f.proxiable){ - if(!tgt->flags.proxiable) - return KRB5KDC_ERR_BADOPTION; - et->flags.proxiable = 1; - } - if(f.proxy){ - if(!tgt->flags.proxiable) - return KRB5KDC_ERR_BADOPTION; - et->flags.proxy = 1; - et->caddr = req->req_body.addresses; - /* resp.caddr := req.addresses */ - } - if(f.allow_postdate){ - if(!tgt->flags.may_postdate) - return KRB5KDC_ERR_BADOPTION; - et->flags.may_postdate = 1; - } - if(f.postdated){ - if(!tgt->flags.may_postdate) - return KRB5KDC_ERR_BADOPTION; - et->flags.postdated = 1; - et->flags.invalid = 1; - et->starttime = malloc(sizeof(*et->starttime)); - *et->starttime = *req->req_body.from; - } - if(f.validate){ - if(!tgt->flags.invalid) - return KRB5KDC_ERR_BADOPTION; - if(*tgt->starttime > kdc_time) - return KRB5KRB_AP_ERR_TKT_NYV; - /* XXX tkt = tgt */ - et->flags.invalid = 0; - } - /* check for excess flags */ - - et->authtime = tgt->authtime; - - if(f.renew){ - time_t old_life; - if(!tgt->flags.renewable) - return KRB5KDC_ERR_BADOPTION; - if(*tgt->renew_till >= kdc_time) - return KRB5KRB_AP_ERR_TKT_EXPIRED; - /* XXX tkt = tgt */ - et->starttime = malloc(sizeof(*et->starttime)); - *et->starttime = kdc_time; - old_life = tgt->endtime - *tgt->starttime; - et->endtime = MIN(*tgt->renew_till, - *et->starttime + old_life); - }else{ - time_t till; - et->starttime = malloc(sizeof(*et->starttime)); - *et->starttime = kdc_time; - till = b->till; - if(till == 0) - till = MAX_TIME; - if(client->max_life) - till = MIN(till, *et->starttime + client->max_life); - if(server->max_life) - till = MIN(till, *et->starttime + server->max_life); - till = MIN(till, tgt->endtime); -#if 0 - till = MIN(till, et->starttime + realm->max_life); -#endif - et->endtime = till; - if(f.renewable_ok && - et->endtime < b->till && - tgt->flags.renewable){ - f.renewable = 1; - b->rtime = malloc(sizeof(*b->rtime)); - *b->rtime = MIN(b->till, *tgt->renew_till); - } - } - if(f.renewable && tgt->flags.renewable && b->rtime){ - time_t rtime; - rtime = *b->rtime; - if(rtime == 0) - rtime = MAX_TIME; - et->flags.renewable = 1; - if(client->max_renew) - rtime = MIN(rtime, *et->starttime + client->max_renew); - if(server->max_renew) - rtime = MIN(rtime, *et->starttime + server->max_renew); - rtime = MIN(rtime, *tgt->renew_till); -#if 0 - rtime = MIN(rtime, *et->starttime + realm->max_renew); -#endif - et->renew_till = malloc(sizeof(*et->renew_till)); - *et->renew_till = rtime; - } - - /* XXX Check enc-authorization-data */ - - - mk_des_keyblock(&et->key); - et->crealm = tgt->crealm; - et->cname = tgt->cname; - et->transited = tgt->transited; - - - memset(ek, 0, sizeof(*ek)); - ek->key = et->key; - /* MIT must have at least one last_req */ - ek->last_req.len = 1; - ek->last_req.val = malloc(sizeof(*ek->last_req.val)); - ek->last_req.val->lr_type = 0; - ek->last_req.val->lr_value = 0; - ek->nonce = b->nonce; - ek->flags = et->flags; - ek->authtime = et->authtime; - ek->starttime = et->starttime; - ek->endtime = et->endtime; - ek->renew_till = et->renew_till; - ek->srealm = rep.ticket.realm; - ek->sname = rep.ticket.sname; - ek->caddr = et->caddr; - - { - unsigned char buf[1024]; /* XXX The data could be indefinite */ - int len; - len = encode_EncTicketPart(buf + sizeof(buf) - 1, sizeof(buf), et); - if(len < 0) - return ASN1_OVERFLOW; - rep.ticket.enc_part.etype = ETYPE_DES_CBC_CRC; - rep.ticket.enc_part.kvno = NULL; - krb5_encrypt(context, buf + sizeof(buf) - len, len, &server->keyblock, - &rep.ticket.enc_part.cipher); - - len = encode_EncTGSRepPart(buf + sizeof(buf) - 1, sizeof(buf), ek); - if(len < 0) - return ASN1_OVERFLOW; - rep.enc_part.etype = ETYPE_DES_CBC_CRC; - rep.enc_part.kvno = NULL; - { - krb5_keyblock kb; - kb.keytype = tgt->key.keytype; - kb.contents = tgt->key.keyvalue; - krb5_encrypt(context, buf + sizeof(buf) - len, len, &kb, - &rep.enc_part.cipher); - } - - len = encode_TGS_REP(buf + sizeof(buf) - 1, sizeof(buf), &rep); - if(len < 0) - return ASN1_OVERFLOW; - free_TGS_REP(&rep); - krb5_data_copy(data, buf + sizeof(buf) - len, len); - } - - return 0; - } - -} - - -krb5_error_code -process_request(krb5_context context, - KDC_REQ *req, - krb5_data *reply) -{ - gettimeofday(&now, NULL); - - if(req->msg_type == krb_as_req) - return as_rep(context, req, reply); - else if(req->msg_type == krb_tgs_req) - return tgs_rep(context, req, reply); - else - return KRB5KRB_AP_ERR_MSG_TYPE; /* XXX */ -} - -int -kerberos(krb5_context context, - unsigned char *buf, - size_t len, - krb5_data *reply) -{ - KDC_REQ req; - krb5_error_code err; - int i; - i = decode_AS_REQ(buf, len, &req); - if(i >= 0){ - err = process_request(context, &req, reply); - free_AS_REQ(&req); - return err; - } - i = decode_TGS_REQ(buf, len, &req); - if(i >= 0){ - err = process_request(context, &req, reply); - free_TGS_REQ(&req); - return err; - } - return -1; -} - -main(int argc, char **argv) -{ - krb5_context context; - int s = socket(AF_INET, SOCK_DGRAM, 0); - struct sockaddr_in sin; - int one = 1; - if(s < 0){ - perror("socket"); - exit(1); - } - krb5_init_context(&context); - memset(&sin, 0, sizeof(sin)); - sin.sin_family = AF_INET; - sin.sin_port = htons(88); - if(bind(s, (struct sockaddr*)&sin, sizeof(sin)) < 0){ - perror("bind"); - exit(1); - } - setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)); - while(1){ - fd_set fds; - unsigned char buf[1024]; - size_t len; - FD_ZERO(&fds); - FD_SET(s, &fds); - if(select(s + 1, &fds, NULL, NULL, NULL) < 0){ - perror("select"); - exit(1); - } - if(FD_ISSET(s, &fds)){ - struct sockaddr_in from; - int from_len = sizeof(from); - krb5_error_code err; - krb5_data reply; - len = recvfrom(s, buf, sizeof(buf), 0, - (struct sockaddr*)&from, &from_len); - fprintf(stderr, "%d byte packet from %s\n", - len, inet_ntoa(from.sin_addr)); - err = kerberos(context, buf, len, &reply); - if(err){ - fprintf(stderr, "%s\n", krb5_get_err_text(context, err)); - }else{ - fprintf(stderr, "sending %d bytes\n", reply.length); - sendto(s, reply.data, reply.length, 0, - (struct sockaddr*)&from, from_len); - krb5_data_free(&reply); - } - } - } -}