(out: 'OutputBuffer', s: 'SSH_Socket', banner: Optional['Banner'], kex: 'SSH2_Kex')
| 125 | # Runs the DH moduli test against the specified target. |
| 126 | @staticmethod |
| 127 | def run(out: 'OutputBuffer', s: 'SSH_Socket', banner: Optional['Banner'], kex: 'SSH2_Kex') -> None: |
| 128 | GEX_ALGS = { |
| 129 | 'diffie-hellman-group-exchange-sha1': KexGroupExchange_SHA1, |
| 130 | 'diffie-hellman-group-exchange-sha256': KexGroupExchange_SHA256, |
| 131 | } |
| 132 | |
| 133 | # The previous RSA tests put the server in a state we can't |
| 134 | # test. So we need a new connection to start with a clean |
| 135 | # slate. |
| 136 | if s.is_connected(): |
| 137 | s.close() |
| 138 | |
| 139 | # Check if the server supports any of the group-exchange |
| 140 | # algorithms. If so, test each one. |
| 141 | for gex_alg, kex_group_class in GEX_ALGS.items(): # pylint: disable=too-many-nested-blocks |
| 142 | if gex_alg in kex.kex_algorithms: |
| 143 | out.d('Preparing to perform DH group exchange using ' + gex_alg + ' with min, pref and max modulus sizes of 512 bits, 1024 bits and 1536 bits...', write_now=True) |
| 144 | |
| 145 | kex_group = kex_group_class(out) |
| 146 | smallest_modulus, reconnect_failed = GEXTest._send_init(out, s, kex_group, kex, gex_alg, 512, 1024, 1536) |
| 147 | if reconnect_failed: |
| 148 | break |
| 149 | |
| 150 | # Try an array of specific modulus sizes... one at a time. |
| 151 | reconnect_failed = False |
| 152 | for bits in [512, 768, 1024, 1536, 2048, 3072, 4096]: |
| 153 | |
| 154 | # If we found one modulus size already, but we're about |
| 155 | # to test a larger one, don't bother. |
| 156 | if bits >= smallest_modulus > 0: |
| 157 | break |
| 158 | |
| 159 | smallest_modulus, reconnect_failed = GEXTest._send_init(out, s, kex_group, kex, gex_alg, bits, bits, bits) |
| 160 | |
| 161 | # If the smallest modulus is 2048 and the server is OpenSSH, then we may have triggered the fallback mechanism, which tends to happen in testing scenarios such as this but not in most real-world conditions (see X). To better test this condition, we will do an additional check to see if the server supports sizes between 2048 and 4096, and consider this the definitive result. |
| 162 | openssh_test_updated = False |
| 163 | if (smallest_modulus == 2048) and (banner is not None) and (banner.software is not None) and (banner.software.find('OpenSSH') != -1): |
| 164 | out.d('First pass found a minimum GEX modulus of 2048 against OpenSSH server. Performing a second pass to get a more accurate result...') |
| 165 | smallest_modulus, _ = GEXTest._send_init(out, s, kex_group, kex, gex_alg, 2048, 3072, 4096) |
| 166 | out.d('Modulus size returned by server during second pass: %d bits' % smallest_modulus, write_now=True) |
| 167 | openssh_test_updated = bool((smallest_modulus > 0) and (smallest_modulus != 2048)) |
| 168 | |
| 169 | if smallest_modulus > 0: |
| 170 | kex.set_dh_modulus_size(gex_alg, smallest_modulus) |
| 171 | |
| 172 | lst = SSH2_KexDB.get_db()['kex'][gex_alg] |
| 173 | |
| 174 | # We flag moduli smaller than 2048 as a failure. |
| 175 | if smallest_modulus < 2048: |
| 176 | text = 'using small %d-bit modulus' % smallest_modulus |
| 177 | |
| 178 | # For 'diffie-hellman-group-exchange-sha256', add |
| 179 | # a failure reason. |
| 180 | if len(lst) == 1: |
| 181 | lst.append([text]) |
| 182 | # For 'diffie-hellman-group-exchange-sha1', delete |
| 183 | # the existing failure reason (which is vague), and |
| 184 | # insert our own. |
nothing calls this directly
no test coverage detected