--- cups-1.2.8/cups/auth.c.scm_credentials 2007-01-10 16:48:37.000000000 +0000 +++ cups-1.2.8/cups/auth.c 2007-03-09 17:02:06.000000000 +0000 @@ -26,6 +26,8 @@ * Contents: * * cupsDoAuthentication() - Authenticate a request. + * cups_peercred_auth() - Find out if SO_PEERCRED authentication + * is possible * cups_local_auth() - Get the local authorization certificate if * available/applicable... */ @@ -40,7 +42,9 @@ #include #include #include +#include #include +#include #if defined(WIN32) || defined(__EMX__) # include #else @@ -177,6 +181,59 @@ return (0); } +/* + * 'cups_peercred_auth()' + * - UNIX Domain Sockets authentication + */ + +static int /* O - 0 if available, -1 if not */ +cups_peercred_auth(http_t *http) /* I - HTTP connection to server */ +{ +#ifdef SO_PEERCRED + long buflen; + char *buf; + struct passwd pwbuf, *pwbufptr; + + if (http->hostaddr->addr.sa_family != AF_LOCAL) + return (-1); + + /* + * Are we trying to authenticate as ourselves? If not, SO_PEERCRED + * is no use. + */ + buflen = sysconf (_SC_GETPW_R_SIZE_MAX); + buf = malloc (buflen); + if (buf == NULL) + return (-1); + + if (getpwnam_r (cupsUser(), &pwbuf, buf, buflen, &pwbufptr) != 0) + { + free (buf); + return (-1); + } + + if (pwbuf.pw_uid != getuid()) + { + free (buf); + return (-1); + } + + free (buf); + + /* + * Set the authorization string and return... + */ + + snprintf(http->authstring, sizeof(http->authstring), "SO_PEERCRED"); + + DEBUG_printf(("cups_peercred_auth: Returning authstring = \"%s\"\n", + http->authstring)); + + return (0); +#else + return (-1); +#endif /* SO_PEERCRED */ +} /* * 'cups_local_auth()' - Get the local authorization certificate if @@ -234,7 +291,7 @@ { DEBUG_printf(("cups_local_auth: Unable to open file %s: %s\n", filename, strerror(errno))); - return (-1); + return cups_peercred_auth(http); } /* --- cups-1.2.8/scheduler/auth.c.scm_credentials 2006-09-12 14:58:39.000000000 +0100 +++ cups-1.2.8/scheduler/auth.c 2007-03-09 17:11:21.000000000 +0000 @@ -60,6 +60,9 @@ #include "cupsd.h" #include +#include +#include +#include #ifdef HAVE_SHADOW_H # include #endif /* HAVE_SHADOW_H */ @@ -79,6 +82,9 @@ #ifdef HAVE_MEMBERSHIP_H # include #endif /* HAVE_MEMBERSHIP_H */ +#if !defined(WIN32) && !defined(__EMX__) +# include +#endif /* @@ -384,6 +390,42 @@ "cupsdAuthorize: No authentication data provided."); return; } +#ifdef SO_PEERCRED + else if (!strncmp(authorization, "SO_PEERCRED", 3) && + con->http.hostaddr->addr.sa_family == AF_LOCAL) + { + long buflen; + char *buf; + struct passwd pwbuf, *pwbufptr; + struct ucred u; + socklen_t ulen = sizeof(u); + if (getsockopt(con->http.fd, SOL_SOCKET, SO_PEERCRED, &u, &ulen) == -1) + { + cupsdLogMessage(CUPSD_LOG_ERROR, + "cupsdAuthorize: getsockopt failed for SO_PEERCRED"); + return; + } + + buflen = sysconf (_SC_GETPW_R_SIZE_MAX); + buf = malloc (buflen); + if (buf == NULL) + return; + + /* Look up which username the UID is for. */ + if (getpwuid_r (u.uid, &pwbuf, buf, buflen, &pwbufptr) != 0) + { + cupsdLogMessage(CUPSD_LOG_ERROR, + "cupsdAuthorize: getpwuid_r failed after SO_PEERCRED"); + free (buf); + return; + } + + strlcpy(username, pwbuf.pw_name, sizeof(username)); + free (buf); + cupsdLogMessage(CUPSD_LOG_DEBUG2, + "cupsdAuthorize: using SO_PEERCRED (uid=%d)", u.uid); + } +#endif /* SO_PEERCRED */ else if (!strncmp(authorization, "Local", 5) && !strcasecmp(con->http.hostname, "localhost")) {