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