]> git.ipfire.org Git - thirdparty/cups.git/blobdiff - scheduler/auth.c
Merge changes from CUPS 1.5svn-r9567
[thirdparty/cups.git] / scheduler / auth.c
index 8b3571f298805b44bdfe8ecab40d81316ebcbce4..191e17fc253a9c065f3f52aa924297a7dd237a76 100644 (file)
@@ -3,7 +3,7 @@
  *
  *   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
@@ -401,7 +401,7 @@ cupsdAuthorize(cupsd_client_t *con) /* I - Client connection */
     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 */
@@ -412,7 +412,7 @@ cupsdAuthorize(cupsd_client_t *con) /* I - Client connection */
     * Get the Authorization Services data...
     */
 
-    authorization += 7;
+    authorization += 8;
     while (isspace(*authorization & 255))
       authorization ++;
 
@@ -435,21 +435,58 @@ cupsdAuthorize(cupsd_client_t *con)       /* I - Client connection */
       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 */
@@ -944,7 +981,7 @@ cupsdAuthorize(cupsd_client_t *con) /* I - Client connection */
 #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...
@@ -954,7 +991,8 @@ cupsdAuthorize(cupsd_client_t *con) /* I - Client connection */
     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);
 
@@ -998,30 +1036,48 @@ cupsdAuthorize(cupsd_client_t *con)      /* I - Client connection */
       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 */
@@ -1084,7 +1140,7 @@ cupsdAuthorize(cupsd_client_t *con)       /* I - Client connection */
     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,
@@ -1120,7 +1176,7 @@ cupsdAuthorize(cupsd_client_t *con)       /* I - Client connection */
                         "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))
@@ -2074,7 +2130,7 @@ cupsdIsAuthorized(cupsd_client_t *con,    /* I - Connection */
   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,
@@ -2356,11 +2412,11 @@ check_authref(cupsd_client_t *con,      /* I - Connection */
   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,