|
40 | 40 | import socket
|
41 | 41 | import subprocess
|
42 | 42 | import sys
|
| 43 | +from time import sleep |
43 | 44 |
|
44 | 45 | import tests
|
45 | 46 | from . import check_tls_versions_support
|
|
57 | 58 | from mysql.connector import (connect, connection, network, errors,
|
58 | 59 | constants, cursor, abstracts, catch23,
|
59 | 60 | HAVE_DNSPYTHON)
|
60 |
| -from mysql.connector.errors import InterfaceError |
| 61 | +from mysql.connector.errors import InterfaceError, ProgrammingError |
61 | 62 | from mysql.connector.optionfiles import read_option_files
|
62 | 63 | from mysql.connector.network import TLS_V1_3_SUPPORTED
|
63 | 64 | from mysql.connector.utils import linux_distribution
|
@@ -2531,6 +2532,170 @@ def test_connect_with_can_handle_expired_pw_flag(self):
|
2531 | 2532 | _ = self.cnx.__class__(**cnx_config)
|
2532 | 2533 |
|
2533 | 2534 |
|
| 2535 | +@unittest.skipIf(tests.MYSQL_VERSION < (5, 7), |
| 2536 | + "Authentication with ldap_simple not supported") |
| 2537 | +@unittest.skipIf(not tests.is_plugin_available("authentication_ldap_simple"), |
| 2538 | + "Plugin authentication_ldap_simple not available") |
| 2539 | +#Skip if remote ldap server is not reachable. |
| 2540 | +@unittest.skipIf(not tests.is_host_reachable("100.103.18.98"), |
| 2541 | + "ldap server is not reachable") |
| 2542 | +class WL13994(tests.MySQLConnectorTests): |
| 2543 | + """WL#13994: Support clear text passwords |
| 2544 | + """ |
| 2545 | + def setUp(self): |
| 2546 | + self.server = tests.MYSQL_SERVERS[0] |
| 2547 | + self.server_cnf = self.server._cnf |
| 2548 | + self.config = tests.get_mysql_config() |
| 2549 | + self.config.pop("unix_socket", None) |
| 2550 | + |
| 2551 | + self.host = "%" |
| 2552 | + |
| 2553 | + cnx = connection.MySQLConnection(**self.config) |
| 2554 | + ext = "dll" if os.name == "nt" else "so" |
| 2555 | + plugin_name = "authentication_ldap_simple.{}".format(ext) |
| 2556 | + |
| 2557 | + ldap_simple_config = { |
| 2558 | + "plugin-load-add": plugin_name, |
| 2559 | + "authentication_ldap_simple_auth_method_name": "simple", |
| 2560 | + "authentication_ldap_simple_bind_base_dn": '"dc=MYSQL,dc=local"', |
| 2561 | + "authentication_ldap_simple_init_pool_size": 1, |
| 2562 | + "authentication_ldap_simple_bind_root_dn": "", |
| 2563 | + "authentication_ldap_simple_bind_root_pwd": "", |
| 2564 | + "authentication_ldap_simple_ca_path": '""', |
| 2565 | + "authentication_ldap_simple_log_status": 6, |
| 2566 | + "authentication_ldap_simple_server_host": "100.103.18.98", |
| 2567 | + "authentication_ldap_simple_user_search_attr": "cn", |
| 2568 | + "authentication_ldap_simple_group_search_attr": "cn", |
| 2569 | + } |
| 2570 | + cnf = "\n# ldap_simple" |
| 2571 | + for key in ldap_simple_config: |
| 2572 | + cnf = "{}\n{}={}".format(cnf, key, ldap_simple_config[key]) |
| 2573 | + self.server_cnf += cnf |
| 2574 | + |
| 2575 | + cnx.close() |
| 2576 | + self.server.stop() |
| 2577 | + self.server.wait_down() |
| 2578 | + |
| 2579 | + self.server.start(my_cnf=self.server_cnf) |
| 2580 | + self.server.wait_up() |
| 2581 | + sleep(1) |
| 2582 | + |
| 2583 | + cnx = connection.MySQLConnection(**self.config) |
| 2584 | + |
| 2585 | + identified_by = "CN=test1,CN=Users,DC=mysql,DC=local" |
| 2586 | + |
| 2587 | + cnx.cmd_query("CREATE USER '{}'@'{}' IDENTIFIED " |
| 2588 | + "WITH authentication_ldap_simple AS" |
| 2589 | + "'{}'".format(self.user, self.host, identified_by)) |
| 2590 | + cnx.cmd_query("GRANT ALL ON *.* TO '{}'@'{}'" |
| 2591 | + "".format(self.user, self.host)) |
| 2592 | + cnx.cmd_query("FLUSH PRIVILEGES") |
| 2593 | + cnx.close() |
| 2594 | + |
| 2595 | + def tearDown(self): |
| 2596 | + cnx = connection.MySQLConnection(**self.config) |
| 2597 | + try: |
| 2598 | + cnx.cmd_query("DROP USER '{}'@'{}'".format(self.user, self.host)) |
| 2599 | + except: |
| 2600 | + pass |
| 2601 | + cnx.cmd_query("UNINSTALL PLUGIN authentication_ldap_simple") |
| 2602 | + cnx.cmd_query('show variables like "have_ssl"') |
| 2603 | + res = cnx.get_rows()[0][0] |
| 2604 | + cnx.close() |
| 2605 | + if res == ('have_ssl', 'DISABLED'): |
| 2606 | + self._enable_ssl() |
| 2607 | + |
| 2608 | + def _disable_ssl(self): |
| 2609 | + self.server.stop() |
| 2610 | + self.server.wait_down() |
| 2611 | + |
| 2612 | + self.server.start(ssl_ca='', ssl_cert='', ssl_key='', ssl=0, |
| 2613 | + my_cnf=self.server_cnf) |
| 2614 | + self.server.wait_up() |
| 2615 | + sleep(1) |
| 2616 | + cnx = connection.MySQLConnection(**self.config) |
| 2617 | + cnx.cmd_query('show variables like "have_ssl"') |
| 2618 | + res = cnx.get_rows()[0][0] |
| 2619 | + self.assertEqual(res, ('have_ssl', 'DISABLED'), |
| 2620 | + "can not dissable ssl: {}".format(res)) |
| 2621 | + |
| 2622 | + def _enable_ssl(self): |
| 2623 | + self.server.stop() |
| 2624 | + self.server.wait_down() |
| 2625 | + self.server.start() |
| 2626 | + self.server.wait_up() |
| 2627 | + sleep(1) |
| 2628 | + |
| 2629 | + @tests.foreach_cnx() |
| 2630 | + def test_clear_text_pass(self): |
| 2631 | + """test_clear_text_passwords_without_secure_connection""" |
| 2632 | + conn_args = { |
| 2633 | + |
| 2634 | + "host": self.config["host"], |
| 2635 | + "port": self.config["port"], |
| 2636 | + "password": "Testpw1", |
| 2637 | + "auth_plugin": "mysql_clear_password", |
| 2638 | + } |
| 2639 | + |
| 2640 | + # Atempt connection with wrong password |
| 2641 | + bad_pass_args = conn_args.copy() |
| 2642 | + bad_pass_args["password"] = "wrong_password" |
| 2643 | + with self.assertRaises(ProgrammingError) as context: |
| 2644 | + _ = self.cnx.__class__(**bad_pass_args) |
| 2645 | + self.assertIn("Access denied for user", context.exception.msg, |
| 2646 | + "not the expected error {}".format(context.exception.msg)) |
| 2647 | + |
| 2648 | + # connect using mysql clear password and ldap simple auth method |
| 2649 | + cnx = self.cnx.__class__(**conn_args) |
| 2650 | + cnx.cmd_query('SELECT USER()') |
| 2651 | + res = cnx.get_rows()[0][0][0] |
| 2652 | + self.assertIn(self.user, res, "not the expected user {}".format(res)) |
| 2653 | + cnx.close() |
| 2654 | + |
| 2655 | + # Disabling ssl must raise an error. |
| 2656 | + conn_args["ssl_disabled"] = True |
| 2657 | + with self.assertRaises(InterfaceError) as context: |
| 2658 | + _ = self.cnx.__class__(**conn_args) |
| 2659 | + self.assertEqual("Clear password authentication is not supported over " |
| 2660 | + "insecure channels", context.exception.msg, |
| 2661 | + "Unexpected exception message found: {}" |
| 2662 | + "".format(context.exception.msg)) |
| 2663 | + |
| 2664 | + # Unix socket is used in unix by default if not popped or set to None |
| 2665 | + conn_args["unix_socket"] = tests.get_mysql_config().get("unix_socket", None) |
| 2666 | + with self.assertRaises(InterfaceError) as context: |
| 2667 | + _ = self.cnx.__class__(**conn_args) |
| 2668 | + self.assertEqual("Clear password authentication is not supported over " |
| 2669 | + "insecure channels", context.exception.msg, |
| 2670 | + "Unexpected exception message found: {}" |
| 2671 | + "".format(context.exception.msg)) |
| 2672 | + |
| 2673 | + # Attempt connection with verify certificate set to True |
| 2674 | + conn_args.pop("ssl_disabled") |
| 2675 | + conn_args.pop("unix_socket") |
| 2676 | + conn_args.update({ |
| 2677 | + 'ssl_ca': os.path.abspath( |
| 2678 | + os.path.join(tests.SSL_DIR, 'tests_CA_cert.pem')), |
| 2679 | + 'ssl_cert': os.path.abspath( |
| 2680 | + os.path.join(tests.SSL_DIR, 'tests_client_cert.pem')), |
| 2681 | + 'ssl_key': os.path.abspath( |
| 2682 | + os.path.join(tests.SSL_DIR, 'tests_client_key.pem')), |
| 2683 | + }) |
| 2684 | + conn_args["ssl_verify_cert"] = True |
| 2685 | + cnx = self.cnx.__class__(**conn_args) |
| 2686 | + cnx.cmd_query('SELECT USER()') |
| 2687 | + res = cnx.get_rows()[0][0][0] |
| 2688 | + self.assertIn(self.user, res, "not the expected user {}".format(res)) |
| 2689 | + cnx.close() |
| 2690 | + |
| 2691 | + if CMySQLConnection is not None and isinstance(cnx, CMySQLConnection): |
| 2692 | + # Not testing cext without ssl |
| 2693 | + return |
| 2694 | + self._disable_ssl() |
| 2695 | + # Error must be raised to avoid send the password insecurely |
| 2696 | + self.assertRaises(InterfaceError, self.cnx.__class__, **conn_args) |
| 2697 | + |
| 2698 | + |
2534 | 2699 | class WL13334(tests.MySQLConnectorTests):
|
2535 | 2700 | """WL#13334: Failover and multihost
|
2536 | 2701 | """
|
|
0 commit comments