[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
GSSAPI + pserver + systemauth=no
From: |
jomarqua |
Subject: |
GSSAPI + pserver + systemauth=no |
Date: |
Tue, 17 Sep 2002 22:58:56 -0400 (EDT) |
CVS'ers
I noticed during my attempts to configure cvs 1.11.1p1 using
gssapi authentication and systemauth=no that it did not work as one might
expect from the documentation.
I am attaching a patch that changes the behavior - such that
gssapi authentication is now subject to the systemauth configuration and
the CVSROOT/passwd file. (This includes support for virtual users via the
passwd file remapping of usernames.)
I submit this for suggestions on how to make it better - i am concerned
about the addition of a new function gssapi_check_password() - i feel that
there should be a better method of integrating this functionality with the
normal check_password function. If anyone has sugegstions about how to
better clean that up, I would be delighted to resubmit this patch with
modifications to the News file, and other suggestions in the HACKING file.
Thanks ever so much for a fabulous product!
-VaiX
--------------SNIP--------------
diff -rU 5 cvs-1.11.2/src/client.c j.cvs2/src/client.c
--- cvs-1.11.2/src/client.c Thu Aug 9 16:27:26 2001
+++ j.cvs2/src/client.c Tue Sep 17 20:05:27 2002
@@ -4236,10 +4236,18 @@
str = "BEGIN GSSAPI REQUEST\012";
if (send (sock, str, strlen (str), 0) < 0)
error (1, 0, "cannot send: %s", SOCK_STRERROR (SOCK_ERRNO));
+ if (send (sock, current_parsed_root->directory, strlen
(current_parsed_root->directory), 0) < 0)
+ error (1, 0, "cannot send: %s", SOCK_STRERROR (SOCK_ERRNO));
+
+ str = "\012";
+
+ if (send (sock, str, strlen (str), 0) < 0)
+ error (1, 0, "cannot send: %s", SOCK_STRERROR (SOCK_ERRNO));
+
if (strlen (hostinfo->h_name) > BUFSIZE - 5)
error (1, 0, "Internal error: hostname exceeds length of buffer");
sprintf (buf, "cvs@%s", hostinfo->h_name);
tok_in.length = strlen (buf);
tok_in.value = buf;
diff -rU 5 cvs-1.11.2/src/server.c j.cvs2/src/server.c
--- cvs-1.11.2/src/server.c Tue Mar 19 14:15:45 2002
+++ j.cvs2/src/server.c Tue Sep 17 20:03:37 2002
@@ -31,11 +31,11 @@
# include <krb5.h>
/* We need this to wrap data. */
static gss_ctx_id_t gcontext;
-static void gserver_authenticate_connection PROTO((void));
+static void gserver_authenticate_connection PROTO((char *));
/* Whether we are already wrapping GSSAPI communication. */
static int cvs_gssapi_wrapping;
# ifdef ENCRYPTION
@@ -5437,10 +5437,11 @@
fp = CVS_FOPEN (filename, "r");
if (fp == NULL)
{
if (!existence_error (errno))
error (0, errno, "cannot open %s", filename);
+ error (0, errno, "cannot open %s", filename);
return 0;
}
/* Look for a relevant line -- one with this user's name. */
namelen = strlen (username);
@@ -5674,10 +5675,55 @@
}
return host_user;
}
+
+
+
+/* Return a hosting username if password matches, else NULL. */
+static char *
+gssapi_check_password (username, password, repository)
+ char *username, *password, *repository;
+{
+
+
+ int rc;
+ char *host_user = NULL;
+
+ /* We see if this user has a password in the CVS-specific
+ * password file. If so, that's enough to authenticate
with. */
+
+ rc = check_repository_password (username, password, repository,
+ &host_user);
+
+ if (rc == 2)
+ return NULL;
+
+ /* else */
+
+ if (rc == 1)
+ {
+ /* host_user already set by reference, so just return. */
+ goto handle_return;
+ }
+ if (rc == 0 )
+ error (1, 0, "GSSAPI authentication failed");
+
+
+handle_return:
+ if (host_user)
+ {
+ /* Set CVS_Username here, in allocated space.
+ * It might or might not be the same as host_user. */
+ CVS_Username = xmalloc (strlen (username) + 1);
+ strcpy (CVS_Username, username);
+ }
+
+ return host_user;
+}
+
#endif /* AUTH_SERVER_SUPPORT */
#if defined (AUTH_SERVER_SUPPORT) || defined (HAVE_GSSAPI)
/* Read username and password from client (i.e., stdin).
@@ -5774,11 +5820,28 @@
;
else if (strcmp (tmp, "BEGIN GSSAPI REQUEST\n") == 0)
{
#ifdef HAVE_GSSAPI
free (tmp);
- gserver_authenticate_connection ();
+
+ getline_safe (&repository, &repository_allocated, stdin, PATH_MAX);
+ strip_trailing_newlines (repository);
+
+ if (!root_allow_ok (repository))
+ {
+ printf ("error 0 %s: no such repository\n", repository);
+#ifdef HAVE_SYSLOG_H
+ syslog (LOG_DAEMON | LOG_NOTICE, "login refused for %s", repository);
+#endif
+ goto i_hate_you;
+ }
+
+
+ gserver_authenticate_connection (repository);
+
+
+
return;
#else
error (1, 0, "GSSAPI authentication not supported by this server");
#endif
}
@@ -5980,21 +6043,26 @@
/* Authenticate a GSSAPI connection. This is called from
pserver_authenticate_connection, and it handles success and failure
the same way. */
static void
-gserver_authenticate_connection ()
+gserver_authenticate_connection (repository)
+
+ char *repository;
+
{
char hostname[MAXHOSTNAMELEN];
struct hostent *hp;
gss_buffer_desc tok_in, tok_out;
char buf[1024];
OM_uint32 stat_min, ret;
gss_name_t server_name, client_name;
gss_cred_id_t server_creds;
int nbytes;
gss_OID mechid;
+ char *host_user = NULL;
+
gethostname (hostname, sizeof hostname);
hp = gethostbyname (hostname);
if (hp == NULL)
error (1, 0, "can't get canonical hostname");
@@ -6051,20 +6119,38 @@
We could instead use an authentication to access mapping. */
{
krb5_context kc;
krb5_principal p;
gss_buffer_desc desc;
+
krb5_init_context (&kc);
if (gss_display_name (&stat_min, client_name, &desc,
- &mechid) != GSS_S_COMPLETE
+ &mechid) != GSS_S_COMPLETE
|| krb5_parse_name (kc, ((gss_buffer_t) &desc)->value, &p) != 0
- || krb5_aname_to_localname (kc, p, sizeof buf, buf) != 0
- || krb5_kuserok (kc, p, buf) != TRUE)
+ || krb5_aname_to_localname (kc, p, sizeof buf, buf) != 0 )
{
error (1, 0, "access denied");
}
+
+ parse_config (repository);
+
+ if ( system_auth && krb5_kuserok (kc, p, buf) != TRUE )
+ {
+ error (1, 0, "access denied");
+ }
+
+ if ( ! system_auth )
+ {
+ host_user = gssapi_check_password (buf, "", repository);
+
+ if ( host_user == NULL )
+ {
+ error (1, 0, "access denied");
+ }
+ }
+
krb5_free_principal (kc, p);
krb5_free_context (kc);
}
if (tok_out.length != 0)
@@ -6077,11 +6163,15 @@
|| (fwrite (tok_out.value, 1, tok_out.length, stdout)
!= tok_out.length))
error (1, errno, "fwrite failed");
}
- switch_to_user (buf);
+
+ if ( system_auth )
+ switch_to_user (buf);
+ else
+ switch_to_user (host_user);
printf ("I LOVE YOU\n");
fflush (stdout);
}