summaryrefslogtreecommitdiff
path: root/server
diff options
context:
space:
mode:
authorGravatar Karl Ramm <kcr@mit.edu>2007-12-25 00:56:08 +0000
committerGravatar Karl Ramm <kcr@mit.edu>2007-12-25 00:56:08 +0000
commit1a0e03eb19998ab496a6ea845ff2c42d9a02df0b (patch)
tree29b47c8532e1f1678063fbb1b851ee4208134626 /server
parent3f120f880be9ae9aa1612ddc2412e9acb9a8e85e (diff)
applied athena-update-branch patch
Diffstat (limited to 'server')
-rw-r--r--server/bdump.c229
-rw-r--r--server/class.c12
-rw-r--r--server/client.c10
-rw-r--r--server/dispatch.c60
-rw-r--r--server/kstuff.c811
-rw-r--r--server/main.c44
-rw-r--r--server/realm.c384
-rw-r--r--server/server.c8
-rw-r--r--server/subscr.c88
-rw-r--r--server/uloc.c17
-rw-r--r--server/zserver.h68
-rw-r--r--server/zsrv_conf.h4
-rw-r--r--server/zsrv_err.et2
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,