summaryrefslogtreecommitdiff
path: root/server/kstuff.c
diff options
context:
space:
mode:
authorGravatar Karl Ramm <kcr@1ts.org>2009-07-27 05:31:53 +0000
committerGravatar Karl Ramm <kcr@1ts.org>2009-07-27 05:31:53 +0000
commitc57cb726d8889f9bafa558698d98376485900034 (patch)
treed82fd86f62fb223faa0432691dac84bd5a424034 /server/kstuff.c
parent78adeeac1cce9d015c6cbc9bea8ac163a420caeb (diff)
Refactor ZCheckRealmAuthentication into ZCheckSrvAuthentication.
(also fiddle around with what krb4 checksums are available in krb5-only land)
Diffstat (limited to 'server/kstuff.c')
-rw-r--r--server/kstuff.c371
1 files changed, 33 insertions, 338 deletions
diff --git a/server/kstuff.c b/server/kstuff.c
index fcb3218..3677a80 100644
--- a/server/kstuff.c
+++ b/server/kstuff.c
@@ -21,10 +21,10 @@ static const char rcsid_kstuff_c[] = "$Id$";
#endif
#if defined(HAVE_KRB4) && defined(HAVE_KRB5)
-static ZChecksum_t compute_checksum(ZNotice_t *, C_Block);
static Code_t ZCheckAuthentication4(ZNotice_t *notice, struct sockaddr_in *from);
#endif
#ifdef HAVE_KRB5
+static ZChecksum_t compute_checksum(ZNotice_t *, unsigned char *);
static ZChecksum_t compute_rlm_checksum(ZNotice_t *, unsigned char *);
#endif
@@ -241,328 +241,9 @@ SendKrb5Data(int fd, krb5_data *data) {
#endif
Code_t
-ZCheckRealmAuthentication(ZNotice_t *notice,
- struct sockaddr_in *from,
- char *realm)
-{
-#ifdef HAVE_KRB5
- char *authbuf;
- char rlmprincipal[MAX_PRINCIPAL_SIZE];
- 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 = NULL, *cksum2_base;
- char *x;
- unsigned char *asn1_data;
- unsigned char *key_data;
- int asn1_len, key_len, cksum0_len = 0, cksum1_len = 0, cksum2_len = 0;
- krb5_flags acflags;
-#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 <= 0)
- return ZAUTH_FAILED;
-
- len = strlen(notice->z_ascii_authent)+1;
- authbuf = malloc(len);
-
- /* Read in the authentication data. */
- if (ZReadZcode((unsigned char *)notice->z_ascii_authent,
- (unsigned char *)authbuf,
- len, &len) == ZERR_BADFIELD) {
- return ZAUTH_FAILED;
- }
-
- (void) snprintf(rlmprincipal, MAX_PRINCIPAL_SIZE, "%s/%s@%s", SERVER_SERVICE,
- SERVER_INSTANCE, realm);
-
- 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);
- }
-
- result = krb5_auth_con_getflags(Z_krb5_ctx, authctx, &acflags);
- if (result) {
- krb5_kt_close(Z_krb5_ctx, keytabid);
- free(authbuf);
- return (result);
- }
-
- acflags &= ~KRB5_AUTH_CONTEXT_DO_TIME;
-
- result = krb5_auth_con_setflags(Z_krb5_ctx, authctx, acflags);
- 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, NULL, &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_sender_(sock)addr
- * - z_charset
- * - z_other_fields[]
- */
- if (notice->z_num_hdr_fields > 15 ) {
- cksum1_base = notice->z_multinotice;
- if (notice->z_num_other_fields)
- x = notice->z_other_fields[notice->z_num_other_fields - 1];
- else {
- /* see also ZCheckSrvAuthentication and
- lib/ZCkZaut.c:ZCheckZcodeAuthentication */
- /* XXXXXXXXXXXXXXXXXXXXXXX */
- if (notice->z_num_hdr_fields > 16)
- x = cksum1_base + strlen(cksum1_base) + 1; /* multinotice */
- if (notice->z_num_hdr_fields > 17)
- x = x + strlen(x) + 1; /* multiuid */
- if (notice->z_num_hdr_fields > 18)
- x = x + strlen(x) + 1; /* sender */
- }
- cksum1_len = x + strlen(x) + 1 - cksum1_base; /* charset / extra field */
- }
-
- /* 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_FAILED;
- }
- /* HOLDING: authctx, authenticator, cksumbuf.data */
-
- memcpy(cksumbuf.data, cksum0_base, cksum0_len);
- if (cksum1_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((unsigned char *)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,
- Z_KEYUSAGE_CLT_CKSUM,
- 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
-}
-
-Code_t
ZCheckSrvAuthentication(ZNotice_t *notice,
- struct sockaddr_in *from)
+ struct sockaddr_in *from,
+ char *realm)
{
#ifdef HAVE_KRB5
unsigned char *authbuf;
@@ -592,16 +273,18 @@ ZCheckSrvAuthentication(ZNotice_t *notice,
#define KRB5AUTHENT &authenticator
#endif
int len;
+ char *sender;
+ char rlmprincipal[MAX_PRINCIPAL_SIZE];
if (!notice->z_auth)
return ZAUTH_NO;
/* Check for bogus authentication data length. */
- if (notice->z_authent_len <= 1)
+ if (notice->z_authent_len <= 0)
return ZAUTH_FAILED;
#ifdef HAVE_KRB4
- if (notice->z_ascii_authent[0] != 'Z')
+ if (notice->z_ascii_authent[0] != 'Z' && realm == NULL)
return ZCheckAuthentication4(notice, from);
#endif
@@ -615,6 +298,14 @@ ZCheckSrvAuthentication(ZNotice_t *notice,
return ZAUTH_FAILED;
}
+ if (realm == NULL) {
+ sender = notice->z_sender;
+ } else {
+ (void) snprintf(rlmprincipal, MAX_PRINCIPAL_SIZE, "%s/%s@%s", SERVER_SERVICE,
+ SERVER_INSTANCE, realm);
+ sender = rlmprincipal;
+ }
+
packet.length = len;
packet.data = (char *)authbuf;
@@ -682,6 +373,7 @@ ZCheckSrvAuthentication(ZNotice_t *notice,
krb5_auth_con_free(Z_krb5_ctx, authctx);
return ZAUTH_FAILED;
}
+
princ = Z_tktprinc(tkt);
if (princ == 0) {
@@ -705,9 +397,9 @@ ZCheckSrvAuthentication(ZNotice_t *notice,
krb5_free_ticket(Z_krb5_ctx, tkt);
/* HOLDING: authbuf, authctx, name */
- if (strcmp(name, notice->z_sender)) {
+ if (strcmp(name, sender)) {
syslog(LOG_WARNING, "k5 name mismatch: '%s' vs '%s'",
- name, notice->z_sender);
+ name, sender);
krb5_auth_con_free(Z_krb5_ctx, authctx);
free(name);
free(authbuf);
@@ -746,7 +438,8 @@ ZCheckSrvAuthentication(ZNotice_t *notice,
}
/* HOLDING: authctx, authenticator, keyblock */
- ZSetSession(keyblock);
+ if (realm == NULL)
+ ZSetSession(keyblock);
/* Assemble the things to be checksummed */
/* first part is from start of packet through z_default_format:
@@ -771,6 +464,8 @@ ZCheckSrvAuthentication(ZNotice_t *notice,
/* second part is from z_multinotice through other fields:
* - z_multinotice
* - z_multiuid
+ * - z_sender_(sock)addr
+ * - z_charset
* - z_other_fields[]
*/
if (notice->z_num_hdr_fields > 15 ) {
@@ -795,7 +490,7 @@ ZCheckSrvAuthentication(ZNotice_t *notice,
cksum2_base = notice->z_message;
cksum2_len = notice->z_message_len;
-#ifdef HAVE_KRB4 /*XXX*/
+ /*XXX we may wish to ditch this code someday?*/
if ((!notice->z_ascii_checksum || *notice->z_ascii_checksum != 'Z') &&
key_len == 8 &&
(enctype == ENCTYPE_DES_CBC_CRC ||
@@ -805,7 +500,10 @@ ZCheckSrvAuthentication(ZNotice_t *notice,
ZChecksum_t our_checksum;
- our_checksum = compute_checksum(notice, key_data);
+ if (realm == NULL)
+ our_checksum = compute_checksum(notice, key_data);
+ else
+ our_checksum = compute_rlm_checksum(notice, key_data);
krb5_free_keyblock(Z_krb5_ctx, keyblock);
krb5_auth_con_free(Z_krb5_ctx, authctx);
@@ -816,7 +514,6 @@ ZCheckSrvAuthentication(ZNotice_t *notice,
else
return ZAUTH_FAILED;
}
-#endif
/* HOLDING: authctx, authenticator */
@@ -935,25 +632,23 @@ ZCheckAuthentication4(ZNotice_t *notice,
#endif
-#if defined(HAVE_KRB4) && defined(HAVE_KRB5)
+#ifdef HAVE_KRB5
static ZChecksum_t
compute_checksum(ZNotice_t *notice,
- C_Block session_key)
+ unsigned char *session_key)
{
ZChecksum_t checksum;
char *cstart, *cend, *hstart = notice->z_packet, *hend = notice->z_message;
cstart = notice->z_default_format + strlen(notice->z_default_format) + 1;
cend = cstart + strlen(cstart) + 1;
- checksum = des_quad_cksum((unsigned char *)hstart, NULL, cstart - hstart, 0, (C_Block *)session_key);
- checksum ^= des_quad_cksum((unsigned char *)cend, NULL, hend - cend, 0, (C_Block *)session_key);
- checksum ^= des_quad_cksum((unsigned char *)notice->z_message, NULL, notice->z_message_len,
- 0, (C_Block *)session_key);
+ checksum = z_quad_cksum((unsigned char *)hstart, NULL, cstart - hstart, 0, session_key);
+ checksum ^= z_quad_cksum((unsigned char *)cend, NULL, hend - cend, 0, session_key);
+ checksum ^= z_quad_cksum((unsigned char *)notice->z_message, NULL, notice->z_message_len,
+ 0, session_key);
return checksum;
}
-#endif
-#ifdef HAVE_KRB5
static ZChecksum_t compute_rlm_checksum(ZNotice_t *notice,
unsigned char *session_key)
{