Index: config-scripts/cups-common.m4 =================================================================== --- config-scripts/cups-common.m4 (revision 6639) +++ config-scripts/cups-common.m4 (working copy) @@ -132,6 +132,7 @@ AC_CHECK_HEADER(bstring.h,AC_DEFINE(HAVE_BSTRING_H)) AC_CHECK_HEADER(usersec.h,AC_DEFINE(HAVE_USERSEC_H)) AC_CHECK_HEADER(sys/ioctl.h,AC_DEFINE(HAVE_SYS_IOCTL_H)) +AC_CHECK_HEADER(sys/ucred.h,AC_DEFINE(HAVE_SYS_UCRED_H)) AC_CHECK_HEADER(scsi/sg.h,AC_DEFINE(HAVE_SCSI_SG_H)) dnl Checks for string functions. Index: cups/http.h =================================================================== --- cups/http.h (revision 6639) +++ cups/http.h (working copy) @@ -64,6 +64,9 @@ # ifdef AF_LOCAL # include # endif /* AF_LOCAL */ +# if defined(LOCAL_PEERCRED) && !defined(SO_PEERCRED) +# define SO_PEERCRED LOCAL_PEERCRED +# endif /* LOCAL_PEERCRED && !SO_PEERCRED */ # endif /* WIN32 */ /* Index: cups/auth.c =================================================================== --- cups/auth.c (revision 6639) +++ cups/auth.c (working copy) @@ -61,7 +61,11 @@ # endif /* HAVE_SECBASEPRIV_H */ #endif /* HAVE_AUTHORIZATION_H */ +#if defined(SO_PEERCRED) && defined(AF_LOCAL) +# include +#endif /* SO_PEERCRED && AF_LOCAL */ + /* * Local functions... */ @@ -439,7 +443,7 @@ char filename[1024], /* Certificate filename */ certificate[33];/* Certificate string */ _cups_globals_t *cg = _cupsGlobals(); /* Global data */ -#if defined(HAVE_AUTHORIZATION_H) +# if defined(HAVE_AUTHORIZATION_H) OSStatus status; /* Status */ AuthorizationItem auth_right; /* Authorization right */ AuthorizationRights auth_rights; /* Authorization rights */ @@ -447,7 +451,7 @@ AuthorizationExternalForm auth_extrn; /* Authorization ref external */ char auth_key[1024]; /* Buffer */ char buffer[1024]; /* Buffer */ -#endif /* HAVE_AUTHORIZATION_H */ +# endif /* HAVE_AUTHORIZATION_H */ DEBUG_printf(("cups_local_auth(http=%p) hostaddr=%s, hostname=\"%s\"\n", @@ -464,7 +468,7 @@ return (1); } -#if defined(HAVE_AUTHORIZATION_H) +# if defined(HAVE_AUTHORIZATION_H) /* * Delete any previous authorization reference... */ @@ -535,7 +539,7 @@ * Fall through to try certificates... */ } -#endif /* HAVE_AUTHORIZATION_H */ +# endif /* HAVE_AUTHORIZATION_H */ /* * Try opening a certificate file for this PID. If that fails, @@ -566,7 +570,7 @@ * Set the authorization string and return... */ - http->authstring = malloc(strlen(certificate) + 10); + http->authstring = malloc(strlen(certificate) + 7); sprintf(http->authstring, "Local %s", certificate); /* Copy back to _authstring for backwards compatibility */ @@ -578,6 +582,40 @@ return (0); } +# if defined(SO_PEERCRED) && defined(AF_LOCAL) + /* + * See if we can authenticate using the peer credentials provided over a + * domain socket; if so, specify "PeerCred username" as the authentication + * information... + */ + + if (http->hostaddr->addr.sa_family == AF_LOCAL) + { + /* + * Verify that the current cupsUser() matches the current UID... + */ + + struct passwd *pwd; /* Password information */ + const char *username; /* Current username */ + + username = cupsUser(); + + if ((pwd = getpwnam(username)) != NULL && pwd->pw_uid == getuid()) + { + http->authstring = malloc(strlen(username) + 10); + sprintf(http->authstring, "PeerCred %s", username); + + /* Copy back to _authstring for backwards compatibility */ + strlcpy(http->_authstring, http->authstring, sizeof(http->_authstring)); + + DEBUG_printf(("cups_local_auth: Returning authstring = \"%s\"\n", + http->authstring)); + + return (0); + } + } +# endif /* SO_PEERCRED && AF_LOCAL */ + return (1); #endif /* WIN32 || __EMX__ */ } Index: CHANGES.txt =================================================================== --- CHANGES.txt (revision 6646) +++ CHANGES.txt (working copy) @@ -5,6 +5,8 @@ - Documentation updates (STR #1775, STR #2027, STR #2130, STR #2131, STR #2263, STR #2356, STR #2397) + - CUPS now supports authentication via peer credentials + over domain sockets (STR #2242, STR #2277) - The CUPS sample driver PPDs are now generated by the PPD compiler and include all of the localized languages by default (STR #2164) Index: config.h.in =================================================================== --- config.h.in (revision 6639) +++ config.h.in (working copy) @@ -531,6 +531,13 @@ #undef HAVE_DLFCN_H +/* + * Do we have ? + */ + +#undef HAVE_SYS_UCRED_H + + #endif /* !_CUPS_CONFIG_H_ */ /* Index: scheduler/auth.c =================================================================== --- scheduler/auth.c (revision 6639) +++ scheduler/auth.c (working copy) @@ -92,6 +92,14 @@ extern const char *cssmErrorString(int error); # endif /* HAVE_SECBASEPRIV_H */ #endif /* HAVE_AUTHORIZATION_H */ +#ifdef HAVE_SYS_UCRED_H +# include +typedef struct xucred cupsd_ucred_t; +# define CUPSD_UCRED_UID(c) (c).cr_uid +#else +typedef struct ucred cupsd_ucred_t; +# define CUPSD_UCRED_UID(c) (c).uid +#endif /* HAVE_SYS_UCRED_H */ /* @@ -433,8 +441,7 @@ if (authlen != kAuthorizationExternalFormLength) { cupsdLogMessage(CUPSD_LOG_ERROR, - "cupsdAuthorize: External Authorization reference size" - "is incorrect!"); + "External Authorization reference size is incorrect!"); return; } @@ -442,8 +449,7 @@ (AuthorizationExternalForm *)nonce, &con->authref)) != 0) { cupsdLogMessage(CUPSD_LOG_ERROR, - "cupsdAuthorize: AuthorizationCreateFromExternalForm " - "returned %d (%s)", + "AuthorizationCreateFromExternalForm returned %d (%s)", (int)status, cssmErrorString(status)); return; } @@ -453,7 +459,7 @@ &authinfo)) != 0) { cupsdLogMessage(CUPSD_LOG_ERROR, - "cupsdAuthorize: AuthorizationCopyInfo returned %d (%s)", + "AuthorizationCopyInfo returned %d (%s)", (int)status, cssmErrorString(status)); return; } @@ -464,6 +470,57 @@ AuthorizationFreeItemSet(authinfo); } #endif /* HAVE_AUTHORIZATION_H */ +#if defined(SO_PEERCRED) && defined(AF_LOCAL) + else if (!strncmp(authorization, "PeerCred ", 9) && + con->http.hostaddr->addr.sa_family == AF_LOCAL) + { + /* + * Use peer credentials from domain socket connection... + */ + + struct passwd *pwd; /* Password entry for this user */ + cupsd_ucred_t peercred; /* Peer credentials */ + socklen_t peersize; /* Size of peer credentials */ + + + if ((pwd = getpwnam(authorization + 9)) == NULL) + { + cupsdLogMessage(CUPSD_LOG_ERROR, "User \"%s\" does not exist!", + authorization + 9); + return; + } + + peersize = sizeof(peercred); + + if (getsockopt(con->http.fd, SOL_SOCKET, SO_PEERCRED, &peercred, &peersize)) + { + cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to get peer credentials - %s", + strerror(errno)); + return; + } + + if (pwd->pw_uid != CUPSD_UCRED_UID(peercred)) + { + cupsdLogMessage(CUPSD_LOG_ERROR, + "Invalid peer credentials for \"%s\" - got %d, " + "expected %d!", authorization + 9, + CUPSD_UCRED_UID(peercred), pwd->pw_uid); +# ifdef HAVE_SYS_UCRED_H + cupsdLogMessage(CUPSD_LOG_DEBUG, "cupsdAuthorize: cr_version=%d", + peercred.cr_version); + cupsdLogMessage(CUPSD_LOG_DEBUG, "cupsdAuthorize: cr_uid=%d", + peercred.cr_uid); + cupsdLogMessage(CUPSD_LOG_DEBUG, "cupsdAuthorize: cr_ngroups=%d", + peercred.cr_ngroups); + cupsdLogMessage(CUPSD_LOG_DEBUG, "cupsdAuthorize: cr_groups[0]=%d", + peercred.cr_groups[0]); +# endif /* HAVE_SYS_UCRED_H */ + return; + } + + strlcpy(username, authorization + 9, sizeof(username)); + } +#endif /* SO_PEERCRED && AF_LOCAL */ else if (!strncmp(authorization, "Local", 5) && !strcasecmp(con->http.hostname, "localhost")) {