/*
* 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.
*/
/*
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 (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))
- {
- cupsdCloseClient(con);
- return;
- }
-
- break;
- }
-
- type = mimeFileType(MimeDatabase, filename, NULL, NULL);
-
- if (!is_cgi(con, filename, &filestats, type))
+ if (!cupsdSendError(con, HTTP_STATUS_NOT_FOUND, CUPSD_AUTH_NONE))
{
- /*
- * 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;
auth_str[0] = '\0';
if (auth_type == CUPSD_AUTH_BASIC)
+ {
strlcpy(auth_str, "Basic realm=\"CUPS\"", sizeof(auth_str));
+ }
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));
}
- 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])
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 */
+
+ 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;
+ }
+ }
+ }
- snprintf(filename, len, "%s%s", ServerRoot, con->uri);
+ 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))
{