/*
- * "$Id: auth.c 7830 2008-08-04 20:38:50Z mike $"
+ * "$Id$"
*
* Authorization routines for the CUPS scheduler.
*
- * Copyright 2007-2010 by Apple Inc.
+ * Copyright 2007-2012 by Apple Inc.
* Copyright 1997-2007 by Easy Software Products, all rights reserved.
*
* This file contains Kerberos support code, copyright 2006 by
* access a location.
* cupsdCheckAuth() - Check authorization masks.
* cupsdCheckGroup() - Check for a user's group membership.
- * cupsdCopyKrb5Creds() - Get a copy of the Kerberos credentials.
* cupsdCopyLocation() - Make a copy of a location...
* cupsdDeleteAllLocations() - Free all memory used for location
* authorization.
typedef struct xucred cupsd_ucred_t;
# define CUPSD_UCRED_UID(c) (c).cr_uid
#else
+# ifndef __OpenBSD__
typedef struct ucred cupsd_ucred_t;
+# else
+typedef struct sockpeercred cupsd_ucred_t;
+# endif
# define CUPSD_UCRED_UID(c) (c).uid
#endif /* HAVE_SYS_UCRED_H */
-#ifdef HAVE_KRB5_IPC_CLIENT_SET_TARGET_UID
-/* Not in public headers... */
-extern void krb5_ipc_client_set_target_uid(uid_t);
-extern void krb5_ipc_client_clear_target(void);
-#endif /* HAVE_KRB5_IPC_CLIENT_SET_TARGET_UID */
/*
#if HAVE_LIBPAM
typedef struct cupsd_authdata_s /**** Authentication data ****/
{
- char username[33], /* Username string */
- password[33]; /* Password string */
+ char username[HTTP_MAX_VALUE], /* Username string */
+ password[HTTP_MAX_VALUE]; /* Password string */
} cupsd_authdata_t;
#endif /* HAVE_LIBPAM */
"cupsdAddNameMask(masks=%p(%p), name=\"%s\")",
masks, *masks, name);
- if (!strcasecmp(name, "@LOCAL"))
+ if (!_cups_strcasecmp(name, "@LOCAL"))
{
/*
* Deny *interface*...
temp.type = CUPSD_AUTH_INTERFACE;
temp.mask.name.name = (char *)"*";
}
- else if (!strncasecmp(name, "@IF(", 4))
+ else if (!_cups_strncasecmp(name, "@IF(", 4))
{
/*
* Deny *interface*...
int type; /* Authentication type */
const char *authorization; /* Pointer into Authorization string */
char *ptr, /* Pointer into string */
- username[256], /* Username string */
- password[33]; /* Password string */
+ username[HTTP_MAX_VALUE],
+ /* Username string */
+ password[HTTP_MAX_VALUE];
+ /* Password string */
cupsd_cert_t *localuser; /* Certificate username */
char nonce[HTTP_MAX_VALUE], /* Nonce value from client */
md5[33], /* MD5 password */
con->type = CUPSD_AUTH_NONE;
cupsdLogMessage(CUPSD_LOG_DEBUG2,
- "cupsdAuthorize: con->uri=\"%s\", con->best=%p(%s)",
- con->uri, con->best, con->best ? con->best->location : "");
+ "[Client %d] con->uri=\"%s\", con->best=%p(%s)",
+ con->http.fd, con->uri, con->best,
+ con->best ? con->best->location : "");
if (con->best && con->best->type != CUPSD_AUTH_NONE)
{
if (con->best->type == CUPSD_AUTH_DEFAULT)
- type = DefaultAuthType;
+ type = cupsdDefaultAuthType();
else
type = con->best->type;
}
else
- type = DefaultAuthType;
+ type = cupsdDefaultAuthType();
/*
* Decode the Authorization string...
authorization = httpGetField(&con->http, HTTP_FIELD_AUTHORIZATION);
- cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdAuthorize: Authorization=\"%s\"",
- authorization);
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "[Client %d] Authorization=\"%s\"",
+ con->http.fd, authorization);
username[0] = '\0';
password[0] = '\0';
+#ifdef HAVE_GSSAPI
+ con->gss_uid = 0;
+#endif /* HAVE_GSSAPI */
+
#ifdef HAVE_AUTHORIZATION_H
if (con->authref)
{
*/
cupsdLogMessage(CUPSD_LOG_DEBUG,
- "cupsdAuthorize: No authentication data provided.");
+ "[Client %d] No authentication data provided.",
+ con->http.fd);
return;
}
#ifdef HAVE_AUTHORIZATION_H
- else if (!strncmp(authorization, "AuthRef", 6) &&
- !strcasecmp(con->http.hostname, "localhost"))
+ else if (!strncmp(authorization, "AuthRef ", 8) &&
+ !_cups_strcasecmp(con->http.hostname, "localhost"))
{
OSStatus status; /* Status */
int authlen; /* Auth string length */
* Get the Authorization Services data...
*/
- authorization += 7;
+ authorization += 8;
while (isspace(*authorization & 255))
authorization ++;
if (authlen != kAuthorizationExternalFormLength)
{
cupsdLogMessage(CUPSD_LOG_ERROR,
- "External Authorization reference size is incorrect!");
+ "[Client %d] External Authorization reference size is "
+ "incorrect.", con->http.fd);
return;
}
(AuthorizationExternalForm *)nonce, &con->authref)) != 0)
{
cupsdLogMessage(CUPSD_LOG_ERROR,
- "AuthorizationCreateFromExternalForm returned %d (%s)",
- (int)status, cssmErrorString(status));
+ "[Client %d] AuthorizationCreateFromExternalForm "
+ "returned %d (%s)", con->http.fd, (int)status,
+ cssmErrorString(status));
return;
}
- strlcpy(username, "_AUTHREF_", sizeof(username));
+ username[0] = '\0';
- if (!AuthorizationCopyInfo(con->authref, kAuthorizationEnvironmentUsername,
+ if (!AuthorizationCopyInfo(con->authref, kAuthorizationEnvironmentUsername,
&authinfo))
{
if (authinfo->count == 1 && authinfo->items[0].value &&
authinfo->items[0].valueLength >= 2)
+ {
strlcpy(username, authinfo->items[0].value, sizeof(username));
+ cupsdLogMessage(CUPSD_LOG_DEBUG,
+ "[Client %d] Authorized as \"%s\" using AuthRef",
+ con->http.fd, username);
+ }
+
AuthorizationFreeItemSet(authinfo);
}
- cupsdLogMessage(CUPSD_LOG_DEBUG,
- "cupsdAuthorize: Authorized as \"%s\" using AuthRef",
- username);
+ if (!username[0])
+ {
+ /*
+ * No username in AuthRef, grab username using peer credentials...
+ */
+
+ struct passwd *pwd; /* Password entry for this user */
+ cupsd_ucred_t peercred; /* Peer credentials */
+ socklen_t peersize; /* Size of peer credentials */
+
+ peersize = sizeof(peercred);
+
+ if (getsockopt(con->http.fd, 0, LOCAL_PEERCRED, &peercred, &peersize))
+ {
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "[Client %d] Unable to get peer credentials - %s",
+ con->http.fd, strerror(errno));
+ return;
+ }
+
+ if ((pwd = getpwuid(CUPSD_UCRED_UID(peercred))) == NULL)
+ {
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "[Client %d] Unable to find UID %d for peer "
+ "credentials.", con->http.fd,
+ (int)CUPSD_UCRED_UID(peercred));
+ return;
+ }
+
+ strlcpy(username, pwd->pw_name, sizeof(username));
+
+ cupsdLogMessage(CUPSD_LOG_DEBUG,
+ "[Client %d] Authorized as \"%s\" using "
+ "AuthRef + PeerCred", con->http.fd, username);
+ }
+
con->type = CUPSD_AUTH_BASIC;
}
#endif /* HAVE_AUTHORIZATION_H */
struct passwd *pwd; /* Password entry for this user */
cupsd_ucred_t peercred; /* Peer credentials */
socklen_t peersize; /* Size of peer credentials */
+#ifdef HAVE_AUTHORIZATION_H
+ const char *name; /* Authorizing name */
+ int no_peer = 0; /* Don't allow peer credentials? */
+
+ /*
+ * See if we should allow peer credentials...
+ */
+ for (name = (char *)cupsArrayFirst(con->best->names);
+ name;
+ name = (char *)cupsArrayNext(con->best->names))
+ {
+ if (!_cups_strncasecmp(name, "@AUTHKEY(", 9) ||
+ !_cups_strcasecmp(name, "@SYSTEM"))
+ {
+ /* Normally don't want peer credentials if we need an auth key... */
+ no_peer = 1;
+ }
+ else if (!_cups_strcasecmp(name, "@OWNER"))
+ {
+ /* but if @OWNER is present then we allow it... */
+ no_peer = 0;
+ break;
+ }
+ }
+
+ if (no_peer)
+ {
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "[Client %d] PeerCred authentication not allowed for "
+ "resource per AUTHKEY policy.", con->http.fd);
+ return;
+ }
+#endif /* HAVE_AUTHORIZATION_H */
if ((pwd = getpwnam(authorization + 9)) == NULL)
{
- cupsdLogMessage(CUPSD_LOG_ERROR, "User \"%s\" does not exist!",
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "[Client %d] User \"%s\" does not exist.", con->http.fd,
authorization + 9);
return;
}
if (getsockopt(con->http.fd, SOL_SOCKET, SO_PEERCRED, &peercred, &peersize))
# endif /* __APPLE__ */
{
- cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to get peer credentials - %s",
- strerror(errno));
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "[Client %d] Unable to get peer credentials - %s",
+ con->http.fd, 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,
+ "[Client %d] Invalid peer credentials for \"%s\" - got "
+ "%d, expected %d!", con->http.fd, 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]);
+ cupsdLogMessage(CUPSD_LOG_DEBUG, "[Client %d] cr_version=%d",
+ con->http.fd, peercred.cr_version);
+ cupsdLogMessage(CUPSD_LOG_DEBUG, "[Client %d] cr_uid=%d",
+ con->http.fd, peercred.cr_uid);
+ cupsdLogMessage(CUPSD_LOG_DEBUG, "[Client %d] cr_ngroups=%d",
+ con->http.fd, peercred.cr_ngroups);
+ cupsdLogMessage(CUPSD_LOG_DEBUG, "[Client %d] cr_groups[0]=%d",
+ con->http.fd, peercred.cr_groups[0]);
# endif /* HAVE_SYS_UCRED_H */
return;
}
strlcpy(username, authorization + 9, sizeof(username));
+# ifdef HAVE_GSSAPI
+ con->gss_uid = CUPSD_UCRED_UID(peercred);
+# endif /* HAVE_GSSAPI */
+
cupsdLogMessage(CUPSD_LOG_DEBUG,
- "cupsdAuthorize: Authorized as %s using PeerCred",
+ "[Client %d] Authorized as %s using PeerCred", con->http.fd,
username);
con->type = CUPSD_AUTH_BASIC;
}
#endif /* SO_PEERCRED && AF_LOCAL */
else if (!strncmp(authorization, "Local", 5) &&
- !strcasecmp(con->http.hostname, "localhost"))
+ !_cups_strcasecmp(con->http.hostname, "localhost"))
{
/*
* Get Local certificate authentication data...
while (isspace(*authorization & 255))
authorization ++;
- if ((localuser = cupsdFindCert(authorization)) != NULL)
- {
- strlcpy(username, localuser->username, sizeof(username));
-
- cupsdLogMessage(CUPSD_LOG_DEBUG,
- "cupsdAuthorize: Authorized as %s using Local",
- username);
- }
- else
+ if ((localuser = cupsdFindCert(authorization)) == NULL)
{
cupsdLogMessage(CUPSD_LOG_ERROR,
- "cupsdAuthorize: Local authentication certificate not "
- "found!");
+ "[Client %d] Local authentication certificate not found.",
+ con->http.fd);
return;
}
-#ifdef HAVE_GSSAPI
- if (localuser->ccache)
- con->type = CUPSD_AUTH_NEGOTIATE;
- else
-#endif /* HAVE_GSSAPI */
- con->type = CUPSD_AUTH_BASIC;
+ strlcpy(username, localuser->username, sizeof(username));
+ con->type = localuser->type;
+
+ cupsdLogMessage(CUPSD_LOG_DEBUG,
+ "[Client %d] Authorized as %s using Local", con->http.fd,
+ username);
}
else if (!strncmp(authorization, "Basic", 5))
{
if ((ptr = strchr(username, ':')) == NULL)
{
- cupsdLogMessage(CUPSD_LOG_ERROR,
- "cupsdAuthorize: Missing Basic password!");
+ cupsdLogMessage(CUPSD_LOG_ERROR, "[Client %d] Missing Basic password.",
+ con->http.fd);
return;
}
* Username must not be empty...
*/
- cupsdLogMessage(CUPSD_LOG_ERROR,
- "cupsdAuthorize: Empty Basic username!");
+ cupsdLogMessage(CUPSD_LOG_ERROR, "[Client %d] Empty Basic username.",
+ con->http.fd);
return;
}
* Password must not be empty...
*/
- cupsdLogMessage(CUPSD_LOG_ERROR,
- "cupsdAuthorize: Empty Basic password!");
+ cupsdLogMessage(CUPSD_LOG_ERROR, "[Client %d] Empty Basic password.",
+ con->http.fd);
return;
}
if (pamerr != PAM_SUCCESS)
{
cupsdLogMessage(CUPSD_LOG_ERROR,
- "cupsdAuthorize: pam_start() returned %d (%s)!",
- pamerr, pam_strerror(pamh, pamerr));
+ "[Client %d] pam_start() returned %d (%s)",
+ con->http.fd, pamerr, pam_strerror(pamh, pamerr));
return;
}
pamerr = pam_set_item(pamh, PAM_RHOST, con->http.hostname);
if (pamerr != PAM_SUCCESS)
cupsdLogMessage(CUPSD_LOG_WARN,
- "cupsdAuthorize: pam_set_item(PAM_RHOST) "
- "returned %d (%s)!", pamerr,
+ "[Client %d] pam_set_item(PAM_RHOST) "
+ "returned %d (%s)", con->http.fd, pamerr,
pam_strerror(pamh, pamerr));
# endif /* PAM_RHOST */
pamerr = pam_set_item(pamh, PAM_TTY, "cups");
if (pamerr != PAM_SUCCESS)
cupsdLogMessage(CUPSD_LOG_WARN,
- "cupsdAuthorize: pam_set_item(PAM_TTY) "
- "returned %d (%s)!", pamerr,
+ "[Client %d] pam_set_item(PAM_TTY) "
+ "returned %d (%s)!", con->http.fd, pamerr,
pam_strerror(pamh, pamerr));
# endif /* PAM_TTY */
# endif /* HAVE_PAM_SET_ITEM */
if (pamerr != PAM_SUCCESS)
{
cupsdLogMessage(CUPSD_LOG_ERROR,
- "cupsdAuthorize: pam_authenticate() returned %d "
- "(%s)!",
- pamerr, pam_strerror(pamh, pamerr));
+ "[Client %d] pam_authenticate() returned %d (%s)",
+ con->http.fd, pamerr, pam_strerror(pamh, pamerr));
pam_end(pamh, 0);
return;
}
pamerr = pam_setcred(pamh, PAM_ESTABLISH_CRED | PAM_SILENT);
if (pamerr != PAM_SUCCESS)
cupsdLogMessage(CUPSD_LOG_WARN,
- "cupsdAuthorize: pam_setcred() "
- "returned %d (%s)!", pamerr,
+ "[Client %d] pam_setcred() returned %d (%s)",
+ con->http.fd, pamerr,
pam_strerror(pamh, pamerr));
# endif /* HAVE_PAM_SETCRED */
if (pamerr != PAM_SUCCESS)
{
cupsdLogMessage(CUPSD_LOG_ERROR,
- "cupsdAuthorize: pam_acct_mgmt() returned %d "
- "(%s)!",
- pamerr, pam_strerror(pamh, pamerr));
+ "[Client %d] pam_acct_mgmt() returned %d (%s)",
+ con->http.fd, pamerr, pam_strerror(pamh, pamerr));
pam_end(pamh, 0);
return;
}
cupsdLogMessage(CUPSD_LOG_DEBUG,
- "cupsdAuthorize: AIX authenticate of username "
- "\"%s\"", username);
+ "[Client %d] AIX authenticate of username \"%s\"",
+ con->http.fd, username);
reenter = 1;
if (authenticate(username, password, &reenter, &authmsg) != 0)
{
cupsdLogMessage(CUPSD_LOG_DEBUG,
- "cupsdAuthorize: Unable to authenticate username "
- "\"%s\": %s",
- username, strerror(errno));
+ "[Client %d] Unable to authenticate username "
+ "\"%s\": %s", con->http.fd, username,
+ strerror(errno));
return;
}
*/
cupsdLogMessage(CUPSD_LOG_ERROR,
- "cupsdAuthorize: Unknown username \"%s\"!",
- username);
+ "[Client %d] Unknown username \"%s\".",
+ con->http.fd, username);
return;
}
*/
cupsdLogMessage(CUPSD_LOG_ERROR,
- "cupsdAuthorize: Username \"%s\" has no shadow "
- "password!", username);
+ "[Client %d] Username \"%s\" has no shadow "
+ "password.", con->http.fd, username);
return;
}
*/
cupsdLogMessage(CUPSD_LOG_ERROR,
- "cupsdAuthorize: Username \"%s\" has no password!",
- username);
+ "[Client %d] Username \"%s\" has no password.",
+ con->http.fd, username);
return;
}
pass = cups_crypt(password, pw->pw_passwd);
cupsdLogMessage(CUPSD_LOG_DEBUG2,
- "cupsdAuthorize: pw_passwd=\"%s\", crypt=\"%s\"",
- pw->pw_passwd, pass);
+ "[Client %d] pw_passwd=\"%s\", crypt=\"%s\"",
+ con->http.fd, pw->pw_passwd, pass);
if (!pass || strcmp(pw->pw_passwd, pass))
{
pass = cups_crypt(password, spw->sp_pwdp);
cupsdLogMessage(CUPSD_LOG_DEBUG2,
- "cupsdAuthorize: sp_pwdp=\"%s\", crypt=\"%s\"",
- spw->sp_pwdp, pass);
+ "[Client %d] sp_pwdp=\"%s\", crypt=\"%s\"",
+ con->http.fd, spw->sp_pwdp, pass);
if (pass == NULL || strcmp(spw->sp_pwdp, pass))
{
cupsdLogMessage(CUPSD_LOG_ERROR,
- "cupsdAuthorize: Authentication failed for "
- "user \"%s\"!",
- username);
+ "[Client %d] Authentication failed for user "
+ "\"%s\".", con->http.fd, username);
return;
}
}
# endif /* HAVE_SHADOW_H */
{
cupsdLogMessage(CUPSD_LOG_ERROR,
- "cupsdAuthorize: Authentication failed for "
- "user \"%s\"!",
- username);
+ "[Client %d] Authentication failed for user "
+ "\"%s\".", con->http.fd, username);
return;
}
}
}
cupsdLogMessage(CUPSD_LOG_DEBUG,
- "cupsdAuthorize: Authorized as %s using Basic",
- username);
+ "[Client %d] Authorized as %s using Basic",
+ con->http.fd, username);
break;
case CUPSD_AUTH_BASICDIGEST :
if (!get_md5_password(username, NULL, md5))
{
cupsdLogMessage(CUPSD_LOG_ERROR,
- "cupsdAuthorize: Unknown MD5 username \"%s\"!",
- username);
+ "[Client %d] Unknown MD5 username \"%s\".",
+ con->http.fd, username);
return;
}
if (strcmp(md5, basicmd5))
{
cupsdLogMessage(CUPSD_LOG_ERROR,
- "cupsdAuthorize: Authentication failed for \"%s\"!",
- username);
+ "[Client %d] Authentication failed for \"%s\".",
+ con->http.fd, username);
return;
}
cupsdLogMessage(CUPSD_LOG_DEBUG,
- "cupsdAuthorize: Authorized as %s using BasicDigest",
- username);
+ "[Client %d] Authorized as %s using BasicDigest",
+ con->http.fd, username);
break;
}
*/
cupsdLogMessage(CUPSD_LOG_ERROR,
- "cupsdAuthorize: Empty or missing Digest username!");
+ "[Client %d] Empty or missing Digest username.",
+ con->http.fd);
return;
}
*/
cupsdLogMessage(CUPSD_LOG_ERROR,
- "cupsdAuthorize: Empty or missing Digest password!");
+ "[Client %d] Empty or missing Digest password.",
+ con->http.fd);
return;
}
nonce))
{
cupsdLogMessage(CUPSD_LOG_ERROR,
- "cupsdAuthorize: No nonce value for Digest "
- "authentication!");
+ "[Client %d] No nonce value for Digest authentication.",
+ con->http.fd);
return;
}
if (strcmp(con->http.hostname, nonce))
{
cupsdLogMessage(CUPSD_LOG_ERROR,
- "cupsdAuthorize: Bad nonce value, expected \"%s\", "
- "got \"%s\"!", con->http.hostname, nonce);
+ "[Client %d] Bad nonce value, expected \"%s\", "
+ "got \"%s\".", con->http.fd, con->http.hostname, nonce);
return;
}
if (!get_md5_password(username, NULL, md5))
{
cupsdLogMessage(CUPSD_LOG_ERROR,
- "cupsdAuthorize: Unknown MD5 username \"%s\"!",
- username);
+ "[Client %d] Unknown MD5 username \"%s\".",
+ con->http.fd, username);
return;
}
if (strcmp(md5, password))
{
cupsdLogMessage(CUPSD_LOG_ERROR,
- "cupsdAuthorize: Authentication failed for \"%s\"!",
- username);
+ "[Client %d] Authentication failed for \"%s\".",
+ con->http.fd, username);
return;
}
cupsdLogMessage(CUPSD_LOG_DEBUG,
- "cupsdAuthorize: Authorized as %s using Digest",
+ "[Client %d] Authorized as %s using Digest", con->http.fd,
username);
con->type = CUPSD_AUTH_DIGEST;
}
#ifdef HAVE_GSSAPI
-# ifdef HAVE_KRB5_IPC_CLIENT_SET_TARGET_UID
- else if (con->http.hostaddr->addr.sa_family == AF_LOCAL &&
- !strncmp(authorization, "Negotiate", 9))
- {
- /*
- * Pull the credentials directly from the user...
- */
-
- krb5_error_code error; /* Kerberos error code */
- cupsd_ucred_t peercred; /* Peer credentials */
- socklen_t peersize; /* Size of peer credentials */
- krb5_ccache peerccache; /* Peer Kerberos credentials */
- const char *peername; /* Peer username */
-
- peersize = sizeof(peercred);
-
-# ifdef __APPLE__
- if (getsockopt(con->http.fd, 0, LOCAL_PEERCRED, &peercred, &peersize))
-# else
- if (getsockopt(con->http.fd, SOL_SOCKET, SO_PEERCRED, &peercred, &peersize))
-# endif /* __APPLE__ */
- {
- cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to get peer credentials - %s",
- strerror(errno));
- return;
- }
-
- cupsdLogMessage(CUPSD_LOG_DEBUG,
- "cupsdAuthorize: Copying credentials for UID %d...",
- CUPSD_UCRED_UID(peercred));
-
- if (!KerberosInitialized)
- {
- /*
- * Setup a Kerberos context for the scheduler to use...
- */
-
- KerberosInitialized = 1;
-
- if (krb5_init_context(&KerberosContext))
- {
- KerberosContext = NULL;
-
- cupsdLogMessage(CUPSD_LOG_ERROR,
- "Unable to initialize Kerberos context");
- return;
- }
- }
-
- krb5_ipc_client_set_target_uid(CUPSD_UCRED_UID(peercred));
-
- if ((error = krb5_cc_default(KerberosContext, &peerccache)) != 0)
- {
- cupsdLogMessage(CUPSD_LOG_ERROR,
- "Unable to get credentials cache for UID %d (%d/%s)",
- (int)CUPSD_UCRED_UID(peercred), error, strerror(errno));
- return;
- }
-
- if ((peername = krb5_cc_get_name(KerberosContext, peerccache)) != NULL)
- {
- strlcpy(username, peername, sizeof(username));
-
- con->have_gss = 1;
- con->type = CUPSD_AUTH_NEGOTIATE;
-
- cupsdLogMessage(CUPSD_LOG_DEBUG,
- "cupsdAuthorize: Authorized as %s using Negotiate",
- username);
- }
- else
- cupsdLogMessage(CUPSD_LOG_ERROR,
- "Unable to get Kerberos name for UID %d",
- (int)CUPSD_UCRED_UID(peercred));
-
- krb5_cc_close(KerberosContext, peerccache);
- krb5_ipc_client_clear_target();
- }
-# endif /* HAVE_KRB5_IPC_CLIENT_SET_TARGET_UID */
- else if (!strncmp(authorization, "Negotiate", 9))
+ else if (!strncmp(authorization, "Negotiate", 9))
{
int len; /* Length of authorization string */
gss_ctx_id_t context; /* Authorization context */
if (gss_init_sec_context == NULL)
{
cupsdLogMessage(CUPSD_LOG_WARN,
- "GSSAPI/Kerberos authentication failed because the "
- "Kerberos framework is not present.");
+ "[Client %d] GSSAPI/Kerberos authentication failed "
+ "because the Kerberos framework is not present.",
+ con->http.fd);
return;
}
# endif /* __APPLE__ */
- con->gss_output_token.length = 0;
-
/*
* Find the start of the Kerberos input token...
*/
if (!*authorization)
{
cupsdLogMessage(CUPSD_LOG_DEBUG2,
- "cupsdAuthorize: No authentication data specified.");
+ "[Client %d] No authentication data specified.",
+ con->http.fd);
return;
}
client_name = GSS_C_NO_NAME;
major_status = gss_accept_sec_context(&minor_status,
&context,
- GSS_C_NO_CREDENTIAL,
+ ServerCreds,
&input_token,
GSS_C_NO_CHANNEL_BINDINGS,
&client_name,
NULL,
- &con->gss_output_token,
- &con->gss_flags,
+ &output_token,
+ NULL,
NULL,
- &con->gss_creds);
+ NULL);
+
+ if (output_token.length > 0)
+ gss_release_buffer(&minor_status, &output_token);
if (GSS_ERROR(major_status))
{
cupsdLogGSSMessage(CUPSD_LOG_DEBUG, major_status, minor_status,
- "cupsdAuthorize: Error accepting GSSAPI security "
- "context");
+ "[Client %d] Error accepting GSSAPI security context",
+ con->http.fd);
if (context != GSS_C_NO_CONTEXT)
gss_delete_sec_context(&minor_status, &context, GSS_C_NO_BUFFER);
* Get the username associated with the client's credentials...
*/
- if (!con->gss_creds)
- cupsdLogMessage(CUPSD_LOG_DEBUG,
- "cupsdAuthorize: No delegated credentials!");
-
if (major_status == GSS_S_CONTINUE_NEEDED)
cupsdLogGSSMessage(CUPSD_LOG_DEBUG, major_status, minor_status,
- "cupsdAuthorize: Credentials not complete");
+ "[Client %d] Credentials not complete", con->http.fd);
else if (major_status == GSS_S_COMPLETE)
{
- major_status = gss_display_name(&minor_status, client_name,
+ major_status = gss_display_name(&minor_status, client_name,
&output_token, NULL);
if (GSS_ERROR(major_status))
{
cupsdLogGSSMessage(CUPSD_LOG_DEBUG, major_status, minor_status,
- "cupsdAuthorize: Error getting username");
- gss_release_cred(&minor_status, &con->gss_creds);
+ "[Client %d] Error getting username", con->http.fd);
gss_release_name(&minor_status, &client_name);
gss_delete_sec_context(&minor_status, &context, GSS_C_NO_BUFFER);
return;
strlcpy(username, output_token.value, sizeof(username));
cupsdLogMessage(CUPSD_LOG_DEBUG,
- "cupsdAuthorize: Authorized as %s using Negotiate",
- username);
+ "[Client %d] Authorized as %s using Negotiate",
+ con->http.fd, username);
gss_release_name(&minor_status, &client_name);
gss_release_buffer(&minor_status, &output_token);
con->type = CUPSD_AUTH_NEGOTIATE;
}
- else
- gss_release_cred(&minor_status, &con->gss_creds);
gss_delete_sec_context(&minor_status, &context, GSS_C_NO_BUFFER);
+
+# if defined(SO_PEERCRED) && defined(AF_LOCAL)
+ /*
+ * Get the client's UID if we are printing locally - that allows a backend
+ * to run as the correct user to get Kerberos credentials of its own.
+ */
+
+ if (_httpAddrFamily(con->http.hostaddr) == AF_LOCAL)
+ {
+ cupsd_ucred_t peercred; /* Peer credentials */
+ socklen_t peersize; /* Size of peer credentials */
+
+ peersize = sizeof(peercred);
+
+# ifdef __APPLE__
+ if (getsockopt(con->http.fd, 0, LOCAL_PEERCRED, &peercred, &peersize))
+# else
+ if (getsockopt(con->http.fd, SOL_SOCKET, SO_PEERCRED, &peercred,
+ &peersize))
+# endif /* __APPLE__ */
+ {
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "[Client %d] Unable to get peer credentials - %s",
+ con->http.fd, strerror(errno));
+ }
+ else
+ {
+ cupsdLogMessage(CUPSD_LOG_DEBUG,
+ "[Client %d] Using credentials for UID %d.",
+ con->http.fd, CUPSD_UCRED_UID(peercred));
+ con->gss_uid = CUPSD_UCRED_UID(peercred);
+ }
+ }
+# endif /* SO_PEERCRED && AF_LOCAL */
}
#endif /* HAVE_GSSAPI */
else
if (sscanf(authorization, "%255s", scheme) != 1)
- strcpy(scheme, "UNKNOWN");
+ strlcpy(scheme, "UNKNOWN", sizeof(scheme));
- cupsdLogMessage(CUPSD_LOG_ERROR, "Bad authentication data \"%s ...\"",
- scheme);
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "[Client %d] Bad authentication data \"%s ...\"",
+ con->http.fd, scheme);
return;
}
int allow; /* 1 if allowed, 0 otherwise */
- if (!strcasecmp(name, "localhost"))
+ if (!_cups_strcasecmp(name, "localhost"))
{
/*
* Access from localhost (127.0.0.1 or ::1) is always allowed...
* Check for exact name match...
*/
- if (!strcasecmp(name, mask->mask.name.name))
+ if (!_cups_strcasecmp(name, mask->mask.name.name))
return (1);
/*
if (name_len >= mask->mask.name.length &&
mask->mask.name.name[0] == '.' &&
- !strcasecmp(name + name_len - mask->mask.name.length,
+ !_cups_strcasecmp(name + name_len - mask->mask.name.length,
mask->mask.name.name))
return (1);
break;
*/
for (i = 0; group->gr_mem[i]; i ++)
- if (!strcasecmp(username, group->gr_mem[i]))
+ if (!_cups_strcasecmp(username, group->gr_mem[i]))
return (1);
}
}
-#ifdef HAVE_GSSAPI
-/*
- * 'cupsdCopyKrb5Creds()' - Get a copy of the Kerberos credentials.
- */
-
-krb5_ccache /* O - Credentials or NULL */
-cupsdCopyKrb5Creds(cupsd_client_t *con) /* I - Client connection */
-{
-# if !defined(HAVE_KRB5_CC_NEW_UNIQUE) && !defined(HAVE_HEIMDAL)
- cupsdLogMessage(CUPSD_LOG_INFO,
- "Sorry, your version of Kerberos does not support delegated "
- "credentials!");
- return (NULL);
-
-# else
- krb5_ccache ccache = NULL; /* Credentials */
- krb5_error_code error; /* Kerberos error code */
- OM_uint32 major_status, /* Major status code */
- minor_status; /* Minor status code */
- krb5_principal principal; /* Kerberos principal */
-
-
-# ifdef __APPLE__
- /*
- * If the weak-linked GSSAPI/Kerberos library is not present, don't try
- * to use it...
- */
-
- if (krb5_init_context == NULL)
- return (NULL);
-# endif /* __APPLE__ */
-
- if (!KerberosInitialized)
- {
- /*
- * Setup a Kerberos context for the scheduler to use...
- */
-
- KerberosInitialized = 1;
-
- if (krb5_init_context(&KerberosContext))
- {
- KerberosContext = NULL;
-
- cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to initialize Kerberos context");
- return (NULL);
- }
- }
-
- /*
- * We MUST create a file-based cache because memory-based caches are
- * only valid for the current process/address space.
- *
- * Due to various bugs/features in different versions of Kerberos, we
- * need either the krb5_cc_new_unique() function or Heimdal's version
- * of krb5_cc_gen_new() to create a new FILE: credential cache that
- * can be passed to the backend. These functions create a temporary
- * file (typically in /tmp) containing the cached credentials, which
- * are removed when we have successfully printed a job.
- */
-
-# ifdef HAVE_KRB5_CC_NEW_UNIQUE
- if ((error = krb5_cc_new_unique(KerberosContext, "FILE", NULL, &ccache)) != 0)
-# else /* HAVE_HEIMDAL */
- if ((error = krb5_cc_gen_new(KerberosContext, &krb5_fcc_ops, &ccache)) != 0)
-# endif /* HAVE_KRB5_CC_NEW_UNIQUE */
- {
- cupsdLogMessage(CUPSD_LOG_ERROR,
- "Unable to create new credentials cache (%d/%s)",
- error, strerror(errno));
- return (NULL);
- }
-
- if ((error = krb5_parse_name(KerberosContext, con->username, &principal)) != 0)
- {
- cupsdLogMessage(CUPSD_LOG_ERROR,
- "Unable to parse kerberos username (%d/%s)", error,
- strerror(errno));
- krb5_cc_destroy(KerberosContext, ccache);
- return (NULL);
- }
-
- if ((error = krb5_cc_initialize(KerberosContext, ccache, principal)))
- {
- cupsdLogMessage(CUPSD_LOG_ERROR,
- "Unable to initialize credentials cache (%d/%s)", error,
- strerror(errno));
- krb5_cc_destroy(KerberosContext, ccache);
- krb5_free_principal(KerberosContext, principal);
- return (NULL);
- }
-
- krb5_free_principal(KerberosContext, principal);
-
- /*
- * Copy the user's credentials to the new cache file...
- */
-
-# ifdef HAVE_KRB5_IPC_CLIENT_SET_TARGET_UID
- if (con->http.hostaddr->addr.sa_family == AF_LOCAL &&
- !(con->gss_flags & GSS_C_DELEG_FLAG))
- {
- /*
- * Pull the credentials directly from the user...
- */
-
- cupsd_ucred_t peercred; /* Peer credentials */
- socklen_t peersize; /* Size of peer credentials */
- krb5_ccache peerccache; /* Peer Kerberos credentials */
-
- peersize = sizeof(peercred);
-
-# ifdef __APPLE__
- if (getsockopt(con->http.fd, 0, LOCAL_PEERCRED, &peercred, &peersize))
-# else
- if (getsockopt(con->http.fd, SOL_SOCKET, SO_PEERCRED, &peercred, &peersize))
-# endif /* __APPLE__ */
- {
- cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to get peer credentials - %s",
- strerror(errno));
- krb5_cc_destroy(KerberosContext, ccache);
- return (NULL);
- }
-
- cupsdLogMessage(CUPSD_LOG_DEBUG,
- "cupsdCopyKrb5Creds: Copying credentials for UID %d...",
- CUPSD_UCRED_UID(peercred));
-
- krb5_ipc_client_set_target_uid(CUPSD_UCRED_UID(peercred));
-
- if ((error = krb5_cc_default(KerberosContext, &peerccache)) != 0)
- {
- cupsdLogMessage(CUPSD_LOG_ERROR,
- "Unable to get credentials cache for UID %d (%d/%s)",
- (int)CUPSD_UCRED_UID(peercred), error, strerror(errno));
- krb5_cc_destroy(KerberosContext, ccache);
- return (NULL);
- }
-
- error = krb5_cc_copy_creds(KerberosContext, peerccache, ccache);
- krb5_cc_close(KerberosContext, peerccache);
- krb5_ipc_client_clear_target();
-
- if (error)
- {
- cupsdLogMessage(CUPSD_LOG_ERROR,
- "Unable to copy credentials cache for UID %d (%d/%s)",
- (int)CUPSD_UCRED_UID(peercred), error, strerror(errno));
- krb5_cc_destroy(KerberosContext, ccache);
- return (NULL);
- }
- }
- else
-# endif /* HAVE_KRB5_IPC_CLIENT_SET_TARGET_UID */
- {
- major_status = gss_krb5_copy_ccache(&minor_status, con->gss_creds, ccache);
-
- if (GSS_ERROR(major_status))
- {
- cupsdLogGSSMessage(CUPSD_LOG_ERROR, major_status, minor_status,
- "Unable to copy client credentials cache");
- krb5_cc_destroy(KerberosContext, ccache);
- return (NULL);
- }
- }
-
- return (ccache);
-# endif /* !HAVE_KRB5_CC_NEW_UNIQUE && !HAVE_HEIMDAL */
-}
-#endif /* HAVE_GSSAPI */
-
-
/*
* 'cupsdCopyLocation()' - Make a copy of a location...
*/
*/
if (loc->length > bestlen && loc->location &&
- !strncasecmp(uri, loc->location, loc->length) &&
+ !_cups_strncasecmp(uri, loc->location, loc->length) &&
loc->location[0] == '/' &&
(limit & loc->limit) != 0)
{
best = con->best;
if ((type = best->type) == CUPSD_AUTH_DEFAULT)
- type = DefaultAuthType;
+ type = cupsdDefaultAuthType();
cupsdLogMessage(CUPSD_LOG_DEBUG2,
"cupsdIsAuthorized: level=CUPSD_AUTH_%s, type=%s, "
*/
if ((best->encryption >= HTTP_ENCRYPT_REQUIRED && !con->http.tls &&
- strcasecmp(con->http.hostname, "localhost") &&
+ _cups_strcasecmp(con->http.hostname, "localhost") &&
best->satisfy == CUPSD_AUTH_SATISFY_ALL) &&
- !(type == CUPSD_AUTH_NEGOTIATE ||
- (type == CUPSD_AUTH_NONE && DefaultAuthType == CUPSD_AUTH_NEGOTIATE)))
+ !(type == CUPSD_AUTH_NEGOTIATE ||
+ (type == CUPSD_AUTH_NONE &&
+ cupsdDefaultAuthType() == CUPSD_AUTH_NEGOTIATE)))
{
cupsdLogMessage(CUPSD_LOG_DEBUG,
"cupsdIsAuthorized: Need upgrade to TLS...");
return (HTTP_OK); /* unless overridden with Satisfy */
}
+
if (con->type != type && type != CUPSD_AUTH_NONE &&
+#ifdef HAVE_GSSAPI
+ (type != CUPSD_AUTH_NEGOTIATE || con->gss_uid <= 0) &&
+#endif /* HAVE_GSSAPI */
(con->type != CUPSD_AUTH_BASIC || type != CUPSD_AUTH_BASICDIGEST))
{
cupsdLogMessage(CUPSD_LOG_ERROR, "Authorized using %s, expected %s!",
name;
name = (char *)cupsArrayNext(best->names))
{
- if (!strncasecmp(name, "@AUTHKEY(", 9) && check_authref(con, name + 9))
+ if (!_cups_strncasecmp(name, "@AUTHKEY(", 9) && check_authref(con, name + 9))
return (HTTP_OK);
- else if (!strcasecmp(name, "@SYSTEM") && SystemGroupAuthKey &&
+ else if (!_cups_strcasecmp(name, "@SYSTEM") && SystemGroupAuthKey &&
check_authref(con, SystemGroupAuthKey))
return (HTTP_OK);
}
name;
name = (char *)cupsArrayNext(best->names))
{
- if (!strcasecmp(name, "@OWNER") && owner &&
- !strcasecmp(username, ownername))
+ if (!_cups_strcasecmp(name, "@OWNER") && owner &&
+ !_cups_strcasecmp(username, ownername))
return (HTTP_OK);
- else if (!strcasecmp(name, "@SYSTEM"))
+ else if (!_cups_strcasecmp(name, "@SYSTEM"))
{
for (i = 0; i < NumSystemGroups; i ++)
if (cupsdCheckGroup(username, pw, SystemGroups[i]))
if (cupsdCheckGroup(username, pw, name + 1))
return (HTTP_OK);
}
- else if (!strcasecmp(username, name))
+ else if (!_cups_strcasecmp(username, name))
return (HTTP_OK);
}
- return (HTTP_FORBIDDEN);
+ return (con->username[0] ? HTTP_FORBIDDEN : HTTP_UNAUTHORIZED);
}
/*
"cupsdIsAuthorized: Checking group \"%s\" membership...",
name);
- if (!strcasecmp(name, "@SYSTEM"))
+ if (!_cups_strcasecmp(name, "@SYSTEM"))
{
for (i = 0; i < NumSystemGroups; i ++)
if (cupsdCheckGroup(username, pw, SystemGroups[i]))
cupsdLogMessage(CUPSD_LOG_DEBUG,
"cupsdIsAuthorized: User not in group(s)!");
- return (HTTP_FORBIDDEN);
+ return (con->username[0] ? HTTP_FORBIDDEN : HTTP_UNAUTHORIZED);
}
authrights.count = 1;
authrights.items = &authright;
- authflags = kAuthorizationFlagDefaults |
+ authflags = kAuthorizationFlagDefaults |
kAuthorizationFlagExtendRights;
- if ((status = AuthorizationCopyRights(con->authref, &authrights,
- kAuthorizationEmptyEnvironment,
+ if ((status = AuthorizationCopyRights(con->authref, &authrights,
+ kAuthorizationEmptyEnvironment,
authflags, NULL)) != 0)
{
cupsdLogMessage(CUPSD_LOG_ERROR,
/*
- * End of "$Id: auth.c 7830 2008-08-04 20:38:50Z mike $".
+ * End of "$Id$".
*/