Browse Source

Merge branch 'thirdparty_dev' into dev

# Conflicts:
#	source/putty/WINDOWS/winpgntc.c

#	source/putty/sshecc.c
#	source/putty/sshmac.c
#	source/putty/sshmd5.c

Source commit: 2d64f12003405137ecfd66145cfc6adac1bc5e26
Martin Prikryl 6 năm trước cách đây
mục cha
commit
d378c25d9a

+ 5 - 6
source/putty/import.c

@@ -750,7 +750,7 @@ static struct ssh2_userkey *openssh_pem_read(
         }
 
     } else {
-        assert(0 && "Bad key type from load_openssh_pem_key");
+        unreachable("Bad key type from load_openssh_pem_key");
 	errmsg = "Bad key type from load_openssh_pem_key";
 	goto error;
     }
@@ -973,8 +973,7 @@ static bool openssh_pem_write(
         header = "-----BEGIN EC PRIVATE KEY-----\n";
         footer = "-----END EC PRIVATE KEY-----\n";
     } else {
-        assert(0);                     /* zoinks! */
-	exit(1); /* XXX: GCC doesn't understand assert() on some systems. */
+        unreachable("bad key alg in openssh_pem_write");
     }
 
     /*
@@ -1363,7 +1362,7 @@ static struct ssh2_userkey *openssh_new_read(
             keysize = 48;              /* 32 byte key + 16 byte IV */
             break;
           default:
-            assert(0 && "Bad cipher enumeration value");
+            unreachable("Bad cipher enumeration value");
         }
         assert(keysize <= sizeof(keybuf));
         switch (key->kdf) {
@@ -1378,7 +1377,7 @@ static struct ssh2_userkey *openssh_new_read(
                            keybuf, keysize);
             break;
           default:
-            assert(0 && "Bad kdf enumeration value");
+            unreachable("Bad kdf enumeration value");
         }
         switch (key->cipher) {
           case ON_E_NONE:
@@ -1408,7 +1407,7 @@ static struct ssh2_userkey *openssh_new_read(
             }
             break;
           default:
-            assert(0 && "Bad cipher enumeration value");
+            unreachable("Bad cipher enumeration value");
         }
     }
 

+ 18 - 0
source/putty/misc.h

@@ -11,8 +11,10 @@
 
 #include <stdio.h>		       /* for FILE * */
 #include <stdarg.h>		       /* for va_list */
+#include <stdlib.h>                    /* for abort */
 #include <time.h>                      /* for struct tm */
 #include <limits.h>                    /* for INT_MAX/MIN */
+#include <assert.h>                    /* for assert (obviously) */
 
 unsigned long parse_blocksize(const char *bs);
 char ctrlparse(char *s, char **next);
@@ -169,6 +171,22 @@ bool smemeq(const void *av, const void *bv, size_t len);
 
 char *buildinfo(const char *newline);
 
+/*
+ * A function you can put at points in the code where execution should
+ * never reach in the first place. Better than assert(false), or even
+ * assert(false && "some explanatory message"), because some compilers
+ * don't interpret assert(false) as a declaration of unreachability,
+ * so they may still warn about pointless things like some variable
+ * not being initialised on the unreachable code path.
+ *
+ * I follow the assertion with a call to abort() just in case someone
+ * compiles with -DNDEBUG, and I wrap that abort inside my own
+ * function labelled NORETURN just in case some unusual kind of system
+ * header wasn't foresighted enough to label abort() itself that way.
+ */
+static inline NORETURN void unreachable_internal(void) { abort(); }
+#define unreachable(msg) (assert(false && msg), unreachable_internal())
+
 /*
  * Debugging functions.
  *

+ 1 - 1
source/putty/portfwd.c

@@ -243,7 +243,7 @@ static void pfd_receive(Plug *plug, int urgent, char *data, int len)
             switch (pf->socks_state) {
               case SOCKS_INITIAL:
               case SOCKS_NONE:
-                assert(0 && "These case values cannot appear");
+                unreachable("These case values cannot appear");
 
               case SOCKS_4:
                 /* SOCKS 4/4A connect message */

+ 3 - 3
source/putty/ssh.h

@@ -746,7 +746,7 @@ struct ssh2_macalg {
 
 #define ssh2_mac_new(alg, cipher) ((alg)->new(alg, cipher))
 #define ssh2_mac_free(ctx) ((ctx)->vt->free(ctx))
-#define ssh2_mac_setkey(ctx, key) ((ctx)->vt->free(ctx, key))
+#define ssh2_mac_setkey(ctx, key) ((ctx)->vt->setkey(ctx, key))
 #define ssh2_mac_start(ctx) ((ctx)->vt->start(ctx))
 #define ssh2_mac_genresult(ctx, out) ((ctx)->vt->genresult(ctx, out))
 #define ssh2_mac_alg(ctx) ((ctx)->vt)
@@ -879,8 +879,8 @@ struct ssh2_userkey {
     char *comment;		       /* the key comment */
 };
 
-/* The maximum length of any hash algorithm used in kex. (bytes) */
-#define SSH2_KEX_MAX_HASH_LEN (64) /* SHA-512 */
+/* The maximum length of any hash algorithm. (bytes) */
+#define MAX_HASH_LEN (64)              /* longest is SHA-512 */
 
 extern const struct ssh1_cipheralg ssh1_3des;
 extern const struct ssh1_cipheralg ssh1_des;

+ 2 - 4
source/putty/ssh1connection-client.c

@@ -526,12 +526,10 @@ struct ssh_rportfwd *ssh1_rportfwd_alloc(
 SshChannel *ssh1_serverside_x11_open(
     ConnectionLayer *cl, Channel *chan, const SocketPeerInfo *pi)
 {
-    assert(false && "Should never be called in the client");
-    return NULL;
+    unreachable("Should never be called in the client");
 }
 
 SshChannel *ssh1_serverside_agent_open(ConnectionLayer *cl, Channel *chan)
 {
-    assert(false && "Should never be called in the client");
-    return NULL;
+    unreachable("Should never be called in the client");
 }

+ 2 - 2
source/putty/ssh1login.c

@@ -252,6 +252,7 @@ static void ssh1_login_process_queue(PacketProtocolLayer *ppl)
                 return;
             }
         } else {
+            sfree(fingerprint);
             sfree(keystr);
         }
     }
@@ -689,8 +690,7 @@ static void ssh1_login_process_queue(PacketProtocolLayer *ppl)
                     got_passphrase = false;
                     /* and try again */
                 } else {
-                    assert(0 && "unexpected return from rsa_ssh1_loadkey()");
-                    got_passphrase = false;   /* placate optimisers */
+                    unreachable("unexpected return from rsa_ssh1_loadkey()");
                 }
             }
 

+ 2 - 2
source/putty/ssh2bpp.c

@@ -122,7 +122,7 @@ void ssh2_bpp_new_outgoing_crypto(
     s->out.etm_mode = etm_mode;
     if (mac) {
         s->out.mac = ssh2_mac_new(mac, s->out.cipher);
-        mac->setkey(s->out.mac, mac_key);
+        ssh2_mac_setkey(s->out.mac, mac_key);
 
         bpp_logevent("Initialised %s outbound MAC algorithm%s%s",
                      ssh2_mac_alg(s->out.mac)->text_name,
@@ -184,7 +184,7 @@ void ssh2_bpp_new_incoming_crypto(
     s->in.etm_mode = etm_mode;
     if (mac) {
         s->in.mac = ssh2_mac_new(mac, s->in.cipher);
-        mac->setkey(s->in.mac, mac_key);
+        ssh2_mac_setkey(s->in.mac, mac_key);
 
         bpp_logevent("Initialised %s inbound MAC algorithm%s%s",
                      ssh2_mac_alg(s->in.mac)->text_name,

+ 5 - 7
source/putty/ssh2connection-client.c

@@ -308,14 +308,12 @@ SshChannel *ssh2_session_open(ConnectionLayer *cl, Channel *chan)
 SshChannel *ssh2_serverside_x11_open(
     ConnectionLayer *cl, Channel *chan, const SocketPeerInfo *pi)
 {
-    assert(false && "Should never be called in the client");
-    return 0;                          /* placate optimiser */
+    unreachable("Should never be called in the client");
 }
 
 SshChannel *ssh2_serverside_agent_open(ConnectionLayer *cl, Channel *chan)
 {
-    assert(false && "Should never be called in the client");
-    return 0;                          /* placate optimiser */
+    unreachable("Should never be called in the client");
 }
 
 static void ssh2_channel_response(
@@ -362,19 +360,19 @@ bool ssh2channel_start_subsystem(
 
 void ssh2channel_send_exit_status(SshChannel *sc, int status)
 {
-    assert(false && "Should never be called in the client");
+    unreachable("Should never be called in the client");
 }
 
 void ssh2channel_send_exit_signal(
     SshChannel *sc, ptrlen signame, bool core_dumped, ptrlen msg)
 {
-    assert(false && "Should never be called in the client");
+    unreachable("Should never be called in the client");
 }
 
 void ssh2channel_send_exit_signal_numeric(
     SshChannel *sc, int signum, bool core_dumped, ptrlen msg)
 {
-    assert(false && "Should never be called in the client");
+    unreachable("Should never be called in the client");
 }
 
 void ssh2channel_request_x11_forwarding(

+ 1 - 1
source/putty/ssh2transport.c

@@ -932,7 +932,7 @@ static bool ssh2_scan_kexinits(
             break;
 
           default:
-            assert(false && "Bad list index in scan_kexinits");
+            unreachable("Bad list index in scan_kexinits");
         }
     }
 

+ 2 - 2
source/putty/ssh2transport.h

@@ -131,7 +131,7 @@ struct ssh2_transport_state {
     const struct ssh_kex *kex_alg;
     const ssh_keyalg *hostkey_alg;
     char *hostkey_str; /* string representation, for easy checking in rekeys */
-    unsigned char session_id[SSH2_KEX_MAX_HASH_LEN];
+    unsigned char session_id[MAX_HASH_LEN];
     int session_id_len;
     int dh_min_size, dh_max_size;
     bool dh_got_size_bounds;
@@ -178,7 +178,7 @@ struct ssh2_transport_state {
     ssh_key *hkey;                     /* actual host key */
     struct RSAKey *rsa_kex_key;             /* for RSA kex */
     ecdh_key *ecdh_key;                     /* for ECDH kex */
-    unsigned char exchange_hash[SSH2_KEX_MAX_HASH_LEN];
+    unsigned char exchange_hash[MAX_HASH_LEN];
     bool can_gssapi_keyex;
     bool need_gss_transient_hostkey;
     bool warned_about_no_gss_transient_hostkey;

+ 9 - 9
source/putty/sshaes.c

@@ -867,7 +867,7 @@ static void aes_setup(AESContext * ctx, const unsigned char *key, int keylen)
             ENCLASTROUND;
             break;
           default:
-            assert(0);
+            unreachable("bad AES round count");
         }
 	for (i = 0; i < 4; i++)
             PUT_32BIT_MSB_FIRST(blk + 4 * i, block[i]);
@@ -912,7 +912,7 @@ static void aes_setup(AESContext * ctx, const unsigned char *key, int keylen)
             ENCLASTROUND;
             break;
           default:
-            assert(0);
+            unreachable("bad AES round count");
         }
 	for (i = 0; i < 4; i++) {
             tmp = GET_32BIT_MSB_FIRST(blk + 4 * i);
@@ -963,7 +963,7 @@ static void aes_setup(AESContext * ctx, const unsigned char *key, int keylen)
             DECLASTROUND;
             break;
           default:
-            assert(0);
+            unreachable("bad AES round count");
         }
 	for (i = 0; i < 4; i++) {
             PUT_32BIT_MSB_FIRST(blk + 4 * i, iv[i] ^ block[i]);
@@ -1514,7 +1514,7 @@ static void aes_encrypt_cbc_ni(unsigned char *blk, int len, AESContext * ctx)
             enc = _mm_aesenclast_si128(enc, *(++keysched));
             break;
           default:
-            assert(0);
+            unreachable("bad AES round count");
         }
 
         /* Store and go to next block */
@@ -1561,7 +1561,7 @@ static void aes_decrypt_cbc_ni(unsigned char *blk, int len, AESContext * ctx)
             dec = _mm_aesdeclast_si128(dec, *(++keysched));
             break;
           default:
-            assert(0);
+            unreachable("bad AES round count");
         }
 
         /* Xor data with IV */
@@ -1619,7 +1619,7 @@ static void aes_sdctr_ni(unsigned char *blk, int len, AESContext *ctx)
             enc = _mm_aesenclast_si128(enc, *(++keysched));
             break;
           default:
-            assert(0);
+            unreachable("bad AES round count");
         }
 
         /* Xor with block and store result */
@@ -1734,7 +1734,7 @@ static void aes_setup_ni(AESContext * ctx,
         AES_256_Key_Expansion (key, keysched);
         break;
       default:
-        assert(0);
+        unreachable("bad AES key length");
     }
 
     /*
@@ -1751,7 +1751,7 @@ static void aes_setup_ni(AESContext * ctx,
         aes_inv_key_14(ctx);
         break;
       default:
-        assert(0);
+        unreachable("bad AES key length");
     }
 }
 
@@ -1759,7 +1759,7 @@ static void aes_setup_ni(AESContext * ctx,
 
 static void aes_setup_ni(AESContext * ctx, const unsigned char *key, int keylen)
 {
-    assert(0);
+    unreachable("aes_setup_ni called when not compiled in");
 }
 
 INLINE static bool supports_aes_ni()

+ 4 - 4
source/putty/sshcommon.c

@@ -368,12 +368,12 @@ static bool zombiechan_want_close(Channel *chan, bool sent_eof, bool rcvd_eof)
 
 void chan_remotely_opened_confirmation(Channel *chan)
 {
-    assert(0 && "this channel type should never receive OPEN_CONFIRMATION");
+    unreachable("this channel type should never receive OPEN_CONFIRMATION");
 }
 
 void chan_remotely_opened_failure(Channel *chan, const char *errtext)
 {
-    assert(0 && "this channel type should never receive OPEN_FAILURE");
+    unreachable("this channel type should never receive OPEN_FAILURE");
 }
 
 bool chan_default_want_close(
@@ -461,7 +461,7 @@ bool chan_no_change_window_size(
 
 void chan_no_request_response(Channel *chan, bool success)
 {
-    assert(0 && "this channel type should never send a want-reply request");
+    unreachable("this channel type should never send a want-reply request");
 }
 
 /* ----------------------------------------------------------------------
@@ -582,7 +582,7 @@ struct ssh_ttymodes get_ttymodes_from_conf(Seat *seat, Conf *conf)
                     ival = (atoi(sval) != 0);
                 break;
               default:
-                assert(0 && "Bad mode->type");
+                unreachable("Bad mode->type");
             }
 
             modes.have_mode[mode->opcode] = true;

+ 10 - 5
source/putty/sshdh.c

@@ -186,11 +186,16 @@ int dh_modulus_bit_size(const struct dh_ctx *ctx)
  */
 void dh_cleanup(struct dh_ctx *ctx)
 {
-    mp_free(ctx->x);
-    mp_free(ctx->e);
-    mp_free(ctx->p);
-    mp_free(ctx->g);
-    mp_free(ctx->q);
+    if (ctx->x)
+        mp_free(ctx->x);
+    if (ctx->e)
+        mp_free(ctx->e);
+    if (ctx->p)
+        mp_free(ctx->p);
+    if (ctx->g)
+        mp_free(ctx->g);
+    if (ctx->q)
+        mp_free(ctx->q);
     sfree(ctx);
 }
 

+ 14 - 19
source/putty/sshecc.c

@@ -389,7 +389,7 @@ EdwardsPoint *eddsa_public(mp_int *private_key, const ssh_keyalg *alg)
         put_byte(h, mp_get_byte(private_key, i));
 
     { // WINSCP
-    unsigned char * hash = snewn(extra->hash->hlen, unsigned char); // WINSCP
+    unsigned char hash[MAX_HASH_LEN];
     ssh_hash_final(h, hash);
 
     { // WINSCP
@@ -398,7 +398,6 @@ EdwardsPoint *eddsa_public(mp_int *private_key, const ssh_keyalg *alg)
 
     EdwardsPoint *toret = ecc_edwards_multiply(curve->e.G, exponent);
     mp_free(exponent);
-    sfree(hash); // WINSCP
 
     return toret;
     } // WINSCP
@@ -955,11 +954,10 @@ static mp_int *ecdsa_signing_exponent_from_data(
     ptrlen data)
 {
     /* Hash the data being signed. */
-    unsigned char * hash = snewn(extra->hash->hlen, unsigned char); // WINSCP
+    unsigned char hash[MAX_HASH_LEN];
     ssh_hash *h = ssh_hash_new(extra->hash);
     put_data(h, data.ptr, data.len);
     ssh_hash_final(h, hash);
-    sfree(hash);
 
     /*
      * Take the leftmost b bits of the hash of the signed data (where
@@ -1071,13 +1069,12 @@ static mp_int *eddsa_signing_exponent_from_data(
     ptrlen r_encoded, ptrlen data)
 {
     /* Hash (r || public key || message) */
-    unsigned char * hash = snewn(extra->hash->hlen, unsigned char);
+    unsigned char hash[MAX_HASH_LEN];
     ssh_hash *h = ssh_hash_new(extra->hash);
     put_data(h, r_encoded.ptr, r_encoded.len);
     put_epoint(h, ek->publicKey, ek->curve, true); /* omit string header */
     put_data(h, data.ptr, data.len);
     ssh_hash_final(h, hash);
-    sfree(hash);
 
     /* Convert to an integer */
     { // WINSCP
@@ -1239,13 +1236,12 @@ static void eddsa_sign(ssh_key *key, const void *data, int datalen,
      * into a hash generating 2*fieldBytes of output.
      */
     { // WINSCP
-    unsigned char * hash = snewn(extra->hash->hlen, unsigned char); // WINSCP
+    unsigned char hash[MAX_HASH_LEN];
     ssh_hash *h = ssh_hash_new(extra->hash);
     size_t i; // WINSCP
     for (i = 0; i < ek->curve->fieldBytes; ++i)
         put_byte(h, mp_get_byte(ek->privateKey, i));
     ssh_hash_final(h, hash);
-    sfree(hash); // WINSCP
 
     /*
      * The first half of the output hash is converted into an
@@ -1467,17 +1463,16 @@ static void ssh_ecdhkex_w_setup(ecdh_key *dh)
 
 static void ssh_ecdhkex_m_setup(ecdh_key *dh)
 {
-    unsigned char * bytes = snewn(dh->curve->fieldBytes, unsigned char); // WINSCP
-    size_t i; // WINSCP
-    for (i = 0; i < sizeof(bytes); ++i)
-        bytes[i] = random_byte();
-
-    bytes[0] &= 0xF8;
-    bytes[dh->curve->fieldBytes-1] &= 0x7F;
-    bytes[dh->curve->fieldBytes-1] |= 0x40;
-    dh->private = mp_from_bytes_le(make_ptrlen(bytes, dh->curve->fieldBytes));
-    smemclr(bytes, sizeof(bytes));
-    sfree(bytes); // WINSCP
+    strbuf *bytes = strbuf_new();
+    size_t i;
+    for (i = 0; i < dh->curve->fieldBytes; ++i)
+        put_byte(bytes, random_byte());
+
+    bytes->u[0] &= 0xF8;
+    bytes->u[bytes->len-1] &= 0x7F;
+    bytes->u[bytes->len-1] |= 0x40;
+    dh->private = mp_from_bytes_le(ptrlen_from_strbuf(bytes));
+    strbuf_free(bytes);
 
     dh->m_public = ecc_montgomery_multiply(dh->curve->m.G, dh->private);
 }

+ 1 - 1
source/putty/sshmac.c

@@ -32,7 +32,7 @@ static void ssh2_mac_prepare(ssh2_mac *mac, const void *blk, int len,
 void ssh2_mac_generate(ssh2_mac *mac, void *blk, int len, unsigned long seq)
 {
     ssh2_mac_prepare(mac, blk, len, seq);
-    /*MPEXT return*/ ssh2_mac_genresult(mac, (unsigned char *)blk + len);
+    ssh2_mac_genresult(mac, (unsigned char *)blk + len);
 }
 
 bool ssh2_mac_verify(

+ 1 - 1
source/putty/sshmd5.c

@@ -314,7 +314,7 @@ void hmacmd5_do_hmac(struct hmacmd5_context *ctx,
 {
     ssh2_mac_start(&ctx->mac);
     put_data(&ctx->mac, blk, len);
-    /*WINSCP return*/ ssh2_mac_genresult(&ctx->mac, hmac);
+    ssh2_mac_genresult(&ctx->mac, hmac);
 }
 
 const struct ssh2_macalg ssh_hmac_md5 = {

+ 1 - 1
source/putty/sshpubk.c

@@ -1508,7 +1508,7 @@ void ssh2_write_pubkey(FILE *fp, const char *comment,
         fprintf(fp, "%s\n", buffer);
         sfree(buffer);
     } else {
-        assert(0 && "Bad key type in ssh2_write_pubkey");
+        unreachable("Bad key type in ssh2_write_pubkey");
     }
 }
 

+ 2 - 2
source/putty/sshrsa.c

@@ -750,9 +750,9 @@ static void oaep_mask(const struct ssh_hashalg *h, void *seed, int seedlen,
     while (datalen > 0) {
         int i, max = (datalen > h->hlen ? h->hlen : datalen);
         ssh_hash *s;
-        unsigned char hash[SSH2_KEX_MAX_HASH_LEN];
+        unsigned char hash[MAX_HASH_LEN];
 
-	assert(h->hlen <= SSH2_KEX_MAX_HASH_LEN);
+	assert(h->hlen <= MAX_HASH_LEN);
         s = ssh_hash_new(h);
         put_data(s, seed, seedlen);
         put_uint32(s, count);

+ 1 - 1
source/putty/sshsh256.c

@@ -641,7 +641,7 @@ static void SHA256_ni(SHA256_State * s, const unsigned char *q, int len)
 
 static void SHA256_ni(SHA256_State * s, const unsigned char *q, int len)
 {
-    assert(0);
+    unreachable("SHA256_ni not compiled in");
 }
 
 #endif  /* COMPILER_SUPPORTS_AES_NI */

+ 1 - 1
source/putty/sshsha.c

@@ -686,7 +686,7 @@ static void sha1_ni(SHA_State * s, const unsigned char *q, int len)
 
 static void sha1_ni(SHA_State * s, const unsigned char *q, int len)
 {
-    assert(0);
+    unreachable("sha1_ni not compiled in");
 }
 
 bool supports_sha_ni(void)

+ 4 - 5
source/putty/sshverstring.c

@@ -407,16 +407,15 @@ void ssh_verstring_handle_input(BinaryPacketProtocol *bpp)
 
 static PktOut *ssh_verstring_new_pktout(int type)
 {
-    assert(0 && "Should never try to send packets during SSH version "
-           "string exchange");
-    return NULL;
+    unreachable("Should never try to send packets during SSH version "
+                "string exchange");
 }
 
 static void ssh_verstring_handle_output(BinaryPacketProtocol *bpp)
 {
     if (pq_peek(&bpp->out_pq)) {
-        assert(0 && "Should never try to send packets during SSH version "
-               "string exchange");
+        unreachable("Should never try to send packets during SSH version "
+                    "string exchange");
     }
 }
 

+ 1 - 1
source/putty/windows/winnet.c

@@ -808,7 +808,7 @@ void sk_addrcopy(SockAddr *addr, char *buf)
 	    memcpy(buf, &((struct sockaddr_in6 *)step.ai->ai_addr)->sin6_addr,
 		   sizeof(struct in6_addr));
 	else
-	    assert(false);
+	    unreachable("bad address family in sk_addrcopy");
     } else
 #endif
     if (family == AF_INET) {

+ 1 - 1
source/putty/windows/winpgntc.c

@@ -27,7 +27,7 @@ bool agent_exists(void)
 
 void agent_cancel_query(agent_pending_query *q)
 {
-    assert(0 && "Windows agent queries are never asynchronous!");
+    unreachable("Windows agent queries are never asynchronous!");
 }
 
 agent_pending_query *agent_query(

+ 1 - 1
source/putty/x11fwd.c

@@ -667,7 +667,7 @@ void x11_format_auth_for_authfile(
         put_uint16(bs, 6); /* indicates IPv6 */
         put_stringpl_xauth(bs, make_ptrlen(ipv6buf, 16));
     } else {
-        assert(false && "Bad address type in x11_format_auth_for_authfile");
+        unreachable("Bad address type in x11_format_auth_for_authfile");
     }
 
     {