Bug in Kerberos support for openssh.

Eric Youngdale eric at andante.org
Tue Feb 28 02:39:45 EST 2006


It took me a while to track this down.  I am using MIT Kerberos 1.4.3 
and libgssapi-0.7.  With some patches that came with Suse 10, but that 
doesn't appear to be relevant.  I have been using openssh-4.2p1 (with 
Simon's patches) and openssh-4p3p2 out of the box.  I see the same 
problem no matter which version of openssh I am using.  I am using two 
Suse Linux x86 boxes as a test environment, and was able to reproduce 
the problem there.  The KDC is a Windows Server 2003 box, but that 
probably isn't relevant.

The failure mode is that when I connect using ssh, the connection gets 
set up most of the way.  It finds something it doesn't like, and then 
tears down the connection.  In the server logs, I would see messages 
like this:

debug1: userauth-request for user vatester service ssh-connection method 
gssapi-with-mic
debug1: attempt 1 failures 1
debug2: input_userauth_request: try method gssapi-with-mic
Postponed gssapi-with-mic for vatester from 10.18.3.52 port 1960 ssh2
debug1: Got no client credentials
debug1: An invalid name was supplied
A parameter was malformed
Validation error

Couldn't convert client name
debug1: do_cleanup

I spent some time in the debugger, and found that essentially the 
problem was that ssh is calling

   ctx->major = gss_accept_sec_context(&ctx->minor,
       &ctx->context, ctx->creds, recv_tok,
       GSS_C_NO_CHANNEL_BINDINGS, &ctx->client, &mech,
       send_tok, flags, NULL, &ctx->client_creds);

and saving off ctx->client for later use.  Under the hood, ctx->client 
is simply a gss_union_name_t.

Later on (not much further later), ssh calls

        if ((ctx->major = gss_export_name(&ctx->minor, ctx->client,
            &ename))) {
                ssh_gssapi_error(ctx);
                return (ctx->major);
        }

Here ctx->client is passed in but gss_export_name assumes that the input 
name is a krb5_principal.  Not surprisingly, the datatype mismatch 
causes the call to fail.  Could have caused it to crash, I suppose - 
that would have been a much clearer indication of what the trouble was.

I did manage to hack the thing to work - I first hacked libgssapi.so to 
include a new function:

OM_uint32 KRB5_CALLCONV
gss_hack_ssh_to_fix_stupid_bug(minor_status,
                               input_name,
                               output_name)
OM_uint32 *             minor_status;
gss_name_t              input_name;
gss_name_t *            output_name;
{
    gss_union_name_t    union_name;

        union_name = (gss_union_name_t) input_name;
        *output_name = union_name->mech_name;
        return 0;
}

and then hacked gss-serv.c to have this:

#if 0
        /* FIXME(eric) - this is the wrong type for this type of
         * lookup.
         */
        if ((ctx->major = gss_export_name(&ctx->minor, ctx->client,
            &ename))) {
                ssh_gssapi_error(ctx);
                return (ctx->major);
        }
#else
        {
                extern gss_hack_ssh_to_fix_stupid_bug(OM_uint32 * 
minor_status,
                               gss_name_t input_name,
                               gss_name_t *output_name);

                void * pname;

                gss_hack_ssh_to_fix_stupid_bug(NULL, ctx->client, &pname);
                if ((ctx->major = gss_export_name(&ctx->minor, pname,
                    &ename))) {
                        ssh_gssapi_error(ctx);
                        return (ctx->major);
                }
        }
#endif

With these two changes, ssh is now able to authenticate with Kerberos, 
and I get a nice shell prompt on the remote machine.  Server logs look 
good too:

WARNING: /usr/local/etc/moduli does not exist, using fixed modulus
Authorized to vatester, krb5 principal vatester at VADEV.COM (krb5_kuserok)
Accepted gssapi-with-mic for vatester from 10.18.3.52 port 2729 ssh2

I honestly have no clue how this could have ever have worked - my guess 
is that at one point in the past libgssapi didn't use the 
gss_union_name_t, and just used krb5_principal as a return parameter 
from gss_accept_sec_context().  I leave it to the people who know the 
history of this thing, and who better understand the intent of the 
original code to best figure out how to fix this.






More information about the openssh-unix-dev mailing list