From e2475934ac246abb0e6ea261fc61ed748eb5fd02 Mon Sep 17 00:00:00 2001 From: Assar Westerlund Date: Sun, 17 Mar 1996 14:59:05 +0000 Subject: [PATCH] kinit now builds and works on some machines git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@302 ec53bebd-3082-4978-b11e-865c3cabbd6b --- Makefile | 17 ++-- cache.c | 6 +- config_file.y | 5 +- d.c | 9 +- der.c | 5 +- der.h | 2 +- der_get.c | 179 --------------------------------------- der_put.c | 150 ++++++++++++++++++++++++++++++++ e.c | 31 +++---- get_addrs.c | 45 ++++++++++ get_in_tkt.c | 110 +++++++++++++++++------- get_in_tkt_pw.c | 14 +-- k5_der.c | 37 ++++---- k5_der.h | 99 ++++++++-------------- kinit.c | 44 ++++++++++ krb5.h | 44 +++++++--- krb5_error.h | 6 ++ krb5_locl.h | 9 ++ krbhst.c | 6 +- kuser/kinit.c | 44 ++++++++++ lib/krb5/cache.c | 6 +- lib/krb5/config_file.y | 5 +- lib/krb5/get_addrs.c | 45 ++++++++++ lib/krb5/get_in_tkt.c | 110 +++++++++++++++++------- lib/krb5/get_in_tkt_pw.c | 14 +-- lib/krb5/krb5.h | 44 +++++++--- lib/krb5/krb5_error.h | 6 ++ lib/krb5/krb5_locl.h | 9 ++ lib/krb5/krbhst.c | 6 +- lib/krb5/send_to_kdc.c | 47 +++++++--- lib/krb5/str2key.c | 6 +- send_to_kdc.c | 47 +++++++--- str2key.c | 6 +- 33 files changed, 781 insertions(+), 432 deletions(-) delete mode 100644 der_get.c create mode 100644 der_put.c create mode 100644 get_addrs.c create mode 100644 kinit.c create mode 100644 kuser/kinit.c create mode 100644 lib/krb5/get_addrs.c diff --git a/Makefile b/Makefile index ec365c05c..d3fcf770c 100644 --- a/Makefile +++ b/Makefile @@ -1,16 +1,21 @@ -CC=cc -std1 -CFLAGS=-I/usr/athena/include -g +CC=cc +CFLAGS=-I. -I/usr/athena/include -g -YFLAGS = -d +#YACC=bison -y +YACC=yacc SOURCES = cache.c principal.c principal_p.c data.c context.c misc.c \ - krbhst.c getport.c send_to_kdc.c der.c e.c d.c str2key.c \ - get_in_tkt.c get_in_tkt_pw.c + krbhst.c get_port.c send_to_kdc.c der.c e.c d.c str2key.c \ + get_in_tkt.c get_in_tkt_pw.c der_put.c constants.c get_addrs.c \ + k5_der.c OBJECTS = $(SOURCES:%.c=%.o) config_file.o +kinit: kinit.o libkrb5.a + $(CC) -o kinit kinit.o libkrb5.a -L/usr/local/lib -ldes + tt: test.o libkrb5.a $(CC) -o tt test.o libkrb5.a @@ -23,7 +28,7 @@ libkrb5.a: $(OBJECTS) config_file.o: config_file.c config_file.c: config_file.y - yacc -b y -p __k5cf_ $< + $(YACC) -p __k5cf_ $< mv -f y.tab.c config_file.c clean: diff --git a/cache.c b/cache.c index 56d7a1899..05f945316 100644 --- a/cache.c +++ b/cache.c @@ -46,6 +46,10 @@ krb5_error_code krb5_cc_default(krb5_context context, krb5_ccache *id) { + *id = malloc(sizeof(**id)); + if (*id == NULL) + return ENOMEM; + return krb5_cc_resolve (context, id, "/tmp/foo"); } static krb5_error_code @@ -112,7 +116,7 @@ krb5_cc_initialize(krb5_context context, if(ret = erase_file(f->filename)) return ret; - fd = open(f->filename, O_RDWR, 0600); + fd = open(f->filename, O_RDWR | O_CREAT | O_EXCL, 0600); if(fd == -1) return errno; store_int16(fd, 0x503); diff --git a/config_file.y b/config_file.y index 1936c519f..82fd938bb 100644 --- a/config_file.y +++ b/config_file.y @@ -19,6 +19,9 @@ static krb5_config_relation **crel; static krb5_config_relation **rels[16]; static int relp; +static void yyerror (char *); +static int yylex (void); + %} %union { @@ -143,7 +146,7 @@ static int yylex(void) return type; } -static void yyerror(char *s) +void yyerror(char *s) { printf("yyerror: %s\n", s); } diff --git a/d.c b/d.c index 5ec9dab51..d6c8ea909 100644 --- a/d.c +++ b/d.c @@ -1,6 +1,4 @@ -#include -#include -#include +#include #include int @@ -160,8 +158,8 @@ der_get_octetstring (Buffer *b, void *val) char *p; len = buf_bytesleft (b); - str->len = len; - str->data = p = malloc (len + 1); + str->length = len; + str->data = p = malloc (len + 1); while (len && (c = buf_getbyte (b)) != EOF) { *p++ = c; --len; @@ -177,6 +175,7 @@ der_get_generalizedtime (Buffer *b, void *val) int len; krb5_data str; struct tm tm; + extern long timezone; len = der_get_octetstring (b, &str); sscanf (str.data, "%04d%02d%02d%02d%02d%02dZ", diff --git a/der.c b/der.c index 2d4f364cc..302175a03 100644 --- a/der.c +++ b/der.c @@ -1,5 +1,4 @@ -#include -#include +#include #include /* @@ -11,7 +10,7 @@ string_make_n (int n, char *s) { krb5_data ret; - ret.len = n; + ret.length = n; ret.data = s; return ret; } diff --git a/der.h b/der.h index 30ed912e3..8ae2facce 100644 --- a/der.h +++ b/der.h @@ -20,7 +20,7 @@ enum { UT_IA5String = 22, UT_UTCTime = 23, UT_GeneralizedTime = 24, - UT_GeneralString = 27, + UT_GeneralString = 27 }; krb5_data string_make (char *); diff --git a/der_get.c b/der_get.c deleted file mode 100644 index 6b80d80a3..000000000 --- a/der_get.c +++ /dev/null @@ -1,179 +0,0 @@ -#include -#include -#include - -/* - * Functions for parsing DER - */ - -unsigned -der_get_length (unsigned char *ptr, unsigned *res) -{ - unsigned char *p = ptr; - unsigned char c; - - c = *p++; - if (c < 0x80) { - *res = c; - return 1; - } else { - c &= 0x7F; - *res = 0; - while (c--) - *res = *res * 0x100 + *p++; - return p - ptr; - } -} - -unsigned -der_get_tag (unsigned char *ptr, Der_class *class, Der_type *type, - unsigned *tag) -{ - unsigned char *p = ptr; - unsigned char o1; - - o1 = *p++; - *class = o1 >> 6; - *type = (o1 >> 5) & 1; - *tag = o1 & 0x1F; - if (*tag == 0x1F) { - do { - o1 = *p++; - *tag = *tag * 0x80 + (o1 & 0x7F); - } while( o1 & 0x80); - } - return p - ptr; -} - -unsigned -der_get_integer (unsigned char *ptr, int len, void *v) -{ - unsigned char *p = ptr; - unsigned *res = v; - - *res = 0; - while(len--) - *res = *res * 0x100 + *p++; - return p - ptr; -} - -unsigned -der_get_octetstring (unsigned char *ptr, int len, void *v) -{ - unsigned char *p = ptr; - krb5_data *res = v; - - res->data = malloc(len + 1); - res->len = len; - memcpy (*res, p, len); - (*res)[len] = '\0'; - p += len; - - return p - ptr; -} - -static unsigned (*get_univ_funcs[])(unsigned char *, int len, void *val) = { - NULL, /* 0 */ - NULL, /* 1 */ - der_get_integer, /* 2 */ - NULL, /* 3 */ - der_get_octetstring, /* 4 */ - NULL, /* 5 */ - NULL, /* 6 */ - NULL, /* 7 */ - NULL, /* 8 */ - NULL, /* 9 */ - NULL, /* 10 */ - NULL, /* 11 */ - NULL, /* 12 */ - NULL, /* 13 */ - NULL, /* 14 */ - NULL, /* 15 */ - NULL, /* 16 */ - NULL, /* 17 */ - NULL, /* 18 */ - NULL, /* 19 */ - NULL, /* 20 */ - NULL, /* 21 */ - NULL, /* 22 */ - NULL, /* 23 */ - der_get_octetstring, /* 24 */ - NULL, /* 25 */ - NULL, /* 26 */ - der_get_octetstring, /* 27 */ -}; - -unsigned -der_get_val (unsigned char *ptr, int type, int len, void *val) -{ - return (*(get_univ_funcs[type]))(ptr, len, val); -} - -unsigned -der_get_type (unsigned char *ptr, Der_class *class, Der_type *type, - unsigned *tag, unsigned *len) -{ - unsigned char *p = ptr; - - return p - ptr; -} - -int -der_match_type (unsigned char **ptr, Der_class class, Der_type type, - unsigned tag, unsigned *len) -{ - unsigned char *p = ptr; - Der_class c1; - Der_type t1; - unsigned tag1; - - p += der_get_tag (p, &c1, &t1, &tag1); - if (c1 != class || t1 != type || tag != tag1) - return -1; - p += der_get_length (p, len); - - return p - ptr; -} - -int -der_get_context (unsigned char *ptr, unsigned *tag, unsigned *type, - unsigned *len) -{ - unsigned char *p = ptr; - Der_class class; - Der_type foo; - - p += der_get_tag (p, &class, &foo, tag); - if (class != CONTEXT || foo != CONS ) - return -1; - p += der_get_length (p, len); - p += der_get_tag (p, &class, &foo, type); - if (class != UNIV || foo != PRIM) - return -1; - p += der_get_length (p, len); - - return p - ptr; -} - -int -der_match_context (unsigned char *ptr, unsigned tag, int type, void *arg) -{ - unsigned char *p = ptr; - int len; - int tlen; - - len = der_match_type (p, CONTEXT, CONS, tag, &tlen); - if (len < 0) - return len; - else - p += len; - len = der_match_type (p, UNIV, PRIM, type, &tlen); - if (len < 0) - return len; - else - p += len; - - p += der_get_val (p, type, tlen, arg); - - return p - ptr; -} diff --git a/der_put.c b/der_put.c new file mode 100644 index 000000000..d4eca41e1 --- /dev/null +++ b/der_put.c @@ -0,0 +1,150 @@ +#include +#include + +/* + * Functions for generating DER + */ + +/* + * All these functions generate the data backwards starting at `ptr' + * and return the length. + */ + +unsigned +der_put_integer (unsigned char *ptr, void *v) +{ + unsigned char *p = ptr; + unsigned i = *(int *)v; + + if (i) { + while(i) { + *p-- = i % 0x100; + i /= 0x100; + } + return ptr - p; + } else { + *p = 0; + return 1; + } +} + +unsigned +der_put_length (unsigned char *ptr, unsigned len) +{ + unsigned char *p = ptr; + + if (len < 0x80) { + *p = len; + return 1; + } else { + unsigned q; + + q = der_put_integer (p, &len); + p -= q; + *p = 0x80 | q; + return q + 1; + } +} + +unsigned +der_put_octetstring (unsigned char *ptr, void *v) +{ + unsigned char *p = ptr; + krb5_data *str = (krb5_data *)v; + int len = str->length; + + p -= len; + memcpy (p + 1, str->data, len); + + return ptr - p; +} + +unsigned +der_put_tag (unsigned char *ptr, Der_class class, Der_type type, unsigned tag) +{ + unsigned char o1; + unsigned char *p = ptr; + + o1 = (class << 6) | (type << 5); + if (tag < 0x1F) + o1 |= tag; + else { + o1 |= 0x1F; + *p-- = tag % 0x80; + tag /= 0x80; + while(tag) { + *p-- = 0x80 | (tag % 0x80); + tag /= 0x80; + } + } + *p-- = o1; + return ptr - p; +} + +unsigned +der_put_type (unsigned char *ptr, Der_class class, Der_type type, + unsigned tag, unsigned len) +{ + unsigned char *p = ptr; + + p -= der_put_length (p, len); + p -= der_put_tag (p, class, type, tag); + return ptr - p; +} + +static unsigned (*put_univ_funcs[])(unsigned char *, void *val) = { + NULL, /* 0 */ + NULL, /* 1 */ + der_put_integer, /* 2 */ + NULL, /* 3 */ + der_put_octetstring, /* 4 */ + NULL, /* 5 */ + NULL, /* 6 */ + NULL, /* 7 */ + NULL, /* 8 */ + NULL, /* 9 */ + NULL, /* 10 */ + NULL, /* 11 */ + NULL, /* 12 */ + NULL, /* 13 */ + NULL, /* 14 */ + NULL, /* 15 */ + NULL, /* 16 */ + NULL, /* 17 */ + NULL, /* 18 */ + NULL, /* 19 */ + NULL, /* 20 */ + NULL, /* 21 */ + NULL, /* 22 */ + NULL, /* 23 */ + der_put_octetstring, /* 24 */ + NULL, /* 25 */ + NULL, /* 26 */ + der_put_octetstring, /* 27 */ +}; + +unsigned +der_put_val (unsigned char *ptr, int type, void *val) +{ + return (*(put_univ_funcs[type]))(ptr, val); +} + +unsigned +der_put_type_and_value (unsigned char *ptr, int type, void *val) +{ + unsigned char *p = ptr; + + p -= der_put_val (p, type, val); + p -= der_put_type (p, UNIV, PRIM, type, ptr - p); + return ptr - p; +} + +unsigned +der_put_context (unsigned char *ptr, int tag, int type, void *val) +{ + unsigned char *p = ptr; + + p -= der_put_type_and_value (p, type, val); + p -= der_put_type (p, CONTEXT, CONS, tag, ptr - p); + return ptr - p; +} diff --git a/e.c b/e.c index 57a3829c8..faedaea68 100644 --- a/e.c +++ b/e.c @@ -1,37 +1,38 @@ -#include -#include -#include +#include #include #include int -der_get_principalname (Buffer *b, PrincipalName *p) +der_get_principalname (Buffer *b, krb5_principal *p) { Identifier i; int cur, max; char *str; int len; - p->num_strings = 0; + *p = malloc(sizeof(**p)); + if (*p == NULL) + return -1; + (*p)->ncomp = 0; if (matchid3 (b, &i, UNIV, CONS, UT_Sequence) == NULL) return -1; if (matchcontextid3 (b, &i, UNIV, PRIM, UT_Integer, 0) == NULL) return -1; - getdata (b, &i, &p->name_type); + getdata (b, &i, &(*p)->type); if (matchcontextid3 (b, &i, UNIV, CONS, UT_Sequence, 1) == NULL) return -1; cur = 0; max = 1; - p->names = malloc(sizeof(char *) * max); + (*p)->comp = malloc(sizeof(*(*p)->comp) * max); while (matchid3 (b, &i, UNIV, PRIM, UT_GeneralString)) { if (cur >= max) { max *= 2; - p->names = realloc (p->names, sizeof(char *) * max); + (*p)->comp = realloc ((*p)->comp, sizeof(*(*p)->comp) * max); } - getdata (b, &i, &p->names[cur++]); + getdata (b, &i, &(*p)->comp[cur++]); } - p->num_strings = cur; + (*p)->ncomp = cur; return buf_length (b); } @@ -106,7 +107,7 @@ der_get_ticket (Buffer *b, Ticket *t) } int -der_get_kdc_rep (Buffer *b, int msg, Kdc_Rep *k) +der_get_kdc_rep (Buffer *b, int msg, krb5_kdc_rep *k) { Identifier i, i0; Buffer tmp; @@ -160,7 +161,7 @@ der_get_kdc_rep (Buffer *b, int msg, Kdc_Rep *k) } static int -der_get_kdc_rep_msg (Buffer *b, int msg, Kdc_Rep *a) +der_get_kdc_rep_msg (Buffer *b, int msg, krb5_kdc_rep *a) { Identifier i; @@ -198,7 +199,7 @@ der_get_encryptionkey (Buffer *b, EncryptionKey *k) } int -der_get_hostaddresses (Buffer *b, HostAddresses *h) +der_get_hostaddresses (Buffer *b, krb5_addresses *h) { Identifier i; int cur, max; @@ -215,10 +216,10 @@ der_get_hostaddresses (Buffer *b, HostAddresses *h) } if (matchcontextid3 (b, &i, UNIV, PRIM, UT_Integer, 0) == NULL) return -1; - getdata (b, &i, &h->addrs[cur].addr_type); + getdata (b, &i, &h->addrs[cur].type); if (matchcontextid3 (b, &i, UNIV, PRIM, UT_OctetString, 1) == NULL) return -1; - getdata (b, &i, &h->addrs[cur].addr); + getdata (b, &i, &h->addrs[cur].address); ++cur; } h->number = cur; diff --git a/get_addrs.c b/get_addrs.c new file mode 100644 index 000000000..c94dabdd6 --- /dev/null +++ b/get_addrs.c @@ -0,0 +1,45 @@ +#include "krb5_locl.h" + +static krb5_error_code +get_addrs () +{ + /* here the code from krb4/lib/krb/getaddrs.c will go */ +} + +/* + * Try to get all addresses, but return the one corresponding to + * `hostname' if we fail. + */ + +krb5_error_code +krb5_get_all_client_addrs (krb5_addresses *res) +{ + krb5_error_code err; + char hostname[MAXHOSTNAMELEN]; + struct hostent *hostent; + + if (gethostname (hostname, sizeof(hostname))) + return errno; + hostent = gethostbyname (hostname); + if (hostent == NULL) + return errno; + res->number = 1; + res->addrs = malloc (sizeof(*res->addrs)); + res->addrs[0].type = hostent->h_addrtype; + err = krb5_data_alloc (&res->addrs[0].address, hostent->h_length); + if (err) + return err; + memcpy (res->addrs[0].address.data, + hostent->h_addr, + hostent->h_length); + return 0; +} + +/* + * Same as above, but with the fall-back to INADDR_ANY. + */ + +krb5_error_code +krb5_get_all_server_addrs () +{ +} diff --git a/get_in_tkt.c b/get_in_tkt.c index 3d5bf1c54..716012e2e 100644 --- a/get_in_tkt.c +++ b/get_in_tkt.c @@ -1,4 +1,7 @@ #include "krb5_locl.h" +#include +#include +#include static krb5_error_code krb5_get_salt (krb5_principal princ, @@ -10,22 +13,52 @@ krb5_get_salt (krb5_principal princ, krb5_error_code err; char *p; - len = realm->len; + len = realm.length; for (i = 0; i < princ->ncomp; ++i) len += princ->comp[i].length; - err = krb5_alloc (salt, len); + err = krb5_data_alloc (salt, len); if (err) return err; p = salt->data; - strncpy (p, realm->data, realm->len); - p += realm->len; - for (i = 0; i < princ->cnomp; ++i) { + strncpy (p, realm.data, realm.length); + p += realm.length; + for (i = 0; i < princ->ncomp; ++i) { strncpy (p, princ->comp[i].data, princ->comp[i].length); p += princ->comp[i].length; } return 0; } +static krb5_error_code +decrypt_tkt (krb5_context context, + const krb5_keyblock *key, + krb5_const_pointer decrypt_arg, + krb5_kdc_rep *dec_rep) +{ + des_key_schedule sched; + char *buf; + Buffer buffer; + + des_set_key (key->contents.data, sched); + buf = malloc (dec_rep->enc_part.cipher.length); + if (buf == NULL) + return ENOMEM; + des_cbc_encrypt ((des_cblock *)dec_rep->enc_part.cipher.data, + (des_cblock *)buf, + dec_rep->enc_part.cipher.length, + sched, + key->contents.data, + DES_DECRYPT); + /* XXX: Check CRC */ + buf_init (&buffer, buf + 12, dec_rep->enc_part.cipher.length - 12); + if (der_get_enctgsreppart (&buffer, &dec_rep->enc_part2) == -1) { + free (buf); + return ASN1_PARSE_ERROR; + } + free (buf); + return 0; +} + /* * */ @@ -44,65 +77,82 @@ krb5_get_in_tkt(krb5_context context, krb5_ccache ccache, krb5_kdc_rep **ret_as_reply) { + krb5_error_code err; As_Req a; - Kdc_Rep rep; - krb5_principal server; + krb5_kdc_rep rep; + krb5_principal_data server; krb5_data req, resp; char buf[BUFSIZ]; - Buffer buf; + Buffer buffer; krb5_data salt; krb5_keyblock *key; - server.type = KRB_NT_SRV_INST; + server.type = KRB5_NT_SRV_INST; server.ncomp = 2; server.comp = malloc (sizeof(*server.comp) * server.ncomp); server.comp[0] = string_make ("krbtgt"); - server.comp[1] = creds->client.realm; + server.comp[1] = creds->client->realm; a.pvno = 5; a.msg_type = KRB_AS_REQ; /* a.kdc_options */ - a.cname = &creds->client; + a.cname = creds->client; a.sname = &server; - a.realm = creds->client.realm; + a.realm = creds->client->realm; a.till = creds->times.endtime; a.nonce = 17; if (etypes) a.etypes = etypes; - else - a.etypes = context->etypes; - if (addrs) - a.addresses = addrs; - else - a.addresses = krb5_get_all_client_addrs (); + else { + err = krb5_get_default_in_tkt_etypes (context, &a.etypes); + if (err) + return err; + a.num_etypes = 1; + } + if (addrs){ + } else { + err = krb5_get_all_client_addrs (&a.addrs); + if (err) + return err; + } - req.data = buf; - - req.len = der_put_as_req (req.data + sizeof(buf) - 1, &a); - string_free (server.comp[0]); + req.length = der_put_as_req (buf + sizeof(buf) - 1, &a); + req.data = buf + sizeof(buf) - req.length; free (server.comp); - if (addrs == NULL) - free (a.addresses); + if (addrs == NULL) { + int i; - err = krb5_sendto_kdc (context, &req, a.realm, &resp); + for (i = 0; i < a.addrs.number; ++i) + krb5_data_free (&a.addrs.addrs[i].address); + free (a.addrs.addrs); + } + + err = krb5_sendto_kdc (context, &req, &a.realm, &resp); if (err) { return err; } - buf_init (&buffer, resp.data, resp.len); + buf_init (&buffer, resp.data, resp.length); if (der_get_as_rep (&buffer, &rep) == -1) { return ASN1_PARSE_ERROR; } - err = krb5_get_salt (creds->client, creds->client.realm, &salt); + salt.length = 0; + salt.data = NULL; + err = krb5_get_salt (creds->client, creds->client->realm, &salt); if (err) return err; - err = (*key_proc)(context, b.enc_part.etype, salt, keyseed, &key); + err = (*key_proc)(context, rep.enc_part.etype, &salt, keyseed, &key); krb5_data_free (&salt); if (err) return err; + if (decrypt_proc == NULL) + decrypt_proc = decrypt_tkt; + err = (*decrypt_proc)(context, key, decryptarg, &rep); - memset (&key.contents.data, 0, key.contents.length); - krb5_data_free (&key.contents); + memset (key->contents.data, 0, key->contents.length); + krb5_data_free (&key->contents); + free (key); if (err) return err; + return 0; } diff --git a/get_in_tkt_pw.c b/get_in_tkt_pw.c index dfe52d004..908583543 100644 --- a/get_in_tkt_pw.c +++ b/get_in_tkt_pw.c @@ -11,15 +11,17 @@ key_proc (krb5_context context, char *password = (char *)keyseed; char buf[BUFSIZ]; - key = malloc (sizeof (*key)); - if (key == NULL) + *key = malloc (sizeof (**key)); + if (*key == NULL) return ENOMEM; - key->keytype = type; + (*key)->keytype = type; + (*key)->contents.length = 0; + (*key)->contents.data = NULL; if (password == NULL) { des_read_pw_string (buf, sizeof(buf), "Password: ", 0); password = buf; } - err = krb5_string_to_key (password, salt, key); + err = krb5_string_to_key (password, salt, *key); memset (buf, 0, sizeof(buf)); return err; } @@ -33,9 +35,9 @@ krb5_get_in_tkt_with_password (krb5_context context, const char *password, krb5_ccache ccache, krb5_creds *creds, - krb5_kdc-rep **ret_as_reply) + krb5_kdc_rep **ret_as_reply) { return krb5_get_in_tkt (context, options, addrs, etypes, pre_auth_types, key_proc, password, - NULL, NULL, creds, cache, ret_as_reply); + NULL, NULL, creds, ccache, ret_as_reply); } diff --git a/k5_der.c b/k5_der.c index 35e9489ca..60874d3a0 100644 --- a/k5_der.c +++ b/k5_der.c @@ -1,8 +1,4 @@ -#include -#include -#include -#include -#include +#include #include static void @@ -11,7 +7,7 @@ time2generalizedtime (krb5_data *s, time_t t) struct tm *tm; s->data = malloc(16); - s->len = 15; + s->length = 15; tm = gmtime (&t); sprintf (s->data, "%04d%02d%02d%02d%02d%02dZ", tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, @@ -20,7 +16,7 @@ time2generalizedtime (krb5_data *s, time_t t) unsigned der_put_context_etypes (unsigned char *ptr, int tag, - EncryptionType *etypes, unsigned num_etypes) + krb5_enctype *etypes, unsigned num_etypes) { unsigned char *p = ptr; int i; @@ -34,19 +30,19 @@ der_put_context_etypes (unsigned char *ptr, int tag, unsigned der_put_context_principalname (unsigned char *ptr, int tag, - PrincipalName *name) + krb5_principal name) { unsigned char *p = ptr; int i; if (name == NULL) return 0; - for (i = name->num_strings - 1; i >= 0; --i) + for (i = name->ncomp - 1; i >= 0; --i) p -= der_put_type_and_value (p, UT_GeneralString, - &name->names[i]); + &name->comp[i]); p -= der_put_type (p, UNIV, CONS, UT_Sequence, ptr - p); p -= der_put_type (p, CONTEXT, CONS, 1, ptr - p); - p -= der_put_context (p, 0, UT_Integer, &name->name_type); + p -= der_put_context (p, 0, UT_Integer, &name->type); p -= der_put_type (p, UNIV, CONS, UT_Sequence, ptr - p); p -= der_put_type (p, CONTEXT, CONS, tag, ptr - p); return ptr - p; @@ -71,15 +67,16 @@ der_put_context_kdcoptions (unsigned char *ptr, int tag, KdcOptions *k) unsigned der_put_context_hostaddresses (unsigned char *ptr, int tag, - HostAddress *addrs, - unsigned naddr) + krb5_addresses addrs) { unsigned char *p = ptr; int i; - for(i = naddr - 1; i >= 0; --i) { - p -= der_put_context (p, 1, UT_OctetString, &addrs[i].addr); - p -= der_put_context (p, 0, UT_Integer, &addrs[i].addr_type); + for(i = addrs.number - 1; i >= 0; --i) { + p -= der_put_context (p, 1, UT_OctetString, + &addrs.addrs[i].address); + p -= der_put_context (p, 0, UT_Integer, + &addrs.addrs[i].type); } p -= der_put_type (p, UNIV, CONS, UT_Sequence, ptr - p); p -= der_put_type (p, UNIV, CONS, UT_Sequence, ptr - p); @@ -91,15 +88,13 @@ unsigned der_put_kdc_req_body (unsigned char *ptr, Kdc_Req *k) { unsigned char *p = ptr; - unsigned random = 17; /* additional-tickets[11] SEQUENCE OF Ticket OPTIONAL */ /* enc-authorization-data[10] EncryptedData OPTIONAL */ - p -= der_put_context_hostaddresses (p, 9, k->addrs, - k->num_addrs); + p -= der_put_context_hostaddresses (p, 9, k->addrs); /* addresses[9] HostAddresses OPTIONAL */ p -= der_put_context_etypes (p, 8, k->etypes, k->num_etypes); - p -= der_put_context (p, 7, UT_Integer, &random); + p -= der_put_context (p, 7, UT_Integer, &k->nonce); /* rtime[6] KerberosTime OPTIONAL */ { krb5_data t; @@ -180,7 +175,7 @@ der_get_principalname (unsigned char *ptr, Principalname *name) int der_get_kdc_rep (unsigned char *ptr, unsigned mylen, int msg_type, - Kdc_Rep *k) + krb5_kdc_rep *k) { unsigned char *p = ptr; unsigned tlen, slen; diff --git a/k5_der.h b/k5_der.h index 67e8c32cc..ab8991abb 100644 --- a/k5_der.h +++ b/k5_der.h @@ -28,37 +28,6 @@ enum { APPL_TICKET = 1 }; -struct HostAddress { - int addr_type; - krb5_data addr; -}; - -typedef struct HostAddress HostAddress; - -struct HostAddresses { - int number; - HostAddress *addrs; -}; - -typedef struct HostAddresses HostAddresses; - -struct PrincipalName { - int name_type; - unsigned num_strings; - krb5_data *names; -}; - -enum { - nt_unknown = 0, - nt_principal = 1, - nt_srv_inst = 2, - nt_srv_hst = 3, - nt_srv_xhst = 4, - nt_uid = 5 -}; - -typedef struct PrincipalName PrincipalName; - struct KdcOptions { unsigned reserved : 1, @@ -81,22 +50,20 @@ struct KdcOptions { typedef struct KdcOptions KdcOptions; -typedef krb5_data Realm; - typedef int EncryptionType; struct Kdc_Req { int pvno; int msg_type; KdcOptions kdc_options; - PrincipalName *cname; - Realm realm; - PrincipalName *sname; - time_t till; + krb5_principal cname; + krb5_realm realm; + krb5_principal sname; + krb5_time till; + int nonce; unsigned num_etypes; - EncryptionType *etypes; - HostAddress *addrs; - unsigned num_addrs; + krb5_enctype *etypes; + krb5_addresses addrs; }; typedef struct Kdc_Req Kdc_Req; @@ -113,28 +80,13 @@ typedef struct EncryptedData EncryptedData; struct Ticket { int tkt_vno; - Realm realm; - PrincipalName sname; + krb5_realm realm; + krb5_principal sname; EncryptedData enc_part; }; typedef struct Ticket Ticket; -struct Kdc_Rep { - int pvno; - int msg_type; - Realm realm; - PrincipalName cname; - Ticket ticket; - EncryptedData enc_part; -}; - -typedef struct Kdc_Rep Kdc_Rep; - -typedef Kdc_Rep As_Rep; - -typedef Kdc_Rep Tgs_Rep; - struct EncryptionKey { int keytype; krb5_data keyvalue; @@ -146,7 +98,7 @@ struct LastReq { int number; struct { int lr_type; - time_t lr_value; + krb5_time lr_value; } *values; }; @@ -172,18 +124,33 @@ struct EncKdcRepPart { EncryptionKey key; LastReq req; int nonce; - time_t *key_expiration; + krb5_time *key_expiration; TicketFlags flags; - time_t authtime; - time_t *starttime; - time_t endtime; - time_t *renew_till; - Realm srealm; - PrincipalName sname; - HostAddresses caddr; + krb5_time authtime; + krb5_time *starttime; + krb5_time endtime; + krb5_time *renew_till; + krb5_realm srealm; + krb5_principal sname; + krb5_addresses caddr; }; typedef struct EncKdcRepPart EncKdcRepPart; typedef EncKdcRepPart EncASRepPart; typedef EncKdcRepPart EncTGSRepPart; + +struct krb5_kdc_rep { + int pvno; + int msg_type; + krb5_realm realm; + krb5_principal cname; + Ticket ticket; + EncryptedData enc_part; + EncASRepPart enc_part2; +}; + +typedef krb5_kdc_rep As_Rep; + +typedef krb5_kdc_rep Tgs_Rep; + diff --git a/kinit.c b/kinit.c new file mode 100644 index 000000000..c0bbb5374 --- /dev/null +++ b/kinit.c @@ -0,0 +1,44 @@ +#include +#include + +int +main (int argc, char **argv) +{ + krb5_error_code err; + krb5_context context; + krb5_ccache ccache; + krb5_principal principal; + krb5_creds cred; + + err = krb5_init_context (&context); + if (err) + abort (); + + err = krb5_cc_default (context, &ccache); + if (err) + abort (); + + err = krb5_parse_name (context, argv[1], &principal); + if (err) + abort (); + + err = krb5_cc_initialize (context, ccache, principal); + if (err) + abort (); + + cred.client = principal; + cred.times.endtime = time (NULL) + 4711; + + err = krb5_get_in_tkt_with_password (context, + 0, + NULL, + NULL, + NULL, + NULL, + ccache, + &cred, + NULL); + if (err) + abort (); + return 0; +} diff --git a/krb5.h b/krb5.h index 219a472c4..4fdf082aa 100644 --- a/krb5.h +++ b/krb5.h @@ -8,6 +8,13 @@ #include "config_file.h" +/* simple constants */ + +#ifndef TRUE +#define TRUE 1 +#define FALSE 0 +#endif + /* types */ typedef int32_t krb5_int32; typedef int16_t krb5_int16; @@ -40,7 +47,7 @@ typedef enum krb5_cksumtype { CKSUMTYPE_DES_MAC = 4, CKSUMTYPE_DES_MAC_K = 5, CKSUMTYPE_RSA_MD4_DES_K = 6, - CKSUMTYPE_RSA_MD5_DES = 7, + CKSUMTYPE_RSA_MD5_DES = 7 } krb5_cksumtype; @@ -63,7 +70,7 @@ typedef enum krb5_preauthtype { typedef enum krb5_address_type { - KRB5_ADDRESS_INET = 2, + KRB5_ADDRESS_INET = 2 } krb5_address_type; typedef struct krb5_address{ @@ -71,7 +78,10 @@ typedef struct krb5_address{ krb5_data address; } krb5_address; - +typedef struct krb5_addresses { + int number; + krb5_address *addrs; +} krb5_addresses; typedef enum krb5_keytype { KEYTYPE_DES } krb5_keytype; @@ -80,7 +90,6 @@ typedef struct krb5_keyblock{ krb5_data contents; } krb5_keyblock; - typedef struct krb5_context_data{ krb5_enctype *etypes; char *default_realm; @@ -107,6 +116,7 @@ enum{ KRB5_NT_SRV_XHST = 4, KRB5_NT_UID = 5 }; + typedef struct krb5_principal_data{ int type; krb5_data realm; @@ -117,6 +127,7 @@ typedef struct krb5_principal_data{ typedef krb5_principal_data *krb5_principal; typedef const krb5_principal_data *krb5_const_principal; +typedef krb5_data krb5_realm; typedef struct krb5_ticket{ int kvno; @@ -198,10 +209,7 @@ typedef struct krb5_auth_context{ typedef krb5_uint32 krb5_flags; -typedef struct krb5_kdc_rep{ - int dummy; -}krb5_kdc_rep; - +typedef struct krb5_kdc_rep krb5_kdc_rep; krb5_error_code krb5_init_context(krb5_context *context); @@ -223,13 +231,13 @@ krb5_get_credentials(krb5_context context, krb5_creds *out_creds); typedef krb5_error_code (*krb5_key_proc)(krb5_context context, - const krb5_keytype type, + krb5_keytype type, krb5_data *salt, krb5_const_pointer keyseed, krb5_keyblock **key); typedef krb5_error_code (*krb5_decrypt_proc)(krb5_context context, const krb5_keyblock *key, - krb5_const_pointer *decrypt_arg, + krb5_const_pointer decrypt_arg, krb5_kdc_rep *dec_rep); krb5_error_code @@ -246,6 +254,16 @@ krb5_get_in_tkt(krb5_context context, krb5_ccache ccache, krb5_kdc_rep **ret_as_reply); +krb5_error_code +krb5_get_in_tkt_with_password (krb5_context context, + krb5_flags options, + krb5_address *const *addrs, + const krb5_enctype *etypes, + const krb5_preauthtype *pre_auth_types, + const char *password, + krb5_ccache ccache, + krb5_creds *creds, + krb5_kdc_rep **ret_as_reply); krb5_error_code krb5_mk_req(krb5_context context, @@ -354,5 +372,11 @@ krb5_free_krbhst (krb5_context context, char *const *hostlist); +/* variables */ + +extern const char krb5_config_file[]; +extern const char krb5_defkeyname[]; + + #endif /* __KRB5_H__ */ diff --git a/krb5_error.h b/krb5_error.h index 20316f8c2..a013f0615 100644 --- a/krb5_error.h +++ b/krb5_error.h @@ -49,4 +49,10 @@ #define KRB_ERR_GENERIC 60 #define KRB_ERR_FIELD_TOOLONG 61 +#define KRB5_KDC_UNREACH 155 + +/* Just some random number */ + +#define ASN1_PARSE_ERROR 274 + #endif /* __KRB5_ERROR_H__ */ diff --git a/krb5_locl.h b/krb5_locl.h index 55ad6120f..df09c62a8 100644 --- a/krb5_locl.h +++ b/krb5_locl.h @@ -7,7 +7,16 @@ #include #include +#include #include +#include +#include +#include +#include +#include +#include +#include +#include #include diff --git a/krbhst.c b/krbhst.c index c05714d56..2367afd9f 100644 --- a/krbhst.c +++ b/krbhst.c @@ -9,11 +9,11 @@ krb5_get_krbhst (krb5_context context, char buf[BUFSIZ]; char *val; - sprintf (buf, "realms %s kdc", realm.data); - err = krb5_get_config_tag (context.cf, buf, &val); + sprintf (buf, "realms %.*s kdc", realm->length, realm->data); + err = krb5_get_config_tag (context->cf, buf, &val); if (err) return err; - **hostlist = malloc (2 * sizeof (char *)); + *hostlist = malloc (2 * sizeof (char *)); (*hostlist)[0] = val; (*hostlist)[1] = NULL; return 0; diff --git a/kuser/kinit.c b/kuser/kinit.c new file mode 100644 index 000000000..c0bbb5374 --- /dev/null +++ b/kuser/kinit.c @@ -0,0 +1,44 @@ +#include +#include + +int +main (int argc, char **argv) +{ + krb5_error_code err; + krb5_context context; + krb5_ccache ccache; + krb5_principal principal; + krb5_creds cred; + + err = krb5_init_context (&context); + if (err) + abort (); + + err = krb5_cc_default (context, &ccache); + if (err) + abort (); + + err = krb5_parse_name (context, argv[1], &principal); + if (err) + abort (); + + err = krb5_cc_initialize (context, ccache, principal); + if (err) + abort (); + + cred.client = principal; + cred.times.endtime = time (NULL) + 4711; + + err = krb5_get_in_tkt_with_password (context, + 0, + NULL, + NULL, + NULL, + NULL, + ccache, + &cred, + NULL); + if (err) + abort (); + return 0; +} diff --git a/lib/krb5/cache.c b/lib/krb5/cache.c index 56d7a1899..05f945316 100644 --- a/lib/krb5/cache.c +++ b/lib/krb5/cache.c @@ -46,6 +46,10 @@ krb5_error_code krb5_cc_default(krb5_context context, krb5_ccache *id) { + *id = malloc(sizeof(**id)); + if (*id == NULL) + return ENOMEM; + return krb5_cc_resolve (context, id, "/tmp/foo"); } static krb5_error_code @@ -112,7 +116,7 @@ krb5_cc_initialize(krb5_context context, if(ret = erase_file(f->filename)) return ret; - fd = open(f->filename, O_RDWR, 0600); + fd = open(f->filename, O_RDWR | O_CREAT | O_EXCL, 0600); if(fd == -1) return errno; store_int16(fd, 0x503); diff --git a/lib/krb5/config_file.y b/lib/krb5/config_file.y index 1936c519f..82fd938bb 100644 --- a/lib/krb5/config_file.y +++ b/lib/krb5/config_file.y @@ -19,6 +19,9 @@ static krb5_config_relation **crel; static krb5_config_relation **rels[16]; static int relp; +static void yyerror (char *); +static int yylex (void); + %} %union { @@ -143,7 +146,7 @@ static int yylex(void) return type; } -static void yyerror(char *s) +void yyerror(char *s) { printf("yyerror: %s\n", s); } diff --git a/lib/krb5/get_addrs.c b/lib/krb5/get_addrs.c new file mode 100644 index 000000000..c94dabdd6 --- /dev/null +++ b/lib/krb5/get_addrs.c @@ -0,0 +1,45 @@ +#include "krb5_locl.h" + +static krb5_error_code +get_addrs () +{ + /* here the code from krb4/lib/krb/getaddrs.c will go */ +} + +/* + * Try to get all addresses, but return the one corresponding to + * `hostname' if we fail. + */ + +krb5_error_code +krb5_get_all_client_addrs (krb5_addresses *res) +{ + krb5_error_code err; + char hostname[MAXHOSTNAMELEN]; + struct hostent *hostent; + + if (gethostname (hostname, sizeof(hostname))) + return errno; + hostent = gethostbyname (hostname); + if (hostent == NULL) + return errno; + res->number = 1; + res->addrs = malloc (sizeof(*res->addrs)); + res->addrs[0].type = hostent->h_addrtype; + err = krb5_data_alloc (&res->addrs[0].address, hostent->h_length); + if (err) + return err; + memcpy (res->addrs[0].address.data, + hostent->h_addr, + hostent->h_length); + return 0; +} + +/* + * Same as above, but with the fall-back to INADDR_ANY. + */ + +krb5_error_code +krb5_get_all_server_addrs () +{ +} diff --git a/lib/krb5/get_in_tkt.c b/lib/krb5/get_in_tkt.c index 3d5bf1c54..716012e2e 100644 --- a/lib/krb5/get_in_tkt.c +++ b/lib/krb5/get_in_tkt.c @@ -1,4 +1,7 @@ #include "krb5_locl.h" +#include +#include +#include static krb5_error_code krb5_get_salt (krb5_principal princ, @@ -10,22 +13,52 @@ krb5_get_salt (krb5_principal princ, krb5_error_code err; char *p; - len = realm->len; + len = realm.length; for (i = 0; i < princ->ncomp; ++i) len += princ->comp[i].length; - err = krb5_alloc (salt, len); + err = krb5_data_alloc (salt, len); if (err) return err; p = salt->data; - strncpy (p, realm->data, realm->len); - p += realm->len; - for (i = 0; i < princ->cnomp; ++i) { + strncpy (p, realm.data, realm.length); + p += realm.length; + for (i = 0; i < princ->ncomp; ++i) { strncpy (p, princ->comp[i].data, princ->comp[i].length); p += princ->comp[i].length; } return 0; } +static krb5_error_code +decrypt_tkt (krb5_context context, + const krb5_keyblock *key, + krb5_const_pointer decrypt_arg, + krb5_kdc_rep *dec_rep) +{ + des_key_schedule sched; + char *buf; + Buffer buffer; + + des_set_key (key->contents.data, sched); + buf = malloc (dec_rep->enc_part.cipher.length); + if (buf == NULL) + return ENOMEM; + des_cbc_encrypt ((des_cblock *)dec_rep->enc_part.cipher.data, + (des_cblock *)buf, + dec_rep->enc_part.cipher.length, + sched, + key->contents.data, + DES_DECRYPT); + /* XXX: Check CRC */ + buf_init (&buffer, buf + 12, dec_rep->enc_part.cipher.length - 12); + if (der_get_enctgsreppart (&buffer, &dec_rep->enc_part2) == -1) { + free (buf); + return ASN1_PARSE_ERROR; + } + free (buf); + return 0; +} + /* * */ @@ -44,65 +77,82 @@ krb5_get_in_tkt(krb5_context context, krb5_ccache ccache, krb5_kdc_rep **ret_as_reply) { + krb5_error_code err; As_Req a; - Kdc_Rep rep; - krb5_principal server; + krb5_kdc_rep rep; + krb5_principal_data server; krb5_data req, resp; char buf[BUFSIZ]; - Buffer buf; + Buffer buffer; krb5_data salt; krb5_keyblock *key; - server.type = KRB_NT_SRV_INST; + server.type = KRB5_NT_SRV_INST; server.ncomp = 2; server.comp = malloc (sizeof(*server.comp) * server.ncomp); server.comp[0] = string_make ("krbtgt"); - server.comp[1] = creds->client.realm; + server.comp[1] = creds->client->realm; a.pvno = 5; a.msg_type = KRB_AS_REQ; /* a.kdc_options */ - a.cname = &creds->client; + a.cname = creds->client; a.sname = &server; - a.realm = creds->client.realm; + a.realm = creds->client->realm; a.till = creds->times.endtime; a.nonce = 17; if (etypes) a.etypes = etypes; - else - a.etypes = context->etypes; - if (addrs) - a.addresses = addrs; - else - a.addresses = krb5_get_all_client_addrs (); + else { + err = krb5_get_default_in_tkt_etypes (context, &a.etypes); + if (err) + return err; + a.num_etypes = 1; + } + if (addrs){ + } else { + err = krb5_get_all_client_addrs (&a.addrs); + if (err) + return err; + } - req.data = buf; - - req.len = der_put_as_req (req.data + sizeof(buf) - 1, &a); - string_free (server.comp[0]); + req.length = der_put_as_req (buf + sizeof(buf) - 1, &a); + req.data = buf + sizeof(buf) - req.length; free (server.comp); - if (addrs == NULL) - free (a.addresses); + if (addrs == NULL) { + int i; - err = krb5_sendto_kdc (context, &req, a.realm, &resp); + for (i = 0; i < a.addrs.number; ++i) + krb5_data_free (&a.addrs.addrs[i].address); + free (a.addrs.addrs); + } + + err = krb5_sendto_kdc (context, &req, &a.realm, &resp); if (err) { return err; } - buf_init (&buffer, resp.data, resp.len); + buf_init (&buffer, resp.data, resp.length); if (der_get_as_rep (&buffer, &rep) == -1) { return ASN1_PARSE_ERROR; } - err = krb5_get_salt (creds->client, creds->client.realm, &salt); + salt.length = 0; + salt.data = NULL; + err = krb5_get_salt (creds->client, creds->client->realm, &salt); if (err) return err; - err = (*key_proc)(context, b.enc_part.etype, salt, keyseed, &key); + err = (*key_proc)(context, rep.enc_part.etype, &salt, keyseed, &key); krb5_data_free (&salt); if (err) return err; + if (decrypt_proc == NULL) + decrypt_proc = decrypt_tkt; + err = (*decrypt_proc)(context, key, decryptarg, &rep); - memset (&key.contents.data, 0, key.contents.length); - krb5_data_free (&key.contents); + memset (key->contents.data, 0, key->contents.length); + krb5_data_free (&key->contents); + free (key); if (err) return err; + return 0; } diff --git a/lib/krb5/get_in_tkt_pw.c b/lib/krb5/get_in_tkt_pw.c index dfe52d004..908583543 100644 --- a/lib/krb5/get_in_tkt_pw.c +++ b/lib/krb5/get_in_tkt_pw.c @@ -11,15 +11,17 @@ key_proc (krb5_context context, char *password = (char *)keyseed; char buf[BUFSIZ]; - key = malloc (sizeof (*key)); - if (key == NULL) + *key = malloc (sizeof (**key)); + if (*key == NULL) return ENOMEM; - key->keytype = type; + (*key)->keytype = type; + (*key)->contents.length = 0; + (*key)->contents.data = NULL; if (password == NULL) { des_read_pw_string (buf, sizeof(buf), "Password: ", 0); password = buf; } - err = krb5_string_to_key (password, salt, key); + err = krb5_string_to_key (password, salt, *key); memset (buf, 0, sizeof(buf)); return err; } @@ -33,9 +35,9 @@ krb5_get_in_tkt_with_password (krb5_context context, const char *password, krb5_ccache ccache, krb5_creds *creds, - krb5_kdc-rep **ret_as_reply) + krb5_kdc_rep **ret_as_reply) { return krb5_get_in_tkt (context, options, addrs, etypes, pre_auth_types, key_proc, password, - NULL, NULL, creds, cache, ret_as_reply); + NULL, NULL, creds, ccache, ret_as_reply); } diff --git a/lib/krb5/krb5.h b/lib/krb5/krb5.h index 219a472c4..4fdf082aa 100644 --- a/lib/krb5/krb5.h +++ b/lib/krb5/krb5.h @@ -8,6 +8,13 @@ #include "config_file.h" +/* simple constants */ + +#ifndef TRUE +#define TRUE 1 +#define FALSE 0 +#endif + /* types */ typedef int32_t krb5_int32; typedef int16_t krb5_int16; @@ -40,7 +47,7 @@ typedef enum krb5_cksumtype { CKSUMTYPE_DES_MAC = 4, CKSUMTYPE_DES_MAC_K = 5, CKSUMTYPE_RSA_MD4_DES_K = 6, - CKSUMTYPE_RSA_MD5_DES = 7, + CKSUMTYPE_RSA_MD5_DES = 7 } krb5_cksumtype; @@ -63,7 +70,7 @@ typedef enum krb5_preauthtype { typedef enum krb5_address_type { - KRB5_ADDRESS_INET = 2, + KRB5_ADDRESS_INET = 2 } krb5_address_type; typedef struct krb5_address{ @@ -71,7 +78,10 @@ typedef struct krb5_address{ krb5_data address; } krb5_address; - +typedef struct krb5_addresses { + int number; + krb5_address *addrs; +} krb5_addresses; typedef enum krb5_keytype { KEYTYPE_DES } krb5_keytype; @@ -80,7 +90,6 @@ typedef struct krb5_keyblock{ krb5_data contents; } krb5_keyblock; - typedef struct krb5_context_data{ krb5_enctype *etypes; char *default_realm; @@ -107,6 +116,7 @@ enum{ KRB5_NT_SRV_XHST = 4, KRB5_NT_UID = 5 }; + typedef struct krb5_principal_data{ int type; krb5_data realm; @@ -117,6 +127,7 @@ typedef struct krb5_principal_data{ typedef krb5_principal_data *krb5_principal; typedef const krb5_principal_data *krb5_const_principal; +typedef krb5_data krb5_realm; typedef struct krb5_ticket{ int kvno; @@ -198,10 +209,7 @@ typedef struct krb5_auth_context{ typedef krb5_uint32 krb5_flags; -typedef struct krb5_kdc_rep{ - int dummy; -}krb5_kdc_rep; - +typedef struct krb5_kdc_rep krb5_kdc_rep; krb5_error_code krb5_init_context(krb5_context *context); @@ -223,13 +231,13 @@ krb5_get_credentials(krb5_context context, krb5_creds *out_creds); typedef krb5_error_code (*krb5_key_proc)(krb5_context context, - const krb5_keytype type, + krb5_keytype type, krb5_data *salt, krb5_const_pointer keyseed, krb5_keyblock **key); typedef krb5_error_code (*krb5_decrypt_proc)(krb5_context context, const krb5_keyblock *key, - krb5_const_pointer *decrypt_arg, + krb5_const_pointer decrypt_arg, krb5_kdc_rep *dec_rep); krb5_error_code @@ -246,6 +254,16 @@ krb5_get_in_tkt(krb5_context context, krb5_ccache ccache, krb5_kdc_rep **ret_as_reply); +krb5_error_code +krb5_get_in_tkt_with_password (krb5_context context, + krb5_flags options, + krb5_address *const *addrs, + const krb5_enctype *etypes, + const krb5_preauthtype *pre_auth_types, + const char *password, + krb5_ccache ccache, + krb5_creds *creds, + krb5_kdc_rep **ret_as_reply); krb5_error_code krb5_mk_req(krb5_context context, @@ -354,5 +372,11 @@ krb5_free_krbhst (krb5_context context, char *const *hostlist); +/* variables */ + +extern const char krb5_config_file[]; +extern const char krb5_defkeyname[]; + + #endif /* __KRB5_H__ */ diff --git a/lib/krb5/krb5_error.h b/lib/krb5/krb5_error.h index 20316f8c2..a013f0615 100644 --- a/lib/krb5/krb5_error.h +++ b/lib/krb5/krb5_error.h @@ -49,4 +49,10 @@ #define KRB_ERR_GENERIC 60 #define KRB_ERR_FIELD_TOOLONG 61 +#define KRB5_KDC_UNREACH 155 + +/* Just some random number */ + +#define ASN1_PARSE_ERROR 274 + #endif /* __KRB5_ERROR_H__ */ diff --git a/lib/krb5/krb5_locl.h b/lib/krb5/krb5_locl.h index 55ad6120f..df09c62a8 100644 --- a/lib/krb5/krb5_locl.h +++ b/lib/krb5/krb5_locl.h @@ -7,7 +7,16 @@ #include #include +#include #include +#include +#include +#include +#include +#include +#include +#include +#include #include diff --git a/lib/krb5/krbhst.c b/lib/krb5/krbhst.c index c05714d56..2367afd9f 100644 --- a/lib/krb5/krbhst.c +++ b/lib/krb5/krbhst.c @@ -9,11 +9,11 @@ krb5_get_krbhst (krb5_context context, char buf[BUFSIZ]; char *val; - sprintf (buf, "realms %s kdc", realm.data); - err = krb5_get_config_tag (context.cf, buf, &val); + sprintf (buf, "realms %.*s kdc", realm->length, realm->data); + err = krb5_get_config_tag (context->cf, buf, &val); if (err) return err; - **hostlist = malloc (2 * sizeof (char *)); + *hostlist = malloc (2 * sizeof (char *)); (*hostlist)[0] = val; (*hostlist)[1] = NULL; return 0; diff --git a/lib/krb5/send_to_kdc.c b/lib/krb5/send_to_kdc.c index 51e62f94d..9e564d320 100644 --- a/lib/krb5/send_to_kdc.c +++ b/lib/krb5/send_to_kdc.c @@ -1,17 +1,18 @@ #include "krb5_locl.h" +#include "krb5_error.h" static int send_and_recv (int fd, struct sockaddr_in *addr, - krb5_data *send, + const krb5_data *send, krb5_data *recv) { - struct fdset fdset; + struct fd_set fdset; struct timeval timeout; int ret; long nbytes; - if (sendto (fd, send->data, send->len, 0, + if (sendto (fd, send->data, send->length, 0, (struct sockaddr *)addr, sizeof(*addr)) < 0) return -1; FD_ZERO(&fdset); @@ -22,24 +23,25 @@ send_and_recv (int fd, if (ret <= 0) return -1; else { - ioctl (fd, FIONREAD, &nbytes); + int len; - nbytes -= sizeof(struct udphdr) + sizeof(struct iphdr); + if (ioctl (fd, FIONREAD, &nbytes) < 0) + return -1; recv->data = malloc (nbytes); - ret = recvfrom (fd, recv->data, nbytes, 0, NULL, 0); + ret = recvfrom (fd, recv->data, nbytes, 0, NULL, &len); if (ret < 0) { free (recv->data); return -1; } recv->data = realloc (recv->data, ret); - recv->len = ret; + recv->length = ret; return 0; } } krb5_error_code -krb5_sentdo_kdc (krb5_context context, +krb5_sendto_kdc (krb5_context context, const krb5_data *send, const krb5_data *realm, krb5_data *receive) @@ -51,35 +53,52 @@ krb5_sentdo_kdc (krb5_context context, int port; int i; - port = krb5_getportbyname ("kerberos", "udp", htons(750)); + port = krb5_getportbyname ("kerberos", "udp", htons(88)); fd = socket (AF_INET, SOCK_DGRAM, 0); - if (fd < 0) + if (fd < 0) { + krb5_free_krbhst (context, hostlist); return errno; + } err = krb5_get_krbhst (context, realm, &hostlist); if (err) { close (fd); return err; } + for (i = 0; i < 3; ++i) for (hp = hostlist; p = *hp; ++hp) { char *addr; + char *colon; + colon = strchr (p, ':'); + if (colon) + *colon = '\0'; hostent = gethostbyname (p); + if (colon) + *colon++ = ':'; while (addr = *hostent->h_addr_list++) { struct sockaddr_in a; - memset (a, 0, sizeof(a)); + memset (&a, 0, sizeof(a)); a.sin_family = AF_INET; - a.sin_port = port; + if (colon) { + int tmp; + + sscanf (colon, "%d", &tmp); + a.sin_port = htons(tmp); + } else + a.sin_port = port; a.sin_addr = *((struct in_addr *)addr); - if (send_and_recv (fd, &a, send, recv) == 0) { + if (send_and_recv (fd, &a, send, receive) == 0) { + close (fd); krb5_free_krbhst (context, hostlist); - return KDC_ERR_NONE; + return 0; } } } + close (fd); krb5_free_krbhst (context, hostlist); return KRB5_KDC_UNREACH; } diff --git a/lib/krb5/str2key.c b/lib/krb5/str2key.c index 9e9f2ba55..a63e584b1 100644 --- a/lib/krb5/str2key.c +++ b/lib/krb5/str2key.c @@ -86,7 +86,7 @@ init (unsigned char *a, unsigned char *b) a[7] = b[7] << 1; } -void +krb5_error_code krb5_string_to_key (char *str, krb5_data *salt, krb5_keyblock *key) @@ -98,7 +98,7 @@ krb5_string_to_key (char *str, des_key_schedule sched; krb5_error_code err; - len = strlen(str) + salt->len; + len = strlen(str) + salt->length; #if 1 len = (len + 7) / 8 * 8; #endif @@ -113,7 +113,7 @@ krb5_string_to_key (char *str, memset (s, 0, len); strncpy (p, str, strlen(str)); p += strlen(str); - strncpy (p, salt->data, salt->len); + strncpy (p, salt->data, salt->length); odd = 1; memset (tempkey, 0, sizeof(tempkey)); for (i = 0; i < len; i += 8) { diff --git a/send_to_kdc.c b/send_to_kdc.c index 51e62f94d..9e564d320 100644 --- a/send_to_kdc.c +++ b/send_to_kdc.c @@ -1,17 +1,18 @@ #include "krb5_locl.h" +#include "krb5_error.h" static int send_and_recv (int fd, struct sockaddr_in *addr, - krb5_data *send, + const krb5_data *send, krb5_data *recv) { - struct fdset fdset; + struct fd_set fdset; struct timeval timeout; int ret; long nbytes; - if (sendto (fd, send->data, send->len, 0, + if (sendto (fd, send->data, send->length, 0, (struct sockaddr *)addr, sizeof(*addr)) < 0) return -1; FD_ZERO(&fdset); @@ -22,24 +23,25 @@ send_and_recv (int fd, if (ret <= 0) return -1; else { - ioctl (fd, FIONREAD, &nbytes); + int len; - nbytes -= sizeof(struct udphdr) + sizeof(struct iphdr); + if (ioctl (fd, FIONREAD, &nbytes) < 0) + return -1; recv->data = malloc (nbytes); - ret = recvfrom (fd, recv->data, nbytes, 0, NULL, 0); + ret = recvfrom (fd, recv->data, nbytes, 0, NULL, &len); if (ret < 0) { free (recv->data); return -1; } recv->data = realloc (recv->data, ret); - recv->len = ret; + recv->length = ret; return 0; } } krb5_error_code -krb5_sentdo_kdc (krb5_context context, +krb5_sendto_kdc (krb5_context context, const krb5_data *send, const krb5_data *realm, krb5_data *receive) @@ -51,35 +53,52 @@ krb5_sentdo_kdc (krb5_context context, int port; int i; - port = krb5_getportbyname ("kerberos", "udp", htons(750)); + port = krb5_getportbyname ("kerberos", "udp", htons(88)); fd = socket (AF_INET, SOCK_DGRAM, 0); - if (fd < 0) + if (fd < 0) { + krb5_free_krbhst (context, hostlist); return errno; + } err = krb5_get_krbhst (context, realm, &hostlist); if (err) { close (fd); return err; } + for (i = 0; i < 3; ++i) for (hp = hostlist; p = *hp; ++hp) { char *addr; + char *colon; + colon = strchr (p, ':'); + if (colon) + *colon = '\0'; hostent = gethostbyname (p); + if (colon) + *colon++ = ':'; while (addr = *hostent->h_addr_list++) { struct sockaddr_in a; - memset (a, 0, sizeof(a)); + memset (&a, 0, sizeof(a)); a.sin_family = AF_INET; - a.sin_port = port; + if (colon) { + int tmp; + + sscanf (colon, "%d", &tmp); + a.sin_port = htons(tmp); + } else + a.sin_port = port; a.sin_addr = *((struct in_addr *)addr); - if (send_and_recv (fd, &a, send, recv) == 0) { + if (send_and_recv (fd, &a, send, receive) == 0) { + close (fd); krb5_free_krbhst (context, hostlist); - return KDC_ERR_NONE; + return 0; } } } + close (fd); krb5_free_krbhst (context, hostlist); return KRB5_KDC_UNREACH; } diff --git a/str2key.c b/str2key.c index 9e9f2ba55..a63e584b1 100644 --- a/str2key.c +++ b/str2key.c @@ -86,7 +86,7 @@ init (unsigned char *a, unsigned char *b) a[7] = b[7] << 1; } -void +krb5_error_code krb5_string_to_key (char *str, krb5_data *salt, krb5_keyblock *key) @@ -98,7 +98,7 @@ krb5_string_to_key (char *str, des_key_schedule sched; krb5_error_code err; - len = strlen(str) + salt->len; + len = strlen(str) + salt->length; #if 1 len = (len + 7) / 8 * 8; #endif @@ -113,7 +113,7 @@ krb5_string_to_key (char *str, memset (s, 0, len); strncpy (p, str, strlen(str)); p += strlen(str); - strncpy (p, salt->data, salt->len); + strncpy (p, salt->data, salt->length); odd = 1; memset (tempkey, 0, sizeof(tempkey)); for (i = 0; i < len; i += 8) {