diff --git a/configure.ac b/configure.ac index 56520853..6e18fff1 100644 --- a/configure.ac +++ b/configure.ac @@ -362,7 +362,48 @@ if test "$enable_encryption" = yes \ AC_CHECK_HEADERS([com_err.h kerberosV/krb5.h krb5.h \ krb5/asn1.h krb5/crc-32.h krb5/ext-proto.h \ krb5/krb5.h krb5/los-proto.h]) + _SAVE_LIBS="$LIBS" + LIBS="$KRB5_LIBS" + AC_CHECK_FUNCS([krb5_auth_con_getrecvsubkey]) + LIBS="$_SAVE_LIBS" + AC_CACHE_CHECK([for enctype in krb5_keyblock], [ac_cv_have_krb5_keyblock_enctype], [ + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([#include ], [krb5_keyblock key; key.enctype;])], + [ac_cv_have_krb5_keyblock_enctype=yes], [ac_cv_have_krb5_keyblock_enctype=no]) + ]) + AC_CACHE_CHECK([for double pointer in krb5_auth_con_getauthenticator], [ac_cv_have_krb5_auth_con_getauthenticator_double_pointer], [ + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([#include + krb5_error_code krb5_auth_con_getauthenticator(krb5_context, krb5_auth_context, krb5_authenticator**);], [])], + [ac_cv_have_krb5_auth_con_getauthenticator_double_pointer=yes], [ac_cv_have_krb5_auth_con_getauthenticator_double_pointer=no]) + ]) + AC_CACHE_CHECK([for checksum in krb5_authenticator], [ac_cv_have_krb5_authenticator_checksum], [ + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([#include ], [krb5_authenticator auth; auth.checksum;])], + [ac_cv_have_krb5_authenticator_checksum=yes], [ac_cv_have_krb5_authenticator_checksum=no]) + ]) + AC_CACHE_CHECK([for keyblock in krb5_creds], [ac_cv_have_krb5_creds_keyblock], [ + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([#include ], [krb5_creds creds; creds.keyblock;])], + [ac_cv_have_krb5_creds_keyblock=yes], [ac_cv_have_krb5_creds_keyblock=no]) + ]) + AC_CACHE_CHECK([for seven parameters in krb5_verify_checksum], [ac_cv_have_krb5_verify_checksum_seven_parameters], [ + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([#include ], [krb5_verify_checksum(0, 0, 0, 0, 0, 0, 0);])], + [ac_cv_have_krb5_verify_checksum_seven_parameters=yes], [ac_cv_have_krb5_verify_checksum_seven_parameters=no]) + ]) + AC_CACHE_CHECK([for enc_part2 in krb5_ticket], [ac_cv_have_krb5_ticket_enc_part2], [ + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([#include ], [krb5_ticket ticket; ticket.enc_part2;])], + [ac_cv_have_krb5_ticket_enc_part2=yes], [ac_cv_have_krb5_ticket_enc_part2=no]) + ]) CPPFLAGS=$save_CPPFLAGS + test "$ac_cv_have_krb5_keyblock_enctype" = yes \ + && AC_DEFINE(HAVE_KRB5_KEYBLOCK_ENCTYPE, 1, [Define to one if the krb5_keyblock struct has a enctype property.]) + test "$ac_cv_have_krb5_auth_con_getauthenticator_double_pointer" = yes \ + && AC_DEFINE(HAVE_KRB5_AUTH_CON_GETAUTHENTICATOR_DOUBLE_POINTER, 1, [Define to one if the krb5_auth_con_getauthenticator function takes a double pointer.]) + test "$ac_cv_have_krb5_authenticator_checksum" = yes \ + && AC_DEFINE(HAVE_KRB5_AUTHENTICATOR_CHECKSUM, 1, [Define to one if the krb5_authenticator struct has a checksum property.]) + test "$ac_cv_have_krb5_creds_keyblock" = yes \ + && AC_DEFINE(HAVE_KRB5_CREDS_KEYBLOCK, 1, [Define to one if the krb5_creds struct has a keyblock property.]) + test "$ac_cv_have_krb5_verify_checksum_seven_parameters" = yes \ + && AC_DEFINE(HAVE_KRB5_VERIFY_CHECKSUM_SEVEN_PARAMETERS, 1, [Define to one if the krb5_verify_checksum function takes seven parameters.]) + test "$ac_cv_have_krb5_ticket_enc_part2" = yes \ + && AC_DEFINE(HAVE_KRB5_TICKET_ENC_PART2, 1, [Define to one if the krb5_ticket struct has a enc_part2 property.]) # We have limited support for krcmd() with Kerberos5. # Encryption must be sorted out as a first step. IU_DISABLE_TARGET(rcp) diff --git a/libtelnet/kerberos5.c b/libtelnet/kerberos5.c index 6d873634..8e82ce11 100644 --- a/libtelnet/kerberos5.c +++ b/libtelnet/kerberos5.c @@ -39,6 +39,59 @@ # include "auth.h" # include "misc.h" +#ifndef HAVE_KRB5_AUTH_CON_GETRECVSUBKEY /* Heimdal */ +krb5_error_code +krb5_auth_con_getrecvsubkey (krb5_context context, + krb5_auth_context auth_context, krb5_keyblock **keyblock) +{ + return krb5_auth_con_getremotesubkey (context, auth_context, keyblock); +} +#endif + +# ifdef HAVE_KRB5_KEYBLOCK_ENCTYPE /* MIT */ +# define KRB5_KEYBLOCK_ENCTYPE(k) ((k)->enctype) +# define KRB5_KEYBLOCK_LENGTH(k) ((k)->length) +# define KRB5_KEYBLOCK_CONTENTS(k) ((k)->contents) +# else /* Heimdal */ +# define KRB5_KEYBLOCK_ENCTYPE(k) ((k)->keytype) +# define KRB5_KEYBLOCK_LENGTH(k) ((k)->keyvalue.length) +# define KRB5_KEYBLOCK_CONTENTS(k) ((k)->keyvalue.data) +# endif + +# ifdef HAVE_KRB5_AUTHENTICATOR_CHECKSUM /* MIT */ +# define KRB5_AUTHENTICATOR_CHECKSUM(a) ((a)->checksum) +# define KRB5_CHECKSUM_CHECKSUM_TYPE(c) ((c)->checksum_type) +# else /* Heimdal */ +# define KRB5_AUTHENTICATOR_CHECKSUM(a) ((a)->cksum) +# define KRB5_CHECKSUM_CHECKSUM_TYPE(c) ((c)->cksumtype) +# endif + +# ifdef HAVE_KRB5_CREDS_KEYBLOCK /* MIT */ +# define KRB5_CREDS_KEYBLOCK(c) ((c)->keyblock) +# else /* Heimdal */ +# define KRB5_CREDS_KEYBLOCK(c) ((c)->session) +# endif + +# ifdef HAVE_KRB5_TICKET_ENC_PART2 /* MIT */ +# define KRB5_TICKET_ENC_PART2(t) ((t)->enc_part2) +# define KRB5_ENC_PART2_SESSION(e) ((e)->session) +# else /* Heimdal */ +# define KRB5_TICKET_ENC_PART2(t) ((t)) +# define KRB5_ENC_PART2_SESSION(e) (&(e)->ticket.key) +# endif + +# ifndef krb5_princ_component /* Heimdal */ +static krb5_data * +krb5_princ_component (krb5_context context, krb5_principal principal, int i) +{ + static krb5_data pdata; + + pdata.data = (char*)krb5_principal_get_comp_string (context, principal, i); + pdata.length = strlen (pdata.data); + return &pdata; +} +# endif + # ifndef KRB5_ENV_CCNAME # define KRB5_ENV_CCNAME "KRB5CCNAME" # endif @@ -162,7 +215,7 @@ encryption_init (krb5_creds * creds) if (newkey) { - switch (newkey->enctype) + switch (KRB5_KEYBLOCK_ENCTYPE (newkey)) { case ENCTYPE_DES_CBC_CRC: case ENCTYPE_DES_CBC_MD5: @@ -170,11 +223,11 @@ encryption_init (krb5_creds * creds) break; default: - switch (creds->keyblock.enctype) + switch (KRB5_KEYBLOCK_ENCTYPE (&KRB5_CREDS_KEYBLOCK (creds))) { case ENCTYPE_DES_CBC_CRC: case ENCTYPE_DES_CBC_MD5: - krb5_copy_keyblock (telnet_context, &creds->keyblock, + krb5_copy_keyblock (telnet_context, &KRB5_CREDS_KEYBLOCK (creds), &session_key); break; @@ -235,7 +288,11 @@ kerberos5_send (TN_Authenticator * ap) return 0; } strcpy (rdata.data, dest_realm); +# ifdef krb5_princ_set_realm /* MIT */ krb5_princ_set_realm (telnet_context, creds.server, &rdata); +# else /* Heimdal */ + krb5_princ_set_realm (telnet_context, creds.server, (char **) &rdata.data); +# endif } if ((r = krb5_cc_get_principal (telnet_context, ccache, &creds.client))) @@ -246,7 +303,7 @@ kerberos5_send (TN_Authenticator * ap) return 0; } - creds.keyblock.enctype = ENCTYPE_DES_CBC_CRC; + KRB5_KEYBLOCK_ENCTYPE (&KRB5_CREDS_KEYBLOCK (&creds)) = ENCTYPE_DES_CBC_CRC; if ((r = krb5_get_credentials (telnet_context, 0, ccache, &creds, &new_creds))) { @@ -283,7 +340,9 @@ kerberos5_send (TN_Authenticator * ap) type_check[0] = ap->type; type_check[1] = ap->way; +# ifdef KV5M_DATA /* MIT */ check_data.magic = KV5M_DATA; +# endif check_data.length = 2; check_data.data = (char *) &type_check; @@ -326,7 +385,7 @@ telnet_encrypt_key (Session_Key * skey) { skey->type = SK_DES; skey->length = 8; - skey->data = session_key->contents; + skey->data = KRB5_KEYBLOCK_CONTENTS (session_key); encrypt_session_key (skey, 0); } } @@ -432,7 +491,7 @@ kerberos5_status (TN_Authenticator * ap MAYBE_UNUSED, return level; if (UserNameRequested - && krb5_kuserok (telnet_context, ticket->enc_part2->client, + && krb5_kuserok (telnet_context, KRB5_TICKET_ENC_PART2 (ticket)->client, UserNameRequested)) { /* FIXME: Check buffer length */ @@ -448,7 +507,11 @@ kerberos5_is_auth (TN_Authenticator * ap, unsigned char *data, int cnt, { int r = 0; krb5_keytab keytabid = 0; +# ifdef HAVE_KRB5_AUTH_CON_GETAUTHENTICATOR_DOUBLE_POINTER /* MIT */ krb5_authenticator *authenticator; +# else /* Heimdal */ + krb5_authenticator authenticator; +# endif char *name; krb5_data outbuf; krb5_keyblock *newkey = NULL; @@ -534,7 +597,7 @@ kerberos5_is_auth (TN_Authenticator * ap, unsigned char *data, int cnt, # ifdef AUTH_ENCRYPT_MASK if ((ap->way & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_ON - && !authenticator->checksum) + && !KRB5_AUTHENTICATOR_CHECKSUM (authenticator)) { snprintf (errbuf, errbuflen, "authenticator is missing required checksum"); @@ -542,12 +605,11 @@ kerberos5_is_auth (TN_Authenticator * ap, unsigned char *data, int cnt, } # endif - if (authenticator->checksum) + if (KRB5_AUTHENTICATOR_CHECKSUM (authenticator)) { char type_check[2]; - krb5_checksum *cksum = authenticator->checksum; + krb5_checksum *cksum = KRB5_AUTHENTICATOR_CHECKSUM (authenticator); krb5_keyblock *key; - krb5_boolean valid; type_check[0] = ap->type; type_check[1] = ap->way; @@ -562,9 +624,26 @@ kerberos5_is_auth (TN_Authenticator * ap, unsigned char *data, int cnt, # if 1 /* XXX: Obsolete interface. Remove after investigation. */ +# ifdef HAVE_KRB5_VERIFY_CHECKSUM_SEVEN_PARAMETERS /* MIT */ r = krb5_verify_checksum (telnet_context, - cksum->checksum_type, cksum, - &type_check, 2, key->contents, key->length); + KRB5_CHECKSUM_CHECKSUM_TYPE (cksum), cksum, + &type_check, 2, KRB5_KEYBLOCK_CONTENTS (key), KRB5_KEYBLOCK_LENGTH (key)); +# else /* Heimdal */ + { + krb5_crypto crypto; + + r = krb5_crypto_init (telnet_context, key, 0, &crypto); + if (r) + { + snprintf (errbuf, errbuflen, + "crypto initialization failed: %s", error_message (r)); + return 1; + } + r = krb5_verify_checksum (telnet_context, crypto, KRB5_KU_OTHER_CKSUM, + &type_check, 2, cksum); + krb5_crypto_destroy (telnet_context, crypto); + } +# endif krb5_free_keyblock (telnet_context, key); if (r) @@ -574,26 +653,47 @@ kerberos5_is_auth (TN_Authenticator * ap, unsigned char *data, int cnt, return 1; } #else - /* Incomplete call! + /* Untested call! * * XXX: Establish replacement for the preceding call. * It is no longer present in all implementations. */ - r = krb5_c_verify_checksum (telnet_context, key, - /* usage */, /* data */, - cksum, &valid); - krb5_free_keyblock (telnet_context, key); + { + krb5_keyusage usage; + krb5_data input; + krb5_boolean valid; + +# ifdef KRB5_KEYUSAGE_APP_DATA_CKSUM /* MIT */ + usage = KRB5_KEYUSAGE_APP_DATA_CKSUM; +# else /* Heimdal */ + usage = KRB5_KU_OTHER_CKSUM; +# endif - if (r || !valid) - { - snprintf (errbuf, errbuflen, - "checksum verification failed: %s", error_message (r)); - return 1; - } + input.length = 2; + input.data = (char *) &type_check; + + r = krb5_c_verify_checksum (telnet_context, key, + usage, &input, + cksum, &valid); + krb5_free_keyblock (telnet_context, key); + + if (!valid) + { + if (!r) + r = KRB5KRB_AP_ERR_BAD_INTEGRITY; + snprintf (errbuf, errbuflen, + "checksum verification failed: %s", error_message (r)); + return 1; + } + } #endif } +# ifdef HAVE_KRB5_AUTH_CON_GETAUTHENTICATOR_DOUBLE_POINTER krb5_free_authenticator (telnet_context, authenticator); +# else + krb5_free_authenticator (telnet_context, &authenticator); +# endif if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) { if ((r = krb5_mk_rep (telnet_context, auth_context, &outbuf))) @@ -606,7 +706,7 @@ kerberos5_is_auth (TN_Authenticator * ap, unsigned char *data, int cnt, Data (ap, KRB_RESPONSE, outbuf.data, outbuf.length); } - if (krb5_unparse_name (telnet_context, ticket->enc_part2->client, &name)) + if (krb5_unparse_name (telnet_context, KRB5_TICKET_ENC_PART2 (ticket)->client, &name)) name = 0; Data (ap, KRB_ACCEPT, name, name ? -1 : 0); @@ -630,7 +730,7 @@ kerberos5_is_auth (TN_Authenticator * ap, unsigned char *data, int cnt, } else { - krb5_copy_keyblock (telnet_context, ticket->enc_part2->session, + krb5_copy_keyblock (telnet_context, KRB5_ENC_PART2_SESSION (KRB5_TICKET_ENC_PART2 (ticket)), &session_key); } telnet_encrypt_key (&skey);