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

Diff for /src/usr.bin/ssh/Attic/sshconnect1.c between version 1.41 and 1.41.2.3

version 1.41, 2001/10/06 11:18:19 version 1.41.2.3, 2002/06/22 07:23:18
Line 16 
Line 16 
 RCSID("$OpenBSD$");  RCSID("$OpenBSD$");
   
 #include <openssl/bn.h>  #include <openssl/bn.h>
 #include <openssl/evp.h>  #include <openssl/md5.h>
   
 #ifdef KRB4  #ifdef KRB4
 #include <krb.h>  #include <krb.h>
Line 67 
Line 67 
         AuthenticationConnection *auth;          AuthenticationConnection *auth;
         u_char response[16];          u_char response[16];
         u_int i;          u_int i;
         int plen, clen;  
         Key *key;          Key *key;
         BIGNUM *challenge;          BIGNUM *challenge;
   
Line 76 
Line 75 
         if (!auth)          if (!auth)
                 return 0;                  return 0;
   
         challenge = BN_new();          if ((challenge = BN_new()) == NULL)
                   fatal("try_agent_authentication: BN_new failed");
         /* Loop through identities served by the agent. */          /* Loop through identities served by the agent. */
         for (key = ssh_get_first_identity(auth, &comment, 1);          for (key = ssh_get_first_identity(auth, &comment, 1);
              key != NULL;              key != NULL;
              key = ssh_get_next_identity(auth, &comment, 1)) {              key = ssh_get_next_identity(auth, &comment, 1)) {
   
                 /* Try this identity. */                  /* Try this identity. */
                 debug("Trying RSA authentication via agent with '%.100s'", comment);                  debug("Trying RSA authentication via agent with '%.100s'", comment);
Line 94 
Line 93 
                 packet_write_wait();                  packet_write_wait();
   
                 /* Wait for server's response. */                  /* Wait for server's response. */
                 type = packet_read(&plen);                  type = packet_read();
   
                 /* The server sends failure if it doesn\'t like our key or                  /* The server sends failure if it doesn\'t like our key or
                    does not support RSA authentication. */                     does not support RSA authentication. */
Line 108 
Line 107 
                         packet_disconnect("Protocol error during RSA authentication: %d",                          packet_disconnect("Protocol error during RSA authentication: %d",
                                           type);                                            type);
   
                 packet_get_bignum(challenge, &clen);                  packet_get_bignum(challenge);
                   packet_check_eom();
   
                 packet_integrity_check(plen, clen, type);  
   
                 debug("Received RSA challenge from server.");                  debug("Received RSA challenge from server.");
   
                 /* Ask the agent to decrypt the challenge. */                  /* Ask the agent to decrypt the challenge. */
Line 135 
Line 133 
                 packet_write_wait();                  packet_write_wait();
   
                 /* Wait for response from the server. */                  /* Wait for response from the server. */
                 type = packet_read(&plen);                  type = packet_read();
   
                 /* The server returns success if it accepted the authentication. */                  /* The server returns success if it accepted the authentication. */
                 if (type == SSH_SMSG_SUCCESS) {                  if (type == SSH_SMSG_SUCCESS) {
Line 210 
Line 208 
         BIGNUM *challenge;          BIGNUM *challenge;
         Key *public, *private;          Key *public, *private;
         char buf[300], *passphrase, *comment, *authfile;          char buf[300], *passphrase, *comment, *authfile;
         int i, type, quit, plen, clen;          int i, type, quit;
   
         public = options.identity_keys[idx];          public = options.identity_keys[idx];
         authfile = options.identity_files[idx];          authfile = options.identity_files[idx];
Line 225 
Line 223 
         packet_write_wait();          packet_write_wait();
   
         /* Wait for server's response. */          /* Wait for server's response. */
         type = packet_read(&plen);          type = packet_read();
   
         /*          /*
          * The server responds with failure if it doesn\'t like our key or           * The server responds with failure if it doesn\'t like our key or
Line 241 
Line 239 
                 packet_disconnect("Protocol error during RSA authentication: %d", type);                  packet_disconnect("Protocol error during RSA authentication: %d", type);
   
         /* Get the challenge from the packet. */          /* Get the challenge from the packet. */
         challenge = BN_new();          if ((challenge = BN_new()) == NULL)
         packet_get_bignum(challenge, &clen);                  fatal("try_rsa_authentication: BN_new failed");
           packet_get_bignum(challenge);
           packet_check_eom();
   
         packet_integrity_check(plen, clen, type);  
   
         debug("Received RSA challenge from server.");          debug("Received RSA challenge from server.");
   
         /*          /*
Line 292 
Line 290 
                 packet_write_wait();                  packet_write_wait();
   
                 /* Expect the server to reject it... */                  /* Expect the server to reject it... */
                 packet_read_expect(&plen, SSH_SMSG_FAILURE);                  packet_read_expect(SSH_SMSG_FAILURE);
                 BN_clear_free(challenge);                  BN_clear_free(challenge);
                 return 0;                  return 0;
         }          }
Line 308 
Line 306 
         BN_clear_free(challenge);          BN_clear_free(challenge);
   
         /* Wait for response from the server. */          /* Wait for response from the server. */
         type = packet_read(&plen);          type = packet_read();
         if (type == SSH_SMSG_SUCCESS) {          if (type == SSH_SMSG_SUCCESS) {
                 debug("RSA authentication accepted by server.");                  debug("RSA authentication accepted by server.");
                 return 1;                  return 1;
Line 328 
Line 326 
 {  {
         int type;          int type;
         BIGNUM *challenge;          BIGNUM *challenge;
         int plen, clen;  
   
         debug("Trying rhosts or /etc/hosts.equiv with RSA host authentication.");          debug("Trying rhosts or /etc/hosts.equiv with RSA host authentication.");
   
Line 342 
Line 339 
         packet_write_wait();          packet_write_wait();
   
         /* Wait for server's response. */          /* Wait for server's response. */
         type = packet_read(&plen);          type = packet_read();
   
         /* The server responds with failure if it doesn't admit our          /* The server responds with failure if it doesn't admit our
            .rhosts authentication or doesn't know our host key. */             .rhosts authentication or doesn't know our host key. */
Line 355 
Line 352 
                 packet_disconnect("Protocol error during RSA authentication: %d", type);                  packet_disconnect("Protocol error during RSA authentication: %d", type);
   
         /* Get the challenge from the packet. */          /* Get the challenge from the packet. */
         challenge = BN_new();          if ((challenge = BN_new()) == NULL)
         packet_get_bignum(challenge, &clen);                  fatal("try_rhosts_rsa_authentication: BN_new failed");
           packet_get_bignum(challenge);
           packet_check_eom();
   
         packet_integrity_check(plen, clen, type);  
   
         debug("Received RSA challenge for host key from server.");          debug("Received RSA challenge for host key from server.");
   
         /* Compute a response to the challenge. */          /* Compute a response to the challenge. */
Line 369 
Line 366 
         BN_clear_free(challenge);          BN_clear_free(challenge);
   
         /* Wait for response from the server. */          /* Wait for response from the server. */
         type = packet_read(&plen);          type = packet_read();
         if (type == SSH_SMSG_SUCCESS) {          if (type == SSH_SMSG_SUCCESS) {
                 debug("Rhosts or /etc/hosts.equiv with RSA host authentication accepted by server.");                  debug("Rhosts or /etc/hosts.equiv with RSA host authentication accepted by server.");
                 return 1;                  return 1;
Line 389 
Line 386 
         char inst[INST_SZ];          char inst[INST_SZ];
         char *realm;          char *realm;
         CREDENTIALS cred;          CREDENTIALS cred;
         int r, type, plen;          int r, type;
         socklen_t slen;          socklen_t slen;
         Key_schedule schedule;          Key_schedule schedule;
         u_long checksum, cksum;          u_long checksum, cksum;
Line 400 
Line 397 
         /* Don't do anything if we don't have any tickets. */          /* Don't do anything if we don't have any tickets. */
         if (stat(tkt_string(), &st) < 0)          if (stat(tkt_string(), &st) < 0)
                 return 0;                  return 0;
   
         strlcpy(inst, (char *)krb_get_phost(get_canonical_hostname(1)),          strlcpy(inst, (char *)krb_get_phost(get_canonical_hostname(1)),
             INST_SZ);              INST_SZ);
   
         realm = (char *)krb_realmofhost(get_canonical_hostname(1));          realm = (char *)krb_realmofhost(get_canonical_hostname(1));
         if (!realm) {          if (!realm) {
                 debug("Kerberos v4: no realm for %s", get_canonical_hostname(1));                  debug("Kerberos v4: no realm for %s", get_canonical_hostname(1));
Line 411 
Line 408 
         }          }
         /* This can really be anything. */          /* This can really be anything. */
         checksum = (u_long)getpid();          checksum = (u_long)getpid();
   
         r = krb_mk_req(&auth, KRB4_SERVICE_NAME, inst, realm, checksum);          r = krb_mk_req(&auth, KRB4_SERVICE_NAME, inst, realm, checksum);
         if (r != KSUCCESS) {          if (r != KSUCCESS) {
                 debug("Kerberos v4 krb_mk_req failed: %s", krb_err_txt[r]);                  debug("Kerberos v4 krb_mk_req failed: %s", krb_err_txt[r]);
Line 424 
Line 421 
                 return 0;                  return 0;
         }          }
         des_key_sched((des_cblock *) cred.session, schedule);          des_key_sched((des_cblock *) cred.session, schedule);
   
         /* Send authentication info to server. */          /* Send authentication info to server. */
         packet_start(SSH_CMSG_AUTH_KERBEROS);          packet_start(SSH_CMSG_AUTH_KERBEROS);
         packet_put_string((char *) auth.dat, auth.length);          packet_put_string((char *) auth.dat, auth.length);
         packet_send();          packet_send();
         packet_write_wait();          packet_write_wait();
   
         /* Zero the buffer. */          /* Zero the buffer. */
         (void) memset(auth.dat, 0, MAX_KTXT_LEN);          (void) memset(auth.dat, 0, MAX_KTXT_LEN);
   
         slen = sizeof(local);          slen = sizeof(local);
         memset(&local, 0, sizeof(local));          memset(&local, 0, sizeof(local));
         if (getsockname(packet_get_connection_in(),          if (getsockname(packet_get_connection_in(),
             (struct sockaddr *)&local, &slen) < 0)              (struct sockaddr *)&local, &slen) < 0)
                 debug("getsockname failed: %s", strerror(errno));                  debug("getsockname failed: %s", strerror(errno));
   
         slen = sizeof(foreign);          slen = sizeof(foreign);
         memset(&foreign, 0, sizeof(foreign));          memset(&foreign, 0, sizeof(foreign));
         if (getpeername(packet_get_connection_in(),          if (getpeername(packet_get_connection_in(),
Line 448 
Line 445 
                 fatal_cleanup();                  fatal_cleanup();
         }          }
         /* Get server reply. */          /* Get server reply. */
         type = packet_read(&plen);          type = packet_read();
         switch (type) {          switch (type) {
         case SSH_SMSG_FAILURE:          case SSH_SMSG_FAILURE:
                 /* Should really be SSH_SMSG_AUTH_KERBEROS_FAILURE */                  /* Should really be SSH_SMSG_AUTH_KERBEROS_FAILURE */
                 debug("Kerberos v4 authentication failed.");                  debug("Kerberos v4 authentication failed.");
                 return 0;                  return 0;
                 break;                  break;
   
         case SSH_SMSG_AUTH_KERBEROS_RESPONSE:          case SSH_SMSG_AUTH_KERBEROS_RESPONSE:
                 /* SSH_SMSG_AUTH_KERBEROS_SUCCESS */                  /* SSH_SMSG_AUTH_KERBEROS_SUCCESS */
                 debug("Kerberos v4 authentication accepted.");                  debug("Kerberos v4 authentication accepted.");
   
                 /* Get server's response. */                  /* Get server's response. */
                 reply = packet_get_string((u_int *) &auth.length);                  reply = packet_get_string((u_int *) &auth.length);
                   if (auth.length >= MAX_KTXT_LEN)
                           fatal("Kerberos v4: Malformed response from server");
                 memcpy(auth.dat, reply, auth.length);                  memcpy(auth.dat, reply, auth.length);
                 xfree(reply);                  xfree(reply);
   
                 packet_integrity_check(plen, 4 + auth.length, type);                  packet_check_eom();
   
                 /*                  /*
                  * If his response isn't properly encrypted with the session                   * If his response isn't properly encrypted with the session
                  * key, and the decrypted checksum fails to match, he's                   * key, and the decrypted checksum fails to match, he's
Line 483 
Line 482 
                 memcpy((char *)&cksum, (char *)msg_data.app_data,                  memcpy((char *)&cksum, (char *)msg_data.app_data,
                     sizeof(cksum));                      sizeof(cksum));
                 cksum = ntohl(cksum);                  cksum = ntohl(cksum);
   
                 /* If it matches, we're golden. */                  /* If it matches, we're golden. */
                 if (cksum == checksum + 1) {                  if (cksum == checksum + 1) {
                         debug("Kerberos v4 challenge successful.");                          debug("Kerberos v4 challenge successful.");
Line 491 
Line 490 
                 } else                  } else
                         packet_disconnect("Kerberos v4 challenge failed!");                          packet_disconnect("Kerberos v4 challenge failed!");
                 break;                  break;
   
         default:          default:
                 packet_disconnect("Protocol error on Kerberos v4 response: %d", type);                  packet_disconnect("Protocol error on Kerberos v4 response: %d", type);
         }          }
Line 510 
Line 509 
         krb5_ccache ccache = NULL;          krb5_ccache ccache = NULL;
         const char *remotehost;          const char *remotehost;
         krb5_data ap;          krb5_data ap;
         int type, payload_len;          int type;
         krb5_ap_rep_enc_part *reply = NULL;          krb5_ap_rep_enc_part *reply = NULL;
         int ret;          int ret;
   
         memset(&ap, 0, sizeof(ap));          memset(&ap, 0, sizeof(ap));
   
         problem = krb5_init_context(context);          problem = krb5_init_context(context);
         if (problem) {          if (problem) {
                 debug("Kerberos v5: krb5_init_context failed");                  debug("Kerberos v5: krb5_init_context failed");
                 ret = 0;                  ret = 0;
                 goto out;                  goto out;
         }          }
   
         tkfile = krb5_cc_default_name(*context);          tkfile = krb5_cc_default_name(*context);
         if (strncmp(tkfile, "FILE:", 5) == 0)          if (strncmp(tkfile, "FILE:", 5) == 0)
                 tkfile += 5;                  tkfile += 5;
   
         if (stat(tkfile, &buf) == 0 && getuid() != buf.st_uid) {          if (stat(tkfile, &buf) == 0 && getuid() != buf.st_uid) {
                 debug("Kerberos v5: could not get default ccache (permission denied).");                  debug("Kerberos v5: could not get default ccache (permission denied).");
                 ret = 0;                  ret = 0;
                 goto out;                  goto out;
         }          }
   
         problem = krb5_cc_default(*context, &ccache);          problem = krb5_cc_default(*context, &ccache);
         if (problem) {          if (problem) {
                 debug("Kerberos v5: krb5_cc_default failed: %s",                  debug("Kerberos v5: krb5_cc_default failed: %s",
Line 540 
Line 539 
                 ret = 0;                  ret = 0;
                 goto out;                  goto out;
         }          }
   
         remotehost = get_canonical_hostname(1);          remotehost = get_canonical_hostname(1);
   
         problem = krb5_mk_req(*context, auth_context, AP_OPTS_MUTUAL_REQUIRED,          problem = krb5_mk_req(*context, auth_context, AP_OPTS_MUTUAL_REQUIRED,
             "host", remotehost, NULL, ccache, &ap);              "host", remotehost, NULL, ccache, &ap);
         if (problem) {          if (problem) {
Line 551 
Line 550 
                 ret = 0;                  ret = 0;
                 goto out;                  goto out;
         }          }
   
         packet_start(SSH_CMSG_AUTH_KERBEROS);          packet_start(SSH_CMSG_AUTH_KERBEROS);
         packet_put_string((char *) ap.data, ap.length);          packet_put_string((char *) ap.data, ap.length);
         packet_send();          packet_send();
         packet_write_wait();          packet_write_wait();
   
         xfree(ap.data);          xfree(ap.data);
         ap.length = 0;          ap.length = 0;
   
         type = packet_read(&payload_len);          type = packet_read();
         switch (type) {          switch (type) {
         case SSH_SMSG_FAILURE:          case SSH_SMSG_FAILURE:
                 /* Should really be SSH_SMSG_AUTH_KERBEROS_FAILURE */                  /* Should really be SSH_SMSG_AUTH_KERBEROS_FAILURE */
                 debug("Kerberos v5 authentication failed.");                  debug("Kerberos v5 authentication failed.");
                 ret = 0;                  ret = 0;
                 break;                  break;
   
         case SSH_SMSG_AUTH_KERBEROS_RESPONSE:          case SSH_SMSG_AUTH_KERBEROS_RESPONSE:
                 /* SSH_SMSG_AUTH_KERBEROS_SUCCESS */                  /* SSH_SMSG_AUTH_KERBEROS_SUCCESS */
                 debug("Kerberos v5 authentication accepted.");                  debug("Kerberos v5 authentication accepted.");
   
                 /* Get server's response. */                  /* Get server's response. */
                 ap.data = packet_get_string((unsigned int *) &ap.length);                  ap.data = packet_get_string((unsigned int *) &ap.length);
                   packet_check_eom();
                 packet_integrity_check(payload_len, 4 + ap.length, type);                  /* XXX je to dobre? */
                 /* XXX je to dobre? */  
                   problem = krb5_rd_rep(*context, *auth_context, &ap, &reply);
                 problem = krb5_rd_rep(*context, *auth_context, &ap, &reply);                  if (problem) {
                 if (problem) {  
                         ret = 0;                          ret = 0;
                 }                  }
                 ret = 1;                  ret = 1;
                 break;                  break;
   
         default:          default:
                 packet_disconnect("Protocol error on Kerberos v5 response: %d",                  packet_disconnect("Protocol error on Kerberos v5 response: %d",
                     type);                      type);
                 ret = 0;                  ret = 0;
                 break;                  break;
   
         }          }
   
  out:   out:
         if (ccache != NULL)          if (ccache != NULL)
                 krb5_cc_close(*context, ccache);                  krb5_cc_close(*context, ccache);
Line 600 
Line 598 
                 krb5_free_ap_rep_enc_part(*context, reply);                  krb5_free_ap_rep_enc_part(*context, reply);
         if (ap.length > 0)          if (ap.length > 0)
                 krb5_data_free(&ap);                  krb5_data_free(&ap);
   
         return (ret);          return (ret);
 }  }
   
 static void  static void
 send_krb5_tgt(krb5_context context, krb5_auth_context auth_context)  send_krb5_tgt(krb5_context context, krb5_auth_context auth_context)
 {  {
         int fd, type, payload_len;          int fd, type;
         krb5_error_code problem;          krb5_error_code problem;
         krb5_data outbuf;          krb5_data outbuf;
         krb5_ccache ccache = NULL;          krb5_ccache ccache = NULL;
         krb5_creds creds;          krb5_creds creds;
         krb5_kdc_flags flags;          krb5_kdc_flags flags;
         const char *remotehost;          const char *remotehost;
   
         memset(&creds, 0, sizeof(creds));          memset(&creds, 0, sizeof(creds));
         memset(&outbuf, 0, sizeof(outbuf));          memset(&outbuf, 0, sizeof(outbuf));
   
         fd = packet_get_connection_in();          fd = packet_get_connection_in();
   
         problem = krb5_auth_con_setaddrs_from_fd(context, auth_context, &fd);          problem = krb5_auth_con_setaddrs_from_fd(context, auth_context, &fd);
         if (problem)          if (problem)
                 goto out;                  goto out;
   
         problem = krb5_cc_default(context, &ccache);          problem = krb5_cc_default(context, &ccache);
         if (problem)          if (problem)
                 goto out;                  goto out;
   
         problem = krb5_cc_get_principal(context, ccache, &creds.client);          problem = krb5_cc_get_principal(context, ccache, &creds.client);
         if (problem)          if (problem)
                 goto out;                  goto out;
   
         problem = krb5_build_principal(context, &creds.server,          problem = krb5_build_principal(context, &creds.server,
             strlen(creds.client->realm), creds.client->realm,              strlen(creds.client->realm), creds.client->realm,
             "krbtgt", creds.client->realm, NULL);              "krbtgt", creds.client->realm, NULL);
         if (problem)          if (problem)
                 goto out;                  goto out;
   
         creds.times.endtime = 0;          creds.times.endtime = 0;
   
         flags.i = 0;          flags.i = 0;
         flags.b.forwarded = 1;          flags.b.forwarded = 1;
         flags.b.forwardable = krb5_config_get_bool(context,  NULL,          flags.b.forwardable = krb5_config_get_bool(context,  NULL,
             "libdefaults", "forwardable", NULL);              "libdefaults", "forwardable", NULL);
   
         remotehost = get_canonical_hostname(1);          remotehost = get_canonical_hostname(1);
   
         problem = krb5_get_forwarded_creds(context, auth_context,          problem = krb5_get_forwarded_creds(context, auth_context,
             ccache, flags.i, remotehost, &creds, &outbuf);              ccache, flags.i, remotehost, &creds, &outbuf);
         if (problem)          if (problem)
                 goto out;                  goto out;
   
         packet_start(SSH_CMSG_HAVE_KERBEROS_TGT);          packet_start(SSH_CMSG_HAVE_KERBEROS_TGT);
         packet_put_string((char *)outbuf.data, outbuf.length);          packet_put_string((char *)outbuf.data, outbuf.length);
         packet_send();          packet_send();
         packet_write_wait();          packet_write_wait();
   
         type = packet_read(&payload_len);          type = packet_read();
   
         if (type == SSH_SMSG_SUCCESS) {          if (type == SSH_SMSG_SUCCESS) {
                 char *pname;                  char *pname;
   
                 krb5_unparse_name(context, creds.client, &pname);                  krb5_unparse_name(context, creds.client, &pname);
                 debug("Kerberos v5 TGT forwarded (%s).", pname);                  debug("Kerberos v5 TGT forwarded (%s).", pname);
                 xfree(pname);                  xfree(pname);
         } else          } else
                 debug("Kerberos v5 TGT forwarding failed.");                  debug("Kerberos v5 TGT forwarding failed.");
   
         return;          return;
   
  out:   out:
         if (problem)          if (problem)
                 debug("Kerberos v5 TGT forwarding failed: %s",                  debug("Kerberos v5 TGT forwarding failed: %s",
Line 692 
Line 690 
         CREDENTIALS *creds;          CREDENTIALS *creds;
         struct stat st;          struct stat st;
         char buffer[4096], pname[ANAME_SZ], pinst[INST_SZ], prealm[REALM_SZ];          char buffer[4096], pname[ANAME_SZ], pinst[INST_SZ], prealm[REALM_SZ];
         int problem, type, len;          int problem, type;
   
         /* Don't do anything if we don't have any tickets. */          /* Don't do anything if we don't have any tickets. */
         if (stat(tkt_string(), &st) < 0)          if (stat(tkt_string(), &st) < 0)
                 return;                  return;
   
         creds = xmalloc(sizeof(*creds));          creds = xmalloc(sizeof(*creds));
   
         problem = krb_get_tf_fullname(TKT_FILE, pname, pinst, prealm);          problem = krb_get_tf_fullname(TKT_FILE, pname, pinst, prealm);
         if (problem)          if (problem)
                 goto out;                  goto out;
   
         problem = krb_get_cred("krbtgt", prealm, prealm, creds);          problem = krb_get_cred("krbtgt", prealm, prealm, creds);
         if (problem)          if (problem)
                 goto out;                  goto out;
   
         if (time(0) > krb_life_to_time(creds->issue_date, creds->lifetime)) {          if (time(0) > krb_life_to_time(creds->issue_date, creds->lifetime)) {
                 problem = RD_AP_EXP;                  problem = RD_AP_EXP;
                 goto out;                  goto out;
         }          }
         creds_to_radix(creds, (u_char *)buffer, sizeof(buffer));          creds_to_radix(creds, (u_char *)buffer, sizeof(buffer));
   
         packet_start(SSH_CMSG_HAVE_KERBEROS_TGT);          packet_start(SSH_CMSG_HAVE_KERBEROS_TGT);
         packet_put_cstring(buffer);          packet_put_cstring(buffer);
         packet_send();          packet_send();
         packet_write_wait();          packet_write_wait();
   
         type = packet_read(&len);          type = packet_read();
   
         if (type == SSH_SMSG_SUCCESS)          if (type == SSH_SMSG_SUCCESS)
                 debug("Kerberos v4 TGT forwarded (%s%s%s@%s).",                  debug("Kerberos v4 TGT forwarded (%s%s%s@%s).",
                     creds->pname, creds->pinst[0] ? "." : "",                      creds->pname, creds->pinst[0] ? "." : "",
                     creds->pinst, creds->realm);                      creds->pinst, creds->realm);
         else          else
                 debug("Kerberos v4 TGT rejected.");                  debug("Kerberos v4 TGT rejected.");
   
         xfree(creds);          xfree(creds);
         return;          return;
   
  out:   out:
         debug("Kerberos v4 TGT passing failed: %s", krb_err_txt[problem]);          debug("Kerberos v4 TGT passing failed: %s", krb_err_txt[problem]);
         xfree(creds);          xfree(creds);
Line 745 
Line 743 
         int i, type, len;          int i, type, len;
         char buf[2048], *p, *server_cell;          char buf[2048], *p, *server_cell;
         char buffer[8192];          char buffer[8192];
   
         /* Move over ktc_GetToken, here's something leaner. */          /* Move over ktc_GetToken, here's something leaner. */
         for (i = 0; i < 100; i++) {     /* just in case */          for (i = 0; i < 100; i++) {     /* just in case */
                 parms.in = (char *) &i;                  parms.in = (char *) &i;
Line 755 
Line 753 
                 if (k_pioctl(0, VIOCGETTOK, &parms, 0) != 0)                  if (k_pioctl(0, VIOCGETTOK, &parms, 0) != 0)
                         break;                          break;
                 p = buf;                  p = buf;
   
                 /* Get secret token. */                  /* Get secret token. */
                 memcpy(&creds.ticket_st.length, p, sizeof(u_int));                  memcpy(&creds.ticket_st.length, p, sizeof(u_int));
                 if (creds.ticket_st.length > MAX_KTXT_LEN)                  if (creds.ticket_st.length > MAX_KTXT_LEN)
Line 763 
Line 761 
                 p += sizeof(u_int);                  p += sizeof(u_int);
                 memcpy(creds.ticket_st.dat, p, creds.ticket_st.length);                  memcpy(creds.ticket_st.dat, p, creds.ticket_st.length);
                 p += creds.ticket_st.length;                  p += creds.ticket_st.length;
   
                 /* Get clear token. */                  /* Get clear token. */
                 memcpy(&len, p, sizeof(len));                  memcpy(&len, p, sizeof(len));
                 if (len != sizeof(struct ClearToken))                  if (len != sizeof(struct ClearToken))
Line 773 
Line 771 
                 p += len;                  p += len;
                 p += sizeof(len);       /* primary flag */                  p += sizeof(len);       /* primary flag */
                 server_cell = p;                  server_cell = p;
   
                 /* Flesh out our credentials. */                  /* Flesh out our credentials. */
                 strlcpy(creds.service, "afs", sizeof(creds.service));                  strlcpy(creds.service, "afs", sizeof(creds.service));
                 creds.instance[0] = '\0';                  creds.instance[0] = '\0';
Line 785 
Line 783 
                 creds.kvno = ct.AuthHandle;                  creds.kvno = ct.AuthHandle;
                 snprintf(creds.pname, sizeof(creds.pname), "AFS ID %d", ct.ViceId);                  snprintf(creds.pname, sizeof(creds.pname), "AFS ID %d", ct.ViceId);
                 creds.pinst[0] = '\0';                  creds.pinst[0] = '\0';
   
                 /* Encode token, ship it off. */                  /* Encode token, ship it off. */
                 if (creds_to_radix(&creds, (u_char *)buffer,                  if (creds_to_radix(&creds, (u_char *)buffer,
                     sizeof(buffer)) <= 0)                      sizeof(buffer)) <= 0)
Line 797 
Line 795 
   
                 /* Roger, Roger. Clearance, Clarence. What's your vector,                  /* Roger, Roger. Clearance, Clarence. What's your vector,
                    Victor? */                     Victor? */
                 type = packet_read(&len);                  type = packet_read();
   
                 if (type == SSH_SMSG_FAILURE)                  if (type == SSH_SMSG_FAILURE)
                         debug("AFS token for cell %s rejected.", server_cell);                          debug("AFS token for cell %s rejected.", server_cell);
                 else if (type != SSH_SMSG_SUCCESS)                  else if (type != SSH_SMSG_SUCCESS)
Line 816 
Line 814 
 try_challenge_response_authentication(void)  try_challenge_response_authentication(void)
 {  {
         int type, i;          int type, i;
         int payload_len;  
         u_int clen;          u_int clen;
         char prompt[1024];          char prompt[1024];
         char *challenge, *response;          char *challenge, *response;
Line 829 
Line 826 
                 packet_send();                  packet_send();
                 packet_write_wait();                  packet_write_wait();
   
                 type = packet_read(&payload_len);                  type = packet_read();
                 if (type != SSH_SMSG_FAILURE &&                  if (type != SSH_SMSG_FAILURE &&
                     type != SSH_SMSG_AUTH_TIS_CHALLENGE) {                      type != SSH_SMSG_AUTH_TIS_CHALLENGE) {
                         packet_disconnect("Protocol error: got %d in response "                          packet_disconnect("Protocol error: got %d in response "
Line 840 
Line 837 
                         return 0;                          return 0;
                 }                  }
                 challenge = packet_get_string(&clen);                  challenge = packet_get_string(&clen);
                 packet_integrity_check(payload_len, (4 + clen), type);                  packet_check_eom();
                 snprintf(prompt, sizeof prompt, "%s%s", challenge,                  snprintf(prompt, sizeof prompt, "%s%s", challenge,
                      strchr(challenge, '\n') ? "" : "\nResponse: ");                      strchr(challenge, '\n') ? "" : "\nResponse: ");
                 xfree(challenge);                  xfree(challenge);
                 if (i != 0)                  if (i != 0)
                         error("Permission denied, please try again.");                          error("Permission denied, please try again.");
                 if (options.cipher == SSH_CIPHER_NONE)                  if (options.cipher == SSH_CIPHER_NONE)
                         log("WARNING: Encryption is disabled! "                          log("WARNING: Encryption is disabled! "
                             "Reponse will be transmitted in clear text.");                              "Response will be transmitted in clear text.");
                 response = read_passphrase(prompt, 0);                  response = read_passphrase(prompt, 0);
                 if (strcmp(response, "") == 0) {                  if (strcmp(response, "") == 0) {
                         xfree(response);                          xfree(response);
Line 860 
Line 857 
                 xfree(response);                  xfree(response);
                 packet_send();                  packet_send();
                 packet_write_wait();                  packet_write_wait();
                 type = packet_read(&payload_len);                  type = packet_read();
                 if (type == SSH_SMSG_SUCCESS)                  if (type == SSH_SMSG_SUCCESS)
                         return 1;                          return 1;
                 if (type != SSH_SMSG_FAILURE)                  if (type != SSH_SMSG_FAILURE)
Line 877 
Line 874 
 static int  static int
 try_password_authentication(char *prompt)  try_password_authentication(char *prompt)
 {  {
         int type, i, payload_len;          int type, i;
         char *password;          char *password;
   
         debug("Doing password authentication.");          debug("Doing password authentication.");
Line 894 
Line 891 
                 packet_send();                  packet_send();
                 packet_write_wait();                  packet_write_wait();
   
                 type = packet_read(&payload_len);                  type = packet_read();
                 if (type == SSH_SMSG_SUCCESS)                  if (type == SSH_SMSG_SUCCESS)
                         return 1;                          return 1;
                 if (type != SSH_SMSG_FAILURE)                  if (type != SSH_SMSG_FAILURE)
Line 912 
Line 909 
 {  {
         int i;          int i;
         BIGNUM *key;          BIGNUM *key;
         RSA *host_key;          Key *host_key, *server_key;
         RSA *public_key;  
         Key k;  
         int bits, rbits;          int bits, rbits;
         int ssh_cipher_default = SSH_CIPHER_3DES;          int ssh_cipher_default = SSH_CIPHER_3DES;
         u_char session_key[SSH_SESSION_KEY_LENGTH];          u_char session_key[SSH_SESSION_KEY_LENGTH];
         u_char cookie[8];          u_char cookie[8];
         u_int supported_ciphers;          u_int supported_ciphers;
         u_int server_flags, client_flags;          u_int server_flags, client_flags;
         int payload_len, clen, sum_len = 0;  
         u_int32_t rand = 0;          u_int32_t rand = 0;
   
         debug("Waiting for server public key.");          debug("Waiting for server public key.");
   
         /* Wait for a public key packet from the server. */          /* Wait for a public key packet from the server. */
         packet_read_expect(&payload_len, SSH_SMSG_PUBLIC_KEY);          packet_read_expect(SSH_SMSG_PUBLIC_KEY);
   
         /* Get cookie from the packet. */          /* Get cookie from the packet. */
         for (i = 0; i < 8; i++)          for (i = 0; i < 8; i++)
                 cookie[i] = packet_get_char();                  cookie[i] = packet_get_char();
   
         /* Get the public key. */          /* Get the public key. */
         public_key = RSA_new();          server_key = key_new(KEY_RSA1);
         bits = packet_get_int();/* bits */          bits = packet_get_int();
         public_key->e = BN_new();          packet_get_bignum(server_key->rsa->e);
         packet_get_bignum(public_key->e, &clen);          packet_get_bignum(server_key->rsa->n);
         sum_len += clen;  
         public_key->n = BN_new();  
         packet_get_bignum(public_key->n, &clen);  
         sum_len += clen;  
   
         rbits = BN_num_bits(public_key->n);          rbits = BN_num_bits(server_key->rsa->n);
         if (bits != rbits) {          if (bits != rbits) {
                 log("Warning: Server lies about size of server public key: "                  log("Warning: Server lies about size of server public key: "
                     "actual size is %d bits vs. announced %d.", rbits, bits);                      "actual size is %d bits vs. announced %d.", rbits, bits);
                 log("Warning: This may be due to an old implementation of ssh.");                  log("Warning: This may be due to an old implementation of ssh.");
         }          }
         /* Get the host key. */          /* Get the host key. */
         host_key = RSA_new();          host_key = key_new(KEY_RSA1);
         bits = packet_get_int();/* bits */          bits = packet_get_int();
         host_key->e = BN_new();          packet_get_bignum(host_key->rsa->e);
         packet_get_bignum(host_key->e, &clen);          packet_get_bignum(host_key->rsa->n);
         sum_len += clen;  
         host_key->n = BN_new();  
         packet_get_bignum(host_key->n, &clen);  
         sum_len += clen;  
   
         rbits = BN_num_bits(host_key->n);          rbits = BN_num_bits(host_key->rsa->n);
         if (bits != rbits) {          if (bits != rbits) {
                 log("Warning: Server lies about size of server host key: "                  log("Warning: Server lies about size of server host key: "
                     "actual size is %d bits vs. announced %d.", rbits, bits);                      "actual size is %d bits vs. announced %d.", rbits, bits);
Line 972 
Line 958 
   
         supported_ciphers = packet_get_int();          supported_ciphers = packet_get_int();
         supported_authentications = packet_get_int();          supported_authentications = packet_get_int();
           packet_check_eom();
   
         debug("Received server public key (%d bits) and host key (%d bits).",          debug("Received server public key (%d bits) and host key (%d bits).",
               BN_num_bits(public_key->n), BN_num_bits(host_key->n));              BN_num_bits(server_key->rsa->n), BN_num_bits(host_key->rsa->n));
   
         packet_integrity_check(payload_len,          if (verify_host_key(host, hostaddr, host_key) == -1)
                                8 + 4 + sum_len + 0 + 4 + 0 + 0 + 4 + 4 + 4,  
                                SSH_SMSG_PUBLIC_KEY);  
         k.type = KEY_RSA1;  
         k.rsa = host_key;  
         if (verify_host_key(host, hostaddr, &k) == -1)  
                 fatal("Host key verification failed.");                  fatal("Host key verification failed.");
   
         client_flags = SSH_PROTOFLAG_SCREEN_NUMBER | SSH_PROTOFLAG_HOST_IN_FWD_OPEN;          client_flags = SSH_PROTOFLAG_SCREEN_NUMBER | SSH_PROTOFLAG_HOST_IN_FWD_OPEN;
   
         compute_session_id(session_id, cookie, host_key->n, public_key->n);          compute_session_id(session_id, cookie, host_key->rsa->n, server_key->rsa->n);
   
         /* Generate a session key. */          /* Generate a session key. */
         arc4random_stir();          arc4random_stir();
Line 1008 
Line 990 
          * is the highest byte of the integer.  The session key is xored with           * is the highest byte of the integer.  The session key is xored with
          * the first 16 bytes of the session id.           * the first 16 bytes of the session id.
          */           */
         key = BN_new();          if ((key = BN_new()) == NULL)
                   fatal("respond_to_rsa_challenge: BN_new failed");
         BN_set_word(key, 0);          BN_set_word(key, 0);
         for (i = 0; i < SSH_SESSION_KEY_LENGTH; i++) {          for (i = 0; i < SSH_SESSION_KEY_LENGTH; i++) {
                 BN_lshift(key, key, 8);                  BN_lshift(key, key, 8);
Line 1022 
Line 1005 
          * Encrypt the integer using the public key and host key of the           * Encrypt the integer using the public key and host key of the
          * server (key with smaller modulus first).           * server (key with smaller modulus first).
          */           */
         if (BN_cmp(public_key->n, host_key->n) < 0) {          if (BN_cmp(server_key->rsa->n, host_key->rsa->n) < 0) {
                 /* Public key has smaller modulus. */                  /* Public key has smaller modulus. */
                 if (BN_num_bits(host_key->n) <                  if (BN_num_bits(host_key->rsa->n) <
                     BN_num_bits(public_key->n) + SSH_KEY_BITS_RESERVED) {                      BN_num_bits(server_key->rsa->n) + SSH_KEY_BITS_RESERVED) {
                         fatal("respond_to_rsa_challenge: host_key %d < public_key %d + "                          fatal("respond_to_rsa_challenge: host_key %d < server_key %d + "
                               "SSH_KEY_BITS_RESERVED %d",                              "SSH_KEY_BITS_RESERVED %d",
                               BN_num_bits(host_key->n),                              BN_num_bits(host_key->rsa->n),
                               BN_num_bits(public_key->n),                              BN_num_bits(server_key->rsa->n),
                               SSH_KEY_BITS_RESERVED);                              SSH_KEY_BITS_RESERVED);
                 }                  }
                 rsa_public_encrypt(key, key, public_key);                  rsa_public_encrypt(key, key, server_key->rsa);
                 rsa_public_encrypt(key, key, host_key);                  rsa_public_encrypt(key, key, host_key->rsa);
         } else {          } else {
                 /* Host key has smaller modulus (or they are equal). */                  /* Host key has smaller modulus (or they are equal). */
                 if (BN_num_bits(public_key->n) <                  if (BN_num_bits(server_key->rsa->n) <
                     BN_num_bits(host_key->n) + SSH_KEY_BITS_RESERVED) {                      BN_num_bits(host_key->rsa->n) + SSH_KEY_BITS_RESERVED) {
                         fatal("respond_to_rsa_challenge: public_key %d < host_key %d + "                          fatal("respond_to_rsa_challenge: server_key %d < host_key %d + "
                               "SSH_KEY_BITS_RESERVED %d",                              "SSH_KEY_BITS_RESERVED %d",
                               BN_num_bits(public_key->n),                              BN_num_bits(server_key->rsa->n),
                               BN_num_bits(host_key->n),                              BN_num_bits(host_key->rsa->n),
                               SSH_KEY_BITS_RESERVED);                              SSH_KEY_BITS_RESERVED);
                 }                  }
                 rsa_public_encrypt(key, key, host_key);                  rsa_public_encrypt(key, key, host_key->rsa);
                 rsa_public_encrypt(key, key, public_key);                  rsa_public_encrypt(key, key, server_key->rsa);
         }          }
   
         /* Destroy the public keys since we no longer need them. */          /* Destroy the public keys since we no longer need them. */
         RSA_free(public_key);          key_free(server_key);
         RSA_free(host_key);          key_free(host_key);
   
         if (options.cipher == SSH_CIPHER_NOT_SET) {          if (options.cipher == SSH_CIPHER_NOT_SET) {
                 if (cipher_mask_ssh1(1) & supported_ciphers & (1 << ssh_cipher_default))                  if (cipher_mask_ssh1(1) & supported_ciphers & (1 << ssh_cipher_default))
Line 1064 
Line 1047 
         /* Check that the selected cipher is supported. */          /* Check that the selected cipher is supported. */
         if (!(supported_ciphers & (1 << options.cipher)))          if (!(supported_ciphers & (1 << options.cipher)))
                 fatal("Selected cipher type %.100s not supported by server.",                  fatal("Selected cipher type %.100s not supported by server.",
                       cipher_name(options.cipher));                      cipher_name(options.cipher));
   
         debug("Encryption type: %.100s", cipher_name(options.cipher));          debug("Encryption type: %.100s", cipher_name(options.cipher));
   
Line 1099 
Line 1082 
          * Expect a success message from the server.  Note that this message           * Expect a success message from the server.  Note that this message
          * will be received in encrypted form.           * will be received in encrypted form.
          */           */
         packet_read_expect(&payload_len, SSH_SMSG_SUCCESS);          packet_read_expect(SSH_SMSG_SUCCESS);
   
         debug("Received encrypted confirmation.");          debug("Received encrypted confirmation.");
 }  }
Line 1109 
Line 1092 
  */   */
 void  void
 ssh_userauth1(const char *local_user, const char *server_user, char *host,  ssh_userauth1(const char *local_user, const char *server_user, char *host,
     Key **keys, int nkeys)      Sensitive *sensitive)
 {  {
 #ifdef KRB5  #ifdef KRB5
         krb5_context context = NULL;          krb5_context context = NULL;
         krb5_auth_context auth_context = NULL;          krb5_auth_context auth_context = NULL;
 #endif  #endif
         int i, type;          int i, type;
         int payload_len;  
   
         if (supported_authentications == 0)          if (supported_authentications == 0)
                 fatal("ssh_userauth1: server supports no auth methods");                  fatal("ssh_userauth1: server supports no auth methods");
   
Line 1132 
Line 1114 
          * needed (the user has no password).  Otherwise the server responds           * needed (the user has no password).  Otherwise the server responds
          * with failure.           * with failure.
          */           */
         type = packet_read(&payload_len);          type = packet_read();
   
         /* check whether the connection was accepted without authentication. */          /* check whether the connection was accepted without authentication. */
         if (type == SSH_SMSG_SUCCESS)          if (type == SSH_SMSG_SUCCESS)
                 goto success;                  goto success;
         if (type != SSH_SMSG_FAILURE)          if (type != SSH_SMSG_FAILURE)
                 packet_disconnect("Protocol error: got %d in response to SSH_CMSG_USER", type);                  packet_disconnect("Protocol error: got %d in response to SSH_CMSG_USER", type);
   
 #ifdef KRB5  #ifdef KRB5
         if ((supported_authentications & (1 << SSH_AUTH_KERBEROS)) &&          if ((supported_authentications & (1 << SSH_AUTH_KERBEROS)) &&
             options.kerberos_authentication) {              options.kerberos_authentication) {
                 debug("Trying Kerberos v5 authentication.");                  debug("Trying Kerberos v5 authentication.");
   
                 if (try_krb5_authentication(&context, &auth_context)) {                  if (try_krb5_authentication(&context, &auth_context)) {
                         type = packet_read(&payload_len);                          type = packet_read();
                         if (type == SSH_SMSG_SUCCESS)                          if (type == SSH_SMSG_SUCCESS)
                                 goto success;                                  goto success;
                         if (type != SSH_SMSG_FAILURE)                          if (type != SSH_SMSG_FAILURE)
Line 1154 
Line 1136 
                 }                  }
         }          }
 #endif /* KRB5 */  #endif /* KRB5 */
   
 #ifdef KRB4  #ifdef KRB4
         if ((supported_authentications & (1 << SSH_AUTH_KERBEROS)) &&          if ((supported_authentications & (1 << SSH_AUTH_KERBEROS)) &&
             options.kerberos_authentication) {              options.kerberos_authentication) {
                 debug("Trying Kerberos v4 authentication.");                  debug("Trying Kerberos v4 authentication.");
   
                 if (try_krb4_authentication()) {                  if (try_krb4_authentication()) {
                         type = packet_read(&payload_len);                          type = packet_read();
                         if (type == SSH_SMSG_SUCCESS)                          if (type == SSH_SMSG_SUCCESS)
                                 goto success;                                  goto success;
                         if (type != SSH_SMSG_FAILURE)                          if (type != SSH_SMSG_FAILURE)
Line 1169 
Line 1151 
                 }                  }
         }          }
 #endif /* KRB4 */  #endif /* KRB4 */
   
         /*          /*
          * Use rhosts authentication if running in privileged socket and we           * Use rhosts authentication if running in privileged socket and we
          * do not wish to remain anonymous.           * do not wish to remain anonymous.
Line 1183 
Line 1165 
                 packet_write_wait();                  packet_write_wait();
   
                 /* The server should respond with success or failure. */                  /* The server should respond with success or failure. */
                 type = packet_read(&payload_len);                  type = packet_read();
                 if (type == SSH_SMSG_SUCCESS)                  if (type == SSH_SMSG_SUCCESS)
                         goto success;                          goto success;
                 if (type != SSH_SMSG_FAILURE)                  if (type != SSH_SMSG_FAILURE)
Line 1196 
Line 1178 
          */           */
         if ((supported_authentications & (1 << SSH_AUTH_RHOSTS_RSA)) &&          if ((supported_authentications & (1 << SSH_AUTH_RHOSTS_RSA)) &&
             options.rhosts_rsa_authentication) {              options.rhosts_rsa_authentication) {
                 for (i = 0; i < nkeys; i++) {                  for (i = 0; i < sensitive->nkeys; i++) {
                         if (keys[i] != NULL && keys[i]->type == KEY_RSA1 &&                          if (sensitive->keys[i] != NULL &&
                             try_rhosts_rsa_authentication(local_user, keys[i]))                              sensitive->keys[i]->type == KEY_RSA1 &&
                               try_rhosts_rsa_authentication(local_user,
                               sensitive->keys[i]))
                                 goto success;                                  goto success;
                 }                  }
         }          }
Line 1254 
Line 1238 
         if (context)          if (context)
                 krb5_free_context(context);                  krb5_free_context(context);
 #endif  #endif
   
 #ifdef AFS  #ifdef AFS
         /* Try Kerberos v4 TGT passing if the server supports it. */          /* Try Kerberos v4 TGT passing if the server supports it. */
         if ((supported_authentications & (1 << SSH_PASS_KERBEROS_TGT)) &&          if ((supported_authentications & (1 << SSH_PASS_KERBEROS_TGT)) &&

Legend:
Removed from v.1.41  
changed lines
  Added in v.1.41.2.3