[BACK]Return to auth2.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / ssh

Diff for /src/usr.bin/ssh/auth2.c between version 1.71.2.5 and 1.72

version 1.71.2.5, 2002/10/11 14:53:06 version 1.72, 2001/11/07 22:41:51
Line 25 
Line 25 
 #include "includes.h"  #include "includes.h"
 RCSID("$OpenBSD$");  RCSID("$OpenBSD$");
   
   #include <openssl/evp.h>
   
 #include "ssh2.h"  #include "ssh2.h"
 #include "xmalloc.h"  #include "xmalloc.h"
   #include "rsa.h"
   #include "sshpty.h"
 #include "packet.h"  #include "packet.h"
   #include "buffer.h"
 #include "log.h"  #include "log.h"
 #include "servconf.h"  #include "servconf.h"
 #include "compat.h"  #include "compat.h"
   #include "channels.h"
   #include "bufaux.h"
 #include "auth.h"  #include "auth.h"
   #include "session.h"
 #include "dispatch.h"  #include "dispatch.h"
   #include "key.h"
   #include "cipher.h"
   #include "kex.h"
 #include "pathnames.h"  #include "pathnames.h"
 #include "monitor_wrap.h"  #include "uidswap.h"
   #include "auth-options.h"
   #include "misc.h"
   #include "hostfile.h"
   #include "canohost.h"
   #include "match.h"
   
 /* import */  /* import */
 extern ServerOptions options;  extern ServerOptions options;
 extern u_char *session_id2;  extern u_char *session_id2;
 extern int session_id2_len;  extern int session_id2_len;
   
 Authctxt *x_authctxt = NULL;  static Authctxt *x_authctxt = NULL;
   static int one = 1;
   
 /* methods */  typedef struct Authmethod Authmethod;
   struct Authmethod {
 extern Authmethod method_none;          char    *name;
 extern Authmethod method_pubkey;          int     (*userauth)(Authctxt *authctxt);
 extern Authmethod method_passwd;          int     *enabled;
 extern Authmethod method_kbdint;  
 extern Authmethod method_hostbased;  
   
 Authmethod *authmethods[] = {  
         &method_none,  
         &method_pubkey,  
         &method_passwd,  
         &method_kbdint,  
         &method_hostbased,  
         NULL  
 };  };
   
 /* protocol */  /* protocol */
   
 static void input_service_request(int, u_int32_t, void *);  static void input_service_request(int, int, void *);
 static void input_userauth_request(int, u_int32_t, void *);  static void input_userauth_request(int, int, void *);
   static void protocol_error(int, int, void *);
   
 /* helper */  /* helper */
 static Authmethod *authmethod_lookup(const char *);  static Authmethod *authmethod_lookup(const char *);
 static char *authmethods_get(void);  static char *authmethods_get(void);
 int user_key_allowed(struct passwd *, Key *);  static int user_key_allowed(struct passwd *, Key *);
 int hostbased_key_allowed(struct passwd *, const char *, char *, Key *);  static int hostbased_key_allowed(struct passwd *, const char *, char *, Key *);
   
   /* auth */
   static void userauth_banner(void);
   static int userauth_none(Authctxt *);
   static int userauth_passwd(Authctxt *);
   static int userauth_pubkey(Authctxt *);
   static int userauth_hostbased(Authctxt *);
   static int userauth_kbdint(Authctxt *);
   
   Authmethod authmethods[] = {
           {"none",
                   userauth_none,
                   &one},
           {"publickey",
                   userauth_pubkey,
                   &options.pubkey_authentication},
           {"password",
                   userauth_passwd,
                   &options.password_authentication},
           {"keyboard-interactive",
                   userauth_kbdint,
                   &options.kbd_interactive_authentication},
           {"hostbased",
                   userauth_hostbased,
                   &options.hostbased_authentication},
           {NULL, NULL, NULL}
   };
   
 /*  /*
  * loop until authctxt->success == TRUE   * loop until authctxt->success == TRUE
  */   */
   
 Authctxt *  void
 do_authentication2(void)  do_authentication2()
 {  {
         Authctxt *authctxt = authctxt_new();          Authctxt *authctxt = authctxt_new();
   
Line 86 
Line 121 
         if (options.challenge_response_authentication)          if (options.challenge_response_authentication)
                 options.kbd_interactive_authentication = 1;                  options.kbd_interactive_authentication = 1;
   
         dispatch_init(&dispatch_protocol_error);          dispatch_init(&protocol_error);
         dispatch_set(SSH2_MSG_SERVICE_REQUEST, &input_service_request);          dispatch_set(SSH2_MSG_SERVICE_REQUEST, &input_service_request);
         dispatch_run(DISPATCH_BLOCK, &authctxt->success, authctxt);          dispatch_run(DISPATCH_BLOCK, &authctxt->success, authctxt);
           do_authenticated(authctxt);
   }
   
         return (authctxt);  static void
   protocol_error(int type, int plen, void *ctxt)
   {
           log("auth: protocol error: type %d plen %d", type, plen);
           packet_start(SSH2_MSG_UNIMPLEMENTED);
           packet_put_int(0);
           packet_send();
           packet_write_wait();
 }  }
   
 static void  static void
 input_service_request(int type, u_int32_t seq, void *ctxt)  input_service_request(int type, int plen, void *ctxt)
 {  {
         Authctxt *authctxt = ctxt;          Authctxt *authctxt = ctxt;
         u_int len;          u_int len;
         int acceptit = 0;          int accept = 0;
         char *service = packet_get_string(&len);          char *service = packet_get_string(&len);
         packet_check_eom();          packet_done();
   
         if (authctxt == NULL)          if (authctxt == NULL)
                 fatal("input_service_request: no authctxt");                  fatal("input_service_request: no authctxt");
   
         if (strcmp(service, "ssh-userauth") == 0) {          if (strcmp(service, "ssh-userauth") == 0) {
                 if (!authctxt->success) {                  if (!authctxt->success) {
                         acceptit = 1;                          accept = 1;
                         /* now we can handle user-auth requests */                          /* now we can handle user-auth requests */
                         dispatch_set(SSH2_MSG_USERAUTH_REQUEST, &input_userauth_request);                          dispatch_set(SSH2_MSG_USERAUTH_REQUEST, &input_userauth_request);
                 }                  }
         }          }
         /* XXX all other service requests are denied */          /* XXX all other service requests are denied */
   
         if (acceptit) {          if (accept) {
                 packet_start(SSH2_MSG_SERVICE_ACCEPT);                  packet_start(SSH2_MSG_SERVICE_ACCEPT);
                 packet_put_cstring(service);                  packet_put_cstring(service);
                 packet_send();                  packet_send();
Line 127 
Line 171 
 }  }
   
 static void  static void
 input_userauth_request(int type, u_int32_t seq, void *ctxt)  input_userauth_request(int type, int plen, void *ctxt)
 {  {
         Authctxt *authctxt = ctxt;          Authctxt *authctxt = ctxt;
         Authmethod *m = NULL;          Authmethod *m = NULL;
Line 148 
Line 192 
   
         if (authctxt->attempt++ == 0) {          if (authctxt->attempt++ == 0) {
                 /* setup auth context */                  /* setup auth context */
                 authctxt->pw = PRIVSEP(getpwnamallow(user));                  struct passwd *pw = NULL;
                 if (authctxt->pw && strcmp(service, "ssh-connection")==0) {                  pw = getpwnam(user);
                   if (pw && allowed_user(pw) && strcmp(service, "ssh-connection")==0) {
                           authctxt->pw = pwcopy(pw);
                         authctxt->valid = 1;                          authctxt->valid = 1;
                         debug2("input_userauth_request: setting up authctxt for %s", user);                          debug2("input_userauth_request: setting up authctxt for %s", user);
                 } else {                  } else {
                         log("input_userauth_request: illegal user %s", user);                          log("input_userauth_request: illegal user %s", user);
                 }                  }
                 setproctitle("%s%s", authctxt->pw ? user : "unknown",                  setproctitle("%s", pw ? user : "unknown");
                     use_privsep ? " [net]" : "");  
                 authctxt->user = xstrdup(user);                  authctxt->user = xstrdup(user);
                 authctxt->service = xstrdup(service);                  authctxt->service = xstrdup(service);
                 authctxt->style = style ? xstrdup(style) : NULL;                  authctxt->style = style ? xstrdup(style) : NULL;
                 if (use_privsep)  
                         mm_inform_authserv(service, style);  
         } else if (strcmp(user, authctxt->user) != 0 ||          } else if (strcmp(user, authctxt->user) != 0 ||
             strcmp(service, authctxt->service) != 0) {              strcmp(service, authctxt->service) != 0) {
                 packet_disconnect("Change of username or service not allowed: "                  packet_disconnect("Change of username or service not allowed: "
Line 169 
Line 212 
                     authctxt->user, authctxt->service, user, service);                      authctxt->user, authctxt->service, user, service);
         }          }
         /* reset state */          /* reset state */
         auth2_challenge_stop(authctxt);          dispatch_set(SSH2_MSG_USERAUTH_INFO_RESPONSE, &protocol_error);
         authctxt->postponed = 0;          authctxt->postponed = 0;
   #ifdef BSD_AUTH
           if (authctxt->as) {
                   auth_close(authctxt->as);
                   authctxt->as = NULL;
           }
   #endif
   
         /* try to authenticate user */          /* try to authenticate user */
         m = authmethod_lookup(method);          m = authmethod_lookup(method);
Line 195 
Line 244 
                     authctxt->user);                      authctxt->user);
   
         /* Special handling for root */          /* Special handling for root */
         if (!use_privsep &&          if (authenticated && authctxt->pw->pw_uid == 0 &&
             authenticated && authctxt->pw->pw_uid == 0 &&  
             !auth_root_allowed(method))              !auth_root_allowed(method))
                 authenticated = 0;                  authenticated = 0;
   
Line 209 
Line 257 
         /* XXX todo: check if multiple auth methods are needed */          /* XXX todo: check if multiple auth methods are needed */
         if (authenticated == 1) {          if (authenticated == 1) {
                 /* turn off userauth */                  /* turn off userauth */
                 dispatch_set(SSH2_MSG_USERAUTH_REQUEST, &dispatch_protocol_ignore);                  dispatch_set(SSH2_MSG_USERAUTH_REQUEST, &protocol_error);
                 packet_start(SSH2_MSG_USERAUTH_SUCCESS);                  packet_start(SSH2_MSG_USERAUTH_SUCCESS);
                 packet_send();                  packet_send();
                 packet_write_wait();                  packet_write_wait();
Line 228 
Line 276 
         }          }
 }  }
   
   static void
   userauth_banner(void)
   {
           struct stat st;
           char *banner = NULL;
           off_t len, n;
           int fd;
   
           if (options.banner == NULL || (datafellows & SSH_BUG_BANNER))
                   return;
           if ((fd = open(options.banner, O_RDONLY)) < 0)
                   return;
           if (fstat(fd, &st) < 0)
                   goto done;
           len = st.st_size;
           banner = xmalloc(len + 1);
           if ((n = read(fd, banner, len)) < 0)
                   goto done;
           banner[n] = '\0';
           packet_start(SSH2_MSG_USERAUTH_BANNER);
           packet_put_cstring(banner);
           packet_put_cstring("");         /* language, unused */
           packet_send();
           debug("userauth_banner: sent");
   done:
           if (banner)
                   xfree(banner);
           close(fd);
           return;
   }
   
   static int
   userauth_none(Authctxt *authctxt)
   {
           /* disable method "none", only allowed one time */
           Authmethod *m = authmethod_lookup("none");
           if (m != NULL)
                   m->enabled = NULL;
           packet_done();
           userauth_banner();
           return authctxt->valid ? auth_password(authctxt, "") : 0;
   }
   
   static int
   userauth_passwd(Authctxt *authctxt)
   {
           char *password;
           int authenticated = 0;
           int change;
           u_int len;
           change = packet_get_char();
           if (change)
                   log("password change not supported");
           password = packet_get_string(&len);
           packet_done();
           if (authctxt->valid &&
               auth_password(authctxt, password) == 1)
                   authenticated = 1;
           memset(password, 0, len);
           xfree(password);
           return authenticated;
   }
   
   static int
   userauth_kbdint(Authctxt *authctxt)
   {
           int authenticated = 0;
           char *lang, *devs;
   
           lang = packet_get_string(NULL);
           devs = packet_get_string(NULL);
           packet_done();
   
           debug("keyboard-interactive devs %s", devs);
   
           if (options.challenge_response_authentication)
                   authenticated = auth2_challenge(authctxt, devs);
   
           xfree(devs);
           xfree(lang);
           return authenticated;
   }
   
   static int
   userauth_pubkey(Authctxt *authctxt)
   {
           Buffer b;
           Key *key;
           char *pkalg, *pkblob, *sig;
           u_int alen, blen, slen;
           int have_sig, pktype;
           int authenticated = 0;
   
           if (!authctxt->valid) {
                   debug2("userauth_pubkey: disabled because of invalid user");
                   return 0;
           }
           have_sig = packet_get_char();
           if (datafellows & SSH_BUG_PKAUTH) {
                   debug2("userauth_pubkey: SSH_BUG_PKAUTH");
                   /* no explicit pkalg given */
                   pkblob = packet_get_string(&blen);
                   buffer_init(&b);
                   buffer_append(&b, pkblob, blen);
                   /* so we have to extract the pkalg from the pkblob */
                   pkalg = buffer_get_string(&b, &alen);
                   buffer_free(&b);
           } else {
                   pkalg = packet_get_string(&alen);
                   pkblob = packet_get_string(&blen);
           }
           pktype = key_type_from_name(pkalg);
           if (pktype == KEY_UNSPEC) {
                   /* this is perfectly legal */
                   log("userauth_pubkey: unsupported public key algorithm: %s", pkalg);
                   xfree(pkalg);
                   xfree(pkblob);
                   return 0;
           }
           key = key_from_blob(pkblob, blen);
           if (key != NULL) {
                   if (have_sig) {
                           sig = packet_get_string(&slen);
                           packet_done();
                           buffer_init(&b);
                           if (datafellows & SSH_OLD_SESSIONID) {
                                   buffer_append(&b, session_id2, session_id2_len);
                           } else {
                                   buffer_put_string(&b, session_id2, session_id2_len);
                           }
                           /* reconstruct packet */
                           buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
                           buffer_put_cstring(&b, authctxt->user);
                           buffer_put_cstring(&b,
                               datafellows & SSH_BUG_PKSERVICE ?
                               "ssh-userauth" :
                               authctxt->service);
                           if (datafellows & SSH_BUG_PKAUTH) {
                                   buffer_put_char(&b, have_sig);
                           } else {
                                   buffer_put_cstring(&b, "publickey");
                                   buffer_put_char(&b, have_sig);
                                   buffer_put_cstring(&b, pkalg);
                           }
                           buffer_put_string(&b, pkblob, blen);
   #ifdef DEBUG_PK
                           buffer_dump(&b);
   #endif
                           /* test for correct signature */
                           if (user_key_allowed(authctxt->pw, key) &&
                               key_verify(key, sig, slen, buffer_ptr(&b), buffer_len(&b)) == 1)
                                   authenticated = 1;
                           buffer_clear(&b);
                           xfree(sig);
                   } else {
                           debug("test whether pkalg/pkblob are acceptable");
                           packet_done();
   
                           /* XXX fake reply and always send PK_OK ? */
                           /*
                            * XXX this allows testing whether a user is allowed
                            * to login: if you happen to have a valid pubkey this
                            * message is sent. the message is NEVER sent at all
                            * if a user is not allowed to login. is this an
                            * issue? -markus
                            */
                           if (user_key_allowed(authctxt->pw, key)) {
                                   packet_start(SSH2_MSG_USERAUTH_PK_OK);
                                   packet_put_string(pkalg, alen);
                                   packet_put_string(pkblob, blen);
                                   packet_send();
                                   packet_write_wait();
                                   authctxt->postponed = 1;
                           }
                   }
                   if (authenticated != 1)
                           auth_clear_options();
                   key_free(key);
           }
           debug2("userauth_pubkey: authenticated %d pkalg %s", authenticated, pkalg);
           xfree(pkalg);
           xfree(pkblob);
           return authenticated;
   }
   
   static int
   userauth_hostbased(Authctxt *authctxt)
   {
           Buffer b;
           Key *key;
           char *pkalg, *pkblob, *sig, *cuser, *chost, *service;
           u_int alen, blen, slen;
           int pktype;
           int authenticated = 0;
   
           if (!authctxt->valid) {
                   debug2("userauth_hostbased: disabled because of invalid user");
                   return 0;
           }
           pkalg = packet_get_string(&alen);
           pkblob = packet_get_string(&blen);
           chost = packet_get_string(NULL);
           cuser = packet_get_string(NULL);
           sig = packet_get_string(&slen);
   
           debug("userauth_hostbased: cuser %s chost %s pkalg %s slen %d",
               cuser, chost, pkalg, slen);
   #ifdef DEBUG_PK
           debug("signature:");
           buffer_init(&b);
           buffer_append(&b, sig, slen);
           buffer_dump(&b);
           buffer_free(&b);
   #endif
           pktype = key_type_from_name(pkalg);
           if (pktype == KEY_UNSPEC) {
                   /* this is perfectly legal */
                   log("userauth_hostbased: unsupported "
                       "public key algorithm: %s", pkalg);
                   goto done;
           }
           key = key_from_blob(pkblob, blen);
           if (key == NULL) {
                   debug("userauth_hostbased: cannot decode key: %s", pkalg);
                   goto done;
           }
           service = datafellows & SSH_BUG_HBSERVICE ? "ssh-userauth" :
               authctxt->service;
           buffer_init(&b);
           buffer_put_string(&b, session_id2, session_id2_len);
           /* reconstruct packet */
           buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
           buffer_put_cstring(&b, authctxt->user);
           buffer_put_cstring(&b, service);
           buffer_put_cstring(&b, "hostbased");
           buffer_put_string(&b, pkalg, alen);
           buffer_put_string(&b, pkblob, blen);
           buffer_put_cstring(&b, chost);
           buffer_put_cstring(&b, cuser);
   #ifdef DEBUG_PK
           buffer_dump(&b);
   #endif
           /* test for allowed key and correct signature */
           if (hostbased_key_allowed(authctxt->pw, cuser, chost, key) &&
               key_verify(key, sig, slen, buffer_ptr(&b), buffer_len(&b)) == 1)
                   authenticated = 1;
   
           buffer_clear(&b);
           key_free(key);
   
   done:
           debug2("userauth_hostbased: authenticated %d", authenticated);
           xfree(pkalg);
           xfree(pkblob);
           xfree(cuser);
           xfree(chost);
           xfree(sig);
           return authenticated;
   }
   
 /* get current user */  /* get current user */
   
 struct passwd*  struct passwd*
Line 241 
Line 549 
 static char *  static char *
 authmethods_get(void)  authmethods_get(void)
 {  {
         Buffer b;          Authmethod *method = NULL;
           u_int size = 0;
         char *list;          char *list;
         int i;  
   
         buffer_init(&b);          for (method = authmethods; method->name != NULL; method++) {
         for (i = 0; authmethods[i] != NULL; i++) {                  if (strcmp(method->name, "none") == 0)
                 if (strcmp(authmethods[i]->name, "none") == 0)  
                         continue;                          continue;
                 if (authmethods[i]->enabled != NULL &&                  if (method->enabled != NULL && *(method->enabled) != 0) {
                     *(authmethods[i]->enabled) != 0) {                          if (size != 0)
                         if (buffer_len(&b) > 0)                                  size += strlen(DELIM);
                                 buffer_append(&b, ",", 1);                          size += strlen(method->name);
                         buffer_append(&b, authmethods[i]->name,  
                             strlen(authmethods[i]->name));  
                 }                  }
         }          }
         buffer_append(&b, "\0", 1);          size++;                 /* trailing '\0' */
         list = xstrdup(buffer_ptr(&b));          list = xmalloc(size);
         buffer_free(&b);          list[0] = '\0';
   
           for (method = authmethods; method->name != NULL; method++) {
                   if (strcmp(method->name, "none") == 0)
                           continue;
                   if (method->enabled != NULL && *(method->enabled) != 0) {
                           if (list[0] != '\0')
                                   strlcat(list, DELIM, size);
                           strlcat(list, method->name, size);
                   }
           }
         return list;          return list;
 }  }
   
 static Authmethod *  static Authmethod *
 authmethod_lookup(const char *name)  authmethod_lookup(const char *name)
 {  {
         int i;          Authmethod *method = NULL;
   
         if (name != NULL)          if (name != NULL)
                 for (i = 0; authmethods[i] != NULL; i++)                  for (method = authmethods; method->name != NULL; method++)
                         if (authmethods[i]->enabled != NULL &&                          if (method->enabled != NULL &&
                             *(authmethods[i]->enabled) != 0 &&                              *(method->enabled) != 0 &&
                             strcmp(name, authmethods[i]->name) == 0)                              strcmp(name, method->name) == 0)
                                 return authmethods[i];                                  return method;
         debug2("Unrecognized authentication method name: %s",          debug2("Unrecognized authentication method name: %s", name ? name : "NULL");
             name ? name : "NULL");  
         return NULL;          return NULL;
 }  }
   
   /* return 1 if user allows given key */
   static int
   user_key_allowed2(struct passwd *pw, Key *key, char *file)
   {
           char line[8192];
           int found_key = 0;
           FILE *f;
           u_long linenum = 0;
           struct stat st;
           Key *found;
   
           if (pw == NULL)
                   return 0;
   
           /* Temporarily use the user's uid. */
           temporarily_use_uid(pw);
   
           debug("trying public key file %s", file);
   
           /* Fail quietly if file does not exist */
           if (stat(file, &st) < 0) {
                   /* Restore the privileged uid. */
                   restore_uid();
                   return 0;
           }
           /* Open the file containing the authorized keys. */
           f = fopen(file, "r");
           if (!f) {
                   /* Restore the privileged uid. */
                   restore_uid();
                   return 0;
           }
           if (options.strict_modes &&
               secure_filename(f, file, pw, line, sizeof(line)) != 0) {
                   fclose(f);
                   log("Authentication refused: %s", line);
                   restore_uid();
                   return 0;
           }
   
           found_key = 0;
           found = key_new(key->type);
   
           while (fgets(line, sizeof(line), f)) {
                   char *cp, *options = NULL;
                   linenum++;
                   /* Skip leading whitespace, empty and comment lines. */
                   for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
                           ;
                   if (!*cp || *cp == '\n' || *cp == '#')
                           continue;
   
                   if (key_read(found, &cp) != 1) {
                           /* no key?  check if there are options for this key */
                           int quoted = 0;
                           debug2("user_key_allowed: check options: '%s'", cp);
                           options = cp;
                           for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) {
                                   if (*cp == '\\' && cp[1] == '"')
                                           cp++;   /* Skip both */
                                   else if (*cp == '"')
                                           quoted = !quoted;
                           }
                           /* Skip remaining whitespace. */
                           for (; *cp == ' ' || *cp == '\t'; cp++)
                                   ;
                           if (key_read(found, &cp) != 1) {
                                   debug2("user_key_allowed: advance: '%s'", cp);
                                   /* still no key?  advance to next line*/
                                   continue;
                           }
                   }
                   if (key_equal(found, key) &&
                       auth_parse_options(pw, options, file, linenum) == 1) {
                           found_key = 1;
                           debug("matching key found: file %s, line %lu",
                               file, linenum);
                           break;
                   }
           }
           restore_uid();
           fclose(f);
           key_free(found);
           if (!found_key)
                   debug2("key not found");
           return found_key;
   }
   
   /* check whether given key is in .ssh/authorized_keys* */
   static int
   user_key_allowed(struct passwd *pw, Key *key)
   {
           int success;
           char *file;
   
           file = authorized_keys_file(pw);
           success = user_key_allowed2(pw, key, file);
           xfree(file);
           if (success)
                   return success;
   
           /* try suffix "2" for backward compat, too */
           file = authorized_keys_file2(pw);
           success = user_key_allowed2(pw, key, file);
           xfree(file);
           return success;
   }
   
   /* return 1 if given hostkey is allowed */
   static int
   hostbased_key_allowed(struct passwd *pw, const char *cuser, char *chost,
       Key *key)
   {
           const char *resolvedname, *ipaddr, *lookup;
           int host_status, len;
   
           resolvedname = get_canonical_hostname(options.reverse_mapping_check);
           ipaddr = get_remote_ipaddr();
   
           debug2("userauth_hostbased: chost %s resolvedname %s ipaddr %s",
               chost, resolvedname, ipaddr);
   
           if (options.hostbased_uses_name_from_packet_only) {
                   if (auth_rhosts2(pw, cuser, chost, chost) == 0)
                           return 0;
                   lookup = chost;
           } else {
                   if (((len = strlen(chost)) > 0) && chost[len - 1] == '.') {
                           debug2("stripping trailing dot from chost %s", chost);
                           chost[len - 1] = '\0';
                   }
                   if (strcasecmp(resolvedname, chost) != 0)
                           log("userauth_hostbased mismatch: "
                               "client sends %s, but we resolve %s to %s",
                               chost, ipaddr, resolvedname);
                   if (auth_rhosts2(pw, cuser, resolvedname, ipaddr) == 0)
                           return 0;
                   lookup = resolvedname;
           }
           debug2("userauth_hostbased: access allowed by auth_rhosts2");
   
           host_status = check_key_in_hostfiles(pw, key, lookup,
               _PATH_SSH_SYSTEM_HOSTFILE,
               options.ignore_user_known_hosts ? NULL : _PATH_SSH_USER_HOSTFILE);
   
           /* backward compat if no key has been found. */
           if (host_status == HOST_NEW)
                   host_status = check_key_in_hostfiles(pw, key, lookup,
                       _PATH_SSH_SYSTEM_HOSTFILE2,
                       options.ignore_user_known_hosts ? NULL :
                       _PATH_SSH_USER_HOSTFILE2);
   
           return (host_status == HOST_OK);
   }
   

Legend:
Removed from v.1.71.2.5  
changed lines
  Added in v.1.72