Just to update on this, I have included both sources (cyrus_sasl.c and cyrus_stub.c) and it works as expected.
Cheers Andrew North SOFTWARE ENGINEER From: Andrew North Sent: Monday, June 10, 2024 3:57 PM To: users@qpid.apache.org Subject: Is SASL_SSL enforced with qpid-proton when CyrusSASL dependency is used Hi, I've been using qpid-proton 0.39 C/C++, I have been testing with an extended version of the samples. I'm sending secure messages and authenticating connections with SSL certificates I have generated manually connecting to a RabbitMQ broker. I've validated the certificates and connections using openssl on the terminal and using qpid-proton samples. I'm using both OpenSSL and CyrusSASL dependencies. I have a "bug" perhaps in configuration of my client, where when I enable the dependency for cyrus-sasl.c over the cyrus-stub.c, I am no longer able to authenticate using "PLAIN", and my default connection is forcing "EXTERNAL" SASL mechanism even if explicitly set it to false in connection options. Below are some snippets from my tests: This is my dummy_client """ class dummy_client : public proton::messaging_handler { public: void on_container_start(proton::container& c) override { proton::connection_options client_opts; client_opts.handler(*this); if(this->_use_auth){ client_opts.user(this->_user); client_opts.password(this->_password); } client_opts.sasl_enabled(false); if(this->_use_ssl) { std::string client_cert = this->_cert_dir + "client-cert.pem"; std::string client_key = this->_cert_dir + "client-key.pem"; std::string client_pw = "password"; std::string client_ca = this->_cert_dir + "ca-cert.pem"; proton::ssl_certificate ssl_cert(client_cert, client_key, client_pw); proton::ssl_client_options ssl_client_opts(ssl_cert, client_ca, proton::ssl::VERIFY_PEER); if(this->_use_sasl){ client_opts.sasl_enabled(true); client_opts.ssl_client_options(ssl_client_opts).sasl_allowed_mechs(this->_sasl_mech); } else { client_opts.ssl_client_options(ssl_client_opts); } } if(this->_sasl_mech == "INSECURE") { client_opts.sasl_allow_insecure_mechs(true); } proton::sender s = c.open_sender(this->_url + "/" + this->_address, client_opts); } void on_sendable(proton::sender& s) override { proton::message m; m.body("Hello World!"); s.send(m); s.close(); } } """ Simplified test logic: """ { dummy_client client; proton::container container(client); local_thread = std::jthread([&](){ container.run(); }); std::this_thread::sleep_for(std::chrono::microseconds(wait_sec*1000000)); if (local_thread.joinable()) { container.stop(); local_thread.join(); } } """ I have multiple tests with the following configurations: * _url=target_ip:{5672,5671} * _address=test_NN * _use_auth={true,false} * _user={guest,new_user} * _password={guest,password} * _use_ssl={true,false} * _use_sasl={true,false} * _sasl_mech={"INSECURE","PLAIN","EXTERNAL"} I have run the tests in 4 different scenarios, below are the results: * Using one of these two dependencies {cyrus_stub.c, cyrus_sasl.c} * RabbitMQ - SASL_SSL authentication {on, off} port use_auth user password use_ssl use_sasl sasl_mech result w/plugin w/cyrus_stub.c result wo/plugin w/cyrus_stub.c result w/plugin w/cyrus_sasl.c result wo/plugin w/cyrus_sasl.c 5672 - - - - - - PASS PASS PASS PASS 5672 X guest guest - - - PASS PASS FAIL - SASL error (-4) FAIL - SASL error (-4) 5672 X new_user password - - - PASS PASS FAIL - SASL error (-4) FAIL - SASL error (-4) 5671 - - - X - "INSECURE" ERROR PASS PASS FAIL - SASL error (-4) 5671 X guest guest X - "INSECURE" ERROR PASS PASS FAIL - SASL error (-4) 5671 X new_user password X - "INSECURE" ERROR PASS PASS FAIL - SASL error (-4) 5671 - - - X - - ERROR PASS PASS FAIL - SASL error (-4) 5671 X guest guest X - - ERROR PASS PASS FAIL - SASL error (-4) 5671 X new_user password X - - ERROR PASS PASS FAIL - SASL error (-4) 5671 X guest guest X X "PLAIN" PASS PASS FAIL - SASL error (-4) FAIL - SASL error (-4) 5671 - - - X X "PLAIN" FAIL - auth mech=none FAIL - auth mech=none FAIL - SASL error (-4) FAIL - SASL error (-4) 5671 X guest guest X X "EXTERNAL" PASS FAIL - auth mech=none PASS FAIL - auth 5671 - - - X X "EXTERNAL" PASS FAIL - auth mech=none PASS FAIL - auth Summary of results using cyrus_stub.c: * Can always connect and send unsecure messages with no configuration set (assuming this means "ANONYMOUS") * RabbitMQ NOT Using SASL_SSL: * Can connect and send unsecure messages via port 5672, even with user credentials * Can connect and send secure messages via port 5671, even with user credentials * Can authenticate using "PLAIN" SASL * Fails to authenticate using "EXTERNAL" assumed to be SASL_SSL authentication * RabbitMQ Using SASL_SSL: * Can connect and send unsecure messages via port 5672, even with user credentials * Can't connect and send secure messages via port 5671 * Can authenticate using "PLAIN" SASL, and send secure messages via port 5671 * Can authenticate using "EXTERNAL", assumed to be SASL_SSL authentication and send secure messages via port 5671 Summary of results using cyrus_sasl.c: * Can always connect and send unsecure messages with no configuration set (assuming this means "ANONYMOUS") * RabbitMQ NOT Using SASL_SSL: * Can't connect or send unsecure/secure message via ports 5672/5671, with or without user credentials * Can't authenticate using "PLAIN" SASL * Fails to authenticate using "EXTERNAL" assumed to be SASL_SSL authentication * Always assumes SASL is using "EXTERNAL" mech when sasl is explicitly disabled using "client_opts.sasl_enabled(false);" * RabbitMQ Using SASL_SSL: * Can't connect and send unsecure messages via port 5672, even with user credentials * Can connect and send secure messages via port 5671 - but transport assumes use of "EXTERNAL" mech. * Can't authenticate using "PLAIN" SASL * Can authenticate using "EXTERNAL", assumed to be SASL_SSL authentication and send secure messages via port 5671 Let me know if you can see the formatted results as a table, I also have the following questions: * Are we forced to use SASL authentication if we use dependency cyrus_sasl.c as opposed to cyrus_stub.c? * Is there a configuration I am doing by mistake? * Can a client be configured to open a container with "PLAIN" authentication, and a second container be opened with "EXTERNAL" or "NONE" depending on other log If you have any suggestions or further clarity regarding above, that would be great thanks. I will continue to experiment with what I have. Kind Regards, Andrew