From 3ee2980a80610a63ae34ace0053ae1c4735def25 Mon Sep 17 00:00:00 2001 From: Johan Danielsson Date: Tue, 11 Mar 1997 19:22:07 +0000 Subject: [PATCH] Some kind of non-working TGS support. git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@1350 ec53bebd-3082-4978-b11e-865c3cabbd6b --- kdc/kdc.c | 318 ++++++++++++++++++++++++++++++++++++++++++------ kdc/kerberos5.c | 318 ++++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 562 insertions(+), 74 deletions(-) diff --git a/kdc/kdc.c b/kdc/kdc.c index 556f19f00..09e4977c6 100644 --- a/kdc/kdc.c +++ b/kdc/kdc.c @@ -2,6 +2,9 @@ RCSID("$Id$"); +struct timeval now; +#define kdc_time now.tv_sec + struct db_entry* db_fetch(krb5_context context, krb5_principal princ) { @@ -50,9 +53,175 @@ krb5_encrypt (krb5_context context, krb5_keyblock *keyblock, krb5_data *result); +krb5_mk_error(krb5_principal princ, + krb5_error_code error_code, + 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); + 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 -foo(krb5_context context, KDC_REQ *req, unsigned char *reply, size_t *len) +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, EncTicketPart *et) +{ + KDCOptions f = req->req_body.kdc_options; + + 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; + + if(f.postdated && req->req_body.from){ + et->starttime = malloc(sizeof(*et->starttime)); + *et->starttime = *req->req_body.from; + et->flags.invalid = 1; + et->flags.postdated = 1; + } + return 0; +} + +krb5_error_code +tgs_rep(krb5_context context, KDC_REQ *req, EncTicketPart *et) +{ + KDCOptions f = req->req_body.kdc_options; + + + 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; + struct db_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; + + ent = db_fetch(context, princ); + if(ent == NULL) return 17; + + err = krb5_rd_req_with_keyblock(context, &ac, + &req->padata->val->padata_value, + princ, + &ent->keyblock, + &ap_req_options, + &ticket); + if(err) return err; + + if(f.forwardable){ + if(!ticket->tkt.flags.forwardable) + return KRB5KDC_ERR_BADOPTION; + et->flags.forwardable = 1; + } + if(f.forwarded){ + if(!ticket->tkt.flags.forwardable) + return KRB5KDC_ERR_BADOPTION; + et->flags.forwarded = 1; + et->caddr = req->req_body.addresses; + } + if(ticket->tkt.flags.forwarded) + et->flags.forwarded = 1; + if(f.proxiable){ + if(!ticket->tkt.flags.proxiable) + return KRB5KDC_ERR_BADOPTION; + et->flags.proxiable = 1; + } + if(f.proxy){ + if(!ticket->tkt.flags.proxiable) + return KRB5KDC_ERR_BADOPTION; + et->flags.proxy = 1; + et->caddr = req->req_body.addresses; + } + if(f.allow_postdate){ + if(!ticket->tkt.flags.may_postdate) + return KRB5KDC_ERR_BADOPTION; + et->flags.may_postdate = 1; + } + if(f.postdated){ + if(!ticket->tkt.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(!ticket->tkt.flags.invalid) + return KRB5KDC_ERR_BADOPTION; + if(*ticket->tkt.starttime > kdc_time) + return KRB5KRB_AP_ERR_TKT_NYV; + /* XXX tkt = tgt */ + et->flags.invalid = 0; + } + /* check for excess flags */ + + if(f.renew){ + time_t old_life; + if(!ticket->tkt.flags.renewable) + return KRB5KDC_ERR_BADOPTION; + if(*ticket->tkt.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 = ticket->tkt.endtime - *ticket->tkt.starttime; + et->endtime = MIN(*ticket->tkt.renew_till, + *et->starttime + old_life); + }else{ + time_t till; + et->starttime = malloc(sizeof(*et->starttime)); + *et->starttime = kdc_time; + } + req->req_body.cname = malloc(sizeof(*req->req_body.cname)); + krb5_principal2principalname(req->req_body.cname, + ticket->enc_part2.client); + } + +} + + +krb5_error_code +process_request(krb5_context context, + KDC_REQ *req, + krb5_data *reply) { krb5_error_code err; krb5_principal princ; @@ -61,7 +230,6 @@ foo(krb5_context context, KDC_REQ *req, unsigned char *reply, size_t *len) DB *db; DBT key, value; - struct timeval now; KDC_REP rep; EncTicketPart et; @@ -69,57 +237,103 @@ foo(krb5_context context, KDC_REQ *req, unsigned char *reply, size_t *len) struct db_entry *cname, *sname; + + gettimeofday(&now, NULL); + + memset(&rep, 0, sizeof(rep)); + rep.pvno = 5; + if(req->msg_type == krb_as_req) + rep.msg_type = krb_as_rep; + else if(req->msg_type == krb_tgs_req){ + rep.msg_type = krb_tgs_rep; + + }else{ + /* XXX */ + return KRB5KRB_AP_ERR_MSG_TYPE; + } + err = principalname2krb5_principal (&princ, + *req->req_body.sname, + req->req_body.realm); + if(err) return err; + sname = db_fetch(context, princ); + if(sname == NULL){ + krb5_mk_error(princ, + KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN, + reply); + return 0; + } + + krb5_free_principal(princ); + + memset(&et, 0, sizeof(et)); + if(req->msg_type == krb_as_req) + as_rep(context, req, &et); + else + tgs_rep(context, req, &et); err = principalname2krb5_principal (&princ, *req->req_body.cname, req->req_body.realm); if(err) return err; cname = db_fetch(context, princ); + if(cname == NULL){ + krb5_mk_error(sname->principal, + KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN, + reply); + return 0; + + } krb5_free_principal(princ); - err = principalname2krb5_principal (&princ, - *req->req_body.sname, - req->req_body.realm); - if(err) return err; - sname = db_fetch(context, princ); - krb5_free_principal(princ); - memset(&rep, 0, sizeof(rep)); - rep.pvno = 5; - rep.msg_type = krb_as_rep; rep.crealm = req->req_body.realm; krb5_principal2principalname(&rep.cname, cname->principal); - memset(&rep.ticket, 0, sizeof(rep.ticket)); rep.ticket.tkt_vno = 5; rep.ticket.realm = req->req_body.realm; krb5_principal2principalname(&rep.ticket.sname, sname->principal); - - memset(&et, 0, sizeof(et)); - et.flags.initial = 1; - et.key.keytype = sname->keyblock.keytype; - et.key.keyvalue.data = sname->keyblock.contents.data; - et.key.keyvalue.length = sname->keyblock.contents.length; + mk_des_keyblock(&et.key); et.crealm = req->req_body.realm; - krb5_principal2principalname(&et.cname, cname->principal); - gettimeofday(&now, NULL); - et.authtime = now.tv_sec; + et.cname = *req->req_body.cname; + et.authtime = kdc_time; { time_t till; + time_t start = et.authtime; + if(et.starttime) + start = *et.starttime; till = req->req_body.till; - till = MIN(till, now.tv_sec + sname->max_life); - till = MIN(till, now.tv_sec + cname->max_life); + if(till == 0) + till = start + cname->max_life; + till = MIN(till, start + sname->max_life); + till = MIN(till, start + cname->max_life); et.endtime = till; } + if(req->req_body.kdc_options.renewable && req->req_body.rtime){ + time_t rtime; + time_t start = et.authtime; + if(et.starttime) + start = *et.starttime; + rtime = *req->req_body.rtime; + if(rtime == 0) + rtime = start + cname->max_renew; + rtime = MIN(rtime, start + sname->max_renew); + rtime = MIN(rtime, start + cname->max_renew); + if(rtime > et.endtime){ + et.renew_till = malloc(sizeof(*et.renew_till)); + *et.renew_till = rtime; + et.flags.renewable = 1; + } + } 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 = 1; + ek.last_req.val->lr_type = 0; ek.last_req.val->lr_value = 0; ek.nonce = req->req_body.nonce; ek.flags = et.flags; @@ -127,8 +341,9 @@ foo(krb5_context context, KDC_REQ *req, unsigned char *reply, size_t *len) ek.starttime = et.starttime; ek.endtime = et.endtime; ek.renew_till = et.renew_till; - ek.srealm = et.crealm; - krb5_principal2principalname(&ek.sname, sname->principal); + ek.srealm = req->req_body.realm; + ek.sname = *req->req_body.sname; + ek.caddr = req->req_body.addresses; { unsigned char buf[1024]; @@ -140,7 +355,18 @@ foo(krb5_context context, KDC_REQ *req, unsigned char *reply, size_t *len) &sname->keyblock, &rep.ticket.enc_part.cipher); - err = encode_EncASRepPart(buf + sizeof(buf) - 1, sizeof(buf), &ek); + switch(rep.msg_type){ + case krb_as_rep: + err = encode_EncASRepPart(buf + sizeof(buf) - 1, sizeof(buf), &ek); + break; + case krb_tgs_rep: + err = encode_EncTGSRepPart(buf + sizeof(buf) - 1, sizeof(buf), + &ek); + break; + default: + abort(); + break; + } rep.enc_part.etype = ETYPE_DES_CBC_CRC; rep.enc_part.kvno = NULL; @@ -148,26 +374,37 @@ foo(krb5_context context, KDC_REQ *req, unsigned char *reply, size_t *len) &cname->keyblock, &rep.enc_part.cipher); - *len = encode_AS_REP(reply + 1023, 1024, &rep); - memmove(reply, reply + 1024 - *len, *len); + switch(rep.msg_type){ + case krb_as_rep: + reply->length = encode_AS_REP(buf + sizeof(buf) - 1, + sizeof(buf), &rep); + break; + case krb_tgs_rep: + reply->length = encode_TGS_REP(buf + sizeof(buf) - 1, + sizeof(buf), &rep); + break; + } + reply->data = malloc(reply->length); + memcpy(reply->data, buf + sizeof(buf) - reply->length, reply->length); } return 0; } int -kerberos(krb5_context context, unsigned char *buf, size_t len) +kerberos(krb5_context context, + unsigned char *buf, + size_t len, + krb5_data *reply) { KDC_REQ req; int i; i = decode_AS_REQ(buf, len, &req); if(i >= 0){ - foo(context, &req, buf, &len); - return len; + return process_request(context, &req, reply); } i = decode_TGS_REQ(buf, len, &req); if(i >= 0){ - foo(context, &req, buf, &len); - return len; + return process_request(context, &req, reply); } return -1; } @@ -204,11 +441,18 @@ main(int argc, char **argv) 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); - len = kerberos(context, buf, len); - sendto(s, buf, len, 0, - (struct sockaddr*)&from, from_len); + err = kerberos(context, buf, len, &reply); + if(err){ + fprintf(stderr, "%s\n", krb5_get_err_text(context, err)); + }else{ + sendto(s, reply.data, reply.length, 0, + (struct sockaddr*)&from, from_len); + krb5_data_free(&reply); + } } } } diff --git a/kdc/kerberos5.c b/kdc/kerberos5.c index 556f19f00..09e4977c6 100644 --- a/kdc/kerberos5.c +++ b/kdc/kerberos5.c @@ -2,6 +2,9 @@ RCSID("$Id$"); +struct timeval now; +#define kdc_time now.tv_sec + struct db_entry* db_fetch(krb5_context context, krb5_principal princ) { @@ -50,9 +53,175 @@ krb5_encrypt (krb5_context context, krb5_keyblock *keyblock, krb5_data *result); +krb5_mk_error(krb5_principal princ, + krb5_error_code error_code, + 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); + 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 -foo(krb5_context context, KDC_REQ *req, unsigned char *reply, size_t *len) +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, EncTicketPart *et) +{ + KDCOptions f = req->req_body.kdc_options; + + 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; + + if(f.postdated && req->req_body.from){ + et->starttime = malloc(sizeof(*et->starttime)); + *et->starttime = *req->req_body.from; + et->flags.invalid = 1; + et->flags.postdated = 1; + } + return 0; +} + +krb5_error_code +tgs_rep(krb5_context context, KDC_REQ *req, EncTicketPart *et) +{ + KDCOptions f = req->req_body.kdc_options; + + + 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; + struct db_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; + + ent = db_fetch(context, princ); + if(ent == NULL) return 17; + + err = krb5_rd_req_with_keyblock(context, &ac, + &req->padata->val->padata_value, + princ, + &ent->keyblock, + &ap_req_options, + &ticket); + if(err) return err; + + if(f.forwardable){ + if(!ticket->tkt.flags.forwardable) + return KRB5KDC_ERR_BADOPTION; + et->flags.forwardable = 1; + } + if(f.forwarded){ + if(!ticket->tkt.flags.forwardable) + return KRB5KDC_ERR_BADOPTION; + et->flags.forwarded = 1; + et->caddr = req->req_body.addresses; + } + if(ticket->tkt.flags.forwarded) + et->flags.forwarded = 1; + if(f.proxiable){ + if(!ticket->tkt.flags.proxiable) + return KRB5KDC_ERR_BADOPTION; + et->flags.proxiable = 1; + } + if(f.proxy){ + if(!ticket->tkt.flags.proxiable) + return KRB5KDC_ERR_BADOPTION; + et->flags.proxy = 1; + et->caddr = req->req_body.addresses; + } + if(f.allow_postdate){ + if(!ticket->tkt.flags.may_postdate) + return KRB5KDC_ERR_BADOPTION; + et->flags.may_postdate = 1; + } + if(f.postdated){ + if(!ticket->tkt.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(!ticket->tkt.flags.invalid) + return KRB5KDC_ERR_BADOPTION; + if(*ticket->tkt.starttime > kdc_time) + return KRB5KRB_AP_ERR_TKT_NYV; + /* XXX tkt = tgt */ + et->flags.invalid = 0; + } + /* check for excess flags */ + + if(f.renew){ + time_t old_life; + if(!ticket->tkt.flags.renewable) + return KRB5KDC_ERR_BADOPTION; + if(*ticket->tkt.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 = ticket->tkt.endtime - *ticket->tkt.starttime; + et->endtime = MIN(*ticket->tkt.renew_till, + *et->starttime + old_life); + }else{ + time_t till; + et->starttime = malloc(sizeof(*et->starttime)); + *et->starttime = kdc_time; + } + req->req_body.cname = malloc(sizeof(*req->req_body.cname)); + krb5_principal2principalname(req->req_body.cname, + ticket->enc_part2.client); + } + +} + + +krb5_error_code +process_request(krb5_context context, + KDC_REQ *req, + krb5_data *reply) { krb5_error_code err; krb5_principal princ; @@ -61,7 +230,6 @@ foo(krb5_context context, KDC_REQ *req, unsigned char *reply, size_t *len) DB *db; DBT key, value; - struct timeval now; KDC_REP rep; EncTicketPart et; @@ -69,57 +237,103 @@ foo(krb5_context context, KDC_REQ *req, unsigned char *reply, size_t *len) struct db_entry *cname, *sname; + + gettimeofday(&now, NULL); + + memset(&rep, 0, sizeof(rep)); + rep.pvno = 5; + if(req->msg_type == krb_as_req) + rep.msg_type = krb_as_rep; + else if(req->msg_type == krb_tgs_req){ + rep.msg_type = krb_tgs_rep; + + }else{ + /* XXX */ + return KRB5KRB_AP_ERR_MSG_TYPE; + } + err = principalname2krb5_principal (&princ, + *req->req_body.sname, + req->req_body.realm); + if(err) return err; + sname = db_fetch(context, princ); + if(sname == NULL){ + krb5_mk_error(princ, + KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN, + reply); + return 0; + } + + krb5_free_principal(princ); + + memset(&et, 0, sizeof(et)); + if(req->msg_type == krb_as_req) + as_rep(context, req, &et); + else + tgs_rep(context, req, &et); err = principalname2krb5_principal (&princ, *req->req_body.cname, req->req_body.realm); if(err) return err; cname = db_fetch(context, princ); + if(cname == NULL){ + krb5_mk_error(sname->principal, + KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN, + reply); + return 0; + + } krb5_free_principal(princ); - err = principalname2krb5_principal (&princ, - *req->req_body.sname, - req->req_body.realm); - if(err) return err; - sname = db_fetch(context, princ); - krb5_free_principal(princ); - memset(&rep, 0, sizeof(rep)); - rep.pvno = 5; - rep.msg_type = krb_as_rep; rep.crealm = req->req_body.realm; krb5_principal2principalname(&rep.cname, cname->principal); - memset(&rep.ticket, 0, sizeof(rep.ticket)); rep.ticket.tkt_vno = 5; rep.ticket.realm = req->req_body.realm; krb5_principal2principalname(&rep.ticket.sname, sname->principal); - - memset(&et, 0, sizeof(et)); - et.flags.initial = 1; - et.key.keytype = sname->keyblock.keytype; - et.key.keyvalue.data = sname->keyblock.contents.data; - et.key.keyvalue.length = sname->keyblock.contents.length; + mk_des_keyblock(&et.key); et.crealm = req->req_body.realm; - krb5_principal2principalname(&et.cname, cname->principal); - gettimeofday(&now, NULL); - et.authtime = now.tv_sec; + et.cname = *req->req_body.cname; + et.authtime = kdc_time; { time_t till; + time_t start = et.authtime; + if(et.starttime) + start = *et.starttime; till = req->req_body.till; - till = MIN(till, now.tv_sec + sname->max_life); - till = MIN(till, now.tv_sec + cname->max_life); + if(till == 0) + till = start + cname->max_life; + till = MIN(till, start + sname->max_life); + till = MIN(till, start + cname->max_life); et.endtime = till; } + if(req->req_body.kdc_options.renewable && req->req_body.rtime){ + time_t rtime; + time_t start = et.authtime; + if(et.starttime) + start = *et.starttime; + rtime = *req->req_body.rtime; + if(rtime == 0) + rtime = start + cname->max_renew; + rtime = MIN(rtime, start + sname->max_renew); + rtime = MIN(rtime, start + cname->max_renew); + if(rtime > et.endtime){ + et.renew_till = malloc(sizeof(*et.renew_till)); + *et.renew_till = rtime; + et.flags.renewable = 1; + } + } 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 = 1; + ek.last_req.val->lr_type = 0; ek.last_req.val->lr_value = 0; ek.nonce = req->req_body.nonce; ek.flags = et.flags; @@ -127,8 +341,9 @@ foo(krb5_context context, KDC_REQ *req, unsigned char *reply, size_t *len) ek.starttime = et.starttime; ek.endtime = et.endtime; ek.renew_till = et.renew_till; - ek.srealm = et.crealm; - krb5_principal2principalname(&ek.sname, sname->principal); + ek.srealm = req->req_body.realm; + ek.sname = *req->req_body.sname; + ek.caddr = req->req_body.addresses; { unsigned char buf[1024]; @@ -140,7 +355,18 @@ foo(krb5_context context, KDC_REQ *req, unsigned char *reply, size_t *len) &sname->keyblock, &rep.ticket.enc_part.cipher); - err = encode_EncASRepPart(buf + sizeof(buf) - 1, sizeof(buf), &ek); + switch(rep.msg_type){ + case krb_as_rep: + err = encode_EncASRepPart(buf + sizeof(buf) - 1, sizeof(buf), &ek); + break; + case krb_tgs_rep: + err = encode_EncTGSRepPart(buf + sizeof(buf) - 1, sizeof(buf), + &ek); + break; + default: + abort(); + break; + } rep.enc_part.etype = ETYPE_DES_CBC_CRC; rep.enc_part.kvno = NULL; @@ -148,26 +374,37 @@ foo(krb5_context context, KDC_REQ *req, unsigned char *reply, size_t *len) &cname->keyblock, &rep.enc_part.cipher); - *len = encode_AS_REP(reply + 1023, 1024, &rep); - memmove(reply, reply + 1024 - *len, *len); + switch(rep.msg_type){ + case krb_as_rep: + reply->length = encode_AS_REP(buf + sizeof(buf) - 1, + sizeof(buf), &rep); + break; + case krb_tgs_rep: + reply->length = encode_TGS_REP(buf + sizeof(buf) - 1, + sizeof(buf), &rep); + break; + } + reply->data = malloc(reply->length); + memcpy(reply->data, buf + sizeof(buf) - reply->length, reply->length); } return 0; } int -kerberos(krb5_context context, unsigned char *buf, size_t len) +kerberos(krb5_context context, + unsigned char *buf, + size_t len, + krb5_data *reply) { KDC_REQ req; int i; i = decode_AS_REQ(buf, len, &req); if(i >= 0){ - foo(context, &req, buf, &len); - return len; + return process_request(context, &req, reply); } i = decode_TGS_REQ(buf, len, &req); if(i >= 0){ - foo(context, &req, buf, &len); - return len; + return process_request(context, &req, reply); } return -1; } @@ -204,11 +441,18 @@ main(int argc, char **argv) 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); - len = kerberos(context, buf, len); - sendto(s, buf, len, 0, - (struct sockaddr*)&from, from_len); + err = kerberos(context, buf, len, &reply); + if(err){ + fprintf(stderr, "%s\n", krb5_get_err_text(context, err)); + }else{ + sendto(s, reply.data, reply.length, 0, + (struct sockaddr*)&from, from_len); + krb5_data_free(&reply); + } } } }