diff --git a/Makefile b/Makefile new file mode 100644 index 000000000..a30a91696 --- /dev/null +++ b/Makefile @@ -0,0 +1,33 @@ +CC=cc +CFLAGS=-g + + +YFLAGS = -d + +SOURCES = principal.c principal_p.c data.c context.c misc.c string2key.c + +OBJECTS = $(SOURCES:%.c=%.o) config_file.o + + +tt: test.o libkrb5.a + $(CC) -o tt test.o libkrb5.a + +test.o: krb5.h + +libkrb5.a: $(OBJECTS) + ar cr libkrb5.a $(OBJECTS) + ranlib libkrb5.a + +config_file.o: config_file.c + +config_file.c: config_file.y + yacc -b y -p __k5cf_ $< + mv -f y.tab.c config_file.c + +clean: + rm -f *.o *~ libkrb5.a tt core \#* config_file.c + + + +$(OBJECTS): krb5_locl.h krb5.h + diff --git a/auth_context.c b/auth_context.c new file mode 100644 index 000000000..547c075bf --- /dev/null +++ b/auth_context.c @@ -0,0 +1,135 @@ +krb5_error_code +krb5_auth_con_init(krb5_context context, + krb5_auth_context **auth_context) +{ + +} + + +krb5_error_code +krb5_auth_con_free(krb5_context context, + krb5_auth_context *auth_context) +{ +} + + +krb5_error_code +krb5_auth_con_setflags(krb5_context context, + krb5_auth_context *auth_context, + krb5_int32 flags) +{ +} + + +krb5_error_code +krb5_auth_con_getflags(krb5_context context, + krb5_auth_context *auth_context, + krb5_int32 *flags) +{ +} + + +krb5_error_code +krb5_auth_con_setaddrs(krb5_context context, + krb5_auth_context *auth_context, + krb5_address *local_addr, + krb5_address *remote_addr) +{ +} + + +krb5_error_code +krb5_auth_con_getaddrs(krb5_context context, + krb5_auth_context *auth_context, + krb5_address **local_addr, + krb5_address **remote_addr) +{ +} + + + +krb5_error_code +krb5_auth_con_setuserkey(krb5_context context, + krb5_auth_context *auth_context, + krb5_keyblock *keyblock) +{ +} + + +krb5_error_code +krb5_auth_con_getkey(krb5_context context, + krb5_auth_context *auth_context, + krb5_keyblock **keyblock) +{ +} + + +/* ??? */ +void +krb5_free_keyblock(krb5_keyblock *keyblock) +{ + +} + +krb5_error_code +krb5_auth_setcksumtype(krb5_context context, + krb5_auth_context *auth_context, + krb5_cksumtype cksumtype) +{ +} + + +krb5_error_code +krb5_auth_getlocalseqnumber(krb5_context context, + krb5_auth_context *auth_context, + krb5_int32 *seqnumber) +{ +} + + +krb5_error_code +krb5_auth_getremoteseqnumber(krb5_context context, + krb5_auth_context *auth_context, + krb5_int32 *seqnumber) +{ +} + + +krb5_error_code +krb5_auth_getauthenticator(krb5_context context, + krb5_auth_context *auth_context, + krb5_authenticator **authenticator) +{ +} + + +void +krb5_free_authenticator(krb5_authenticator *authenticator) +{ +} + /* ??? */ + +krb5_error_code +krb5_auth_initvector(krb5_context context, + krb5_auth_context *auth_context) +{ +} + + +krb5_error_code +krb5_set_initvector(krb5_context context, + krb5_auth_context *auth_context, + krb5_pointer ivector) +{ +} + + +krb5_error_code +krb5_set_rcache(krb5_context context, + krb5_auth_context *auth_context, + krb5_rcache rcache) +{ +} + + + diff --git a/cache.c b/cache.c new file mode 100644 index 000000000..6ef2b4595 --- /dev/null +++ b/cache.c @@ -0,0 +1,182 @@ +#include "krb5_locl.h" + + +krb5_error_code +krb5_cc_resolve(krb5_context context, + krb5_ccache *id, + const char *residual) +{ + +} + +krb5_error_code +krb5_cc_gen_new(krb5_context context, + krb5_ccache *id) +{ +} + +krb5_error_code +krb5_cc_default(krb5_context context, + krb5_ccache *id) +{ +} + +static krb5_error_code +store_int32(int fd, + int32_t value) +{ + value = htonl(value); + return write(fd, &value, sizeof(value)); +} + +static krb5_error_code +store_int16(int fd, + int16_t value) +{ + value = htons(value); + return write(fd, &value, sizeof(value)); +} + +static krb5_error_code +store_int8(int fd, + int8_t value) +{ + return write(fd, &value, sizeof(value)); +} + +static krb5_error_code +store_data(int fd, + krb5_data *data) +{ + int ret; + ret = store_int32(fd, data->length); + if(ret < 0) + return ret; + return write(fd, data->data, data->length); +} + +static krb5_error_code +store_principal(int fd, + krb5_principal p) +{ + int i; + store_int32(fd, p->type); + store_int32(fd, p->ncomp); + store_data(fd, p->realm); + for(i = 0; i < p->ncomp; i++) + store_data(fd, p->comp[i]); + return 0; +} + +krb5_error_code +krb5_cc_initialize(krb5_context context, + krb5_ccache id, + krb5_principal primary_principal) +{ + char cc[1024]; + char *p; + int ret; + int fd; + + krb5_fcache *f; + + p = getenv("KRB5CCNAME"); + if(p) + strcpy(cc, p); + else + sprintf(cc, "/tmp/krb5cc_%d", getuid()); + + + ret = unlink(cc); + if(ret == -1 && errno != ENOENT) + return ret; + fd = open(cc, O_RDWR, 0600); + if(fd == -1) + return ret; + store_int16(fd, 0x503); + store_principal(fd, primary_principal); + close(fd); + + f = ALLOC(1, krb5_fcache); /* XXX */ + f->filename = strdup(cc); + + id->data->data = f; + id->data->length = sizeof(*f); + id->type = 4711/3210; + + return 0; +} + +krb5_error_code +krb5_cc_destroy(krb5_context context, + krb5_ccache id) +{ +} + +krb5_error_code +krb5_cc_close(krb5_context context, + krb5_ccache id) +{ +} + +krb5_error_code +krb5_cc_store(krb5_context context, + krb5_ccache id, + krb5_creds *creds) +{ + +} + +krb5_error_code +krb5_cc_retrieve(krb5_context context, + krb5_ccache id, + krb5_flags whichfields, + krb5_creds *mcreds, + krb5_creds *creds) +{ +} + +krb5_error_code +krb5_cc_get_princ(krb5_context context, + krb5_ccache id, + krb5_pricipal *principal) +{ +} + +krb5_error_code +krb5_cc_get_first(krb5_context context, + krb5_ccache id, + krb5_cc_cursor *cursor) +{ +} + +krb5_error_code +krb5_cc_get_next(krb5_context context, + krb5_ccache id, + krb5_creds *creds, + krb5_cc_cursor *cursor) +{ +} + +krb5_error_code +krb5_cc_end_get(krb5_context context, + krb5_ccache id, + krb5_cc_cursor *cursor) +{ +} + +krb5_error_code +krb5_cc_remove_cred(krb5_context context, + krb5_ccache id, + krb5_flags which, + krb5_creds *cred) +{ +} + +krb5_error_code +krb5_cc_set_flags(krb5_context context, + krb5_ccache id, + krb5_flags flags) +{ +} + diff --git a/config_file.h b/config_file.h new file mode 100644 index 000000000..1374216bb --- /dev/null +++ b/config_file.h @@ -0,0 +1,55 @@ +#ifndef __CONF_H__ +#define __CONF_H__ + +enum { + krb5_config_value_string, + krb5_config_value_list +}; + +struct krb5_config_relation; + +typedef struct krb5_config_value{ + int type; + union { + char *string; + struct krb5_config_relation *relations; + }data; +}krb5_config_value; + +typedef struct krb5_config_relation{ + char *tag; + struct krb5_config_value value; + struct krb5_config_relation *next; +}krb5_config_relation; + +typedef struct krb5_config_section{ + char *name; + struct krb5_config_relation *relations; + struct krb5_config_section *next; +}krb5_config_section; + +typedef struct krb5_config_file{ + char *filename; + struct krb5_config_section *sections; +}krb5_config_file; + + + +/* +static char *gettoken(FILE *F); +static void +free_config_file(krb5_config_file *cf); +static krb5_error_code +new_config_file(krb5_config_file **cf, const char *filename); +static void +free_config_section(krb5_config_section *sec); +static krb5_error_code +new_config_section(krb5_config_section **sec, const char *name); +static void +free_config_relation(krb5_config_relation *rel); +static void +free_config_value(krb5_config_value val); +static krb5_error_code +parse_config_file(krb5_config_file **cf, const char *filename); +*/ +#endif /* __CONF_H__ */ diff --git a/config_file.y b/config_file.y new file mode 100644 index 000000000..f1318eb3e --- /dev/null +++ b/config_file.y @@ -0,0 +1,259 @@ +%{ + +#include +#include +#include +#include + +#include "krb5_locl.h" +#include "config_file.h" + +static char section[128]; +static FILE *F; + +static krb5_config_file *cf; + +static krb5_config_section *csec; + +static krb5_config_relation **crel; +static krb5_config_relation **rels[16]; +static int relp; + +%} + +%union { + int i; + char *s; +} + +%token STRING + +%% + +file : section_list + ; + +section_list : /* empty */ + | section rel_list section_list { + printf("section_list\n"); } + ; + +section + : '[' STRING ']' + { + krb5_config_section *p; + p = ALLOC(1, krb5_config_section); + p->next = NULL; + p->name = $2; + p->relations = NULL; + if(cf->sections) + p->next = cf->sections; + cf->sections = p; + csec = p; + crel = &p->relations; + printf("section\n"); strcpy(section, $2); } + ; + +rel_list + : relation rel_sub + ; + +rel_sub : /* empty */ + | relation rel_sub + ; + +relation + : tag '=' value { printf("relation\n"); } + ; + +tag : STRING + { + krb5_config_relation *p; + if(!crel){ + fprintf(stderr, "error\n"); + return -17; + } + p = ALLOC(1, krb5_config_relation); + p->tag = $1; + if(*crel){ + p->next = NULL; + (*crel)->value.data.relations = p; + rels[relp++] = crel; + crel = &p; + }else{ + p->next = *crel; + *crel = p; + } + printf("tag\n"); + } + ; + +value : STRING + { + (*crel)->value.type = krb5_config_value_string; + (*crel)->value.data.string = $1; + crel = &(*crel)->next; + printf("value/string\n"); + } + | '{' rel_list '}' + { + crel = rels[--relp]; + (*crel)->value.type = krb5_config_value_list; + crel = &(*crel)->next; + printf("value/list\n"); + } + ; + +%% + +static int yylex(void) +{ + int c; + static char save; + static char yytext[1024]; + char *p = yytext; + int type = 0; + while(1){ + if(save){ + c = save; + save = 0; + }else + c = getc(F); + if(c == EOF) + break; + if(isspace(c)) + if(type) + break; /* end of token */ + else + continue; /* eat ws */ + if(strchr("[]={}", c)){ + if(type) + save = c; + else{ + return c; + } + break; + } + *p++ = c; + type = STRING; + continue; + } + *p = 0; + yylval.s = strdup(yytext); + return type; +} + +static void yyerror(char *s) +{ + printf("yyerror: %s\n", s); +} + + +/*----------------------------------------*/ + +static void +free_config_file(krb5_config_file *cf) +{ + if(!cf) + return; + FREE(cf->filename); + free(cf); +} + +static void free_config_relation(krb5_config_relation *rel); + +static void +free_config_value(krb5_config_value val) +{ + if(val.type == krb5_config_value_string) + FREE(val.data.string); + else if(val.type == krb5_config_value_list) + free_config_relation(val.data.relations); + else + fprintf(stderr, "free_config_value: krb5_config_value " + "with bad type passed (%d)\n", val.type); +} + +static void +free_config_relation(krb5_config_relation *rel) +{ + if(!rel) + return; + free_config_value(rel->value); + free_config_relation(rel->next); + FREE(rel); +} + +static void +free_config_section(krb5_config_section *sec) +{ + if(!sec) + return; + FREE(sec->name); + free_config_relation(sec->relations); + free_config_section(sec->next); + FREE(sec); +} + + +void +krb5_free_config_file(krb5_config_file *cf) +{ + free_config_file(cf); +} + +krb5_error_code +krb5_get_config_tag(krb5_config_file *cf, const char *tag, char **value) +{ + char *str; + char *p; + krb5_config_section *s; + krb5_config_relation *r; + + str = strdup(tag); + p = strtok(str, " \t"); + if(!p) + return ENOENT; + for(s = cf->sections; s; s = s->next){ + if(!strcmp(s->name, p)){ + p = strtok(NULL, " \t"); + for(r = s->relations; r;){ + if(!strcmp(r->tag, p)){ + if(r->value.type == krb5_config_value_string){ + *value = strdup(r->value.data.string); + free(str); + return 0; + }else{ + p = strtok(NULL, " \t"); + r = r->value.data.relations; + continue; + } + } + r = r->next; + } + } + } + return ENOENT; +} + +krb5_error_code +krb5_parse_config_file(krb5_config_file **cfile, const char *filename) +{ + krb5_error_code ret; + if(!filename) + filename = krb5_config_file; + F = fopen(filename, "r"); + if(F == NULL) + return errno; + cf = ALLOC(1, krb5_config_file); + if(!cf) + return ENOMEM; + ret = yyparse(); + + fclose(F); + if(ret) + krb5_free_config_file(cf); + else + *cfile = cf; + return ret; +} diff --git a/constants.c b/constants.c new file mode 100644 index 000000000..94e5664c1 --- /dev/null +++ b/constants.c @@ -0,0 +1,4 @@ + + +const char krb5_config_file[] = "/etc/krb5.conf"; +const char krb5_defkeyname[] = "/etc/v5srvtab"; diff --git a/context.c b/context.c new file mode 100644 index 000000000..898ad87bf --- /dev/null +++ b/context.c @@ -0,0 +1,88 @@ +#include "krb5_locl.h" + +krb5_error_code +krb5_init_context(krb5_context *context) +{ + krb5_context p; + p = ALLOC(1, krb5_context_data); + if(!p) + return ENOMEM; + memset(p, 0, sizeof(krb5_context_data)); + krb5_parse_config_file(&p->cf, NULL); + krb5_get_lrealm(&p->default_realm); + *context = p; + return 0; +} + +void krb5_os_free_context(krb5_context context) +{ + +} + +void krb5_free_context(krb5_context context) +{ + free(context->default_realm); + free(context); +} + + +static krb5_boolean +valid_etype(krb5_enctype e) +{ + return e == ETYPE_DES_CBC_CRC; +} + +static krb5_error_code +default_etypes(krb5_enctype **etype) +{ + krb5_enctype *p; + p = ALLOC(1, krb5_enctype); + if(!p) + return ENOMEM; + p[0] = ETYPE_DES_CBC_CRC; + *etype = p; + return 0; +} + +krb5_error_code +krb5_set_default_in_tkt_etypes(krb5_context context, + const krb5_enctype *etypes) +{ + int i; + krb5_enctype *p = NULL; + if(etypes){ + i = 0; + while(etypes[i]) + if(!valid_etype(etypes[i++])) + return KRB5_PROG_ETYPE_NOSUPP; + p = ALLOC(i, krb5_enctype); + if(!p) + return ENOMEM; + memmove(p, etypes, i * sizeof(krb5_enctype)); + } + if(context->etypes) free(context->etypes); + context->etypes = p; + return 0; +} + + + +krb5_error_code +krb5_get_default_in_tkt_etypes(krb5_context context, + krb5_enctype **etypes) +{ + krb5_enctype *p; + int i; + if(context->etypes){ + for(i = 0; context->etypes[i]; i++); + p = ALLOC(i, krb5_enctype); + if(!p) + return ENOMEM; + memmove(p, context->etypes, i * sizeof(krb5_enctype)); + }else + if(default_etypes(&p)) + return ENOMEM; + *etypes = p; + return 0; +} + diff --git a/data.c b/data.c new file mode 100644 index 000000000..80234db64 --- /dev/null +++ b/data.c @@ -0,0 +1,46 @@ +#include "krb5_locl.h" + + +void +krb5_data_free(krb5_data *p) +{ + if(p->length && p->data) + free(p->data); + p->length = 0; +} + +krb5_error_code +krb5_data_alloc(krb5_data *p, int len) +{ + krb5_data_free(p); + p->data = (krb5_pointer)malloc(len); + if(!p->data) + return ENOMEM; + p->length = len; + return 0; +} + +krb5_error_code +krb5_data_realloc(krb5_data *p, int len) +{ + void *tmp; + tmp = realloc(p->data, len); + if(!tmp) + return ENOMEM; + p->data = tmp; + p->length = len; + return 0; +} + +krb5_error_code +krb5_data_copy(krb5_data *p, void *data, size_t len) +{ + krb5_data_free(p); + p->data = (krb5_pointer)malloc(len); + if(!p->data) + return ENOMEM; + memmove(p->data, data, len); + p->length = len; + return 0; +} + diff --git a/get_in_tkt.c b/get_in_tkt.c new file mode 100644 index 000000000..8d630318d --- /dev/null +++ b/get_in_tkt.c @@ -0,0 +1,18 @@ +#include "krb5_locl.h" + +krb5_error_code +krb5_get_in_tkt(krb5_context context, + krb5_flags options, + krb5_address *const *addrs, + const krb5_enctype *etypes, + const krb5_preauthtype *ptypes, + krb5_key_proc key_proc, + krb5_const_pointer keyseed, + krb5_decrypt_proc decrypt_proc, + krb5_const_pointer decryptarg, + krb5_creds *creds, + krb5_ccache ccache, + krb5_kdc_rep **ret_as_reply) +{ + +} diff --git a/krb5.conf b/krb5.conf new file mode 100644 index 000000000..174c3c7ba --- /dev/null +++ b/krb5.conf @@ -0,0 +1,37 @@ +[libdefaults] + ticket_lifetime = 600 + default_realm = x-dce.pdc.kth.se + +[realms] + foo = bar + x-dce.pdc.kth.se = { + kdc = sisyphus.pdc.kth.se:88 + admin_server = sisyphus.pdc.kth.se + default_domain = x-dce.pdc.kth.se + } + + ATHENA.MIT.EDU = { + kdc = KERBEROS-2.MIT.EDU:88 + kdc = KERBEROS.MIT.EDU + kdc = KERBEROS-1.MIT.EDU + admin_server = KERBEROS.MIT.EDU + default_domain = MIT.EDU + v4_instance_convert = { + mit = mit.edu + lithium = lithium.lcs.mit.edu + } + } + CYGNUS.COM = { + kdc = KERBEROS-1.CYGNUS.COM + kdc = KERBEROS.CYGNUS.COM + admin_server = KERBEROS.MIT.EDU + } + +[domain_realm] + emma.pdc.kth.se = x-dce.pdc.kth.se + farbrorn.pdc.kth.se = test.pdc.kth.se + sisyphus.pdc.kth.se = x-dce.pdc.kth.se + .mit.edu = ATHENA.MIT.EDU + mit.edu = ATHENA.MIT.EDU + .media.mit.edu = MEDIA-LAB.MIT.EDU + media.mit.edu = MEDIA-LAB.MIT.EDU diff --git a/krb5.h b/krb5.h new file mode 100644 index 000000000..72305bfa9 --- /dev/null +++ b/krb5.h @@ -0,0 +1,344 @@ +#ifndef __KRB5_H__ +#define __KRB5_H__ + +#include +#include + +/* types */ +typedef int int32_t; +typedef short int16_t; +typedef char int8_t; + +typedef int32_t krb5_int32; +typedef int16_t krb5_int16; +typedef int8_t krb5_int8; + +typedef unsigned int krb5_uint32; +typedef unsigned short krb5_uint16; +typedef unsigned char krb5_uint8; + +typedef int krb5_boolean; + +typedef krb5_int32 krb5_error_code; + + + +typedef void *krb5_pointer; +typedef const void *krb5_const_pointer; + +typedef struct krb5_data{ + size_t length; + krb5_pointer data; +} krb5_data; + + +typedef enum krb5_cksumtype { + CKSUMTYPE_NONE = 0, + CKSUMTYPE_CRC32 = 1, + CKSUMTYPE_RSA_MD4 = 2, + CKSUMTYPE_RSA_MD4_DES = 3, + CKSUMTYPE_DES_MAC = 4, + CKSUMTYPE_DES_MAC_K = 5, + CKSUMTYPE_RSA_MD4_DES_K = 6, + CKSUMTYPE_RSA_MD5_DES = 7, +} krb5_cksumtype; + + + +typedef enum krb5_enctype { + ETYPE_NONE = 0, + ETYPE_DES_CBC_CRC = 1, + ETYPE_DES_CBC_MD4 = 2, + ETYPE_DES_CBC_MD5 = 3 +} krb5_enctype; + +typedef enum krb5_preauthtype { + KRB5_PADATA_NONE = 0, + KRB5_PADATA_AP_REQ, + KRB5_PADATA_TGS_REQ = 1, + KRB5_PADATA_PW_SALT = 3, + KRB5_PADATA_ENC_TIMESTAMP = 2, + KRB5_PADATA_ENC_SECURID +} krb5_preauthtype; + + +typedef enum krb5_address_type { + KRB5_ADDRESS_INET = AF_INET, +} krb5_address_type; + +typedef struct krb5_address{ + krb5_address_type type; + krb5_data address; +} krb5_address; + + + +typedef enum krb5_keytype { KEYTYPE_DES } krb5_keytype; + +typedef struct krb5_keyblock{ + krb5_keytype keytype; + krb5_data contents; +} krb5_keyblock; + + +typedef struct krb5_context_data{ + krb5_enctype *etypes; + char *default_realm; + krb5_config_file *cf; +} krb5_context_data; + +typedef krb5_context_data *krb5_context; + + +typedef time_t krb5_time; + +typedef struct krb5_times{ + krb5_time endtime; + krb5_time starttime; + krb5_time renew_till; +} krb5_times; + +typedef struct krb5_ticket{ + int kvno; + krb5_principal sprinc; + krb5_data enc_part; + krb5_data enc_part2; + krb5_enctype etype; +}krb5_ticket; + + + +#define KRB5_PARSE_MALFORMED 17 +#define KRB5_PROG_ETYPE_NOSUPP 4711 + +typedef enum k{ + KRB_NT_UNKNOWNN = 0, + KRB_NT_PRINCIPAL = 1. + KRB_NT_SRV_INST = 2, + KRB_NT_SRV_HST = 3, + KRB_NT_SRV_XHST = 4, + KRB_NT_UID = 5 +}; + +typedef struct krb5_principal_data{ + int type; + krb5_data realm; + krb5_data *comp; + int ncomp; +}krb5_principal_data; + +typedef krb5_principal_data *krb5_principal; +typedef const krb5_principal_data *krb5_const_principal; + +typedef struct krb5_creds { + krb5_principal client; + krb5_principal server; + krb5_keyblock session; + krb5_times times; + krb5_ticket ticket; + + krb5_ticket second_ticket; /* ? */ + krb5_data authdata; /* ? */ + +} krb5_creds; + + +typedef struct krb5_authenticator_data{ + int dummy; +} krb5_authenticator_data; + +typedef krb5_authenticator_data *krb5_authenticator; + +typedef struct krb5_rcache{ + int dummy; +}krb5_rcache; + +typedef struct krb5_ccache{ + krb5_data data; +}krb5_ccache; + +typedef struct krb5_fcache{ + char *filename; +}; + +typedef struct krb5_cc_cursor{ + int dummy; +}krb5_cc_cursor; + +typedef struct krb5_keytab{ + int dummy; +}krb5_keytab; + + +typedef struct krb5_auth_context{ + krb5_int32 flags; + krb5_cksumtype cksumtype; + + krb5_address local_address; + krb5_address remote_address; + krb5_keyblock key; + krb5_keyblock local_subkey; + krb5_keyblock remote_subkey; + + krb5_int32 local_seqnumber; + krb5_int32 remote_seqnumber; + + krb5_authenticator authenticator; + + krb5_pointer i_vector; + + krb5_rcache rcache; + +}krb5_auth_context; + + +typedef krb5_uint32 krb5_flags; + +typedef struct krb5_kdc_rep{ + int dummy; +}krb5_kdc_rep; + + +krb5_error_code +krb5_init_context(krb5_context *context); + + +krb5_error_code +krb5_get_cred_from_kdc(krb5_context, + krb5_ccache ccache, + krb5_creds *in_cred, + krb5_creds **out_cred, + krb5_creds **tgts); + + +krb5_error_code +krb5_get_credentials(krb5_context context, + krb5_flags options, + krb5_ccache ccache, + krb5_creds *in_creds, + krb5_creds *out_creds); + +typedef krb5_error_code (*krb5_key_proc)(krb5_context context, + const 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_kdc_rep *dec_rep); + +krb5_error_code +krb5_get_in_tkt(krb5_context context, + krb5_flags options, + krb5_address *const *addrs, + const krb5_enctype *etypes, + const krb5_preauthtype *ptypes, + krb5_key_proc key_proc, + krb5_const_pointer keyseed, + krb5_decrypt_proc decrypt_proc, + krb5_const_pointer decryptarg, + krb5_creds *creds, + krb5_ccache ccache, + krb5_kdc_rep **ret_as_reply); + + +krb5_error_code +krb5_mk_req(krb5_context context, + krb5_auth_context **auth_context, + const krb5_flags ap_req_options, + char *service, + char *hostname, + krb5_data *in_data, + krb5_ccache ccache, + krb5_data *outbuf); + +krb5_error_code +krb5_generate_subkey(krb5_context context, + const krb5_keyblock *key, + krb5_keyblock **subkey); + + +krb5_error_code +krb5_rd_req(krb5_context context, + krb5_auth_context **auth_context, + const krb5_data *inbuf, + krb5_const_principal server, + krb5_keytab keytab, + krb5_flags *ap_req_options, + krb5_ticket **ticket); + + +krb5_error_code +krb5_parse_name(krb5_context context, + const char *name, + krb5_principal *principal); + +void +krb5_free_principal(krb5_principal principal); + +krb5_error_code +krb5_unparse_name(krb5_context context, + krb5_principal principal, + char **name); + +krb5_error_code +krb5_unparse_name_ext(krb5_context context, + krb5_const_principal principal, + char **name, + size_t *size); + +krb5_data* +krb5_princ_realm(krb5_context context, + krb5_principal principal); + +void +krb5_princ_set_realm(krb5_context context, + krb5_principal principal, + krb5_data *realm); + +krb5_error_code +krb5_build_principal(krb5_context context, + krb5_principal *principal, + int rlen, + const char *realm, + ...); + +krb5_error_code +krb5_build_principal_va(krb5_context context, + krb5_principal *principal, + int rlen, + const char *realm, + va_list ap); + +krb5_error_code +krb5_build_principal_ext(krb5_context context, + krb5_principal *principal, + int rlen, + const char *realm, + ...); + +krb5_error_code +krb5_copy_principal(krb5_context context, + krb5_const_principal inprinc, + krb5_principal *outprinc); + +krb5_boolean +krb5_principal_compare(krb5_context context, + krb5_const_principal princ1, + krb5_const_principal princ2); + +krb5_boolean +krb5_realm_compare(krb5_context context, + krb5_const_principal princ1, + krb5_const_principal princ2); + +krb5_error_code +krb5_425_conv_principal(krb5_context context, + const char *name, + const char *instance, + const char *realm, + krb5_principal *princ); + +#endif /* __KRB5_H__ */ + diff --git a/krb5_error.c b/krb5_error.c new file mode 100644 index 000000000..d31695850 --- /dev/null +++ b/krb5_error.c @@ -0,0 +1,66 @@ +#include "krb5_locl.h" + +static char *krb5_error_table[] = { + "No error", /* 0 */ + "Client's entry in database has expired", /* 1 */ + "Server's entry in database has expired", /* 2 */ + "Requested protocol version number not supported", /* 3 */ + "Client's key encrypted in old master key", /* 4 */ + "Server's key encrypted in old master key", /* 5 */ + "Client not found in Kerberos database", /* 6 */ + "Server not found in Kerberos database", /* 7 */ + "Multiple principal entries in database", /* 8 */ + "he client or server has a null key", /* 9 */ + "icket not eligible for postdating", /* 10 */ + "Requested start time is later than end time", /* 11 */ + "KDC policy rejects request", /* 12 */ + "KDC cannot accommodate requested option", /* 13 */ + "KDC has no support for encryption type", /* 14 */ + "KDC has no support for checksum type", /* 15 */ + "KDC has no support for padata type", /* 16 */ + "KDC has no support for transited type", /* 17 */ + "Clients credentials have been revoked", /* 18 */ + "Credentials for server have been revoked", /* 19 */ + "GT has been revoked", /* 20 */ + "Client not yet valid - try again later", /* 21 */ + "Server not yet valid - try again later", /* 22 */ + "Password has expired - change password to reset", /* 23 */ + "Pre-authentication information was invalid", /* 24 */ + "Additional pre-authentication required", /* 25 */ + "(reserved)", /* 26 */ + "(reserved)", /* 27 */ + "(reserved)", /* 28 */ + "(reserved)", /* 29 */ + "(reserved)", /* 30 */ + "Integrity check on decrypted field failed", /* 31 */ + "Ticket expired", /* 32 */ + "Ticket not yet valid", /* 33 */ + "Request is a replay", /* 34 */ + "The ticket isn't for us", /* 35 */ + "Ticket and authenticator don't match", /* 36 */ + "Clock skew too great", /* 37 */ + "Incorrect net address", /* 38 */ + "Protocol version mismatch", /* 39 */ + "Invalid msg type", /* 40 */ + "Message stream modified", /* 41 */ + "Message out of order", /* 42 */ + "(reserved)", /* 43 */ + "Specified version of key is not available", /* 44 */ + "Service key not available", /* 45 */ + "Mutual authentication failed", /* 46 */ + "Incorrect message direction", /* 47 */ + "Alternative authentication method required", /* 48 */ + "Incorrect sequence number in message", /* 49 */ + "Inappropriate type of checksum in message", /* 50 */ + "(reserved)", /* 51 */ + "(reserved)", /* 52 */ + "(reserved)", /* 53 */ + "(reserved)", /* 54 */ + "(reserved)", /* 55 */ + "(reserved)", /* 56 */ + "(reserved)", /* 57 */ + "(reserved)", /* 58 */ + "(reserved)", /* 59 */ + "Generic error", /* 60 */ + "Field is too long for this implementation", /* 61 */ +}; diff --git a/krb5_error.h b/krb5_error.h new file mode 100644 index 000000000..20316f8c2 --- /dev/null +++ b/krb5_error.h @@ -0,0 +1,52 @@ +#ifndef __KRB5_ERROR_H__ +#define __KRB5_ERROR_H__ + +#define KDC_ERR_NONE 0 +#define KDC_ERR_NAME_EXP 1 +#define KDC_ERR_SERVICE_EXP 2 +#define KDC_ERR_BAD_PVNO 3 +#define KDC_ERR_C_OLD_MAST_KVNO 4 +#define KDC_ERR_S_OLD_MAST_KVNO 5 +#define KDC_ERR_C_PRINCIPAL_UNKNOWN 6 +#define KDC_ERR_S_PRINCIPAL_UNKNOWN 7 +#define KDC_ERR_PRINCIPAL_NOT_UNIQUE 8 +#define KDC_ERR_NULL_KEY 9 +#define KDC_ERR_CANNOT_POSTDATE 10 +#define KDC_ERR_NEVER_VALID 11 +#define KDC_ERR_POLICY 12 +#define KDC_ERR_BADOPTION 13 +#define KDC_ERR_ETYPE_NOSUPP 14 +#define KDC_ERR_SUMTYPE_NOSUPP 15 +#define KDC_ERR_PADATA_TYPE_NOSUPP 16 +#define KDC_ERR_TRTYPE_NOSUPP 17 +#define KDC_ERR_CLIENT_REVOKED 18 +#define KDC_ERR_SERVICE_REVOKED 19 +#define KDC_ERR_TGT_REVOKED 20 +#define KDC_ERR_CLIENT_NOTYET 21 +#define KDC_ERR_SERVICE_NOTYET 22 +#define KDC_ERR_KEY_EXPIRED 23 +#define KDC_ERR_PREAUTH_FAILED 24 +#define KDC_ERR_PREAUTH_REQUIRED 25 +#define KRB_AP_ERR_BAD_INTEGRITY 31 +#define KRB_AP_ERR_TKT_EXPIRED 32 +#define KRB_AP_ERR_TKT_NYV 33 +#define KRB_AP_ERR_REPEAT 34 +#define KRB_AP_ERR_NOT_US 35 +#define KRB_AP_ERR_BADMATCH 36 +#define KRB_AP_ERR_SKEW 37 +#define KRB_AP_ERR_BADADDR 38 +#define KRB_AP_ERR_BADVERSION 39 +#define KRB_AP_ERR_MSG_TYPE 40 +#define KRB_AP_ERR_MODIFIED 41 +#define KRB_AP_ERR_BADORDER 42 +#define KRB_AP_ERR_BADKEYVER 44 +#define KRB_AP_ERR_NOKEY 45 +#define KRB_AP_ERR_MUT_FAIL 46 +#define KRB_AP_ERR_BADDIRECTION 47 +#define KRB_AP_ERR_METHOD 48 +#define KRB_AP_ERR_BADSEQ 49 +#define KRB_AP_ERR_INAPP_CKSUM 50 +#define KRB_ERR_GENERIC 60 +#define KRB_ERR_FIELD_TOOLONG 61 + +#endif /* __KRB5_ERROR_H__ */ diff --git a/krb5_locl.h b/krb5_locl.h new file mode 100644 index 000000000..5ab659129 --- /dev/null +++ b/krb5_locl.h @@ -0,0 +1,30 @@ +#ifndef __KRB5_LOCL_H__ +#define __KRB5_LOCL_H__ + +#include +#include +#include +#include +#include + +#include "krb5.h" + +void krb5_data_free(krb5_data *); +krb5_error_code krb5_data_alloc(krb5_data *, int); +krb5_error_code krb5_data_realloc(krb5_data *, int); +krb5_error_code krb5_data_copy(krb5_data *, void *, size_t); + + +krb5_error_code krb5_principal_alloc(krb5_principal*); +void krb5_principal_free(krb5_principal); + +krb5_error_code krb5_get_lrealm(char ** realm); + + + +#define ALLOC(N, X) ((X*)malloc((N) * sizeof(X))) +#define FREE(X) do{if(X)free(X);}while(0) + +#define RCSID(X) static char *rcsid[] = { (char*)rcsid, X } + +#endif /* __KRB5_LOCL_H__ */ diff --git a/lib/krb5/cache.c b/lib/krb5/cache.c new file mode 100644 index 000000000..6ef2b4595 --- /dev/null +++ b/lib/krb5/cache.c @@ -0,0 +1,182 @@ +#include "krb5_locl.h" + + +krb5_error_code +krb5_cc_resolve(krb5_context context, + krb5_ccache *id, + const char *residual) +{ + +} + +krb5_error_code +krb5_cc_gen_new(krb5_context context, + krb5_ccache *id) +{ +} + +krb5_error_code +krb5_cc_default(krb5_context context, + krb5_ccache *id) +{ +} + +static krb5_error_code +store_int32(int fd, + int32_t value) +{ + value = htonl(value); + return write(fd, &value, sizeof(value)); +} + +static krb5_error_code +store_int16(int fd, + int16_t value) +{ + value = htons(value); + return write(fd, &value, sizeof(value)); +} + +static krb5_error_code +store_int8(int fd, + int8_t value) +{ + return write(fd, &value, sizeof(value)); +} + +static krb5_error_code +store_data(int fd, + krb5_data *data) +{ + int ret; + ret = store_int32(fd, data->length); + if(ret < 0) + return ret; + return write(fd, data->data, data->length); +} + +static krb5_error_code +store_principal(int fd, + krb5_principal p) +{ + int i; + store_int32(fd, p->type); + store_int32(fd, p->ncomp); + store_data(fd, p->realm); + for(i = 0; i < p->ncomp; i++) + store_data(fd, p->comp[i]); + return 0; +} + +krb5_error_code +krb5_cc_initialize(krb5_context context, + krb5_ccache id, + krb5_principal primary_principal) +{ + char cc[1024]; + char *p; + int ret; + int fd; + + krb5_fcache *f; + + p = getenv("KRB5CCNAME"); + if(p) + strcpy(cc, p); + else + sprintf(cc, "/tmp/krb5cc_%d", getuid()); + + + ret = unlink(cc); + if(ret == -1 && errno != ENOENT) + return ret; + fd = open(cc, O_RDWR, 0600); + if(fd == -1) + return ret; + store_int16(fd, 0x503); + store_principal(fd, primary_principal); + close(fd); + + f = ALLOC(1, krb5_fcache); /* XXX */ + f->filename = strdup(cc); + + id->data->data = f; + id->data->length = sizeof(*f); + id->type = 4711/3210; + + return 0; +} + +krb5_error_code +krb5_cc_destroy(krb5_context context, + krb5_ccache id) +{ +} + +krb5_error_code +krb5_cc_close(krb5_context context, + krb5_ccache id) +{ +} + +krb5_error_code +krb5_cc_store(krb5_context context, + krb5_ccache id, + krb5_creds *creds) +{ + +} + +krb5_error_code +krb5_cc_retrieve(krb5_context context, + krb5_ccache id, + krb5_flags whichfields, + krb5_creds *mcreds, + krb5_creds *creds) +{ +} + +krb5_error_code +krb5_cc_get_princ(krb5_context context, + krb5_ccache id, + krb5_pricipal *principal) +{ +} + +krb5_error_code +krb5_cc_get_first(krb5_context context, + krb5_ccache id, + krb5_cc_cursor *cursor) +{ +} + +krb5_error_code +krb5_cc_get_next(krb5_context context, + krb5_ccache id, + krb5_creds *creds, + krb5_cc_cursor *cursor) +{ +} + +krb5_error_code +krb5_cc_end_get(krb5_context context, + krb5_ccache id, + krb5_cc_cursor *cursor) +{ +} + +krb5_error_code +krb5_cc_remove_cred(krb5_context context, + krb5_ccache id, + krb5_flags which, + krb5_creds *cred) +{ +} + +krb5_error_code +krb5_cc_set_flags(krb5_context context, + krb5_ccache id, + krb5_flags flags) +{ +} + diff --git a/lib/krb5/config_file.h b/lib/krb5/config_file.h new file mode 100644 index 000000000..1374216bb --- /dev/null +++ b/lib/krb5/config_file.h @@ -0,0 +1,55 @@ +#ifndef __CONF_H__ +#define __CONF_H__ + +enum { + krb5_config_value_string, + krb5_config_value_list +}; + +struct krb5_config_relation; + +typedef struct krb5_config_value{ + int type; + union { + char *string; + struct krb5_config_relation *relations; + }data; +}krb5_config_value; + +typedef struct krb5_config_relation{ + char *tag; + struct krb5_config_value value; + struct krb5_config_relation *next; +}krb5_config_relation; + +typedef struct krb5_config_section{ + char *name; + struct krb5_config_relation *relations; + struct krb5_config_section *next; +}krb5_config_section; + +typedef struct krb5_config_file{ + char *filename; + struct krb5_config_section *sections; +}krb5_config_file; + + + +/* +static char *gettoken(FILE *F); +static void +free_config_file(krb5_config_file *cf); +static krb5_error_code +new_config_file(krb5_config_file **cf, const char *filename); +static void +free_config_section(krb5_config_section *sec); +static krb5_error_code +new_config_section(krb5_config_section **sec, const char *name); +static void +free_config_relation(krb5_config_relation *rel); +static void +free_config_value(krb5_config_value val); +static krb5_error_code +parse_config_file(krb5_config_file **cf, const char *filename); +*/ +#endif /* __CONF_H__ */ diff --git a/lib/krb5/config_file.y b/lib/krb5/config_file.y new file mode 100644 index 000000000..f1318eb3e --- /dev/null +++ b/lib/krb5/config_file.y @@ -0,0 +1,259 @@ +%{ + +#include +#include +#include +#include + +#include "krb5_locl.h" +#include "config_file.h" + +static char section[128]; +static FILE *F; + +static krb5_config_file *cf; + +static krb5_config_section *csec; + +static krb5_config_relation **crel; +static krb5_config_relation **rels[16]; +static int relp; + +%} + +%union { + int i; + char *s; +} + +%token STRING + +%% + +file : section_list + ; + +section_list : /* empty */ + | section rel_list section_list { + printf("section_list\n"); } + ; + +section + : '[' STRING ']' + { + krb5_config_section *p; + p = ALLOC(1, krb5_config_section); + p->next = NULL; + p->name = $2; + p->relations = NULL; + if(cf->sections) + p->next = cf->sections; + cf->sections = p; + csec = p; + crel = &p->relations; + printf("section\n"); strcpy(section, $2); } + ; + +rel_list + : relation rel_sub + ; + +rel_sub : /* empty */ + | relation rel_sub + ; + +relation + : tag '=' value { printf("relation\n"); } + ; + +tag : STRING + { + krb5_config_relation *p; + if(!crel){ + fprintf(stderr, "error\n"); + return -17; + } + p = ALLOC(1, krb5_config_relation); + p->tag = $1; + if(*crel){ + p->next = NULL; + (*crel)->value.data.relations = p; + rels[relp++] = crel; + crel = &p; + }else{ + p->next = *crel; + *crel = p; + } + printf("tag\n"); + } + ; + +value : STRING + { + (*crel)->value.type = krb5_config_value_string; + (*crel)->value.data.string = $1; + crel = &(*crel)->next; + printf("value/string\n"); + } + | '{' rel_list '}' + { + crel = rels[--relp]; + (*crel)->value.type = krb5_config_value_list; + crel = &(*crel)->next; + printf("value/list\n"); + } + ; + +%% + +static int yylex(void) +{ + int c; + static char save; + static char yytext[1024]; + char *p = yytext; + int type = 0; + while(1){ + if(save){ + c = save; + save = 0; + }else + c = getc(F); + if(c == EOF) + break; + if(isspace(c)) + if(type) + break; /* end of token */ + else + continue; /* eat ws */ + if(strchr("[]={}", c)){ + if(type) + save = c; + else{ + return c; + } + break; + } + *p++ = c; + type = STRING; + continue; + } + *p = 0; + yylval.s = strdup(yytext); + return type; +} + +static void yyerror(char *s) +{ + printf("yyerror: %s\n", s); +} + + +/*----------------------------------------*/ + +static void +free_config_file(krb5_config_file *cf) +{ + if(!cf) + return; + FREE(cf->filename); + free(cf); +} + +static void free_config_relation(krb5_config_relation *rel); + +static void +free_config_value(krb5_config_value val) +{ + if(val.type == krb5_config_value_string) + FREE(val.data.string); + else if(val.type == krb5_config_value_list) + free_config_relation(val.data.relations); + else + fprintf(stderr, "free_config_value: krb5_config_value " + "with bad type passed (%d)\n", val.type); +} + +static void +free_config_relation(krb5_config_relation *rel) +{ + if(!rel) + return; + free_config_value(rel->value); + free_config_relation(rel->next); + FREE(rel); +} + +static void +free_config_section(krb5_config_section *sec) +{ + if(!sec) + return; + FREE(sec->name); + free_config_relation(sec->relations); + free_config_section(sec->next); + FREE(sec); +} + + +void +krb5_free_config_file(krb5_config_file *cf) +{ + free_config_file(cf); +} + +krb5_error_code +krb5_get_config_tag(krb5_config_file *cf, const char *tag, char **value) +{ + char *str; + char *p; + krb5_config_section *s; + krb5_config_relation *r; + + str = strdup(tag); + p = strtok(str, " \t"); + if(!p) + return ENOENT; + for(s = cf->sections; s; s = s->next){ + if(!strcmp(s->name, p)){ + p = strtok(NULL, " \t"); + for(r = s->relations; r;){ + if(!strcmp(r->tag, p)){ + if(r->value.type == krb5_config_value_string){ + *value = strdup(r->value.data.string); + free(str); + return 0; + }else{ + p = strtok(NULL, " \t"); + r = r->value.data.relations; + continue; + } + } + r = r->next; + } + } + } + return ENOENT; +} + +krb5_error_code +krb5_parse_config_file(krb5_config_file **cfile, const char *filename) +{ + krb5_error_code ret; + if(!filename) + filename = krb5_config_file; + F = fopen(filename, "r"); + if(F == NULL) + return errno; + cf = ALLOC(1, krb5_config_file); + if(!cf) + return ENOMEM; + ret = yyparse(); + + fclose(F); + if(ret) + krb5_free_config_file(cf); + else + *cfile = cf; + return ret; +} diff --git a/lib/krb5/constants.c b/lib/krb5/constants.c new file mode 100644 index 000000000..94e5664c1 --- /dev/null +++ b/lib/krb5/constants.c @@ -0,0 +1,4 @@ + + +const char krb5_config_file[] = "/etc/krb5.conf"; +const char krb5_defkeyname[] = "/etc/v5srvtab"; diff --git a/lib/krb5/context.c b/lib/krb5/context.c new file mode 100644 index 000000000..898ad87bf --- /dev/null +++ b/lib/krb5/context.c @@ -0,0 +1,88 @@ +#include "krb5_locl.h" + +krb5_error_code +krb5_init_context(krb5_context *context) +{ + krb5_context p; + p = ALLOC(1, krb5_context_data); + if(!p) + return ENOMEM; + memset(p, 0, sizeof(krb5_context_data)); + krb5_parse_config_file(&p->cf, NULL); + krb5_get_lrealm(&p->default_realm); + *context = p; + return 0; +} + +void krb5_os_free_context(krb5_context context) +{ + +} + +void krb5_free_context(krb5_context context) +{ + free(context->default_realm); + free(context); +} + + +static krb5_boolean +valid_etype(krb5_enctype e) +{ + return e == ETYPE_DES_CBC_CRC; +} + +static krb5_error_code +default_etypes(krb5_enctype **etype) +{ + krb5_enctype *p; + p = ALLOC(1, krb5_enctype); + if(!p) + return ENOMEM; + p[0] = ETYPE_DES_CBC_CRC; + *etype = p; + return 0; +} + +krb5_error_code +krb5_set_default_in_tkt_etypes(krb5_context context, + const krb5_enctype *etypes) +{ + int i; + krb5_enctype *p = NULL; + if(etypes){ + i = 0; + while(etypes[i]) + if(!valid_etype(etypes[i++])) + return KRB5_PROG_ETYPE_NOSUPP; + p = ALLOC(i, krb5_enctype); + if(!p) + return ENOMEM; + memmove(p, etypes, i * sizeof(krb5_enctype)); + } + if(context->etypes) free(context->etypes); + context->etypes = p; + return 0; +} + + + +krb5_error_code +krb5_get_default_in_tkt_etypes(krb5_context context, + krb5_enctype **etypes) +{ + krb5_enctype *p; + int i; + if(context->etypes){ + for(i = 0; context->etypes[i]; i++); + p = ALLOC(i, krb5_enctype); + if(!p) + return ENOMEM; + memmove(p, context->etypes, i * sizeof(krb5_enctype)); + }else + if(default_etypes(&p)) + return ENOMEM; + *etypes = p; + return 0; +} + diff --git a/lib/krb5/data.c b/lib/krb5/data.c new file mode 100644 index 000000000..80234db64 --- /dev/null +++ b/lib/krb5/data.c @@ -0,0 +1,46 @@ +#include "krb5_locl.h" + + +void +krb5_data_free(krb5_data *p) +{ + if(p->length && p->data) + free(p->data); + p->length = 0; +} + +krb5_error_code +krb5_data_alloc(krb5_data *p, int len) +{ + krb5_data_free(p); + p->data = (krb5_pointer)malloc(len); + if(!p->data) + return ENOMEM; + p->length = len; + return 0; +} + +krb5_error_code +krb5_data_realloc(krb5_data *p, int len) +{ + void *tmp; + tmp = realloc(p->data, len); + if(!tmp) + return ENOMEM; + p->data = tmp; + p->length = len; + return 0; +} + +krb5_error_code +krb5_data_copy(krb5_data *p, void *data, size_t len) +{ + krb5_data_free(p); + p->data = (krb5_pointer)malloc(len); + if(!p->data) + return ENOMEM; + memmove(p->data, data, len); + p->length = len; + return 0; +} + diff --git a/lib/krb5/get_in_tkt.c b/lib/krb5/get_in_tkt.c new file mode 100644 index 000000000..8d630318d --- /dev/null +++ b/lib/krb5/get_in_tkt.c @@ -0,0 +1,18 @@ +#include "krb5_locl.h" + +krb5_error_code +krb5_get_in_tkt(krb5_context context, + krb5_flags options, + krb5_address *const *addrs, + const krb5_enctype *etypes, + const krb5_preauthtype *ptypes, + krb5_key_proc key_proc, + krb5_const_pointer keyseed, + krb5_decrypt_proc decrypt_proc, + krb5_const_pointer decryptarg, + krb5_creds *creds, + krb5_ccache ccache, + krb5_kdc_rep **ret_as_reply) +{ + +} diff --git a/lib/krb5/krb5.h b/lib/krb5/krb5.h new file mode 100644 index 000000000..72305bfa9 --- /dev/null +++ b/lib/krb5/krb5.h @@ -0,0 +1,344 @@ +#ifndef __KRB5_H__ +#define __KRB5_H__ + +#include +#include + +/* types */ +typedef int int32_t; +typedef short int16_t; +typedef char int8_t; + +typedef int32_t krb5_int32; +typedef int16_t krb5_int16; +typedef int8_t krb5_int8; + +typedef unsigned int krb5_uint32; +typedef unsigned short krb5_uint16; +typedef unsigned char krb5_uint8; + +typedef int krb5_boolean; + +typedef krb5_int32 krb5_error_code; + + + +typedef void *krb5_pointer; +typedef const void *krb5_const_pointer; + +typedef struct krb5_data{ + size_t length; + krb5_pointer data; +} krb5_data; + + +typedef enum krb5_cksumtype { + CKSUMTYPE_NONE = 0, + CKSUMTYPE_CRC32 = 1, + CKSUMTYPE_RSA_MD4 = 2, + CKSUMTYPE_RSA_MD4_DES = 3, + CKSUMTYPE_DES_MAC = 4, + CKSUMTYPE_DES_MAC_K = 5, + CKSUMTYPE_RSA_MD4_DES_K = 6, + CKSUMTYPE_RSA_MD5_DES = 7, +} krb5_cksumtype; + + + +typedef enum krb5_enctype { + ETYPE_NONE = 0, + ETYPE_DES_CBC_CRC = 1, + ETYPE_DES_CBC_MD4 = 2, + ETYPE_DES_CBC_MD5 = 3 +} krb5_enctype; + +typedef enum krb5_preauthtype { + KRB5_PADATA_NONE = 0, + KRB5_PADATA_AP_REQ, + KRB5_PADATA_TGS_REQ = 1, + KRB5_PADATA_PW_SALT = 3, + KRB5_PADATA_ENC_TIMESTAMP = 2, + KRB5_PADATA_ENC_SECURID +} krb5_preauthtype; + + +typedef enum krb5_address_type { + KRB5_ADDRESS_INET = AF_INET, +} krb5_address_type; + +typedef struct krb5_address{ + krb5_address_type type; + krb5_data address; +} krb5_address; + + + +typedef enum krb5_keytype { KEYTYPE_DES } krb5_keytype; + +typedef struct krb5_keyblock{ + krb5_keytype keytype; + krb5_data contents; +} krb5_keyblock; + + +typedef struct krb5_context_data{ + krb5_enctype *etypes; + char *default_realm; + krb5_config_file *cf; +} krb5_context_data; + +typedef krb5_context_data *krb5_context; + + +typedef time_t krb5_time; + +typedef struct krb5_times{ + krb5_time endtime; + krb5_time starttime; + krb5_time renew_till; +} krb5_times; + +typedef struct krb5_ticket{ + int kvno; + krb5_principal sprinc; + krb5_data enc_part; + krb5_data enc_part2; + krb5_enctype etype; +}krb5_ticket; + + + +#define KRB5_PARSE_MALFORMED 17 +#define KRB5_PROG_ETYPE_NOSUPP 4711 + +typedef enum k{ + KRB_NT_UNKNOWNN = 0, + KRB_NT_PRINCIPAL = 1. + KRB_NT_SRV_INST = 2, + KRB_NT_SRV_HST = 3, + KRB_NT_SRV_XHST = 4, + KRB_NT_UID = 5 +}; + +typedef struct krb5_principal_data{ + int type; + krb5_data realm; + krb5_data *comp; + int ncomp; +}krb5_principal_data; + +typedef krb5_principal_data *krb5_principal; +typedef const krb5_principal_data *krb5_const_principal; + +typedef struct krb5_creds { + krb5_principal client; + krb5_principal server; + krb5_keyblock session; + krb5_times times; + krb5_ticket ticket; + + krb5_ticket second_ticket; /* ? */ + krb5_data authdata; /* ? */ + +} krb5_creds; + + +typedef struct krb5_authenticator_data{ + int dummy; +} krb5_authenticator_data; + +typedef krb5_authenticator_data *krb5_authenticator; + +typedef struct krb5_rcache{ + int dummy; +}krb5_rcache; + +typedef struct krb5_ccache{ + krb5_data data; +}krb5_ccache; + +typedef struct krb5_fcache{ + char *filename; +}; + +typedef struct krb5_cc_cursor{ + int dummy; +}krb5_cc_cursor; + +typedef struct krb5_keytab{ + int dummy; +}krb5_keytab; + + +typedef struct krb5_auth_context{ + krb5_int32 flags; + krb5_cksumtype cksumtype; + + krb5_address local_address; + krb5_address remote_address; + krb5_keyblock key; + krb5_keyblock local_subkey; + krb5_keyblock remote_subkey; + + krb5_int32 local_seqnumber; + krb5_int32 remote_seqnumber; + + krb5_authenticator authenticator; + + krb5_pointer i_vector; + + krb5_rcache rcache; + +}krb5_auth_context; + + +typedef krb5_uint32 krb5_flags; + +typedef struct krb5_kdc_rep{ + int dummy; +}krb5_kdc_rep; + + +krb5_error_code +krb5_init_context(krb5_context *context); + + +krb5_error_code +krb5_get_cred_from_kdc(krb5_context, + krb5_ccache ccache, + krb5_creds *in_cred, + krb5_creds **out_cred, + krb5_creds **tgts); + + +krb5_error_code +krb5_get_credentials(krb5_context context, + krb5_flags options, + krb5_ccache ccache, + krb5_creds *in_creds, + krb5_creds *out_creds); + +typedef krb5_error_code (*krb5_key_proc)(krb5_context context, + const 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_kdc_rep *dec_rep); + +krb5_error_code +krb5_get_in_tkt(krb5_context context, + krb5_flags options, + krb5_address *const *addrs, + const krb5_enctype *etypes, + const krb5_preauthtype *ptypes, + krb5_key_proc key_proc, + krb5_const_pointer keyseed, + krb5_decrypt_proc decrypt_proc, + krb5_const_pointer decryptarg, + krb5_creds *creds, + krb5_ccache ccache, + krb5_kdc_rep **ret_as_reply); + + +krb5_error_code +krb5_mk_req(krb5_context context, + krb5_auth_context **auth_context, + const krb5_flags ap_req_options, + char *service, + char *hostname, + krb5_data *in_data, + krb5_ccache ccache, + krb5_data *outbuf); + +krb5_error_code +krb5_generate_subkey(krb5_context context, + const krb5_keyblock *key, + krb5_keyblock **subkey); + + +krb5_error_code +krb5_rd_req(krb5_context context, + krb5_auth_context **auth_context, + const krb5_data *inbuf, + krb5_const_principal server, + krb5_keytab keytab, + krb5_flags *ap_req_options, + krb5_ticket **ticket); + + +krb5_error_code +krb5_parse_name(krb5_context context, + const char *name, + krb5_principal *principal); + +void +krb5_free_principal(krb5_principal principal); + +krb5_error_code +krb5_unparse_name(krb5_context context, + krb5_principal principal, + char **name); + +krb5_error_code +krb5_unparse_name_ext(krb5_context context, + krb5_const_principal principal, + char **name, + size_t *size); + +krb5_data* +krb5_princ_realm(krb5_context context, + krb5_principal principal); + +void +krb5_princ_set_realm(krb5_context context, + krb5_principal principal, + krb5_data *realm); + +krb5_error_code +krb5_build_principal(krb5_context context, + krb5_principal *principal, + int rlen, + const char *realm, + ...); + +krb5_error_code +krb5_build_principal_va(krb5_context context, + krb5_principal *principal, + int rlen, + const char *realm, + va_list ap); + +krb5_error_code +krb5_build_principal_ext(krb5_context context, + krb5_principal *principal, + int rlen, + const char *realm, + ...); + +krb5_error_code +krb5_copy_principal(krb5_context context, + krb5_const_principal inprinc, + krb5_principal *outprinc); + +krb5_boolean +krb5_principal_compare(krb5_context context, + krb5_const_principal princ1, + krb5_const_principal princ2); + +krb5_boolean +krb5_realm_compare(krb5_context context, + krb5_const_principal princ1, + krb5_const_principal princ2); + +krb5_error_code +krb5_425_conv_principal(krb5_context context, + const char *name, + const char *instance, + const char *realm, + krb5_principal *princ); + +#endif /* __KRB5_H__ */ + diff --git a/lib/krb5/krb5_error.h b/lib/krb5/krb5_error.h new file mode 100644 index 000000000..20316f8c2 --- /dev/null +++ b/lib/krb5/krb5_error.h @@ -0,0 +1,52 @@ +#ifndef __KRB5_ERROR_H__ +#define __KRB5_ERROR_H__ + +#define KDC_ERR_NONE 0 +#define KDC_ERR_NAME_EXP 1 +#define KDC_ERR_SERVICE_EXP 2 +#define KDC_ERR_BAD_PVNO 3 +#define KDC_ERR_C_OLD_MAST_KVNO 4 +#define KDC_ERR_S_OLD_MAST_KVNO 5 +#define KDC_ERR_C_PRINCIPAL_UNKNOWN 6 +#define KDC_ERR_S_PRINCIPAL_UNKNOWN 7 +#define KDC_ERR_PRINCIPAL_NOT_UNIQUE 8 +#define KDC_ERR_NULL_KEY 9 +#define KDC_ERR_CANNOT_POSTDATE 10 +#define KDC_ERR_NEVER_VALID 11 +#define KDC_ERR_POLICY 12 +#define KDC_ERR_BADOPTION 13 +#define KDC_ERR_ETYPE_NOSUPP 14 +#define KDC_ERR_SUMTYPE_NOSUPP 15 +#define KDC_ERR_PADATA_TYPE_NOSUPP 16 +#define KDC_ERR_TRTYPE_NOSUPP 17 +#define KDC_ERR_CLIENT_REVOKED 18 +#define KDC_ERR_SERVICE_REVOKED 19 +#define KDC_ERR_TGT_REVOKED 20 +#define KDC_ERR_CLIENT_NOTYET 21 +#define KDC_ERR_SERVICE_NOTYET 22 +#define KDC_ERR_KEY_EXPIRED 23 +#define KDC_ERR_PREAUTH_FAILED 24 +#define KDC_ERR_PREAUTH_REQUIRED 25 +#define KRB_AP_ERR_BAD_INTEGRITY 31 +#define KRB_AP_ERR_TKT_EXPIRED 32 +#define KRB_AP_ERR_TKT_NYV 33 +#define KRB_AP_ERR_REPEAT 34 +#define KRB_AP_ERR_NOT_US 35 +#define KRB_AP_ERR_BADMATCH 36 +#define KRB_AP_ERR_SKEW 37 +#define KRB_AP_ERR_BADADDR 38 +#define KRB_AP_ERR_BADVERSION 39 +#define KRB_AP_ERR_MSG_TYPE 40 +#define KRB_AP_ERR_MODIFIED 41 +#define KRB_AP_ERR_BADORDER 42 +#define KRB_AP_ERR_BADKEYVER 44 +#define KRB_AP_ERR_NOKEY 45 +#define KRB_AP_ERR_MUT_FAIL 46 +#define KRB_AP_ERR_BADDIRECTION 47 +#define KRB_AP_ERR_METHOD 48 +#define KRB_AP_ERR_BADSEQ 49 +#define KRB_AP_ERR_INAPP_CKSUM 50 +#define KRB_ERR_GENERIC 60 +#define KRB_ERR_FIELD_TOOLONG 61 + +#endif /* __KRB5_ERROR_H__ */ diff --git a/lib/krb5/krb5_locl.h b/lib/krb5/krb5_locl.h new file mode 100644 index 000000000..5ab659129 --- /dev/null +++ b/lib/krb5/krb5_locl.h @@ -0,0 +1,30 @@ +#ifndef __KRB5_LOCL_H__ +#define __KRB5_LOCL_H__ + +#include +#include +#include +#include +#include + +#include "krb5.h" + +void krb5_data_free(krb5_data *); +krb5_error_code krb5_data_alloc(krb5_data *, int); +krb5_error_code krb5_data_realloc(krb5_data *, int); +krb5_error_code krb5_data_copy(krb5_data *, void *, size_t); + + +krb5_error_code krb5_principal_alloc(krb5_principal*); +void krb5_principal_free(krb5_principal); + +krb5_error_code krb5_get_lrealm(char ** realm); + + + +#define ALLOC(N, X) ((X*)malloc((N) * sizeof(X))) +#define FREE(X) do{if(X)free(X);}while(0) + +#define RCSID(X) static char *rcsid[] = { (char*)rcsid, X } + +#endif /* __KRB5_LOCL_H__ */ diff --git a/lib/krb5/misc.c b/lib/krb5/misc.c new file mode 100644 index 000000000..37e8e153a --- /dev/null +++ b/lib/krb5/misc.c @@ -0,0 +1,27 @@ +#include "krb5_locl.h" + + +krb5_error_code +krb5_get_lrealm(char **realm) +{ + FILE *F; + char s[128]; + char *p, *q; + F = fopen("/etc/krb5.conf", "r"); + while(fgets(s, 128, F)){ + if((p = strstr(s, "default_realm"))){ + p = strchr(p, '='); + p++; + while(isspace(*p)) p++; + q = p; + while(isalnum(*p) || strchr("_.-", *p)) p++; + *p=0; + *realm = strdup(q); + fclose(F); + return 0; + } + } + fclose(F); + *realm = 0; + return 0; +} diff --git a/lib/krb5/principal.c b/lib/krb5/principal.c new file mode 100644 index 000000000..a6c407110 --- /dev/null +++ b/lib/krb5/principal.c @@ -0,0 +1,349 @@ +#include "krb5_locl.h" + +RCSID("$Id$"); + +/* Public principal handling functions */ + +void +krb5_free_principal(krb5_principal p) +{ + krb5_principal_free(p); +} + +krb5_error_code +krb5_parse_name(krb5_context context, + const char *name, + krb5_principal *principal) +{ + + krb5_data *comp; + int ncomp; + krb5_data realm; + + char *p; + char *q; + char *s; + char *start; + + int n; + char c; + int got_realm = 0; + + /* count number of component */ + ncomp = 1; + for(p = (char*)name; *p; p++){ + if(*p=='\\'){ + if(!p[1]) + return KRB5_PARSE_MALFORMED; + p++; + } else if(*p == '/') + ncomp++; + } + comp = ALLOC(ncomp, krb5_data); + + n = 0; + start = q = p = s = strdup(name); + while(*p){ + c = *p++; + if(c == '\\'){ + c = *p++; + if(c == 'n') + c = '\n'; + else if(c == 't') + c = '\t'; + else if(c == 'b') + c = '\b'; + else if(c == '0') + c = '\0'; + }else if(c == '/' || c == '@'){ + if(got_realm){ + while(n>0) + free(comp[--n].data); + free(comp); + free(s); + return KRB5_PARSE_MALFORMED; + }else{ + comp[n].length = q - start; + comp[n].data = (krb5_pointer)malloc(comp[n].length); + memmove(comp[n].data, start, comp[n].length); + n++; + } + if(c == '@') + got_realm = 1; + start = q; + continue; + } + if(got_realm && (c == ':' || c == '/' || c == '\0')){ + while(n>0) + free(comp[--n].data); + free(comp); + free(s); + return KRB5_PARSE_MALFORMED; + } + *q++ = c; + } + if(got_realm){ + realm.length = q - start; + realm.data = (krb5_pointer)malloc(realm.length); + memmove(realm.data, start, realm.length); + }else{ + comp[n].length = q - start; + comp[n].data = (krb5_pointer)malloc(comp[n].length); + memmove(comp[n].data, start, comp[n].length); + n++; + } + *principal = ALLOC(1, krb5_principal_data); + (*principal)->type = KRB5_NT_PRINCIPAL; + (*principal)->realm = realm; + (*principal)->comp = comp; + (*principal)->ncomp = n; + free(s); + return 0; +} + +static void quote_string(char *s, int len, char **out) +{ + char *q; + char *p = *out; + int c=0; + for(q = s; q < s + len; q++){ + if(*q == '\n') + c = 'n'; + else if(*q == '\t') + c = 't'; + else if(*q == '\b') + c = 'b'; + else if(*q == '\0') + c = '0'; + else if(*q == '/') + c='/'; + else if(*q == '@') + c = '@'; + if(c){ + *p++ = '\\'; + *p++ = c; + c = 0; + }else + *p++ = *q; + } + *out = p; +} + + +krb5_error_code +krb5_unparse_name(krb5_context context, + krb5_principal principal, + char **name) +{ + int size = 0; + char *p; + char *s; + int i; + for(i = 0; i < principal->ncomp; i++) + size += 2*principal->comp[i].length + 1; + size += 2*principal->realm.length + 1; + s = ALLOC(size, char); + p = s; + for(i = 0; i < principal->ncomp; i++){ + if(i) *p++ = '/'; + quote_string(principal->comp[i].data, principal->comp[i].length, &p); + } + *p++ = '@'; + quote_string(principal->realm.data, principal->realm.length, &p); + *p = 0; + *name = strdup(s); + free(s); + return 0; +} + + +krb5_error_code +krb5_unparse_name_ext(krb5_context context, + krb5_const_principal principal, + char **name, + size_t *size) +{ + fprintf(stderr, "krb5_unparse_name_ext: not implemented\n"); + abort(); +} + + +krb5_data* +krb5_princ_realm(krb5_context context, + krb5_principal principal) +{ + return &principal->realm; +} + + +void +krb5_princ_set_realm(krb5_context context, + krb5_principal principal, + krb5_data *realm) +{ + principal->realm = *realm; +} + + +krb5_error_code +krb5_build_principal(krb5_context context, + krb5_principal *principal, + int rlen, + const char *realm, + ...) +{ + krb5_error_code ret; + va_list ap; + va_start(ap, realm); + ret = krb5_build_principal_va(context, principal, rlen, realm, ap); + va_end(ap); + return ret; +} + +krb5_error_code +krb5_principal_set_component(krb5_principal p, int n, void *data, size_t len) +{ + krb5_data *tmp; + if(p->ncomp <= n){ + int s = n + 10; + if(p->comp) + tmp = (krb5_data*)realloc(p->comp, s * sizeof(krb5_data)); + else + tmp = ALLOC(s, krb5_data); + if(!tmp) + return ENOMEM; + p->comp = tmp; + p->ncomp = s; + } + krb5_data_copy(&p->comp[n], data, len); + return 0; +} + + +krb5_error_code +krb5_build_principal_va(krb5_context context, + krb5_principal *principal, + int rlen, + const char *realm, + va_list ap) +{ + krb5_principal p; + int n; + char *s; + + if(krb5_principal_alloc(&p)) + return ENOMEM; + p->type = KRB5_NT_PRINCIPAL; + + if(krb5_data_copy(&p->realm, (void*)realm, rlen)){ + free(p); + return ENOMEM; + } + + n = 0; + while(1){ + s = va_arg(ap, char*); + if(s == NULL) + break; + krb5_principal_set_component(p, n, s, strlen(s)); + n++; + } + p->ncomp = n; + *principal = p; + return 0; +} + + +krb5_error_code +krb5_build_principal_ext(krb5_context context, + krb5_principal *principal, + int rlen, + const char *realm, + ...) +{ + fprintf(stderr, "krb5_build_principal_ext: not implemented\n"); + abort(); +} + + +krb5_error_code +krb5_copy_principal(krb5_context context, + krb5_const_principal inprinc, + krb5_principal *outprinc) +{ + krb5_principal p; + int i; + if(krb5_principal_alloc(&p)) + return ENOMEM; + p->type = inprinc->type; + if(krb5_data_copy(&p->realm, inprinc->realm.data, inprinc->realm.length)){ + krb5_free_principal(p); + return ENOMEM; + } + p->comp = ALLOC(inprinc->ncomp, krb5_data); + if(!p->comp){ + krb5_free_principal(p); + return ENOMEM; + } + + for(i=0; incomp; i++){ + if(krb5_data_copy(&p->comp[i], inprinc->comp[i].data, + inprinc->comp[i].length)){ + krb5_free_principal(p); + return ENOMEM; + } + p->ncomp = i+1; + } + return 0; +} + + +krb5_boolean +krb5_principal_compare(krb5_context context, + krb5_const_principal princ1, + krb5_const_principal princ2) +{ + int i; + if(!krb5_realm_compare(context, princ1, princ2)) + return FALSE; + if(princ1->ncomp != princ2->ncomp) + return FALSE; + for(i=0; incomp; i++){ + if(princ1->comp[i].length != princ2->comp[i].length) + return FALSE; + if(memcmp(princ1->comp[i].data, princ2->comp[i].data, + princ1->comp[i].length)) + return FALSE; + } + return TRUE; +} + + +krb5_boolean +krb5_realm_compare(krb5_context context, + krb5_const_principal princ1, + krb5_const_principal princ2) +{ + if(princ1->realm.length != princ2->realm.length) + return FALSE; + if(memcmp(princ1->realm.data, princ2->realm.data, princ1->realm.length)) + return FALSE; + return TRUE; +} + + +krb5_error_code +krb5_425_conv_principal(krb5_context context, + const char *name, + const char *instance, + const char *realm, + krb5_principal *princ) +{ + if(!strcmp(name, "rcmd")) + name = "host"; + return krb5_build_principal(context, princ, + strlen(realm), realm, name, instance, 0); +} + + + diff --git a/lib/krb5/principal.h b/lib/krb5/principal.h new file mode 100644 index 000000000..e2e4a4f71 --- /dev/null +++ b/lib/krb5/principal.h @@ -0,0 +1,6 @@ +#ifndef __PRINCIPAL_H__ +#define __PRINCIPAL_H__ + +#include "krb5.h" + +#endif /* __PRINCIPAL_H__ */ diff --git a/lib/krb5/principal_p.c b/lib/krb5/principal_p.c new file mode 100644 index 000000000..91362aefe --- /dev/null +++ b/lib/krb5/principal_p.c @@ -0,0 +1,24 @@ +#include "krb5_locl.h" + +krb5_error_code +krb5_principal_alloc(krb5_principal *p) +{ + krb5_principal tmp; + tmp = ALLOC(1, krb5_principal_data); + if(!tmp) + return ENOMEM; + memset(tmp, 0, sizeof(krb5_principal_data)); + *p = tmp; + return 0; +} + +void +krb5_principal_free(krb5_principal principal) +{ + int i; + for(i = 0; i < principal->ncomp; i++) + krb5_data_free(&principal->comp[i]); + free(principal->comp); + krb5_data_free(&principal->realm); + free(principal); +} diff --git a/misc.c b/misc.c new file mode 100644 index 000000000..37e8e153a --- /dev/null +++ b/misc.c @@ -0,0 +1,27 @@ +#include "krb5_locl.h" + + +krb5_error_code +krb5_get_lrealm(char **realm) +{ + FILE *F; + char s[128]; + char *p, *q; + F = fopen("/etc/krb5.conf", "r"); + while(fgets(s, 128, F)){ + if((p = strstr(s, "default_realm"))){ + p = strchr(p, '='); + p++; + while(isspace(*p)) p++; + q = p; + while(isalnum(*p) || strchr("_.-", *p)) p++; + *p=0; + *realm = strdup(q); + fclose(F); + return 0; + } + } + fclose(F); + *realm = 0; + return 0; +} diff --git a/principal.c b/principal.c new file mode 100644 index 000000000..a6c407110 --- /dev/null +++ b/principal.c @@ -0,0 +1,349 @@ +#include "krb5_locl.h" + +RCSID("$Id$"); + +/* Public principal handling functions */ + +void +krb5_free_principal(krb5_principal p) +{ + krb5_principal_free(p); +} + +krb5_error_code +krb5_parse_name(krb5_context context, + const char *name, + krb5_principal *principal) +{ + + krb5_data *comp; + int ncomp; + krb5_data realm; + + char *p; + char *q; + char *s; + char *start; + + int n; + char c; + int got_realm = 0; + + /* count number of component */ + ncomp = 1; + for(p = (char*)name; *p; p++){ + if(*p=='\\'){ + if(!p[1]) + return KRB5_PARSE_MALFORMED; + p++; + } else if(*p == '/') + ncomp++; + } + comp = ALLOC(ncomp, krb5_data); + + n = 0; + start = q = p = s = strdup(name); + while(*p){ + c = *p++; + if(c == '\\'){ + c = *p++; + if(c == 'n') + c = '\n'; + else if(c == 't') + c = '\t'; + else if(c == 'b') + c = '\b'; + else if(c == '0') + c = '\0'; + }else if(c == '/' || c == '@'){ + if(got_realm){ + while(n>0) + free(comp[--n].data); + free(comp); + free(s); + return KRB5_PARSE_MALFORMED; + }else{ + comp[n].length = q - start; + comp[n].data = (krb5_pointer)malloc(comp[n].length); + memmove(comp[n].data, start, comp[n].length); + n++; + } + if(c == '@') + got_realm = 1; + start = q; + continue; + } + if(got_realm && (c == ':' || c == '/' || c == '\0')){ + while(n>0) + free(comp[--n].data); + free(comp); + free(s); + return KRB5_PARSE_MALFORMED; + } + *q++ = c; + } + if(got_realm){ + realm.length = q - start; + realm.data = (krb5_pointer)malloc(realm.length); + memmove(realm.data, start, realm.length); + }else{ + comp[n].length = q - start; + comp[n].data = (krb5_pointer)malloc(comp[n].length); + memmove(comp[n].data, start, comp[n].length); + n++; + } + *principal = ALLOC(1, krb5_principal_data); + (*principal)->type = KRB5_NT_PRINCIPAL; + (*principal)->realm = realm; + (*principal)->comp = comp; + (*principal)->ncomp = n; + free(s); + return 0; +} + +static void quote_string(char *s, int len, char **out) +{ + char *q; + char *p = *out; + int c=0; + for(q = s; q < s + len; q++){ + if(*q == '\n') + c = 'n'; + else if(*q == '\t') + c = 't'; + else if(*q == '\b') + c = 'b'; + else if(*q == '\0') + c = '0'; + else if(*q == '/') + c='/'; + else if(*q == '@') + c = '@'; + if(c){ + *p++ = '\\'; + *p++ = c; + c = 0; + }else + *p++ = *q; + } + *out = p; +} + + +krb5_error_code +krb5_unparse_name(krb5_context context, + krb5_principal principal, + char **name) +{ + int size = 0; + char *p; + char *s; + int i; + for(i = 0; i < principal->ncomp; i++) + size += 2*principal->comp[i].length + 1; + size += 2*principal->realm.length + 1; + s = ALLOC(size, char); + p = s; + for(i = 0; i < principal->ncomp; i++){ + if(i) *p++ = '/'; + quote_string(principal->comp[i].data, principal->comp[i].length, &p); + } + *p++ = '@'; + quote_string(principal->realm.data, principal->realm.length, &p); + *p = 0; + *name = strdup(s); + free(s); + return 0; +} + + +krb5_error_code +krb5_unparse_name_ext(krb5_context context, + krb5_const_principal principal, + char **name, + size_t *size) +{ + fprintf(stderr, "krb5_unparse_name_ext: not implemented\n"); + abort(); +} + + +krb5_data* +krb5_princ_realm(krb5_context context, + krb5_principal principal) +{ + return &principal->realm; +} + + +void +krb5_princ_set_realm(krb5_context context, + krb5_principal principal, + krb5_data *realm) +{ + principal->realm = *realm; +} + + +krb5_error_code +krb5_build_principal(krb5_context context, + krb5_principal *principal, + int rlen, + const char *realm, + ...) +{ + krb5_error_code ret; + va_list ap; + va_start(ap, realm); + ret = krb5_build_principal_va(context, principal, rlen, realm, ap); + va_end(ap); + return ret; +} + +krb5_error_code +krb5_principal_set_component(krb5_principal p, int n, void *data, size_t len) +{ + krb5_data *tmp; + if(p->ncomp <= n){ + int s = n + 10; + if(p->comp) + tmp = (krb5_data*)realloc(p->comp, s * sizeof(krb5_data)); + else + tmp = ALLOC(s, krb5_data); + if(!tmp) + return ENOMEM; + p->comp = tmp; + p->ncomp = s; + } + krb5_data_copy(&p->comp[n], data, len); + return 0; +} + + +krb5_error_code +krb5_build_principal_va(krb5_context context, + krb5_principal *principal, + int rlen, + const char *realm, + va_list ap) +{ + krb5_principal p; + int n; + char *s; + + if(krb5_principal_alloc(&p)) + return ENOMEM; + p->type = KRB5_NT_PRINCIPAL; + + if(krb5_data_copy(&p->realm, (void*)realm, rlen)){ + free(p); + return ENOMEM; + } + + n = 0; + while(1){ + s = va_arg(ap, char*); + if(s == NULL) + break; + krb5_principal_set_component(p, n, s, strlen(s)); + n++; + } + p->ncomp = n; + *principal = p; + return 0; +} + + +krb5_error_code +krb5_build_principal_ext(krb5_context context, + krb5_principal *principal, + int rlen, + const char *realm, + ...) +{ + fprintf(stderr, "krb5_build_principal_ext: not implemented\n"); + abort(); +} + + +krb5_error_code +krb5_copy_principal(krb5_context context, + krb5_const_principal inprinc, + krb5_principal *outprinc) +{ + krb5_principal p; + int i; + if(krb5_principal_alloc(&p)) + return ENOMEM; + p->type = inprinc->type; + if(krb5_data_copy(&p->realm, inprinc->realm.data, inprinc->realm.length)){ + krb5_free_principal(p); + return ENOMEM; + } + p->comp = ALLOC(inprinc->ncomp, krb5_data); + if(!p->comp){ + krb5_free_principal(p); + return ENOMEM; + } + + for(i=0; incomp; i++){ + if(krb5_data_copy(&p->comp[i], inprinc->comp[i].data, + inprinc->comp[i].length)){ + krb5_free_principal(p); + return ENOMEM; + } + p->ncomp = i+1; + } + return 0; +} + + +krb5_boolean +krb5_principal_compare(krb5_context context, + krb5_const_principal princ1, + krb5_const_principal princ2) +{ + int i; + if(!krb5_realm_compare(context, princ1, princ2)) + return FALSE; + if(princ1->ncomp != princ2->ncomp) + return FALSE; + for(i=0; incomp; i++){ + if(princ1->comp[i].length != princ2->comp[i].length) + return FALSE; + if(memcmp(princ1->comp[i].data, princ2->comp[i].data, + princ1->comp[i].length)) + return FALSE; + } + return TRUE; +} + + +krb5_boolean +krb5_realm_compare(krb5_context context, + krb5_const_principal princ1, + krb5_const_principal princ2) +{ + if(princ1->realm.length != princ2->realm.length) + return FALSE; + if(memcmp(princ1->realm.data, princ2->realm.data, princ1->realm.length)) + return FALSE; + return TRUE; +} + + +krb5_error_code +krb5_425_conv_principal(krb5_context context, + const char *name, + const char *instance, + const char *realm, + krb5_principal *princ) +{ + if(!strcmp(name, "rcmd")) + name = "host"; + return krb5_build_principal(context, princ, + strlen(realm), realm, name, instance, 0); +} + + + diff --git a/principal.h b/principal.h new file mode 100644 index 000000000..e2e4a4f71 --- /dev/null +++ b/principal.h @@ -0,0 +1,6 @@ +#ifndef __PRINCIPAL_H__ +#define __PRINCIPAL_H__ + +#include "krb5.h" + +#endif /* __PRINCIPAL_H__ */ diff --git a/principal_p.c b/principal_p.c new file mode 100644 index 000000000..91362aefe --- /dev/null +++ b/principal_p.c @@ -0,0 +1,24 @@ +#include "krb5_locl.h" + +krb5_error_code +krb5_principal_alloc(krb5_principal *p) +{ + krb5_principal tmp; + tmp = ALLOC(1, krb5_principal_data); + if(!tmp) + return ENOMEM; + memset(tmp, 0, sizeof(krb5_principal_data)); + *p = tmp; + return 0; +} + +void +krb5_principal_free(krb5_principal principal) +{ + int i; + for(i = 0; i < principal->ncomp; i++) + krb5_data_free(&principal->comp[i]); + free(principal->comp); + krb5_data_free(&principal->realm); + free(principal); +} diff --git a/string2key.c b/string2key.c new file mode 100644 index 000000000..340a7df41 --- /dev/null +++ b/string2key.c @@ -0,0 +1,87 @@ +#include "krb5_locl.h" + +static void reverse(unsigned char *p) +{ + unsigned char tmp[8]; + unsigned int a, b; + int i; + + a = 0; + b = *(unsigned int*)p; + for(i = 0; i < 32; i++){ + a >>= 1; + a |= b & 0x80000000; + b <<= 1; + } + *(unsigned int*)(tmp + 4) = a; + + a = 0; + b = *(unsigned int*)(p + 4); + for(i = 0; i < 32; i++){ + a >>= 1; + a |= b & 0x80000000; + b <<= 1; + } + *(unsigned int*)tmp = a; + + a = 0; + b = 0; + memmove(p, tmp, 8); + memset(tmp, 0, 8); +} + + +krb5_error_code +mit_des_string_to_key(const krb5_keytype keytype, + krb5_keyblock *keyblock, + krb5_data *data, + krb5_data *salt) +{ + unsigned char *p; + unsigned char *key; + unsigned char tmp[8]; + + int len; + int i, j; + int odd = 0; + + len = data->length; + if(salt) + len += salt->length; + len = (len / 8 + 1) * 8; + p = (unsigned char*)malloc(len); + memset(p, 0, len); + memmove(p, data->data, data->length); + if(salt) + memmove(p + data->length, salt->data, salt->length); + + memset(key, 0, 8); + + for(i = 0; i < len; i += 8){ + memmove(tmp, p + i, 8); + if(odd) + reverse(tmp); +#ifndef RFC1510 + else + for(j = 0; j < 8; j++) tmp[j] <<= 1; +#endif + for(j = 0; j < 8; j++) + key[j] ^= tmp[j]; + odd = !odd; + } + + des_set_odd_parity(key); + des_key_schedule(key, &sched); + des_cbc_cksum(key, key, 8, &sched, key); + des_set_odd_parity(key); + if(des_is_weak_key(key)) + key[8] ^= 0xf0; + memset(p, 0, len); + memset(tmp, 0, 8); + free(p); + keyblock->keytype = KEYTYPE_DES; + keyblock->contents.data = key; + keyblock->contents.length = 8; + + return 0; +} diff --git a/test.c b/test.c new file mode 100644 index 000000000..0b82938a3 --- /dev/null +++ b/test.c @@ -0,0 +1,13 @@ +#include +#include "krb5.h" +#include "config_file.h" + +int main(int argc, char **argv) +{ + krb5_config_file *cf; + char *p; + krb5_parse_config_file(&cf, "krb5.conf"); + krb5_get_config_tag(cf, "realms ATHENA.MIT.EDU v4_instance_convert mit", &p); + + return 0; +} diff --git a/xxx b/xxx new file mode 100644 index 000000000..c9aff2011 --- /dev/null +++ b/xxx @@ -0,0 +1,312 @@ +krb5_get_in_tkt() +krb5_get_in_tkt_with_password() + +krb5_send_tgs() + +KDC_OPT_FORWARDABLE +KDC_OPT_FORWARDED +KDC_OPT_PROXIABLE +KDC_OPT_PROXY +KDC_OPT_ALLOW_POSTDATE +KDC_OPT_POSTDATED +KDC_OPT_RENEWABLE +KDC_OPT_RENEWABLE_OK +KDC_OPT_ENC_TKT_IN_SKEY +KDC_OPT_RENEW +KDC_OPT_VALIDATE + + +KRB5_PADATA_NONE +KRB5_PADATA_AP_REQ +KRB5_PADATA_TGS_REQ +KRB5_PADATA_PW_SALT +KRB5_PADATA_ENC_TIMESTAMP +KRB5_PADATA_ENC_SECURID + +KRB5_AUTH_CONTEXT_DO_TIME +KRB5_AUTH_CONTEXT_RET_TIME +KRB5_AUTH_CONTEXT_DO_SEQUENCE +KRB5_AUTH_CONTEXT_RET_REQUENCE + +/* types */ +krb5_error_code; +krb5_context; + +typedef struct krb5_auth_context{ + krb5_int32 flags; + krb5_cksumtype cksumtype; + + krb5_address local_address; + krb5_address remote_address; + krb5_keyblock key; + krb5_keyblock local_subkey; + krb5_keyblock remote_subkey; + + krb5_int32 local_seqnumber; + krb5_int32 remote_seqnumber; + + krb5_authenticator authenticator; + + krb5_pointer i_vector; + + krb5_rcache rcache; + +}krb5_auth_context; + +enum krb5_enc_type; + +krb5_int32; +krb5_address; + +krb5_error_code +krb5_init_context(krb5_context *context); + +void krb5_os_free_context(krb5_context context); +void krb5_free_context(krb5_context context); + +krb5_error_code +krb5_set_default_in_tkt_etypes(krb5_context context, + const krb5_enc_type *etypes); + + +krb5_error_code +krb5_get_default_in_tkt_etypes(krb5_context context, + krb5_enctype **etypes); + +krb5_error_code +krb5_auth_con_init(krb5_context context, + krb5_auth_context **auth_context); + +krb5_error_code +krb5_auth_con_free(krb5_context context, + krb5_auth_context *auth_context); + +krb5_error_code +krb5_auth_con_setflags(krb5_context context, + krb5_auth_context *auth_context, + krb5_int32 flags); + +krb5_error_code +krb5_auth_con_getflags(krb5_context context, + krb5_auth_context *auth_context, + krb5_int32 *flags); + +krb5_error_code +krb5_auth_con_setaddrs(krb5_context context, + krb5_auth_context *auth_context, + krb5_address *local_addr, + krb5_address *remote_addr); + +krb5_error_code +krb5_auth_con_getaddrs(krb5_context context, + krb5_auth_context *auth_context, + krb5_address **local_addr, + krb5_address **remote_addr); + + +krb5_error_code +krb5_auth_con_setuserkey(krb5_context context, + krb5_auth_context *auth_context, + krb5_keyblock *keyblock); + +krb5_error_code +krb5_auth_con_getkey(krb5_context context, + krb5_auth_context *auth_context, + krb5_keyblock **keyblock); + +void +krb5_free_keyblock(krb5_keyblock *keyblock); /* ??? */ + +krb5_error_code +krb5_auth_setcksumtype(krb5_context context, + krb5_auth_context *auth_context, + krb5_cksumtype cksumtype); + +krb5_error_code +krb5_auth_getlocalseqnumber(krb5_context context, + krb5_auth_context *auth_context, + krb5_int32 *seqnumber); + +krb5_error_code +krb5_auth_getremoteseqnumber(krb5_context context, + krb5_auth_context *auth_context, + krb5_int32 *seqnumber); + +krb5_error_code +krb5_auth_getauthenticator(krb5_context context, + krb5_auth_context *auth_context, + krb5_authenticator **authenticator); + +void +krb5_free_authenticator(krb5_authenticator *authenticator); /* ??? */ + +krb5_error_code +krb5_auth_initvector(krb5_context context, + krb5_auth_context *auth_context); + +krb5_error_code +krb5_set_initvector(krb5_context context, + krb5_auth_context *auth_context, + krb5_pointer ivector); + +krb5_error_code +krb5_set_rcache(krb5_context context, + krb5_auth_context *auth_context, + krb5_rcache rcache); + + + +KRB5_PARSE_MALFORMED + +typedef struct krb5_principal{ + +}krb5_principal; + +krb5_err_code +krb5_parse_name(krb5_context context, + const char *name, + krb5_principal *principal); + +void +krb5_free_principal(krb5_principal *principal); + +krb5_error_code +krb5_unparse_name(krb5_context context, + krb5_const_principal principal, + char **name); + +krb5_error_code +krb5_unparse_name_ext(krb5_context context, + krb5_const_principal principal, + char **name, + int *size); +krb5_data +krb5_princ_realm(krb5_context context, + krb5_principal principal); + +krb5_data +krb5_princ_set_realm(krb5_context context, + krb5_principal principal, + krb5_data *realm); + +krb5_error_code +krb5_build_principal(krb5_context context, + krb5_principal *principal, + int rlen, + const char *realm, + ...); + +krb5_error_code +krb5_build_principal(krb5_context context, + krb5_principal *principal, + int rlen, + const char *realm, + va_list ap); + +krb5_error_code +krb5_copy_principal(krb5_context *context, + krb5_const_principal inprinc, + krb5_principal *outprinc); + +krb5_boolean +krb5_principal_compare(krb5_context context, + krb5_const_principal princ1, + krb5_const_principal princ2); + +krb5_boolean +krb5_realm_compare(krb5_context context, + krb5_const_principal princ1, + krb5_const_principal princ2); + +krb5_error_code +krb5_425_conv_principal(krb5_context context, + const char *name, + const char *instance, + const char *realm, + krb5_principal *principal); + +krb5_error_code +krb5_get_cred_from_kdc(krb5_context, + krb5_ccache ccache, + krb5_creds *in_cred, + krb5_cred **out_cred, + krb5_creds **tgts); + + +krb5_keyblock{ + krb5_keytype keytype; +}; + +krb5_times{ + krb5_time endtime; + krb5_time starttime; + krb5_time renew_till; +}; + +struct krb5_creds { + krb5_principal client; /* ? */ + krb5_principal server; /* ? */ + krb5_times times; + krb5_keyblock keyblock + second_ticket; + krb5_data authdata; + +}; + +krb5_error_code +krb5_get_credentials(krb5_context context, + krb5_flags options, + krb5_ccache ccache, + krb5_creds *in_creds, + krb5_creds *out_creds); + +typedef krb5_error_code (*krb5_key_proc)(krb5_context context, + const 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_kdc_rep *dec_rep); + +krb5_error_code +krb5_get_in_tkt(krb5_context context, + krb5_flags options, + krb5_address *const *addrs, + const krb5_enctype *etypes, + const krb5_preauthtype *ptypes, + krb5_key_proc key_proc, + krb5_const_pointer keyseed, + krb5_decrypt_proc decrypt_proc, + krb5_const_pointer decryptarg, + krb5_creds *creds, + krb5_ccache ccache, + krb5_kdc_rep **ret_as_reply); + + +krb5_error_code +krb5_mk_req(krb5_context context, + krb5_auth_context **auth_context, + const krb5_flags ap_req_options, + char *service, + char *hostname, + krb5_data *in_data, + krb5_ccache ccache, + krb5_data *outbuf); + +krb5_error_code +krb5_generate_subkey(krb5_context context, + const krb5_keyblock *key, + krb5_keyblock **subkey); + + +krb5_error_code +krb5_rd_req(krb5_context context, + krb5_auth_context **auth_context, + const krb5_data *inbuf, + krb5_const_principal server, + krb5_keytab keytab, + krb5_flags *ap_req_options, + krb5_ticket **ticket); +