]> git.ipfire.org Git - thirdparty/cups.git/blobdiff - backend/ipp.c
Merge changes from CUPS 1.5svn-r8950.
[thirdparty/cups.git] / backend / ipp.c
index 65c254c860f9fd6ca3bbf7fae80817435008ce14..1e58d71f5efc6f52f3a69940d6a52256aeb44f50 100644 (file)
@@ -3,7 +3,7 @@
  *
  *   IPP backend for the Common UNIX Printing System (CUPS).
  *
- *   Copyright 2007-2009 by Apple Inc.
+ *   Copyright 2007-2010 by Apple Inc.
  *   Copyright 1997-2007 by Easy Software Products, all rights reserved.
  *
  *   These coded instructions, statements, and computer programs are the
@@ -45,6 +45,8 @@
 
 static char    *password = NULL;       /* Password for device URI */
 static int     password_tries = 0;     /* Password tries */
+static const char *auth_info_required = "none";
+                                       /* New auth-info-required value */
 #ifdef __APPLE__
 static char    pstmpname[1024] = "";   /* Temporary PostScript file name */
 #endif /* __APPLE__ */
@@ -115,7 +117,6 @@ main(int  argc,                             /* I - Number of command-line args */
                *response,              /* IPP response */
                *supported;             /* get-printer-attributes response */
   time_t       start_time;             /* Time of first connect */
-  int          recoverable;            /* Recoverable error shown? */
   int          contimeout;             /* Connection timeout */
   int          delay;                  /* Delay for retries... */
   int          compression,            /* Do compression of the job data? */
@@ -139,7 +140,6 @@ main(int  argc,                             /* I - Number of command-line args */
   int          version;                /* IPP version */
   static const char * const pattrs[] =
                {                       /* Printer attributes we want */
-                  "com.apple.print.recoverable-message",
                  "copies-supported",
                  "document-format-supported",
                  "marker-colors",
@@ -343,7 +343,7 @@ main(int  argc,                             /* I - Number of command-line args */
        else
        {
          _cupsLangPrintf(stderr,
-                         _("ERROR: Unknown encryption option value \"%s\"!\n"),
+                         _("ERROR: Unknown encryption option value \"%s\"\n"),
                          value);
         }
       }
@@ -360,7 +360,7 @@ main(int  argc,                             /* I - Number of command-line args */
        else
        {
          _cupsLangPrintf(stderr,
-                         _("ERROR: Unknown version option value \"%s\"!\n"),
+                         _("ERROR: Unknown version option value \"%s\"\n"),
                          value);
        }
       }
@@ -389,7 +389,7 @@ main(int  argc,                             /* I - Number of command-line args */
        */
 
        _cupsLangPrintf(stderr,
-                       _("ERROR: Unknown option \"%s\" with value \"%s\"!\n"),
+                       _("ERROR: Unknown option \"%s\" with value \"%s\"\n"),
                        name, value);
       }
     }
@@ -417,7 +417,7 @@ main(int  argc,                             /* I - Number of command-line args */
 
     if ((addrlist = httpAddrGetList(hostname, AF_UNSPEC, "1")) == NULL)
     {
-      _cupsLangPrintf(stderr, _("ERROR: Unable to locate printer \'%s\'!\n"),
+      _cupsLangPrintf(stderr, _("ERROR: Unable to locate printer \'%s\'\n"),
                      hostname);
       return (CUPS_BACKEND_STOP);
     }
@@ -432,7 +432,7 @@ main(int  argc,                             /* I - Number of command-line args */
 
     _cupsLangPuts(stderr, _("INFO: Copying print data...\n"));
 
-    tbytes = backendRunLoop(-1, fd, snmp_fd, &(addrlist->addr), 0,
+    tbytes = backendRunLoop(-1, fd, snmp_fd, &(addrlist->addr), 0, 0,
                             backendNetworkSideCB);
 
     if (snmp_fd >= 0)
@@ -448,7 +448,7 @@ main(int  argc,                             /* I - Number of command-line args */
 
     if (tbytes <= 1)
     {
-      _cupsLangPuts(stderr, _("ERROR: Empty print file!\n"));
+      _cupsLangPuts(stderr, _("ERROR: Empty print file\n"));
       unlink(tmpfilename);
       return (CUPS_BACKEND_FAILED);
     }
@@ -515,9 +515,8 @@ main(int  argc,                             /* I - Number of command-line args */
   * Try connecting to the remote server...
   */
 
-  delay       = 5;
-  recoverable = 0;
-  start_time  = time(NULL);
+  delay      = 5;
+  start_time = time(NULL);
 
   fputs("STATE: +connecting-to-device\n", stderr);
 
@@ -561,14 +560,12 @@ main(int  argc,                           /* I - Number of command-line args */
       {
         if (contimeout && (time(NULL) - start_time) > contimeout)
        {
-         _cupsLangPuts(stderr, _("ERROR: Printer not responding!\n"));
+         _cupsLangPuts(stderr, _("ERROR: Printer not responding\n"));
          return (CUPS_BACKEND_FAILED);
        }
 
-        recoverable = 1;
-
        _cupsLangPrintf(stderr,
-                       _("WARNING: recoverable: Network host \'%s\' is busy; "
+                       _("WARNING: Network host \'%s\' is busy; "
                          "will retry in %d seconds...\n"),
                        hostname, delay);
 
@@ -579,18 +576,16 @@ main(int  argc,                           /* I - Number of command-line args */
       }
       else if (h_errno)
       {
-       _cupsLangPrintf(stderr, _("ERROR: Unable to locate printer \'%s\'!\n"),
+       _cupsLangPrintf(stderr, _("ERROR: Unable to locate printer \'%s\'\n"),
                        hostname);
        return (CUPS_BACKEND_STOP);
       }
       else
       {
-        recoverable = 1;
-
         fprintf(stderr, "DEBUG: Connection error: %s\n", strerror(errno));
        _cupsLangPuts(stderr,
-                     _("ERROR: recoverable: Unable to connect to printer; will "
-                       "retry in 30 seconds...\n"));
+                     _("ERROR: Unable to connect to printer; will retry in 30 "
+                       "seconds...\n"));
        sleep(30);
       }
 
@@ -696,16 +691,13 @@ main(int  argc,                           /* I - Number of command-line args */
       {
         if (contimeout && (time(NULL) - start_time) > contimeout)
        {
-         _cupsLangPuts(stderr, _("ERROR: Printer not responding!\n"));
+         _cupsLangPuts(stderr, _("ERROR: Printer not responding\n"));
          return (CUPS_BACKEND_FAILED);
        }
 
-        recoverable = 1;
-
        _cupsLangPrintf(stderr,
-                       _("WARNING: recoverable: Network host \'%s\' is busy; "
-                         "will retry in %d seconds...\n"),
-                       hostname, delay);
+                       _("WARNING: Network host \'%s\' is busy; will retry in "
+                         "%d seconds...\n"), hostname, delay);
 
         report_printer_state(supported, 0);
 
@@ -729,17 +721,26 @@ main(int  argc,                           /* I - Number of command-line args */
       }
       else if (ipp_status == IPP_NOT_FOUND)
       {
-        _cupsLangPuts(stderr, _("ERROR: Destination printer does not exist!\n"));
+        _cupsLangPuts(stderr, _("ERROR: Destination printer does not exist\n"));
 
        if (supported)
           ippDelete(supported);
 
        return (CUPS_BACKEND_STOP);
       }
+      else if (ipp_status == IPP_NOT_AUTHORIZED || ipp_status == IPP_FORBIDDEN)
+      {
+       if (!strncmp(httpGetField(http, HTTP_FIELD_WWW_AUTHENTICATE),
+                    "Negotiate", 9))
+         auth_info_required = "negotiate";
+
+       fprintf(stderr, "ATTR: auth-info-required=%s\n", auth_info_required);
+       return (CUPS_BACKEND_AUTH_REQUIRED);
+      }
       else
       {
        _cupsLangPrintf(stderr,
-                       _("ERROR: Unable to get printer status (%s)!\n"),
+                       _("ERROR: Unable to get printer status (%s)\n"),
                        cupsLastErrorString());
         sleep(10);
       }
@@ -822,18 +823,6 @@ main(int  argc,                            /* I - Number of command-line args */
     }
   }
 
-  if (recoverable)
-  {
-   /*
-    * If we've shown a recoverable error make sure the printer proxies
-    * have a chance to see the recovered message. Not pretty but
-    * necessary for now...
-    */
-
-    fputs("INFO: recovered: \n", stderr);
-    sleep(5);
-  }
-
  /*
   * See if the printer supports multiple copies...
   */
@@ -1046,19 +1035,24 @@ main(int  argc,                         /* I - Number of command-line args */
        * Update auth-info-required as needed...
        */
 
-        _cupsLangPrintf(stderr, _("ERROR: Print file was not accepted (%s)!\n"),
+        _cupsLangPrintf(stderr, _("ERROR: Print file was not accepted (%s)\n"),
                        cupsLastErrorString());
 
-       if (ipp_status == IPP_NOT_AUTHORIZED)
+       if (ipp_status == IPP_NOT_AUTHORIZED || ipp_status == IPP_FORBIDDEN)
        {
          fprintf(stderr, "DEBUG: WWW-Authenticate=\"%s\"\n",
                  httpGetField(http, HTTP_FIELD_WWW_AUTHENTICATE));
 
+         /*
+         * Normal authentication goes through the password callback, which sets
+         * auth_info_required to "username,password".  Kerberos goes directly
+         * through GSSAPI, so look for Negotiate in the WWW-Authenticate header
+         * here and set auth_info_required as needed...
+         */
+
          if (!strncmp(httpGetField(http, HTTP_FIELD_WWW_AUTHENTICATE),
                       "Negotiate", 9))
-           fputs("ATTR: auth-info-required=negotiate\n", stderr);
-         else
-           fputs("ATTR: auth-info-required=username,password\n", stderr);
+           auth_info_required = "negotiate";
        }
       }
     }
@@ -1212,7 +1206,7 @@ main(int  argc,                           /* I - Number of command-line args */
          ippDelete(response);
 
           _cupsLangPrintf(stderr,
-                         _("ERROR: Unable to get job %d attributes (%s)!\n"),
+                         _("ERROR: Unable to get job %d attributes (%s)\n"),
                          job_id, cupsLastErrorString());
           break;
        }
@@ -1296,6 +1290,15 @@ main(int  argc,                          /* I - Number of command-line args */
       page_count > start_count)
     fprintf(stderr, "PAGE: total %d\n", page_count - start_count);
 
+#ifdef HAVE_GSSAPI
+ /*
+  * See if we used Kerberos at all...
+  */
+
+  if (http->gssctx)
+    auth_info_required = "negotiate";
+#endif /* HAVE_GSSAPI */
+
  /*
   * Free memory...
   */
@@ -1328,14 +1331,19 @@ main(int  argc,                         /* I - Number of command-line args */
   * Return the queue status...
   */
 
-  if (ipp_status == IPP_NOT_AUTHORIZED)
+  fprintf(stderr, "ATTR: auth-info-required=%s\n", auth_info_required);
+
+  if (ipp_status == IPP_NOT_AUTHORIZED || ipp_status == IPP_FORBIDDEN)
     return (CUPS_BACKEND_AUTH_REQUIRED);
   else if (ipp_status == IPP_INTERNAL_ERROR)
     return (CUPS_BACKEND_STOP);
   else if (ipp_status > IPP_OK_CONFLICT)
     return (CUPS_BACKEND_FAILED);
   else
+  {
+    _cupsLangPuts(stderr, _("INFO: Ready to print.\n"));
     return (CUPS_BACKEND_OK);
+  }
 }
 
 
@@ -1400,7 +1408,6 @@ check_printer_state(
        *response;                      /* IPP response */
   static const char * const attrs[] =  /* Attributes we want */
   {
-    "com.apple.print.recoverable-message",
     "marker-colors",
     "marker-levels",
     "marker-message",
@@ -1532,6 +1539,12 @@ password_cb(const char *prompt)          /* I - Prompt (not used) */
 {
   (void)prompt;
 
+ /*
+  * Remember that we need to authenticate...
+  */
+
+  auth_info_required = "username,password";
+
   if (password && *password && password_tries < 3)
   {
     password_tries ++;
@@ -1541,23 +1554,10 @@ password_cb(const char *prompt)         /* I - Prompt (not used) */
   else
   {
    /*
-    * If there is no password set in the device URI, return the
-    * "authentication required" exit code...
+    * Give up after 3 tries or if we don't have a password to begin with...
     */
 
-    if (tmpfilename[0])
-      unlink(tmpfilename);
-
-#ifdef __APPLE__
-    if (pstmpname[0])
-      unlink(pstmpname);
-#endif /* __APPLE__ */
-
-    fputs("ATTR: auth-info-required=username,password\n", stderr);
-
-    exit(CUPS_BACKEND_AUTH_REQUIRED);
-
-    return (NULL);                     /* Eliminate compiler warning */
+    return (NULL);
   }
 }
 
@@ -1640,14 +1640,12 @@ report_printer_state(ipp_t *ipp,        /* I - IPP response */
 {
   int                  i;              /* Looping var */
   int                  count;          /* Count of reasons shown... */
-  ipp_attribute_t      *caprm,         /* com.apple.print.recoverable-message */
-                       *psm,           /* printer-state-message */
+  ipp_attribute_t      *psm,           /* printer-state-message */
                        *reasons,       /* printer-state-reasons */
                        *marker;        /* marker-* attributes */
   const char           *reason;        /* Current reason */
   const char           *prefix;        /* Prefix for STATE: line */
   char                 state[1024];    /* State string */
-  int                  saw_caprw;      /* Saw com.apple.print.recoverable-warning state */
 
 
   if ((psm = ippFindAttribute(ipp, "printer-state-message",
@@ -1658,17 +1656,15 @@ report_printer_state(ipp_t *ipp,        /* I - IPP response */
                                   IPP_TAG_KEYWORD)) == NULL)
     return (0);
 
-  saw_caprw = 0;
-  state[0]  = '\0';
-  prefix    = "STATE: ";
+  state[0] = '\0';
+  prefix   = "STATE: ";
 
   for (i = 0, count = 0; i < reasons->num_values; i ++)
   {
     reason = reasons->values[i].string.text;
 
-    if (!strcmp(reason, "com.apple.print.recoverable-warning"))
-      saw_caprw = 1;
-    else if (strcmp(reason, "paused"))
+    if (strcmp(reason, "paused") &&
+       strcmp(reason, "com.apple.print.recoverable-warning"))
     {
       strlcat(state, prefix, sizeof(state));
       strlcat(state, reason, sizeof(state));
@@ -1680,16 +1676,6 @@ report_printer_state(ipp_t *ipp, /* I - IPP response */
   if (state[0])
     fprintf(stderr, "%s\n", state);
 
- /*
-  * Relay com.apple.print.recoverable-message...
-  */
-
-  if ((caprm = ippFindAttribute(ipp, "com.apple.print.recoverable-message",
-                                IPP_TAG_TEXT)) != NULL)
-    fprintf(stderr, "WARNING: %s: %s\n",
-            saw_caprw ? "recoverable" : "recovered",
-           caprm->values[0].string.text);
-
  /*
   * Relay the current marker-* attribute values...
   */
@@ -1749,7 +1735,7 @@ run_pictwps_filter(char       **argv,     /* I - Command-line arguments */
   if (!printer)
   {
     _cupsLangPuts(stderr,
-                  _("ERROR: PRINTER environment variable not defined!\n"));
+                  _("ERROR: PRINTER environment variable not defined\n"));
     return (-1);
   }
 
@@ -1820,8 +1806,11 @@ run_pictwps_filter(char       **argv,    /* I - Command-line arguments */
       * Change to an unpriviledged user...
       */
 
-      setgid(fileinfo.st_gid);
-      setuid(fileinfo.st_uid);
+      if (setgid(fileinfo.st_gid))
+        return (errno);
+
+      if (setuid(fileinfo.st_uid))
+        return (errno);
     }
 
     execlp("pictwpstops", printer, argv[1], argv[2], argv[3], argv[4], argv[5],
@@ -1868,10 +1857,10 @@ run_pictwps_filter(char       **argv,   /* I - Command-line arguments */
   if (status)
   {
     if (status >= 256)
-      _cupsLangPrintf(stderr, _("ERROR: pictwpstops exited with status %d!\n"),
+      _cupsLangPrintf(stderr, _("ERROR: pictwpstops exited with status %d\n"),
                      status / 256);
     else
-      _cupsLangPrintf(stderr, _("ERROR: pictwpstops exited on signal %d!\n"),
+      _cupsLangPrintf(stderr, _("ERROR: pictwpstops exited on signal %d\n"),
                      status);
 
     return (status);