]> git.ipfire.org Git - thirdparty/cups.git/blobdiff - scheduler/client.c
Update ipp documentation to reflect the behavior of configuring WiFi on IPP USB printers.
[thirdparty/cups.git] / scheduler / client.c
index 923a6e67a22e9b026b90f4caa29f279cb0def0ab..0126ef02daec31edd8ff9a4f0eb79bc4497787d5 100644 (file)
@@ -1,8 +1,9 @@
 /*
  * Client routines for the CUPS scheduler.
  *
- * Copyright © 2007-2019 by Apple Inc.
- * Copyright © 1997-2007 by Easy Software Products, all rights reserved.
+ * Copyright © 2021 by OpenPrinting.
+ * Copyright © 2007-2021 by Apple Inc.
+ * Copyright © 1997-2007 by Easy Software Products, all rights reserved.
  *
  * This file contains Kerberos support code, copyright 2006 by
  * Jelmer Vernooij.
@@ -564,6 +565,17 @@ cupsdReadClient(cupsd_client_t *con)       /* I - Client to read from */
 
   cupsdLogClient(con, CUPSD_LOG_DEBUG2, "cupsdReadClient: error=%d, used=%d, state=%s, data_encoding=HTTP_ENCODING_%s, data_remaining=" CUPS_LLFMT ", request=%p(%s), file=%d", httpError(con->http), (int)httpGetReady(con->http), httpStateString(httpGetState(con->http)), httpIsChunked(con->http) ? "CHUNKED" : "LENGTH", CUPS_LLCAST httpGetRemaining(con->http), con->request, con->request ? ippStateString(ippGetState(con->request)) : "", con->file);
 
+  if (httpError(con->http) == EPIPE && !httpGetReady(con->http) && recv(httpGetFd(con->http), buf, 1, MSG_PEEK) < 1)
+  {
+   /*
+    * Connection closed...
+    */
+
+    cupsdLogClient(con, CUPSD_LOG_DEBUG, "Closing on EOF.");
+    cupsdCloseClient(con);
+    return;
+  }
+
   if (httpGetState(con->http) == HTTP_STATE_GET_SEND ||
       httpGetState(con->http) == HTTP_STATE_POST_SEND ||
       httpGetState(con->http) == HTTP_STATE_STATUS)
@@ -573,17 +585,6 @@ cupsdReadClient(cupsd_client_t *con)       /* I - Client to read from */
     * connection and we need to shut it down...
     */
 
-    if (!httpGetReady(con->http) && recv(httpGetFd(con->http), buf, 1, MSG_PEEK) < 1)
-    {
-     /*
-      * Connection closed...
-      */
-
-      cupsdLogClient(con, CUPSD_LOG_DEBUG, "Closing on EOF.");
-      cupsdCloseClient(con);
-      return;
-    }
-
     cupsdLogClient(con, CUPSD_LOG_DEBUG, "Closing on unexpected HTTP read state %s.", httpStateString(httpGetState(con->http)));
     cupsdCloseClient(con);
     return;
@@ -1099,7 +1100,7 @@ cupsdReadClient(cupsd_client_t *con)      /* I - Client to read from */
                }
              }
             }
-            else if (!strncmp(con->uri, "/admin", 6) || !strncmp(con->uri, "/printers", 9) || !strncmp(con->uri, "/classes", 8) || !strncmp(con->uri, "/help", 5) || !strncmp(con->uri, "/jobs", 5))
+            else if (!buf[0] && (!strncmp(con->uri, "/admin", 6) || !strncmp(con->uri, "/classes", 8) || !strncmp(con->uri, "/help", 5) || !strncmp(con->uri, "/jobs", 5) || !strncmp(con->uri, "/printers", 9)))
            {
              if (!WebInterface)
              {
@@ -1125,14 +1126,6 @@ cupsdReadClient(cupsd_client_t *con)     /* I - Client to read from */
                cupsdSetStringf(&con->command, "%s/cgi-bin/admin.cgi", ServerBin);
                cupsdSetString(&con->options, strchr(con->uri + 6, '?'));
              }
-              else if (!strncmp(con->uri, "/printers", 9))
-             {
-               cupsdSetStringf(&con->command, "%s/cgi-bin/printers.cgi", ServerBin);
-                if (con->uri[9] && con->uri[10])
-                 cupsdSetString(&con->options, con->uri + 9);
-               else
-                 cupsdSetString(&con->options, NULL);
-             }
              else if (!strncmp(con->uri, "/classes", 8))
              {
                cupsdSetStringf(&con->command, "%s/cgi-bin/classes.cgi", ServerBin);
@@ -1149,6 +1142,14 @@ cupsdReadClient(cupsd_client_t *con)     /* I - Client to read from */
                else
                  cupsdSetString(&con->options, NULL);
              }
+              else if (!strncmp(con->uri, "/printers", 9))
+             {
+               cupsdSetStringf(&con->command, "%s/cgi-bin/printers.cgi", ServerBin);
+                if (con->uri[9] && con->uri[10])
+                 cupsdSetString(&con->options, con->uri + 9);
+               else
+                 cupsdSetString(&con->options, NULL);
+             }
              else
              {
                cupsdSetStringf(&con->command, "%s/cgi-bin/help.cgi", ServerBin);
@@ -1458,7 +1459,7 @@ cupsdReadClient(cupsd_client_t *con)      /* I - Client to read from */
              break;
            }
 
-           if (!strncmp(con->uri, "/admin", 6) || !strncmp(con->uri, "/printers", 9) || !strncmp(con->uri, "/classes", 8) || !strncmp(con->uri, "/help", 5) || !strncmp(con->uri, "/jobs", 5))
+           if (!buf[0] && (!strncmp(con->uri, "/admin", 6) || !strncmp(con->uri, "/classes", 8) || !strncmp(con->uri, "/help", 5) || !strncmp(con->uri, "/jobs", 5) || !strncmp(con->uri, "/printers", 9)))
            {
             /*
              * CGI output...
@@ -1950,6 +1951,7 @@ cupsdSendError(cupsd_client_t *con,       /* I - Connection */
   strlcpy(location, httpGetField(con->http, HTTP_FIELD_LOCATION), sizeof(location));
 
   httpClearFields(con->http);
+  httpClearCookie(con->http);
 
   httpSetField(con->http, HTTP_FIELD_LOCATION, location);
 
@@ -2108,18 +2110,13 @@ cupsdSendHeader(
     }
     else if (auth_type == CUPSD_AUTH_NEGOTIATE)
     {
-#if defined(SO_PEERCRED) && defined(AF_LOCAL)
-      if (httpAddrFamily(httpGetAddress(con->http)) == AF_LOCAL)
-       strlcpy(auth_str, "PeerCred", sizeof(auth_str));
-      else
-#endif /* SO_PEERCRED && AF_LOCAL */
       strlcpy(auth_str, "Negotiate", sizeof(auth_str));
     }
 
-    if (con->best && auth_type != CUPSD_AUTH_NEGOTIATE && !con->is_browser && !_cups_strcasecmp(httpGetHostname(con->http, NULL, 0), "localhost"))
+    if (con->best && !con->is_browser && !_cups_strcasecmp(httpGetHostname(con->http, NULL, 0), "localhost"))
     {
      /*
-      * Add a "trc" (try root certification) parameter for local non-Kerberos
+      * Add a "trc" (try root certification) parameter for local
       * requests when the request requires system group membership - then the
       * client knows the root certificate can/should be used.
       *
@@ -2700,6 +2697,7 @@ get_file(cupsd_client_t *con,             /* I  - Client connection */
   * Figure out the real filename...
   */
 
+  filename[0] = '\0';
   language[0] = '\0';
 
   if (!strncmp(con->uri, "/help", 5) && (con->uri[5] == '/' || !con->uri[5]))
@@ -2717,6 +2715,7 @@ get_file(cupsd_client_t *con,             /* I  - Client connection */
 
     if ((p = cupsdFindDest(dest)) == NULL)
     {
+      strlcpy(filename, "/", len);
       cupsdLogClient(con, CUPSD_LOG_INFO, "No destination \"%s\" found.", dest);
       return (NULL);
     }
@@ -2753,6 +2752,7 @@ get_file(cupsd_client_t *con,             /* I  - Client connection */
 
     if ((p = cupsdFindDest(dest)) == NULL)
     {
+      strlcpy(filename, "/", len);
       cupsdLogClient(con, CUPSD_LOG_INFO, "No destination \"%s\" found.", dest);
       return (NULL);
     }
@@ -2785,6 +2785,33 @@ get_file(cupsd_client_t *con,            /* I  - Client connection */
 
     perm_check = 0;
   }
+  else if (!strcmp(con->uri, "/admin/conf/cupsd.conf"))
+  {
+    strlcpy(filename, ConfigurationFile, len);
+
+    perm_check = 0;
+  }
+  else if (!strncmp(con->uri, "/admin/log/", 11))
+  {
+    if (!strncmp(con->uri + 11, "access_log", 10) && AccessLog[0] == '/')
+      strlcpy(filename, AccessLog, len);
+    else if (!strncmp(con->uri + 11, "error_log", 9) && ErrorLog[0] == '/')
+      strlcpy(filename, ErrorLog, len);
+    else if (!strncmp(con->uri + 11, "page_log", 8) && PageLog[0] == '/')
+      strlcpy(filename, PageLog, len);
+    else
+      return (NULL);
+
+    perm_check = 0;
+  }
+  else if (!strncmp(con->uri, "/admin", 6) || !strncmp(con->uri, "/classes", 8) || !strncmp(con->uri, "/jobs", 5) || !strncmp(con->uri, "/printers", 9))
+  {
+   /*
+    * Admin/class/job/printer pages are served by CGI...
+    */
+
+    return (NULL);
+  }
   else if (!strncmp(con->uri, "/rss/", 5) && !strchr(con->uri + 5, '/'))
     snprintf(filename, len, "%s/rss/%s", CacheDir, con->uri + 5);
   else if (!strncmp(con->uri, "/strings/", 9) && !strcmp(con->uri + strlen(con->uri) - 8, ".strings"))
@@ -2794,12 +2821,14 @@ get_file(cupsd_client_t *con,           /* I  - Client connection */
 
     if ((p = cupsdFindDest(dest)) == NULL)
     {
+      strlcpy(filename, "/", len);
       cupsdLogClient(con, CUPSD_LOG_INFO, "No destination \"%s\" found.", dest);
       return (NULL);
     }
 
     if (!p->strings)
     {
+      strlcpy(filename, "/", len);
       cupsdLogClient(con, CUPSD_LOG_INFO, "No strings files for \"%s\".", dest);
       return (NULL);
     }
@@ -2808,25 +2837,6 @@ get_file(cupsd_client_t *con,            /* I  - Client connection */
 
     perm_check = 0;
   }
-  else if (!strcmp(con->uri, "/admin/conf/cupsd.conf"))
-  {
-    strlcpy(filename, ConfigurationFile, len);
-
-    perm_check = 0;
-  }
-  else if (!strncmp(con->uri, "/admin/log/", 11))
-  {
-    if (!strncmp(con->uri + 11, "access_log", 10) && AccessLog[0] == '/')
-      strlcpy(filename, AccessLog, len);
-    else if (!strncmp(con->uri + 11, "error_log", 9) && ErrorLog[0] == '/')
-      strlcpy(filename, ErrorLog, len);
-    else if (!strncmp(con->uri + 11, "page_log", 8) && PageLog[0] == '/')
-      strlcpy(filename, PageLog, len);
-    else
-      return (NULL);
-
-    perm_check = 0;
-  }
   else if (con->language)
   {
     snprintf(language, sizeof(language), "/%s", con->language->language);
@@ -2924,7 +2934,7 @@ get_file(cupsd_client_t *con,             /* I  - Client connection */
        */
 
        if (language[3])
-         language[0] = '\0';           /* Strip country code */
+         language[3] = '\0';           /* Strip country code */
        else
          language[0] = '\0';           /* Strip language */
       }
@@ -3110,8 +3120,7 @@ is_cgi(cupsd_client_t *con,               /* I - Client connection */
     return (0);
   }
 
-  if (!_cups_strcasecmp(type->type, "x-httpd-cgi") &&
-      (filestats->st_mode & 0111))
+  if (!_cups_strcasecmp(type->type, "x-httpd-cgi") && (filestats->st_mode & 0111) && (getuid() || !(filestats->st_mode & 022)))
   {
    /*
     * "application/x-httpd-cgi" is a CGI script.
@@ -3457,8 +3466,7 @@ pipe_command(cupsd_client_t *con, /* I - Client connection */
   }
   else
   {
-    sprintf(content_length, "CONTENT_LENGTH=" CUPS_LLFMT,
-            CUPS_LLCAST con->bytes);
+    snprintf(content_length, sizeof(content_length), "CONTENT_LENGTH=" CUPS_LLFMT, CUPS_LLCAST con->bytes);
     snprintf(content_type, sizeof(content_type), "CONTENT_TYPE=%s",
              httpGetField(con->http, HTTP_FIELD_CONTENT_TYPE));