diff options
author | Karl Ramm <kcr@mit.edu> | 2007-12-25 00:56:08 +0000 |
---|---|---|
committer | Karl Ramm <kcr@mit.edu> | 2007-12-25 00:56:08 +0000 |
commit | 1a0e03eb19998ab496a6ea845ff2c42d9a02df0b (patch) | |
tree | 29b47c8532e1f1678063fbb1b851ee4208134626 /server | |
parent | 3f120f880be9ae9aa1612ddc2412e9acb9a8e85e (diff) |
applied athena-update-branch patch
Diffstat (limited to 'server')
-rw-r--r-- | server/bdump.c | 229 | ||||
-rw-r--r-- | server/class.c | 12 | ||||
-rw-r--r-- | server/client.c | 10 | ||||
-rw-r--r-- | server/dispatch.c | 60 | ||||
-rw-r--r-- | server/kstuff.c | 811 | ||||
-rw-r--r-- | server/main.c | 44 | ||||
-rw-r--r-- | server/realm.c | 384 | ||||
-rw-r--r-- | server/server.c | 8 | ||||
-rw-r--r-- | server/subscr.c | 88 | ||||
-rw-r--r-- | server/uloc.c | 17 | ||||
-rw-r--r-- | server/zserver.h | 68 | ||||
-rw-r--r-- | server/zsrv_conf.h | 4 | ||||
-rw-r--r-- | server/zsrv_err.et | 2 |
13 files changed, 1311 insertions, 426 deletions
diff --git a/server/bdump.c b/server/bdump.c index 22bf518..d997672 100644 --- a/server/bdump.c +++ b/server/bdump.c @@ -66,6 +66,12 @@ static int setup_file_pointers __P((void)); static void shutdown_file_pointers __P((void)); static void cleanup __P((Server *server)); +#ifdef HAVE_KRB5 +static long ticket5_time; +#define TKT5LIFETIME 8*60*60 +#define tkt5_lifetime(val) (val) +#endif + #ifdef HAVE_KRB4 static long ticket_time; @@ -272,7 +278,12 @@ bdump_send() } /* Now begin the brain dump. */ - +#ifdef HAVE_KRB5 + { /* "server" side */ + krb5_auth_context actx; + + } +#else /* HAVE_KRB5 */ #ifdef HAVE_KRB4 /* receive the authenticator */ retval = GetKerberosData(live_socket, from.sin_addr, &kdata, @@ -311,6 +322,7 @@ bdump_send() return; } #endif /* HAVE_KRB4 */ +#endif /* HAVE_KRB5 */ retval = setup_file_pointers(); if (retval != 0) { @@ -450,6 +462,109 @@ bdump_get_v12 (notice, auth, who, server) /* Now begin the brain dump. */ +#ifdef HAVE_KRB5 + if (get_tgt()) { + cleanup(server); + return; + } + { /* "client" side */ + krb5_auth_context actx; + krb5_creds creds; + krb5_creds *credsp; + krb5_principal principal; + krb5_data data; + krb5_ap_rep_enc_part *rep; + + memset((char *)&creds, 0, sizeof(creds)); + + retval = krb5_build_principal(Z_krb5_ctx, &principal, + strlen(ZGetRealm()), + ZGetRealm(), + SERVER_KRB5_SERVICE, SERVER_INSTANCE, + 0); + if (retval) { + syslog(LOG_ERR, "bdump_get: krb5_build_principal: %s", error_message(retval)); + cleanup(server); + return; + } + + retval = krb5_copy_principal(Z_krb5_ctx, principal, &creds.server); + if (retval) { + syslog(LOG_ERR, "bdump_get: krb5_copy_principal (server): %s", error_message(retval)); + krb5_free_principal(Z_krb5_ctx, principal); + cleanup(server); + return; + } + + retval = krb5_copy_principal(Z_krb5_ctx, principal, &creds.client); + krb5_free_principal(Z_krb5_ctx, principal); + if (retval) { + syslog(LOG_ERR, "bdump_get: krb5_copy_principal (client): %s", error_message(retval)); + krb5_free_cred_contents(Z_krb5_ctx, &creds); + cleanup(server); + return; + } + + retval = krb5_get_credentials(Z_krb5_ctx, 0, Z_krb5_ccache, + &creds, &credsp); + krb5_free_cred_contents(Z_krb5_ctx, &creds); + if (retval) { + syslog(LOG_ERR, "bdump_get: krb5_get_credentials: %s", error_message(retval)); + cleanup(server); + return; + } + + retval = krb5_auth_con_init(Z_krb5_ctx, &actx); + if (retval) { + syslog(LOG_ERR, "bdump_get: krb5_auth_con_init: %s", error_message(retval)); + krb5_free_creds(Z_krb5_ctx, credsp); + cleanup(server); + return; + } + + memset((char *)&data, 0, sizeof(krb5_data)); + retval = krb5_mk_req_extended(Z_krb5_ctx, &actx, AP_OPTS_MUTUAL_REQUIRED|AP_OPTS_USE_SUBKEY, + NULL, credsp, &data); + if (retval) { + syslog(LOG_ERR, "bdump_get: krb5_mk_req_ext: %s", error_message(retval)); + krb5_auth_con_free(Z_krb5_ctx, actx); + krb5_free_creds(Z_krb5_ctx, credsp); + cleanup(server); + return; + } + retval = SendKrb5Data(live_socket, &data); + krb5_free_creds(Z_krb5_ctx, credsp); + if (retval) { + syslog(LOG_ERR, "bdump_get: cannot send authenticator: %s", + error_message(retval)); + krb5_free_data_contents(Z_krb5_ctx, &data); + krb5_auth_con_free(Z_krb5_ctx, actx); + cleanup(server); + return; + } + krb5_free_data_contents(Z_krb5_ctx, &data); + memset((char *)&data, 0, sizeof(krb5_data)); + retval = GetKrb5Data(live_socket, &data); + if (retval) { + syslog(LOG_ERR, "bdump_get: cannot get auth response: %s", + error_message(retval)); + krb5_auth_con_free(Z_krb5_ctx, actx); + cleanup(server); + return; + } + retval = krb5_rd_rep(Z_krb5_ctx, actx, &data, &rep); + free(data.data); + memset((char *)&data, 0, sizeof(krb5_data)); + if (retval) { + syslog(LOG_ERR, "bdump_get: mutual authentication failed: %s", + error_message(retval)); + krb5_auth_con_free(Z_krb5_ctx, actx); + cleanup(server); + return; + } + + } +#else #ifdef HAVE_KRB4 /* send an authenticator */ if (get_tgt()) { @@ -485,6 +600,7 @@ bdump_get_v12 (notice, auth, who, server) return; } #endif /* HAVE_KRB4 */ +#endif retval = setup_file_pointers(); if (retval != 0) { syslog(LOG_WARNING, "bdump_get: can't set up file pointers: %s", @@ -728,6 +844,54 @@ get_tgt() des_key_sched(serv_key, serv_ksched.s); #endif /* !NOENCRYPTION */ } +#ifdef HAVE_KRB5 + /* XXX */ + if (ticket5_time < NOW - tkt5_lifetime(TKT5LIFETIME) + (15L * 60L)) { + krb5_keytab kt; + krb5_get_init_creds_opt opt; + krb5_creds cred; + krb5_principal principal; + + memset(&cred, 0, sizeof(cred)); + + retval = krb5_build_principal(Z_krb5_ctx, &principal, + strlen(ZGetRealm()), + ZGetRealm(), + SERVER_KRB5_SERVICE, SERVER_INSTANCE, + 0); + if (retval) { + krb5_free_principal(Z_krb5_ctx, principal); + return(1); + } + + krb5_get_init_creds_opt_init (&opt); + krb5_get_init_creds_opt_set_tkt_life (&opt, TKT5LIFETIME); + + retval = krb5_kt_resolve(Z_krb5_ctx, keytab_file, &kt); + if (retval) return(1); + + retval = krb5_get_init_creds_keytab (Z_krb5_ctx, + &cred, + principal, + kt, + 0, + NULL, + &opt); + krb5_free_principal(Z_krb5_ctx, principal); + krb5_kt_close(Z_krb5_ctx, kt); + if (retval) return(1); + + retval = krb5_cc_initialize (Z_krb5_ctx, Z_krb5_ccache, cred.client); + if (retval) return(1); + + retval = krb5_cc_store_cred (Z_krb5_ctx, Z_krb5_ccache, &cred); + if (retval) return(1); + + ticket5_time = NOW; + + krb5_free_cred_contents (Z_krb5_ctx, &cred); + } +#endif return(0); } #endif /* HAVE_KRB4 */ @@ -771,11 +935,17 @@ bdump_recv_loop(server) Code_t retval; Client *client = NULL; struct sockaddr_in who; -#ifdef HAVE_KRB4 +#ifdef HAVE_KRB5 + char buf[512]; + int blen; +#endif +#if defined(HAVE_KRB4) || defined(HAVE_KRB5) char *cp; +#endif +#ifdef HAVE_KRB4 C_Block cblock; #endif /* HAVE_KRB4 */ - Realm *realm = NULL; + ZRealm *realm = NULL; #if 1 zdbug((LOG_DEBUG, "bdump recv loop")); @@ -853,6 +1023,52 @@ bdump_recv_loop(server) syslog(LOG_ERR,"brl failed: %s", error_message(retval)); return retval; } +#ifdef HAVE_KRB5 + client->session_keyblock = NULL; + if (*notice.z_class_inst) { + /* check out this session key I found */ + cp = notice.z_message + strlen(notice.z_message) + 1; + if (*cp == '0') { + /* ****ing netascii; this is an encrypted DES keyblock + XXX this code should be conditionalized for server + transitions */ + retval = krb5_init_keyblock(Z_krb5_ctx, ENCTYPE_DES_CBC_CRC, + sizeof(C_Block), + &client->session_keyblock); + if (retval) { + syslog(LOG_ERR, "brl failed to allocate DES keyblock: %s", + error_message(retval)); + return retval; + } + retval = ZReadAscii(cp, strlen(cp), cblock, sizeof(C_Block)); + if (retval != ZERR_NONE) { + syslog(LOG_ERR,"brl bad cblk read: %s (%s)", + error_message(retval), cp); + } else { + des_ecb_encrypt(cblock, client->session_keyblock->contents, + serv_ksched.s, DES_DECRYPT); + } + } else if (*cp == 'Z') { /* Zcode! Long live the new flesh! */ + retval = ZReadZcode(cp, buf, sizeof(buf), &blen); + if (retval != ZERR_NONE) { + syslog(LOG_ERR,"brl bad cblk read: %s (%s)", + error_message(retval), cp); + } else { + retval = krb5_init_keyblock(Z_krb5_ctx, + ntohl(*(krb5_enctype *)&buf[0]), + ntohl(*(krb5_ui_4 *)&buf[4]), + &client->session_keyblock); + if (retval) { + syslog(LOG_ERR, "brl failed to allocate keyblock: %s", + error_message(retval)); + return retval; + } + memcpy(client->session_keyblock->contents, &buf[8], + client->session_keyblock->length); + } + } + } +#else #ifdef HAVE_KRB4 memset(client->session_key, 0, sizeof(C_Block)); if (*notice.z_class_inst) { @@ -872,6 +1088,7 @@ bdump_recv_loop(server) } } #endif /* HAVE_KRB4 */ +#endif } else if (strcmp(notice.z_opcode, CLIENT_SUBSCRIBE) == 0) { /* a subscription packet */ if (!client) { @@ -1138,7 +1355,13 @@ net_read(f, buf, len) errno = 0; cc = fread(buf, 1, len, f); if (cc == 0) + { + if (feof(f)) + return len2; + if (errno == 0) + errno = EIO; return -1; + } buf += cc; len2 += cc; len -= cc; diff --git a/server/class.c b/server/class.c index 6ccacae..0ce5da3 100644 --- a/server/class.c +++ b/server/class.c @@ -81,9 +81,9 @@ static const char rcsid_class_c[] = static Triplet *triplet_bucket[HASHSIZE]; /* the hash table of pointers */ static Code_t remove_client __P((Triplet *triplet, Client *client, - Realm *realm)); + ZRealm *realm)); static Code_t insert_client __P((Triplet *triplet, Client *client, - Realm *realm)); + ZRealm *realm)); static Triplet *triplet_alloc __P((String *classname, String *inst, String *recipient)); static void free_triplet __P((Triplet *)); @@ -117,7 +117,7 @@ Code_t triplet_register(client, dest, realm) Client *client; Destination *dest; - Realm *realm; + ZRealm *realm; { Triplet *triplet; unsigned long hashval; @@ -140,7 +140,7 @@ Code_t triplet_deregister(client, dest, realm) Client *client; Destination *dest; - Realm *realm; + ZRealm *realm; { Triplet *triplet; int retval; @@ -304,7 +304,7 @@ static Code_t insert_client(triplet, client, realm) Triplet *triplet; Client *client; - Realm *realm; + ZRealm *realm; { Client **clientp, **newclients; int new_size; @@ -348,7 +348,7 @@ insert_client(triplet, client, realm) static Code_t remove_client(triplet, client, realm) Triplet *triplet; Client *client; - Realm *realm; + ZRealm *realm; { Client **clientp; diff --git a/server/client.c b/server/client.c index 85918e7..9098ac0 100644 --- a/server/client.c +++ b/server/client.c @@ -84,9 +84,13 @@ client_register(notice, host, client_p, wantdefaults) if (!client) return ENOMEM; memset(&client->addr, 0, sizeof(struct sockaddr_in)); -#ifdef KERBEROS +#ifdef HAVE_KRB5 + client->session_keyblock = NULL; +#else +#ifdef HAVE_KRB4 memset(&client->session_key, 0, sizeof(client->session_key)); #endif +#endif client->last_send = 0; client->last_ack = NOW; client->addr.sin_family = AF_INET; @@ -122,6 +126,10 @@ client_deregister(client, flush) nack_release(client); subscr_cancel_client(client); free_string(client->principal); +#ifdef HAVE_KRB5 + if (client->session_keyblock) + krb5_free_keyblock(Z_krb5_ctx, client->session_keyblock); +#endif if (flush) uloc_flush_client(&client->addr); free(client); diff --git a/server/dispatch.c b/server/dispatch.c index 493fcd4..09fa0c1 100644 --- a/server/dispatch.c +++ b/server/dispatch.c @@ -14,6 +14,7 @@ #include <zephyr/mit-copyright.h> #include "zserver.h" #include <sys/socket.h> +#include <com_err.h> #ifndef lint #ifndef SABER @@ -134,7 +135,7 @@ handle_packet() int authentic; /* authentic flag */ Pending *pending; /* pending packet */ int from_server; /* packet is from another server */ - Realm *realm; /* foreign realm ptr */ + ZRealm *realm; /* foreign realm ptr */ #ifdef DEBUG static int first_time = 1; #endif @@ -201,8 +202,8 @@ handle_packet() } else { if (realm = realm_which_realm(&input_sin)) { authentic = ZCheckRealmAuthentication(&new_notice, - &input_sin, - realm->name); + &input_sin, + realm->name); } else authentic = ZCheckAuthentication(&new_notice, &input_sin); } @@ -223,6 +224,7 @@ handle_packet() } } +#if 0 if (whoisit.sin_port != hm_port && whoisit.sin_port != hm_srv_port && strcasecmp(new_notice.z_class, ZEPHYR_ADMIN_CLASS) != 0 && whoisit.sin_port != srv_addr.sin_port && @@ -231,6 +233,7 @@ handle_packet() ntohs(whoisit.sin_port)); return; } +#endif message_notices.val++; dispatch(&new_notice, authentic, &whoisit, from_server); @@ -251,7 +254,7 @@ dispatch(notice, auth, who, from_server) String *notice_class; struct sockaddr_in who2; int authflag; - Realm *realm; + ZRealm *realm; char *cp; #ifdef DEBUG char dbg_buf[BUFSIZ]; @@ -353,7 +356,7 @@ sendit(notice, auth, who, external) class = make_string(notice->z_class, 1); if (realm_bound_for_realm(ZGetRealm(), notice->z_recipient)) { - Realm *rlm; + ZRealm *rlm; acl = class_get_acl(class); if (acl != NULL) { @@ -586,6 +589,7 @@ xmit_frag(notice, buf, len, waitforack) return(ZERR_NONE); } + /* * Send the notice to the client. After transmitting, put it onto the * not ack'ed list. @@ -619,14 +623,23 @@ xmit(notice, dest, auth, client) we are distributing authentic and we have a pointer to auth info */ -#ifdef HAVE_KRB4 - retval = ZFormatAuthenticNotice(notice, noticepack, packlen, &packlen, - client->session_key); - if (retval != ZERR_NONE) { - syslog(LOG_ERR, "xmit auth format: %s", error_message(retval)); - free(noticepack); - return; - } +#ifdef HAVE_KRB5 + retval = ZFormatAuthenticNoticeV5(notice, noticepack, packlen, + &packlen, client->session_keyblock); + if (retval != ZERR_NONE) { + syslog(LOG_ERR, "xmit auth format: %s", error_message(retval)); + free(noticepack); + return; + } +#else +#if defined(HAVE_KRB4) + retval = ZFormatAuthenticNotice(notice, noticepack, packlen, + &packlen, client->session_key); + if (retval != ZERR_NONE) { + syslog(LOG_ERR, "xmit auth format: %s", error_message(retval)); + free(noticepack); + return; + } #else /* !HAVE_KRB4 */ notice->z_auth = 1; retval = ZFormatSmallRawNotice(notice, noticepack, &packlen); @@ -636,6 +649,7 @@ xmit(notice, dest, auth, client) return; } #endif /* HAVE_KRB4 */ +#endif /* HAVE_KRB5 */ } else { notice->z_auth = 0; notice->z_authent_len = 0; @@ -1095,7 +1109,7 @@ control_dispatch(notice, auth, who, server) Client *client; Code_t retval; int wantdefs; - Realm *realm; + ZRealm *realm; struct sockaddr_in newwho; /* @@ -1163,10 +1177,28 @@ control_dispatch(notice, auth, who, server) clt_ack(notice, who, AUTH_FAILED); return ZERR_NONE; } +#ifdef HAVE_KRB5 + if (client->session_keyblock) { + krb5_free_keyblock_contents(Z_krb5_ctx, client->session_keyblock); + retval = krb5_copy_keyblock_contents(Z_krb5_ctx, ZGetSession(), + client->session_keyblock); + } else { + retval = krb5_copy_keyblock(Z_krb5_ctx, ZGetSession(), + &client->session_keyblock); + } + if (retval) { + syslog(LOG_WARNING, "keyblock copy failed in subscr: %s", + error_message(retval)); + if (server == me_server) + nack(notice, who); + return ZERR_NONE; + } +#else #ifdef HAVE_KRB4 /* in case it's changed */ memcpy(client->session_key, ZGetSession(), sizeof(C_Block)); #endif +#endif retval = subscr_subscribe(client, notice, server); if (retval != ZERR_NONE) { syslog(LOG_WARNING, "subscr failed: %s", error_message(retval)); diff --git a/server/kstuff.c b/server/kstuff.c index eff445d..b4b48d7 100644 --- a/server/kstuff.c +++ b/server/kstuff.c @@ -22,30 +22,6 @@ static const char rcsid_kstuff_c[] = "$Id$"; #ifdef HAVE_KRB4 -/* Keep a hash table mapping tickets to session keys, so we can do a fast - * check of the cryptographic checksum without doing and DES decryptions. - * Also remember the expiry time of the ticket, so that we can sweep the - * table periodically. */ - -#define HASHTAB_SIZE 4091 - -typedef struct hash_entry Hash_entry; - -/* The ticket comes at the end, in a variable-length array. */ -struct hash_entry { - C_Block session_key; - time_t expires; - char srcprincipal[ANAME_SZ+INST_SZ+REALM_SZ+4]; - Hash_entry *next; - int ticket_len; - unsigned char ticket[1]; -}; - -Hash_entry *hashtab[HASHTAB_SIZE]; - -static int hash_ticket __P((unsigned char *, int)); -static void add_session_key __P((KTEXT, C_Block, char *, time_t)); -static int find_session_key __P((KTEXT, C_Block, char *)); static ZChecksum_t compute_checksum __P((ZNotice_t *, C_Block)); static ZChecksum_t compute_rlm_checksum __P((ZNotice_t *, C_Block)); @@ -113,6 +89,10 @@ GetKerberosData(fd, haddr, kdata, service, srvtab) * get the ticket and write it to the file descriptor */ +#if !defined(krb_err_base) && defined(ERROR_TABLE_BASE_krb) +#define krb_err_base ERROR_TABLE_BASE_krb +#endif + Code_t SendKerberosData(fd, ticket, service, host) int fd; /* file descriptor to write onto */ @@ -142,21 +122,93 @@ SendKerberosData(fd, ticket, service, host) #endif /* HAVE_KRB4 */ +#ifdef HAVE_KRB5 +Code_t +GetKrb5Data(int fd, krb5_data *data) { + char p[20]; + int i; + unsigned char *dst; + Code_t retval; + + for (i=0; i<20; i++) { + if (read(fd, &p[i], 1) != 1) { + syslog(LOG_WARNING,"bad read reply len"); + return(KFAILURE); + } + if (p[i] == ' ') { + p[i] = '\0'; + break; + } + } + if (i == 20 || strncmp(p, "V5-", 3) || !atoi(p+3)) { + syslog(LOG_WARNING,"bad reply len"); + return ZSRV_PKSHORT; + } + data->length = atoi(p+3); + data->data = malloc(data->length); + if (! data->data) { + data->length = 0; + return errno; + } + dst=data->data; + for (i=0; i < data->length; i++) { + if (read(fd, dst++, 1) != 1) { + free(data->data); + memset((char *)data, 0, sizeof(krb5_data)); + syslog(LOG_WARNING,"bad read reply string"); + return ZSRV_PKSHORT; + } + } + return 0; +} +Code_t +SendKrb5Data(int fd, krb5_data *data) { + char p[32]; + int written, size_to_write; + sprintf(p, "V5-%d", data->length); + size_to_write = strlen (p); + if (size_to_write != (written = write(fd, p, size_to_write)) || + data->length != (written = write(fd, data->data, data->length))) { + return (written < 0) ? errno : ZSRV_PKSHORT; + } + return 0; +} +#endif + Code_t ZCheckRealmAuthentication(notice, from, realm) ZNotice_t *notice; struct sockaddr_in *from; char *realm; { -#ifdef HAVE_KRB4 - int result; - char rlmprincipal[ANAME_SZ+INST_SZ+REALM_SZ+4]; - char srcprincipal[ANAME_SZ+INST_SZ+REALM_SZ+4]; - KTEXT_ST authent, ticket; - AUTH_DAT dat; - ZChecksum_t checksum; - CREDENTIALS cred; - C_Block session_key; +#ifdef HAVE_KRB5 + char *authbuf; + char rlmprincipal[ANAME_SZ+INST_SZ+REALM_SZ+4+1024]; + krb5_principal princ; + krb5_data packet; + krb5_ticket *tkt; + char *name; + krb5_error_code result; + krb5_principal server; + krb5_keytab keytabid = 0; + krb5_auth_context authctx; + krb5_keyblock *keyblock; + krb5_enctype enctype; + krb5_cksumtype cksumtype; + krb5_data cksumbuf; + int valid; + char *cksum0_base, *cksum1_base, *cksum2_base; + char *svcinst, *x, *y; + char *asn1_data, *key_data; + int asn1_len, key_len, cksum0_len, cksum1_len, cksum2_len; +#ifdef KRB5_AUTH_CON_GETAUTHENTICATOR_TAKES_DOUBLE_POINTER + krb5_authenticator *authenticator; +#define KRB5AUTHENT authenticator +#else + krb5_authenticator authenticator; +#define KRB5AUTHENT &authenticator +#endif + int len; if (!notice->z_auth) return ZAUTH_NO; @@ -165,52 +217,537 @@ ZCheckRealmAuthentication(notice, from, realm) if (notice->z_authent_len <= 0) return ZAUTH_FAILED; + len = strlen(notice->z_ascii_authent)+1; + authbuf=malloc(len); + /* Read in the authentication data. */ - if (ZReadAscii(notice->z_ascii_authent, - strlen(notice->z_ascii_authent)+1, - (unsigned char *)authent.dat, - notice->z_authent_len) == ZERR_BADFIELD) { + if (ZReadZcode(notice->z_ascii_authent, + authbuf, + len, &len) == ZERR_BADFIELD) { return ZAUTH_FAILED; } - authent.length = notice->z_authent_len; - (void) sprintf(rlmprincipal, "%s.%s@%s", SERVER_SERVICE, + (void) sprintf(rlmprincipal, "%s/%s@%s", SERVER_SERVICE, SERVER_INSTANCE, realm); - result = krb_rd_req(&authent, SERVER_SERVICE, SERVER_INSTANCE, - from->sin_addr.s_addr, &dat, srvtab_file); - if (result == RD_AP_OK) { - sprintf(srcprincipal, "%s%s%s@%s", dat.pname, dat.pinst[0] ? "." : "", - dat.pinst, dat.prealm); - if (strcmp(rlmprincipal, srcprincipal)) - return ZAUTH_FAILED; - } else { - return ZAUTH_FAILED; /* didn't decode correctly */ + packet.length = len; + packet.data = authbuf; + + result = krb5_kt_resolve(Z_krb5_ctx, + keytab_file, &keytabid); + if (result) { + free(authbuf); + return (result); } - /* Check the cryptographic checksum. */ -#ifdef NOENCRYPTION - checksum = 0; + /* HOLDING: authbuf, keytabid */ + /* Create the auth context */ + result = krb5_auth_con_init(Z_krb5_ctx, &authctx); + if (result) { + krb5_kt_close(Z_krb5_ctx, keytabid); + free(authbuf); + return (result); + } + + /* HOLDING: authbuf, authctx */ + result = krb5_build_principal(Z_krb5_ctx, &server, strlen(__Zephyr_realm), + __Zephyr_realm, SERVER_SERVICE, + SERVER_INSTANCE, NULL); + if (!result) { + result = krb5_rd_req(Z_krb5_ctx, &authctx, &packet, server, + keytabid, 0, &tkt); + krb5_free_principal(Z_krb5_ctx, server); + } + krb5_kt_close(Z_krb5_ctx, keytabid); + + if (result) { + if (result == KRB5KRB_AP_ERR_REPEAT) + syslog(LOG_DEBUG, "ZCheckRealmAuthentication: k5 auth failed: %s", error_message(result)); + else + syslog(LOG_WARNING,"ZCheckRealmAuthentication: k5 auth failed: %s", error_message(result)); + free(authbuf); + krb5_auth_con_free(Z_krb5_ctx, authctx); + return ZAUTH_FAILED; + } + + /* HOLDING: authbuf, authctx, tkt */ + + if (tkt == 0 || !Z_tktprincp(tkt)) { + if (tkt) + krb5_free_ticket(Z_krb5_ctx, tkt); + free(authbuf); + krb5_auth_con_free(Z_krb5_ctx, authctx); + return ZAUTH_FAILED; + } + + princ = Z_tktprinc(tkt); + + if (princ == 0) { + krb5_free_ticket(Z_krb5_ctx, tkt); + free(authbuf); + krb5_auth_con_free(Z_krb5_ctx, authctx); + return ZAUTH_FAILED; + } + + /* HOLDING: authbuf, authctx, tkt */ + result = krb5_unparse_name(Z_krb5_ctx, princ, &name); + if (result) { + syslog(LOG_WARNING, "k5 unparse_name failed: %s", + error_message(result)); + free(authbuf); + krb5_auth_con_free(Z_krb5_ctx, authctx); + krb5_free_ticket(Z_krb5_ctx, tkt); + return ZAUTH_FAILED; + } + + krb5_free_ticket(Z_krb5_ctx, tkt); + + /* HOLDING: authbuf, authctx, name */ + if (strcmp(name, rlmprincipal)) { + syslog(LOG_WARNING, "k5 name mismatch: '%s' vs '%s'", + name, rlmprincipal); + krb5_auth_con_free(Z_krb5_ctx, authctx); + free(name); + free(authbuf); + return ZAUTH_FAILED; + } + free(name); + free(authbuf); + + /* HOLDING: authctx */ + /* Get an authenticator so we can get the keyblock */ + result = krb5_auth_con_getauthenticator (Z_krb5_ctx, authctx, + &authenticator); + if(result) { + krb5_auth_con_free(Z_krb5_ctx, authctx); + return result; + } + + /* HOLDING: authctx, authenticator */ + result = krb5_auth_con_getkey(Z_krb5_ctx, authctx, &keyblock); + if (result) { + krb5_auth_con_free(Z_krb5_ctx, authctx); + krb5_free_authenticator(Z_krb5_ctx, KRB5AUTHENT); + return (ZAUTH_FAILED); + } + + /* HOLDING: authctx, authenticator, keyblock */ + /* Figure out what checksum type to use */ + key_data = Z_keydata(keyblock); + key_len = Z_keylen(keyblock); + result = Z_ExtractEncCksum(keyblock, &enctype, &cksumtype); + if (result) { + krb5_free_keyblock(Z_krb5_ctx, keyblock); + krb5_auth_con_free(Z_krb5_ctx, authctx); + krb5_free_authenticator(Z_krb5_ctx, KRB5AUTHENT); + return (ZAUTH_FAILED); + } + /* HOLDING: authctx, authenticator, keyblock */ + + /* Assemble the things to be checksummed */ + /* first part is from start of packet through z_default_format: + * - z_version + * - z_num_other_fields + * - z_kind + * - z_uid + * - z_port + * - z_auth + * - z_authent_len + * - z_ascii_authent + * - z_class + * - z_class_inst + * - z_opcode + * - z_sender + * - z_recipient + * - z_default_format + */ + cksum0_base = notice->z_packet; + x = notice->z_default_format; + cksum0_len = x + strlen(x) + 1 - cksum0_base; + /* second part is from z_multinotice through other fields: + * - z_multinotice + * - z_multiuid + * - z_other_fields[] + */ + cksum1_base = notice->z_multinotice; + if (notice->z_num_other_fields) + x = notice->z_other_fields[notice->z_num_other_fields]; + else + x = cksum1_base + strlen(cksum1_base) + 1; /* multiuid */ + cksum1_len = x + strlen(x) + 1 - cksum1_base; + + /* last part is the message body */ + cksum2_base = notice->z_message; + cksum2_len = notice->z_message_len; + + if ((!notice->z_ascii_checksum || *notice->z_ascii_checksum != 'Z') && + key_len == 8 && + (enctype == ENCTYPE_DES_CBC_CRC || + enctype == ENCTYPE_DES_CBC_MD4 || + enctype == ENCTYPE_DES_CBC_MD5)) { + /* try old-format checksum (covers cksum0 only) */ + + ZChecksum_t our_checksum; + + our_checksum = compute_rlm_checksum(notice, key_data); + + krb5_free_keyblock(Z_krb5_ctx, keyblock); + krb5_auth_con_free(Z_krb5_ctx, authctx); + krb5_free_authenticator(Z_krb5_ctx, KRB5AUTHENT); + + if (our_checksum == notice->z_checksum) { + return ZAUTH_YES; + } else + return ZAUTH_FAILED; + } + + /* HOLDING: authctx, authenticator */ + + cksumbuf.length = cksum0_len + cksum1_len + cksum2_len; + cksumbuf.data = malloc(cksumbuf.length); + if (!cksumbuf.data) { + krb5_free_keyblock(Z_krb5_ctx, keyblock); + krb5_auth_con_free(Z_krb5_ctx, authctx); + krb5_free_authenticator(Z_krb5_ctx, KRB5AUTHENT); + return ZAUTH_NO; + } + /* HOLDING: authctx, authenticator, cksumbuf.data */ + + memcpy(cksumbuf.data, cksum0_base, cksum0_len); + memcpy(cksumbuf.data + cksum0_len, cksum1_base, cksum1_len); + memcpy(cksumbuf.data + cksum0_len + cksum1_len, + cksum2_base, cksum2_len); + + /* decode zcoded checksum */ + /* The encoded form is always longer than the original */ + asn1_len = strlen(notice->z_ascii_checksum) + 1; + asn1_data = malloc(asn1_len); + if (!asn1_data) { + krb5_free_keyblock(Z_krb5_ctx, keyblock); + krb5_auth_con_free(Z_krb5_ctx, authctx); + krb5_free_authenticator(Z_krb5_ctx, KRB5AUTHENT); + free(cksumbuf.data); + return ZAUTH_FAILED; + } + /* HOLDING: authctx, authenticator, cksumbuf.data, asn1_data */ + result = ZReadZcode(notice->z_ascii_checksum, + asn1_data, asn1_len, &asn1_len); + if (result != ZERR_NONE) { + krb5_free_keyblock(Z_krb5_ctx, keyblock); + krb5_auth_con_free(Z_krb5_ctx, authctx); + krb5_free_authenticator(Z_krb5_ctx, KRB5AUTHENT); + free(asn1_data); + free(cksumbuf.data); + return ZAUTH_FAILED; + } + /* HOLDING: asn1_data, cksumbuf.data */ + + valid = Z_krb5_verify_cksum(keyblock, &cksumbuf, cksumtype, asn1_data, asn1_len); + + free(asn1_data); + krb5_auth_con_free(Z_krb5_ctx, authctx); + krb5_free_authenticator(Z_krb5_ctx, KRB5AUTHENT); + krb5_free_keyblock(Z_krb5_ctx, keyblock); + free(cksumbuf.data); + + if (valid) + return (ZAUTH_YES); + else + return (ZAUTH_FAILED); #else - checksum = compute_rlm_checksum(notice, dat.session); + return (notice->z_auth) ? ZAUTH_YES : ZAUTH_NO; #endif - if (checksum != notice->z_checksum) { -#ifndef NOENCRYPTION - checksum = compute_checksum(notice, dat.session); - if (checksum != notice->z_checksum) +} + +Code_t +ZCheckAuthentication(notice, from) + ZNotice_t *notice; + struct sockaddr_in *from; +{ +#ifdef HAVE_KRB5 + char *authbuf; + krb5_principal princ; + krb5_data packet; + krb5_ticket *tkt; + char *name; + krb5_error_code result; + krb5_principal server; + krb5_keytab keytabid = 0; + krb5_auth_context authctx; + krb5_keyblock *keyblock; + krb5_enctype enctype; + krb5_cksumtype cksumtype; + krb5_data cksumbuf; + int valid; + char *cksum0_base, *cksum1_base, *cksum2_base; + char *svcinst, *x, *y; + char *asn1_data, *key_data; + int asn1_len, key_len, cksum0_len, cksum1_len, cksum2_len; +#ifdef KRB5_AUTH_CON_GETAUTHENTICATOR_TAKES_DOUBLE_POINTER + krb5_authenticator *authenticator; +#define KRB5AUTHENT authenticator +#else + krb5_authenticator authenticator; +#define KRB5AUTHENT &authenticator #endif + int len; + + if (!notice->z_auth) + return ZAUTH_NO; + + /* Check for bogus authentication data length. */ + if (notice->z_authent_len <= 1) + return ZAUTH_FAILED; + +#ifdef HAVE_KRB4 + if (notice->z_ascii_authent[0] != 'Z') + return ZCheckAuthentication4(notice, from); +#endif + + len = strlen(notice->z_ascii_authent)+1; + authbuf=malloc(len); + + /* Read in the authentication data. */ + if (ZReadZcode(notice->z_ascii_authent, + authbuf, + len, &len) == ZERR_BADFIELD) { return ZAUTH_FAILED; } - return ZAUTH_YES; + packet.length = len; + packet.data = authbuf; -#else /* !HAVE_KRB4 */ + result = krb5_kt_resolve(Z_krb5_ctx, + keytab_file, &keytabid); + if (result) { + free(authbuf); + return (result); + } + + /* HOLDING: authbuf, keytabid */ + /* Create the auth context */ + result = krb5_auth_con_init(Z_krb5_ctx, &authctx); + if (result) { + krb5_kt_close(Z_krb5_ctx, keytabid); + free(authbuf); + return (result); + } + + /* HOLDING: authbuf, authctx */ + result = krb5_build_principal(Z_krb5_ctx, &server, strlen(__Zephyr_realm), + __Zephyr_realm, SERVER_SERVICE, + SERVER_INSTANCE, NULL); + if (!result) { + result = krb5_rd_req(Z_krb5_ctx, &authctx, &packet, server, + keytabid, 0, &tkt); + krb5_free_principal(Z_krb5_ctx, server); + } + krb5_kt_close(Z_krb5_ctx, keytabid); + + if (result) { + if (result == KRB5KRB_AP_ERR_REPEAT) + syslog(LOG_DEBUG, "ZCheckAuthentication: k5 auth failed: %s", error_message(result)); + else + syslog(LOG_WARNING,"ZCheckAuthentication: k5 auth failed: %s", error_message(result)); + free(authbuf); + krb5_auth_con_free(Z_krb5_ctx, authctx); + return ZAUTH_FAILED; + } + + /* HOLDING: authbuf, authctx, tkt */ + + if (tkt == 0 || !Z_tktprincp(tkt)) { + if (tkt) + krb5_free_ticket(Z_krb5_ctx, tkt); + free(authbuf); + krb5_auth_con_free(Z_krb5_ctx, authctx); + return ZAUTH_FAILED; + } + princ = Z_tktprinc(tkt); + + if (princ == 0) { + krb5_free_ticket(Z_krb5_ctx, tkt); + free(authbuf); + krb5_auth_con_free(Z_krb5_ctx, authctx); + return ZAUTH_FAILED; + } + + /* HOLDING: authbuf, authctx, tkt */ + result = krb5_unparse_name(Z_krb5_ctx, princ, &name); + if (result) { + syslog(LOG_WARNING, "k5 unparse_name failed: %s", + error_message(result)); + free(authbuf); + krb5_auth_con_free(Z_krb5_ctx, authctx); + krb5_free_ticket(Z_krb5_ctx, tkt); + return ZAUTH_FAILED; + } + + krb5_free_ticket(Z_krb5_ctx, tkt); + + /* HOLDING: authbuf, authctx, name */ + if (strcmp(name, notice->z_sender)) { + syslog(LOG_WARNING, "k5 name mismatch: '%s' vs '%s'", + name, notice->z_sender); + krb5_auth_con_free(Z_krb5_ctx, authctx); + free(name); + free(authbuf); + return ZAUTH_FAILED; + } + free(name); + free(authbuf); + + /* HOLDING: authctx */ + /* Get an authenticator so we can get the keyblock */ + result = krb5_auth_con_getauthenticator (Z_krb5_ctx, authctx, + &authenticator); + if(result) { + krb5_auth_con_free(Z_krb5_ctx, authctx); + return result; + } + + /* HOLDING: authctx, authenticator */ + result = krb5_auth_con_getkey(Z_krb5_ctx, authctx, &keyblock); + if (result) { + krb5_auth_con_free(Z_krb5_ctx, authctx); + krb5_free_authenticator(Z_krb5_ctx, KRB5AUTHENT); + return (ZAUTH_FAILED); + } + + /* HOLDING: authctx, authenticator, keyblock */ + /* Figure out what checksum type to use */ + key_data = Z_keydata(keyblock); + key_len = Z_keylen(keyblock); + result = Z_ExtractEncCksum(keyblock, &enctype, &cksumtype); + if (result) { + krb5_free_keyblock(Z_krb5_ctx, keyblock); + krb5_auth_con_free(Z_krb5_ctx, authctx); + krb5_free_authenticator(Z_krb5_ctx, KRB5AUTHENT); + return (ZAUTH_FAILED); + } + /* HOLDING: authctx, authenticator, keyblock */ + + ZSetSession(keyblock); + + /* Assemble the things to be checksummed */ + /* first part is from start of packet through z_default_format: + * - z_version + * - z_num_other_fields + * - z_kind + * - z_uid + * - z_port + * - z_auth + * - z_authent_len + * - z_ascii_authent + * - z_class + * - z_class_inst + * - z_opcode + * - z_sender + * - z_recipient + * - z_default_format + */ + cksum0_base = notice->z_packet; + x = notice->z_default_format; + cksum0_len = x + strlen(x) + 1 - cksum0_base; + /* second part is from z_multinotice through other fields: + * - z_multinotice + * - z_multiuid + * - z_other_fields[] + */ + cksum1_base = notice->z_multinotice; + if (notice->z_num_other_fields) + x = notice->z_other_fields[notice->z_num_other_fields]; + else + x = cksum1_base + strlen(cksum1_base) + 1; /* multiuid */ + cksum1_len = x + strlen(x) + 1 - cksum1_base; + + /* last part is the message body */ + cksum2_base = notice->z_message; + cksum2_len = notice->z_message_len; + + if ((!notice->z_ascii_checksum || *notice->z_ascii_checksum != 'Z') && + key_len == 8 && + (enctype == ENCTYPE_DES_CBC_CRC || + enctype == ENCTYPE_DES_CBC_MD4 || + enctype == ENCTYPE_DES_CBC_MD5)) { + /* try old-format checksum (covers cksum0 only) */ + + ZChecksum_t our_checksum; + + our_checksum = compute_checksum(notice, key_data); + + krb5_free_keyblock(Z_krb5_ctx, keyblock); + krb5_auth_con_free(Z_krb5_ctx, authctx); + krb5_free_authenticator(Z_krb5_ctx, KRB5AUTHENT); + + if (our_checksum == notice->z_checksum) + return ZAUTH_YES; + else + return ZAUTH_FAILED; + } + + /* HOLDING: authctx, authenticator */ + + cksumbuf.length = cksum0_len + cksum1_len + cksum2_len; + cksumbuf.data = malloc(cksumbuf.length); + if (!cksumbuf.data) { + krb5_free_keyblock(Z_krb5_ctx, keyblock); + krb5_auth_con_free(Z_krb5_ctx, authctx); + krb5_free_authenticator(Z_krb5_ctx, KRB5AUTHENT); + return ZAUTH_NO; + } + /* HOLDING: authctx, authenticator, cksumbuf.data */ + + memcpy(cksumbuf.data, cksum0_base, cksum0_len); + memcpy(cksumbuf.data + cksum0_len, cksum1_base, cksum1_len); + memcpy(cksumbuf.data + cksum0_len + cksum1_len, + cksum2_base, cksum2_len); + + /* decode zcoded checksum */ + /* The encoded form is always longer than the original */ + asn1_len = strlen(notice->z_ascii_checksum) + 1; + asn1_data = malloc(asn1_len); + if (!asn1_data) { + krb5_free_keyblock(Z_krb5_ctx, keyblock); + krb5_auth_con_free(Z_krb5_ctx, authctx); + krb5_free_authenticator(Z_krb5_ctx, KRB5AUTHENT); + free(cksumbuf.data); + return ZAUTH_FAILED; + } + /* HOLDING: authctx, authenticator, cksumbuf.data, asn1_data */ + result = ZReadZcode(notice->z_ascii_checksum, + asn1_data, asn1_len, &asn1_len); + if (result != ZERR_NONE) { + krb5_free_keyblock(Z_krb5_ctx, keyblock); + krb5_auth_con_free(Z_krb5_ctx, authctx); + krb5_free_authenticator(Z_krb5_ctx, KRB5AUTHENT); + free(asn1_data); + free(cksumbuf.data); + return ZAUTH_FAILED; + } + /* HOLDING: asn1_data, cksumbuf.data, authctx, authenticator */ + + valid = Z_krb5_verify_cksum(keyblock, &cksumbuf, cksumtype, asn1_data, asn1_len); + + free(asn1_data); + krb5_auth_con_free(Z_krb5_ctx, authctx); + krb5_free_authenticator(Z_krb5_ctx, KRB5AUTHENT); + krb5_free_keyblock(Z_krb5_ctx, keyblock); + free(cksumbuf.data); + + if (valid) + return (ZAUTH_YES); + else + return (ZAUTH_FAILED); +#else return (notice->z_auth) ? ZAUTH_YES : ZAUTH_NO; #endif } +#undef KRB5AUTHENT + Code_t -ZCheckAuthentication(notice, from) +ZCheckAuthentication4(notice, from) ZNotice_t *notice; struct sockaddr_in *from; { @@ -221,6 +758,7 @@ ZCheckAuthentication(notice, from) AUTH_DAT dat; ZChecksum_t checksum; C_Block session_key; + char instance[INST_SZ+1]; if (!notice->z_auth) return ZAUTH_NO; @@ -238,10 +776,13 @@ ZCheckAuthentication(notice, from) } authent.length = notice->z_authent_len; - result = krb_rd_req(&authent, SERVER_SERVICE, SERVER_INSTANCE, + strcpy(instance, SERVER_INSTANCE); + + /* We don't have the session key cached; do it the long way. */ + result = krb_rd_req(&authent, SERVER_SERVICE, instance, from->sin_addr.s_addr, &dat, srvtab_file); if (result == RD_AP_OK) { - memcpy(__Zephyr_session, dat.session, sizeof(C_Block)); + ZSetSessionDES(&dat.session); sprintf(srcprincipal, "%s%s%s@%s", dat.pname, dat.pinst[0] ? "." : "", dat.pinst, dat.prealm); if (strcmp(srcprincipal, notice->z_sender)) @@ -266,76 +807,8 @@ ZCheckAuthentication(notice, from) #endif } -#ifdef HAVE_KRB4 - -static int hash_ticket(p, len) - unsigned char *p; - int len; -{ - unsigned long hashval = 0, g; - - for (; len > 0; p++, len--) { - hashval = (hashval << 4) + *p; - g = hashval & 0xf0000000; - if (g) { - hashval ^= g >> 24; - hashval ^= g; - } - } - return hashval % HASHTAB_SIZE; -} - -static void add_session_key(ticket, session_key, srcprincipal, expires) - KTEXT ticket; - C_Block session_key; - char *srcprincipal; - time_t expires; -{ - Hash_entry *entry; - int hashval; - - /* If we can't allocate memory for the hash table entry, just forget - * about it. */ - entry = (Hash_entry *) malloc(sizeof(Hash_entry) - 1 + ticket->length); - if (!entry) - return; - - /* Initialize the new entry. */ - memcpy(entry->session_key, session_key, sizeof(entry->session_key)); - strcpy(entry->srcprincipal, srcprincipal); - entry->expires = expires; - entry->ticket_len = ticket->length; - memcpy(entry->ticket, ticket->dat, ticket->length * sizeof(unsigned char)); - - /* Insert the new entry in the hash table. */ - hashval = hash_ticket(ticket->dat, ticket->length); - entry->next = hashtab[hashval]; - hashtab[hashval] = entry; -} - -static int find_session_key(ticket, key, srcprincipal) - KTEXT ticket; - C_Block key; - char *srcprincipal; -{ - unsigned char *dat; - int hashval, len; - Hash_entry *entry; - - dat = ticket->dat; - len = ticket->length; - hashval = hash_ticket(dat, len); - - for (entry = hashtab[hashval]; entry; entry = entry->next) { - if (entry->ticket_len == len && memcmp(entry->ticket, dat, len) == 0) { - memcpy(key, entry->session_key, sizeof(entry->session_key)); - strcpy(srcprincipal, entry->srcprincipal); - return 0; - } - } - return -1; -} +#ifdef HAVE_KRB4 static ZChecksum_t compute_checksum(notice, session_key) ZNotice_t *notice; C_Block session_key; @@ -373,26 +846,68 @@ static ZChecksum_t compute_rlm_checksum(notice, session_key) #endif } -void sweep_ticket_hash_table(arg) - void *arg; -{ - int i; - Hash_entry **ptr, *entry; - - for (i = 0; i < HASHTAB_SIZE; i++) { - ptr = &hashtab[i]; - while (*ptr) { - entry = *ptr; - if (entry->expires < NOW) { - *ptr = entry->next; - free(entry); - } else { - ptr = &(*ptr)->next; - } - } +#ifdef HAVE_KRB5 +void +ZSetSession(krb5_keyblock *keyblock) { +#if 1 + krb5_error_code result; + + if (__Zephyr_keyblock) { + krb5_free_keyblock_contents(Z_krb5_ctx, __Zephyr_keyblock); + result = krb5_copy_keyblock_contents(Z_krb5_ctx, keyblock, __Zephyr_keyblock); + } else { + result = krb5_copy_keyblock(Z_krb5_ctx, keyblock, &__Zephyr_keyblock); } - timer_set_rel(SWEEP_INTERVAL, sweep_ticket_hash_table, NULL); + + if (result) /*XXX we're out of memory? */ + ; +#else + memcpy(__Zephyr_session, Z_keydata(keyblock), sizeof(C_Block)); +#endif } +#endif +#ifdef HAVE_KRB4 +void +ZSetSessionDES(C_Block *key) { +#ifdef HAVE_KRB5 + Code_t result; +#ifdef HAVE_KRB5_INIT_KEYBLOCK + if (__Zephyr_keyblock) { + krb5_free_keyblock(__Zephyr_keyblock); + __Zephyr_keyblock=NULL; + } + result = krb5_init_keyblock(Z_krb5_ctx, ENCTYPE_DES_CBC_CRC, + sizeof(C_Block) + &__Zephyr_keyblock); + if (result) /*XXX we're out of memory? */ + return; + + memcpy(Z_keydata(__Zephyr_keyblock), key, sizeof(C_Block)); +#else + krb5_keyblock *tmp, tmp_ss; + tmp = &tmp_ss; + Z_keylen(tmp)=sizeof(C_Block); + Z_keydata(tmp)=key; +#if HAVE_KRB5_CREDS_KEYBLOCK_ENCTYPE + tmp->enctype = ENCTYPE_DES_CBC_CRC; +#else + tmp->keytype = KEYTYPE_DES; +#endif + if (__Zephyr_keyblock) { + krb5_free_keyblock_contents(Z_krb5_ctx, __Zephyr_keyblock); + result = krb5_copy_keyblock_contents(Z_krb5_ctx, tmp, + __Zephyr_keyblock); + } else { + result = krb5_copy_keyblock(Z_krb5_ctx, tmp, &__Zephyr_keyblock); + } + if (result) /*XXX we're out of memory? */ + ; +#endif +#else + memcpy(__Zephyr_session, key, sizeof(C_Block)); +#endif +} +#endif #endif /* HAVE_KRB4 */ diff --git a/server/main.c b/server/main.c index e160929..0f2aa4c 100644 --- a/server/main.c +++ b/server/main.c @@ -92,6 +92,10 @@ char *programname; /* set to the basename of argv[0] */ char myname[MAXHOSTNAMELEN]; /* my host name */ char list_file[128]; +#ifdef HAVE_KRB5 +char keytab_file[128]; +static char tkt5_file[256]; +#endif #ifdef HAVE_KRB4 char srvtab_file[128]; char my_realm[REALM_SZ]; @@ -120,6 +124,15 @@ static int nofork; struct in_addr my_addr; char *bdump_version = "1.2"; +#ifdef HAVE_KRB5 +krb5_ccache Z_krb5_ccache; +krb5_keyblock *__Zephyr_keyblock; +#else +#ifdef HAVE_KRB4 +C_Block __Zephyr_session; +#endif +#endif + int main(argc, argv) int argc; @@ -142,6 +155,10 @@ main(argc, argv) sprintf(srvtab_file, "%s/zephyr/%s", SYSCONFDIR, ZEPHYR_SRVTAB); sprintf(tkt_file, "%s/zephyr/%s", SYSCONFDIR, ZEPHYR_TKFILE); #endif +#ifdef HAVE_KRB5 + sprintf(keytab_file, "%s/zephyr/%s", SYSCONFDIR, ZEPHYR_KEYTAB); + sprintf(tkt5_file, "FILE:%s/zephyr/%s", SYSCONFDIR, ZEPHYR_TK5FILE); +#endif sprintf(acl_dir, "%s/zephyr/%s", SYSCONFDIR, ZEPHYR_ACL_DIR); sprintf(subs_file, "%s/zephyr/%s", SYSCONFDIR, DEFAULT_SUBS_FILE); @@ -293,9 +310,6 @@ main(argc, argv) /* Reinitialize t_local now that initialization is done. */ gettimeofday(&t_local, NULL); uptime = NOW; -#ifdef HAVE_KRB4 - timer_set_rel(SWEEP_INTERVAL, sweep_ticket_hash_table, NULL); -#endif realm_wakeup(); #ifdef DEBUG_MALLOC @@ -369,6 +383,7 @@ main(argc, argv) static int initialize() { + int zero = 0; if (do_net_setup()) return(1); @@ -381,6 +396,20 @@ initialize() ZSetServerState(1); ZInitialize(); /* set up the library */ +#ifdef HAVE_KRB5 + krb5_cc_resolve(Z_krb5_ctx, tkt5_file, &Z_krb5_ccache); +#ifdef HAVE_KRB5_CC_SET_DEFAULT_NAME + krb5_cc_set_default_name(Z_krb5_ctx, tkt5_file); +#else + { + /* Hack to make krb5_cc_default do something reasonable */ + char *env=(char *)malloc(strlen(tkt5_file)+12); + if (!env) return(1); + sprintf(env, "KRB5CCNAME=%s", tkt5_file); + putenv(env); + } +#endif +#endif #ifdef HAVE_KRB4 /* Override what Zinitialize set for ZGetRealm() */ if (*my_realm) @@ -447,6 +476,13 @@ do_net_setup() if (srv_socket < 0) { syslog(LOG_ERR, "client_sock failed: %m"); return 1; + } else { +#ifdef SO_BSDCOMPAT + int on = 1; + + /* Prevent Linux from giving us socket errors we don't care about. */ + setsockopt(srv_socket, SOL_SOCKET, SO_BSDCOMPAT, &on, sizeof(on)); +#endif } if (bind(srv_socket, (struct sockaddr *) &srv_addr, sizeof(srv_addr)) < 0) { @@ -633,7 +669,7 @@ reap(sig) { int pid, i = 0; int oerrno = errno; - Realm *rlm; + ZRealm *rlm; #ifdef _POSIX_VERSION int waitb; #else diff --git a/server/realm.c b/server/realm.c index ecef9eb..ddfd057 100644 --- a/server/realm.c +++ b/server/realm.c @@ -3,17 +3,17 @@ Unacked *rlm_nacklist = NULL; /* not acked list for realm-realm packets */ -Realm *otherrealms; /* points to an array of the known +ZRealm *otherrealms; /* points to an array of the known servers */ int nrealms = 0; /* number of other realms */ /* * External Routines: * - * Realm *realm_which_realm(struct sockaddr_in *who) + * ZRealm *realm_which_realm(struct sockaddr_in *who) * figures out if this packet came from another realm's server * - * Realm *realm_get_realm_by_pid(int pid) + * ZRealm *realm_get_realm_by_pid(int pid) * figures out which realm a child handler was for * * void kill_realm_pids() @@ -31,7 +31,7 @@ int nrealms = 0; /* number of other realms */ * int realm_sender_in_realm(char *realm, char *sender) * figures out if sender is in realm * - * Realm *realm_get_realm_by_name(char *name) + * ZRealm *realm_get_realm_by_name(char *name) * finds a realm struct from the realm array by name, tries expansion * * Code_t realm_dispatch(ZNotice_t *notice, int auth, struct sockaddr_in *who, @@ -49,35 +49,34 @@ int nrealms = 0; /* number of other realms */ * * Code_t realm_control_dispatch(ZNotice_t *notice, int auth, * struct sockaddr_in *who, Server *server, - * Realm *realm) + * ZRealm *realm) * dispatches a foreign realm control message * * void realm_handoff(ZNotice_t *notice, int auth, struct sockaddr_in *who, - * Realm *realm, int ack_to_sender) + * ZRealm *realm, int ack_to_sender) * hands off a message to another realm * * void realm_dump_realms(File *fp) * do a database dump of foreign realm info * */ -static void realm_sendit __P((ZNotice_t *notice, struct sockaddr_in *who, int auth, Realm *realm, int ack_to_sender)); -static void realm_sendit_auth __P((ZNotice_t *notice, struct sockaddr_in *who, int auth, Realm *realm, int ack_to_sender)); +static void realm_sendit __P((ZNotice_t *notice, struct sockaddr_in *who, int auth, ZRealm *realm, int ack_to_sender)); +static Code_t realm_sendit_auth __P((ZNotice_t *notice, struct sockaddr_in *who, int auth, ZRealm *realm, int ack_to_sender)); static void rlm_ack __P((ZNotice_t *notice, Unacked *nacked)); static void rlm_nack_cancel __P((ZNotice_t *notice, struct sockaddr_in *who)); static void rlm_new_ticket __P(()); static void rlm_rexmit __P((void *arg)); -static Code_t realm_ulocate_dispatch __P((ZNotice_t *notice,int auth,struct sockaddr_in *who,Server *server,Realm *realm)); -static Code_t realm_new_server __P((struct sockaddr_in *, ZNotice_t *, Realm *)); -static Code_t realm_set_server __P((struct sockaddr_in *, Realm *)); +static Code_t realm_ulocate_dispatch __P((ZNotice_t *notice,int auth,struct sockaddr_in *who,Server *server,ZRealm *realm)); +static Code_t realm_new_server __P((struct sockaddr_in *, ZNotice_t *, ZRealm *)); +static Code_t realm_set_server __P((struct sockaddr_in *, ZRealm *)); #ifdef HAVE_KRB4 -static Code_t ticket_retrieve __P((Realm *realm)); +static Code_t ticket_retrieve __P((ZRealm *realm)); static int ticket_lookup __P((char *realm)); -static int ticket_expired __P((CREDENTIALS *cred)); #endif static int realm_get_idx_by_addr(realm, who) - Realm *realm; + ZRealm *realm; struct sockaddr_in *who; { struct sockaddr_in *addr; @@ -95,7 +94,7 @@ char * realm_expand_realm(realmname) char *realmname; { - Realm *realm; + ZRealm *realm; int a; /* First, look for an exact match (case insensitive) */ @@ -120,11 +119,11 @@ char *realmname; return(realmname); } -Realm * +ZRealm * realm_get_realm_by_pid(pid) int pid; { - Realm *realm; + ZRealm *realm; int a; for (realm = otherrealms, a = 0; a < nrealms; a++, realm++) @@ -137,7 +136,7 @@ realm_get_realm_by_pid(pid) void kill_realm_pids() { - Realm *realm; + ZRealm *realm; int a; for (realm = otherrealms, a = 0; a < nrealms; a++, realm++) @@ -147,11 +146,11 @@ kill_realm_pids() return; } -Realmname * +ZRealmname * get_realm_lists(file) char *file; { - Realmname *rlm_list, *rlm; + ZRealmname *rlm_list, *rlm; int ii, nused, ntotal; FILE *fp; char buf[REALM_SZ + MAXHOSTNAMELEN + 1]; /* one for newline */ @@ -159,11 +158,11 @@ get_realm_lists(file) nused = 0; if (!(fp = fopen(file, "r"))) - return((Realmname *)0); + return((ZRealmname *)0); /* start with 16, realloc if necessary */ ntotal = 16; - rlm_list = (Realmname *)malloc(ntotal * sizeof(Realmname)); + rlm_list = (ZRealmname *)malloc(ntotal * sizeof(ZRealmname)); if (!rlm_list) { syslog(LOG_CRIT, "get_realm_lists malloc"); abort(); @@ -197,9 +196,9 @@ get_realm_lists(file) /* new realm */ if (nused + 1 >= ntotal) { /* make more space */ - rlm_list = (Realmname *)realloc((char *)rlm_list, + rlm_list = (ZRealmname *)realloc((char *)rlm_list, (unsigned)ntotal * 2 * - sizeof(Realmname)); + sizeof(ZRealmname)); if (!rlm_list) { syslog(LOG_CRIT, "get_realm_lists realloc"); abort(); @@ -219,9 +218,9 @@ get_realm_lists(file) } } if (nused + 1 >= ntotal) { - rlm_list = (Realmname *)realloc((char *)rlm_list, + rlm_list = (ZRealmname *)realloc((char *)rlm_list, (unsigned)(ntotal + 1) * - sizeof(Realmname)); + sizeof(ZRealmname)); if (!rlm_list) { syslog(LOG_CRIT, "get_realm_lists realloc"); abort(); @@ -229,6 +228,7 @@ get_realm_lists(file) } *rlm_list[nused].name = '\0'; + fclose(fp); return(rlm_list); } @@ -282,7 +282,7 @@ realm_sender_in_realm(realm, sender) return 0; } -sender_in_realm(notice) +int sender_in_realm(notice) ZNotice_t *notice; { char *realm; @@ -295,11 +295,11 @@ sender_in_realm(notice) return 0; } -Realm * +ZRealm * realm_which_realm(who) struct sockaddr_in *who; { - Realm *realm; + ZRealm *realm; struct sockaddr_in *addr; int a, b; @@ -316,12 +316,12 @@ realm_which_realm(who) return 0; } -Realm * +ZRealm * realm_get_realm_by_name(name) char *name; { int a; - Realm *realm; + ZRealm *realm; /* First, look for an exact match (case insensitive) */ for (realm = otherrealms, a = 0; a < nrealms; a++, realm++) @@ -341,7 +341,7 @@ rlm_nack_cancel(notice, who) register ZNotice_t *notice; struct sockaddr_in *who; { - register Realm *which = realm_which_realm(who); + register ZRealm *which = realm_which_realm(who); register Unacked *nacked, *next; ZPacket_t retval; @@ -424,7 +424,7 @@ realm_dispatch(notice, auth, who, server) struct sockaddr_in *who; Server *server; { - Realm *realm; + ZRealm *realm; struct sockaddr_in newwho; Code_t status = ZERR_NONE; char rlm_recipient[REALM_SZ + 1]; @@ -490,8 +490,8 @@ void realm_init() { Client *client; - Realmname *rlmnames; - Realm *rlm; + ZRealmname *rlmnames; + ZRealm *rlm; int ii, jj, found; struct in_addr *addresses; struct hostent *hp; @@ -508,7 +508,7 @@ realm_init() for (nrealms = 0; *rlmnames[nrealms].name; nrealms++); - otherrealms = (Realm *)malloc(nrealms * sizeof(Realm)); + otherrealms = (ZRealm *)malloc(nrealms * sizeof(ZRealm)); if (!otherrealms) { syslog(LOG_CRIT, "malloc failed in realm_init"); abort(); @@ -557,9 +557,13 @@ realm_init() abort(); } memset(&client->addr, 0, sizeof(struct sockaddr_in)); +#ifdef HAVE_KRB5 + client->session_keyblock = NULL; +#else #ifdef HAVE_KRB4 memset(&client->session_key, 0, sizeof(client->session_key)); #endif +#endif sprintf(rlmprinc, "%s.%s@%s", SERVER_SERVICE, SERVER_INSTANCE, rlm->name); client->principal = make_string(rlmprinc, 0); @@ -589,7 +593,7 @@ void realm_deathgram(server) Server *server; { - Realm *realm; + ZRealm *realm; char rlm_recipient[REALM_SZ + 1]; int jj = 0; @@ -628,7 +632,7 @@ realm_deathgram(server) } #endif - if ((retval = ZFormatNotice(&snotice, &pack, &packlen, ZAUTH)) + if ((retval = ZFormatNotice(&snotice, &pack, &packlen, ZCAUTH)) != ZERR_NONE) { syslog(LOG_WARNING, "rlm_deathgram format: %s", @@ -651,7 +655,7 @@ void realm_wakeup() { int jj, found = 0; - Realm *realm; + ZRealm *realm; char rlm_recipient[REALM_SZ + 1]; for (jj = 1; jj < nservers; jj++) { /* skip limbo server */ @@ -721,7 +725,7 @@ realm_ulocate_dispatch(notice, auth, who, server, realm) int auth; struct sockaddr_in *who; Server *server; - Realm *realm; + ZRealm *realm; { register char *opcode = notice->z_opcode; Code_t status; @@ -761,7 +765,7 @@ realm_control_dispatch(notice, auth, who, server, realm) int auth; struct sockaddr_in *who; Server *server; - Realm *realm; + ZRealm *realm; { register char *opcode = notice->z_opcode; Code_t status; @@ -841,12 +845,12 @@ static Code_t realm_new_server(sin, notice, realm) struct sockaddr_in *sin; ZNotice_t *notice; - Realm *realm; + ZRealm *realm; { struct hostent *hp; char suggested_server[MAXHOSTNAMELEN]; unsigned long addr; - Realm *rlm; + ZRealm *rlm; struct sockaddr_in sinaddr; int srvidx; @@ -877,9 +881,9 @@ realm_new_server(sin, notice, realm) static Code_t realm_set_server(sin, realm) struct sockaddr_in *sin; - Realm *realm; + ZRealm *realm; { - Realm *rlm; + ZRealm *rlm; rlm = realm_which_realm(sin); /* Not exactly */ @@ -894,7 +898,7 @@ realm_handoff(notice, auth, who, realm, ack_to_sender) ZNotice_t *notice; int auth; struct sockaddr_in *who; - Realm *realm; + ZRealm *realm; int ack_to_sender; { #ifdef HAVE_KRB4 @@ -917,7 +921,7 @@ realm_handoff(notice, auth, who, realm, ack_to_sender) zdbug((LOG_DEBUG, "realm_sendit to realm %s auth %d", realm->name, auth)); /* valid ticket available now, send the message */ - realm_sendit_auth(notice, who, auth, realm, ack_to_sender); + retval = realm_sendit_auth(notice, who, auth, realm, ack_to_sender); #else /* HAVE_KRB4 */ realm_sendit(notice, who, auth, realm, ack_to_sender); #endif /* HAVE_KRB4 */ @@ -928,7 +932,7 @@ realm_sendit(notice, who, auth, realm, ack_to_sender) ZNotice_t *notice; struct sockaddr_in *who; int auth; - Realm *realm; + ZRealm *realm; int ack_to_sender; { caddr_t pack; @@ -1009,7 +1013,7 @@ rlm_rexmit(arg) { Unacked *nackpacket = (Unacked *) arg; Code_t retval; - register Realm *realm; + register ZRealm *realm; int new_srv_idx; zdbug((LOG_DEBUG,"rlm_rexmit")); @@ -1100,12 +1104,12 @@ realm_dump_realms(fp) } #ifdef HAVE_KRB4 -static void +static Code_t realm_sendit_auth(notice, who, auth, realm, ack_to_sender) ZNotice_t *notice; int auth; struct sockaddr_in *who; - Realm *realm; + ZRealm *realm; int ack_to_sender; { char *buffer, *ptr; @@ -1115,33 +1119,27 @@ realm_sendit_auth(notice, who, auth, realm, ack_to_sender) Code_t retval; Unacked *nacked; char buf[1024], multi[64]; - CREDENTIALS cred; - KTEXT_ST authent; ZNotice_t partnotice, newnotice; offset = 0; - /* build an authent. first, make sure we have the ticket available */ - retval = krb_get_cred(SERVER_SERVICE, SERVER_INSTANCE, realm->name, &cred); - if (retval != GC_OK) { - syslog(LOG_WARNING, "rlm_sendit_auth get_cred: %s", - error_message(retval+krb_err_base)); - return; + buffer = (char *) malloc(sizeof(ZPacket_t)); + if (!buffer) { + syslog(LOG_ERR, "realm_sendit_auth malloc"); + return ENOMEM; /* DON'T put on nack list */ } - retval = krb_mk_req(&authent, SERVER_SERVICE, SERVER_INSTANCE, - realm->name, 1); - if (retval != MK_AP_OK) { - syslog(LOG_WARNING, "rlm_sendit_auth mk_req: %s", - error_message(retval+krb_err_base)); - return; - } + buffer_len = sizeof(ZPacket_t); + + newnotice = *notice; - retval = ZMakeAscii(buf, sizeof(buf), authent.dat, authent.length); + hdrlen = 0; + retval = ZMakeZcodeRealmAuthentication(&newnotice, buffer, buffer_len, + &hdrlen, realm->name); if (retval != ZERR_NONE) { - syslog(LOG_WARNING, "rlm_sendit_auth mk_ascii: %s", + syslog(LOG_WARNING, "rlm_sendit_auth set addr: %s", error_message(retval)); - return; + return (retval); } /* set the dest addr */ @@ -1149,45 +1147,7 @@ realm_sendit_auth(notice, who, auth, realm, ack_to_sender) if (retval != ZERR_NONE) { syslog(LOG_WARNING, "rlm_sendit_auth set addr: %s", error_message(retval)); - return; - } - - /* now format the notice, refragmenting if needed */ - newnotice = *notice; - newnotice.z_auth = 1; - newnotice.z_ascii_authent = buf; - newnotice.z_authent_len = authent.length; - - buffer = (char *) malloc(sizeof(ZPacket_t)); - if (!buffer) { - syslog(LOG_ERR, "realm_sendit_auth malloc"); - return; /* DON'T put on nack list */ - } - - buffer_len = sizeof(ZPacket_t); - - retval = Z_FormatRawHeader(&newnotice, buffer, buffer_len, &hdrlen, &ptr, - NULL); - if (retval != ZERR_NONE) { - syslog(LOG_WARNING, "rlm_sendit_auth raw: %s", error_message(retval)); - free(buffer); - return; - } - -#ifdef NOENCRYPTION - newnotice.z_checksum = 0; -#else - newnotice.z_checksum = - (ZChecksum_t)des_quad_cksum(buffer, NULL, ptr - buffer, 0, - cred.session); -#endif - - retval = Z_FormatRawHeader(&newnotice, buffer, buffer_len, &hdrlen, - NULL, NULL); - if (retval != ZERR_NONE) { - syslog(LOG_WARNING, "rlm_sendit_auth raw: %s", error_message(retval)); - free(buffer); - return; + return (retval); } /* This is not terribly pretty, but it does do its job. @@ -1199,16 +1159,13 @@ realm_sendit_auth(notice, who, auth, realm, ack_to_sender) * but only the server uses it. */ - if ((newnotice.z_message_len+hdrlen > buffer_len) || - (newnotice.z_message_len+hdrlen > Z_MAXPKTLEN)) { - /* Deallocate buffer, use a local one */ + if ((notice->z_message_len+hdrlen > buffer_len) || + (notice->z_message_len+hdrlen > Z_MAXPKTLEN)) { + + /* Reallocate buffers inside the refragmenter */ free(buffer); - - partnotice = *notice; - partnotice.z_auth = 1; - partnotice.z_ascii_authent = buf; - partnotice.z_authent_len = authent.length; + partnotice = *notice; origoffset = 0; origlen = notice->z_message_len; @@ -1217,7 +1174,7 @@ realm_sendit_auth(notice, who, auth, realm, ack_to_sender) if (sscanf(notice->z_multinotice, "%d/%d", &origoffset, &origlen) != 2) { syslog(LOG_WARNING, "rlm_sendit_auth frag: parse failed"); - return; + return ZERR_BADFIELD; } #if 0 @@ -1252,33 +1209,19 @@ realm_sendit_auth(notice, who, auth, realm, ack_to_sender) buffer = (char *) malloc(sizeof(ZPacket_t)); if (!buffer) { syslog(LOG_ERR, "realm_sendit_auth malloc"); - return; /* DON'T put on nack list */ + return ENOMEM; /* DON'T put on nack list */ } - - retval = Z_FormatRawHeader(&partnotice, buffer, buffer_len, - &hdrlen, &ptr, NULL); - if (retval != ZERR_NONE) { - syslog(LOG_WARNING, "rlm_sendit_auth raw: %s", - error_message(retval)); - free(buffer); - return; - } - -#ifdef NOENCRYPTION - partnotice.z_checksum = 0; -#else - partnotice.z_checksum = - (ZChecksum_t)des_quad_cksum(buffer, NULL, ptr - buffer, 0, - cred.session); -#endif - retval = Z_FormatRawHeader(&partnotice, buffer, buffer_len, - &hdrlen, NULL, NULL); + buffer_len = sizeof(ZPacket_t); + + retval = ZMakeZcodeRealmAuthentication(&partnotice, buffer, + buffer_len, &hdrlen, + realm->name); if (retval != ZERR_NONE) { - syslog(LOG_WARNING, "rlm_sendit_auth raw: %s", + syslog(LOG_WARNING, "rlm_sendit_auth set addr: %s", error_message(retval)); free(buffer); - return; + return (retval); } ptr = buffer+hdrlen; @@ -1292,14 +1235,14 @@ realm_sendit_auth(notice, who, auth, realm, ack_to_sender) syslog(LOG_WARNING, "rlm_sendit_auth xmit: %s", error_message(retval)); free(buffer); - return; + return(retval); } if (!(nacked = (Unacked *)malloc(sizeof(Unacked)))) { /* no space: just punt */ syslog(LOG_ERR, "rlm_sendit_auth nack malloc"); free(buffer); - return; + return ENOMEM; } nacked->rexmits = 0; @@ -1326,35 +1269,30 @@ realm_sendit_auth(notice, who, auth, realm, ack_to_sender) if (!notice->z_message_len) break; } -#if 0 - zdbug((LOG_DEBUG, "rlm_sendit_auth frag message sent")); -#endif - } else { + } + else { /* This is easy, no further fragmentation needed */ ptr = buffer+hdrlen; (void) memcpy(ptr, newnotice.z_message, newnotice.z_message_len); - buffer_len = hdrlen+newnotice.z_message_len; + buffer_len = hdrlen+newnotice.z_message_len; /* now send */ if ((retval = ZSendPacket(buffer, buffer_len, 0)) != ZERR_NONE) { syslog(LOG_WARNING, "rlm_sendit_auth xmit: %s", error_message(retval)); free(buffer); - return; + return(retval); } -#if 0 - zdbug((LOG_DEBUG, "rlm_sendit_auth message sent")); -#endif /* now we've sent it, mark it as not ack'ed */ if (!(nacked = (Unacked *)malloc(sizeof(Unacked)))) { /* no space: just punt */ syslog(LOG_ERR, "rlm_sendit_auth nack malloc"); free(buffer); - return; + return 0; } nacked->rexmits = 0; @@ -1375,61 +1313,103 @@ realm_sendit_auth(notice, who, auth, realm, ack_to_sender) /* chain in */ LIST_INSERT(&rlm_nacklist, nacked); } - return; -} - -static int -ticket_expired(cred) -CREDENTIALS *cred; -{ -#ifdef HAVE_KRB_LIFE_TO_TIME - return (krb_life_to_time(cred->issue_date, cred->lifetime) < NOW); -#else /* HAVE_KRB_LIFE_TO_TIME */ - return (cred->issue_date + cred->lifetime*5*60 < NOW); -#endif /* HAVE_KRB_LIFE_TO_TIME */ + return 0; } static int ticket_lookup(realm) char *realm; { - CREDENTIALS cred; - KTEXT_ST authent; - int retval; + krb5_error_code result; + krb5_timestamp sec; + krb5_ccache ccache; + krb5_creds creds_in, *creds; - retval = krb_get_cred(SERVER_SERVICE, SERVER_INSTANCE, realm, &cred); - if (retval == GC_OK && !ticket_expired(&cred)) - /* good ticket */ - return(1); + result = krb5_cc_default(Z_krb5_ctx, &ccache); + if (result) + return 0; + + memset(&creds_in, 0, sizeof(creds_in)); + + result = krb5_cc_get_principal(Z_krb5_ctx, ccache, &creds_in.client); + if (result) { + krb5_cc_close(Z_krb5_ctx, ccache); + return 0; + } + + result = krb5_build_principal(Z_krb5_ctx, &creds_in.server, + strlen(realm), + realm, + SERVER_KRB5_SERVICE, SERVER_INSTANCE, 0); + if (result) { + krb5_cc_close(Z_krb5_ctx, ccache); + return 0; + } + + result = krb5_get_credentials(Z_krb5_ctx, 0 /* flags */, ccache, + &creds_in, &creds); + krb5_cc_close(Z_krb5_ctx, ccache); + /* good ticket? */ + + krb5_timeofday (Z_krb5_ctx, &sec); + krb5_free_cred_contents(Z_krb5_ctx, &creds_in); /* hope this is OK */ + if ((result == 0) && (sec < creds->times.endtime)) { + krb5_free_creds(Z_krb5_ctx, creds); + return (1); + } + if (!result) krb5_free_creds(Z_krb5_ctx, creds); return (0); } static Code_t ticket_retrieve(realm) - Realm *realm; + ZRealm *realm; { - int pid, retval = 0; - KTEXT_ST authent; + int pid; + krb5_ccache ccache; + krb5_error_code result; + krb5_auth_context authctx; + krb5_creds creds_in, *creds; get_tgt(); if (realm->child_pid) /* Right idea. Basically, we haven't gotten it yet */ - return KRBET_KDC_AUTH_EXP; - - /* For Putrify */ - memset(&authent.dat,0,MAX_KTXT_LEN); - authent.mbz=0; + return KRB5KRB_AP_ERR_TKT_EXPIRED; if (realm->have_tkt) { - retval = krb_mk_req(&authent, SERVER_SERVICE, SERVER_INSTANCE, - realm->name, 0); - if (retval == KSUCCESS) { - return retval; + /* Get a pointer to the default ccache. We don't need to free this. */ + result = krb5_cc_default(Z_krb5_ctx, &ccache); + + /* GRRR. There's no allocator or constructor for krb5_creds */ + /* GRRR. It would be nice if this API were documented at all */ + memset(&creds_in, 0, sizeof(creds_in)); + + if (!result) + result = krb5_cc_get_principal(Z_krb5_ctx, ccache, &creds_in.client); + /* construct the service principal */ + if (!result) + result = krb5_build_principal(Z_krb5_ctx, &creds_in.server, + strlen(realm->name), realm->name, + SERVER_KRB5_SERVICE, SERVER_INSTANCE, + 0); + + /* HOLDING: creds_in.server */ + + /* look up or get the credentials we need */ + if (!result) + result = krb5_get_credentials(Z_krb5_ctx, 0 /* flags */, ccache, + &creds_in, &creds); + krb5_cc_close(Z_krb5_ctx, ccache); + krb5_free_cred_contents(Z_krb5_ctx, &creds_in); /* hope this is OK */ + if (!result) { + krb5_free_creds(Z_krb5_ctx, creds); + return 0; } } else { syslog(LOG_ERR, "tkt_rtrv: don't have ticket, but have no child"); + result = KRB5KRB_AP_ERR_TKT_EXPIRED; } pid = fork(); @@ -1467,11 +1447,37 @@ ticket_retrieve(realm) #endif #endif + syslog(LOG_INFO, "tkt_rtrv running for %s", realm->name); while (1) { - retval = krb_mk_req(&authent, SERVER_SERVICE, SERVER_INSTANCE, - realm->name, 0); - if (retval == KSUCCESS) + /* Get a pointer to the default ccache. We don't need to free this. */ + result = krb5_cc_default(Z_krb5_ctx, &ccache); + + /* GRRR. There's no allocator or constructor for krb5_creds */ + /* GRRR. It would be nice if this API were documented at all */ + memset(&creds_in, 0, sizeof(creds_in)); + + if (!result) + result = krb5_cc_get_principal(Z_krb5_ctx, ccache, &creds_in.client); + /* construct the service principal */ + if (!result) + result = krb5_build_principal(Z_krb5_ctx, &creds_in.server, + strlen(realm->name), realm->name, + SERVER_KRB5_SERVICE, SERVER_INSTANCE, + 0); + + /* HOLDING: creds_in.server */ + + /* look up or get the credentials we need */ + if (!result) + result = krb5_get_credentials(Z_krb5_ctx, 0 /* flags */, ccache, + &creds_in, &creds); + krb5_cc_close(Z_krb5_ctx, ccache); + krb5_free_cred_contents(Z_krb5_ctx, &creds_in); /* hope this is OK */ + if (!result) { + krb5_free_creds(Z_krb5_ctx, creds); + syslog(LOG_INFO, "tkt_rtrv succeeded for %s", realm->name); exit(0); + } /* Sleep a little while before retrying */ sleep(30); @@ -1479,10 +1485,10 @@ ticket_retrieve(realm) } else { realm->child_pid = pid; realm->have_tkt = 0; - - syslog(LOG_WARNING, "tkt_rtrv: %s: %s", realm->name, - krb_err_txt[retval]); - return (retval+krb_err_base); + + syslog(LOG_WARNING, "tkt_rtrv: %s: %d", realm->name, + result); + return (result); } } #endif /* HAVE_KRB4 */ diff --git a/server/server.c b/server/server.c index 5cce0ff..c2c6421 100644 --- a/server/server.c +++ b/server/server.c @@ -880,7 +880,7 @@ send_stats(who) char **responses; int num_resp; char *vers, *pkts, *upt; - Realm *realm; + ZRealm *realm; int extrafields = 0; #define NUM_FIXED 3 /* 3 fixed fields, plus server info */ @@ -1381,7 +1381,11 @@ server_forward(notice, auth, who) syslog(LOG_CRIT, "srv_fwd malloc"); abort(); } - retval = ZFormatSmallRawNotice(notice, pack, &packlen); + if (realm_which_realm(who)) { + retval = ZNewFormatSmallRawNotice(notice, pack, &packlen); + } else { + retval = ZFormatSmallRawNotice(notice, pack, &packlen); + } if (retval != ZERR_NONE) { syslog(LOG_WARNING, "srv_fwd format: %s", error_message(retval)); continue; diff --git a/server/subscr.c b/server/subscr.c index b5da880..49d3211 100644 --- a/server/subscr.c +++ b/server/subscr.c @@ -95,10 +95,10 @@ static char **subscr_marshal_subs __P((ZNotice_t *notice, int auth, int *found)); static Destlist *subscr_copy_def_subs __P((char *person)); static Code_t subscr_realm_sendit __P((Client *who, Destlist *subs, - ZNotice_t *notice, Realm *realm)); + ZNotice_t *notice, ZRealm *realm)); static void subscr_unsub_realms __P((Destlist *newsubs)); static void subscr_unsub_sendit __P((Client *who, Destlist *subs, - Realm *realm)); + ZRealm *realm)); static int cl_match __P((Destlist*, Client *)); static int defaults_read = 0; /* set to 1 if the default subs @@ -140,7 +140,7 @@ add_subscriptions(who, subs, notice, server) Code_t retval; Acl *acl; String *sender; - Realm *realm = NULL; + ZRealm *realm = NULL; if (!subs) return ZERR_NONE; /* no subscr -> no error */ @@ -187,18 +187,14 @@ add_subscriptions(who, subs, notice, server) } } if (realm && !bdumping) { - if (server && server == me_server) { retval = subscr_realm_sendit(who, subs, notice, realm); if (retval != ZERR_NONE) { - free_subscriptions(subs); - free_string(sender); - return(retval); - } else { - /* free this one, will get from ADD */ free_subscription(subs); - } + continue; /* the for loop */ } else { /* Indicates we leaked traffic back to our realm */ + free_subscription(subs); /* free this one, wil get from + ADD */ } } else { retval = triplet_register(who, &subs->dest, NULL); @@ -333,7 +329,7 @@ subscr_cancel(sin, notice) struct sockaddr_in *sin; ZNotice_t *notice; { - Realm *realm; + ZRealm *realm; Client *who; Destlist *cancel_subs, *subs, *cancel_next, *client_subs, *client_next; Code_t retval; @@ -396,7 +392,7 @@ Code_t subscr_realm_cancel(sin, notice, realm) struct sockaddr_in *sin; ZNotice_t *notice; - Realm *realm; + ZRealm *realm; { Client *who; Destlist *cancel_subs, *subs, *client_subs, *next, *next2; @@ -452,7 +448,7 @@ subscr_cancel_client(client) { Destlist *subs, *next; Code_t retval; - Realm *realm; + ZRealm *realm; #if 0 zdbug((LOG_DEBUG,"subscr_cancel_client %s", @@ -557,7 +553,7 @@ subscr_marshal_subs(notice, auth, who, found) zdbug((LOG_DEBUG, "subscr_marshal")); #endif *found = 0; - + /* Note that the following code is an incredible crock! */ /* We cannot send multiple packets as acknowledgements to the client, @@ -842,10 +838,15 @@ subscr_send_subs(client) { int i = 0; Destlist *subs; +#ifdef HAVE_KRB5 + char buf[512]; + char *bufp; +#else #ifdef HAVE_KRB4 char buf[512]; C_Block cblock; #endif /* HAVE_KRB4 */ +#endif char buf2[512]; char *list[7 * NUM_FIELDS]; int num = 0; @@ -858,14 +859,45 @@ subscr_send_subs(client) list[num++] = buf2; +#ifdef HAVE_KRB5 +#ifdef HAVE_KRB4 /* XXX make this optional for server transition time */ + if (client->session_keyblock->enctype == ENCTYPE_DES_CBC_CRC) { + bufp = malloc(client->session_keyblock->length); + if (bufp == NULL) { + syslog(LOG_WARNING, "subscr_send_subs: cannot allocate memory for DES keyblock: %m"); + return errno; + } + des_ecb_encrypt(client->session_keyblock->contents, bufp, serv_ksched.s, DES_ENCRYPT); + retval = ZMakeAscii(buf, sizeof(buf), bufp, client->session_keyblock->length); + } else { +#endif + bufp = malloc(client->session_keyblock->length + 8); /* + enctype + + length */ + if (bufp == NULL) { + syslog(LOG_WARNING, "subscr_send_subs: cannot allocate memory for keyblock: %m"); + return errno; + } + *(krb5_enctype *)&bufp[0] = htonl(client->session_keyblock->enctype); + *(krb5_ui_4 *)&bufp[4] = htonl(client->session_keyblock->length); + memcpy(&bufp[8], client->session_keyblock->contents, client->session_keyblock->length); + + retval = ZMakeZcode(buf, sizeof(buf), bufp, client->session_keyblock->length + 8); +#ifdef HAVE_KRB4 + } +#endif /* HAVE_KRB4 */ +#else /* HAVE_KRB5 */ #ifdef HAVE_KRB4 #ifdef NOENCRYPTION memcpy(cblock, client->session_key, sizeof(C_Block)); -#else +#else /* NOENCRYPTION */ des_ecb_encrypt(client->session_key, cblock, serv_ksched.s, DES_ENCRYPT); -#endif +#endif /* NOENCRYPTION */ retval = ZMakeAscii(buf, sizeof(buf), cblock, sizeof(C_Block)); +#endif /* HAVE_KRB4 */ +#endif /* HAVE_KRB5 */ + +#if defined(HAVE_KRB4) || defined(HAVE_KRB5) if (retval != ZERR_NONE) { #if 0 zdbug((LOG_DEBUG,"zmakeascii failed: %s", error_message(retval))); @@ -876,7 +908,7 @@ subscr_send_subs(client) zdbug((LOG_DEBUG, "cblock %s", buf)); #endif } -#endif /* HAVE_KRB4 */ +#endif /* HAVE_KRB4 || HAVE_KRB5*/ retval = bdump_send_list_tcp(SERVACK, &client->addr, ZEPHYR_ADMIN_CLASS, num > 1 ? "CBLOCK" : "", ADMIN_NEWCLT, client->principal->string, "", list, num); @@ -1047,7 +1079,7 @@ subscr_realm_sendit(who, subs, notice, realm) Client *who; Destlist *subs; ZNotice_t *notice; - Realm *realm; + ZRealm *realm; { ZNotice_t snotice; char *pack; @@ -1132,7 +1164,7 @@ subscr_realm_sendit(who, subs, notice, realm) static Code_t subscr_add_raw(client, realm, newsubs) Client *client; - Realm *realm; + ZRealm *realm; Destlist *newsubs; { Destlist *subs, *subs2, *subs3, **head; @@ -1162,7 +1194,7 @@ subscr_add_raw(client, realm, newsubs) } } else { if (!realm) { - Realm *remrealm = + ZRealm *remrealm = realm_get_realm_by_name(subs->dest.recip->string + 1); if (remrealm) { Destlist *sub = (Destlist *) malloc(sizeof(Destlist)); @@ -1190,7 +1222,7 @@ subscr_add_raw(client, realm, newsubs) /* Called from bdump_recv_loop to decapsulate realm subs */ Code_t subscr_realm(realm, notice) - Realm *realm; + ZRealm *realm; ZNotice_t *notice; { Destlist *newsubs; @@ -1210,7 +1242,7 @@ static void subscr_unsub_sendit(who, subs, realm) Client *who; Destlist *subs; - Realm *realm; + ZRealm *realm; { ZNotice_t unotice; Code_t retval; @@ -1275,7 +1307,7 @@ subscr_unsub_sendit(who, subs, realm) /* Called from bump_send_loop by way of realm_send_realms */ Code_t subscr_send_realm_subs(realm) - Realm *realm; + ZRealm *realm; { int i = 0; Destlist *subs, *next; @@ -1342,7 +1374,7 @@ subscr_send_realm_subs(realm) Code_t subscr_realm_subs(realm) - Realm *realm; + ZRealm *realm; { int i = 0; Destlist *subs, *next; @@ -1431,7 +1463,7 @@ subscr_check_foreign_subs(notice, who, server, realm, newsubs) ZNotice_t *notice; struct sockaddr_in *who; Server *server; - Realm *realm; + ZRealm *realm; Destlist *newsubs; { Destlist *subs, *subs2, *next; @@ -1470,7 +1502,7 @@ subscr_check_foreign_subs(notice, who, server, realm, newsubs) found = 0; for (subs = newsubs; subs; subs = next) { - Realm *rlm; + ZRealm *rlm; next=subs->next; if (subs->dest.recip->string[0] != '\0') { rlm = realm_which_realm(who); @@ -1566,7 +1598,7 @@ Code_t subscr_foreign_user(notice, who, server, realm) ZNotice_t *notice; struct sockaddr_in *who; Server *server; - Realm *realm; + ZRealm *realm; { Destlist *newsubs, *temp; Acl *acl; @@ -1640,7 +1672,7 @@ Code_t subscr_foreign_user(notice, who, server, realm) temp->dest.recip = make_string(rlm_recipient, 0); } - status = subscr_add_raw(client, (Realm *)0, newsubs); + status = subscr_add_raw(client, (ZRealm *)0, newsubs); } else if (!strcmp(snotice.z_opcode, REALM_REQ_SUBSCRIBE)) { zdbug((LOG_DEBUG, "subscr_foreign_user REQ %s/%s", tp0, tp1)); status = subscr_check_foreign_subs(notice, who, server, realm, newsubs); diff --git a/server/uloc.c b/server/uloc.c index 0d7ea8e..66071cf 100644 --- a/server/uloc.c +++ b/server/uloc.c @@ -106,7 +106,7 @@ static int ul_equiv __P((Location *l1, Location *l2)); static void free_loc __P((Location *loc)); static void ulogin_locate_forward __P((ZNotice_t *notice, - struct sockaddr_in *who, Realm *realm)); + struct sockaddr_in *who, ZRealm *realm)); static Location *locations = NULL; /* ptr to first in array */ static int num_locs = 0; /* number in array */ @@ -241,7 +241,11 @@ ulogin_dispatch(notice, auth, who, server) login_sendit(notice, auth, who, 1); } } else { - syslog(LOG_ERR, "unknown ulog opcode %s", notice->z_opcode); + if (!strcmp(notice->z_opcode, LOGIN_USER_LOGIN)) + zdbug((LOG_DEBUG, "ulog opcode from unknown foreign realm %s", + notice->z_opcode)); + else + syslog(LOG_ERR, "unknown ulog opcode %s", notice->z_opcode); if (server == me_server) nack(notice, who); return ZERR_NONE; @@ -282,7 +286,7 @@ ulocate_dispatch(notice, auth, who, server) Server *server; { char *cp; - Realm *realm; + ZRealm *realm; if (!strcmp(notice->z_opcode, LOCATE_LOCATE)) { /* we are talking to a current-rev client; send an ack */ @@ -294,7 +298,7 @@ ulocate_dispatch(notice, auth, who, server) ulogin_locate(notice, who, auth); return ZERR_NONE; } else { - syslog(LOG_ERR, "unknown uloc opcode %s", notice->z_opcode); + syslog(LOG_ERR, "unknown uloc opcode %s", notice->z_opcode); if (server == me_server) nack(notice, who); return ZERR_NONE; @@ -441,6 +445,7 @@ uloc_send_locations() default: syslog(LOG_ERR,"broken location state %s/%d", loc->user->string, (int) loc->exposure); + exposure_level = EXPOSE_OPSTAFF; break; } retval = bdump_send_list_tcp(ACKED, &loc->addr, LOGIN_CLASS, @@ -1004,7 +1009,7 @@ static void ulogin_locate_forward(notice, who, realm) ZNotice_t *notice; struct sockaddr_in *who; - Realm *realm; + ZRealm *realm; { ZNotice_t lnotice; @@ -1018,7 +1023,7 @@ void ulogin_realm_locate(notice, who, realm) ZNotice_t *notice; struct sockaddr_in *who; - Realm *realm; + ZRealm *realm; { char **answer; int found; diff --git a/server/zserver.h b/server/zserver.h index 221e26b..981a000 100644 --- a/server/zserver.h +++ b/server/zserver.h @@ -17,6 +17,9 @@ #include <zephyr/mit-copyright.h> #include <internal.h> + +#include <com_err.h> + #include <arpa/inet.h> #include "zsrv_err.h" @@ -28,10 +31,19 @@ #include "access.h" #include "acl.h" -#ifdef HAVE_KRB4 +#if defined(HAVE_KRB5) || defined(HAVE_KRB4) /* Kerberos-specific library interfaces used only by the server. */ +#ifdef HAVE_KRB5 +extern krb5_keyblock *__Zephyr_keyblock; +#define ZGetSession() (__Zephyr_keyblock) +void ZSetSession(krb5_keyblock *keyblock); +Code_t ZFormatAuthenticNoticeV5 __P((ZNotice_t*, char*, int, int*, krb5_keyblock *)); +#else extern C_Block __Zephyr_session; #define ZGetSession() (__Zephyr_session) +#endif +void ZSetSessionDES(C_Block *key); + Code_t ZFormatAuthenticNotice __P((ZNotice_t*, char*, int, int*, C_Block)); #endif @@ -67,9 +79,9 @@ typedef struct { typedef struct _Destination Destination; typedef struct _Destlist Destlist; -typedef struct _Realm Realm; -typedef struct _Realmname Realmname; -typedef enum _Realm_state Realm_state; +typedef struct _ZRealm ZRealm; +typedef struct _ZRealmname ZRealmname; +typedef enum _ZRealm_state ZRealm_state; typedef struct _Client Client; typedef struct _Triplet Triplet; typedef enum _Server_state Server_state; @@ -90,14 +102,14 @@ struct _Destlist { struct _Destlist *next, **prev_p; }; -enum _Realm_state { - REALM_UP, /* Realm is up */ - REALM_TARDY, /* Realm due for a hello XXX */ - REALM_DEAD, /* Realm is considered dead */ - REALM_STARTING /* Realm is between dead and up */ +enum _ZRealm_state { + REALM_UP, /* ZRealm is up */ + REALM_TARDY, /* ZRealm due for a hello XXX */ + REALM_DEAD, /* ZRealm is considered dead */ + REALM_STARTING /* ZRealm is between dead and up */ }; -struct _Realm { +struct _ZRealm { char name[REALM_SZ]; int count; struct sockaddr_in *addrs; @@ -107,10 +119,10 @@ struct _Realm { Client *client; int child_pid; int have_tkt; - Realm_state state; + ZRealm_state state; }; -struct _Realmname { +struct _ZRealmname { char name[REALM_SZ]; char **servers; int nused; @@ -120,13 +132,17 @@ struct _Realmname { struct _Client { struct sockaddr_in addr; /* ipaddr/port of client */ Destlist *subs ; /* subscriptions */ +#ifdef HAVE_KRB5 + krb5_keyblock *session_keyblock; +#else #ifdef HAVE_KRB4 C_Block session_key; /* session key for this client */ #endif /* HAVE_KRB4 */ +#endif String *principal; /* krb principal of user */ int last_send; /* Counter for last sent packet. */ time_t last_ack; /* Time of last received ack */ - Realm *realm; + ZRealm *realm; struct _Client *next, **prev_p; }; @@ -215,9 +231,9 @@ int get_tgt __P((void)); extern String *class_control, *class_admin, *class_hm; extern String *class_ulogin, *class_ulocate; int ZDest_eq __P((Destination *d1, Destination *d2)); -Code_t triplet_register __P((Client *client, Destination *dest, Realm *realm)); +Code_t triplet_register __P((Client *client, Destination *dest, ZRealm *realm)); Code_t triplet_deregister __P((Client *client, Destination *dest, - Realm *realm)); + ZRealm *realm)); Code_t class_restrict __P((char *class, Acl *acl)); Code_t class_setup_restricted __P((char *class, Acl *acl)); Client **triplet_lookup __P((Destination *dest)); @@ -268,7 +284,7 @@ void sweep_ticket_hash_table __P((void *)); #ifndef NOENCRYPTION Sched *check_key_sched_cache __P((des_cblock key)); void add_to_key_sched_cache __P((des_cblock key, Sched *sched)); -int krb_set_key __P((char *key, int cvt)); +/*int krb_set_key __P((void *key, int cvt));*/ /* int krb_rd_req __P((KTEXT authent, char *service, char *instance, unsigned KRB_INT32 from_addr, AUTH_DAT *ad, char *fn)); */ int krb_find_ticket __P((KTEXT authent, KTEXT ticket)); @@ -297,7 +313,7 @@ Code_t server_adispatch __P((ZNotice_t *notice, int auth, struct sockaddr_in *who, Server *server)); /* found in subscr.c */ -Code_t subscr_foreign_user __P((ZNotice_t *, struct sockaddr_in *, Server *, Realm *)); +Code_t subscr_foreign_user __P((ZNotice_t *, struct sockaddr_in *, Server *, ZRealm *)); Code_t subscr_cancel __P((struct sockaddr_in *sin, ZNotice_t *notice)); Code_t subscr_subscribe __P((Client *who, ZNotice_t *notice, Server *server)); Code_t subscr_send_subs __P((Client *client)); @@ -321,16 +337,16 @@ Code_t uloc_send_locations __P((void)); /* found in realm.c */ int realm_sender_in_realm __P((char *realm, char *sender)); int realm_bound_for_realm __P((char *realm, char *recip)); -Realm *realm_which_realm __P((struct sockaddr_in *who)); -Realm *realm_get_realm_by_name __P((char *name)); -Realm *realm_get_realm_by_pid __P((int)); -void realm_handoff(ZNotice_t *, int, struct sockaddr_in *, Realm *, int); +ZRealm *realm_which_realm __P((struct sockaddr_in *who)); +ZRealm *realm_get_realm_by_name __P((char *name)); +ZRealm *realm_get_realm_by_pid __P((int)); +void realm_handoff(ZNotice_t *, int, struct sockaddr_in *, ZRealm *, int); char *realm_expand_realm(char *); void realm_init __P((void)); -Code_t ZCheckRealmAuthentication __P((ZNotice_t *, struct sockaddr_in *, +Code_t ZCheckZRealmAuthentication __P((ZNotice_t *, struct sockaddr_in *, char *)); Code_t realm_control_dispatch __P((ZNotice_t *, int, struct sockaddr_in *, - Server *, Realm *)); + Server *, ZRealm *)); void realm_shutdown __P((void)); void realm_deathgram __P((Server *)); @@ -355,6 +371,10 @@ extern int nfds; /* number to look at in select() */ extern int zdebug; extern char myname[]; /* domain name of this host */ extern char list_file[]; +#ifdef HAVE_KRB5 +extern char keytab_file[]; +extern krb5_ccache Z_krb5_ccache; +#endif #ifdef HAVE_KRB4 extern char srvtab_file[]; extern char my_realm[]; @@ -385,7 +405,7 @@ extern int nservers; /* number of other servers*/ extern String *empty; extern String *wildcard_instance; -extern Realm *otherrealms; +extern ZRealm *otherrealms; extern int nrealms; extern struct in_addr my_addr; /* my inet address */ diff --git a/server/zsrv_conf.h b/server/zsrv_conf.h index 7b663da..5508e3a 100644 --- a/server/zsrv_conf.h +++ b/server/zsrv_conf.h @@ -18,6 +18,10 @@ #define SERVER_LIST_FILE "server.list" #define REALM_LIST_FILE "realm.list" +#ifdef HAVE_KRB5 +#define ZEPHYR_KEYTAB "krb5.keytab" +#define ZEPHYR_TK5FILE "z5tkts" +#endif #ifdef HAVE_KRB4 #define ZEPHYR_SRVTAB "srvtab" #define ZEPHYR_TKFILE "ztkts" diff --git a/server/zsrv_err.et b/server/zsrv_err.et index de48f21..36d6a3f 100644 --- a/server/zsrv_err.et +++ b/server/zsrv_err.et @@ -13,7 +13,7 @@ ec ZSRV_NOCLT, ec ZSRV_NOSUB, "No such subscription" ec ZSRV_NOCLASS, - "Class unkown" + "Class unknown" ec ZSRV_CLASSXISTS, "Class already registered" ec ZSRV_CLASSRESTRICTED, |