* client sends only new-style messages
Milestone 3.5
- * offer to Derrick.
+ * refactor checksumming code
Milestone 4
* server sends only newstyle messages, and can't brain dump the
Milestone 7
* brain dump via krb5, encrypted
+ (optional) brain dump to/from file
Milestone 8
* bring sourceforge up to date
#ifdef HAVE_KRB5
int ZGetCreds(krb5_creds **creds_out);
+int ZGetCredsRealm(krb5_creds **creds_out, char *realm);
+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);
+
+#endif
+
+#ifdef HAVE_KRB5_CREDS_KEYBLOCK_ENCTYPE
+#define Z_keydata(keyblock) ((keyblock)->contents)
+#define Z_keylen(keyblock) ((keyblock)->length)
+#define Z_credskey(creds) (&(creds)->keyblock)
+#else
+#define Z_keydata(keyblock) ((keyblock)->keyvalue.data)
+#define Z_keylen(keyblock) ((keyblock)->keyvalue.length)
+#define Z_credskey(creds) (&(creds)->session)
#endif
+
+#ifdef HAVE_KRB5_TICKET_ENC_PART2
+#define Z_tktprincp(tkt) ((tkt)->enc_part2 != 0)
+#define Z_tktprinc(tkt) ((tkt)->enc_part2->client)
+#else
+#define Z_tktprincp(tkt) ((tkt)->client != 0)
+#define Z_tktprinc(tkt) ((tkt)->client)
+#endif
+
#endif /* __INTERNAL_H__ */
INSTALL=@INSTALL@
RANLIB=@RANLIB@
FPIC=
-DEBUG=-O
+DEBUG=
CPPFLAGS=@CPPFLAGS@
CFLAGS=@CFLAGS@ ${DEBUG} ${FPIC}
ALL_CFLAGS=${CFLAGS} -DSYSCONFDIR=\"${sysconfdir}\" -I${top_srcdir}/h \
Code_t ZCheckAuthentication(notice, from)
ZNotice_t *notice;
struct sockaddr_in *from;
-{
+{
+#if 0
#if defined(HAVE_KRB4) || defined(HAVE_KRB5)
int result;
ZChecksum_t our_checksum;
#else
return (notice->z_auth ? ZAUTH_YES : ZAUTH_NO);
#endif
+#else
+ ZCheckZcodeAuthentication(notice, from);
+#endif
}
#ifdef HAVE_KRB5
{
krb5_error_code result;
- krb5_ccache ccache;
- krb5_creds creds_in, *creds;
+ krb5_creds *creds;
krb5_keyblock *keyblock;
krb5_enctype enctype;
krb5_cksumtype cksumtype;
krb5_data cksumbuf;
-#if HAVE_KRB5_C_MAKE_CHECKSUM
- krb5_checksum checksum;
- krb5_boolean valid;
-#else
- krb5_crypto cryptctx;
- Checksum checksum;
- size_t xlen;
-#endif
+ 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;
- /* Get a pointer to the default ccache. We don't need to free this. */
- result = krb5_cc_default(Z_krb5_ctx, &ccache);
- if (result)
- return (ZAUTH_NO);
-
- /* 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));
-
- result = krb5_cc_get_principal(Z_krb5_ctx, ccache, &creds_in.client);
- if (result) {
- krb5_cc_close(Z_krb5_ctx, ccache);
- return(result);
- }
- /* construct the service principal */
- result = krb5_build_principal(Z_krb5_ctx, &creds_in.server,
- strlen(__Zephyr_realm),
- __Zephyr_realm,
- SERVER_KRB5_SERVICE, SERVER_INSTANCE, 0);
- if (result) {
- krb5_free_cred_contents(Z_krb5_ctx, &creds_in);
- krb5_cc_close(Z_krb5_ctx, ccache);
- return (ZAUTH_NO);
- }
- /* HOLDING: creds_in.server */
-
- /* look up or get the credentials we need */
- result = krb5_get_credentials(Z_krb5_ctx, 0 /* flags */, ccache,
- &creds_in, &creds);
- krb5_free_cred_contents(Z_krb5_ctx, &creds_in); /* hope this is OK */
- krb5_cc_close(Z_krb5_ctx, ccache);
+ result = ZGetCreds(&creds);
if (result)
return (ZAUTH_NO);
/* HOLDING: creds */
/* Figure out what checksum type to use */
-#if HAVE_KRB5_CREDS_KEYBLOCK_ENCTYPE
- keyblock = &creds->keyblock;
- key_data = keyblock->contents;
- key_len = keyblock->length;
- enctype = keyblock->enctype;
- result = Z_krb5_lookup_cksumtype(enctype, &cksumtype);
+ keyblock = Z_credskey(creds);
+ key_data = Z_keydata(keyblock);
+ key_len = Z_keylen(keyblock);
+ result = Z_ExtractEncCksum(keyblock, &enctype, &cksumtype);
if (result) {
krb5_free_creds(Z_krb5_ctx, creds);
return (ZAUTH_FAILED);
}
-#else
- keyblock = &creds->session;
- key_data = keyblock->keyvalue.data;
- key_len = keyblock->keyvalue.length;
- {
- unsigned int len;
- ENCTYPE *val;
- int i = 0;
-
- result = krb5_keytype_to_enctypes(Z_krb5_ctx, keyblock->keytype,
- &len, &val);
- if (result) {
- krb5_free_creds(Z_krb5_ctx, creds);
- return (ZAUTH_FAILED);
- }
-
- do {
- if (i == len) break;
- result = Z_krb5_lookup_cksumtype(val[i], &cksumtype);
- i++;
- } while (result != 0);
-
- if (result) {
- krb5_free_creds(Z_krb5_ctx, creds);
- return (ZAUTH_FAILED);
- }
- enctype = val[i-1];
- }
-#endif
/* HOLDING: creds */
/* Assemble the things to be checksummed */
}
/* HOLDING: creds, asn1_data, cksumbuf.data */
-#if HAVE_KRB5_C_MAKE_CHECKSUM
- /* Verify the checksum -- MIT crypto API */
- memset(&checksum, 0, sizeof(checksum));
- checksum.length = asn1_len;
- checksum.contents = asn1_data;
- checksum.checksum_type = cksumtype;
- result = krb5_c_verify_checksum(Z_krb5_ctx,
- keyblock, Z_KEYUSAGE_SRV_CKSUM,
- &cksumbuf, &checksum, &valid);
+ valid = Z_krb5_verify_cksum(keyblock, &cksumbuf, cksumtype, asn1_data, asn1_len);
+
free(asn1_data);
krb5_free_creds(Z_krb5_ctx, creds);
free(cksumbuf.data);
- if (!result && valid)
- return (ZAUTH_YES);
- else
- return (ZAUTH_FAILED);
-#else
- checksum.checksum.length = asn1_len;
- checksum.checksum.data = asn1_data;
- checksum.cksumtype = cksumtype;
- /* HOLDING: creds, asn1_data, cksumbuf.data */
- result = krb5_crypto_init(Z_krb5_ctx, keyblock, enctype, &cryptctx);
- krb5_free_creds(Z_krb5_ctx, creds);
- if (result) {
- free(asn1_data);
- free(cksumbuf.data);
- return result;
- }
- /* HOLDING: cryptctx, checksum, cksumbuf.data */
- result = krb5_verify_checksum(Z_krb5_ctx, cryptctx,
- Z_KEYUSAGE_SRV_CKSUM,
- cksumbuf.data, cksumbuf.length,
- &checksum);
- krb5_crypto_destroy(Z_krb5_ctx, cryptctx);
- free(asn1_data);
- free(cksumbuf.data);
- if (result)
- return (ZAUTH_FAILED);
- else
- return (ZAUTH_YES);
-#endif
+ if (valid)
+ return ZAUTH_YES;
+ else
+ return ZAUTH_FAILED;
}
#endif /* HAVE_KRB5 */
return (notice->z_auth ? ZAUTH_YES : ZAUTH_NO);
pw = getpwuid((int) getuid());
if (!pw)
return ("unknown");
- sender = malloc(strlen(pw->pw_name) + strlen(__Zephyr_realm));
+ sender = malloc(strlen(pw->pw_name) + strlen(__Zephyr_realm) + 2);
if (sender)
(void) sprintf(sender, "%s@%s", pw->pw_name, __Zephyr_realm);
return (sender);
strcpy(__Zephyr_realm, krealms[0]);
krb5_free_host_realm(Z_krb5_ctx, krealms);
} else {
+ char *p; /* XXX define this somewhere portable */
/* XXX check ticket file here */
- code = krb5_get_default_realm(Z_krb5_ctx, __Zephyr_realm);
+ code = krb5_get_default_realm(Z_krb5_ctx, &p);
+ strcpy(__Zephyr_realm, p);
+ krb5_free_default_realm(Z_krb5_ctx, p);
if (code)
return code;
}
int buffer_len;
int *len;
{
+#if 1
+ return ZMakeZcodeAuthentication(notice, buffer, buffer_len, len/*?XXX*/);
+#else
#if defined(HAVE_KRB4) || defined(HAVE_KRB5)
int result;
time_t now;
notice->z_ascii_authent = "";
return (Z_FormatRawHeader(notice, buffer, buffer_len, len, NULL, NULL));
#endif
+#endif
}
Code_t ZMakeZcodeAuthentication(notice, buffer, buffer_len, phdr_len)
{
#ifdef HAVE_KRB5
krb5_error_code result;
- krb5_ccache ccache;
- krb5_creds creds_in, *creds;
+ krb5_creds *creds;
krb5_keyblock *keyblock;
krb5_enctype enctype;
krb5_cksumtype cksumtype;
krb5_auth_context authctx;
krb5_data *authent;
krb5_data cksumbuf;
-#if HAVE_KRB5_C_MAKE_CHECKSUM
- krb5_checksum checksum;
-#else
- krb5_crypto cryptctx;
- Checksum checksum;
- size_t xlen;
-#endif
char *svcinst, *x, *y;
char *cksum_start, *cstart, *cend, *asn1_data;
int plain_len; /* length of part not to be checksummed */
int cksum1_len; /* length of part after checksum */
int i, zcode_len, asn1_len;
- /* Get a pointer to the default ccache. We don't need to free this. */
- result = krb5_cc_default(Z_krb5_ctx, &ccache);
- if (result)
- return result;
-
- /* 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));
-
- result = krb5_cc_get_principal(Z_krb5_ctx, ccache, &creds_in.client);
- if (result) {
- krb5_cc_close(Z_krb5_ctx, ccache);
- return(result);
- }
-
- /* construct the service principal */
- result = krb5_build_principal(Z_krb5_ctx, &creds_in.server,
- strlen(realm),
- realm,
- SERVER_KRB5_SERVICE, SERVER_INSTANCE, 0);
- if (result) {
- krb5_free_cred_contents(Z_krb5_ctx, &creds_in); /* hope this is OK */
- krb5_cc_close(Z_krb5_ctx, ccache);
- return result;
- }
- /* HOLDING: creds_in.server, ccache */
-
- /* look up or get the credentials we need */
- 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 */
+ result = ZGetCredsRealm(&creds, realm);
if (result)
return result;
/* HOLDING: creds */
/* Figure out what checksum type to use */
-#if HAVE_KRB5_CREDS_KEYBLOCK_ENCTYPE
- keyblock = &creds->keyblock;
- enctype = keyblock->enctype;
-
- result = Z_krb5_lookup_cksumtype(enctype, &cksumtype);
+ keyblock = Z_credskey(creds);
+ result = Z_ExtractEncCksum(keyblock, &enctype, &cksumtype);
if (result) {
krb5_free_creds(Z_krb5_ctx, creds);
return result;
}
-#else
- keyblock = &creds->session;
- {
- unsigned int len;
- ENCTYPE *val;
- int i = 0;
-
- result = krb5_keytype_to_enctypes(Z_krb5_ctx, keyblock->keytype,
- &len, &val);
- if (result) {
- krb5_free_creds(Z_krb5_ctx, creds);
- return result;
- }
-
- do {
- if (i == len) break;
- result = Z_krb5_lookup_cksumtype(val[i], &cksumtype);
- i++;
- } while (result != 0);
-
- if (result) {
- krb5_free_creds(Z_krb5_ctx, creds);
- return result;
- }
- enctype = val[i-1];
- }
-#endif
/* HOLDING: creds */
/* Create the authenticator */
krb5_free_creds(Z_krb5_ctx, creds);
return (result);
}
-
+
authent = (krb5_data *)malloc(sizeof(krb5_data));
/* HOLDING: creds, authctx */
memcpy(cksumbuf.data + cksum0_len, cend, cksum1_len);
memcpy(cksumbuf.data + cksum0_len + cksum1_len,
notice->z_message, notice->z_message_len);
-
-#if HAVE_KRB5_C_MAKE_CHECKSUM
- /* Create the checksum -- MIT crypto API */
- result = krb5_c_make_checksum(Z_krb5_ctx, cksumtype,
- keyblock, Z_KEYUSAGE_CLT_CKSUM,
- &cksumbuf, &checksum);
- krb5_free_creds(Z_krb5_ctx, creds);
- if (result) {
- free(cksumbuf.data);
- return result;
- }
- /* HOLDING: cksumbuf.data, checksum */
- asn1_data = checksum.contents;
- asn1_len = checksum.length;
-#else
- /* Create the checksum -- heimdal crypto API */
- result = krb5_crypto_init(Z_krb5_ctx, keyblock, enctype, &cryptctx);
+ /* compute the checksum */
+ result = Z_Checksum(&cksumbuf, keyblock, cksumtype, &asn1_data, &asn1_len);
krb5_free_creds(Z_krb5_ctx, creds);
if (result) {
free(cksumbuf.data);
return result;
}
- /* HOLDING: cksumbuf.data, cryptctx */
- result = krb5_create_checksum(Z_krb5_ctx, cryptctx,
- Z_KEYUSAGE_CLT_CKSUM, cksumtype,
- cksumbuf.data, cksumbuf.length,
- &checksum);
- krb5_crypto_destroy(Z_krb5_ctx, cryptctx);
- if (result) {
- free(cksumbuf.data);
- return result;
- }
- asn1_len = checksum.checksum.length;
- asn1_data = checksum.checksum.data;
- /* HOLDING: cksumbuf.data, checksum */
-#endif
/*
* OK.... we can zcode to a space starting at 'cstart',
/* free stuff up, and then return the result from the last call */
free(cksumbuf.data);
-#if HAVE_KRB5_C_MAKE_CHECKSUM
- krb5_free_checksum_contents(Z_krb5_ctx, &checksum);
-#else
- free_Checksum(&checksum);
-#endif
+ free(asn1_data);
+
return (result);
#endif /* HAVE_KRB5 */
}
#ifdef HAVE_KRB5
int ZGetCreds(krb5_creds **creds_out) {
+ return ZGetCredsRealm(creds_out, __Zephyr_realm);
+}
+
+int ZGetCredsRealm(krb5_creds **creds_out, char *realm) {
krb5_creds creds_in;
krb5_ccache ccache; /* XXX make this a global or static?*/
int result;
memset((char *)&creds_in, 0, sizeof(creds_in));
result = krb5_build_principal(Z_krb5_ctx, &creds_in.server,
- strlen(__Zephyr_realm), __Zephyr_realm,
+ strlen(realm),
+ realm,
SERVER_SERVICE, SERVER_INSTANCE, 0);
if (result) {
krb5_cc_close(Z_krb5_ctx, ccache);
return result;
}
- creds_in.times.endtime = 0;
- creds_in.keyblock.enctype = ENCTYPE_DES_CBC_CRC;
+ creds_in.keyblock.enctype = ENCTYPE_DES_CBC_CRC; /* XXX? */
result = krb5_get_credentials(Z_krb5_ctx, 0, ccache, &creds_in, creds_out);
krb5_cc_close(Z_krb5_ctx, ccache);
krb5_free_cred_contents(Z_krb5_ctx, &creds_in); /* I also hope this is ok */
return result;
-
-
}
#endif
if (numfields && ptr < end) {
notice->z_ascii_checksum = ptr;
-#ifdef xZCODE_K4SUM
- if (ZReadZcode32(ptr, end-ptr, &temp) == ZERR_BADFIELD)
-#else
if (ZReadAscii32(ptr, end-ptr, &temp) == ZERR_BADFIELD)
-#endif
notice->z_checksum = 0;
else
notice->z_checksum = temp;
if (cstart)
*cstart = ptr;
if (ZMakeAscii32(ptr, end-ptr, notice->z_checksum) == ZERR_FIELDLEN)
- return (ZERR_HEADERLEN);
+ return (ZERR_HEADERLEN);
ptr += strlen(ptr)+1;
if (cend)
*cend = ptr;
}
#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) {
+ krb5_error_code result;
+ char *data;
+ int len;
+#if HAVE_KRB5_C_MAKE_CHECKSUM
+ krb5_checksum checksum;
+#else
+ Checksum checksum;
+ krb5_crypto cryptctx;
+#endif
+
+#if HAVE_KRB5_C_MAKE_CHECKSUM
+ /* Create the checksum -- MIT crypto API */
+ result = krb5_c_make_checksum(Z_krb5_ctx, cksumtype,
+ keyblock, Z_KEYUSAGE_CLT_CKSUM,
+ cksumbuf, &checksum);
+ if (result)
+ return result;
+ /* HOLDING: checksum */
+
+ data = checksum.contents;
+ len = checksum.length;
+#else
+ /* Create the checksum -- heimdal crypto API */
+ result = krb5_crypto_init(Z_krb5_ctx, keyblock, enctype, &cryptctx);
+ if (result)
+ return result;
+
+ /* HOLDING: cryptctx */
+ result = krb5_create_checksum(Z_krb5_ctx, cryptctx,
+ Z_KEYUSAGE_CLT_CKSUM, cksumtype,
+ cksumbuf->data, cksumbuf->length,
+ &checksum);
+ krb5_crypto_destroy(Z_krb5_ctx, cryptctx);
+ if (result)
+ return result;
+
+ len = checksum.checksum.length;
+ data = checksum.checksum.data;
+ /* HOLDING: checksum */
+#endif
+
+ *asn1_data = malloc(len);
+ if (*asn1_data == NULL)
+ return errno;
+ memcpy(*asn1_data, data, len);
+ *asn1_len = len;
+
+#if HAVE_KRB5_C_MAKE_CHECKSUM
+ krb5_free_checksum_contents(Z_krb5_ctx, &checksum);
+#else
+ free_Checksum(&checksum);
+#endif
+
+ return 0;
+}
+
+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);
+#else
+ unsigned int len;
+ ENCTYPE *val;
+ int i = 0;
+
+ result = krb5_keytype_to_enctypes(Z_krb5_ctx, keyblock->keytype,
+ &len, &val);
+ if (result)
+ return result;
+
+ do {
+ if (i == len) break;
+ result = Z_krb5_lookup_cksumtype(val[i], cksumtype);
+ i++;
+ } while (result != 0);
+
+ if (result)
+ return result;
+
+ *enctype = val[i-1];
+#endif
+ return 0;
+}
+#endif
+
+#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) {
+ krb5_error_code result;
+#if HAVE_KRB5_C_MAKE_CHECKSUM
+ krb5_checksum checksum;
+ krb5_boolean valid;
+#else
+ krb5_crypto cryptctx;
+ Checksum checksum;
+ size_t xlen;
+#endif
+
+ memset(&checksum, 0, sizeof(checksum));
+#if HAVE_KRB5_C_MAKE_CHECKSUM
+ /* Verify the checksum -- MIT crypto API */
+ checksum.length = asn1_len;
+ checksum.contents = asn1_data;
+ checksum.checksum_type = cksumtype;
+ result = krb5_c_verify_checksum(Z_krb5_ctx,
+ keyblock, Z_KEYUSAGE_SRV_CKSUM,
+ cksumbuf, &checksum, &valid);
+ if (!result && valid)
+ return 1;
+ else
+ return 0;
+#else
+ checksum.checksum.length = asn1_len;
+ checksum.checksum.data = asn1_data;
+ checksum.cksumtype = cksumtype;
+
+ result = krb5_crypto_init(Z_krb5_ctx, keyblock, enctype, &cryptctx);
+ if (result)
+ return result;
+
+ /* HOLDING: cryptctx */
+ result = krb5_verify_checksum(Z_krb5_ctx, cryptctx,
+ Z_KEYUSAGE_SRV_CKSUM,
+ cksumbuf.data, cksumbuf.length,
+ &checksum);
+ krb5_crypto_destroy(Z_krb5_ctx, cryptctx);
+ if (result)
+ return 0;
+ else
+ return 1;
+#endif
+}
+#endif
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));
#endif
}
+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;
+ }
+
+ packet.length = len;
+ packet.data = authbuf;
+
+ 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, "k5 auth failed: %s", error_message(result));
+ else
+ syslog(LOG_WARNING,"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 */
+
+ memcpy(__Zephyr_session, key_data, sizeof(C_Block)); /* XXX */
+
+ /* 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;
{
}
authent.length = notice->z_authent_len;
-#if 0
- /* Copy the ticket out of the authentication data. */
- if (krb_find_ticket(&authent, &ticket) != RD_AP_OK)
- return ZAUTH_FAILED;
-
- /* Try to do a fast check against the cryptographic checksum. */
- if (find_session_key(&ticket, session_key, srcprincipal) >= 0) {
- if (strcmp(srcprincipal, notice->z_sender) != 0)
- return ZAUTH_FAILED;
- if (notice->z_time.tv_sec - NOW > CLOCK_SKEW)
- return ZAUTH_FAILED;
- checksum = compute_checksum(notice, session_key);
-
- /* If checksum matches, packet is authentic. If not, we might
- * have an outdated session key, so keep going the slow way.
- */
- if (checksum == notice->z_checksum) {
- memcpy(__Zephyr_session, session_key, sizeof(C_Block));
- return ZAUTH_YES;
- }
- }
-#endif
-
strcpy(instance, SERVER_INSTANCE);
/* We don't have the session key cached; do it the long way. */
if (checksum != notice->z_checksum)
return ZAUTH_FAILED;
-#if 0
- /* Record the session key, expiry time, and source principal in the
- * hash table, so we can do a fast check next time. */
- add_session_key(&ticket, dat.session, srcprincipal,
- (time_t)(dat.time_sec + dat.life * 5 * 60));
-#endif
-
return ZAUTH_YES;
#else /* !HAVE_KRB4 */
#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;
-}
-
static ZChecksum_t compute_checksum(notice, session_key)
ZNotice_t *notice;
C_Block session_key;
Zperr(ret);
com_err("hm", ret, "setting destination");
}
- if ((ret = send_outgoing(notice)) != ZERR_NONE) {
+ if ((ret = ZSendPacket(packet, pak_len, 0)) != ZERR_NONE) {
Zperr(ret);
com_err("hm", ret, "while sending raw notice");
}