Tests for granular modulus sizes. Builds a dictionary, where a key represents a DH algorithm name and the values are the modulus sizes (in bits) that have been returned by the target server. Returns an exitcodes.* flag.
(out: 'OutputBuffer', s: 'SSH_Socket', kex: 'SSH2_Kex', bits_min: int, bits_pref: int, bits_max: int, modulus_dict: Dict[str, List[int]])
| 74 | |
| 75 | @staticmethod |
| 76 | def granular_modulus_size_test(out: 'OutputBuffer', s: 'SSH_Socket', kex: 'SSH2_Kex', bits_min: int, bits_pref: int, bits_max: int, modulus_dict: Dict[str, List[int]]) -> int: |
| 77 | ''' |
| 78 | Tests for granular modulus sizes. |
| 79 | Builds a dictionary, where a key represents a DH algorithm name and the |
| 80 | values are the modulus sizes (in bits) that have been returned by the |
| 81 | target server. |
| 82 | Returns an exitcodes.* flag. |
| 83 | ''' |
| 84 | |
| 85 | retval = exitcodes.GOOD |
| 86 | |
| 87 | out.d("Starting modulus_size_test...") |
| 88 | out.d("Bits Min: " + str(bits_min)) |
| 89 | out.d("Bits Pref: " + str(bits_pref)) |
| 90 | out.d("Bits Max: " + str(bits_max)) |
| 91 | |
| 92 | GEX_ALGS = { |
| 93 | 'diffie-hellman-group-exchange-sha1': KexGroupExchange_SHA1, |
| 94 | 'diffie-hellman-group-exchange-sha256': KexGroupExchange_SHA256, |
| 95 | } |
| 96 | |
| 97 | # Check if the server supports any of the group-exchange |
| 98 | # algorithms. If so, test each one. |
| 99 | for gex_alg, kex_group_class in GEX_ALGS.items(): |
| 100 | if gex_alg not in kex.kex_algorithms: |
| 101 | out.d('Server does not support the algorithm "' + gex_alg + '".', write_now=True) |
| 102 | else: |
| 103 | kex_group = kex_group_class(out) |
| 104 | out.d('Preparing to perform DH group exchange using ' + gex_alg + ' with min, pref and max modulus sizes of ' + str(bits_min) + ' bits, ' + str(bits_pref) + ' bits and ' + str(bits_max) + ' bits...', write_now=True) |
| 105 | |
| 106 | # It has been observed that reconnecting to some SSH servers |
| 107 | # multiple times in quick succession can eventually result |
| 108 | # in a "connection reset by peer" error. It may be possible |
| 109 | # to recover from such an error by sleeping for some time |
| 110 | # before continuing to issue reconnects. |
| 111 | modulus_size_returned, reconnect_failed = GEXTest._send_init(out, s, kex_group, kex, gex_alg, bits_min, bits_pref, bits_max) |
| 112 | if reconnect_failed: |
| 113 | out.fail('Reconnect failed.') |
| 114 | return exitcodes.FAILURE |
| 115 | |
| 116 | if modulus_size_returned > 0: |
| 117 | if gex_alg in modulus_dict: |
| 118 | if modulus_size_returned not in modulus_dict[gex_alg]: |
| 119 | modulus_dict[gex_alg].append(modulus_size_returned) |
| 120 | else: |
| 121 | modulus_dict[gex_alg] = [modulus_size_returned] |
| 122 | |
| 123 | return retval |
| 124 | |
| 125 | # Runs the DH moduli test against the specified target. |
| 126 | @staticmethod |
no test coverage detected