*
* Authorization routines for the CUPS scheduler.
*
- * Copyright 2007-2010 by Apple Inc.
+ * Copyright 2007-2011 by Apple Inc.
* Copyright 1997-2007 by Easy Software Products, all rights reserved.
*
* This file contains Kerberos support code, copyright 2006 by
return;
}
#ifdef HAVE_AUTHORIZATION_H
- else if (!strncmp(authorization, "AuthRef", 6) &&
+ else if (!strncmp(authorization, "AuthRef ", 8) &&
!strcasecmp(con->http.hostname, "localhost"))
{
OSStatus status; /* Status */
* Get the Authorization Services data...
*/
- authorization += 7;
+ authorization += 8;
while (isspace(*authorization & 255))
authorization ++;
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,
+ "cupsdAuthorize: Authorized as \"%s\" using AuthRef",
+ 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, "Unable to get peer credentials - %s",
+ strerror(errno));
+ return;
+ }
+
+ if ((pwd = getpwuid(CUPSD_UCRED_UID(peercred))) == NULL)
+ {
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "Unable to find UID %d for peer credentials.",
+ (int)CUPSD_UCRED_UID(peercred));
+ return;
+ }
+
+ strlcpy(username, pwd->pw_name, sizeof(username));
+
+ cupsdLogMessage(CUPSD_LOG_DEBUG,
+ "cupsdAuthorize: Authorized as \"%s\" using "
+ "AuthRef + PeerCred", username);
+ }
+
con->type = CUPSD_AUTH_BASIC;
}
#endif /* HAVE_AUTHORIZATION_H */
#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))
+ !strncmp(authorization, "Negotiate", 9))
{
/*
* 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 */
- const char *peername; /* Peer username */
+ krb5_principal peerprncpl; /* Peer's default principal */
+ char *peername; /* Peer username */
peersize = sizeof(peercred);
cupsdLogMessage(CUPSD_LOG_ERROR,
"Unable to get credentials cache for UID %d (%d/%s)",
(int)CUPSD_UCRED_UID(peercred), error, strerror(errno));
+ krb5_ipc_client_clear_target();
return;
}
- if ((peername = krb5_cc_get_name(KerberosContext, peerccache)) != NULL)
+ if ((error = krb5_cc_get_principal(KerberosContext, peerccache,
+ &peerprncpl)) != 0)
{
- 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);
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "Unable to get Kerberos principal for UID %d",
+ (int)CUPSD_UCRED_UID(peercred));
+ krb5_cc_close(KerberosContext, peerccache);
+ krb5_ipc_client_clear_target();
+ return;
}
- else
+
+ if ((error = krb5_unparse_name(KerberosContext, peerprncpl,
+ &peername)) != 0)
+ {
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();
+ return;
+ }
+
+ strlcpy(username, peername, sizeof(username));
+
+ con->have_gss = 1;
+ con->type = CUPSD_AUTH_NEGOTIATE;
+
+ free(peername);
+
+ cupsdLogMessage(CUPSD_LOG_DEBUG,
+ "cupsdAuthorize: Authorized as %s using Negotiate",
+ username);
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 */
client_name = GSS_C_NO_NAME;
major_status = gss_accept_sec_context(&minor_status,
&context,
- GSS_C_NO_CREDENTIAL,
+ GSS_C_NO_CREDENTIAL,
&input_token,
GSS_C_NO_CHANNEL_BINDINGS,
&client_name,
"cupsdAuthorize: Credentials not complete");
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))
if ((best->encryption >= HTTP_ENCRYPT_REQUIRED && !con->http.tls &&
strcasecmp(con->http.hostname, "localhost") &&
best->satisfy == CUPSD_AUTH_SATISFY_ALL) &&
- !(type == CUPSD_AUTH_NEGOTIATE ||
+ !(type == CUPSD_AUTH_NEGOTIATE ||
(type == CUPSD_AUTH_NONE && DefaultAuthType == CUPSD_AUTH_NEGOTIATE)))
{
cupsdLogMessage(CUPSD_LOG_DEBUG,
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,