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.
Eric Youngdale wrote:>debug1: An invalid name was supplied >A parameter was malformed >Validation error >...>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.gss_export_name() should work with any src_name returned by gss_accept_sec_context()... Whatversion of the MIT libraries do you have? The error appears to come not from a nametype check, but from a pointer validation: if (! kg_validate_name(input_name)) { if (minor_status) *minor_status = (OM_uint32) G_VALIDATE_FAILED; krb5_free_context(context); return(GSS_S_CALL_BAD_STRUCTURE|GSS_S_BAD_NAME); } Is it possible that the ctx->client pointer is getting mangled somehow? d -- David Leonard Vintela Resource Central software engineer Quest Software; 303 Adelaide St, Brisbane, Australia; www.quest.com Phone: (US) +1 801 655 2755 (AU) +61 7 3023 5133
[ cross-posted both to openssh-unix-dev and kerberos at mit.edu as this question has been asked on both lists ] The first and most important point to note here is that the problem you're seeing isn't a bug in OpenSSH - it's a problem with the libraries that your vendor is shipping, and in particular with the libgssapi package. On Mon, 27 Feb 2006, Eric Youngdale wrote> 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, > Later on (not much further later), ssh calls > > if ((ctx->major = gss_export_name(&ctx->minor, ctx->client, > > 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.GSSAPI is an IETF standard. If your GSSAPI library doesn't allow gss_export_name to be called with the client name returned by gss_accept_sec_context then it is broken. The type of the client name is, as others have noted on the Kerberos mailing list, opaque. An implementation can chose to make this whatever it likes, as long as that decision is consistent across every call. The OpenSSH code has been tested with (to my knowledge) GSSAPI implementations from MIT, Heimdal and Globus, and works correctly with all of these. SuSe 10 ships with a library called 'libgssapi', which isn't a Kerberos GSSAPI library at all (the Kerberos GSSAPI library from the MIT code is called libgssapi_krb5.so). It's a version of the 'mechglue' code which, I believe, CITI have packaged up to work with NFSv4. It acts as a 'shim' layer, allowing multiple different GSSAPI libraries to be used by the one application. Unfortunately this code has issues that are causing problems for a number of people trying to do GSSAPI on SuSE 10. Firstly, it calls exit() when it encounters problems - not particular great behaviour from a shared library. I first encountered this with Thunderbird's Kerberos support - both Thunderbird and Firefox now explicitly check for this library and don't use it if found. Secondly, as you've noted, its support for calling 'export_name' is broken. In fact, the version of the library that I have to hand doesn't even support export_name - so I suspect that you're falling back to using the native export_name provided by libgssapi_krb5, although I'm not familiar enough with the behaviour of Linux's linker to work out how. The short answer is - don't build OpenSSH against libgssapi - build it against the GSSAPI library (libgssapi_krb5) which ships with MIT Kerberos. File a bug with your vendor about the fact that they're shipping a broken GSSAPI library. I'll drop Kevin Coffman at UMICH a mail about this too. Cheers, Simon.