You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@qpid.apache.org by AiO <ai...@aio.nu> on 2018/08/30 08:30:32 UTC

Problems with SASL and a simple client/server written in C

Hey!

This is regarding the Qpid Proton C-API and version 0.24.0 and Cyrus SASL 
2.1.26-21 running on CentOS7.

I am new to the AMQP world, hance also to Qpid Proton. I am looking into 
implementing a good single-sign-on solution using Kerberos GSSAPI between 
two very simple softwares as a proof of concept. I am on the other 
hand not new to MIT Kerberos and GSSAPI. So.. Here we go: There is a small
qpid-dispatch-like software as server and a small client connecting to it 
and a heartbeat is received by the client. This works without SASL.

The server was previously written in an way that the transport was handled 
and set-up by a "proactor". I now have the transport initialization in the 
set-up/init of the "container" implementation, to be able to configure the 
SASL-related stuff on the transport before the sockets start opening and 
such. For this transport connection I use pn_proactor_connect2(). It seems 
this modification also works without SASL.

However... I am quite confused - Maybe it's just my understanding of the 
concepts of AMQP that fail, or Cyrus SASL - Maybe both.

In the IT-environment I am expermementing on I have written very simple 
similar client/server solutions using GSSAPI straight off and it works. 
The Cyrus SASL sample-server/sample-client also works. The Kerberos 
single-sign-on authentication works as expected. And I have set-up a 
keytab (and verified that it works with my pure GSSAPI-example) for the 
amqp/my_hostname@MY_REALM.COM principle. Happy times!!!!

I guess, rather than explaining everything in detail trying to debug my 
crappy implemenation - What I am really asking for is a working example 
client/server that use SASL and GSSAPI which would be quite helpful and 
meaningful for others too, i guess. Maybe more effective?

Can some clever person please enlighten me?

I've come so far that the server and the client agree to use SASL and I 
can see that the transport (at least on the server-side) is reused 
Suprisingly both server and client agree to go for SASL. Then everything 
breaks down in "no worthy mechs". And connection is broken/out-of sync.

I do try to allocate pn_transport() in both the client and the server at a 
very early stage.

The gssapi and client variables originate from environment 
variables just to be able to run the same code with different 
authentication models for now.

Client and server common code:

   /*
    * Allocation/initialization (constructor if you'd like) where I keep
    * track of allocated things for a container instance.
    */
   container->transport = pn_transport();
   if (gssapi) {
     if (client) {
       container->sasl = init_client_single_sign_on(container->transport);
     }
     else {
       container->sasl = init_server_single_sign_on(container->transport);
     }
   }

Connecting the container looks somewhat like this:

   char a[PN_MAX_ADDR];
   pn_proactor_addr(a, sizeof(a), "my_hostname", "amqp");
   pn_proactor_connect2(container->proactor,
                        connection->impl,
                        container->transport,
                        a);

Client init:

   pn_sasl_t* s = pn_sasl(t);
   pn_sasl_allowed_mechs(s, "GSSAPI");
   return s;

Server init:

   pn_transport_set_server(t);
   pn_sasl_t* s = pn_sasl(t);
   /*
    * Weird way to find my sasl-config file in current dir AND the
    * CyrusSASL mechanism plugins. (Verified with strace)
    */
   pn_sasl_config_path(s, ".:/usr/lib64/sasl2"); /* TODO: dont hardcode */
   pn_sasl_config_name(s, "my-server");
   /*
    * Regardless: Only allow GSSAPI and require authentication.
    */
   pn_sasl_allowed_mechs(s, "GSSAPI");
   pn_transport_require_auth(t, true);
   pn_sasl_set_allow_insecure_mechs(s, false);
   return s;

my-server.conf:

   keytab: /path/to/my/keytab/the/user/can/access/amqp.keytab
   mech: GSSAPI
   realm: MY_REALM.COM

I don't realy know which of these Cyrus SASL make use of, since I (from my 
point of view) overriede "mech" in the code and "realm" should be comming 
from /etc/krb5.conf in my humble oppinion.

And in the container-code most events are basically empty... I would 
suspect that SASL should do the negotiation and at some point end up in 
some part of the state-machine... Let's say: PN_TRANSPORT_AUTHENTICATED. 
But i get stuck in PN_CONNECTION_BOUND and all hell breaks loose.

Is there something additional i have to do in the state-machine?

And the weird part is that I _currently_ get:

@sasl-mechanisms(64) [sasl-server-mechanisms=@PN_SYMBOL[:"SCRAM-SHA-1", 
:GSSAPI, :"GSS-SPNEGO", :"DIGEST-MD5", :"CRAM-MD5", :ANONYMOUS]]

... Wich seem to be way too many.

Server debug-stuff:

DEBUG: START contructor transport: 0x15a34a0
DEBUG: Setting up server single-sign-on for transport 0x15a34a0 and SASL 0x15a34a0
[0x15b16e0]:(PN_CONNECTION_INIT, pn_connection<0x15b0650>)
[0x15b16e0]:(PN_CONNECTION_BOUND, pn_connection<0x15b0650>)
DEBUG: check_condition() transport 0x15b16e0
DEBUG: PN_CONNECTION_BOUND transport 0x15b16e0
[0x15b16e0]:AMQP SASL layer detected
[0x15b16e0]:  <- SASL
[0x15b16e0]:  -> SASL
[0x15b16e0]:0 -> @sasl-mechanisms(64) 
[sasl-server-mechanisms=@PN_SYMBOL[:"SCRAM-SHA-1", :GSSAPI, :"GSS-SPNEGO", 
:"DIGEST-MD5", :"CRAM-MD5", :ANONYMOUS]]
[0x15b16e0]:RAW: 
"\x00\x00\x00l\x02\x01\x00\x00\x00S@\xd0\x00\x00\x00\\x00\x00\x00\x01\xf0\x00\x00\x00S\x00\x00\x00\x06\xb3\x00\x00\x00\x0bSCRAM-SHA-1\x00\x00\x00\x06GSSAPI\x00\x00\x00\x0aGSS-SPNEGO\x00\x00\x00\x0aDIGEST-MD5\x00\x00\x00\x08CRAM-MD5\x00\x00\x00\x09ANONYMOUS"
[0x15b16e0]:(PN_TRANSPORT, pn_transport<0x15b16e0>)
[0x15b16e0]:ERROR amqp:connection:framing-error connection aborted
[0x15b16e0]:  <- EOS
[0x15b16e0]:  -> EOS
[0x15b16e0]:(PN_TRANSPORT_TAIL_CLOSED, pn_transport<0x15b16e0>)
[0x15b16e0]:(PN_TRANSPORT_ERROR, pn_transport<0x15b16e0>)
[0x15b16e0]:(PN_TRANSPORT_HEAD_CLOSED, pn_transport<0x15b16e0>)
[0x15b16e0]:(PN_TRANSPORT_CLOSED, pn_transport<0x15b16e0>)

Client debug-stuff:

DEBUG: START contructor transport: 0x247b500
DEBUG: Setting up client single-sign-on for transport 0x247b500 and SASL 
0x247b500
[0x247b500]:(PN_CONNECTION_INIT, pn_connection<0x2486af0>)
[0x247b500]:(PN_CONNECTION_LOCAL_OPEN, pn_connection<0x2486af0>)
DEBUG: check_condition() transport 0x247b500
[0x247b500]:(PN_SESSION_INIT, pn_session<0x248b290>)
[0x247b500]:(PN_LINK_INIT, pn_link<0x248c5f0>)
[0x247b500]:(PN_LINK_INIT, pn_link<0x248f160>)
[0x247b500]:(PN_SESSION_LOCAL_OPEN, pn_session<0x248b290>)
[0x247b500]:(PN_LINK_LOCAL_OPEN, pn_link<0x248c5f0>)
[0x247b500]:(PN_LINK_LOCAL_OPEN, pn_link<0x248f160>)
[0x247b500]:(PN_SESSION_INIT, pn_session<0x2491eb0>)
[0x247b500]:(PN_LINK_INIT, pn_link<0x2493210>)
[0x247b500]:(PN_SESSION_LOCAL_OPEN, pn_session<0x2491eb0>)
[0x247b500]:(PN_LINK_LOCAL_OPEN, pn_link<0x2493210>)
[0x247b500]:(PN_CONNECTION_BOUND, pn_connection<0x2486af0>)
DEBUG: check_condition() transport 0x247b500
[0x247b500]:  -> SASL
[0x247b500]:  <- SASL
[0x247b500]:0 <- @sasl-mechanisms(64) 
[sasl-server-mechanisms=@PN_SYMBOL[:"SCRAM-SHA-1", :GSSAPI, :"GSS-SPNEGO", 
:"DIGEST-MD5", :"CRAM-MD5", :ANONYMOUS]]
[0x247b500]:sasl error: SASL(-4): no mechanism available: No worthy mechs 
found
[0x247b500]:(PN_TRANSPORT, pn_transport<0x247b500>)
[0x247b500]:ERROR amqp:unauthorized-access Authentication failed 
[mech=none]
[0x247b500]:  -> EOS
[0x247b500]:(PN_TRANSPORT_ERROR, pn_transport<0x247b500>)
[0x247b500]:(PN_TRANSPORT_TAIL_CLOSED, pn_transport<0x247b500>)
[0x247b500]:(PN_TRANSPORT_HEAD_CLOSED, pn_transport<0x247b500>)
[0x247b500]:(PN_TRANSPORT_CLOSED, pn_transport<0x247b500>)
Segmentation fault

... Heh, nice ending there :) Probably not related.

I get this on both sides... At some point earlier I did only get GSSAPI in 
that list. But still "no worthy mechs" error.

I hope someone can spread some light on my plight to secure this 
implementation. Please let me know if more information is needed too.

Kind regards,
AiO

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@qpid.apache.org
For additional commands, e-mail: users-help@qpid.apache.org


Re: Problems with SASL and a simple client/server written in C

Posted by AiO <ai...@aio.nu>.
Addendum:

Now I also noticed that the transport changed from the server-init to 
PN_CONNECITON_INIT... I realized i used the wrong pn_listener_accept() as 
well... So now I use (in the PN_LISTENER_ACCEPT event:

   container->connection = pn_connection();
   pn_listener_accept2(pn_event_listener(event), container->connection, 
container->transport);

... I did have it like this before the state I had when I wrote my 
original mail, but missed that code.

Now the negotiation halts and both ends halt on epoll_wait() and neither 
side will complete the negotiation.. a small correction to my initial 
question follows:

It's improtant that you have all the correct info.


On Thu, 30 Aug 2018, AiO wrote:

> Server debug-stuff:
>
> DEBUG: START contructor transport: 0x15a34a0
> DEBUG: Setting up server single-sign-on for transport 0x15a34a0 and SASL 
> 0x15a34a0
> [0x15b16e0]:(PN_CONNECTION_INIT, pn_connection<0x15b0650>)

<snip> - As you can see 0x15a34a0 was unused but 0x15b16e0 was created by 
the pn_listener_accept()... Sorry about the confusion

> [0x15b16e0]:(PN_TRANSPORT_HEAD_CLOSED, pn_transport<0x15b16e0>)
> [0x15b16e0]:(PN_TRANSPORT_CLOSED, pn_transport<0x15b16e0>)

This is more like this now:

DEBUG: START contructor transport: 0x1d6f4a0
DEBUG: Setting up server single-sign-on for transport 0x1d6f4a0 and SASL 
0x1d6f4a0
[0x1d6f4a0]:(PN_CONNECTION_INIT, pn_connection<0x1d7bf30>)
[0x1d6f4a0]:(PN_CONNECTION_BOUND, pn_connection<0x1d7bf30>)
DEBUG: check_condition() transport 0x1d6f4a0
[0x1d6f4a0]:AMQP SASL layer detected
[0x1d6f4a0]:  <- SASL
[0x1d6f4a0]:  -> SASL

And also:

> Client debug-stuff:
>
> DEBUG: START contructor transport: 0x247b500
> DEBUG: Setting up client single-sign-on for transport 0x247b500 and SASL 
> 0x247b500
> [0x247b500]:(PN_CONNECTION_INIT, pn_connection<0x2486af0>)

<snip> Nothing really changed. The transport should be and is same

> [0x247b500]:(PN_TRANSPORT_HEAD_CLOSED, pn_transport<0x247b500>)
> [0x247b500]:(PN_TRANSPORT_CLOSED, pn_transport<0x247b500>)

DEBUG: START contructor transport: 0x2376500
DEBUG: Setting up client single-sign-on for transport 0x2376500 and SASL 
0x2376500
[0x2376500]:(PN_CONNECTION_INIT, pn_connection<0x2381af0>)
[0x2376500]:(PN_CONNECTION_LOCAL_OPEN, pn_connection<0x2381af0>)
DEBUG: check_condition() transport 0x2376500
[0x2376500]:(PN_SESSION_INIT, pn_session<0x2386290>)
[0x2376500]:(PN_LINK_INIT, pn_link<0x23875f0>)
[0x2376500]:(PN_LINK_INIT, pn_link<0x238a160>)
[0x2376500]:(PN_SESSION_LOCAL_OPEN, pn_session<0x2386290>)
[0x2376500]:(PN_LINK_LOCAL_OPEN, pn_link<0x23875f0>)
[0x2376500]:(PN_LINK_LOCAL_OPEN, pn_link<0x238a160>)
[0x2376500]:(PN_SESSION_INIT, pn_session<0x238ceb0>)
[0x2376500]:(PN_LINK_INIT, pn_link<0x238e210>)
[0x2376500]:(PN_SESSION_LOCAL_OPEN, pn_session<0x238ceb0>)
[0x2376500]:(PN_LINK_LOCAL_OPEN, pn_link<0x238e210>)
[0x2376500]:(PN_CONNECTION_BOUND, pn_connection<0x2381af0>)
DEBUG: check_condition() transport 0x2376500
[0x2376500]:  -> SASL
[0x2376500]:  <- SASL

That's more like I had it yesterday - And still as confusing... Why should 
both sides hang on epoll_wait() now?

Kind regards,
AiO

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@qpid.apache.org
For additional commands, e-mail: users-help@qpid.apache.org