]> git.ipfire.org Git - thirdparty/cups.git/commitdiff
Use GSS framework, when available, and support acquisition of Kerberos creds
authormike <mike@7a7537e8-13f0-0310-91df-b6672ffda945>
Sun, 1 May 2011 19:55:04 +0000 (19:55 +0000)
committermike <mike@7a7537e8-13f0-0310-91df-b6672ffda945>
Sun, 1 May 2011 19:55:04 +0000 (19:55 +0000)
when the underlying libraries support it (may add others as time permits).

git-svn-id: svn+ssh://src.apple.com/svn/cups/cups.org/trunk@9732 7a7537e8-13f0-0310-91df-b6672ffda945

12 files changed:
config-scripts/cups-gssapi.m4
config-scripts/cups-ssl.m4
config.h.in
cups/auth.c
cups/cups-private.h
cups/http-addrlist.c
cups/http-private.h
cups/request.c
scheduler/auth.c
scheduler/client.c
vcnet/config.h
xcode/config.h

index 7c61735b809477afab5f580ae35c7433a5b2e29c..dc109289031b6c6b833389fbd53cbaa494e596e8 100644 (file)
@@ -28,19 +28,26 @@ if test x$enable_gssapi != xno; then
                        Darwin)
                                # Mac OS X weak-links to the Kerberos framework...
                                LIBGSSAPI="-weak_framework Kerberos"
+                               AC_MSG_CHECKING(for GSS framework)
+                               if test -d /System/Library/Frameworks/GSS.framework; then
+                                       AC_MSG_RESULT(yes)
+                                       LIBGSSAPI="$LIBGSSAPI -weak_framework GSS"
+                               else
+                                       AC_MSG_RESULT(no)
+                               fi
                                ;;
                        SunOS*)
                                # Solaris has a non-standard krb5-config, don't use it!
                                AC_CHECK_LIB(gss, gss_display_status,
                                        AC_DEFINE(HAVE_GSSAPI, 1, [Whether GSSAPI is available])
-                                       CFLAGS="`$KRB5CONFIG --cflags` $CFLAGS"         
-                                       CPPFLAGS="`$KRB5CONFIG --cflags` $CPPFLAGS"             
+                                       CFLAGS="`$KRB5CONFIG --cflags` $CFLAGS"
+                                       CPPFLAGS="`$KRB5CONFIG --cflags` $CPPFLAGS"
                                        LIBGSSAPI="-lgss `$KRB5CONFIG --libs`")
                                ;;
                        *)
                                # Other platforms just ask for GSSAPI
-                               CFLAGS="`$KRB5CONFIG --cflags gssapi` $CFLAGS"          
-                               CPPFLAGS="`$KRB5CONFIG --cflags gssapi` $CPPFLAGS"              
+                               CFLAGS="`$KRB5CONFIG --cflags gssapi` $CFLAGS"
+                               CPPFLAGS="`$KRB5CONFIG --cflags gssapi` $CPPFLAGS"
                                LIBGSSAPI="`$KRB5CONFIG --libs gssapi`"
                                ;;
                esac
@@ -63,26 +70,37 @@ if test x$enable_gssapi != xno; then
 
        if test "x$LIBGSSAPI" != x; then
                AC_CHECK_HEADER(krb5.h, AC_DEFINE(HAVE_KRB5_H))
-               AC_CHECK_HEADER(gssapi.h, AC_DEFINE(HAVE_GSSAPI_H))
-               AC_CHECK_HEADER(gssapi/gssapi.h, AC_DEFINE(HAVE_GSSAPI_GSSAPI_H))
-               AC_CHECK_HEADER(gssapi/gssapi_generic.h, AC_DEFINE(HAVE_GSSAPI_GSSAPI_GENERIC_H))
-               AC_CHECK_HEADER(gssapi/gssapi_krb5.h, AC_DEFINE(HAVE_GSSAPI_GSSAPI_KRB5_H))
+               if test -d /System/Library/Frameworks/GSS.framework; then
+                       AC_CHECK_HEADER(GSS/gssapi.h, AC_DEFINE(HAVE_GSS_GSSAPI_H))
+                       AC_CHECK_HEADER(GSS/gssapi_generic.h, AC_DEFINE(HAVE_GSSAPI_GENERIC_H))
+                       AC_CHECK_HEADER(GSS/gssapi_krb5.h, AC_DEFINE(HAVE_GSSAPI_KRB5_H))
+                       AC_CHECK_HEADER(GSS/gssapi_spi.h, AC_DEFINE(HAVE_GSS_GSSAPI_SPI_H))
+               else
+                       AC_CHECK_HEADER(gssapi.h, AC_DEFINE(HAVE_GSSAPI_H))
+                       AC_CHECK_HEADER(gssapi/gssapi.h, AC_DEFINE(HAVE_GSSAPI_GSSAPI_H))
+                       AC_CHECK_HEADER(gssapi/gssapi_generic.h, AC_DEFINE(HAVE_GSSAPI_GENERIC_H))
+                       AC_CHECK_HEADER(gssapi/gssapi_krb5.h, AC_DEFINE(HAVE_GSSAPI_KRB5_H))
+               fi
 
                SAVELIBS="$LIBS"
                LIBS="$LIBS $LIBGSSAPI"
 
-               AC_CHECK_FUNC(gsskrb5_register_acceptor_identity, 
-                             AC_DEFINE(HAVE_GSSKRB5_REGISTER_ACCEPTOR_IDENTITY))
-               AC_CHECK_FUNC(krb5_cc_new_unique, AC_DEFINE(HAVE_KRB5_CC_NEW_UNIQUE))
-               AC_CHECK_FUNC(krb5_ipc_client_set_target_uid, AC_DEFINE(HAVE_KRB5_IPC_CLIENT_SET_TARGET_UID))
+               AC_CHECK_FUNC(__ApplePrivate_gss_acquire_cred_ex_f,
+                             AC_DEFINE(HAVE_GSS_ACQUIRE_CRED_EX_F))
 
                AC_MSG_CHECKING(for GSS_C_NT_HOSTBASED_SERVICE)
-               if test $ac_cv_header_gssapi_gssapi_h = yes; then
+               if test x$ac_cv_header_gssapi_gssapi_h = xyes; then
                        AC_TRY_COMPILE([ #include <gssapi/gssapi.h> ],
                                       [ gss_OID foo = GSS_C_NT_HOSTBASED_SERVICE; ],
                                       AC_DEFINE(HAVE_GSS_C_NT_HOSTBASED_SERVICE)
                                       AC_MSG_RESULT(yes),
                                       AC_MSG_RESULT(no))
+               elif test x$ac_cv_header_gss_gssapi_h = xyes; then
+                       AC_TRY_COMPILE([ #include <GSS/gssapi.h> ],
+                                      [ gss_OID foo = GSS_C_NT_HOSTBASED_SERVICE; ],
+                                      AC_DEFINE(HAVE_GSS_C_NT_HOSTBASED_SERVICE)
+                                      AC_MSG_RESULT(yes),
+                                      AC_MSG_RESULT(no))
                else
                        AC_TRY_COMPILE([ #include <gssapi.h> ],
                                       [ gss_OID foo = GSS_C_NT_HOSTBASED_SERVICE; ],
@@ -92,13 +110,6 @@ if test x$enable_gssapi != xno; then
                fi
 
                LIBS="$SAVELIBS"
-
-               AC_MSG_CHECKING(for Heimdal Kerberos)
-               AC_TRY_COMPILE([ #include <krb5.h> ],
-                              [ char *tmp = heimdal_version; ],
-                              AC_DEFINE(HAVE_HEIMDAL)
-                              AC_MSG_RESULT(yes),
-                              AC_MSG_RESULT(no))
        fi
 fi
 
index c75c76d9941ef85abe003a722dc3f0b9f67b79b9..899632639949bbaa869ea5c13920cfea9cc7e047 100644 (file)
@@ -43,7 +43,8 @@ if test x$enable_ssl != xno; then
                AC_CHECK_HEADER(Security/SecItem.h,
                    AC_DEFINE(HAVE_SECITEM_H))
                AC_CHECK_HEADER(Security/SecItemPriv.h,
-                   AC_DEFINE(HAVE_SECITEMPRIV_H))
+                   AC_DEFINE(HAVE_SECITEMPRIV_H),,
+                   [#include <Security/SecItem.h>])
                AC_CHECK_HEADER(Security/SecPolicy.h,
                    AC_DEFINE(HAVE_SECPOLICY_H))
                AC_CHECK_HEADER(Security/SecPolicyPriv.h,
index 44e1e4012358ccfca5331b27254992b33fa8a0bd..823af9093146aca3c82786a03de3d880be884f72 100644 (file)
 #undef HAVE_STRINGS_H
 #undef HAVE_BSTRING_H
 
+
 /*
  * Do we have the long long type?
  */
 #  define CUPS_LLCAST  (long)
 #endif /* HAVE_LONG_LONG */
 
+
 /*
  * Do we have the strtoll() function?
  */
 #  define strtoll(nptr,endptr,base) strtol((nptr), (endptr), (base))
 #endif /* !HAVE_STRTOLL */
 
+
 /*
  * Do we have the strXXX() functions?
  */
 
 
 /*
- * Do we have MacOSX 10.4's mbr_XXX functions?
+ * Do we have Mac OS X 10.4's mbr_XXX functions?
  */
 
 #undef HAVE_MEMBERSHIP_H
 #undef HAVE_DBUS_MESSAGE_ITER_INIT_APPEND
 
 
-/*
- * Do we have the AppleTalk/at_proto.h header?
- */
-
-#undef HAVE_APPLETALK_AT_PROTO_H
-
-
 /*
  * Do we have the GSSAPI support library (for Kerberos support)?
  */
 
+#undef HAVE_GSS_ACQUIRE_CRED_EX_F
+#undef HAVE_GSS_C_NT_HOSTBASED_SERVICE
+#undef HAVE_GSS_GSSAPI_H
+#undef HAVE_GSS_GSSAPI_SPI_H
 #undef HAVE_GSSAPI
-#undef HAVE_GSSAPI_H
+#undef HAVE_GSSAPI_GENERIC_H
 #undef HAVE_GSSAPI_GSSAPI_H
-#undef HAVE_GSSAPI_GSSAPI_GENERIC_H
-#undef HAVE_GSSAPI_GSSAPI_KRB5_H
-#undef HAVE_GSSKRB5_REGISTER_ACCEPTOR_IDENTITY
-#undef HAVE_GSS_C_NT_HOSTBASED_SERVICE
-#undef HAVE_KRB5_CC_NEW_UNIQUE
-#undef HAVE_KRB5_IPC_CLIENT_SET_TARGET_UID
+#undef HAVE_GSSAPI_H
+#undef HAVE_GSSAPI_KRB5_H
 #undef HAVE_KRB5_H
-#undef HAVE_HEIMDAL
 
 
 /*
index 9fa74b55b059c782218ffb69b68ac82b767dcc59..5ab48e0531f85124df2c41b15efa97b8b6a62600 100644 (file)
  *
  * Contents:
  *
- *   cupsDoAuthentication() - Authenticate a request.
- *   cups_get_gssname()     - Get GSSAPI name for authentication.
- *   cups_gss_printf()      - Show error messages from GSSAPI...
- *   cups_local_auth()      - Get the local authorization certificate if
- *                            available/applicable...
+ *   cupsDoAuthentication()        - Authenticate a request.
+ *   _cupsSetNegotiateAuthString() - Set the Kerberos authentication string.
+ *   cups_gss_acquire()            - Kerberos credentials callback.
+ *   cups_gss_getname()            - Get CUPS service credentials for
+ *                                   authentication.
+ *   cups_gss_printf()             - Show debug error messages from GSSAPI.
+ *   cups_local_auth()             - Get the local authorization certificate if
+ *                                   available/applicable.
  */
 
 /*
@@ -58,7 +61,42 @@ extern const char *cssmErrorString(int error);
  */
 
 #ifdef HAVE_GSSAPI
-static gss_name_t cups_get_gssname(http_t *http, const char *service_name);
+#  ifdef HAVE_GSS_ACQUIRE_CRED_EX_F
+#    ifdef HAVE_GSS_GSSAPI_SPI_H
+#      include <GSS/gssapi_spi.h>
+#    else
+typedef struct gss_auth_identity
+{
+  uint32_t type;
+  uint32_t flags;
+  char *username;
+  char *realm;
+  char *password;
+  gss_buffer_t *credentialsRef;
+} gss_auth_identity_desc;
+extern OM_uint32 gss_acquire_cred_ex_f(gss_status_id_t, const gss_name_t,
+                                      OM_uint32, OM_uint32, const gss_OID,
+                                      gss_cred_usage_t, gss_auth_identity_t,
+                                      void *, void (*)(void *, OM_uint32,
+                                                       gss_status_id_t,
+                                                       gss_cred_id_t,
+                                                       gss_OID_set,
+                                                       OM_uint32));
+#    endif /* HAVE_GSS_GSSAPI_SPI_H */
+#    include <dispatch/dispatch.h>
+typedef struct _cups_gss_acquire_s     /* Acquire callback data */
+{
+  dispatch_semaphore_t sem;            /* Synchronization semaphore */
+  OM_uint32            major;          /* Returned status code */
+  gss_cred_id_t                creds;          /* Returned credentials */
+} _cups_gss_acquire_t;
+
+static void    cups_gss_acquire(void *ctx, OM_uint32 major,
+                                gss_status_id_t status,
+                                gss_cred_id_t creds, gss_OID_set oids,
+                                OM_uint32 time_rec);
+#  endif /* HAVE_GSS_ACQUIRE_CRED_EX_F */
+static gss_name_t cups_gss_getname(http_t *http, const char *service_name);
 #  ifdef DEBUG
 static void    cups_gss_printf(OM_uint32 major_status, OM_uint32 minor_status,
                                const char *message);
@@ -193,7 +231,7 @@ cupsDoAuthentication(
     * Kerberos authentication...
     */
 
-    if (_cupsSetNegotiateAuthString(http))
+    if (_cupsSetNegotiateAuthString(http, method, resource))
     {
       http->status = HTTP_AUTHORIZATION_CANCELED;
       return (-1);
@@ -255,7 +293,9 @@ cupsDoAuthentication(
 
 int                                    /* O - 0 on success, -1 on error */
 _cupsSetNegotiateAuthString(
-    http_t *http)                      /* I - Connection to server */
+    http_t     *http,                  /* I - Connection to server */
+    const char *method,                        /* I - Request method ("GET", "POST", "PUT") */
+    const char *resource)              /* I - Resource path */
 {
   OM_uint32    minor_status,           /* Minor status code */
                major_status;           /* Major status code */
@@ -283,7 +323,7 @@ _cupsSetNegotiateAuthString(
     if (!cg->gss_service_name[0])
       _cupsSetDefaults();
 
-    http->gssname = cups_get_gssname(http, cg->gss_service_name);
+    http->gssname = cups_gss_getname(http, cg->gss_service_name);
   }
 
   if (http->gssctx != GSS_C_NO_CONTEXT)
@@ -292,14 +332,94 @@ _cupsSetNegotiateAuthString(
     http->gssctx = GSS_C_NO_CONTEXT;
   }
 
-  major_status  = gss_init_sec_context(&minor_status, GSS_C_NO_CREDENTIAL,
-                                      &http->gssctx,
-                                      http->gssname, http->gssmech,
-                                      GSS_C_MUTUAL_FLAG | GSS_C_INTEG_FLAG,
-                                      GSS_C_INDEFINITE,
-                                      GSS_C_NO_CHANNEL_BINDINGS,
-                                      GSS_C_NO_BUFFER, &http->gssmech,
-                                      &output_token, NULL, NULL);
+  major_status = gss_init_sec_context(&minor_status, GSS_C_NO_CREDENTIAL,
+                                     &http->gssctx,
+                                     http->gssname, http->gssmech,
+                                     GSS_C_MUTUAL_FLAG | GSS_C_INTEG_FLAG,
+                                     GSS_C_INDEFINITE,
+                                     GSS_C_NO_CHANNEL_BINDINGS,
+                                     GSS_C_NO_BUFFER, &http->gssmech,
+                                     &output_token, NULL, NULL);
+
+#ifdef HAVE_GSS_ACQUIRE_CRED_EX_F
+  if (major_status == GSS_S_NO_CRED)
+  {
+   /*
+    * Ask the user for credentials...
+    */
+
+    char               prompt[1024],   /* Prompt for user */
+                       userbuf[256];   /* Kerberos username */
+    const char         *username,      /* Username string */
+                       *password;      /* Password string */
+    _cups_gss_acquire_t        data;           /* Callback data */
+    gss_auth_identity_desc identity;   /* Kerberos user identity */
+
+    if (!cg->lang_default)
+      cg->lang_default = cupsLangDefault();
+
+    snprintf(prompt, sizeof(prompt),
+             _cupsLangString(cg->lang_default, _("Password for %s on %s? ")),
+            cupsUser(), http->gssname);
+
+    if ((password = cupsGetPassword2(prompt, http, method, resource)) == NULL)
+      return (-1);
+
+   /*
+    * Try to acquire credentials...
+    */
+
+    username = cupsUser();
+    if (!strchr(username, '@'))
+    {
+      snprintf(userbuf, sizeof(userbuf), "%s@%s", username, http->gssname);
+      username = userbuf;
+    }
+
+    identity.type           = GSS_AUTH_IDENTITY_TYPE_1;
+    identity.flags          = 0;
+    identity.username       = (char *)username;
+    identity.realm          = (char *)"";
+    identity.password       = (char *)password;
+    identity.credentialsRef = NULL;
+
+    data.sem   = dispatch_semaphore_create(0);
+    data.major = 0;
+    data.creds = NULL;
+
+    if (data.sem)
+    {
+      major_status = gss_acquire_cred_ex_f(NULL, GSS_C_NO_NAME, 0,
+                                          GSS_C_INDEFINITE, GSS_KRB5_MECHANISM,
+                                          GSS_C_INITIATE, &identity, &data,
+                                          cups_gss_acquire);
+
+      if (major_status == GSS_S_COMPLETE)
+      {
+       dispatch_semaphore_wait(data.sem, DISPATCH_TIME_FOREVER);
+       major_status = data.major;
+      }
+
+      dispatch_release(data.sem);
+
+      if (major_status == GSS_S_COMPLETE)
+      {
+        OM_uint32      release_minor;  /* Minor status from releasing creds */
+
+       major_status = gss_init_sec_context(&minor_status, data.creds,
+                                           &http->gssctx,
+                                           http->gssname, http->gssmech,
+                                           GSS_C_MUTUAL_FLAG | GSS_C_INTEG_FLAG,
+                                           GSS_C_INDEFINITE,
+                                           GSS_C_NO_CHANNEL_BINDINGS,
+                                           GSS_C_NO_BUFFER, &http->gssmech,
+                                           &output_token, NULL, NULL);
+        gss_release_cred(&release_minor, &data.creds);
+      }
+    }
+  }
+  else
+#endif /* HAVE_GSS_ACQUIRED_CRED_EX_F */
 
   if (GSS_ERROR(major_status))
   {
@@ -310,7 +430,7 @@ _cupsSetNegotiateAuthString(
   }
 
 #ifdef DEBUG
-  if (major_status == GSS_S_CONTINUE_NEEDED)
+  else if (major_status == GSS_S_CONTINUE_NEEDED)
     cups_gss_printf(major_status, minor_status,
                    "_cupsSetNegotiateAuthString: Continuation needed!");
 #endif /* DEBUG */
@@ -353,12 +473,42 @@ _cupsSetNegotiateAuthString(
 }
 
 
+#  ifdef HAVE_GSS_ACQUIRE_CRED_EX_F
 /*
- * 'cups_get_gssname()' - Get CUPS service credentials for authentication.
+ * 'cups_gss_acquire()' - Kerberos credentials callback.
+ */
+static void
+cups_gss_acquire(
+    void            *ctx,              /* I - Caller context */
+    OM_uint32       major,             /* I - Major error code */
+    gss_status_id_t status,            /* I - Status (unused) */
+    gss_cred_id_t   creds,             /* I - Credentials (if any) */
+    gss_OID_set     oids,              /* I - Mechanism OIDs (unused) */
+    OM_uint32       time_rec)          /* I - Timestamp (unused) */
+{
+  uint32_t             min;            /* Minor error code */
+  _cups_gss_acquire_t  *data;          /* Callback data */
+
+
+  (void)status;
+  (void)time_rec;
+
+  data        = (_cups_gss_acquire_t *)ctx;
+  data->major = major;
+  data->creds = creds;
+
+  gss_release_oid_set(&min, &oids);
+  dispatch_semaphore_signal(data->sem);
+}
+#  endif /* HAVE_GSS_ACQUIRE_CRED_EX_F */
+
+
+/*
+ * 'cups_gss_getname()' - Get CUPS service credentials for authentication.
  */
 
 static gss_name_t                      /* O - Server name */
-cups_get_gssname(
+cups_gss_getname(
     http_t     *http,                  /* I - Connection to server */
     const char *service_name)          /* I - Service name */
 {
@@ -367,11 +517,10 @@ cups_get_gssname(
   OM_uint32      major_status,         /* Major status code */
                  minor_status;         /* Minor status code */
   gss_name_t     server_name;          /* Server name */
-  char           buf[1024],            /* Name buffer */
-                 fqdn[HTTP_MAX_URI];   /* Server name buffer */
+  char           buf[1024];            /* Name buffer */
 
 
-  DEBUG_printf(("7cups_get_gssname(http=%p, service_name=\"%s\")", http,
+  DEBUG_printf(("7cups_gss_getname(http=%p, service_name=\"%s\")", http,
                 service_name));
 
 
@@ -379,18 +528,54 @@ cups_get_gssname(
   * Get the hostname...
   */
 
-  httpGetHostname(http, fqdn, sizeof(fqdn));
+  if (!http->gsshost[0])
+  {
+    httpGetHostname(http, http->gsshost, sizeof(http->gsshost));
 
-  if (!strcmp(fqdn, "localhost"))
-    httpGetHostname(NULL, fqdn, sizeof(fqdn));
+    if (!strcmp(http->gsshost, "localhost"))
+    {
+      if (gethostname(http->gsshost, sizeof(http->gsshost)) < 0)
+      {
+       DEBUG_printf(("1cups_gss_getname: gethostname() failed: %s",
+                     strerror(errno)));
+       http->gsshost[0] = '\0';
+       return (NULL);
+      }
+
+      if (!strchr(http->gsshost, '.'))
+      {
+       /*
+       * The hostname is not a FQDN, so look it up...
+       */
+
+       struct hostent  *host;          /* Host entry to get FQDN */
+
+       if ((host = gethostbyname(http->gsshost)) != NULL && host->h_name)
+       {
+        /*
+         * Use the resolved hostname...
+         */
+
+         strlcpy(http->gsshost, host->h_name, sizeof(http->gsshost));
+       }
+       else
+       {
+         DEBUG_printf(("1cups_gss_getname: gethostbyname(\"%s\") failed.",
+                       http->gsshost));
+         http->gsshost[0] = '\0';
+         return (NULL);
+       }
+      }
+    }
+  }
 
  /*
-  * Get a server name we can use for authentication purposes...
+  * Get a service name we can use for authentication purposes...
   */
 
-  snprintf(buf, sizeof(buf), "%s@%s", service_name, fqdn);
+  snprintf(buf, sizeof(buf), "%s@%s", service_name, http->gsshost);
 
-  DEBUG_printf(("9cups_get_gssname: Looking up %s...", buf));
+  DEBUG_printf(("8cups_gss_getname: Looking up \"%s\".", buf));
 
   token.value  = buf;
   token.length = strlen(buf);
@@ -402,7 +587,7 @@ cups_get_gssname(
   if (GSS_ERROR(major_status))
   {
     cups_gss_printf(major_status, minor_status,
-                    "cups_get_gssname: gss_import_name() failed");
+                    "cups_gss_getname: gss_import_name() failed");
     return (NULL);
   }
 
@@ -412,7 +597,7 @@ cups_get_gssname(
 
 #  ifdef DEBUG
 /*
- * 'cups_gss_printf()' - Show debug error messages from GSSAPI...
+ * 'cups_gss_printf()' - Show debug error messages from GSSAPI.
  */
 
 static void
@@ -453,7 +638,7 @@ cups_gss_printf(OM_uint32  major_status,/* I - Major status code */
 
 /*
  * 'cups_local_auth()' - Get the local authorization certificate if
- *                       available/applicable...
+ *                       available/applicable.
  */
 
 static int                             /* O - 0 if available */
index b60c39341ff7aebc073af1a814bffdd27aa5321d..25d3fd66613738f9b6d7b6a56393925f2e605cbb 100644 (file)
@@ -189,7 +189,9 @@ extern void         _cupsSetError(ipp_status_t status, const char *message,
                                      int localize);
 extern void            _cupsSetHTTPError(http_status_t status);
 #  ifdef HAVE_GSSAPI
-extern int             _cupsSetNegotiateAuthString(http_t *http);
+extern int             _cupsSetNegotiateAuthString(http_t *http,
+                                                   const char *method,
+                                                   const char *resource);
 #  endif /* HAVE_GSSAPI */
 extern char            *_cupsUserDefault(char *name, size_t namesize);
 
index b4b9d82fd4eaf9081cbe2edc4a2435e016add72a..664b9cba2fe68e43733acccf643e7d828622d368 100644 (file)
@@ -169,7 +169,7 @@ httpAddrConnect(
   }
 
   if (!addrlist)
-    _cupsSetError(HTTP_SERVICE_UNAVAILABLE, _("Unable to connect to server"), 1);
+    _cupsSetError(IPP_SERVICE_UNAVAILABLE, _("Unable to connect to server"), 1);
 
   return (addrlist);
 }
index f5dbebbde35bab7c145e1266a786751b3ca202fb..33d90b2b848b728fa9e7b77fd37cb33f285cdd35 100644 (file)
 #  endif /* WIN32 */
 
 #  ifdef HAVE_GSSAPI
-#    ifdef HAVE_GSSAPI_GSSAPI_H
+#    ifdef HAVE_GSS_GSSAPI_H
+#      include <GSS/gssapi.h>
+#      ifdef HAVE_GSSAPI_GENERIC_H
+#        include <GSS/gssapi_generic.h>
+#      endif /* HAVE_GSSAPI_GENERIC_H */
+#      ifdef HAVE_GSSAPI_KRB5_H
+#        include <GSS/gssapi_krb5.h>
+#      endif /* HAVE_GSSAPI_KRB5_H */
+#    elif defined(HAVE_GSSAPI_GSSAPI_H)
 #      include <gssapi/gssapi.h>
-#    endif /* HAVE_GSSAPI_GSSAPI_H */
-#    ifdef HAVE_GSSAPI_GSSAPI_GENERIC_H
-#      include <gssapi/gssapi_generic.h>
-#    endif /* HAVE_GSSAPI_GSSAPI_GENERIC_H */
-#    ifdef HAVE_GSSAPI_GSSAPI_KRB5_H
-#      include <gssapi/gssapi_krb5.h>
-#    endif /* HAVE_GSSAPI_GSSAPI_KRB5_H */
-#    ifdef HAVE_GSSAPI_H
+#      ifdef HAVE_GSSAPI_GENERIC_H
+#        include <gssapi/gssapi_generic.h>
+#      endif /* HAVE_GSSAPI_GENERIC_H */
+#      ifdef HAVE_GSSAPI_KRB5_H
+#        include <gssapi/gssapi_krb5.h>
+#      endif /* HAVE_GSSAPI_KRB5_H */
+#    elif defined(HAVE_GSSAPI_H)
 #      include <gssapi.h>
-#    endif /* HAVE_GSSAPI_H */
+#    endif /* HAVE_GSS_GSSAPI_H */
 #    ifndef HAVE_GSS_C_NT_HOSTBASED_SERVICE
 #      define GSS_C_NT_HOSTBASED_SERVICE gss_nt_service_name
 #    endif /* !HAVE_GSS_C_NT_HOSTBASED_SERVICE */
@@ -290,6 +297,9 @@ struct _http_s                              /**** HTTP connection structure. ****/
   _http_timeout_cb_t   timeout_cb;     /* Timeout callback @since CUPS 1.5@ */
   void                 *timeout_data;  /* User data pointer @since CUPS 1.5@ */
   struct timeval       timeout_value;  /* Timeout in seconds */
+#  ifdef HAVE_GSSAPI
+  char                 gsshost[256];   /* Hostname for Kerberos */
+#  endif /* HAVE_GSSAPI */
 };
 
 
index 3c2e076666d085717cd99438bf5ba98b8fcd20ef..7f98b48379d23848373babcdf3f674bee1d3a791 100644 (file)
@@ -691,7 +691,7 @@ cupsSendRequest(http_t     *http,   /* I - Connection to server or @code CUPS_HTTP
       * "replay" attack...
       */
 
-      _cupsSetNegotiateAuthString(http);
+      _cupsSetNegotiateAuthString(http, "POST", resource);
     }
 #endif /* HAVE_GSSAPI */
 
index 11c0bc935ba3648d9d424f9959288487e7638014..0cfb599f57722e91b5a978ef1c262b047ae6866c 100644 (file)
@@ -559,6 +559,10 @@ cupsdAuthorize(cupsd_client_t *con)        /* I - Client connection */
 
     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",
                    username);
@@ -1122,7 +1126,7 @@ cupsdAuthorize(cupsd_client_t *con)       /* I - Client connection */
     * to run as the correct user to get Kerberos credentials of its own.
     */
 
-    if (con->http.hostaddr->addr.sa_family == AF_LOCAL)
+    if (_httpAddrFamily(con->http.hostaddr) == AF_LOCAL)
     {
       cupsd_ucred_t    peercred;       /* Peer credentials */
       socklen_t                peersize;       /* Size of peer credentials */
@@ -1959,7 +1963,11 @@ cupsdIsAuthorized(cupsd_client_t *con,   /* I - Connection */
        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!",
index 87bdbf7c12669b66e572e33a16e16f8e87aedf5d..cfb9b506f36f69dd78eb32812e49bec4e7b7e0f6 100644 (file)
@@ -2588,8 +2588,15 @@ cupsdSendHeader(
       snprintf(auth_str, sizeof(auth_str), "Digest realm=\"CUPS\", nonce=\"%s\"",
               con->http.hostname);
 #ifdef HAVE_GSSAPI
-    else if (auth_type == CUPSD_AUTH_NEGOTIATE /* && con->gss_output_token.length == 0 */)
+    else if (auth_type == CUPSD_AUTH_NEGOTIATE)
+    {
+#  ifdef AF_LOCAL
+      if (_httpAddrFamily(con->http.hostaddr) == AF_LOCAL)
+        strlcpy(auth_str, "Basic realm=\"CUPS\"", sizeof(auth_str));
+      else
+#  endif /* AF_LOCAL */
       strlcpy(auth_str, "Negotiate", sizeof(auth_str));
+    }
 #endif /* HAVE_GSSAPI */
 
     if (con->best && auth_type != CUPSD_AUTH_NEGOTIATE &&
@@ -2651,65 +2658,6 @@ cupsdSendHeader(
     }
   }
 
-#if 0 /* def HAVE_GSSAPI */
- /*
-  * WWW-Authenticate: Negotiate can be included even for
-  * non-401 replies...
-  */
-
-  if (con->gss_output_token.length > 0 && con->gss_output_token.length <= 65536)
-  {
-    OM_uint32  minor_status;           /* Minor status code */
-    int                bufsize;                /* Size of output token buffer */
-
-
-    bufsize = con->gss_output_token.length * 4 / 3 + 2;
-
-    if (bufsize > gss_bufsize)
-    {
-      char     *buf;                   /* New buffer */
-
-
-      bufsize = (bufsize + 1023) & 1023;/* Round up */
-
-      if (gss_buf)
-        buf = realloc(gss_buf, bufsize);
-      else
-        buf = malloc(bufsize);
-
-      if (!buf)
-      {
-       cupsdLogMessage(CUPSD_LOG_ERROR,
-                       "Unable to allocate %d bytes for Kerberos credentials!",
-                       bufsize);
-       return (0);
-      }
-
-      gss_buf     = buf;
-      gss_bufsize = bufsize;
-    }
-
-    httpEncode64_2(gss_buf, gss_bufsize,
-                  con->gss_output_token.value,
-                  con->gss_output_token.length);
-    gss_release_buffer(&minor_status, &con->gss_output_token);
-
-    cupsdLogMessage(CUPSD_LOG_DEBUG,
-                   "cupsdSendHeader: WWW-Authenticate: Negotiate %s", gss_buf);
-
-    if (httpPrintf(HTTP(con), "WWW-Authenticate: Negotiate %s\r\n",
-                   gss_buf) < 0)
-      return (0);
-  }
-  else if (con->gss_output_token.length > 65536)
-  {
-    cupsdLogMessage(CUPSD_LOG_ERROR,
-                    "Kerberos credentials larger than 64k (%d)!",
-                   (int)con->gss_output_token.length);
-    return (0);
-  }
-#endif /* HAVE_GSSAPI */
-
   if (con->language && strcmp(con->language->language, "C"))
   {
     if (httpPrintf(HTTP(con), "Content-Language: %s\r\n",
index 011b2f49a3c899bee0efd17e419c1bdd231459d6..282349752cf18230ea6d148750c1043611a7f11c 100644 (file)
@@ -1,9 +1,9 @@
 /*
  * "$Id$"
  *
- *   Configuration file for CUPS.
+ *   Configuration file for CUPS on Windows.
  *
- *   Copyright 2007-2010 by Apple Inc.
+ *   Copyright 2007-2011 by Apple Inc.
  *   Copyright 1997-2007 by Easy Software Products.
  *
  *   These coded instructions, statements, and computer programs are the
 /* #undef HAVE_SECIDENTITYSEARCHCREATEWITHPOLICY */
 
 
+/*
+ * Do we have the SecPolicyCreateSSL function?
+ */
+
+/* #undef HAVE_SECPOLICYCREATESSL */
+
+
+/*
+ * Do we have the SecPolicyCreateSSL function?
+ */
+
+/* #undef HAVE_SECPOLICYCREATESSL */
+
+
+/*
+ * Do we have the cssmErrorString function?
+ */
+
+/* #undef HAVE_CSSMERRORSTRING */
+
+
 /*
  * Do we have the SLP library?
  */
 #define HAVE_DNSSD 1
 
 
+/*
+ * Does the "stat" structure contain the "st_gen" member?
+ */
+
+/* #undef HAVE_ST_GEN */
+
+
 /*
  * Do we have <sys/ioctl.h>?
  */
 
 
 /*
- * Do we have MacOSX 10.4's mbr_XXX functions()?
+ * Do we have Mac OS X 10.4's mbr_XXX functions?
  */
 
 /* #undef HAVE_MEMBERSHIP_H */
 
 
 /*
- * Do we have Darwin's notify_post() header and function?
+ * Do we have Darwin's notify_post header and function?
  */
 
 /* #undef HAVE_NOTIFY_H */
 
 
 /*
- * Do we have DBUS?
+ * Do we have Darwin's IOKit private headers?
  */
 
-/* #undef HAVE_DBUS */
-/* #undef HAVE_DBUS_MESSAGE_ITER_INIT_APPEND */
+/* #undef HAVE_IOKIT_PWR_MGT_IOPMLIBPRIVATE_H */
 
 
 /*
- * Do we have the AppleTalk/at_proto.h header?
+ * Do we have DBUS?
  */
 
-/* #undef HAVE_APPLETALK_AT_PROTO_H */
+/* #undef HAVE_DBUS */
+/* #undef HAVE_DBUS_MESSAGE_ITER_INIT_APPEND */
 
 
 /*
  * Do we have the GSSAPI support library (for Kerberos support)?
  */
 
+/* #undef HAVE_GSS_ACQUIRE_CRED_EX_F */
+/* #undef HAVE_GSS_C_NT_HOSTBASED_SERVICE */
+/* #undef HAVE_GSS_GSSAPI_H */
+/* #undef HAVE_GSS_GSSAPI_SPI_H */
 /* #undef HAVE_GSSAPI */
-/* #undef HAVE_GSSAPI_H */
+/* #undef HAVE_GSSAPI_GENERIC_H */
 /* #undef HAVE_GSSAPI_GSSAPI_H */
-/* #undef HAVE_GSSAPI_GSSAPI_GENERIC_H */
-/* #undef HAVE_GSSAPI_GSSAPI_KRB5_H */
-/* #undef HAVE_GSSKRB5_REGISTER_ACCEPTOR_IDENTITY */
-/* #undef HAVE_GSS_C_NT_HOSTBASED_SERVICE */
-/* #undef HAVE_KRB5_CC_NEW_UNIQUE */
-/* #undef HAVE_KRB5_IPC_CLIENT_SET_TARGET_UID */
+/* #undef HAVE_GSSAPI_H */
+/* #undef HAVE_GSSAPI_KRB5_H */
 /* #undef HAVE_KRB5_H */
-/* #undef HAVE_HEIMDAL */
 
 
 /*
 /* #undef HAVE_TCPD_H */
 
 
+/*
+ * Do we have <iconv.h>?
+ */
+
+/* #undef HAVE_ICONV_H */
+
+
+/*
+ * Do we have statfs or statvfs and one of the corresponding headers?
+ */
+
+/* #undef HAVE_STATFS */
+/* #undef HAVE_STATVFS */
+/* #undef HAVE_SYS_MOUNT_H */
+/* #undef HAVE_SYS_STATFS_H */
+/* #undef HAVE_SYS_STATVFS_H */
+/* #undef HAVE_SYS_VFS_H */
+
+
+/*
+ * Location of Mac OS X localization bundle, if any.
+ */
+
+/* #undef CUPS_BUNDLEDIR */
+
+
+/*
+ * Do we have the ColorSyncRegisterDevice function?
+ */
+
+/* #undef HAVE_COLORSYNCREGISTERDEVICE */
+
+
 #endif /* !_CUPS_CONFIG_H_ */
 
 /*
index 7ff88561d47c73de0c0a9d7c3f38073b14ee7d4c..a08d81842e0d3784c966a10719a5354eb1f7c580 100644 (file)
  * Do we have the GSSAPI support library (for Kerberos support)?
  */
 
+/* #undef HAVE_GSS_ACQUIRE_CRED_EX_F */
+#define HAVE_GSS_C_NT_HOSTBASED_SERVICE 1
+/* #undef HAVE_GSS_GSSAPI_H */
+/* #undef HAVE_GSS_GSSAPI_SPI_H */
 #define HAVE_GSSAPI 1
 #define HAVE_GSSAPI_H 1
 #define HAVE_GSSAPI_GSSAPI_H 1
 #define HAVE_GSSAPI_GSSAPI_GENERIC_H 1
 #define HAVE_GSSAPI_GSSAPI_KRB5_H 1
-/* #undef HAVE_GSSKRB5_REGISTER_ACCEPTOR_IDENTITY */
-#define HAVE_GSS_C_NT_HOSTBASED_SERVICE 1
-#define HAVE_KRB5_CC_NEW_UNIQUE 1
-#define HAVE_KRB5_IPC_CLIENT_SET_TARGET_UID 1
 #define HAVE_KRB5_H 1
-/* #undef HAVE_HEIMDAL */
 
 
 /*