$NetBSD: patch-bk,v 1.1 2000/03/20 02:25:43 itojun Exp $

--- sshconnect.c-	Wed May 12 20:19:29 1999
+++ sshconnect.c	Mon Mar 20 09:20:32 2000
@@ -215,7 +215,6 @@
 #include "userfile.h"
 #include "emulate.h"
 
-#ifdef KERBEROS
 #ifdef KRB5
 #include <krb5.h>
 
@@ -223,7 +222,19 @@
 krb5_context ssh_context = 0;
 krb5_auth_context auth_context = 0;
 #endif /* KRB5 */
-#endif /* KERBEROS */
+
+#ifdef KRB4
+#include <krb.h>
+#ifdef AFS
+#if defined(HAVE_SYS_IOCTL_H) && SunOS != 4
+#include <sys/ioctl.h>
+#endif
+#ifdef HAVE_SYS_FILIO_H
+#include <sys/filio.h>
+#endif
+#include <kafs.h>
+#endif /* AFS */
+#endif /* KRB4 */
 
 /* Session id for the current session. */
 unsigned char session_id[16];
@@ -337,7 +348,7 @@
 
 /* Creates a (possibly privileged) socket for use as the ssh connection. */
 
-int ssh_create_socket(uid_t original_real_uid, int privileged)
+int ssh_create_socket(uid_t original_real_uid, int privileged, int family)
 {
   int sock;
 
@@ -345,43 +356,62 @@
      bind our own socket to a privileged port. */
   if (privileged)
     {
-      struct sockaddr_in sin;
+      struct addrinfo hints, *ai = NULL;
+      int errgai;
+      char strport[PORTSTRLEN];
       int p;
       for (p = 1023; p > 512; p--)
         {
-          sock = socket(AF_INET, SOCK_STREAM, 0);
+	  sock = socket(family, SOCK_STREAM, 0);
           if (sock < 0)
-            fatal("socket: %.100s", strerror(errno));
+	    {
+	      error("socket: %.100s", strerror(errno));
+	      continue;
+	    }
           
-          /* Initialize the desired sockaddr_in structure. */
-          memset(&sin, 0, sizeof(sin));
-          sin.sin_family = AF_INET;
-          sin.sin_addr.s_addr = INADDR_ANY;
-          sin.sin_port = htons(p);
+	  /* Initialize the desired addrinfo structure. */
+	  memset(&hints, 0, sizeof(hints));
+	  hints.ai_family = family;
+	  hints.ai_flags = AI_PASSIVE;
+	  hints.ai_socktype = SOCK_STREAM;
+	  sprintf(strport, "%d", p);
+	  if ((errgai = getaddrinfo(NULL, strport, &hints, &ai)) != 0)
+	    {
+	      error("getaddrinfo: %.100s", gai_strerror(errgai));
+	      close(sock);
+	      continue;
+	    }
 
           /* Try to bind the socket to the privileged port. */
 #if defined(SOCKS)
-          if (Rbind(sock, (struct sockaddr *)&sin, sizeof(sin)) >= 0)
+	  if (Rbind(sock, ai->ai_addr, ai->ai_addrlen) >= 0)
             break; /* Success. */
 #else /* SOCKS */
-          if (bind(sock, (struct sockaddr *)&sin, sizeof(sin)) >= 0)
+	  if (bind(sock, ai->ai_addr, ai->ai_addrlen) >= 0)
             break; /* Success. */
 #endif /* SOCKS */
           if (errno == EADDRINUSE)
             {
               close(sock);
+	      if (ai)
+	        {
+	          freeaddrinfo(ai);
+		  ai = NULL;
+		}
               continue;
             }
-          fatal("bind: %.100s", strerror(errno));
+          error("bind: %.100s", strerror(errno));
         }
       debug("Allocated local port %d.", p);
+      if (ai)
+        freeaddrinfo(ai);
     }
   else
     { 
       /* Just create an ordinary socket on arbitrary port.  */
-      sock = socket(AF_INET, SOCK_STREAM, 0);
+      sock = socket(family, SOCK_STREAM, 0);
       if (sock < 0)
-        fatal("socket: %.100s", strerror(errno));
+        error("socket: %.100s", strerror(errno));
     }
   return sock;
 }
@@ -396,14 +426,19 @@
    the daemon. */
 
 int ssh_connect(const char *host, int port, int connection_attempts,
+#ifdef ENABLE_ANOTHER_PORT_TRY
+		int another_port,
+#endif /* ENABLE_ANOTHER_PORT_TRY */
                 int anonymous, uid_t original_real_uid, 
                 const char *proxy_command, RandomState *random_state)
 {
   int sock = -1, attempt, i;
   int on = 1;
   struct servent *sp;
-  struct hostent *hp;
-  struct sockaddr_in hostaddr;
+  struct addrinfo hints, *ai, *aitop, *aitmp;
+  struct sockaddr_storage hostaddr;
+  char ntop[ADDRSTRLEN], strport[PORTSTRLEN];
+  int gaierr;
 #if defined(SO_LINGER) && defined(ENABLE_SO_LINGER)
   struct linger linger;
 #endif /* SO_LINGER */
@@ -421,10 +456,6 @@
         port = SSH_DEFAULT_PORT;
     }
 
-  /* Map localhost to ip-address locally */
-  if (strcmp(host, "localhost") == 0)
-    host = "127.0.0.1";
-  
   /* If a proxy command is given, connect using it. */
   if (proxy_command != NULL && *proxy_command)
     return ssh_proxy_connect(host, port, original_real_uid, proxy_command,
@@ -432,9 +463,28 @@
 
   /* No proxy command. */
 
-  /* No host lookup made yet. */
-  hp = NULL;
-  
+  memset(&hints, 0, sizeof(hints));
+  hints.ai_family = IPv4or6;
+  hints.ai_socktype = SOCK_STREAM;
+  sprintf(strport, "%d", port);
+  if ((gaierr = getaddrinfo(host, strport, &hints, &aitop)) != 0)
+    fatal("Bad host name: %.100s (%s)", host, gai_strerror(gaierr));
+
+#ifdef ENABLE_ANOTHER_PORT_TRY
+  if (another_port)
+    {
+      aitmp = aitop;
+      memset(&hints, 0, sizeof(hints));
+      hints.ai_family = IPv4or6;
+      hints.ai_socktype = SOCK_STREAM;
+      sprintf(strport, "%d", another_port);
+      if ((gaierr = getaddrinfo(host, strport, &hints, &aitop)) != 0)
+	fatal("Bad host name: %.100s (%s)", host, gai_strerror(gaierr));
+      for (ai = aitop; ai->ai_next; ai = ai->ai_next);
+      ai->ai_next = aitmp;
+    }
+#endif /* ENABLE_ANOTHER_PORT_TRY */
+
   /* Try to connect several times.  On some machines, the first time will
      sometimes fail.  In general socket code appears to behave quite
      magically on many machines. */
@@ -443,103 +493,29 @@
       if (attempt > 0)
         debug("Trying again...");
 
-      /* Try to parse the host name as a numeric inet address. */
-      memset(&hostaddr, 0, sizeof(hostaddr));
-      hostaddr.sin_family = AF_INET;
-      hostaddr.sin_port = htons(port);
-#ifdef BROKEN_INET_ADDR
-      hostaddr.sin_addr.s_addr = inet_network(host);
-#else /* BROKEN_INET_ADDR */
-      hostaddr.sin_addr.s_addr = inet_addr(host);
-#endif /* BROKEN_INET_ADDR */
-      if ((hostaddr.sin_addr.s_addr & 0xffffffff) != 0xffffffff)
-        { 
-          /* Create a socket. */
-          sock = ssh_create_socket(original_real_uid, 
-                                   !anonymous && geteuid() == UID_ROOT);
-      
-          /* Valid numeric IP address */
-          debug("Connecting to %.100s port %d.", 
-                inet_ntoa(hostaddr.sin_addr), port);
-
-          /* Connect to the host. */
-#if defined(SOCKS)
-          if (Rconnect(sock, (struct sockaddr *)&hostaddr, sizeof(hostaddr))
-#else /* SOCKS */
-          if (connect(sock, (struct sockaddr *)&hostaddr, sizeof(hostaddr))
-#endif /* SOCKS */
-              >= 0)
-            {
-              /* Successful connect. */
-              break;
-            }
-          debug("connect: %.100s", strerror(errno));
-
-          /* Destroy the failed socket. */
-          shutdown(sock, 2);
-          close(sock);
-        }
-      else
-        { 
-          /* Not a valid numeric inet address. */
-          /* Map host name to an address. */
-          if (!hp)
-            {
-              struct hostent *hp_static;
-
-#if defined(SOCKS5)
-              hp_static = Rgethostbyname(host);
-#else
-              hp_static = gethostbyname(host);
-#endif
-              if (hp_static)
-                {
-                  hp = xmalloc(sizeof(struct hostent));
-                  memcpy(hp, hp_static, sizeof(struct hostent));
-
-                  /* Copy list of addresses, not just pointers.
-                     We don't use h_name & h_aliases so leave them as is */
-                  for (i = 0; hp_static->h_addr_list[i]; i++)
-                    ; /* count them */
-                  hp->h_addr_list = xmalloc((i + 1) *
-                                            sizeof(hp_static->h_addr_list[0]));
-                  for (i = 0; hp_static->h_addr_list[i]; i++)
-                    {
-                      hp->h_addr_list[i] = xmalloc(hp->h_length);
-                      memcpy(hp->h_addr_list[i], hp_static->h_addr_list[i],
-                             hp->h_length);
-                    }
-                  hp->h_addr_list[i] = NULL; /* last one */
-                }
-            }
-          if (!hp)
-            fatal("Bad host name: %.100s", host);
-          if (!hp->h_addr_list[0])
-            fatal("Host does not have an IP address: %.100s", host);
-
           /* Loop through addresses for this host, and try each one in
              sequence until the connection succeeds. */
-          for (i = 0; hp->h_addr_list[i]; i++)
+          for (ai = aitop; ai; ai = ai->ai_next)
             {
-              /* Set the address to connect to. */
-              hostaddr.sin_family = hp->h_addrtype;
-              memcpy(&hostaddr.sin_addr, hp->h_addr_list[i],
-                     sizeof(hostaddr.sin_addr));
+	      getnameinfo(ai->ai_addr, ai->ai_addrlen,
+			  ntop, sizeof(ntop), strport, sizeof(strport),
+			  NI_NUMERICHOST|NI_NUMERICSERV);
 
-              debug("Connecting to %.200s [%.100s] port %d.",
-                    host, inet_ntoa(hostaddr.sin_addr), port);
+	      debug("Connecting to %.200s [%.100s] port %s.",
+		    host, ntop, strport);
 
               /* Create a socket for connecting. */
               sock = ssh_create_socket(original_real_uid, 
-                                       !anonymous && geteuid() == UID_ROOT);
+				       !anonymous && geteuid() == UID_ROOT,
+				       ai->ai_family);
+	      if (sock < 0)
+		 continue;
 
               /* Connect to the host. */
 #if defined(SOCKS)
-              if (Rconnect(sock, (struct sockaddr *)&hostaddr, 
-                           sizeof(hostaddr)) >= 0)
+	      if (Rconnect(sock, ai->ai_addr, ai->ai_addrlen) >= 0)
 #else /* SOCKS */
-              if (connect(sock, (struct sockaddr *)&hostaddr, 
-                          sizeof(hostaddr)) >= 0)
+	      if (connect(sock, ai->ai_addr, ai->ai_addrlen) >= 0)
 #endif /* SOCKS */
                 {
                   /* Successful connection. */
@@ -552,22 +528,15 @@
                  returned an error. */
               shutdown(sock, 2);
               close(sock);
-            }
-          if (hp->h_addr_list[i])
+	    } /* for (ai = aitop; ai; ai = ai->ai_next) */
+          if (ai)
             break; /* Successful connection. */
-        }
 
       /* Sleep a moment before retrying. */
       sleep(1);
     }
 
-  if (hp)
-    {
-      for (i = 0; hp->h_addr_list[i]; i++)
-        xfree(hp->h_addr_list[i]);
-      xfree(hp->h_addr_list);
-      xfree(hp);
-    }
+  freeaddrinfo(aitop);
 
   /* Return failure if we didn't get a successful connection. */
   if (attempt >= connection_attempts)
@@ -932,10 +901,9 @@
   return 0;
 }
 
-#ifdef KERBEROS
+#ifdef KRB5
 int try_kerberos_authentication(void)
 {
-#ifdef KRB5
   char *remotehost;
   krb5_data auth;
   krb5_error_code r;
@@ -946,7 +914,7 @@
   int ap_opts, ret_stat = 0;
   krb5_keyblock   *session_key = 0;
   krb5_ap_rep_enc_part *repl = 0;
-  struct sockaddr_in local, foreign;
+  struct sockaddr_storage local, foreign;
   
   memset(&auth, 0 , sizeof(auth));
   remotehost = (char *) get_canonical_hostname();
@@ -1084,15 +1052,118 @@
     krb5_free_ap_rep_enc_part(ssh_context, repl);
   
   return(ret_stat);
+}
 #endif /* KRB5 */
+
+#ifdef KRB4
+int try_kerberos_authentication()
+{
+  KTEXT_ST auth;                     /* Kerberos data */
+  char *reply;
+  char inst[INST_SZ];
+  char *realm;
+  char *service;
+  CREDENTIALS cred;
+  int r, type;
+  Key_schedule schedule;
+  u_long checksum, cksum;
+  MSG_DAT msg_data;
+  struct sockaddr_in local, foreign;
+  struct stat st;
+  
+  /* Don't do anything if we don't have any tickets. */
+  if (stat(tkt_string(), &st) < 0) return 0;
+  
+  strncpy(inst, (char *) krb_get_phost(get_canonical_hostname()), INST_SZ);
+  
+  realm = (char *)krb_realmofhost(get_canonical_hostname());
+  if (!realm) {
+    debug("Kerberos V4: no realm for %s", get_canonical_hostname());
+    return 0;
+  }
+  /* This can really be anything. */
+  checksum = (u_long) getpid();
+  
+  if (r = krb_mk_req(&auth, KRB4_SERVICE_NAME, inst, realm, checksum)) {
+    debug("Kerberos V4 krb_mk_req failed: %s", krb_err_txt[r]);
+    return 0;
+  }
+  /* Get session key to decrypt the server's reply with. */
+  if (r = krb_get_cred(KRB4_SERVICE_NAME, inst, realm, &cred)) {
+     debug("get_cred failed: %s", krb_err_txt[r]);
+     return 0;
+  }
+  des_key_sched((des_cblock *)cred.session, schedule);
+  
+  /* Send authentication info to server. */
+  packet_start(SSH_CMSG_AUTH_KERBEROS);
+  packet_put_string((char *)auth.dat, auth.length);
+  packet_send();
+  packet_write_wait();
+  
+  /* zero the buffer */
+  (void) memset(auth.dat, 0, MAX_KTXT_LEN);
+  
+  r = sizeof(local);
+  memset(&local, 0, sizeof(local));
+  if (getsockname(packet_get_connection_in(),
+ 		  (struct sockaddr *) &local, &r) < 0)
+    debug("getsockname failed: %.100s", strerror(errno));
+  
+  r = sizeof(foreign);
+  memset(&foreign, 0, sizeof(foreign));
+   if (getpeername(packet_get_connection_in(),
+		   (struct sockaddr *)&foreign, &r) < 0)
+     debug("getpeername failed: %.100s", strerror(errno));
+   
+   /* Get server reply. */
+   type = packet_read();
+   switch(type) {
+     
+   case SSH_SMSG_FAILURE: /* Should really be SSH_SMSG_AUTH_KERBEROS_FAILURE */
+     debug("Kerberos V4 authentication failed.");
+     return 0;
+     break;
+     
+   case SSH_SMSG_AUTH_KERBEROS_RESPONSE: /* SSH_SMSG_AUTH_KERBEROS_SUCCESS */
+     debug("Kerberos V4 authentication accepted.");
+     
+     /* Get server's response. */
+     reply = packet_get_string((unsigned int *)&auth.length);
+     memcpy(auth.dat, reply, auth.length);
+     xfree(reply);
+     
+     /* If his response isn't properly encrypted with the session key,
+        and the decrypted checksum fails to match, he's bogus. Bail out. */
+     if (r = krb_rd_priv(auth.dat, auth.length, schedule, &cred.session,
+			 &foreign, &local, &msg_data)) {
+       debug("Kerberos V4 krb_rd_priv failed: %s", krb_err_txt[r]);
+       packet_disconnect("Kerberos V4 challenge failed!");
+     }
+     /* fetch the (incremented) checksum that we supplied in the request */
+     (void)memcpy((char *)&cksum, (char *)msg_data.app_data, sizeof(cksum));
+     cksum = ntohl(cksum);
+     
+     /* If it matches, we're golden. */
+     if (cksum == checksum + 1) {
+       debug("Kerberos V4 challenge successful.");
+       return 1;
+     }
+     else
+       packet_disconnect("Kerberos V4 challenge failed!");
+     break;
+     
+   default:
+     packet_disconnect("Protocol error on Kerberos V4 response: %d", type);
+   }
 }
-#endif /* KERBEROS */
+#endif /* KRB4 */
+
 
-#ifdef KERBEROS_TGT_PASSING
 /* Forward our local Kerberos tgt to the server. */
+#ifdef KRB5
 int send_kerberos_tgt(void)
 {
-#ifdef KRB5
   char *remotehost;
   krb5_principal client;
   krb5_principal server;
@@ -1172,22 +1243,117 @@
     krb5_free_principal(ssh_context, client);
     krb5_free_principal(ssh_context, server);
     
-    type = packet_read();
-    if (type == SSH_SMSG_SUCCESS)
-      {
-        debug("Kerberos V5 TGT passing was successful.");
-        return 1;
-      }
-    else
-      if (type != SSH_SMSG_FAILURE)
-        packet_disconnect("Protocol error on Kerberos tgt response: %d", type);
-      else 
-        debug("Kerberos V5 TGT passing failed.");
-    
-    return 0;
+    return 1;
+}
 #endif /* KRB5 */
+
+#ifdef AFS
+int send_kerberos_tgt()
+{
+  CREDENTIALS *creds;
+  char pname[ANAME_SZ], pinst[INST_SZ], prealm[REALM_SZ];
+  int r, type;
+  unsigned char buffer[8192];
+  struct stat st;
+
+  /* Don't do anything if we don't have any tickets. */
+  if (stat(tkt_string(), &st) < 0) return 0;
+      
+  creds = xmalloc(sizeof(CREDENTIALS));
+  
+  if ((r=krb_get_tf_fullname(TKT_FILE,pname,pinst,prealm)) != KSUCCESS) {
+    debug("Kerberos V4 tf_fullname failed: %s",krb_err_txt[r]);
+    return 0;
+  }
+  if ((r=krb_get_cred("krbtgt", prealm, prealm, creds)) != GC_OK) {
+    debug("Kerberos V4 get_cred failed: %s", krb_err_txt[r]);
+    return 0;
+  }
+  if (time(0) >
+#ifdef HAVE_KRB_LIFE_TO_TIME
+      (unsigned long)krb_life_to_time(creds->issue_date, creds->lifetime)) {
+#else
+      (creds->issue_date + ((unsigned char)creds->lifetime * 5 * 60))) {
+#endif /* HAVE_KRB_LIFE_TO_TIME */
+    debug("Kerberos V4 ticket expired: %s", TKT_FILE);
+    return 0;
+  }
+
+  creds_to_radix(creds, buffer);
+  xfree(creds);
+    
+  packet_start(SSH_CMSG_HAVE_KERBEROS_TGT);
+  packet_put_string((char *)buffer, strlen(buffer));
+  packet_send();
+  packet_write_wait();
+
+  return 1;
+}
+
+/* Forwards our AFS tokens to the server. */
+void send_afs_tokens(void)
+{
+  CREDENTIALS creds;
+  struct ViceIoctl parms;
+  struct ClearToken ct;
+  int i, type;
+  int len;
+  char buf[2048], *p, *server_cell;
+  unsigned char buffer[8192];
+
+  /* Move over ktc_GetToken, here's something leaner. */
+  for (i = 0; i < 100; i++) { /* just in case */
+    parms.in = (char *)&i;
+    parms.in_size = sizeof(i);
+    parms.out = buf;
+    parms.out_size = sizeof(buf);
+    if (k_pioctl(0, VIOCGETTOK, &parms, 0) != 0) break;
+    p = buf;
+    
+    /* Get secret token. */
+    memcpy(&creds.ticket_st.length, p, sizeof(unsigned int));
+    if (creds.ticket_st.length > MAX_KTXT_LEN) break;
+    p += sizeof(unsigned int);
+    memcpy(creds.ticket_st.dat, p, creds.ticket_st.length);
+    p += creds.ticket_st.length;
+        
+    /* Get clear token. */
+    memcpy(&len, p, sizeof(len));
+    if (len != sizeof(struct ClearToken)) break;
+    p += sizeof(len);
+    memcpy(&ct, p, len);
+    p += len;
+    p += sizeof(len); /* primary flag */
+    server_cell = p;
+
+    /* Flesh out our credentials. */
+    strcpy(creds.service, "afs");
+    creds.instance[0] = '\0';
+    strncpy(creds.realm, server_cell, REALM_SZ);
+    memcpy(creds.session, ct.HandShakeKey, DES_KEY_SZ);
+    creds.issue_date = ct.BeginTimestamp;
+    creds.lifetime = krb_time_to_life(creds.issue_date, ct.EndTimestamp);
+    creds.kvno = ct.AuthHandle;
+    snprintf(creds.pname, sizeof(creds.pname), "AFS ID %d", ct.ViceId);
+    creds.pinst[0] = '\0';
+
+    /* Encode token, ship it off. */
+    if (!creds_to_radix(&creds, buffer)) break;
+    packet_start(SSH_CMSG_HAVE_AFS_TOKEN);
+    packet_put_string((char *)buffer, strlen(buffer));
+    packet_send();
+    packet_write_wait();
+
+    /* Roger, Roger. Clearance, Clarence. What's your vector, Victor? */
+    type = packet_read();
+
+    if (type == SSH_SMSG_FAILURE)
+      debug("AFS token for cell %s rejected.", server_cell);
+    else if (type != SSH_SMSG_SUCCESS)
+      packet_disconnect("Protocol error on AFS token response: %d", type);
+  }  
 }
-#endif /* KERBEROS_TGT_PASSING */
+#endif /* AFS */
 
 /* Waits for the server identification string, and sends our own identification
    string. */
@@ -1285,14 +1451,12 @@
   unsigned char check_bytes[8];
   unsigned int supported_ciphers, supported_authentications, protocol_flags;
   HostStatus host_status;
-#ifdef KERBEROS 
 #ifdef KRB5
   char *kuser;
   krb5_ccache ccache;
   krb5_error_code problem;
   krb5_principal client;
-#endif
-#endif
+#endif /* KRB5 */
   
   /* Convert the user-supplied hostname into all lowercase. */
   host = xstrdup(orighost);
@@ -1595,7 +1759,6 @@
 
   debug("Received encrypted confirmation.");
 
-#ifdef KERBEROS 
 #ifdef KRB5
   if (!ssh_context)
     {
@@ -1629,7 +1792,6 @@
         debug("Kerberos V5: could not get default ccache.");
     }
 #endif /* KRB5 */
-#endif /* KERBEROS */
   
   /* Send the name of the user to log in as on the server. */
   packet_start(SSH_CMSG_USER);
@@ -1647,24 +1809,39 @@
     packet_disconnect("Protocol error: got %d in response to SSH_CMSG_USER",
                       type);
 
-#ifdef KERBEROS_TGT_PASSING
+#if defined(KRB5) || defined(AFS)
   /* Try Kerberos tgt passing if the server supports it. */
   if ((supported_authentications & (1 << SSH_PASS_KERBEROS_TGT)) &&
       options->kerberos_tgt_passing)
     {
       if (options->cipher == SSH_CIPHER_NONE)
         log_msg("WARNING: Encryption is disabled! Ticket will be transmitted in the clear!");
-      (void)send_kerberos_tgt();
+      if (send_kerberos_tgt())
+      {
+        type = packet_read();
+        if (type == SSH_SMSG_FAILURE)
+	  debug("Kerberos TGT passing failed.");
+        else if (type != SSH_SMSG_SUCCESS)
+	  packet_disconnect("Protocol error on Kerberos tgt response: %d", type);
+      }
     }
-#endif /* KERBEROS_TGT_PASSING */
+#endif /* KRB5 || AFS */
+
+#ifdef AFS
+  /* Try AFS token passing if the server supports it. */
+  if ((supported_authentications & (1 << SSH_PASS_AFS_TOKEN)) &&
+      options->afs_token_passing && k_hasafs())  {
+    if (options->cipher == SSH_CIPHER_NONE)
+      log_msg("WARNING: Encryption is disabled! Token will be transmitted in the clear!");
+    send_afs_tokens();
+  }
+#endif /* AFS */
   
-#ifdef KERBEROS
-#ifdef KRB5
+#if defined(KRB4) || defined(KRB5)
   if ((supported_authentications & (1 << SSH_AUTH_KERBEROS)) &&
       options->kerberos_authentication)
     {
-      debug("Trying Kerberos V5 authentication.");
-#endif
+      debug("Trying Kerberos authentication.");
       if (try_kerberos_authentication()) {
         /* The server should respond with success or failure. */
         type = packet_read();
@@ -1673,10 +1850,8 @@
         if (type != SSH_SMSG_FAILURE)
           packet_disconnect("Protocol error: got %d in response to Kerberos auth", type);
       }
-#ifdef KRB5
     }
-#endif
-#endif /* KERBEROS */
+#endif /* KRB4 || KRB5 */
 
   /* Use rhosts authentication if running in privileged socket and we do not
      wish to remain anonymous. */