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

Diff for /src/usr.bin/ssh/sshconnect2.c between version 1.169 and 1.170

version 1.169, 2008/11/01 04:50:08 version 1.170, 2008/11/04 08:22:13
Line 1 
Line 1 
 /* $OpenBSD$ */  /* $OpenBSD$ */
 /*  /*
  * Copyright (c) 2000 Markus Friedl.  All rights reserved.   * Copyright (c) 2000 Markus Friedl.  All rights reserved.
    * Copyright (c) 2008 Damien Miller.  All rights reserved.
  *   *
  * Redistribution and use in source and binary forms, with or without   * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions   * modification, are permitted provided that the following conditions
Line 61 
Line 62 
 #include "msg.h"  #include "msg.h"
 #include "pathnames.h"  #include "pathnames.h"
 #include "uidswap.h"  #include "uidswap.h"
   #include "jpake.h"
   
 #ifdef GSSAPI  #ifdef GSSAPI
 #include "ssh-gss.h"  #include "ssh-gss.h"
Line 195 
Line 197 
 struct Authmethod {  struct Authmethod {
         char    *name;          /* string to compare against server's list */          char    *name;          /* string to compare against server's list */
         int     (*userauth)(Authctxt *authctxt);          int     (*userauth)(Authctxt *authctxt);
           void    (*cleanup)(Authctxt *authctxt);
         int     *enabled;       /* flag in option struct that enables method */          int     *enabled;       /* flag in option struct that enables method */
         int     *batch_flag;    /* flag in option struct that disables method */          int     *batch_flag;    /* flag in option struct that disables method */
 };  };
Line 206 
Line 209 
 void    input_userauth_info_req(int, u_int32_t, void *);  void    input_userauth_info_req(int, u_int32_t, void *);
 void    input_userauth_pk_ok(int, u_int32_t, void *);  void    input_userauth_pk_ok(int, u_int32_t, void *);
 void    input_userauth_passwd_changereq(int, u_int32_t, void *);  void    input_userauth_passwd_changereq(int, u_int32_t, void *);
   void    input_userauth_jpake_server_step1(int, u_int32_t, void *);
   void    input_userauth_jpake_server_step2(int, u_int32_t, void *);
   void    input_userauth_jpake_server_confirm(int, u_int32_t, void *);
   
 int     userauth_none(Authctxt *);  int     userauth_none(Authctxt *);
 int     userauth_pubkey(Authctxt *);  int     userauth_pubkey(Authctxt *);
 int     userauth_passwd(Authctxt *);  int     userauth_passwd(Authctxt *);
 int     userauth_kbdint(Authctxt *);  int     userauth_kbdint(Authctxt *);
 int     userauth_hostbased(Authctxt *);  int     userauth_hostbased(Authctxt *);
   int     userauth_jpake(Authctxt *);
   
   void    userauth_jpake_cleanup(Authctxt *);
   
 #ifdef GSSAPI  #ifdef GSSAPI
 int     userauth_gssapi(Authctxt *authctxt);  int     userauth_gssapi(Authctxt *authctxt);
 void    input_gssapi_response(int type, u_int32_t, void *);  void    input_gssapi_response(int type, u_int32_t, void *);
Line 237 
Line 246 
 #ifdef GSSAPI  #ifdef GSSAPI
         {"gssapi-with-mic",          {"gssapi-with-mic",
                 userauth_gssapi,                  userauth_gssapi,
                   NULL,
                 &options.gss_authentication,                  &options.gss_authentication,
                 NULL},                  NULL},
 #endif  #endif
         {"hostbased",          {"hostbased",
                 userauth_hostbased,                  userauth_hostbased,
                   NULL,
                 &options.hostbased_authentication,                  &options.hostbased_authentication,
                 NULL},                  NULL},
         {"publickey",          {"publickey",
                 userauth_pubkey,                  userauth_pubkey,
                   NULL,
                 &options.pubkey_authentication,                  &options.pubkey_authentication,
                 NULL},                  NULL},
   #ifdef JPAKE
           {"jpake-01@openssh.com",
                   userauth_jpake,
                   userauth_jpake_cleanup,
                   &options.zero_knowledge_password_authentication,
                   &options.batch_mode},
   #endif
         {"keyboard-interactive",          {"keyboard-interactive",
                 userauth_kbdint,                  userauth_kbdint,
                   NULL,
                 &options.kbd_interactive_authentication,                  &options.kbd_interactive_authentication,
                 &options.batch_mode},                  &options.batch_mode},
         {"password",          {"password",
                 userauth_passwd,                  userauth_passwd,
                   NULL,
                 &options.password_authentication,                  &options.password_authentication,
                 &options.batch_mode},                  &options.batch_mode},
         {"none",          {"none",
                 userauth_none,                  userauth_none,
                 NULL,                  NULL,
                   NULL,
                 NULL},                  NULL},
         {NULL, NULL, NULL, NULL}          {NULL, NULL, NULL, NULL, NULL}
 };  };
   
 void  void
Line 328 
Line 350 
 void  void
 userauth(Authctxt *authctxt, char *authlist)  userauth(Authctxt *authctxt, char *authlist)
 {  {
           if (authctxt->method != NULL && authctxt->method->cleanup != NULL)
                   authctxt->method->cleanup(authctxt);
   
         if (authctxt->methoddata) {          if (authctxt->methoddata) {
                 xfree(authctxt->methoddata);                  xfree(authctxt->methoddata);
                 authctxt->methoddata = NULL;                  authctxt->methoddata = NULL;
Line 845 
Line 870 
             &input_userauth_passwd_changereq);              &input_userauth_passwd_changereq);
 }  }
   
   #ifdef JPAKE
   static char *
   pw_encrypt(const char *password, const char *crypt_scheme, const char *salt)
   {
           /* OpenBSD crypt(3) handles all of these */
           if (strcmp(crypt_scheme, "crypt") == 0 ||
               strcmp(crypt_scheme, "bcrypt") == 0 ||
               strcmp(crypt_scheme, "md5crypt") == 0 ||
               strcmp(crypt_scheme, "crypt-extended") == 0)
                   return xstrdup(crypt(password, salt));
           error("%s: unsupported password encryption scheme \"%.100s\"",
               __func__, crypt_scheme);
           return NULL;
   }
   
   static BIGNUM *
   jpake_password_to_secret(Authctxt *authctxt, const char *crypt_scheme,
       const char *salt)
   {
           char prompt[256], *password, *crypted;
           u_char *secret;
           u_int secret_len;
           BIGNUM *ret;
   
           snprintf(prompt, sizeof(prompt), "%.30s@%.128s's password (JPAKE): ",
               authctxt->server_user, authctxt->host);
           password = read_passphrase(prompt, 0);
   
           if ((crypted = pw_encrypt(password, crypt_scheme, salt)) == NULL) {
                   logit("Disabling %s authentication", authctxt->method->name);
                   authctxt->method->enabled = NULL;
                   /* Continue with an empty password to fail gracefully */
                   crypted = xstrdup("");
           }
   
   #ifdef JPAKE_DEBUG
           debug3("%s: salt = %s", __func__, salt);
           debug3("%s: scheme = %s", __func__, crypt_scheme);
           debug3("%s: crypted = %s", __func__, crypted);
   #endif
   
           if (hash_buffer(crypted, strlen(crypted), EVP_sha256(),
               &secret, &secret_len) != 0)
                   fatal("%s: hash_buffer", __func__);
   
           bzero(password, strlen(password));
           bzero(crypted, strlen(crypted));
           xfree(password);
           xfree(crypted);
   
           if ((ret = BN_bin2bn(secret, secret_len, NULL)) == NULL)
                   fatal("%s: BN_bin2bn (secret)", __func__);
           bzero(secret, secret_len);
           xfree(secret);
   
           return ret;
   }
   
   /* ARGSUSED */
   void
   input_userauth_jpake_server_step1(int type, u_int32_t seq, void *ctxt)
   {
           Authctxt *authctxt = ctxt;
           struct jpake_ctx *pctx = authctxt->methoddata;
           u_char *x3_proof, *x4_proof, *x2_s_proof;
           u_int x3_proof_len, x4_proof_len, x2_s_proof_len;
           char *crypt_scheme, *salt;
   
           /* Disable this message */
           dispatch_set(SSH2_MSG_USERAUTH_JPAKE_SERVER_STEP1, NULL);
   
           if ((pctx->g_x3 = BN_new()) == NULL ||
               (pctx->g_x4 = BN_new()) == NULL)
                   fatal("%s: BN_new", __func__);
   
           /* Fetch step 1 values */
           crypt_scheme = packet_get_string(NULL);
           salt = packet_get_string(NULL);
           pctx->server_id = packet_get_string(&pctx->server_id_len);
           packet_get_bignum2(pctx->g_x3);
           packet_get_bignum2(pctx->g_x4);
           x3_proof = packet_get_string(&x3_proof_len);
           x4_proof = packet_get_string(&x4_proof_len);
           packet_check_eom();
   
           JPAKE_DEBUG_CTX((pctx, "step 1 received in %s", __func__));
   
           /* Obtain password and derive secret */
           pctx->s = jpake_password_to_secret(authctxt, crypt_scheme, salt);
           bzero(crypt_scheme, strlen(crypt_scheme));
           bzero(salt, strlen(salt));
           xfree(crypt_scheme);
           xfree(salt);
           JPAKE_DEBUG_BN((pctx->s, "%s: s = ", __func__));
   
           /* Calculate step 2 values */
           jpake_step2(pctx->grp, pctx->s, pctx->g_x1,
               pctx->g_x3, pctx->g_x4, pctx->x2,
               pctx->server_id, pctx->server_id_len,
               pctx->client_id, pctx->client_id_len,
               x3_proof, x3_proof_len,
               x4_proof, x4_proof_len,
               &pctx->a,
               &x2_s_proof, &x2_s_proof_len);
   
           bzero(x3_proof, x3_proof_len);
           bzero(x4_proof, x4_proof_len);
           xfree(x3_proof);
           xfree(x4_proof);
   
           JPAKE_DEBUG_CTX((pctx, "step 2 sending in %s", __func__));
   
           /* Send values for step 2 */
           packet_start(SSH2_MSG_USERAUTH_JPAKE_CLIENT_STEP2);
           packet_put_bignum2(pctx->a);
           packet_put_string(x2_s_proof, x2_s_proof_len);
           packet_send();
   
           bzero(x2_s_proof, x2_s_proof_len);
           xfree(x2_s_proof);
   
           /* Expect step 2 packet from peer */
           dispatch_set(SSH2_MSG_USERAUTH_JPAKE_SERVER_STEP2,
               input_userauth_jpake_server_step2);
   }
   
   /* ARGSUSED */
   void
   input_userauth_jpake_server_step2(int type, u_int32_t seq, void *ctxt)
   {
           Authctxt *authctxt = ctxt;
           struct jpake_ctx *pctx = authctxt->methoddata;
           u_char *x4_s_proof;
           u_int x4_s_proof_len;
   
           /* Disable this message */
           dispatch_set(SSH2_MSG_USERAUTH_JPAKE_SERVER_STEP2, NULL);
   
           if ((pctx->b = BN_new()) == NULL)
                   fatal("%s: BN_new", __func__);
   
           /* Fetch step 2 values */
           packet_get_bignum2(pctx->b);
           x4_s_proof = packet_get_string(&x4_s_proof_len);
           packet_check_eom();
   
           JPAKE_DEBUG_CTX((pctx, "step 2 received in %s", __func__));
   
           /* Derive shared key and calculate confirmation hash */
           jpake_key_confirm(pctx->grp, pctx->s, pctx->b,
               pctx->x2, pctx->g_x1, pctx->g_x2, pctx->g_x3, pctx->g_x4,
               pctx->client_id, pctx->client_id_len,
               pctx->server_id, pctx->server_id_len,
               session_id2, session_id2_len,
               x4_s_proof, x4_s_proof_len,
               &pctx->k,
               &pctx->h_k_cid_sessid, &pctx->h_k_cid_sessid_len);
   
           bzero(x4_s_proof, x4_s_proof_len);
           xfree(x4_s_proof);
   
           JPAKE_DEBUG_CTX((pctx, "confirm sending in %s", __func__));
   
           /* Send key confirmation proof */
           packet_start(SSH2_MSG_USERAUTH_JPAKE_CLIENT_CONFIRM);
           packet_put_string(pctx->h_k_cid_sessid, pctx->h_k_cid_sessid_len);
           packet_send();
   
           /* Expect confirmation from peer */
           dispatch_set(SSH2_MSG_USERAUTH_JPAKE_SERVER_CONFIRM,
               input_userauth_jpake_server_confirm);
   }
   
   /* ARGSUSED */
   void
   input_userauth_jpake_server_confirm(int type, u_int32_t seq, void *ctxt)
   {
           Authctxt *authctxt = ctxt;
           struct jpake_ctx *pctx = authctxt->methoddata;
   
           /* Disable this message */
           dispatch_set(SSH2_MSG_USERAUTH_JPAKE_SERVER_CONFIRM, NULL);
   
           pctx->h_k_sid_sessid = packet_get_string(&pctx->h_k_sid_sessid_len);
           packet_check_eom();
   
           JPAKE_DEBUG_CTX((pctx, "confirm received in %s", __func__));
   
           /* Verify expected confirmation hash */
           if (jpake_check_confirm(pctx->k,
               pctx->server_id, pctx->server_id_len,
               session_id2, session_id2_len,
               pctx->h_k_sid_sessid, pctx->h_k_sid_sessid_len) == 1)
                   debug("%s: %s success", __func__, authctxt->method->name);
           else {
                   debug("%s: confirmation mismatch", __func__);
                   /* XXX stash this so if auth succeeds then we can warn/kill */
           }
   
           userauth_jpake_cleanup(authctxt);
   }
   #endif /* JPAKE */
   
 static int  static int
 identity_sign(Identity *id, u_char **sigp, u_int *lenp,  identity_sign(Identity *id, u_char **sigp, u_int *lenp,
     u_char *data, u_int datalen)      u_char *data, u_int datalen)
Line 1419 
Line 1647 
         return 1;          return 1;
 }  }
   
   #ifdef JPAKE
   int
   userauth_jpake(Authctxt *authctxt)
   {
           struct jpake_ctx *pctx;
           u_char *x1_proof, *x2_proof;
           u_int x1_proof_len, x2_proof_len;
           static int attempt = 0; /* XXX share with userauth_password's? */
   
           if (attempt++ >= options.number_of_password_prompts)
                   return 0;
           if (attempt != 1)
                   error("Permission denied, please try again.");
   
           if (authctxt->methoddata != NULL)
                   fatal("%s: authctxt->methoddata already set (%p)",
                       __func__, authctxt->methoddata);
   
           authctxt->methoddata = pctx = jpake_new();
   
           /*
            * Send request immediately, to get the protocol going while
            * we do the initial computations.
            */
           packet_start(SSH2_MSG_USERAUTH_REQUEST);
           packet_put_cstring(authctxt->server_user);
           packet_put_cstring(authctxt->service);
           packet_put_cstring(authctxt->method->name);
           packet_send();
           packet_write_wait();
   
           jpake_step1(pctx->grp,
               &pctx->client_id, &pctx->client_id_len,
               &pctx->x1, &pctx->x2, &pctx->g_x1, &pctx->g_x2,
               &x1_proof, &x1_proof_len,
               &x2_proof, &x2_proof_len);
   
           JPAKE_DEBUG_CTX((pctx, "step 1 sending in %s", __func__));
   
           packet_start(SSH2_MSG_USERAUTH_JPAKE_CLIENT_STEP1);
           packet_put_string(pctx->client_id, pctx->client_id_len);
           packet_put_bignum2(pctx->g_x1);
           packet_put_bignum2(pctx->g_x2);
           packet_put_string(x1_proof, x1_proof_len);
           packet_put_string(x2_proof, x2_proof_len);
           packet_send();
   
           bzero(x1_proof, x1_proof_len);
           bzero(x2_proof, x2_proof_len);
           xfree(x1_proof);
           xfree(x2_proof);
   
           /* Expect step 1 packet from peer */
           dispatch_set(SSH2_MSG_USERAUTH_JPAKE_SERVER_STEP1,
               input_userauth_jpake_server_step1);
   
           return 1;
   }
   
   void
   userauth_jpake_cleanup(Authctxt *authctxt)
   {
           debug3("%s: clean up", __func__);
           if (authctxt->methoddata != NULL) {
                   jpake_free(authctxt->methoddata);
                   authctxt->methoddata = NULL;
           }
   }
   #endif /* JPAKE */
   
 /* find auth method */  /* find auth method */
   
 /*  /*
Line 1520 
Line 1818 
         buffer_free(&b);          buffer_free(&b);
         return list;          return list;
 }  }
   

Legend:
Removed from v.1.169  
changed lines
  Added in v.1.170