|
87 | 87 | from mig.shared.base import invisible_path, force_utf8, force_unicode
|
88 | 88 | from mig.shared.conf import get_configuration_object
|
89 | 89 | from mig.shared.defaults import keyword_auto, STRONG_SSH_KEXALGOS, \
|
90 |
| - STRONG_SSH_CIPHERS, STRONG_SSH_MACS, STRONG_SSH_LEGACY_KEXALGOS, \ |
91 |
| - STRONG_SSH_LEGACY_MACS |
| 90 | + STRONG_SSH_CIPHERS, STRONG_SSH_MACS, LEGACY_SSH_KEXALGOS, \ |
| 91 | + LEGACY_SSH_CIPHERS, LEGACY_SSH_MACS, FALLBACK_SSH_KEXALGOS, \ |
| 92 | + FALLBACK_SSH_CIPHERS, FALLBACK_SSH_MACS |
92 | 93 | from mig.shared.fileio import check_write_access, user_chroot_exceptions, \
|
93 | 94 | read_file
|
94 | 95 | from mig.shared.gdp.all import project_open, project_close, project_log
|
@@ -1518,59 +1519,85 @@ def accept_client(client, addr, root_dir, host_rsa_key, conf={}):
|
1518 | 1519 | default_max_packet_size=max_packet_size)
|
1519 | 1520 | # Restrict transport to strong ciphers+kex+digests used in OpenSSH
|
1520 | 1521 | transport_security = transport.get_security_options()
|
1521 |
| - recommended_ciphers = STRONG_SSH_CIPHERS.split(',') |
| 1522 | + strong_ciphers = STRONG_SSH_CIPHERS.split(',') |
| 1523 | + legacy_ciphers = LEGACY_SSH_CIPHERS.split(',') |
| 1524 | + fallback_ciphers = FALLBACK_SSH_CIPHERS.split(',') |
1522 | 1525 | available_ciphers = transport_security.ciphers
|
1523 |
| - strong_ciphers = [i for i in recommended_ciphers if i in available_ciphers] |
1524 |
| - # logger.debug("TLS ciphers available %s, used %s" % (available_ciphers, |
1525 |
| - # strong_ciphers)) |
1526 |
| - if strong_ciphers: |
1527 |
| - transport_security.ciphers = strong_ciphers |
| 1526 | + best_ciphers = [i for i in strong_ciphers if i in available_ciphers] |
| 1527 | + medium_ciphers = [i for i in legacy_ciphers if i in available_ciphers] |
| 1528 | + weak_ciphers = [i for i in fallback_ciphers if i in available_ciphers] |
| 1529 | + # logger.debug("TLS ciphers available %s: best %s, medium %s, weak %s" % |
| 1530 | + # (available_ciphers, best_ciphers, medium_ciphers, weak_ciphers)) |
| 1531 | + if best_ciphers: |
| 1532 | + # logger.debug("Using only strong ciphers: %s" % |
| 1533 | + # ', '.join(best_ciphers)) |
| 1534 | + transport_security.ciphers = best_ciphers |
| 1535 | + elif medium_ciphers: |
| 1536 | + logger.info("Rely on best available legacy ciphers: %s" % |
| 1537 | + ', '.join(medium_ciphers)) |
| 1538 | + transport_security.ciphers = medium_ciphers |
| 1539 | + elif weak_ciphers: |
| 1540 | + logger.warning("Force best available weak ciphers: %s" % |
| 1541 | + ', '.join(weak_ciphers)) |
| 1542 | + transport_security.ciphers = weak_ciphers |
1528 | 1543 | else:
|
1529 |
| - logger.warning("No strong TLS ciphers available!") |
1530 |
| - logger.info("You need a recent paramiko for best security") |
| 1544 | + logger.warning("No safe TLS ciphers available!") |
| 1545 | + logger.info("You need a modern paramiko for proper security") |
1531 | 1546 | # NOTE: paramiko doesn't yet implement strong modern kex algos - use legacy
|
1532 | 1547 | # A number of paramiko tickets indicate plans and interest for adding the
|
1533 | 1548 | # strong curve25519-sha256@libssh.org eventually, but progress looks
|
1534 | 1549 | # stalled. Until then our best alternative appears to be the legacy
|
1535 | 1550 | # diffie-hellman-group-exchange-sha256 fallback, which should be safe as
|
1536 | 1551 | # long as the moduli size tuning of e.g. ssh-audit is applied:
|
1537 | 1552 | # http://cert.europa.eu/static/WhitePapers/CERT-EU-SWP_16-002_Weaknesses%20in%20Diffie-Hellman%20Key%20v1_0.pdf
|
1538 |
| - recommended_kex = STRONG_SSH_KEXALGOS.split(',') |
1539 |
| - fallback_kex = STRONG_SSH_LEGACY_KEXALGOS.split(',') |
| 1553 | + strong_kex = STRONG_SSH_KEXALGOS.split(',') |
| 1554 | + legacy_kex = LEGACY_SSH_KEXALGOS.split(',') |
| 1555 | + fallback_kex = FALLBACK_SSH_KEXALGOS.split(',') |
1540 | 1556 | available_kex = transport_security.kex
|
1541 |
| - strong_kex = [i for i in recommended_kex if i in available_kex] |
1542 |
| - medium_kex = [i for i in fallback_kex if i in available_kex] |
1543 |
| - # logger.debug("TLS kex available %s, used %s (or fallback to %s)" % |
1544 |
| - # (available_kex, strong_kex, medium_kex)) |
1545 |
| - if strong_kex: |
1546 |
| - # logger.debug("Using only strong key exchange algorithms: %s" % |
1547 |
| - # ', '.join(strong_kex)) |
1548 |
| - transport_security.kex = strong_kex |
| 1557 | + best_kex = [i for i in strong_kex if i in available_kex] |
| 1558 | + medium_kex = [i for i in legacy_kex if i in available_kex] |
| 1559 | + weak_kex = [i for i in fallback_kex if i in available_kex] |
| 1560 | + # logger.debug("TLS kex available %s: best %s, medium %s, weak %s" % |
| 1561 | + # (available_kex, best_kex, medium_kex, weak_kex)) |
| 1562 | + if best_kex: |
| 1563 | + # logger.debug("Using only strong kex algorithms: %s" % |
| 1564 | + # ', '.join(best_kex)) |
| 1565 | + transport_security.kex = best_kex |
1549 | 1566 | elif medium_kex:
|
1550 |
| - # logger.debug("Using only medium strength key exchange algorithms: %s" % |
1551 |
| - # ', '.join(medium_kex)) |
| 1567 | + logger.info("Rely on best available legacy kex algorithms: %s" % |
| 1568 | + ', '.join(medium_kex)) |
1552 | 1569 | transport_security.kex = medium_kex
|
| 1570 | + elif weak_kex: |
| 1571 | + logger.warning("Force best available weak kex algorithms: %s" % |
| 1572 | + ', '.join(weak_kex)) |
| 1573 | + transport_security.kex = weak_kex |
1553 | 1574 | else:
|
1554 |
| - logger.warning("No strong TLS key exchange algorithm available!") |
1555 |
| - logger.info("You need a recent paramiko for best security") |
1556 |
| - recommended_digests = STRONG_SSH_MACS.split(',') |
1557 |
| - fallback_digests = STRONG_SSH_LEGACY_MACS.split(',') |
| 1575 | + logger.warning("No safe TLS key exchange algorithm available!") |
| 1576 | + logger.info("You need a modern paramiko for proper security") |
| 1577 | + strong_digests = STRONG_SSH_MACS.split(',') |
| 1578 | + legacy_digests = LEGACY_SSH_MACS.split(',') |
| 1579 | + fallback_digests = FALLBACK_SSH_MACS.split(',') |
1558 | 1580 | available_digests = transport_security.digests
|
1559 |
| - strong_digests = [i for i in recommended_digests if i in available_digests] |
1560 |
| - medium_digests = [i for i in fallback_digests if i in available_digests] |
1561 |
| - # logger.debug("TLS digests available %s, used %s (or fallback to %s)" % |
1562 |
| - # (available_digests, strong_digests, medium_digests)) |
1563 |
| - if strong_digests: |
1564 |
| - # logger.debug("Using only strong message auth codes: %s" % |
1565 |
| - # ', '.join(strong_digests)) |
1566 |
| - transport_security.digests = strong_digests |
| 1581 | + best_digests = [i for i in strong_digests if i in available_digests] |
| 1582 | + medium_digests = [i for i in legacy_digests if i in available_digests] |
| 1583 | + weak_digests = [i for i in fallback_digests if i in available_digests] |
| 1584 | + # logger.debug("TLS digests available %s: best %s, medium %s, weak %s" % |
| 1585 | + # (available_digests, best_digests, medium_digests, weak_digests)) |
| 1586 | + if best_digests: |
| 1587 | + # logger.debug("Using only strong digests: %s" % |
| 1588 | + # ', '.join(best_digests)) |
| 1589 | + transport_security.digests = best_digests |
1567 | 1590 | elif medium_digests:
|
1568 |
| - # logger.debug("Using only medium strength message auth codes: %s" % |
1569 |
| - # ', '.join(medium_digests)) |
| 1591 | + logger.info("Rely on best available legacy digests: %s" % |
| 1592 | + ', '.join(medium_digests)) |
1570 | 1593 | transport_security.digests = medium_digests
|
| 1594 | + elif weak_digests: |
| 1595 | + logger.warning("Force best available weak digests: %s" % |
| 1596 | + ', '.join(weak_digests)) |
| 1597 | + transport_security.digests = weak_digests |
1571 | 1598 | else:
|
1572 |
| - logger.warning("No strong TLS digest algorithm available!") |
1573 |
| - logger.info("You need paramiko 1.16 or later for best security") |
| 1599 | + logger.warning("No safe TLS digest algorithm available!") |
| 1600 | + logger.info("You need a modern paramiko for proper security") |
1574 | 1601 |
|
1575 | 1602 | # Default forces re-keying after every 512MB or same number of packets.
|
1576 | 1603 | # We bump that to reduce the slowing effect of those: it's a security
|
|
0 commit comments