/*
* Client routines for the CUPS scheduler.
*
- * Copyright 2007-2017 by Apple Inc.
- * Copyright 1997-2007 by Easy Software Products, all rights reserved.
+ * Copyright © 2007-2018 by Apple Inc.
+ * Copyright © 1997-2007 by Easy Software Products, all rights reserved.
*
* This file contains Kerberos support code, copyright 2006 by
* Jelmer Vernooij.
*
- * These coded instructions, statements, and computer programs are the
- * property of Apple Inc. and are protected by Federal copyright
- * law. Distribution and use rights are outlined in the file "LICENSE.txt"
- * which should have been included with this file. If this file is
- * missing or damaged, see the license at "http://www.cups.org/".
+ * Licensed under Apache License v2.0. See the file "LICENSE" for more
+ * information.
*/
/*
if (cupsArrayCount(Clients) == MaxClients)
return;
+ cupsdSetBusyState(1);
+
/*
* Get a pointer to the next available client...
*/
if (httpGetFd(con->http) >= 0)
{
cupsArrayRemove(ActiveClients, con);
- cupsdSetBusyState();
+ cupsdSetBusyState(0);
#ifdef HAVE_SSL
/*
char buf[1024]; /* Buffer for real filename */
struct stat filestats; /* File information */
mime_type_t *type; /* MIME type of file */
- cupsd_printer_t *p; /* Printer */
static unsigned request_id = 0; /* Request ID for temp files */
if (!cupsArrayFind(ActiveClients, con))
{
cupsArrayAdd(ActiveClients, con);
- cupsdSetBusyState();
+ cupsdSetBusyState(0);
}
case HTTP_STATE_OPTIONS :
if (status == HTTP_STATUS_OK)
{
+ /*
+ * Record whether the client is a web browser. "Mozilla" was the original
+ * and it seems that every web browser in existence now uses that as the
+ * prefix with additional information identifying *which* browser.
+ *
+ * Chrome (at least) has problems with multiple WWW-Authenticate values in
+ * a single header, so we only report Basic or Negotiate to web browsers and
+ * leave the multiple choices to the native CUPS client...
+ */
+
+ con->is_browser = !strncmp(httpGetField(con->http, HTTP_FIELD_USER_AGENT), "Mozilla/", 8);
+
if (httpGetField(con->http, HTTP_FIELD_ACCEPT_LANGUAGE)[0])
{
/*
case HTTP_STATE_GET_SEND :
cupsdLogClient(con, CUPSD_LOG_DEBUG, "Processing GET %s", con->uri);
- if ((!strncmp(con->uri, "/ppd/", 5) ||
- !strncmp(con->uri, "/printers/", 10) ||
- !strncmp(con->uri, "/classes/", 9)) &&
- !strcmp(con->uri + strlen(con->uri) - 4, ".ppd"))
- {
- /*
- * Send PPD file - get the real printer name since printer
- * names are not case sensitive but filenames can be...
- */
+ if ((filename = get_file(con, &filestats, buf, sizeof(buf))) != NULL)
+ {
+ type = mimeFileType(MimeDatabase, filename, NULL, NULL);
- con->uri[strlen(con->uri) - 4] = '\0'; /* Drop ".ppd" */
+ cupsdLogClient(con, CUPSD_LOG_DEBUG, "filename=\"%s\", type=%s/%s", filename, type ? type->super : "", type ? type->type : "");
- if (!strncmp(con->uri, "/ppd/", 5))
- p = cupsdFindPrinter(con->uri + 5);
- else if (!strncmp(con->uri, "/printers/", 10))
- p = cupsdFindPrinter(con->uri + 10);
- else
+ if (is_cgi(con, filename, &filestats, type))
{
- p = cupsdFindClass(con->uri + 9);
+ /*
+ * Note: con->command and con->options were set by is_cgi()...
+ */
- if (p)
+ if (!cupsdSendCommand(con, con->command, con->options, 0))
{
- int i; /* Looping var */
-
- for (i = 0; i < p->num_printers; i ++)
+ if (!cupsdSendError(con, HTTP_STATUS_NOT_FOUND, CUPSD_AUTH_NONE))
{
- if (!(p->printers[i]->type & CUPS_PRINTER_CLASS))
- {
- char ppdname[1024];/* PPD filename */
-
- snprintf(ppdname, sizeof(ppdname), "%s/ppd/%s.ppd",
- ServerRoot, p->printers[i]->name);
- if (!access(ppdname, 0))
- {
- p = p->printers[i];
- break;
- }
- }
+ cupsdCloseClient(con);
+ return;
}
+ }
+ else
+ cupsdLogRequest(con, HTTP_STATUS_OK);
- if (i >= p->num_printers)
- p = NULL;
- }
+ if (httpGetVersion(con->http) <= HTTP_VERSION_1_0)
+ httpSetKeepAlive(con->http, HTTP_KEEPALIVE_OFF);
+ break;
}
- if (p)
- {
- snprintf(con->uri, sizeof(con->uri), "/ppd/%s.ppd", p->name);
- }
- else
- {
- if (!cupsdSendError(con, HTTP_STATUS_NOT_FOUND, CUPSD_AUTH_NONE))
+ if (!check_if_modified(con, &filestats))
+ {
+ if (!cupsdSendError(con, HTTP_STATUS_NOT_MODIFIED, CUPSD_AUTH_NONE))
{
cupsdCloseClient(con);
return;
}
-
- break;
}
- }
- else if ((!strncmp(con->uri, "/icons/", 7) ||
- !strncmp(con->uri, "/printers/", 10) ||
- !strncmp(con->uri, "/classes/", 9)) &&
- !strcmp(con->uri + strlen(con->uri) - 4, ".png"))
- {
- /*
- * Send icon file - get the real queue name since queue names are
- * not case sensitive but filenames can be...
- */
-
- con->uri[strlen(con->uri) - 4] = '\0'; /* Drop ".png" */
-
- if (!strncmp(con->uri, "/icons/", 7))
- p = cupsdFindPrinter(con->uri + 7);
- else if (!strncmp(con->uri, "/printers/", 10))
- p = cupsdFindPrinter(con->uri + 10);
- else
+ else
{
- p = cupsdFindClass(con->uri + 9);
-
- if (p)
- {
- int i; /* Looping var */
-
- for (i = 0; i < p->num_printers; i ++)
- {
- if (!(p->printers[i]->type & CUPS_PRINTER_CLASS))
- {
- char ppdname[1024];/* PPD filename */
-
- snprintf(ppdname, sizeof(ppdname), "%s/ppd/%s.ppd",
- ServerRoot, p->printers[i]->name);
- if (!access(ppdname, 0))
- {
- p = p->printers[i];
- break;
- }
- }
- }
-
- if (i >= p->num_printers)
- p = NULL;
- }
- }
+ if (type == NULL)
+ strlcpy(line, "text/plain", sizeof(line));
+ else
+ snprintf(line, sizeof(line), "%s/%s", type->super, type->type);
- if (p)
- snprintf(con->uri, sizeof(con->uri), "/icons/%s.png", p->name);
- else
- {
- if (!cupsdSendError(con, HTTP_STATUS_NOT_FOUND, CUPSD_AUTH_NONE))
+ if (!write_file(con, HTTP_STATUS_OK, filename, line, &filestats))
{
cupsdCloseClient(con);
return;
}
-
- break;
}
- }
-
- if ((!strncmp(con->uri, "/admin", 6) && strcmp(con->uri, "/admin/conf/cupsd.conf") && strncmp(con->uri, "/admin/log/", 11)) ||
- !strncmp(con->uri, "/printers", 9) ||
- !strncmp(con->uri, "/classes", 8) ||
- !strncmp(con->uri, "/help", 5) ||
- !strncmp(con->uri, "/jobs", 5))
+ }
+ 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))
{
if (!WebInterface)
{
if (!strncmp(con->uri, "/admin", 6))
{
- cupsdSetStringf(&con->command, "%s/cgi-bin/admin.cgi",
- ServerBin);
-
+ 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);
-
+ cupsdSetStringf(&con->command, "%s/cgi-bin/printers.cgi", ServerBin);
if (con->uri[9] && con->uri[10])
cupsdSetString(&con->options, con->uri + 9);
else
}
else if (!strncmp(con->uri, "/classes", 8))
{
- cupsdSetStringf(&con->command, "%s/cgi-bin/classes.cgi",
- ServerBin);
-
+ cupsdSetStringf(&con->command, "%s/cgi-bin/classes.cgi", ServerBin);
if (con->uri[8] && con->uri[9])
cupsdSetString(&con->options, con->uri + 8);
else
}
else if (!strncmp(con->uri, "/jobs", 5))
{
- cupsdSetStringf(&con->command, "%s/cgi-bin/jobs.cgi",
- ServerBin);
-
+ cupsdSetStringf(&con->command, "%s/cgi-bin/jobs.cgi", ServerBin);
if (con->uri[5] && con->uri[6])
cupsdSetString(&con->options, con->uri + 5);
else
}
else
{
- cupsdSetStringf(&con->command, "%s/cgi-bin/help.cgi",
- ServerBin);
-
+ cupsdSetStringf(&con->command, "%s/cgi-bin/help.cgi", ServerBin);
if (con->uri[5] && con->uri[6])
cupsdSetString(&con->options, con->uri + 5);
else
if (httpGetVersion(con->http) <= HTTP_VERSION_1_0)
httpSetKeepAlive(con->http, HTTP_KEEPALIVE_OFF);
}
- else if (!strncmp(con->uri, "/admin/log/", 11) && (strchr(con->uri + 11, '/') || strlen(con->uri) == 11))
+ else
{
- /*
- * GET can only be done to configuration files directly under
- * /admin/conf...
- */
-
- cupsdLogClient(con, CUPSD_LOG_ERROR, "Request for subdirectory \"%s\".", con->uri);
-
- if (!cupsdSendError(con, HTTP_STATUS_FORBIDDEN, CUPSD_AUTH_NONE))
+ if (!cupsdSendError(con, HTTP_STATUS_NOT_FOUND, CUPSD_AUTH_NONE))
{
cupsdCloseClient(con);
return;
}
-
- break;
- }
- else
- {
- /*
- * Serve a file...
- */
-
- if ((filename = get_file(con, &filestats, buf,
- sizeof(buf))) == NULL)
- {
- if (!cupsdSendError(con, HTTP_STATUS_NOT_FOUND, CUPSD_AUTH_NONE))
- {
- cupsdCloseClient(con);
- return;
- }
-
- break;
- }
-
- type = mimeFileType(MimeDatabase, filename, NULL, NULL);
-
- cupsdLogClient(con, CUPSD_LOG_DEBUG, "filename=\"%s\", type=%s/%s", filename, type ? type->super : "", type ? type->type : "");
-
- if (is_cgi(con, filename, &filestats, type))
- {
- /*
- * Note: con->command and con->options were set by
- * is_cgi()...
- */
-
- if (!cupsdSendCommand(con, con->command, con->options, 0))
- {
- if (!cupsdSendError(con, HTTP_STATUS_NOT_FOUND, CUPSD_AUTH_NONE))
- {
- cupsdCloseClient(con);
- return;
- }
- }
- else
- cupsdLogRequest(con, HTTP_STATUS_OK);
-
- if (httpGetVersion(con->http) <= HTTP_VERSION_1_0)
- httpSetKeepAlive(con->http, HTTP_KEEPALIVE_OFF);
- break;
- }
-
- if (!check_if_modified(con, &filestats))
- {
- if (!cupsdSendError(con, HTTP_STATUS_NOT_MODIFIED, CUPSD_AUTH_NONE))
- {
- cupsdCloseClient(con);
- return;
- }
- }
- else
- {
- if (type == NULL)
- strlcpy(line, "text/plain", sizeof(line));
- else
- snprintf(line, sizeof(line), "%s/%s", type->super, type->type);
-
- if (!write_file(con, HTTP_STATUS_OK, filename, line, &filestats))
- {
- cupsdCloseClient(con);
- return;
- }
- }
}
break;
* so check the length against any limits that are set...
*/
- if (httpGetField(con->http, HTTP_FIELD_CONTENT_LENGTH)[0] &&
- MaxRequestSize > 0 &&
- httpGetLength2(con->http) > MaxRequestSize)
+ if (httpGetField(con->http, HTTP_FIELD_CONTENT_LENGTH)[0] && MaxRequestSize > 0 && httpGetLength2(con->http) > MaxRequestSize)
{
/*
* Request too large...
* content-type field will be "application/ipp"...
*/
- if (!strcmp(httpGetField(con->http, HTTP_FIELD_CONTENT_TYPE),
- "application/ipp"))
+ if (!strcmp(httpGetField(con->http, HTTP_FIELD_CONTENT_TYPE), "application/ipp"))
+ {
con->request = ippNew();
+ break;
+ }
else if (!WebInterface)
{
/*
break;
}
- else if ((!strncmp(con->uri, "/admin", 6) && strncmp(con->uri, "/admin/log/", 11)) ||
- !strncmp(con->uri, "/printers", 9) ||
- !strncmp(con->uri, "/classes", 8) ||
- !strncmp(con->uri, "/help", 5) ||
- !strncmp(con->uri, "/jobs", 5))
+
+ if ((filename = get_file(con, &filestats, buf, sizeof(buf))) != NULL)
+ {
+ /*
+ * POST to a file...
+ */
+
+ type = mimeFileType(MimeDatabase, filename, NULL, NULL);
+
+ if (!is_cgi(con, filename, &filestats, type))
+ {
+ /*
+ * Only POST to CGI's...
+ */
+
+ if (!cupsdSendError(con, HTTP_STATUS_UNAUTHORIZED, CUPSD_AUTH_NONE))
+ {
+ cupsdCloseClient(con);
+ return;
+ }
+ }
+ }
+ 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))
{
/*
* CGI request...
if (!strncmp(con->uri, "/admin", 6))
{
- cupsdSetStringf(&con->command, "%s/cgi-bin/admin.cgi",
- ServerBin);
-
+ 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);
-
+ cupsdSetStringf(&con->command, "%s/cgi-bin/printers.cgi", ServerBin);
if (con->uri[9] && con->uri[10])
cupsdSetString(&con->options, con->uri + 9);
else
}
else if (!strncmp(con->uri, "/classes", 8))
{
- cupsdSetStringf(&con->command, "%s/cgi-bin/classes.cgi",
- ServerBin);
-
+ cupsdSetStringf(&con->command, "%s/cgi-bin/classes.cgi", ServerBin);
if (con->uri[8] && con->uri[9])
cupsdSetString(&con->options, con->uri + 8);
else
}
else if (!strncmp(con->uri, "/jobs", 5))
{
- cupsdSetStringf(&con->command, "%s/cgi-bin/jobs.cgi",
- ServerBin);
-
+ cupsdSetStringf(&con->command, "%s/cgi-bin/jobs.cgi", ServerBin);
if (con->uri[5] && con->uri[6])
cupsdSetString(&con->options, con->uri + 5);
else
}
else
{
- cupsdSetStringf(&con->command, "%s/cgi-bin/help.cgi",
- ServerBin);
-
+ cupsdSetStringf(&con->command, "%s/cgi-bin/help.cgi", ServerBin);
if (con->uri[5] && con->uri[6])
cupsdSetString(&con->options, con->uri + 5);
else
}
else
{
- /*
- * POST to a file...
- */
-
- if ((filename = get_file(con, &filestats, buf,
- sizeof(buf))) == NULL)
+ if (!cupsdSendError(con, HTTP_STATUS_NOT_FOUND, CUPSD_AUTH_NONE))
{
- if (!cupsdSendError(con, HTTP_STATUS_NOT_FOUND, CUPSD_AUTH_NONE))
- {
- cupsdCloseClient(con);
- return;
- }
-
- break;
- }
-
- type = mimeFileType(MimeDatabase, filename, NULL, NULL);
-
- if (!is_cgi(con, filename, &filestats, type))
- {
- /*
- * Only POST to CGI's...
- */
-
- if (!cupsdSendError(con, HTTP_STATUS_UNAUTHORIZED, CUPSD_AUTH_NONE))
- {
- cupsdCloseClient(con);
- return;
- }
+ cupsdCloseClient(con);
+ return;
}
}
break;
* PUT can only be done to the cupsd.conf file...
*/
- cupsdLogClient(con, CUPSD_LOG_ERROR,
- "Disallowed PUT request for \"%s\".", con->uri);
+ cupsdLogClient(con, CUPSD_LOG_ERROR, "Disallowed PUT request for \"%s\".", con->uri);
if (!cupsdSendError(con, HTTP_STATUS_FORBIDDEN, CUPSD_AUTH_NONE))
{
* so check the length against any limits that are set...
*/
- if (httpGetField(con->http, HTTP_FIELD_CONTENT_LENGTH)[0] &&
- MaxRequestSize > 0 &&
- httpGetLength2(con->http) > MaxRequestSize)
+ if (httpGetField(con->http, HTTP_FIELD_CONTENT_LENGTH)[0] && MaxRequestSize > 0 && httpGetLength2(con->http) > MaxRequestSize)
{
/*
* Request too large...
* Open a temporary file to hold the request...
*/
- cupsdSetStringf(&con->filename, "%s/%08x", RequestRoot,
- request_id ++);
+ cupsdSetStringf(&con->filename, "%s/%08x", RequestRoot, request_id ++);
con->file = open(con->filename, O_WRONLY | O_CREAT | O_TRUNC, 0640);
if (con->file < 0)
{
- cupsdLogClient(con, CUPSD_LOG_ERROR,
- "Unable to create request file \"%s\": %s",
- con->filename, strerror(errno));
+ cupsdLogClient(con, CUPSD_LOG_ERROR, "Unable to create request file \"%s\": %s", con->filename, strerror(errno));
if (!cupsdSendError(con, HTTP_STATUS_REQUEST_TOO_LARGE, CUPSD_AUTH_NONE))
{
return;
case HTTP_STATE_HEAD :
- if (!strncmp(con->uri, "/printers/", 10) &&
- !strcmp(con->uri + strlen(con->uri) - 4, ".ppd"))
- {
- /*
- * Send PPD file - get the real printer name since printer
- * names are not case sensitive but filenames can be...
- */
-
- con->uri[strlen(con->uri) - 4] = '\0'; /* Drop ".ppd" */
-
- if ((p = cupsdFindPrinter(con->uri + 10)) != NULL)
- snprintf(con->uri, sizeof(con->uri), "/ppd/%s.ppd", p->name);
- else
+ if ((filename = get_file(con, &filestats, buf, sizeof(buf))) != NULL)
+ {
+ if (!check_if_modified(con, &filestats))
{
- if (!cupsdSendError(con, HTTP_STATUS_NOT_FOUND, CUPSD_AUTH_NONE))
+ if (!cupsdSendError(con, HTTP_STATUS_NOT_MODIFIED, CUPSD_AUTH_NONE))
{
cupsdCloseClient(con);
return;
}
- cupsdLogRequest(con, HTTP_STATUS_NOT_FOUND);
- break;
+ cupsdLogRequest(con, HTTP_STATUS_NOT_MODIFIED);
}
- }
- else if (!strncmp(con->uri, "/printers/", 10) &&
- !strcmp(con->uri + strlen(con->uri) - 4, ".png"))
- {
- /*
- * Send PNG file - get the real printer name since printer
- * names are not case sensitive but filenames can be...
- */
-
- con->uri[strlen(con->uri) - 4] = '\0'; /* Drop ".ppd" */
-
- if ((p = cupsdFindPrinter(con->uri + 10)) != NULL)
- snprintf(con->uri, sizeof(con->uri), "/icons/%s.png", p->name);
else
{
- if (!cupsdSendError(con, HTTP_STATUS_NOT_FOUND, CUPSD_AUTH_NONE))
+ /*
+ * Serve a file...
+ */
+
+ type = mimeFileType(MimeDatabase, filename, NULL, NULL);
+ if (type == NULL)
+ strlcpy(line, "text/plain", sizeof(line));
+ else
+ snprintf(line, sizeof(line), "%s/%s", type->super, type->type);
+
+ httpClearFields(con->http);
+
+ httpSetField(con->http, HTTP_FIELD_LAST_MODIFIED, httpGetDateString(filestats.st_mtime));
+ httpSetLength(con->http, (size_t)filestats.st_size);
+
+ if (!cupsdSendHeader(con, HTTP_STATUS_OK, line, CUPSD_AUTH_NONE))
{
cupsdCloseClient(con);
return;
}
- cupsdLogRequest(con, HTTP_STATUS_NOT_FOUND);
- break;
+ cupsdLogRequest(con, HTTP_STATUS_OK);
}
- }
+ }
else if (!WebInterface)
{
httpClearFields(con->http);
break;
}
- if ((!strncmp(con->uri, "/admin", 6) && strcmp(con->uri, "/admin/conf/cupsd.conf") && strncmp(con->uri, "/admin/log/", 11)) ||
- !strncmp(con->uri, "/printers", 9) ||
- !strncmp(con->uri, "/classes", 8) ||
- !strncmp(con->uri, "/help", 5) ||
- !strncmp(con->uri, "/jobs", 5))
+ 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))
{
/*
* CGI output...
cupsdLogRequest(con, HTTP_STATUS_OK);
}
- else if (!strncmp(con->uri, "/admin/log/", 11) && (strchr(con->uri + 11, '/') || strlen(con->uri) == 11))
- {
- /*
- * HEAD can only be done to configuration files under
- * /admin/conf...
- */
-
- cupsdLogClient(con, CUPSD_LOG_ERROR,
- "Request for subdirectory \"%s\".", con->uri);
-
- if (!cupsdSendError(con, HTTP_STATUS_FORBIDDEN, CUPSD_AUTH_NONE))
- {
- cupsdCloseClient(con);
- return;
- }
-
- cupsdLogRequest(con, HTTP_STATUS_FORBIDDEN);
- break;
- }
- else if ((filename = get_file(con, &filestats, buf,
- sizeof(buf))) == NULL)
- {
- httpClearFields(con->http);
-
- if (!cupsdSendHeader(con, HTTP_STATUS_NOT_FOUND, "text/html",
- CUPSD_AUTH_NONE))
- {
- cupsdCloseClient(con);
- return;
- }
-
- cupsdLogRequest(con, HTTP_STATUS_NOT_FOUND);
- }
- else if (!check_if_modified(con, &filestats))
- {
- if (!cupsdSendError(con, HTTP_STATUS_NOT_MODIFIED, CUPSD_AUTH_NONE))
- {
- cupsdCloseClient(con);
- return;
- }
-
- cupsdLogRequest(con, HTTP_STATUS_NOT_MODIFIED);
- }
else
{
- /*
- * Serve a file...
- */
-
- type = mimeFileType(MimeDatabase, filename, NULL, NULL);
- if (type == NULL)
- strlcpy(line, "text/plain", sizeof(line));
- else
- snprintf(line, sizeof(line), "%s/%s", type->super, type->type);
-
httpClearFields(con->http);
- httpSetField(con->http, HTTP_FIELD_LAST_MODIFIED,
- httpGetDateString(filestats.st_mtime));
- httpSetLength(con->http, (size_t)filestats.st_size);
-
- if (!cupsdSendHeader(con, HTTP_STATUS_OK, line, CUPSD_AUTH_NONE))
+ if (!cupsdSendHeader(con, HTTP_STATUS_NOT_FOUND, "text/html", CUPSD_AUTH_NONE))
{
cupsdCloseClient(con);
return;
}
- cupsdLogRequest(con, HTTP_STATUS_OK);
+ cupsdLogRequest(con, HTTP_STATUS_NOT_FOUND);
}
break;
else
{
cupsArrayRemove(ActiveClients, con);
- cupsdSetBusyState();
+ cupsdSetBusyState(0);
}
}
}
auth_str[0] = '\0';
if (auth_type == CUPSD_AUTH_BASIC)
+ {
strlcpy(auth_str, "Basic realm=\"CUPS\"", sizeof(auth_str));
-#ifdef HAVE_GSSAPI
+ }
else if (auth_type == CUPSD_AUTH_NEGOTIATE)
{
-# ifdef AF_LOCAL
+#if defined(SO_PEERCRED) && defined(AF_LOCAL)
if (httpAddrFamily(httpGetAddress(con->http)) == AF_LOCAL)
- strlcpy(auth_str, "Basic realm=\"CUPS\"", sizeof(auth_str));
+ strlcpy(auth_str, "PeerCred", sizeof(auth_str));
else
-# endif /* AF_LOCAL */
+#endif /* SO_PEERCRED && AF_LOCAL */
strlcpy(auth_str, "Negotiate", sizeof(auth_str));
}
-#endif /* HAVE_GSSAPI */
- if (con->best && auth_type != CUPSD_AUTH_NEGOTIATE &&
- !_cups_strcasecmp(httpGetHostname(con->http, NULL, 0), "localhost"))
+ if (con->best && auth_type != CUPSD_AUTH_NEGOTIATE && !con->is_browser && !_cups_strcasecmp(httpGetHostname(con->http, NULL, 0), "localhost"))
{
/*
* Add a "trc" (try root certification) parameter for local non-Kerberos
* requests when the request requires system group membership - then the
* client knows the root certificate can/should be used.
*
- * Also, for macOS we also look for @AUTHKEY and add an "authkey"
- * parameter as needed...
+ * Also, for macOS we also look for @AUTHKEY and add an "AuthRef key=foo"
+ * method as needed...
*/
char *name, /* Current user name */
*auth_key; /* Auth key buffer */
size_t auth_size; /* Size of remaining buffer */
+ int need_local = 1; /* Do we need to list "Local" method? */
auth_key = auth_str + strlen(auth_str);
auth_size = sizeof(auth_str) - (size_t)(auth_key - auth_str);
+#if defined(SO_PEERCRED) && defined(AF_LOCAL)
+ if (httpAddrFamily(httpGetAddress(con->http)) == AF_LOCAL)
+ {
+ strlcpy(auth_key, ", PeerCred", auth_size);
+ auth_key += 10;
+ auth_size -= 10;
+ }
+#endif /* SO_PEERCRED && AF_LOCAL */
+
for (name = (char *)cupsArrayFirst(con->best->names);
name;
name = (char *)cupsArrayNext(con->best->names))
{
+ cupsdLogClient(con, CUPSD_LOG_DEBUG2, "cupsdSendHeader: require \"%s\"", name);
+
#ifdef HAVE_AUTHORIZATION_H
if (!_cups_strncasecmp(name, "@AUTHKEY(", 9))
{
- snprintf(auth_key, auth_size, ", authkey=\"%s\"", name + 9);
+ snprintf(auth_key, auth_size, ", AuthRef key=\"%s\", Local trc=\"y\"", name + 9);
+ need_local = 0;
/* end parenthesis is stripped in conf.c */
break;
}
{
#ifdef HAVE_AUTHORIZATION_H
if (SystemGroupAuthKey)
- snprintf(auth_key, auth_size,
- ", authkey=\"%s\"",
- SystemGroupAuthKey);
+ snprintf(auth_key, auth_size, ", AuthRef key=\"%s\", Local trc=\"y\"", SystemGroupAuthKey);
else
-#else
- strlcpy(auth_key, ", trc=\"y\"", auth_size);
#endif /* HAVE_AUTHORIZATION_H */
+ strlcpy(auth_key, ", Local trc=\"y\"", auth_size);
+ need_local = 0;
break;
}
}
+
+ if (need_local)
+ strlcat(auth_key, ", Local", auth_size);
}
if (auth_str[0])
else
{
cupsArrayRemove(ActiveClients, con);
- cupsdSetBusyState();
+ cupsdSetBusyState(0);
}
}
}
char language[7], /* Language subdirectory, if any */
dest[1024]; /* Destination name */
int perm_check = 1; /* Do permissions check? */
+ cupsd_printer_t *p; /* Printer */
/*
language[0] = '\0';
- if (!strncmp(con->uri, "/ppd/", 5) && !strchr(con->uri + 5, '/'))
+ if ((!strncmp(con->uri, "/ppd/", 5) || !strncmp(con->uri, "/printers/", 10) || !strncmp(con->uri, "/classes/", 9)) && !strcmp(con->uri + strlen(con->uri) - 4, ".ppd"))
{
- strlcpy(dest, con->uri + 5, sizeof(dest));
- ptr = dest + strlen(dest) - 4;
+ strlcpy(dest, strchr(con->uri + 1, '/') + 1, sizeof(dest));
+ dest[strlen(dest) - 4] = '\0'; /* Strip .ppd */
- if (ptr <= dest || strcmp(ptr, ".ppd"))
+ if ((p = cupsdFindDest(dest)) == NULL)
{
- cupsdLogClient(con, CUPSD_LOG_INFO, "Disallowed path \"%s\".", con->uri);
+ cupsdLogClient(con, CUPSD_LOG_INFO, "No destination \"%s\" found.", dest);
return (NULL);
}
- *ptr = '\0';
- if (!cupsdFindPrinter(dest))
+ if (p->type & CUPS_PRINTER_CLASS)
{
- cupsdLogClient(con, CUPSD_LOG_INFO, "No printer \"%s\" found.", dest);
- return (NULL);
- }
+ int i; /* Looping var */
- snprintf(filename, len, "%s%s", ServerRoot, con->uri);
+ for (i = 0; i < p->num_printers; i ++)
+ {
+ if (!(p->printers[i]->type & CUPS_PRINTER_CLASS))
+ {
+ snprintf(filename, len, "%s/ppd/%s.ppd", ServerRoot, p->printers[i]->name);
+ if (!access(filename, 0))
+ {
+ p = p->printers[i];
+ break;
+ }
+ }
+ }
+
+ if (i >= p->num_printers)
+ p = NULL;
+ }
+ else
+ snprintf(filename, len, "%s/ppd/%s.ppd", ServerRoot, p->name);
perm_check = 0;
}
- else if (!strncmp(con->uri, "/icons/", 7) && !strchr(con->uri + 7, '/'))
+ else if ((!strncmp(con->uri, "/icons/", 7) || !strncmp(con->uri, "/printers/", 10) || !strncmp(con->uri, "/classes/", 9)) && !strcmp(con->uri + strlen(con->uri) - 4, ".png"))
{
- strlcpy(dest, con->uri + 7, sizeof(dest));
- ptr = dest + strlen(dest) - 4;
+ strlcpy(dest, strchr(con->uri + 1, '/') + 1, sizeof(dest));
+ dest[strlen(dest) - 4] = '\0'; /* Strip .png */
- if (ptr <= dest || strcmp(ptr, ".png"))
+ if ((p = cupsdFindDest(dest)) == NULL)
{
- cupsdLogClient(con, CUPSD_LOG_INFO, "Disallowed path \"%s\".", con->uri);
+ cupsdLogClient(con, CUPSD_LOG_INFO, "No destination \"%s\" found.", dest);
return (NULL);
}
- *ptr = '\0';
- if (!cupsdFindDest(dest))
+ if (p->type & CUPS_PRINTER_CLASS)
{
- cupsdLogClient(con, CUPSD_LOG_INFO, "No printer \"%s\" found.", dest);
- return (NULL);
+ int i; /* Looping var */
+
+ for (i = 0; i < p->num_printers; i ++)
+ {
+ if (!(p->printers[i]->type & CUPS_PRINTER_CLASS))
+ {
+ snprintf(filename, len, "%s/images/%s.png", CacheDir, p->printers[i]->name);
+ if (!access(filename, 0))
+ {
+ p = p->printers[i];
+ break;
+ }
+ }
+ }
+
+ if (i >= p->num_printers)
+ p = NULL;
}
+ else
+ snprintf(filename, len, "%s/images/%s.png", CacheDir, p->name);
- snprintf(filename, len, "%s/%s.png", CacheDir, dest);
if (access(filename, F_OK) < 0)
snprintf(filename, len, "%s/images/generic.png", DocumentRoot);
}
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"))
+ {
+ strlcpy(dest, con->uri + 9, sizeof(dest));
+ dest[strlen(dest) - 8] = '\0';
+
+ if ((p = cupsdFindDest(dest)) == NULL)
+ {
+ cupsdLogClient(con, CUPSD_LOG_INFO, "No destination \"%s\" found.", dest);
+ return (NULL);
+ }
+
+ if (!p->strings)
+ {
+ cupsdLogClient(con, CUPSD_LOG_INFO, "No strings files for \"%s\".", dest);
+ return (NULL);
+ }
+
+ strlcpy(filename, p->strings, len);
+
+ perm_check = 0;
+ }
else if (!strcmp(con->uri, "/admin/conf/cupsd.conf"))
{
strlcpy(filename, ConfigurationFile, len);
strncmp(con->uri, "/icons/", 7) &&
strncmp(con->uri, "/ppd/", 5) &&
strncmp(con->uri, "/rss/", 5) &&
+ strncmp(con->uri, "/strings/", 9) &&
strncmp(con->uri, "/admin/conf/", 12) &&
strncmp(con->uri, "/admin/log/", 11))
{
strlcpy(ptr, "index.html", plen);
status = lstat(filename, filestats);
-
-#ifdef HAVE_JAVA
- if (status)
- {
- strlcpy(ptr, "index.class", plen);
- status = lstat(filename, filestats);
- }
-#endif /* HAVE_JAVA */
-
-#ifdef HAVE_PERL
- if (status)
- {
- strlcpy(ptr, "index.pl", plen);
- status = lstat(filename, filestats);
- }
-#endif /* HAVE_PERL */
-
-#ifdef HAVE_PHP
- if (status)
- {
- strlcpy(ptr, "index.php", plen);
- status = lstat(filename, filestats);
- }
-#endif /* HAVE_PHP */
-
-#ifdef HAVE_PYTHON
- if (status)
- {
- strlcpy(ptr, "index.pyc", plen);
- status = lstat(filename, filestats);
- }
-
- if (status)
- {
- strlcpy(ptr, "index.py", plen);
- status = lstat(filename, filestats);
- }
-#endif /* HAVE_PYTHON */
-
}
while (status && language[0]);
cupsdLogClient(con, CUPSD_LOG_DEBUG2, "is_cgi: filename=\"%s\", filestats=%p, type=%s/%s, returning 1.", filename, filestats, type->super, type->type);
return (1);
}
-#ifdef HAVE_JAVA
- else if (!_cups_strcasecmp(type->type, "x-httpd-java"))
- {
- /*
- * "application/x-httpd-java" is a Java servlet.
- */
-
- cupsdSetString(&con->command, CUPS_JAVA);
-
- if (options)
- cupsdSetStringf(&con->options, " %s %s", filename, options);
- else
- cupsdSetStringf(&con->options, " %s", filename);
-
- cupsdLogClient(con, CUPSD_LOG_DEBUG2, "is_cgi: filename=\"%s\", filestats=%p, type=%s/%s, returning 1.", filename, filestats, type->super, type->type);
- return (1);
- }
-#endif /* HAVE_JAVA */
-#ifdef HAVE_PERL
- else if (!_cups_strcasecmp(type->type, "x-httpd-perl"))
- {
- /*
- * "application/x-httpd-perl" is a Perl page.
- */
-
- cupsdSetString(&con->command, CUPS_PERL);
-
- if (options)
- cupsdSetStringf(&con->options, " %s %s", filename, options);
- else
- cupsdSetStringf(&con->options, " %s", filename);
-
- cupsdLogClient(con, CUPSD_LOG_DEBUG2, "is_cgi: filename=\"%s\", filestats=%p, type=%s/%s, returning 1.", filename, filestats, type->super, type->type);
- return (1);
- }
-#endif /* HAVE_PERL */
-#ifdef HAVE_PHP
- else if (!_cups_strcasecmp(type->type, "x-httpd-php"))
- {
- /*
- * "application/x-httpd-php" is a PHP page.
- */
-
- cupsdSetString(&con->command, CUPS_PHP);
-
- if (options)
- cupsdSetStringf(&con->options, " %s %s", filename, options);
- else
- cupsdSetStringf(&con->options, " %s", filename);
-
- cupsdLogClient(con, CUPSD_LOG_DEBUG2, "is_cgi: filename=\"%s\", filestats=%p, type=%s/%s, returning 1.", filename, filestats, type->super, type->type);
- return (1);
- }
-#endif /* HAVE_PHP */
-#ifdef HAVE_PYTHON
- else if (!_cups_strcasecmp(type->type, "x-httpd-python"))
- {
- /*
- * "application/x-httpd-python" is a Python page.
- */
-
- cupsdSetString(&con->command, CUPS_PYTHON);
-
- if (options)
- cupsdSetStringf(&con->options, " %s %s", filename, options);
- else
- cupsdSetStringf(&con->options, " %s", filename);
-
- cupsdLogClient(con, CUPSD_LOG_DEBUG2, "is_cgi: filename=\"%s\", filestats=%p, type=%s/%s, returning 1.", filename, filestats, type->super, type->type);
- return (1);
- }
-#endif /* HAVE_PYTHON */
cupsdLogClient(con, CUPSD_LOG_DEBUG2, "is_cgi: filename=\"%s\", filestats=%p, type=%s/%s, returning 0.", filename, filestats, type->super, type->type);
return (0);
else
auth_type[0] = '\0';
- if (con->request &&
- (attr = ippFindAttribute(con->request, "attributes-natural-language",
- IPP_TAG_LANGUAGE)) != NULL)
+ if (con->request && (attr = ippFindAttribute(con->request, "attributes-natural-language", IPP_TAG_LANGUAGE)) != NULL)
{
- switch (strlen(attr->values[0].string.text))
- {
- default :
- /*
- * This is an unknown or badly formatted language code; use
- * the POSIX locale...
- */
+ cups_lang_t *language = cupsLangGet(ippGetString(attr, 0, NULL));
- strlcpy(lang, "LANG=C", sizeof(lang));
- break;
-
- case 2 :
- /*
- * Just the language code (ll)...
- */
-
- snprintf(lang, sizeof(lang), "LANG=%s.UTF8",
- attr->values[0].string.text);
- break;
-
- case 5 :
- /*
- * Language and country code (ll-cc)...
- */
-
- snprintf(lang, sizeof(lang), "LANG=%c%c_%c%c.UTF8",
- attr->values[0].string.text[0],
- attr->values[0].string.text[1],
- toupper(attr->values[0].string.text[3] & 255),
- toupper(attr->values[0].string.text[4] & 255));
- break;
- }
+ snprintf(lang, sizeof(lang), "LANG=%s.UTF8", language->language);
+ cupsLangFree(language);
}
else if (con->language)
snprintf(lang, sizeof(lang), "LANG=%s.UTF8", con->language->language);