X-Git-Url: http://git.ipfire.org/?a=blobdiff_plain;f=scheduler%2Fclient.c;h=95b9db68074fe26adc549eafadc16b5c2c6397e1;hb=be7581b6e3a6b0b44255ddb533a30db03ad5c337;hp=ae998e27f0a712aa004d40c4fb6f628e60a190d4;hpb=8719e9dbf52d4cdbc07f6fc7a1f3f113436ee3c6;p=thirdparty%2Fcups.git diff --git a/scheduler/client.c b/scheduler/client.c index ae998e27f..95b9db680 100644 --- a/scheduler/client.c +++ b/scheduler/client.c @@ -1,19 +1,14 @@ /* - * "$Id$" - * * Client routines for the CUPS scheduler. * - * Copyright 2007-2015 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 - * 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. */ /* @@ -87,6 +82,8 @@ cupsdAcceptClient(cupsd_listener_t *lis)/* I - Listener socket */ if (cupsArrayCount(Clients) == MaxClients) return; + cupsdSetBusyState(1); + /* * Get a pointer to the next available client... */ @@ -143,7 +140,12 @@ cupsdAcceptClient(cupsd_listener_t *lis)/* I - Listener socket */ * Save the connected address and port number... */ - con->clientaddr = lis->address; + addrlen = sizeof(con->clientaddr); + + if (getsockname(httpGetFd(con->http), (struct sockaddr *)&con->clientaddr, &addrlen) || addrlen == 0) + con->clientaddr = lis->address; + + cupsdLogClient(con, CUPSD_LOG_DEBUG, "Server address is \"%s\".", httpAddrString(&con->clientaddr, name, sizeof(name))); /* * Check the number of clients on the same address... @@ -436,7 +438,7 @@ cupsdCloseClient(cupsd_client_t *con) /* I - Client to close */ if (httpGetFd(con->http) >= 0) { cupsArrayRemove(ActiveClients, con); - cupsdSetBusyState(); + cupsdSetBusyState(0); #ifdef HAVE_SSL /* @@ -555,7 +557,6 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ 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 */ @@ -757,7 +758,7 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ if (!cupsArrayFind(ActiveClients, con)) { cupsArrayAdd(ActiveClients, con); - cupsdSetBusyState(); + cupsdSetBusyState(0); } case HTTP_STATE_OPTIONS : @@ -809,10 +810,22 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ * Handle new transfers... */ - cupsdLogClient(con, CUPSD_LOG_DEBUG, "Read: status=%d", status); + cupsdLogClient(con, CUPSD_LOG_DEBUG, "Read: status=%d, state=%d", status, httpGetState(con->http)); 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]) { /* @@ -1038,116 +1051,65 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ 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 (type == NULL) + strlcpy(line, "text/plain", sizeof(line)); + else + snprintf(line, sizeof(line), "%s/%s", type->super, type->type); - if (p) + if (!write_file(con, HTTP_STATUS_OK, filename, line, &filestats)) { - 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; + cupsdCloseClient(con); + return; } } - - if (p) - snprintf(con->uri, sizeof(con->uri), "/icons/%s.png", p->name); - else + } + 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 (!cupsdSendError(con, HTTP_STATUS_NOT_FOUND, CUPSD_AUTH_NONE)) + /* + * Web interface is disabled. Show an appropriate message... + */ + + if (!cupsdSendError(con, HTTP_STATUS_CUPS_WEBIF_DISABLED, CUPSD_AUTH_NONE)) { cupsdCloseClient(con); return; @@ -1155,46 +1117,19 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ break; } - } - else if (!WebInterface) - { - /* - * Web interface is disabled. Show an appropriate message... - */ - - if (!cupsdSendError(con, HTTP_STATUS_CUPS_WEBIF_DISABLED, CUPSD_AUTH_NONE)) - { - cupsdCloseClient(con); - return; - } - break; - } - - if ((!strncmp(con->uri, "/admin", 6) && - strncmp(con->uri, "/admin/conf/", 12) && - 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)) - { /* * Send CGI output... */ 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 @@ -1202,9 +1137,7 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ } 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 @@ -1212,9 +1145,7 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ } 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 @@ -1222,9 +1153,7 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ } 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 @@ -1245,95 +1174,13 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ if (httpGetVersion(con->http) <= HTTP_VERSION_1_0) httpSetKeepAlive(con->http, HTTP_KEEPALIVE_OFF); } - else if ((!strncmp(con->uri, "/admin/conf/", 12) && - (strchr(con->uri + 12, '/') || - strlen(con->uri) == 12)) || - (!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; @@ -1343,9 +1190,7 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ * 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... @@ -1379,9 +1224,11 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ * 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) { /* @@ -1396,13 +1243,29 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ break; } - else if ((!strncmp(con->uri, "/admin", 6) && - strncmp(con->uri, "/admin/conf/", 12) && - 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... @@ -1410,16 +1273,12 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ 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 @@ -1427,9 +1286,7 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ } 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 @@ -1437,9 +1294,7 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ } 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 @@ -1447,9 +1302,7 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ } 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 @@ -1461,35 +1314,10 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ } 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; @@ -1505,8 +1333,7 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ * 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)) { @@ -1522,9 +1349,7 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ * 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... @@ -1557,15 +1382,12 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ * 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)) { @@ -1586,54 +1408,44 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ 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); @@ -1648,13 +1460,7 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ break; } - if ((!strncmp(con->uri, "/admin", 6) && - strncmp(con->uri, "/admin/conf/", 12) && - 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... @@ -1670,79 +1476,17 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ cupsdLogRequest(con, HTTP_STATUS_OK); } - else if ((!strncmp(con->uri, "/admin/conf/", 12) && - (strchr(con->uri + 12, '/') || - strlen(con->uri) == 12)) || - (!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; @@ -2095,7 +1839,7 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ else { cupsArrayRemove(ActiveClients, con); - cupsdSetBusyState(); + cupsdSetBusyState(0); } } } @@ -2361,46 +2105,58 @@ cupsdSendHeader( 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 OS X 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\"", name + 9); + need_local = 0; /* end parenthesis is stripped in conf.c */ break; } @@ -2410,16 +2166,18 @@ cupsdSendHeader( { #ifdef HAVE_AUTHORIZATION_H if (SystemGroupAuthKey) - snprintf(auth_key, auth_size, - ", authkey=\"%s\"", - SystemGroupAuthKey); + snprintf(auth_key, auth_size, ", AuthRef key=\"%s\"", SystemGroupAuthKey); else #else - strlcpy(auth_key, ", trc=\"y\"", auth_size); + strlcpy(auth_key, ", Local trc=\"y\"", auth_size); #endif /* HAVE_AUTHORIZATION_H */ + need_local = 0; break; } } + + if (need_local) + strlcat(auth_key, ", Local", auth_size); } if (auth_str[0]) @@ -2822,7 +2580,7 @@ cupsdWriteClient(cupsd_client_t *con) /* I - Client connection */ else { cupsArrayRemove(ActiveClients, con); - cupsdSetBusyState(); + cupsdSetBusyState(0); } } } @@ -2938,6 +2696,7 @@ get_file(cupsd_client_t *con, /* I - Client connection */ char language[7], /* Language subdirectory, if any */ dest[1024]; /* Destination name */ int perm_check = 1; /* Do permissions check? */ + cupsd_printer_t *p; /* Printer */ /* @@ -2946,47 +2705,76 @@ get_file(cupsd_client_t *con, /* I - Client connection */ 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); @@ -2994,6 +2782,27 @@ get_file(cupsd_client_t *con, /* I - Client connection */ } 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); @@ -3033,6 +2842,7 @@ get_file(cupsd_client_t *con, /* I - Client connection */ 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)) { @@ -3128,45 +2938,6 @@ get_file(cupsd_client_t *con, /* I - Client connection */ 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]); @@ -3349,78 +3120,6 @@ is_cgi(cupsd_client_t *con, /* I - Client connection */ 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); @@ -3642,42 +3341,12 @@ pipe_command(cupsd_client_t *con, /* I - Client connection */ 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... - */ - - strlcpy(lang, "LANG=C", sizeof(lang)); - break; + cups_lang_t *language = cupsLangGet(ippGetString(attr, 0, NULL)); - 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); @@ -3903,9 +3572,6 @@ valid_host(cupsd_client_t *con) /* I - Client connection */ return (!_cups_strcasecmp(con->clientname, "localhost") || !_cups_strcasecmp(con->clientname, "localhost.") || -#ifdef __linux - !_cups_strcasecmp(con->clientname, "localhost.localdomain") || -#endif /* __linux */ !strcmp(con->clientname, "127.0.0.1") || !strcmp(con->clientname, "[::1]")); } @@ -4090,8 +3756,3 @@ write_pipe(cupsd_client_t *con) /* I - Client connection */ cupsdLogClient(con, CUPSD_LOG_DEBUG, "CGI data ready to be sent."); } - - -/* - * End of "$Id$". - */