Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Authentication over UNIX domain socket #2277

Closed
michaelrsweet opened this issue Mar 6, 2007 · 7 comments

Comments

@michaelrsweet
Copy link
Collaborator

commented Mar 6, 2007

Version: 1.3-feature
CUPS.org User: twaugh.redhat

If CUPS were to support authentication over a UNIX domain socket as one of its AuthType methods, this might go some way towards mitigating STR #2272.

@michaelrsweet

This comment has been minimized.

Copy link
Collaborator Author

commented Mar 8, 2007

CUPS.org User: twaugh.redhat

Here is a patch that works for me.

@michaelrsweet

This comment has been minimized.

Copy link
Collaborator Author

commented Mar 9, 2007

CUPS.org User: twaugh.redhat

I've attached a better, simpler version of this patch.

@michaelrsweet

This comment has been minimized.

Copy link
Collaborator Author

commented Mar 29, 2007

CUPS.org User: twaugh.redhat

I've attached a slightly updated version. This version makes sure to provide a sufficiently large buffer to getpw{nam,uid}_r when it fails with ERANGE.

Mike, what do you think about this approach in principal?

@michaelrsweet

This comment has been minimized.

Copy link
Collaborator Author

commented Apr 5, 2007

CUPS.org User: mike

Dupe of STR #2242; let's continue any discussions on that bug...

@michaelrsweet

This comment has been minimized.

Copy link
Collaborator Author

commented Apr 5, 2007

"cups-scm_credentials.patch":

--- cups-1.2.8/cups/http.c.scm_credentials 2007-03-08 10:10:38.000000000 +0000
+++ cups-1.2.8/cups/http.c 2007-03-08 10:52:19.000000000 +0000
@@ -109,6 +109,11 @@

include <sys/resource.h>

#endif /* !WIN32 */

+#include <sys/socket.h>
+#include <sys/types.h>
+#if !defined(WIN32) && !defined(EMX)
+# include <unistd.h>
+#endif

/*

  • Some operating systems have done away with the Fxxxx constants for
    @@ -2515,6 +2520,58 @@
    httpGetLength2(http);
    httpClearFields(http);

+#ifdef SCM_CREDENTIALS

  • if (!strncmp(http->authstring, "SCM_CREDENTIALS", 15))
  • {
  • struct msghdr msg;
  • struct cmsghdr *cmsg;
  • struct iovec vec;
  • char dummy;
  • char buf[CMSG_SPACE(sizeof(struct ucred))];
  • struct ucred *uptr;
  • fd_set fds;
  • struct timeval tv;
  • FD_ZERO(&fds);
  • FD_SET(http->fd, &fds);
  • tv.tv_sec = 5; /* Wait up to 5 seconds. */
  • tv.tv_usec = 0;
  • if (select(http->fd + 1, &fds, NULL, &fds, &tv) < 1 ||
  • recv(http->fd, &dummy, 1, 0) != 1)
  • {
  •  DEBUG_printf(("http_send: failed to synchronize for SCM_CREDENTIALS"));
    
  •  return (-1);
    
  • }
  • memset (&msg, 0, sizeof(msg));
  • vec.iov_base = &dummy;
  • vec.iov_len = 1;
  • msg.msg_iov = &vec;
  • msg.msg_iovlen = 1;
  • msg.msg_control = buf;
  • msg.msg_controllen = sizeof(buf);
  • cmsg = CMSG_FIRSTHDR(&msg);
  • cmsg->cmsg_level = SOL_SOCKET;
  • cmsg->cmsg_type = SCM_CREDENTIALS;
  • cmsg->cmsg_len = CMSG_LEN(sizeof(struct ucred));
  • uptr = (struct ucred *)CMSG_DATA(cmsg);
  • uptr->uid = getuid();
  • uptr->gid = getgid();
  • uptr->pid = getpid();
  • msg.msg_controllen = cmsg->cmsg_len;
  • FD_ZERO(&fds);
  • FD_SET(http->fd, &fds);
  • tv.tv_sec = 5;
  • tv.tv_usec = 0;
  • if (select(http->fd + 1, NULL, &fds, &fds, &tv) < 1 ||
  • sendmsg(http->fd, &msg, 0) == -1)
  • {
  •  DEBUG_printf(("http_send: failed to send SCM_CREDENTIALS"));
    
  •  return (-1);
    
  • }
  • }
    +#endif /* SCM_CREDENTIALS */

return (0);
}

--- 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-08 10:53:43.000000000 +0000
@@ -26,6 +26,9 @@

  • Contents:
    *
  • cupsDoAuthentication() - Authenticate a request.
  • * cups_scm_credentials_auth
  • * - Find out if SCM_CREDENTIALS authentication
  • * is possible
  • cups_local_auth() - Get the local authorization certificate if
  •                        available/applicable...
    
    _/
    @@ -47,6 +50,8 @@

    include <unistd.h>

    #endif /_ WIN32 || EMX */

+#include <sys/types.h>
+#include <pwd.h>

/*

  • Local functions...
    @@ -177,6 +182,57 @@
    return (0);
    }

+#ifdef SCM_CREDENTIALS
+/*

  • * 'cups_scm_credentials_auth()'
  • * - UNIX Domain Sockets authentication
  • /
    +
    +static int /
    O - 0 if available, -1 if not /
    +cups_scm_credentials_auth(http_t *http) /
    I - HTTP connection to server */
    +{
  • 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, SCM_CREDENTIALS
  • * 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), "SCM_CREDENTIALS");
  • DEBUG_printf(("cups_scm_credentials_auth: Returning authstring = "%s"\n",
  •   http->authstring));
    
  • return (0);
    +}
    +#endif /* SCM_CREDENTIALS */

/*

  • 'cups_local_auth()' - Get the local authorization certificate if
    @@ -234,7 +290,13 @@
    {
    DEBUG_printf(("cups_local_auth: Unable to open file %s: %s\n",
    filename, strerror(errno)));
    +
    +#ifdef AF_LOCAL

  • return cups_scm_credentials_auth(http);
    +#else
    return (-1);
    +#endif /* AF_LOCAL */

  • }

    /*
    --- 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-08 10:50:19.000000000 +0000
    @@ -80,6 +80,14 @@

    include <membership.h>

    #endif /* HAVE_MEMBERSHIP_H */

+#include <sys/socket.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <pwd.h>
+#if !defined(WIN32) && !defined(EMX)
+# include <unistd.h>
+#endif
+

/*

  • Local functions...
    @@ -384,6 +392,99 @@
    "cupsdAuthorize: No authentication data provided.");
    return;
    }
    +#ifdef SCM_CREDENTIALS
    • else if (!strncmp(authorization, "SCM_CREDENTIALS", 3) &&
    •  con->http.hostaddr->addr.sa_family == AF_LOCAL)
      
    • {
    • const int val = 1;
    • struct msghdr msg;
    • struct cmsghdr *cmsg;
    • struct iovec vec;
    • char dummy;
    • char buf[CMSG_SPACE(sizeof(struct ucred))];
    • fd_set fds;
    • struct timeval tv;
    • cupsdLogMessage(CUPSD_LOG_DEBUG, "SCM_CREDENTIALS authentication");
    • /* Turn on reception of credentials. */
    • if (setsockopt(con->http.fd, SOL_SOCKET, SO_PASSCRED, &val, sizeof(val)))
    • {
    •  cupsdLogMessage(CUPSD_LOG_ERROR, "SCM_CREDENTIALS setsockopt failed!");
      
    •  return;
      
    • }
    • /* If the client sends their SCM_CREDENTIALS message too soon we will
    • \* read it as part of the HTTP request.  To prevent that, they wait
      
    • \* until we send them this zero byte to synchronize.
      
    • */
      
    • dummy = '\0';
    • FD_ZERO(&fds);
    • FD_SET(con->http.fd, &fds);
    • tv.tv_sec = 5; /* Wait up to 5 seconds */
    • tv.tv_usec = 0;
    • if (select(con->http.fd + 1, NULL, &fds, &fds, &tv) < 1 ||
    • send(con->http.fd, &dummy, 1, 0) != 1)
    • {
    •  cupsdLogMessage(CUPSD_LOG_ERROR, "SCM_CREDENTIALS sync failed");
      
    •  return;
      
    • }
    • memset (&msg, 0, sizeof(msg));
    • vec.iov_base = &dummy;
    • vec.iov_len = 1;
    • msg.msg_iov = &vec;
    • msg.msg_iovlen = 1;
    • msg.msg_control = buf;
    • msg.msg_controllen = sizeof(buf);
    • FD_ZERO(&fds);
    • FD_SET(con->http.fd, &fds);
    • tv.tv_sec = 5; /* Wait up to 5 seconds */
    • tv.tv_usec = 0;
    • if (select(con->http.fd + 1, &fds, NULL, &fds, &tv) < 1 ||
    • recvmsg(con->http.fd, &msg, 0) == -1)
    • {
    •  cupsdLogMessage(CUPSD_LOG_ERROR, "SCM_CREDENTIALS recvmsg failed!");
      
    •  return;
      
    • }
    • for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg,cmsg))
    • {
    •  if (cmsg->cmsg_level == SOL_SOCKET &&
      
    • cmsg->cmsg_type == SCM_CREDENTIALS)
      
    •  {
      
    • long buflen;
    • char *buf;
    • struct passwd pwbuf, *pwbufptr;
    • struct ucred *uptr;
    • if (cmsg->cmsg_len != CMSG_LEN(sizeof(struct ucred)))
    • {
    • cupsdLogMessage(CUPSD_LOG_ERROR,
      
    •         "SCM_CREDENTIALS cmsg_len mismatch!");
      
    • return;
      
    • }
    • uptr = (struct ucred *)CMSG_DATA(cmsg);
    • 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 (uptr->uid, &pwbuf, buf, buflen, &pwbufptr) != 0)
    • {
    • free (buf);
      
    • return;
      
    • }
    • strlcpy(username, pwbuf.pw_name, sizeof(username));
    • free (buf);
    •  }
      
    • }
    • }
      +#endif /* SCM_CREDENTIALS */
      else if (!strncmp(authorization, "Local", 5) &&
      !strcasecmp(con->http.hostname, "localhost"))
      {
@michaelrsweet

This comment has been minimized.

Copy link
Collaborator Author

commented Apr 5, 2007

"cups-scm_credentials_v2.patch":

--- 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 <ctype.h>
    #include <errno.h>
    #include <fcntl.h>
    +#include <pwd.h>
    #include <sys/stat.h>
    +#include <sys/types.h>
    #if defined(WIN32) || defined(EMX)

    include <io.h>

    #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 <grp.h>
+#include <pwd.h>
+#include <sys/socket.h>
+#include <sys/types.h>
#ifdef HAVE_SHADOW_H

include <shadow.h>

#endif /* HAVE_SHADOW_H */
@@ -79,6 +82,9 @@
#ifdef HAVE_MEMBERSHIP_H

include <membership.h>

#endif /* HAVE_MEMBERSHIP_H */
+#if !defined(WIN32) && !defined(EMX)
+# include <unistd.h>
+#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"))
    {
@michaelrsweet

This comment has been minimized.

Copy link
Collaborator Author

commented Apr 5, 2007

"cups-af_unix-auth.patch":

--- cups-1.2.10/cups/auth.c.af_unix-auth 2007-01-10 16:48:37.000000000 +0000
+++ cups-1.2.10/cups/auth.c 2007-03-29 16:59:51.000000000 +0100
@@ -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 <ctype.h>
    #include <errno.h>
    #include <fcntl.h>
    +#include <pwd.h>
    #include <sys/stat.h>
    +#include <sys/types.h>
    #if defined(WIN32) || defined(EMX)

    include <io.h>

    #else
    @@ -177,6 +181,76 @@
    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, *newbuf;
  • struct passwd pwbuf, *pwbufptr;
  • int r;
  • 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 = NULL;
  • do
  • {
  • newbuf = realloc (buf, buflen);
  • if (newbuf == NULL)
  • {
  •  free (buf);
    
  •  return (-1);
    
  • }
  • buf = newbuf;
  • r = getpwnam_r (cupsUser(), &pwbuf, buf, buflen, &pwbufptr);
  • if (r != 0)
  • {
  •  if (r == ERANGE)
    
  •  {
    
  • buflen *= 2;
  • continue;
  •  }
    
  •  free (buf);
    
  •  return (-1);
    
  • }
  • }
  • while (r != 0);
  • 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 +308,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.10/scheduler/auth.c.af_unix-auth 2006-09-12 14:58:39.000000000 +0100
+++ cups-1.2.10/scheduler/auth.c 2007-03-29 17:03:53.000000000 +0100
@@ -60,6 +60,9 @@

#include "cupsd.h"
#include <grp.h>
+#include <pwd.h>
+#include <sys/socket.h>
+#include <sys/types.h>
#ifdef HAVE_SHADOW_H

include <shadow.h>

#endif /* HAVE_SHADOW_H */
@@ -79,6 +82,9 @@
#ifdef HAVE_MEMBERSHIP_H

include <membership.h>

#endif /* HAVE_MEMBERSHIP_H */
+#if !defined(WIN32) && !defined(EMX)
+# include <unistd.h>
+#endif

/*
@@ -384,6 +390,61 @@
"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, *newbuf;
  • struct passwd pwbuf, *pwbufptr;
  • struct ucred u;
  • socklen_t ulen = sizeof(u);
  • int r;
  • 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 = NULL;
  • do
  • {
  •  newbuf = realloc (buf, buflen);
    
  •  if (newbuf == NULL)
    
  •  {
    
  • free (buf);
  • return;
  •  }
    
  •  buf = newbuf;
    
  •  /\* Look up which username the UID is for. */
    
  •  r = getpwuid_r (u.uid, &pwbuf, buf, buflen, &pwbufptr);
    
  •  if (r != 0)
    
  •  {
    
  • if (r == ERANGE)
  • {
  • buflen *= 2;
    
  • continue;
    
  • }
  • cupsdLogMessage(CUPSD_LOG_ERROR,
  •       "cupsdAuthorize: getpwuid_r failed after SO_PEERCRED");
    
  • free (buf);
  • return;
  •  }
    
  • }
  • while (r != 0);
  • 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"))
    {
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
1 participant
You can’t perform that action at this time.