Milestone 7
* brain dump via krb5, encrypted
(optional) brain dump to/from file
-
-Milestone 8
- * bring sourceforge up to date
-
-Milestone 9
- * cough up a release of sourceforge
-
int (*pred) __P((ZNotice_t *, void *)), void *arg,
int timeout));
+
+Code_t Z_NewFormatHeader __P((ZNotice_t *, char *, int, int *, Z_AuthProc));
+Code_t Z_NewFormatAuthHeader __P((ZNotice_t *, char *, int, int *, Z_AuthProc));
+Code_t Z_NewFormatRawHeader __P((ZNotice_t *, char *, int, int *, char **,
+ int *, char **, char **));
+Code_t Z_AsciiFormatRawHeader __P((ZNotice_t *, char *, int, int *, char **,
+ int *, char **, char **));
+
void Z_gettimeofday(struct _ZTimeval *ztv, struct timezone *tz);
#ifdef HAVE_KRB5
Code_t Z_Checksum(krb5_data *cksumbuf, krb5_keyblock *keyblock, krb5_cksumtype cksumtype, char **asn1_data, int *asn1_len);
Code_t Z_ExtractEncCksum(krb5_keyblock *keyblock, krb5_enctype *enctype, krb5_cksumtype *cksumtype);
int Z_krb5_verify_cksum(krb5_keyblock *keyblock, krb5_data *cksumbuf, krb5_cksumtype cksumtype, char *asn1_data, int asn1_len);
-
+Code_t Z_InsertZcodeChecksum(krb5_keyblock *keyblock, ZNotice_t *notice,
+ char *buffer,
+ char *cksum_start, int cksum_len,
+ char *cstart, char *cend, int buffer_len,
+ int *length_ajdust);
#endif
#ifdef HAVE_KRB5_CREDS_KEYBLOCK_ENCTYPE
Code_t ZReadAscii ZP((char*, int, unsigned char*, int));
Code_t ZReadAscii32 ZP((char *, int, unsigned long *));
Code_t ZReadAscii16 ZP((char *, int, unsigned short *));
+Code_t ZReadZcode ZP((unsigned char*, unsigned char*, int, int *));
Code_t ZSendPacket ZP((char*, int, int));
Code_t ZSendList ZP((ZNotice_t*, char *[], int, Z_AuthProc));
Code_t ZSrvSendList ZP((ZNotice_t*, char*[], int, Z_AuthProc, Code_t (*)()));
Code_t ZMakeAscii ZP((char*, int, unsigned char*, int));
Code_t ZMakeAscii32 ZP((char *, int, unsigned long));
Code_t ZMakeAscii16 ZP((char *, int, unsigned int));
+Code_t ZMakeZcode ZP((char*, int, unsigned char*, int));
+Code_t ZMakeZcode32 ZP((char *, int, unsigned long));
Code_t ZReceivePacket ZP((ZPacket_t, int*, struct sockaddr_in*));
Code_t ZCheckAuthentication ZP((ZNotice_t*, struct sockaddr_in*));
Code_t ZCheckZcodeAuthentication ZP((ZNotice_t*, struct sockaddr_in*));
#include <internal.h>
-#ifdef HAVE_KRB4
+#if defined(HAVE_KRB4) || defined(HAVE_KRB5)
Code_t ZFormatAuthenticNotice(notice, buffer, buffer_len, len, session)
ZNotice_t *notice;
register char *buffer;
return (ZERR_NONE);
}
#endif
+
+#ifdef HAVE_KRB5
+Code_t ZFormatAuthenticNoticeV5(notice, buffer, buffer_len, len, keyblock)
+ ZNotice_t *notice;
+ register char *buffer;
+ register int buffer_len;
+ int *len;
+ krb5_keyblock *keyblock;
+{
+ ZNotice_t newnotice;
+ char *ptr;
+ int retval, hdrlen, hdr_adj;
+ krb5_enctype enctype;
+ krb5_cksumtype cksumtype;
+ int valid;
+ char *svcinst, *x, *y;
+ int key_len;
+ char *cksum_start, *cstart, *cend;
+ int cksum_len;
+
+ key_len = Z_keylen(keyblock);
+ retval = Z_ExtractEncCksum(keyblock, &enctype, &cksumtype);
+ if (retval)
+ return (ZAUTH_FAILED);
+
+ if (key_len == 8 && (enctype == ENCTYPE_DES_CBC_CRC ||
+ enctype == ENCTYPE_DES_CBC_MD4 ||
+ enctype == ENCTYPE_DES_CBC_MD5)) {
+ C_Block tmp;
+ memcpy(&tmp, Z_keydata(keyblock), key_len);
+ return ZFormatAuthenticNotice(notice, buffer, buffer_len, len,
+ tmp);
+ }
+
+ newnotice = *notice;
+ newnotice.z_auth = 1;
+ newnotice.z_authent_len = 0;
+ newnotice.z_ascii_authent = "";
+
+ if ((retval = Z_NewFormatRawHeader(&newnotice, buffer, buffer_len,
+ &hdrlen,
+ &cksum_start, &cksum_len, &cstart,
+ &cend)) != ZERR_NONE)
+ return (retval);
+
+ retval = Z_InsertZcodeChecksum(keyblock, &newnotice, buffer,
+ cksum_start, cksum_len, cstart, cend,
+ buffer_len, &hdr_adj);
+ if (retval)
+ return retval;
+
+ hdrlen += hdr_adj;
+
+ ptr = buffer+hdrlen;
+
+ if (newnotice.z_message_len+hdrlen > buffer_len)
+ return (ZERR_PKTLEN);
+
+ (void) memcpy(ptr, newnotice.z_message, newnotice.z_message_len);
+
+ *len = hdrlen+newnotice.z_message_len;
+
+ if (*len > Z_MAXPKTLEN)
+ return (ZERR_PKTLEN);
+
+ return (ZERR_NONE);
+}
+#endif
/* XXX check ticket file here */
code = krb5_get_default_realm(Z_krb5_ctx, &p);
strcpy(__Zephyr_realm, p);
+#ifdef HAVE_KRB5_FREE_DEFAULT_REALM
krb5_free_default_realm(Z_krb5_ctx, p);
+#else
+ free(p);
+#endif
if (code)
return code;
}
krb5_cksumtype cksumtype;
krb5_auth_context authctx;
krb5_data *authent;
- krb5_data cksumbuf;
char *svcinst, *x, *y;
char *cksum_start, *cstart, *cend, *asn1_data;
- int plain_len; /* length of part not to be checksummed */
- int cksum_len; /* length of part to be checksummed (incl cksum) */
- int cksum0_len; /* length of part before checksum */
- int cksum1_len; /* length of part after checksum */
- int i, zcode_len, asn1_len;
+ int i, cksum_len, zcode_len, asn1_len, phdr_adj;
result = ZGetCredsRealm(&creds, realm);
if (result)
/* Figure out what checksum type to use */
keyblock = Z_credskey(creds);
- result = Z_ExtractEncCksum(keyblock, &enctype, &cksumtype);
- if (result) {
- krb5_free_creds(Z_krb5_ctx, creds);
- return result;
- }
/* HOLDING: creds */
/* Create the authenticator */
krb5_free_creds(Z_krb5_ctx, creds);
return (result);
}
- /* HOLDING: creds */
-
- /* Assemble the things to be checksummed */
- plain_len = cksum_start - buffer;
- cksum0_len = cstart - cksum_start;
- cksum1_len = (cksum_start + cksum_len) - cend;
- memset(&cksumbuf, 0, sizeof(cksumbuf));
- cksumbuf.length = cksum0_len + cksum1_len + notice->z_message_len;
- cksumbuf.data = malloc(cksumbuf.length);
- if (!cksumbuf.data) {
- krb5_free_creds(Z_krb5_ctx, creds);
- return (ENOMEM);
- }
- /* HOLDING: creds, cksumbuf.data */
- memcpy(cksumbuf.data, cksum_start, cksum0_len);
- memcpy(cksumbuf.data + cksum0_len, cend, cksum1_len);
- memcpy(cksumbuf.data + cksum0_len + cksum1_len,
- notice->z_message, notice->z_message_len);
-
- /* compute the checksum */
- result = Z_Checksum(&cksumbuf, keyblock, cksumtype, &asn1_data, &asn1_len);
+ result = Z_InsertZcodeChecksum(keyblock, notice, buffer, cksum_start,
+ cksum_len, cstart, cend, buffer_len,
+ &phdr_adj);
krb5_free_creds(Z_krb5_ctx, creds);
if (result) {
- free(cksumbuf.data);
- return result;
+ return result;
}
-
- /*
- * OK.... we can zcode to a space starting at 'cstart',
- * with a length of buffer_len - (plain_len + cksum_len).
- * Then we tack on the end part, which is located at
- * cksumbuf.data + cksum0_len and has length cksum1_len
- */
- result = ZMakeZcode(cstart, buffer_len - (plain_len + cksum_len),
- asn1_data, asn1_len);
- if (!result) {
- zcode_len = strlen(cstart) + 1;
- memcpy(cstart + zcode_len, cksumbuf.data + cksum0_len, cksum1_len);
- *phdr_len -= cksum_len - (cksum0_len + cksum1_len);
- *phdr_len += zcode_len;
- }
-
- /* free stuff up, and then return the result from the last call */
-
- free(cksumbuf.data);
- free(asn1_data);
+ *phdr_len += phdr_adj;
return (result);
#endif /* HAVE_KRB5 */
krb5_cc_close(Z_krb5_ctx, ccache);
return result;
}
-
+
+#ifdef HAVE_KRB5_CREDS_KEYBLOCK_ENCTYPE
creds_in.keyblock.enctype = ENCTYPE_DES_CBC_CRC; /* XXX? */
+#else
+ creds_in.session.keytype = KEYTYPE_DES; /* XXX? */
+#endif
result = krb5_get_credentials(Z_krb5_ctx, 0, ccache, &creds_in, creds_out);
krb5_cc_close(Z_krb5_ctx, ccache);
#include <assert.h>
+#if 0
Code_t
ZReadAsciiOrZcode(char *buf, int buflen, unsigned char *data, int datalen)
{
{
abort();
}
+#endif
Code_t ZReadZcode(ptr, field, max, len)
unsigned char *ptr;
static int Z_AddField __P((char **ptr, char *field, char *end));
static int find_or_insert_uid __P((ZUnique_Id_t *uid, ZNotice_Kind_t kind));
+static Code_t Z_ZcodeFormatRawHeader __P((ZNotice_t *, char *, int, int *, char **,
+ int *, char **, char **, int cksumtype));
/* Find or insert uid in the old uids buffer. The buffer is a sorted
* circular queue. We make the assumption that most packets arrive in
Code_t retval;
static char version[BUFSIZ]; /* default init should be all \0 */
struct sockaddr_in name;
+ struct timeval tv;
int namelen = sizeof(name);
if (!notice->z_sender)
notice->z_multinotice = "";
- (void) gettimeofday(¬ice->z_uid.tv, (struct timezone *)0);
- notice->z_uid.tv.tv_sec = htonl((u_long) notice->z_uid.tv.tv_sec);
- notice->z_uid.tv.tv_usec = htonl((u_long) notice->z_uid.tv.tv_usec);
+ (void) gettimeofday(&tv, (struct timezone *)0);
+ notice->z_uid.tv.tv_sec = htonl((u_long) tv.tv_sec);
+ notice->z_uid.tv.tv_usec = htonl((u_long) tv.tv_usec);
(void) memcpy(¬ice->z_uid.zuid_addr, &__My_addr, sizeof(__My_addr));
cksum_start, cksum_len, cstart, cend, 1));
}
-Code_t Z_ZcodeFormatRawHeader(notice, buffer, buffer_len, hdr_len, cksum_start,
+static Code_t Z_ZcodeFormatRawHeader(notice, buffer, buffer_len, hdr_len, cksum_start,
cksum_len, cstart, cend, cksumstyle)
ZNotice_t *notice;
char *buffer;
#endif /* Z_DEBUG */
#ifdef HAVE_KRB5
-Code_t Z_Checksum(krb5_data *cksumbuf, krb5_keyblock *keyblock, krb5_cksumtype cksumtype, char **asn1_data, int *asn1_len) {
+Code_t Z_Checksum(krb5_data *cksumbuf, krb5_keyblock *keyblock,
+ krb5_cksumtype cksumtype,
+ char **asn1_data, int *asn1_len) {
krb5_error_code result;
char *data;
int len;
len = checksum.length;
#else
/* Create the checksum -- heimdal crypto API */
- result = krb5_crypto_init(Z_krb5_ctx, keyblock, enctype, &cryptctx);
+ result = krb5_crypto_init(Z_krb5_ctx, keyblock, keyblock->keytype,
+ &cryptctx);
if (result)
return result;
}
Code_t
-Z_ExtractEncCksum(krb5_keyblock *keyblock, krb5_enctype *enctype, krb5_cksumtype *cksumtype) {
+Z_InsertZcodeChecksum(krb5_keyblock *keyblock, ZNotice_t *notice,
+ char *buffer, char *cksum_start, int cksum_len,
+ char *cstart, char *cend, int buffer_len,
+ int *length_adjust)
+{
+ int plain_len; /* length of part not to be checksummed */
+ int cksum0_len; /* length of part before checksum */
+ int cksum1_len; /* length of part after checksum */
+ krb5_data cksumbuf;
+ krb5_data cksum;
+ char *key_data;
+ int key_len;
+ krb5_enctype enctype;
+ krb5_cksumtype cksumtype;
+ Code_t result;
+
+ key_data = Z_keydata(keyblock);
+ key_len = Z_keylen(keyblock);
+ result = Z_ExtractEncCksum(keyblock, &enctype, &cksumtype);
+ if (result)
+ return (ZAUTH_FAILED);
+
+ /* Assemble the things to be checksummed */
+ plain_len = cksum_start - buffer;
+ cksum0_len = cstart - cksum_start;
+ cksum1_len = (cksum_start + cksum_len) - cend;
+ memset(&cksumbuf, 0, sizeof(cksumbuf));
+ cksumbuf.length = cksum0_len + cksum1_len + notice->z_message_len;
+ cksumbuf.data = malloc(cksumbuf.length);
+ if (!cksumbuf.data)
+ return ENOMEM;
+ memcpy(cksumbuf.data, cksum_start, cksum0_len);
+ memcpy(cksumbuf.data + cksum0_len, cend, cksum1_len);
+ memcpy(cksumbuf.data + cksum0_len + cksum1_len,
+ notice->z_message, notice->z_message_len);
+ /* compute the checksum */
+ result = Z_Checksum(&cksumbuf, keyblock, cksumtype,
+ (char **)&cksum.data, &cksum.length);
+ if (result) {
+ free(cksumbuf.data);
+ return result;
+ }
+
+ /*
+ * OK.... we can zcode to a space starting at 'cstart',
+ * with a length of buffer_len - (plain_len + cksum_len).
+ * Then we tack on the end part, which is located at
+ * cksumbuf.data + cksum0_len and has length cksum1_len
+ */
+
+ result = ZMakeZcode(cstart, buffer_len - (plain_len + cksum_len),
+ cksum.data, cksum.length);
+ free(cksum.data);
+ if (!result) {
+ int zcode_len = strlen(cstart) + 1;
+ memcpy(cstart + zcode_len, cksumbuf.data + cksum0_len, cksum1_len);
+ *length_adjust = zcode_len - cksum_len + (cksum0_len + cksum1_len);
+ }
+ free(cksumbuf.data);
+ return result;
+}
+
+Code_t
+Z_ExtractEncCksum(krb5_keyblock *keyblock, krb5_enctype *enctype,
+ krb5_cksumtype *cksumtype) {
#if HAVE_KRB5_CREDS_KEYBLOCK_ENCTYPE
*enctype = keyblock->enctype;
return Z_krb5_lookup_cksumtype(*enctype, cksumtype);
unsigned int len;
ENCTYPE *val;
int i = 0;
+ Code_t result;
result = krb5_keytype_to_enctypes(Z_krb5_ctx, keyblock->keytype,
&len, &val);
#ifdef HAVE_KRB5
/* returns 0 if invalid or losing, 1 if valid, *sigh* */
int
-Z_krb5_verify_cksum(krb5_keyblock *keyblock, krb5_data *cksumbuf, krb5_cksumtype cksumtype, char *asn1_data, int asn1_len) {
+Z_krb5_verify_cksum(krb5_keyblock *keyblock, krb5_data *cksumbuf,
+ krb5_cksumtype cksumtype, char *asn1_data,
+ int asn1_len) {
krb5_error_code result;
#if HAVE_KRB5_C_MAKE_CHECKSUM
krb5_checksum checksum;
checksum.checksum.data = asn1_data;
checksum.cksumtype = cksumtype;
- result = krb5_crypto_init(Z_krb5_ctx, keyblock, enctype, &cryptctx);
+ result = krb5_crypto_init(Z_krb5_ctx, keyblock, keyblock->keytype, &cryptctx);
if (result)
return result;
/* HOLDING: cryptctx */
result = krb5_verify_checksum(Z_krb5_ctx, cryptctx,
Z_KEYUSAGE_SRV_CKSUM,
- cksumbuf.data, cksumbuf.length,
+ cksumbuf->data, cksumbuf->length,
&checksum);
krb5_crypto_destroy(Z_krb5_ctx, cryptctx);
if (result)
/* Now begin the brain dump. */
#ifdef HAVE_KRB5
+ if (get_tgt()) {
+ cleanup(server);
+ return;
+ }
{ /* "client" side */
krb5_auth_context actx;
krb5_creds creds;
- krb5_creads *credsp;
+ 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,
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);
+ krb5_free_cred_contents(Z_krb5_ctx, &creds);
cleanup(server);
return;
}
- retval = krb5_get_credentials(Z_krb5_context, 0, Z_krb5_ccache,
+ retval = krb5_get_credentials(Z_krb5_ctx, 0, Z_krb5_ccache,
&creds, &credsp);
- krb5_free_cred_contents(Z_krb5_ctx, creds);
+ 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;
}
- memset((char *)data, 0, sizeof(krb5_data));
- retval = krb5_mk_req_ext(Z_krb5_ctx, &actx, AP_OPTS_MUTUAL_REQUIRE|AP_OPTS_USE_SUBKEY,
+ 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);
-i if (retval) {
+ 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
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 */
ZRealm *realm = NULL;
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) {
}
}
#endif /* HAVE_KRB4 */
+#endif
} else if (strcmp(notice.z_opcode, CLIENT_SUBSCRIBE) == 0) {
/* a subscription packet */
if (!client) {
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;
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);
#include <zephyr/mit-copyright.h>
#include "zserver.h"
#include <sys/socket.h>
+#include <com_err.h>
#ifndef lint
#ifndef SABER
return(ZERR_NONE);
}
+
/*
* Send the notice to the client. After transmitting, put it onto the
* not ack'ed list.
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);
return;
}
#endif /* HAVE_KRB4 */
+#endif /* HAVE_KRB5 */
} else {
notice->z_auth = 0;
notice->z_authent_len = 0;
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) {
#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 ZChecksum_t compute_checksum __P((ZNotice_t *, C_Block));
static ZChecksum_t compute_rlm_checksum __P((ZNotice_t *, C_Block));
* 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 */
#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;
if (tkt == 0 || !Z_tktprincp(tkt)) {
if (tkt)
- krb5_free_tickets(Z_krb5_ctx, tkt);
+ krb5_free_ticket(Z_krb5_ctx, tkt);
free(authbuf);
krb5_auth_con_free(Z_krb5_ctx, authctx);
return ZAUTH_FAILED;
result = krb_rd_req(&authent, SERVER_SERVICE, instance,
from->sin_addr.s_addr, &dat, srvtab_file);
if (result == RD_AP_OK) {
- ZSetSessionDES(dat.session);
+ ZSetSessionDES(&dat.session);
sprintf(srcprincipal, "%s%s%s@%s", dat.pname, dat.pinst[0] ? "." : "",
dat.pinst, dat.prealm);
if (strcmp(srcprincipal, notice->z_sender))
#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;
- }
- }
- }
- timer_set_rel(SWEEP_INTERVAL, sweep_ticket_hash_table, NULL);
-}
-
#ifdef HAVE_KRB5
void
ZSetSession(krb5_keyblock *keyblock) {
-#if 0
+#if 1
krb5_error_code result;
- result = krb5_copy_keyblock_contents(Z_krb5_ctx, keyblock, __Zephyr_session_keyblock);
+ 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);
+ }
+
if (result) /*XXX we're out of memory? */
;
#else
#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
#ifdef HAVE_KRB5
krb5_ccache Z_krb5_ccache;
-#endif
-
+krb5_keyblock *__Zephyr_keyblock;
+#else
#ifdef HAVE_KRB4
C_Block __Zephyr_session;
#endif
+#endif
int
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
return 0;
}
-sender_in_realm(notice)
+int sender_in_realm(notice)
ZNotice_t *notice;
{
char *realm;
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);
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
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 */
}
buffer_len = sizeof(ZPacket_t);
}
} else {
syslog(LOG_ERR, "tkt_rtrv: don't have ticket, but have no child");
+ result = KRB5KRB_AP_ERR_TKT_EXPIRED;
}
pid = fork();
} else {
realm->child_pid = pid;
realm->have_tkt = 0;
-
+
syslog(LOG_WARNING, "tkt_rtrv: %s: %d", realm->name,
result);
return (result);
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,
{
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;
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)));
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);
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,
#include <zephyr/mit-copyright.h>
#include <internal.h>
+
+#include <com_err.h>
+
#include <arpa/inet.h>
#include "zsrv_err.h"
#include "access.h"
#include "acl.h"
-#if defined(HAVE_KRB4) || defined(HAVE_KRB5)
+#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)
-void ZSetSession(krb5_keyblock *keyblock);
+#endif
void ZSetSessionDES(C_Block *key);
Code_t ZFormatAuthenticNotice __P((ZNotice_t*, char*, int, int*, C_Block));
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 */
#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));