Monday, May 14, 2007

Getting Subversion (neon) to work with Kerberos on SLES10

Just in case you were wondering why Subversion fails to authenticate against an Apache-based, Kerberos-enabled Subversion repository on SuSE Linux Enterprise Server 10...

$ svn info https://host/path/to/repository
svn: PROPFIND request failed on '/path/to/repository'
svn: PROPFIND of '/path/to/repository': authorization failed (https://host)

For one, SuSE packages a build of neon, the HTTP / WebDAV library the Subversion client uses, that was not configured with Kerberos support:

$ ldd /usr/lib64/libneon.so.24.0.7
libssl.so.0.9.8 => /usr/lib64/libssl.so.0.9.8 (0x00002b5f0548b000)
libcrypto.so.0.9.8 => /usr/lib64/libcrypto.so.0.9.8 (0x00002b5f055d1000)
libz.so.1 => /lib64/libz.so.1 (0x00002b5f05834000)
libexpat.so.1 => /usr/lib64/libexpat.so.1 (0x00002b5f05949000)
libc.so.6 => /lib64/libc.so.6 (0x00002b5f05a6c000)
libdl.so.2 => /lib64/libdl.so.2 (0x00002b5f05c9c000)
/lib64/ld-linux-x86-64.so.2 (0x0000555555554000)

So, by installing the neon source RPM, krb5-devel-1.4.3-19.10.3 and rebuilding the RPM using rpmbuild -bb SPECS/krb5.spec, problem #1 can be solved. Wait, the story isn't over yet.

The situation remains unchanged despite a Kerberos-enabled build:

$ svn info https://host/path/to/repository
svn: PROPFIND request failed on '/path/to/repository'
svn: PROPFIND of '/path/to/repository': authorization failed (https://host)

By enabling neon tracing (by modifying the Subversion 'servers' configuration) and adding additional traces, I found out that gss_init_sec_context fails with GSSAPI major and minor:

No context has been established. Validation error

I checked the Kerberos source:

/usr/src/packages/SOURCES/krb5-1.4.3/src/lib/gssapi/krb5/duplicate_name.c:

...
static OM_uint32
mutual_auth(
OM_uint32 *minor_status,
gss_ctx_id_t *context_handle,
gss_name_t target_name,
gss_OID mech_type,
OM_uint32 req_flags,
OM_uint32 time_req,
gss_channel_bindings_t input_chan_bindings,
gss_buffer_t input_token,
gss_OID *actual_mech_type,
gss_buffer_t output_token,
OM_uint32 *ret_flags,
OM_uint32 *time_rec,
krb5_context context)
{
...
/* validate the context handle */
/*SUPPRESS 29*/
if (! kg_validate_ctx_id(*context_handle)) {
*minor_status = (OM_uint32) G_VALIDATE_FAILED;
return(GSS_S_NO_CONTEXT);
}


There's the problem. gss_init_sec_context validates the input context handle, the validation fails. Looking at the neon source, the bug is obvious:

/usr/src/packages/SOURCES/neon-0.24.7/src/ne_auth.c:

static int
gssapi_challenge(auth_session *sess, struct auth_challenge *parms)
{
...
gss_ctx_id_t context;
gss_name_t server_name;
unsigned int major_status, minor_status;
gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER;
gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER;

clean_session(sess);


if (get_gss_name(&server_name, sess))
return -1;

major_status = gss_init_sec_context(&minor_status,
GSS_C_NO_CREDENTIAL,
&context,
server_name,
GSS_C_NO_OID,
0,
GSS_C_INDEFINITE,
GSS_C_NO_CHANNEL_BINDINGS,
&input_token,
NULL,
&output_token,
NULL,
NULL);

The neon developers forgot to initialize the local variable context with GSS_C_NO_CONTEXT, d'oh...
Apply the following patch to address this:

neon-0.24.7-krb5-auth.patch:

--- neon-0.24.7/src/ne_auth.c 2004-07-05 11:45:42.000000000 +0200
+++ neon-0.24.7-dev/src/ne_auth.c 2007-05-11 22:45:28.000000000 +0200
@@ -343,7 +343,7 @@
static int
gssapi_challenge(auth_session *sess, struct auth_challenge *parms)
{
- gss_ctx_id_t context;
+ gss_ctx_id_t context = GSS_C_NO_CONTEXT;
gss_name_t server_name;
unsigned int major_status, minor_status;
gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER;
@@ -924,15 +924,13 @@
success = 0;

#ifdef HAVE_GSSAPI

Quick Summary:

rpm -ihv neon-devel-0.24.7-20.2..rpm
rpm -ihv krb5-devel-1.4.3-19.2..rpm
Apply the aforementioned patch using patch -p1

It's official: nobody's using Kerberos. OK, just the SLES QA guys ain't... ;)

No comments: