* kerberos5.c (kerberos5_send): Send in as input the
authentication type pair (ap->type, ap->way) to be
checksumed in the authenticator.
(kerberos5_is): If the checksum is present in the
authenticator, then validate the authentication type pair
against the checksum.
(kerberos5_reply): If we didn't do mutual authentication,
and we receive a KRB_ACCEPT, then stash away the session
key anyway. This way we have a chance of doing encryption
even if mutual authentication wasn't done.
* encrypt.c (EncryptStartInput, EncryptStartOutput): Added
conditional around printf so that these two functions can
be called by the server.
(encrypt_is_encrypting): New function which returns true
only if both sides of the telnet stream is encrypted.
Fri Mar 15 18:19:44 1996 Theodore Y. Ts'o <tytso@dcl>
* auth.c: Added new authentication scheme for Krb5 mutual
authentication with mandatory encryption.
(auth_send, auth_send_retry): Split auth_send() so that
the functionality done by auth_send_retry() is separate.
This avoids a really dodgy pointer comparison which was
caused by auth_send() being used for two purposes.
If the client has not requested encryption, then don't
use the authentication systems which require encryption.
(auth_must_encrypt): New function which returns whether
or not encryption must be negotiated.
* auth-proto.h: Added prototype for new option
auth_must_encrypt().
* Makefile.in (ENCRYPTION, DES_ENCRYPTION): Added defines to turn
on encryption and des encryption.
git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@7661
dc483132-0cff-0310-8789-
dd5450dbe970
+Mon Mar 18 20:56:37 1996 Theodore Y. Ts'o <tytso@dcl>
+
+ * kerberos5.c (kerberos5_send): Send in as input the
+ authentication type pair (ap->type, ap->way) to be
+ checksumed in the authenticator.
+ (kerberos5_is): If the checksum is present in the
+ authenticator, then validate the authentication type pair
+ against the checksum.
+ (kerberos5_reply): If we didn't do mutual authentication,
+ and we receive a KRB_ACCEPT, then stash away the session
+ key anyway. This way we have a chance of doing encryption
+ even if mutual authentication wasn't done.
+
+ * encrypt.c (EncryptStartInput, EncryptStartOutput): Added
+ conditional around printf so that these two functions can
+ be called by the server.
+ (encrypt_is_encrypting): New function which returns true
+ only if both sides of the telnet stream is encrypted.
+
+Fri Mar 15 18:19:44 1996 Theodore Y. Ts'o <tytso@dcl>
+
+ * auth.c: Added new authentication scheme for Krb5 mutual
+ authentication with mandatory encryption.
+ (auth_send, auth_send_retry): Split auth_send() so that
+ the functionality done by auth_send_retry() is separate.
+ This avoids a really dodgy pointer comparison which was
+ caused by auth_send() being used for two purposes.
+ If the client has not requested encryption, then don't
+ use the authentication systems which require encryption.
+ (auth_must_encrypt): New function which returns whether
+ or not encryption must be negotiated.
+
+ * auth-proto.h: Added prototype for new option
+ auth_must_encrypt().
+
+ * Makefile.in (ENCRYPTION, DES_ENCRYPTION): Added defines to turn
+ on encryption and des encryption.
+
Fri Jan 26 01:05:46 1996 Sam Hartman <hartmans@tertius.mit.edu>
* kerberos5.c (kerberos5_send): Get DES_CBC-CRC credentials.
#
# @(#)Makefile.generic 5.5 (Berkeley) 3/1/91
#
-AUTH_DEF=-DAUTHENTICATION -DKRB5 -DFORWARD -UNO_LOGIN_F -DLOGIN_CAP_F -DLOGIN_PROGRAM=KRB5_PATH_LOGIN
+AUTH_DEF=-DAUTHENTICATION -DENCRYPTION -DDES_ENCRYPTION -DKRB5 -DFORWARD \
+ -UNO_LOGIN_F -DLOGIN_CAP_F -DLOGIN_PROGRAM=KRB5_PATH_LOGIN
LOCALINCLUDES=-I.. -I$(srcdir)/.. -I$(SRCTOP)/include/kerberosIV
CFLAGS = $(CCOPTS) $(AUTH_DEF) $(DEFS) $(LOCALINCLUDES)
LIBOBJS=@LIBOBJS@
void auth_reply P((unsigned char *, int));
void auth_finished P((Authenticator *, int));
int auth_wait P((char *));
+int auth_must_encrypt P((void));
void auth_disable_name P((char *));
void auth_gen_printsub P((unsigned char *, int, unsigned char *, int));
#endif
int auth_debug_mode = 0;
+int auth_has_failed = 0;
+int auth_enable_encrypt = 0;
static char *Name = "Noname";
static int Server = 0;
static Authenticator *authenticated = 0;
spx_printsub },
#endif
#ifdef KRB5
+#ifdef ENCRYPTION
+ { AUTHTYPE_KERBEROS_V5,
+ AUTH_WHO_CLIENT|AUTH_HOW_MUTUAL|AUTH_ENCRYPT_ON,
+ kerberos5_init,
+ kerberos5_send,
+ kerberos5_is,
+ kerberos5_reply,
+ kerberos5_status,
+ kerberos5_printsub },
+#endif
{ AUTHTYPE_KERBEROS_V5, AUTH_WHO_CLIENT|AUTH_HOW_MUTUAL,
kerberos5_init,
kerberos5_send,
unsigned char *data;
int cnt;
{
- Authenticator *ap;
- static unsigned char str_none[] = { IAC, SB, TELOPT_AUTHENTICATION,
- TELQUAL_IS, AUTHTYPE_NULL, 0,
- IAC, SE };
if (Server) {
if (auth_debug_mode) {
printf(">>>%s: auth_send called!\r\n", Name);
}
/*
- * Save the data, if it is new, so that we can continue looking
- * at it if the authorization we try doesn't work
+ * Save the list of authentication mechanisms
*/
- /* ANSI X3.159-1989 section 3.3.6 indicates that this entire
- conditional is undefined. It will probably work on flat address
- space UNIX systems though. --eichin@mit.edu */
- if (data < _auth_send_data ||
- data > _auth_send_data + sizeof(_auth_send_data)) {
- auth_send_cnt = cnt > sizeof(_auth_send_data)
- ? sizeof(_auth_send_data)
- : cnt;
- memcpy((void *)_auth_send_data, (void *)data, auth_send_cnt);
- auth_send_data = _auth_send_data;
- } else {
+ auth_send_cnt = cnt;
+ if (auth_send_cnt > sizeof(_auth_send_data))
+ auth_send_cnt = sizeof(_auth_send_data);
+ memcpy((void *)_auth_send_data, (void *)data, auth_send_cnt);
+ auth_send_data = _auth_send_data;
+
+ auth_send_retry();
+}
+
+/*
+ * Try the next authentication mechanism on the list, and see if it
+ * works.
+ */
+void auth_send_retry()
+{
+ Authenticator *ap;
+ static unsigned char str_none[] = { IAC, SB, TELOPT_AUTHENTICATION,
+ TELQUAL_IS, AUTHTYPE_NULL, 0,
+ IAC, SE };
+
+ if (Server) {
+ if (auth_debug_mode) {
+ printf(">>>%s: auth_send_retry called!\r\n", Name);
+ }
+ return;
+ }
+
+ for (;(auth_send_cnt -= 2) >= 0; auth_send_data += 2) {
+ if (auth_debug_mode)
+ printf(">>>%s: He supports %d\r\n", Name, *auth_send_data);
+ if (!(i_support & typemask(*auth_send_data)))
+ continue;
+ if (i_wont_support & typemask(*auth_send_data))
+ continue;
+ ap = findauthenticator(auth_send_data[0], auth_send_data[1]);
+ if (!ap || !ap->send)
+ continue;
+ if ((ap->way & AUTH_ENCRYPT_MASK) && !auth_enable_encrypt)
+ continue;
+
+ if (auth_debug_mode)
+ printf(">>>%s: Trying %d %d\r\n", Name, auth_send_data[0],
+ auth_send_data[1]);
+ if ((*ap->send)(ap)) {
/*
- * This is probably a no-op, but we just make sure
+ * Okay, we found one we like and did it. we can go
+ * home now.
*/
- auth_send_data = data;
- auth_send_cnt = cnt;
- }
- while ((auth_send_cnt -= 2) >= 0) {
if (auth_debug_mode)
- printf(">>>%s: He supports %d\r\n",
- Name, *auth_send_data);
- if ((i_support & ~i_wont_support) & typemask(*auth_send_data)) {
- ap = findauthenticator(auth_send_data[0],
- auth_send_data[1]);
- if (ap && ap->send) {
- if (auth_debug_mode)
- printf(">>>%s: Trying %d %d\r\n",
- Name, auth_send_data[0],
- auth_send_data[1]);
- if ((*ap->send)(ap)) {
- /*
- * Okay, we found one we like
- * and did it.
- * we can go home now.
- */
- if (auth_debug_mode)
- printf(">>>%s: Using type %d\r\n",
- Name, *auth_send_data);
- auth_send_data += 2;
- return;
- }
- }
- /* else
- * just continue on and look for the
- * next one if we didn't do anything.
- */
- }
+ printf(">>>%s: Using type %d\r\n", Name, *auth_send_data);
auth_send_data += 2;
+ return;
+ }
}
net_write(str_none, sizeof(str_none));
printsub('>', &str_none[2], sizeof(str_none) - 2);
if (auth_debug_mode)
printf(">>>%s: Sent failure message\r\n", Name);
auth_finished(0, AUTH_REJECT);
+ auth_has_failed = 1;
#ifdef KANNAN
/*
* We requested strong authentication, however no mechanisms worked.
#endif /* KANNAN */
}
- void
-auth_send_retry()
-{
- /*
- * if auth_send_cnt <= 0 then auth_send will end up rejecting
- * the authentication and informing the other side of this.
- */
- auth_send(auth_send_data, auth_send_cnt);
-}
-
void
auth_is(data, cnt)
unsigned char *data;
return(validuser);
}
+int auth_must_encrypt()
+{
+ if (authenticated &&
+ ((authenticated->way & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_ON))
+ return 1;
+ return 0;
+}
+
void
auth_debug(mode)
int mode;
void encrypt_send_request_end P((void));
void encrypt_send_end P((void));
void encrypt_wait P((void));
+int encrypt_is_encrypting P((void));
void encrypt_send_support P((void));
void encrypt_send_keyid P((int, unsigned char *, int, int));
int net_write P((unsigned char *, int));
encrypt_send_request_start();
return(1);
}
- printf("No previous decryption mode, decryption not enabled\r\n");
+ if (!Server)
+ printf("No previous decryption mode, decryption not enabled\r\n");
return(0);
}
encrypt_start_output(encrypt_mode);
return(1);
}
- printf("No previous encryption mode, encryption not enabled\r\n");
+ if (!Server)
+ printf("No previous encryption mode, encryption not enabled\r\n");
return(0);
}
static unsigned char str_keyid[(MAXKEYLEN*2)+5] = { IAC, SB, TELOPT_ENCRYPT };
-encrypt_enc_keyid(keyid, len)
+void encrypt_keyid();
+
+void encrypt_enc_keyid(keyid, len)
unsigned char *keyid;
int len;
{
encrypt_keyid(&ki[1], keyid, len);
}
-encrypt_dec_keyid(keyid, len)
+void encrypt_dec_keyid(keyid, len)
unsigned char *keyid;
int len;
{
encrypt_keyid(&ki[0], keyid, len);
}
-encrypt_keyid(kp, keyid, len)
+void encrypt_keyid(kp, keyid, len)
struct key_info *kp;
unsigned char *keyid;
int len;
{
Encryptions *ep;
- unsigned char *strp, *cp;
int dir = kp->dir;
register int ret = 0;
void
encrypt_wait()
{
- register int encrypt, decrypt;
if (encrypt_debug_mode)
printf(">>>%s: in encrypt_wait\r\n", Name);
if (!havesessionkey || !(I_SUPPORT_ENCRYPT & remote_supports_decrypt))
return;
}
+int encrypt_is_encrypting()
+{
+ if (encrypt_output && decrypt_input)
+ return 1;
+ return 0;
+}
+
void
encrypt_debug(mode)
int mode;
krb5_creds creds; /* telnet gets session key from here */
krb5_creds * new_creds = 0;
int ap_opts;
+ char type_check[2];
+ krb5_data check_data;
#ifdef ENCRYPTION
krb5_keyblock *newkey = 0;
ap_opts |= AP_OPTS_USE_SUBKEY;
#endif /* ENCRYPTION */
- if ((r = krb5_auth_con_init(telnet_context, &auth_context))) {
- if (auth_debug_mode) {
- printf("Kerberos V5: failed to init auth_context (%s)\r\n",
- error_message(r));
+ if (auth_context) {
+ krb5_auth_con_free(telnet_context, auth_context);
+ auth_context = 0;
}
- return(0);
- }
-
- krb5_auth_con_setflags(telnet_context, auth_context,
- KRB5_AUTH_CONTEXT_RET_TIME);
-
- r = krb5_mk_req_extended(telnet_context, &auth_context, ap_opts,
- NULL, new_creds, &auth);
+ if ((r = krb5_auth_con_init(telnet_context, &auth_context))) {
+ if (auth_debug_mode) {
+ printf("Kerberos V5: failed to init auth_context (%s)\r\n",
+ error_message(r));
+ }
+ return(0);
+ }
+
+ krb5_auth_con_setflags(telnet_context, auth_context,
+ KRB5_AUTH_CONTEXT_RET_TIME);
+
+ type_check[0] = ap->type;
+ type_check[1] = ap->way;
+ check_data.magic = KV5M_DATA;
+ check_data.length = 2;
+ check_data.data = (char *) &type_check;
+
+ r = krb5_mk_req_extended(telnet_context, &auth_context, ap_opts,
+ &check_data, new_creds, &auth);
#ifdef ENCRYPTION
krb5_auth_con_getlocalsubkey(telnet_context, auth_context, &newkey);
if (session_key) {
-krb5_free_keyblock(telnet_context, session_key);
-session_key = 0;
+ krb5_free_keyblock(telnet_context, session_key);
+ session_key = 0;
}
if (newkey) {
/* keep the key in our private storage, but don't use it
yet---see kerberos5_reply() below */
- if ((newkey->enctype != ENCTYPE_DES_CBC_CRC) && (newkey-> enctype != ENCTYPE_DES_CBC_MD5)) {
- if ((new_creds->keyblock.enctype == ENCTYPE_DES_CBC_CRC)||( new_creds->keyblock.enctype == ENCTYPE_DES_CBC_MD5))
+ if ((newkey->enctype != ENCTYPE_DES_CBC_CRC) &&
+ (newkey-> enctype != ENCTYPE_DES_CBC_MD5)) {
+ if ((new_creds->keyblock.enctype == ENCTYPE_DES_CBC_CRC) ||
+ (new_creds->keyblock.enctype == ENCTYPE_DES_CBC_MD5))
/* use the session key in credentials instead */
- krb5_copy_keyblock(telnet_context,&new_creds->keyblock, &session_key);
+ krb5_copy_keyblock(telnet_context,&new_creds->keyblock,
+ &session_key);
else
/* XXX ? */;
} else {
#ifdef ENCRYPTION
Session_Key skey;
#endif
+ char errbuf[128];
char *name;
char *getenv();
krb5_data inbuf;
+ krb5_authenticator *authenticator;
if (cnt-- < 1)
return;
krb5_free_principal(telnet_context, server);
}
if (r) {
- char errbuf[128];
-
- errout:
- (void) strcpy(errbuf, "Read req failed: ");
+ (void) strcpy(errbuf, "krb5_rd_req failed: ");
(void) strcat(errbuf, error_message(r));
- Data(ap, KRB_REJECT, errbuf, -1);
- if (auth_debug_mode)
- printf("%s\r\n", errbuf);
- return;
+ goto errout;
+ }
+ r = krb5_auth_con_getauthenticator(telnet_context,
+ auth_context,
+ &authenticator);
+ if (r) {
+ (void) strcpy(errbuf,
+ "krb5_auth_con_getauthenticator failed: ");
+ (void) strcat(errbuf, error_message(r));
+ goto errout;
+ }
+ if ((ap->way & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_ON &&
+ !authenticator->checksum) {
+ (void) strcpy(errbuf,
+ "authenticator is missing required checksum");
+ goto errout;
+ }
+ if (authenticator->checksum) {
+ char type_check[2];
+ krb5_checksum *cksum = authenticator->checksum;
+ krb5_keyblock *key;
+
+ type_check[0] = ap->type;
+ type_check[1] = ap->way;
+
+ r = krb5_auth_con_getkey(telnet_context, auth_context,
+ &key);
+ if (r) {
+ (void) strcpy(errbuf, "krb5_auth_con_getkey failed: ");
+ (void) strcat(errbuf, error_message(r));
+ goto errout;
+ }
+ r = krb5_verify_checksum(telnet_checksum,
+ cksum->checksum_type, cksum,
+ &type_check, 2, key->contents,
+ key->length);
+ if (r) {
+ (void) strcpy(errbuf,
+ "checksum verification failed: ");
+ (void) strcat(errbuf, error_message(r));
+ goto errout;
+ }
+ krb5_free_keyblock(telnet_context, key);
}
+ krb5_free_authenticator(telnet_context, authenticator);
if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) {
/* do ap_rep stuff here */
if ((r = krb5_mk_rep(telnet_context, auth_context,
- &outbuf)))
+ &outbuf))) {
+ (void) strcpy(errbuf, "Make reply failed: ");
+ (void) strcat(errbuf, error_message(r));
goto errout;
+ }
Data(ap, KRB_RESPONSE, outbuf.data, outbuf.length);
}
free(name);
krb5_auth_con_getremotesubkey(telnet_context, auth_context,
&newkey);
+ if (session_key) {
+ krb5_free_keyblock(telnet_context, session_key);
+ session_key = 0;
+ }
if (newkey) {
- if (session_key) {
- krb5_free_keyblock(telnet_context, session_key);
- session_key = 0;
- }
-
- krb5_copy_keyblock(telnet_context, newkey,
- &session_key);
+ krb5_copy_keyblock(telnet_context, newkey, &session_key);
krb5_free_keyblock(telnet_context, newkey);
} else {
- if (session_key){
- krb5_free_keyblock(telnet_context, session_key);
-session_key = 0;
- }
- krb5_copy_keyblock(telnet_context,
- ticket->enc_part2->session,
- &session_key);
+ krb5_copy_keyblock(telnet_context,
+ ticket->enc_part2->session,
+ &session_key);
}
#ifdef ENCRYPTION
Data(ap, KRB_REJECT, 0, 0);
break;
}
+ return;
+
+ errout:
+ Data(ap, KRB_REJECT, errbuf, -1);
+ if (auth_debug_mode)
+ printf("%s\r\n", errbuf);
+ if (auth_context) {
+ krb5_auth_con_free(telnet_context, auth_context);
+ auth_context = 0;
+ }
+ return;
}
void
auth_send_retry();
return;
case KRB_ACCEPT:
- if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL &&
- !mutual_complete) {
- printf("[ Kerberos V5 accepted you, but didn't provide mutual authentication! ]\r\n");
- auth_send_retry();
- return;
+ if (!mutual_complete) {
+ if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) {
+ printf("[ Kerberos V5 accepted you, but didn't provide mutual authentication! ]\r\n");
+ auth_send_retry();
+ return;
+ }
+#ifdef ENCRYPTION
+ if (session_key) {
+ skey.type = SK_DES;
+ skey.length = 8;
+ skey.data = session_key->contents;
+ encrypt_session_key(&skey, 0);
+ }
+#endif /* ENCRYPTION */
}
if (cnt)
printf("[ Kerberos V5 accepts you as ``%.*s'' ]\r\n", cnt, data);
printf("Unknown Kerberos option %d\r\n", data[-1]);
return;
}
+ return;
}
int