From 96f3cac1dad64da0671b94bb206100e6e076100d Mon Sep 17 00:00:00 2001 From: Johan Danielsson Date: Sat, 7 Jun 1997 17:35:53 +0000 Subject: [PATCH] Split into more files. Add support for TCP. git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@1848 ec53bebd-3082-4978-b11e-865c3cabbd6b --- kdc/Makefile.am | 4 +- kdc/connect.c | 257 ++++++++++++++++++++++++++++++++++++++++++++++++ kdc/kdc_locl.h | 14 +++ kdc/kerberos4.c | 15 +++ kdc/kerberos5.c | 147 --------------------------- kdc/main.c | 21 ++++ kdc/misc.c | 33 +++++++ 7 files changed, 343 insertions(+), 148 deletions(-) create mode 100644 kdc/connect.c create mode 100644 kdc/kerberos4.c create mode 100644 kdc/main.c create mode 100644 kdc/misc.c diff --git a/kdc/Makefile.am b/kdc/Makefile.am index 86aec4f32..b8004ee98 100644 --- a/kdc/Makefile.am +++ b/kdc/Makefile.am @@ -1,10 +1,12 @@ # $Id$ -AUTOHEADER_FLAGS = no-dependencies +AUTOHEADER_FLAGS = no-dependencies foreign INCLUDES = -I$(top_builddir)/include bin_PROGRAMS = string2key kdc +kdc_SOURCES = connect.c kerberos4.c kerberos5.c main.c misc.c + LDADD = -L$(top_builddir)/lib/hdb -lhdb -L$(top_builddir)/lib/krb5 -lkrb5 -L$(top_builddir)/lib/des -ldes -L$(top_builddir)/lib/asn1 -lasn1 diff --git a/kdc/connect.c b/kdc/connect.c new file mode 100644 index 000000000..e72569f16 --- /dev/null +++ b/kdc/connect.c @@ -0,0 +1,257 @@ +#include "kdc_locl.h" + +RCSID("$Id$"); + +struct descr { + int s; + int type; + unsigned char *buf; + size_t size; + size_t len; + time_t timeout; +}; + +static void +init_socket(struct descr *d, int type, int port) +{ + struct sockaddr_in sin; + memset(d, 0, sizeof(*d)); + d->s = socket(AF_INET, type, 0); + if(d->s < 0){ + warn("socket(AF_INET, %d, 0)", type); + d->s = -1; + return; + } + d->type = type; + memset(&sin, 0, sizeof(sin)); + sin.sin_family = AF_INET; + sin.sin_port = htons(port); + if(bind(d->s, (struct sockaddr*)&sin, sizeof(sin)) < 0){ + warn("bind(%d)", port); + close(d->s); + d->s = -1; + return; + } + if(type == SOCK_STREAM && listen(d->s, 5) < 0){ + warn("listen"); + close(d->s); + d->s = -1; + } +} + +static int +init_sockets(struct descr **d) +{ + *d = malloc(4 * sizeof(**d)); + init_socket(*d + 0, SOCK_DGRAM, 88); + init_socket(*d + 1, SOCK_DGRAM, 750); + init_socket(*d + 2, SOCK_STREAM, 88); + init_socket(*d + 3, SOCK_STREAM, 750); + return 4; +} + + +static int +process_request(krb5_context context, + unsigned char *buf, + size_t len, + krb5_data *reply) +{ + KDC_REQ req; + krb5_error_code err; + int i; + if (maybe_AS_REQ(buf, len)){ + i = decode_AS_REQ(buf, len, &req); + if(i >= 0){ + err = as_rep(context, &req, reply); + free_AS_REQ(&req); + return err; + } + } + if (maybe_TGS_REQ(buf, len)){ + i = decode_TGS_REQ(buf, len, &req); + if(i >= 0){ + err = tgs_rep(context, &req, reply); + free_TGS_REQ(&req); + return err; + } + } + if (maybe_version4(buf, len)){ + return do_version4(buf, len, reply); + } + return -1; +} + +static void +do_request(krb5_context context, void *buf, size_t len, + int socket, struct sockaddr *from, size_t from_len) +{ + krb5_error_code ret; + krb5_data reply; + ret = process_request(context, buf, len, &reply); + if(ret) + warnx("%s", krb5_get_err_text(context, ret)); + else{ + warnx("sending %d bytes", reply.length); + sendto(socket, reply.data, reply.length, 0, from, from_len); + krb5_data_free(&reply); + } +} + +static void +handle_udp(krb5_context context, struct descr *d) +{ + unsigned char buf[1024]; + struct sockaddr_in from; + size_t from_len = sizeof(from); + size_t n; + n = recvfrom(d->s, buf, sizeof(buf), 0, + (struct sockaddr*)&from, &from_len); + if(n < 0){ + warn("recvfrom"); + return; + } + if(n == 0){ + return; + } + do_request(context, buf, n, d->s, (struct sockaddr*)&from, from_len); +} + +static void +clear_descr(struct descr *d) +{ + if(d->buf) + memset(d->buf, 0, d->size); + d->len = 0; + if(d->s != -1) + close(d->s); + d->s = -1; +} + +static void +handle_tcp(krb5_context context, struct descr *d, int index, int min_free) +{ + unsigned char buf[1024]; + struct sockaddr_in from; + size_t from_len = sizeof(from); + size_t n; + if(d[index].timeout == 0){ + int s; + from_len = sizeof(from); + s = accept(d[index].s, (struct sockaddr*)&from, &from_len); + if(s < 0){ + warn("accept"); + return; + } + if(min_free == -1){ + close(s); + return; + } + + d[min_free].s = s; + d[min_free].timeout = time(NULL) + 4; + d[min_free].type = SOCK_STREAM; + return; + } + n = recvfrom(d[index].s, buf, sizeof(buf), 0, + (struct sockaddr*)&from, &from_len); + if(n < 0){ + warn("recvfrom"); + return; + } + if(d[index].size - d[index].len < n){ + if(d[index].size == 0){ + d[index].buf = malloc(1024); + if(d[index].buf == NULL){ + warnx("No memory"); + close(d[index].s); + return; + } + d[index].size = 1024; + d[index].len = 0; + }else{ + unsigned char *tmp; + tmp = realloc(d[index].buf, 2 * d[index].size); + if(tmp == NULL){ + warnx("No memory"); + close(d[index].s); + return; + } + } + } + memcpy(d[index].buf + d[index].len, buf, n); + d[index].len += n; + if(d[index].len > 4 && d[index].buf[0] == 0){ + krb5_storage *sp; + int32_t len; + sp = krb5_storage_from_mem(d[index].buf, d[index].len); + krb5_ret_int32(sp, &len); + krb5_storage_free(sp); + if(d[index].len - 4 >= len){ + memcpy(d[index].buf, d[index].buf + 4, d[index].len - 4); + n = 0; + } + } + if(n == 0){ + do_request(context, d[index].buf, d[index].len, + d[index].s, (struct sockaddr*)&from, from_len); + clear_descr(d + index); + } +} + + + +void +loop(krb5_context context) +{ + struct descr *d; + int ndescr; + ndescr = init_sockets(&d); + while(1){ + struct fd_set fds; + int min_free = -1; + int max_fd = 0; + int i; + FD_ZERO(&fds); + for(i = 0; i < ndescr; i++){ + if(d[i].s >= 0){ + if(d[i].type == SOCK_STREAM && + d[i].timeout && d[i].timeout < time(NULL)){ + clear_descr(&d[i]); + continue; + } + if(max_fd < d[i].s) + max_fd = d[i].s; + FD_SET(d[i].s, &fds); + }else if(min_free < 0 || i < min_free) + min_free = i; + } + if(min_free == -1){ + struct descr *tmp; + tmp = realloc(d, (ndescr + 4) * sizeof(*d)); + if(tmp == NULL) + warnx("No memory"); + else{ + d = tmp; + memset(d + ndescr, 0, 4 * sizeof(*d)); + min_free = ndescr; + ndescr += 4; + } + } + + switch(select(max_fd + 1, &fds, 0, 0, 0)){ + case 0: + break; + case -1: + warn("select"); + break; + default: + for(i = 0; i < ndescr; i++) + if(FD_ISSET(d[i].s, &fds)) + if(d[i].type == SOCK_DGRAM) + handle_udp(context, &d[i]); + else if(d[i].type == SOCK_STREAM) + handle_tcp(context, d, i, min_free); + } + } +} diff --git a/kdc/kdc_locl.h b/kdc/kdc_locl.h index d2781f68a..57c77b6cf 100644 --- a/kdc/kdc_locl.h +++ b/kdc/kdc_locl.h @@ -21,5 +21,19 @@ #include "hdb.h" +extern struct timeval now; +#define kdc_time (now.tv_sec) + +hdb_entry *db_fetch (krb5_context, PrincipalName *, char *); + +krb5_error_code mk_des_keyblock (EncryptionKey *); + +krb5_error_code tgs_rep(krb5_context, KDC_REQ *, krb5_data *); +krb5_error_code as_rep(krb5_context, KDC_REQ *, krb5_data *); + +int maybe_version4(unsigned char*, int); +krb5_error_code do_version4(); + +void loop (krb5_context); #endif /* __KDC_LOCL_H__ */ diff --git a/kdc/kerberos4.c b/kdc/kerberos4.c new file mode 100644 index 000000000..78bf6f0a3 --- /dev/null +++ b/kdc/kerberos4.c @@ -0,0 +1,15 @@ +#include "kdc_locl.h" + +RCSID("$Id$"); + +int +maybe_version4(unsigned char *buf, int len) +{ + return len > 0 && *buf == 4; +} + +krb5_error_code +do_version4() +{ + +} diff --git a/kdc/kerberos5.c b/kdc/kerberos5.c index 73a638e5e..634dda3a0 100644 --- a/kdc/kerberos5.c +++ b/kdc/kerberos5.c @@ -2,29 +2,12 @@ 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, @@ -32,45 +15,6 @@ krb5_encrypt (krb5_context context, 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, @@ -536,94 +480,3 @@ tgs_rep(krb5_context context, } } - - -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); - } - } - } -} diff --git a/kdc/main.c b/kdc/main.c new file mode 100644 index 000000000..fdd780a14 --- /dev/null +++ b/kdc/main.c @@ -0,0 +1,21 @@ +#include "kdc_locl.h" + +RCSID("$Id$"); + +RETSIGTYPE +sigterm(int sig) +{ + exit(0); +} + +int +main(int argc, char **argv) +{ + krb5_context context; + des_cblock key; + des_new_random_key(&key); + memset(&key, 0, sizeof(key)); + signal(SIGINT, sigterm); + krb5_init_context(&context); + loop(context); +} diff --git a/kdc/misc.c b/kdc/misc.c new file mode 100644 index 000000000..92465babb --- /dev/null +++ b/kdc/misc.c @@ -0,0 +1,33 @@ +#include "kdc_locl.h" + +RCSID("$Id$"); + +struct timeval now; + +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; +} + +/* this should move someplace else */ +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_new_random_key(kb->keyvalue.data); + return 0; +} + + +