diff options
Diffstat (limited to 'scheduler/client.c')
-rw-r--r-- | scheduler/client.c | 1424 |
1 files changed, 226 insertions, 1198 deletions
diff --git a/scheduler/client.c b/scheduler/client.c index e40ed270..4d42bcea 100644 --- a/scheduler/client.c +++ b/scheduler/client.c @@ -1,9 +1,9 @@ /* - * "$Id: client.c 10338 2012-03-07 06:05:39Z mike $" + * "$Id: client.c 10455 2012-05-07 22:41:30Z mike $" * * Client routines for the CUPS scheduler. * - * Copyright 2007-2011 by Apple Inc. + * Copyright 2007-2012 by Apple Inc. * Copyright 1997-2007 by Easy Software Products, all rights reserved. * * This file contains Kerberos support code, copyright 2006 by @@ -17,34 +17,30 @@ * * Contents: * - * cupsdAcceptClient() - Accept a new client. - * cupsdCloseAllClients() - Close all remote clients immediately. - * cupsdCloseClient() - Close a remote client. - * cupsdFlushHeader() - Flush the header fields to the client. - * cupsdReadClient() - Read data from a client. - * cupsdSendCommand() - Send output from a command via HTTP. - * cupsdSendError() - Send an error message via HTTP. - * cupsdSendHeader() - Send an HTTP request. - * cupsdUpdateCGI() - Read status messages from CGI scripts and - * programs. - * cupsdWriteClient() - Write data to a client as needed. - * check_if_modified() - Decode an "If-Modified-Since" line. - * compare_clients() - Compare two client connections. - * copy_cdsa_certificate() - Copy a SSL/TLS certificate from the System - * keychain. - * data_ready() - Check whether data is available from a client. - * encrypt_client() - Enable encryption for the client... - * get_file() - Get a filename and state info. - * install_conf_file() - Install a configuration file. - * is_cgi() - Is the resource a CGI script/program? - * is_path_absolute() - Is a path absolute and free of relative elements - * (i.e. ".."). - * make_certificate() - Make a self-signed SSL/TLS certificate. - * pipe_command() - Pipe the output of a command to the remote - * client. - * valid_host() - Is the Host: field valid? - * write_file() - Send a file via HTTP. - * write_pipe() - Flag that data is available on the CGI pipe. + * cupsdAcceptClient() - Accept a new client. + * cupsdCloseAllClients() - Close all remote clients immediately. + * cupsdCloseClient() - Close a remote client. + * cupsdFlushHeader() - Flush the header fields to the client. + * cupsdReadClient() - Read data from a client. + * cupsdSendCommand() - Send output from a command via HTTP. + * cupsdSendError() - Send an error message via HTTP. + * cupsdSendHeader() - Send an HTTP request. + * cupsdUpdateCGI() - Read status messages from CGI scripts and + * programs. + * cupsdWriteClient() - Write data to a client as needed. + * check_if_modified() - Decode an "If-Modified-Since" line. + * compare_clients() - Compare two client connections. + * data_ready() - Check whether data is available from a client. + * get_file() - Get a filename and state info. + * install_conf_file() - Install a configuration file. + * is_cgi() - Is the resource a CGI script/program? + * is_path_absolute() - Is a path absolute and free of relative elements + * (i.e. ".."). + * pipe_command() - Pipe the output of a command to the remote + * client. + * valid_host() - Is the Host: field valid? + * write_file() - Send a file via HTTP. + * write_pipe() - Flag that data is available on the CGI pipe. */ /* @@ -59,6 +55,36 @@ /* + * Local globals... + */ + +static const char * const http_states[] = + { /* HTTP state strings */ + "HTTP_WAITING", + "HTTP_OPTIONS", + "HTTP_GET", + "HTTP_GET_SEND", + "HTTP_HEAD", + "HTTP_POST", + "HTTP_POST_RECV", + "HTTP_POST_SEND", + "HTTP_PUT", + "HTTP_PUT_RECV", + "HTTP_DELETE", + "HTTP_TRACE", + "HTTP_CLOSE", + "HTTP_STATUS" + }; +static const char * const ipp_states[] = + { /* IPP state strings */ + "IPP_IDLE", + "IPP_HEADER", + "IPP_ATTRIBUTE", + "IPP_DATA" + }; + + +/* * Local functions... */ @@ -66,22 +92,13 @@ static int check_if_modified(cupsd_client_t *con, struct stat *filestats); static int compare_clients(cupsd_client_t *a, cupsd_client_t *b, void *data); -#ifdef HAVE_CDSASSL -static CFArrayRef copy_cdsa_certificate(cupsd_client_t *con); -#endif /* HAVE_CDSASSL */ static int data_ready(cupsd_client_t *con); -#ifdef HAVE_SSL -static int encrypt_client(cupsd_client_t *con); -#endif /* HAVE_SSL */ static char *get_file(cupsd_client_t *con, struct stat *filestats, char *filename, int len); static http_status_t install_conf_file(cupsd_client_t *con); static int is_cgi(cupsd_client_t *con, const char *filename, struct stat *filestats, mime_type_t *type); static int is_path_absolute(const char *path); -#ifdef HAVE_SSL -static int make_certificate(cupsd_client_t *con); -#endif /* HAVE_SSL */ static int pipe_command(cupsd_client_t *con, int infile, int *outfile, char *command, char *options, int root); static int valid_host(cupsd_client_t *con); @@ -157,8 +174,8 @@ cupsdAcceptClient(cupsd_listener_t *lis)/* I - Listener socket */ return; } - con->http.activity = time(NULL); con->file = -1; + con->http.activity = time(NULL); con->http.hostaddr = &(con->clientaddr); con->http.wait_value = 10000; @@ -356,11 +373,11 @@ cupsdAcceptClient(cupsd_listener_t *lis)/* I - Listener socket */ #ifdef AF_LOCAL if (con->http.hostaddr->addr.sa_family == AF_LOCAL) - cupsdLogMessage(CUPSD_LOG_DEBUG, "cupsdAcceptClient: %d from %s (Domain)", + cupsdLogMessage(CUPSD_LOG_DEBUG, "[Client %d] Accepted from %s (Domain)", con->http.fd, con->http.hostname); else #endif /* AF_LOCAL */ - cupsdLogMessage(CUPSD_LOG_DEBUG, "cupsdAcceptClient: %d from %s:%d (IPv%d)", + cupsdLogMessage(CUPSD_LOG_DEBUG, "[Client %d] Accepted from %s:%d (IPv%d)", con->http.fd, con->http.hostname, _httpAddrPort(con->http.hostaddr), _httpAddrFamily(con->http.hostaddr) == AF_INET ? 4 : 6); @@ -397,6 +414,10 @@ cupsdAcceptClient(cupsd_listener_t *lis)/* I - Listener socket */ con->serverport = _httpAddrPort(&(lis->address)); } + /* + * Add the connection to the array of active clients... + */ + cupsArrayAdd(Clients, con); /* @@ -440,7 +461,7 @@ cupsdAcceptClient(cupsd_listener_t *lis)/* I - Listener socket */ con->http.encryption = HTTP_ENCRYPT_ALWAYS; - if (!encrypt_client(con)) + if (!cupsdStartTLS(con)) cupsdCloseClient(con); } else @@ -479,17 +500,13 @@ cupsdCloseClient(cupsd_client_t *con) /* I - Client to close */ { int partial; /* Do partial close for SSL? */ #ifdef HAVE_LIBSSL - SSL_CTX *context; /* Context for encryption */ - unsigned long error; /* Error code */ #elif defined(HAVE_GNUTLS) - int error; /* Error code */ - gnutls_certificate_server_credentials *credentials; - /* TLS credentials */ # elif defined(HAVE_CDSASSL) #endif /* HAVE_LIBSSL */ - cupsdLogMessage(CUPSD_LOG_DEBUG, "cupsdCloseClient: %d", con->http.fd); + cupsdLogMessage(CUPSD_LOG_DEBUG, "[Client %d] Closing connection.", + con->http.fd); /* * Flush pending writes before closing... @@ -508,60 +525,7 @@ cupsdCloseClient(cupsd_client_t *con) /* I - Client to close */ { partial = 1; -# ifdef HAVE_LIBSSL - context = SSL_get_SSL_CTX(con->http.tls); - - switch (SSL_shutdown(con->http.tls)) - { - case 1 : - cupsdLogMessage(CUPSD_LOG_DEBUG, - "SSL shutdown successful!"); - break; - case -1 : - cupsdLogMessage(CUPSD_LOG_ERROR, - "Fatal error during SSL shutdown!"); - default : - while ((error = ERR_get_error()) != 0) - cupsdLogMessage(CUPSD_LOG_ERROR, "SSL shutdown failed: %s", - ERR_error_string(error, NULL)); - break; - } - - SSL_CTX_free(context); - SSL_free(con->http.tls); - -# elif defined(HAVE_GNUTLS) - credentials = (gnutls_certificate_server_credentials *)(con->http.tls_credentials); - - error = gnutls_bye(con->http.tls, GNUTLS_SHUT_WR); - switch (error) - { - case GNUTLS_E_SUCCESS: - cupsdLogMessage(CUPSD_LOG_DEBUG, - "SSL shutdown successful!"); - break; - default: - cupsdLogMessage(CUPSD_LOG_ERROR, - "SSL shutdown failed: %s", gnutls_strerror(error)); - break; - } - - gnutls_deinit(con->http.tls); - gnutls_certificate_free_credentials(*credentials); - free(credentials); - -# elif defined(HAVE_CDSASSL) - while (SSLClose(con->http.tls) == errSSLWouldBlock) - usleep(1000); - - SSLDisposeContext(con->http.tls); - - if (con->http.tls_credentials) - CFRelease(con->http.tls_credentials); - -# endif /* HAVE_LIBSSL */ - - con->http.tls = NULL; + cupsdEndTLS(con); } #endif /* HAVE_SSL */ @@ -719,18 +683,22 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ status = HTTP_CONTINUE; cupsdLogMessage(CUPSD_LOG_DEBUG2, - "cupsdReadClient(con=%p(%d)) " - "con->http.error=%d " - "con->http.used=%d, " - "con->http.state=%d " - "con->data_encoding=HTTP_ENCODE_%s, " - "con->data_remaining=" CUPS_LLFMT ", " - "con->file=%d", - con, con->http.fd, con->http.error, con->http.used, - con->http.state, + "[Client %d] cupsdReadClient " + "error=%d, " + "used=%d, " + "state=%s, " + "data_encoding=HTTP_ENCODE_%s, " + "data_remaining=" CUPS_LLFMT ", " + "request=%p(%s), " + "file=%d", + con->http.fd, con->http.error, con->http.used, + http_states[con->http.state], con->http.data_encoding == HTTP_ENCODE_CHUNKED ? "CHUNKED" : "LENGTH", - CUPS_LLCAST con->http.data_remaining, con->file); + CUPS_LLCAST con->http.data_remaining, + con->request, + con->request ? ipp_states[con->request->state] : "", + con->file); #ifdef HAVE_SSL if (con->auto_ssl) @@ -749,10 +717,10 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ */ cupsdLogMessage(CUPSD_LOG_DEBUG2, - "cupsdReadClient: Saw first byte %02X, auto-negotiating " - "SSL/TLS session...", buf[0] & 255); + "[Client %d] Saw first byte %02X, auto-negotiating " + "SSL/TLS session.", con->http.fd, buf[0] & 255); - if (!encrypt_client(con)) + if (!cupsdStartTLS(con)) cupsdCloseClient(con); return; @@ -771,12 +739,12 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ { if (con->http.error && con->http.error != EPIPE) cupsdLogMessage(CUPSD_LOG_DEBUG, - "cupsdReadClient: %d WAITING Closing for error %d " + "[Client %d] HTTP_WAITING Closing for error %d " "(%s)", con->http.fd, con->http.error, strerror(con->http.error)); else cupsdLogMessage(CUPSD_LOG_DEBUG, - "cupsdReadClient: %d WAITING Closing on EOF", + "[Client %d] HTTP_WAITING Closing on EOF", con->http.fd); cupsdCloseClient(con); @@ -848,7 +816,8 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ if (line[0]) { cupsdLogMessage(CUPSD_LOG_ERROR, - "Bad request line \"%s\" from %s!", + "[Client %d] Bad request line \"%s\" from %s.", + con->http.fd, _httpEncodeURI(buf, line, sizeof(buf)), con->http.hostname); cupsdSendError(con, HTTP_BAD_REQUEST, CUPSD_AUTH_NONE); @@ -862,7 +831,8 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ if (sscanf(version, "HTTP/%d.%d", &major, &minor) != 2) { cupsdLogMessage(CUPSD_LOG_ERROR, - "Bad request line \"%s\" from %s!", + "[Client %d] Bad request line \"%s\" from %s.", + con->http.fd, _httpEncodeURI(buf, line, sizeof(buf)), con->http.hostname); cupsdSendError(con, HTTP_BAD_REQUEST, CUPSD_AUTH_NONE); @@ -881,7 +851,8 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ else { cupsdLogMessage(CUPSD_LOG_ERROR, - "Unsupported request line \"%s\" from %s!", + "[Client %d] Unsupported request line \"%s\" " + "from %s.", con->http.fd, _httpEncodeURI(buf, line, sizeof(buf)), con->http.hostname); cupsdSendError(con, HTTP_NOT_SUPPORTED, CUPSD_AUTH_NONE); @@ -928,8 +899,9 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ * Nope, we don't do proxies... */ - cupsdLogMessage(CUPSD_LOG_ERROR, "Bad URI \"%s\" in request!", - con->uri); + cupsdLogMessage(CUPSD_LOG_ERROR, + "[Client %d] Bad URI \"%s\" in request.", + con->http.fd, con->uri); cupsdSendError(con, HTTP_METHOD_NOT_ALLOWED, CUPSD_AUTH_NONE); cupsdCloseClient(con); return; @@ -963,7 +935,9 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ con->http.state = HTTP_HEAD; else { - cupsdLogMessage(CUPSD_LOG_ERROR, "Bad operation \"%s\"!", operation); + cupsdLogMessage(CUPSD_LOG_ERROR, + "[Client %d] Bad operation \"%s\".", con->http.fd, + operation); cupsdSendError(con, HTTP_BAD_REQUEST, CUPSD_AUTH_NONE); cupsdCloseClient(con); return; @@ -972,7 +946,7 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ gettimeofday(&(con->start), NULL); con->operation = con->http.state; - cupsdLogMessage(CUPSD_LOG_DEBUG, "cupsdReadClient: %d %s %s HTTP/%d.%d", + cupsdLogMessage(CUPSD_LOG_DEBUG, "[Client %d] %s %s HTTP/%d.%d", con->http.fd, operation, con->uri, con->http.version / 100, con->http.version % 100); @@ -1003,13 +977,14 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ { if (con->http.error && con->http.error != EPIPE) cupsdLogMessage(CUPSD_LOG_DEBUG, - "cupsdReadClient: %d FIELDS Closing for error %d " - "(%s)", con->http.fd, con->http.error, + "[Client %d] Closing for error %d (%s) while " + "reading headers.", + con->http.fd, con->http.error, strerror(con->http.error)); else cupsdLogMessage(CUPSD_LOG_DEBUG, - "cupsdReadClient: %d FIELDS Closing on EOF", - con->http.fd); + "[Client %d] Closing on EOF while reading headers.", + con->http.fd); cupsdSendError(con, HTTP_BAD_REQUEST, CUPSD_AUTH_NONE); cupsdCloseClient(con); @@ -1025,7 +1000,7 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ */ cupsdLogMessage(CUPSD_LOG_DEBUG, - "cupsdReadClient: %d Closing on EOF", con->http.fd); + "[Client %d] Closing on EOF", con->http.fd); cupsdCloseClient(con); return; } @@ -1078,10 +1053,11 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ cupsdAuthorize(con); - if (!_cups_strncasecmp(con->http.fields[HTTP_FIELD_CONNECTION], "Keep-Alive", - 10) && KeepAlive) + if (!_cups_strncasecmp(con->http.fields[HTTP_FIELD_CONNECTION], + "Keep-Alive", 10) && KeepAlive) con->http.keep_alive = HTTP_KEEPALIVE_ON; - else if (!_cups_strncasecmp(con->http.fields[HTTP_FIELD_CONNECTION], "close", 5)) + else if (!_cups_strncasecmp(con->http.fields[HTTP_FIELD_CONNECTION], + "close", 5)) con->http.keep_alive = HTTP_KEEPALIVE_OFF; if (!con->http.fields[HTTP_FIELD_HOST][0] && @@ -1093,7 +1069,9 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ if (!cupsdSendError(con, HTTP_BAD_REQUEST, CUPSD_AUTH_NONE)) { - cupsdLogMessage(CUPSD_LOG_ERROR, "Missing Host: field in request!"); + cupsdLogMessage(CUPSD_LOG_ERROR, + "[Client %d] Missing Host: field in request.", + con->http.fd); cupsdCloseClient(con); return; } @@ -1106,8 +1084,9 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ */ cupsdLogMessage(CUPSD_LOG_ERROR, - "Request from \"%s\" using invalid Host: field \"%s\"", - con->http.hostname, con->http.fields[HTTP_FIELD_HOST]); + "[Client %d] Request from \"%s\" using invalid Host: " + "field \"%s\"", con->http.fd, con->http.hostname, + con->http.fields[HTTP_FIELD_HOST]); if (!cupsdSendError(con, HTTP_BAD_REQUEST, CUPSD_AUTH_NONE)) { @@ -1155,7 +1134,7 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ return; } - if (!encrypt_client(con)) + if (!cupsdStartTLS(con)) { cupsdCloseClient(con); return; @@ -1192,7 +1171,8 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ */ cupsdLogMessage(CUPSD_LOG_ERROR, - "Request for non-absolute resource \"%s\"!", con->uri); + "[Client %d] Request for non-absolute resource \"%s\".", + con->http.fd, con->uri); if (!cupsdSendError(con, HTTP_FORBIDDEN, CUPSD_AUTH_NONE)) { @@ -1202,15 +1182,16 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ } else { - if (!_cups_strcasecmp(con->http.fields[HTTP_FIELD_CONNECTION], "Upgrade") && - con->http.tls == NULL) + if (!_cups_strcasecmp(con->http.fields[HTTP_FIELD_CONNECTION], + "Upgrade") && con->http.tls == NULL) { #ifdef HAVE_SSL /* * Do encryption stuff... */ - if (!cupsdSendHeader(con, HTTP_SWITCHING_PROTOCOLS, NULL, CUPSD_AUTH_NONE)) + if (!cupsdSendHeader(con, HTTP_SWITCHING_PROTOCOLS, NULL, + CUPSD_AUTH_NONE)) { cupsdCloseClient(con); return; @@ -1227,7 +1208,7 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ return; } - if (!encrypt_client(con)) + if (!cupsdStartTLS(con)) { cupsdCloseClient(con); return; @@ -1695,7 +1676,8 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ */ cupsdLogMessage(CUPSD_LOG_ERROR, - "Request for subdirectory \"%s\"!", con->uri); + "[Client %d] Request for subdirectory \"%s\".", + con->http.fd, con->uri); if (!cupsdSendError(con, HTTP_FORBIDDEN, CUPSD_AUTH_NONE)) { @@ -1753,8 +1735,9 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ if (con->file < 0) { cupsdLogMessage(CUPSD_LOG_ERROR, - "Unable to create request file %s: %s", - con->filename, strerror(errno)); + "[Client %d] Unable to create request file " + "\"%s\": %s", con->http.fd, con->filename, + strerror(errno)); if (!cupsdSendError(con, HTTP_REQUEST_TOO_LARGE, CUPSD_AUTH_NONE)) { @@ -1890,7 +1873,8 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ */ cupsdLogMessage(CUPSD_LOG_ERROR, - "Request for subdirectory \"%s\"!", con->uri); + "[Client %d] Request for subdirectory \"%s\".", + con->http.fd, con->uri); if (!cupsdSendError(con, HTTP_FORBIDDEN, CUPSD_AUTH_NONE)) { @@ -1991,12 +1975,12 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ { if (con->http.error && con->http.error != EPIPE) cupsdLogMessage(CUPSD_LOG_DEBUG, - "cupsdReadClient: %d PUT_RECV Closing for error " + "[Client %d] HTTP_PUT_RECV Closing for error " "%d (%s)", con->http.fd, con->http.error, strerror(con->http.error)); else cupsdLogMessage(CUPSD_LOG_DEBUG, - "cupsdReadClient: %d PUT_RECV Closing on EOF", + "[Client %d] HTTP_PUT_RECV Closing on EOF", con->http.fd); cupsdCloseClient(con); @@ -2009,8 +1993,9 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ if (write(con->file, line, bytes) < bytes) { cupsdLogMessage(CUPSD_LOG_ERROR, - "cupsdReadClient: Unable to write %d bytes to %s: %s", - bytes, con->filename, strerror(errno)); + "[Client %d] Unable to write %d bytes to " + "\"%s\": %s", con->http.fd, bytes, con->filename, + strerror(errno)); close(con->file); con->file = -1; @@ -2085,8 +2070,8 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ if ((ipp_state = ippRead(&(con->http), con->request)) == IPP_ERROR) { cupsdLogMessage(CUPSD_LOG_ERROR, - "cupsdReadClient: %d IPP Read Error!", - con->http.fd); + "[Client %d] IPP read error: %s", con->http.fd, + cupsLastErrorString()); cupsdSendError(con, HTTP_BAD_REQUEST, CUPSD_AUTH_NONE); cupsdCloseClient(con); @@ -2105,7 +2090,7 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ } else { - cupsdLogMessage(CUPSD_LOG_DEBUG, "cupsdReadClient: %d %d.%d %s %d", + cupsdLogMessage(CUPSD_LOG_DEBUG, "[Client %d] %d.%d %s %d", con->http.fd, con->request->request.op.version[0], con->request->request.op.version[1], ippOpString(con->request->request.op.operation_id), @@ -2127,8 +2112,9 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ if (con->file < 0) { cupsdLogMessage(CUPSD_LOG_ERROR, - "Unable to create request file %s: %s", - con->filename, strerror(errno)); + "[Client %d] Unable to create request file " + "\"%s\": %s", con->http.fd, con->filename, + strerror(errno)); if (!cupsdSendError(con, HTTP_REQUEST_TOO_LARGE, CUPSD_AUTH_NONE)) { @@ -2148,12 +2134,12 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ { if (con->http.error && con->http.error != EPIPE) cupsdLogMessage(CUPSD_LOG_DEBUG, - "cupsdReadClient: %d POST_SEND Closing for " + "[Client %d] HTTP_POST_SEND Closing for " "error %d (%s)", con->http.fd, con->http.error, strerror(con->http.error)); else cupsdLogMessage(CUPSD_LOG_DEBUG, - "cupsdReadClient: %d POST_SEND Closing on EOF", + "[Client %d] HTTP_POST_SEND Closing on EOF", con->http.fd); cupsdCloseClient(con); @@ -2166,9 +2152,9 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ if (write(con->file, line, bytes) < bytes) { cupsdLogMessage(CUPSD_LOG_ERROR, - "cupsdReadClient: Unable to write %d bytes to " - "%s: %s", bytes, con->filename, - strerror(errno)); + "[Client %d] Unable to write %d bytes to " + "\"%s\": %s", con->http.fd, bytes, + con->filename, strerror(errno)); close(con->file); con->file = -1; @@ -2188,8 +2174,8 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ else if (con->http.state != HTTP_POST_SEND) { cupsdLogMessage(CUPSD_LOG_DEBUG, - "cupsdReadClient: %d Closing on unknown HTTP " - "state %d", con->http.fd, con->http.state); + "[Client %d] Closing on unexpected state %s.", + con->http.fd, http_states[con->http.state]); cupsdCloseClient(con); return; } @@ -2281,7 +2267,7 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ if (!con->http.keep_alive) { cupsdLogMessage(CUPSD_LOG_DEBUG, - "cupsdReadClient: %d Closing because Keep-Alive disabled", + "[Client %d] Closing because Keep-Alive disabled", con->http.fd); cupsdCloseClient(con); } @@ -2315,7 +2301,7 @@ cupsdSendCommand( if (fd < 0) { cupsdLogMessage(CUPSD_LOG_ERROR, - "cupsdSendCommand: %d Unable to open \"%s\" for reading: %s", + "[Client %d] Unable to open \"%s\" for reading: %s", con->http.fd, con->filename ? con->filename : "/dev/null", strerror(errno)); return (0); @@ -2331,11 +2317,11 @@ cupsdSendCommand( if (fd >= 0) close(fd); - cupsdLogMessage(CUPSD_LOG_INFO, "Started \"%s\" (pid=%d)", command, - con->pipe_pid); + cupsdLogMessage(CUPSD_LOG_INFO, "[Client %d] Started \"%s\" (pid=%d)", + con->http.fd, command, con->pipe_pid); - cupsdLogMessage(CUPSD_LOG_DEBUG, "cupsdSendCommand: %d file=%d", - con->http.fd, con->file); + cupsdLogMessage(CUPSD_LOG_DEBUG, "[Client %d] file=%d", con->http.fd, + con->file); if (con->pipe_pid == 0) return (0); @@ -2363,7 +2349,7 @@ cupsdSendError(cupsd_client_t *con, /* I - Connection */ int auth_type)/* I - Authentication type */ { cupsdLogMessage(CUPSD_LOG_DEBUG2, - "cupsdSendError(con=%p(%d), code=%d, auth_type=%d", con, + "[Client %d] cupsdSendError code=%d, auth_type=%d", con->http.fd, code, auth_type); #ifdef HAVE_SSL @@ -2519,10 +2505,6 @@ cupsdSendHeader( int auth_type) /* I - Type of authentication */ { char auth_str[1024]; /* Authorization string */ -#if 0 /* def HAVE_GSSAPI */ - static char *gss_buf = NULL; /* Kerberos auth data buffer */ - static int gss_bufsize = 0; /* Size of Kerberos auth data buffer */ -#endif /* HAVE_GSSAPI */ /* @@ -2577,7 +2559,7 @@ cupsdSendHeader( if (auth_type == CUPSD_AUTH_NONE) { if (!con->best || con->best->type <= CUPSD_AUTH_NONE) - auth_type = DefaultAuthType; + auth_type = cupsdDefaultAuthType(); else auth_type = con->best->type; } @@ -2609,7 +2591,7 @@ cupsdSendHeader( * requests when the request requires system group membership - then the * client knows the root certificate can/should be used. * - * Also, for Mac OS X we also look for @AUTHKEY and add an "authkey" + * Also, for OS X we also look for @AUTHKEY and add an "authkey" * parameter as needed... */ @@ -2652,7 +2634,7 @@ cupsdSendHeader( if (auth_str[0]) { cupsdLogMessage(CUPSD_LOG_DEBUG, - "cupsdSendHeader: %d WWW-Authenticate: %s", con->http.fd, + "[Client %d] WWW-Authenticate: %s", con->http.fd, auth_str); if (httpPrintf(HTTP(con), "WWW-Authenticate: %s\r\n", auth_str) < 0) @@ -2733,11 +2715,23 @@ cupsdWriteClient(cupsd_client_t *con) /* I - Client connection */ cupsdLogMessage(CUPSD_LOG_DEBUG2, - "cupsdWriteClient(con=%p(%d)) response=%p(%d), file=%d " - "pipe_pid=%d state=%d", - con, con->http.fd, con->response, - con->response ? con->response->state : -1, - con->file, con->pipe_pid, con->http.state); + "[Client %d] cupsdWriteClient " + "error=%d, " + "used=%d, " + "state=%s, " + "data_encoding=HTTP_ENCODE_%s, " + "data_remaining=" CUPS_LLFMT ", " + "response=%p(%s), " + "pipe_pid=%d, " + "file=%d", + con->http.fd, con->http.error, con->http.used, + http_states[con->http.state], + con->http.data_encoding == HTTP_ENCODE_CHUNKED ? + "CHUNKED" : "LENGTH", + CUPS_LLCAST con->http.data_remaining, + con->response, + con->response ? ipp_states[con->response->state] : "", + con->pipe_pid, con->file); if (con->http.state != HTTP_GET_SEND && con->http.state != HTTP_POST_SEND) @@ -2748,8 +2742,8 @@ cupsdWriteClient(cupsd_client_t *con) /* I - Client connection */ */ cupsdLogMessage(CUPSD_LOG_DEBUG, - "cupsdWriteClient: %d Closing on unknown HTTP state %d", - con->http.fd, con->http.state); + "[Client %d] Closing on unexpected HTTP state %s.", + con->http.fd, http_states[con->http.state]); cupsdCloseClient(con); return; } @@ -2902,7 +2896,7 @@ cupsdWriteClient(cupsd_client_t *con) /* I - Client connection */ if (httpWrite2(HTTP(con), con->header, con->header_used) < 0) { cupsdLogMessage(CUPSD_LOG_DEBUG, - "cupsdWriteClient: %d Closing for error %d (%s)", + "[Client %d] Closing for error %d (%s)", con->http.fd, con->http.error, strerror(con->http.error)); cupsdCloseClient(con); @@ -2939,7 +2933,7 @@ cupsdWriteClient(cupsd_client_t *con) /* I - Client connection */ if (httpWrite2(HTTP(con), "", 0) < 0) { cupsdLogMessage(CUPSD_LOG_DEBUG, - "cupsdWriteClient: %d Closing for error %d (%s)", + "[Client %d] Closing for error %d (%s)", con->http.fd, con->http.error, strerror(con->http.error)); cupsdCloseClient(con); @@ -2989,7 +2983,7 @@ cupsdWriteClient(cupsd_client_t *con) /* I - Client connection */ if (!con->http.keep_alive) { cupsdLogMessage(CUPSD_LOG_DEBUG, - "cupsdWriteClient: %d Closing because Keep-Alive disabled", + "[Client %d] Closing because Keep-Alive disabled.", con->http.fd); cupsdCloseClient(con); return; @@ -3027,9 +3021,9 @@ check_if_modified( return (1); cupsdLogMessage(CUPSD_LOG_DEBUG2, - "check_if_modified(con=%p(%d), " + "[Client %d] check_if_modified " "filestats=%p(" CUPS_LLFMT ", %d)) If-Modified-Since=\"%s\"", - con, con->http.fd, filestats, CUPS_LLCAST filestats->st_size, + con->http.fd, filestats, CUPS_LLCAST filestats->st_size, (int)filestats->st_mtime, ptr); while (*ptr != '\0') @@ -3081,274 +3075,6 @@ compare_clients(cupsd_client_t *a, /* I - First client */ } -#ifdef HAVE_CDSASSL -/* - * 'copy_cdsa_certificate()' - Copy a SSL/TLS certificate from the System - * keychain. - */ - -static CFArrayRef /* O - Array of certificates */ -copy_cdsa_certificate( - cupsd_client_t *con) /* I - Client connection */ -{ - OSStatus err; /* Error info */ - SecKeychainRef keychain = NULL;/* Keychain reference */ - SecIdentitySearchRef search = NULL; /* Search reference */ - SecIdentityRef identity = NULL;/* Identity */ - CFArrayRef certificates = NULL; - /* Certificate array */ -# if HAVE_SECPOLICYCREATESSL - SecPolicyRef policy = NULL; /* Policy ref */ - CFStringRef servername = NULL; - /* Server name */ - CFMutableDictionaryRef query = NULL; /* Query qualifiers */ - char localname[1024];/* Local hostname */ -# elif defined(HAVE_SECIDENTITYSEARCHCREATEWITHPOLICY) - SecPolicyRef policy = NULL; /* Policy ref */ - SecPolicySearchRef policy_search = NULL; - /* Policy search ref */ - CSSM_DATA options; /* Policy options */ - CSSM_APPLE_TP_SSL_OPTIONS - ssl_options; /* SSL Option for hostname */ - char localname[1024];/* Local hostname */ -# endif /* HAVE_SECPOLICYCREATESSL */ - - - cupsdLogMessage(CUPSD_LOG_DEBUG, - "copy_cdsa_certificate: Looking for certs for \"%s\"...", - con->servername); - - if ((err = SecKeychainOpen(ServerCertificate, &keychain))) - { - cupsdLogMessage(CUPSD_LOG_ERROR, "Cannot open keychain \"%s\" - %s (%d)", - ServerCertificate, cssmErrorString(err), (int)err); - goto cleanup; - } - -# if HAVE_SECPOLICYCREATESSL - servername = CFStringCreateWithCString(kCFAllocatorDefault, con->servername, - kCFStringEncodingUTF8); - - policy = SecPolicyCreateSSL(1, servername); - - if (servername) - CFRelease(servername); - - if (!policy) - { - cupsdLogMessage(CUPSD_LOG_ERROR, "Cannot create ssl policy reference"); - goto cleanup; - } - - if (!(query = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, - &kCFTypeDictionaryKeyCallBacks, - &kCFTypeDictionaryValueCallBacks))) - { - cupsdLogMessage(CUPSD_LOG_ERROR, "Cannot create query dictionary"); - goto cleanup; - } - - CFDictionaryAddValue(query, kSecClass, kSecClassIdentity); - CFDictionaryAddValue(query, kSecMatchPolicy, policy); - CFDictionaryAddValue(query, kSecReturnRef, kCFBooleanTrue); - CFDictionaryAddValue(query, kSecMatchLimit, kSecMatchLimitOne); - - err = SecItemCopyMatching(query, (CFTypeRef *)&identity); - - if (err && DNSSDHostName) - { - /* - * Search for the connection server name failed; try the DNS-SD .local - * hostname instead... - */ - - snprintf(localname, sizeof(localname), "%s.local", DNSSDHostName); - - cupsdLogMessage(CUPSD_LOG_DEBUG, - "copy_cdsa_certificate: Looking for certs for \"%s\"...", - localname); - - servername = CFStringCreateWithCString(kCFAllocatorDefault, localname, - kCFStringEncodingUTF8); - - CFRelease(policy); - - policy = SecPolicyCreateSSL(1, servername); - - if (servername) - CFRelease(servername); - - if (!policy) - { - cupsdLogMessage(CUPSD_LOG_ERROR, "Cannot create ssl policy reference"); - goto cleanup; - } - - CFDictionarySetValue(query, kSecMatchPolicy, policy); - - err = SecItemCopyMatching(query, (CFTypeRef *)&identity); - } - - if (err) - { - cupsdLogMessage(CUPSD_LOG_DEBUG, - "Cannot find signing key in keychain \"%s\": %s (%d)", - ServerCertificate, cssmErrorString(err), (int)err); - goto cleanup; - } - -# elif defined(HAVE_SECIDENTITYSEARCHCREATEWITHPOLICY) - /* - * Use a policy to search for valid certificates whose common name matches the - * servername... - */ - - if (SecPolicySearchCreate(CSSM_CERT_X_509v3, &CSSMOID_APPLE_TP_SSL, - NULL, &policy_search)) - { - cupsdLogMessage(CUPSD_LOG_ERROR, "Cannot create a policy search reference"); - goto cleanup; - } - - if (SecPolicySearchCopyNext(policy_search, &policy)) - { - cupsdLogMessage(CUPSD_LOG_ERROR, - "Cannot find a policy to use for searching"); - goto cleanup; - } - - memset(&ssl_options, 0, sizeof(ssl_options)); - ssl_options.Version = CSSM_APPLE_TP_SSL_OPTS_VERSION; - ssl_options.ServerName = con->servername; - ssl_options.ServerNameLen = strlen(con->servername); - - options.Data = (uint8 *)&ssl_options; - options.Length = sizeof(ssl_options); - - if (SecPolicySetValue(policy, &options)) - { - cupsdLogMessage(CUPSD_LOG_ERROR, - "Cannot set policy value to use for searching"); - goto cleanup; - } - - if ((err = SecIdentitySearchCreateWithPolicy(policy, NULL, CSSM_KEYUSE_SIGN, - keychain, FALSE, &search))) - { - cupsdLogMessage(CUPSD_LOG_ERROR, - "Cannot create identity search reference: %s (%d)", - cssmErrorString(err), (int)err); - goto cleanup; - } - - err = SecIdentitySearchCopyNext(search, &identity); - - if (err && DNSSDHostName) - { - /* - * Search for the connection server name failed; try the DNS-SD .local - * hostname instead... - */ - - snprintf(localname, sizeof(localname), "%s.local", DNSSDHostName); - - ssl_options.ServerName = localname; - ssl_options.ServerNameLen = strlen(localname); - - cupsdLogMessage(CUPSD_LOG_DEBUG, - "copy_cdsa_certificate: Looking for certs for \"%s\"...", - localname); - - if (SecPolicySetValue(policy, &options)) - { - cupsdLogMessage(CUPSD_LOG_ERROR, - "Cannot set policy value to use for searching"); - goto cleanup; - } - - CFRelease(search); - search = NULL; - if ((err = SecIdentitySearchCreateWithPolicy(policy, NULL, CSSM_KEYUSE_SIGN, - keychain, FALSE, &search))) - { - cupsdLogMessage(CUPSD_LOG_ERROR, - "Cannot create identity search reference: %s (%d)", - cssmErrorString(err), (int)err); - goto cleanup; - } - - err = SecIdentitySearchCopyNext(search, &identity); - - } - - if (err) - { - cupsdLogMessage(CUPSD_LOG_DEBUG, - "Cannot find signing key in keychain \"%s\": %s (%d)", - ServerCertificate, cssmErrorString(err), (int)err); - goto cleanup; - } - -# else - /* - * Assume there is exactly one SecIdentity in the keychain... - */ - - if ((err = SecIdentitySearchCreate(keychain, CSSM_KEYUSE_SIGN, &search))) - { - cupsdLogMessage(CUPSD_LOG_DEBUG, - "Cannot create identity search reference (%d)", (int)err); - goto cleanup; - } - - if ((err = SecIdentitySearchCopyNext(search, &identity))) - { - cupsdLogMessage(CUPSD_LOG_DEBUG, - "Cannot find signing key in keychain \"%s\": %s (%d)", - ServerCertificate, cssmErrorString(err), (int)err); - goto cleanup; - } -# endif /* HAVE_SECPOLICYCREATESSL */ - - if (CFGetTypeID(identity) != SecIdentityGetTypeID()) - { - cupsdLogMessage(CUPSD_LOG_ERROR, "SecIdentity CFTypeID failure!"); - goto cleanup; - } - - if ((certificates = CFArrayCreate(NULL, (const void **)&identity, - 1, &kCFTypeArrayCallBacks)) == NULL) - { - cupsdLogMessage(CUPSD_LOG_ERROR, "Cannot create certificate array"); - goto cleanup; - } - - cleanup : - - if (keychain) - CFRelease(keychain); - if (search) - CFRelease(search); - if (identity) - CFRelease(identity); - -# if HAVE_SECPOLICYCREATESSL - if (policy) - CFRelease(policy); - if (query) - CFRelease(query); -# elif defined(HAVE_SECIDENTITYSEARCHCREATEWITHPOLICY) - if (policy) - CFRelease(policy); - if (policy_search) - CFRelease(policy_search); -# endif /* HAVE_SECPOLICYCREATESSL */ - - return (certificates); -} -#endif /* HAVE_CDSASSL */ - - /* * 'data_ready()' - Check whether data is available from a client. */ @@ -3380,245 +3106,6 @@ data_ready(cupsd_client_t *con) /* I - Client */ } -#ifdef HAVE_SSL -/* - * 'encrypt_client()' - Enable encryption for the client... - */ - -static int /* O - 1 on success, 0 on error */ -encrypt_client(cupsd_client_t *con) /* I - Client to encrypt */ -{ -# ifdef HAVE_LIBSSL - SSL_CTX *context; /* Context for encryption */ - BIO *bio; /* BIO data */ - unsigned long error; /* Error code */ - - - cupsdLogMessage(CUPSD_LOG_DEBUG2, "encrypt_client(con=%p(%d))", con, - con->http.fd); - - /* - * Verify that we have a certificate... - */ - - if (access(ServerKey, 0) || access(ServerCertificate, 0)) - { - /* - * Nope, make a self-signed certificate... - */ - - if (!make_certificate(con)) - return (0); - } - - /* - * Create the SSL context and accept the connection... - */ - - context = SSL_CTX_new(SSLv23_server_method()); - - SSL_CTX_set_options(context, SSL_OP_NO_SSLv2); /* Only use SSLv3 or TLS */ - if (SSLOptions & CUPSD_SSL_NOEMPTY) - SSL_CTX_set_options(context, SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS); - SSL_CTX_use_PrivateKey_file(context, ServerKey, SSL_FILETYPE_PEM); - SSL_CTX_use_certificate_chain_file(context, ServerCertificate); - - bio = BIO_new(_httpBIOMethods()); - BIO_ctrl(bio, BIO_C_SET_FILE_PTR, 0, (char *)HTTP(con)); - - con->http.tls = SSL_new(context); - SSL_set_bio(con->http.tls, bio, bio); - - if (SSL_accept(con->http.tls) != 1) - { - cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to encrypt connection from %s.", - con->http.hostname); - - while ((error = ERR_get_error()) != 0) - cupsdLogMessage(CUPSD_LOG_ERROR, "%s", ERR_error_string(error, NULL)); - - SSL_CTX_free(context); - SSL_free(con->http.tls); - con->http.tls = NULL; - return (0); - } - - cupsdLogMessage(CUPSD_LOG_DEBUG, "Connection from %s now encrypted.", - con->http.hostname); - - return (1); - -# elif defined(HAVE_GNUTLS) - int status; /* Error code */ - gnutls_certificate_server_credentials *credentials; - /* TLS credentials */ - - - cupsdLogMessage(CUPSD_LOG_DEBUG2, "encrypt_client(con=%p(%d))", con, - con->http.fd); - - /* - * Verify that we have a certificate... - */ - - if (access(ServerKey, 0) || access(ServerCertificate, 0)) - { - /* - * Nope, make a self-signed certificate... - */ - - if (!make_certificate(con)) - return (0); - } - - /* - * Create the SSL object and perform the SSL handshake... - */ - - credentials = (gnutls_certificate_server_credentials *) - malloc(sizeof(gnutls_certificate_server_credentials)); - if (credentials == NULL) - { - cupsdLogMessage(CUPSD_LOG_ERROR, - "Unable to encrypt connection from %s - %s", - con->http.hostname, strerror(errno)); - - return (0); - } - - gnutls_certificate_allocate_credentials(credentials); - gnutls_certificate_set_x509_key_file(*credentials, ServerCertificate, - ServerKey, GNUTLS_X509_FMT_PEM); - - gnutls_init(&con->http.tls, GNUTLS_SERVER); - gnutls_set_default_priority(con->http.tls); - - gnutls_credentials_set(con->http.tls, GNUTLS_CRD_CERTIFICATE, *credentials); - gnutls_transport_set_ptr(con->http.tls, (gnutls_transport_ptr)HTTP(con)); - gnutls_transport_set_pull_function(con->http.tls, _httpReadGNUTLS); - gnutls_transport_set_push_function(con->http.tls, _httpWriteGNUTLS); - - while ((status = gnutls_handshake(con->http.tls)) != GNUTLS_E_SUCCESS) - { - if (gnutls_error_is_fatal(status)) - { - cupsdLogMessage(CUPSD_LOG_ERROR, - "Unable to encrypt connection from %s - %s", - con->http.hostname, gnutls_strerror(status)); - - gnutls_deinit(con->http.tls); - gnutls_certificate_free_credentials(*credentials); - con->http.tls = NULL; - free(credentials); - return (0); - } - } - - cupsdLogMessage(CUPSD_LOG_DEBUG, "Connection from %s now encrypted.", - con->http.hostname); - - con->http.tls_credentials = credentials; - return (1); - -# elif defined(HAVE_CDSASSL) - OSStatus error = 0; /* Error code */ - CFArrayRef peerCerts; /* Peer certificates */ - - - cupsdLogMessage(CUPSD_LOG_DEBUG2, "encrypt_client(con=%p(%d))", con, - con->http.fd); - - con->http.tls_credentials = copy_cdsa_certificate(con); - - if (!con->http.tls_credentials) - { - /* - * No keychain (yet), make a self-signed certificate... - */ - - if (make_certificate(con)) - con->http.tls_credentials = copy_cdsa_certificate(con); - } - - if (!con->http.tls_credentials) - { - cupsdLogMessage(CUPSD_LOG_ERROR, - "Could not find signing key in keychain \"%s\"", - ServerCertificate); - error = errSSLBadCert; /* errSSLBadConfiguration is a better choice, but not available on 10.2.x */ - } - - if (!error) - error = SSLNewContext(true, &con->http.tls); - - if (!error) - error = SSLSetIOFuncs(con->http.tls, _httpReadCDSA, _httpWriteCDSA); - - if (!error) - error = SSLSetConnection(con->http.tls, HTTP(con)); - - if (!error) - error = SSLSetAllowsExpiredCerts(con->http.tls, true); - - if (!error) - error = SSLSetAllowsAnyRoot(con->http.tls, true); - - if (!error) - error = SSLSetCertificate(con->http.tls, con->http.tls_credentials); - - if (!error) - { - /* - * Perform SSL/TLS handshake - */ - - while ((error = SSLHandshake(con->http.tls)) == errSSLWouldBlock) - usleep(1000); - } - - if (error) - { - cupsdLogMessage(CUPSD_LOG_ERROR, - "Unable to encrypt connection from %s - %s (%d)", - con->http.hostname, cssmErrorString(error), (int)error); - - con->http.error = error; - con->http.status = HTTP_ERROR; - - if (con->http.tls) - { - SSLDisposeContext(con->http.tls); - con->http.tls = NULL; - } - - if (con->http.tls_credentials) - { - CFRelease(con->http.tls_credentials); - con->http.tls_credentials = NULL; - } - - return (0); - } - - cupsdLogMessage(CUPSD_LOG_DEBUG, "Connection from %s now encrypted.", - con->http.hostname); - - if (!SSLCopyPeerCertificates(con->http.tls, &peerCerts) && peerCerts) - { - cupsdLogMessage(CUPSD_LOG_DEBUG, "Received %d peer certificates!", - (int)CFArrayGetCount(peerCerts)); - CFRelease(peerCerts); - } - else - cupsdLogMessage(CUPSD_LOG_DEBUG, "Received NO peer certificates!"); - - return (1); - -# endif /* HAVE_LIBSSL */ -} -#endif /* HAVE_SSL */ - - /* * 'get_file()' - Get a filename and state info. */ @@ -3802,8 +3289,8 @@ get_file(cupsd_client_t *con, /* I - Client connection */ } cupsdLogMessage(CUPSD_LOG_DEBUG2, - "get_file(con=%p(%d), filestats=%p, filename=%p, len=%d) = " - "%s", con, con->http.fd, filestats, filename, len, + "[Client %d] get_file filestats=%p, filename=%p, len=%d, " + "returning \"%s\".", con->http.fd, filestats, filename, len, status ? "(null)" : filename); if (status) @@ -3942,9 +3429,9 @@ is_cgi(cupsd_client_t *con, /* I - Client connection */ if (!type || _cups_strcasecmp(type->super, "application")) { cupsdLogMessage(CUPSD_LOG_DEBUG2, - "is_cgi(con=%p(%d), filename=\"%s\", filestats=%p, " - "type=%s/%s) = 0", con, con->http.fd, filename, filestats, - type ? type->super : "unknown", + "[Client %d] is_cgi filename=\"%s\", filestats=%p, " + "type=%s/%s, returning 0", con->http.fd, filename, + filestats, type ? type->super : "unknown", type ? type->type : "unknown"); return (0); } @@ -3962,9 +3449,9 @@ is_cgi(cupsd_client_t *con, /* I - Client connection */ cupsdSetStringf(&con->options, " %s", options); cupsdLogMessage(CUPSD_LOG_DEBUG2, - "is_cgi(con=%p(%d), filename=\"%s\", filestats=%p, " - "type=%s/%s) = 1", con, con->http.fd, filename, filestats, - type->super, type->type); + "[Client %d] is_cgi filename=\"%s\", filestats=%p, " + "type=%s/%s, returning 1", con->http.fd, filename, + filestats, type->super, type->type); return (1); } #ifdef HAVE_JAVA @@ -3982,9 +3469,9 @@ is_cgi(cupsd_client_t *con, /* I - Client connection */ cupsdSetStringf(&con->options, " %s", filename); cupsdLogMessage(CUPSD_LOG_DEBUG2, - "is_cgi(con=%p(%d), filename=\"%s\", filestats=%p, " - "type=%s/%s) = 1", con, con->http.fd, filename, filestats, - type->super, type->type); + "[Client %d] is_cgi filename=\"%s\", filestats=%p, " + "type=%s/%s, returning 1", con->http.fd, filename, + filestats, type->super, type->type); return (1); } #endif /* HAVE_JAVA */ @@ -4003,9 +3490,9 @@ is_cgi(cupsd_client_t *con, /* I - Client connection */ cupsdSetStringf(&con->options, " %s", filename); cupsdLogMessage(CUPSD_LOG_DEBUG2, - "is_cgi(con=%p(%d), filename=\"%s\", filestats=%p, " - "type=%s/%s) = 1", con, con->http.fd, filename, filestats, - type->super, type->type); + "[Client %d] is_cgi filename=\"%s\", filestats=%p, " + "type=%s/%s, returning 1", con->http.fd, filename, + filestats, type->super, type->type); return (1); } #endif /* HAVE_PERL */ @@ -4024,9 +3511,9 @@ is_cgi(cupsd_client_t *con, /* I - Client connection */ cupsdSetStringf(&con->options, " %s", filename); cupsdLogMessage(CUPSD_LOG_DEBUG2, - "is_cgi(con=%p(%d), filename=\"%s\", filestats=%p, " - "type=%s/%s) = 1", con, con->http.fd, filename, filestats, - type->super, type->type); + "[Client %d] is_cgi filename=\"%s\", filestats=%p, " + "type=%s/%s, returning 1", con->http.fd, filename, + filestats, type->super, type->type); return (1); } #endif /* HAVE_PHP */ @@ -4045,17 +3532,17 @@ is_cgi(cupsd_client_t *con, /* I - Client connection */ cupsdSetStringf(&con->options, " %s", filename); cupsdLogMessage(CUPSD_LOG_DEBUG2, - "is_cgi(con=%p(%d), filename=\"%s\", filestats=%p, " - "type=%s/%s) = 1", con, con->http.fd, filename, filestats, - type->super, type->type); + "[Client %d] is_cgi filename=\"%s\", filestats=%p, " + "type=%s/%s, returning 1", con->http.fd, filename, + filestats, type->super, type->type); return (1); } #endif /* HAVE_PYTHON */ cupsdLogMessage(CUPSD_LOG_DEBUG2, - "is_cgi(con=%p(%d), filename=\"%s\", filestats=%p, " - "type=%s/%s) = 0", con, con->http.fd, filename, filestats, - type->super, type->type); + "[Client %d] is_cgi filename=\"%s\", filestats=%p, " + "type=%s/%s, returning 0", con->http.fd, filename, + filestats, type->super, type->type); return (0); } @@ -4095,475 +3582,6 @@ is_path_absolute(const char *path) /* I - Input path */ } -#ifdef HAVE_SSL -/* - * 'make_certificate()' - Make a self-signed SSL/TLS certificate. - */ - -static int /* O - 1 on success, 0 on failure */ -make_certificate(cupsd_client_t *con) /* I - Client connection */ -{ -#if defined(HAVE_LIBSSL) && defined(HAVE_WAITPID) - int pid, /* Process ID of command */ - status; /* Status of command */ - char command[1024], /* Command */ - *argv[12], /* Command-line arguments */ - *envp[MAX_ENV + 1], /* Environment variables */ - infofile[1024], /* Type-in information for cert */ - seedfile[1024]; /* Random number seed file */ - int envc, /* Number of environment variables */ - bytes; /* Bytes written */ - cups_file_t *fp; /* Seed/info file */ - int infofd; /* Info file descriptor */ - - - /* - * Run the "openssl" command to seed the random number generator and - * generate a self-signed certificate that is good for 10 years: - * - * openssl rand -rand seedfile 1 - * - * openssl req -new -x509 -keyout ServerKey \ - * -out ServerCertificate -days 3650 -nodes - * - * The seeding step is crucial in ensuring that the openssl command - * does not block on systems without sufficient entropy... - */ - - if (!cupsFileFind("openssl", getenv("PATH"), 1, command, sizeof(command))) - { - cupsdLogMessage(CUPSD_LOG_ERROR, - "No SSL certificate and openssl command not found!"); - return (0); - } - - if (access("/dev/urandom", 0)) - { - /* - * If the system doesn't provide /dev/urandom, then any random source - * will probably be blocking-style, so generate some random data to - * use as a seed for the certificate. Note that we have already - * seeded the random number generator in cupsdInitCerts()... - */ - - cupsdLogMessage(CUPSD_LOG_INFO, - "Seeding the random number generator..."); - - /* - * Write the seed file... - */ - - if ((fp = cupsTempFile2(seedfile, sizeof(seedfile))) == NULL) - { - cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to create seed file %s - %s", - seedfile, strerror(errno)); - return (0); - } - - for (bytes = 0; bytes < 262144; bytes ++) - cupsFilePutChar(fp, random()); - - cupsFileClose(fp); - - /* - * Run the openssl command to seed its random number generator... - */ - - argv[0] = "openssl"; - argv[1] = "rand"; - argv[2] = "-rand"; - argv[3] = seedfile; - argv[4] = "1"; - argv[5] = NULL; - - envc = cupsdLoadEnv(envp, MAX_ENV); - envp[envc] = NULL; - - if (!cupsdStartProcess(command, argv, envp, -1, -1, -1, -1, -1, 1, NULL, - NULL, &pid)) - { - unlink(seedfile); - return (0); - } - - while (waitpid(pid, &status, 0) < 0) - if (errno != EINTR) - { - status = 1; - break; - } - - cupsdFinishProcess(pid, command, sizeof(command), NULL); - - /* - * Remove the seed file, as it is no longer needed... - */ - - unlink(seedfile); - - if (status) - { - if (WIFEXITED(status)) - cupsdLogMessage(CUPSD_LOG_ERROR, - "Unable to seed random number generator - " - "the openssl command stopped with status %d!", - WEXITSTATUS(status)); - else - cupsdLogMessage(CUPSD_LOG_ERROR, - "Unable to seed random number generator - " - "the openssl command crashed on signal %d!", - WTERMSIG(status)); - - return (0); - } - } - - /* - * Create a file with the certificate information fields... - * - * Note: This assumes that the default questions are asked by the openssl - * command... - */ - - if ((fp = cupsTempFile2(infofile, sizeof(infofile))) == NULL) - { - cupsdLogMessage(CUPSD_LOG_ERROR, - "Unable to create certificate information file %s - %s", - infofile, strerror(errno)); - return (0); - } - - cupsFilePrintf(fp, ".\n.\n.\n%s\n.\n%s\n%s\n", - ServerName, ServerName, ServerAdmin); - cupsFileClose(fp); - - cupsdLogMessage(CUPSD_LOG_INFO, - "Generating SSL server key and certificate..."); - - argv[0] = "openssl"; - argv[1] = "req"; - argv[2] = "-new"; - argv[3] = "-x509"; - argv[4] = "-keyout"; - argv[5] = ServerKey; - argv[6] = "-out"; - argv[7] = ServerCertificate; - argv[8] = "-days"; - argv[9] = "3650"; - argv[10] = "-nodes"; - argv[11] = NULL; - - cupsdLoadEnv(envp, MAX_ENV); - - infofd = open(infofile, O_RDONLY); - - if (!cupsdStartProcess(command, argv, envp, infofd, -1, -1, -1, -1, 1, NULL, - NULL, &pid)) - { - close(infofd); - unlink(infofile); - return (0); - } - - close(infofd); - unlink(infofile); - - while (waitpid(pid, &status, 0) < 0) - if (errno != EINTR) - { - status = 1; - break; - } - - cupsdFinishProcess(pid, command, sizeof(command), NULL); - - if (status) - { - if (WIFEXITED(status)) - cupsdLogMessage(CUPSD_LOG_ERROR, - "Unable to create SSL server key and certificate - " - "the openssl command stopped with status %d!", - WEXITSTATUS(status)); - else - cupsdLogMessage(CUPSD_LOG_ERROR, - "Unable to create SSL server key and certificate - " - "the openssl command crashed on signal %d!", - WTERMSIG(status)); - } - else - { - cupsdLogMessage(CUPSD_LOG_INFO, "Created SSL server key file \"%s\"...", - ServerKey); - cupsdLogMessage(CUPSD_LOG_INFO, - "Created SSL server certificate file \"%s\"...", - ServerCertificate); - } - - return (!status); - -#elif defined(HAVE_GNUTLS) - gnutls_x509_crt crt; /* Self-signed certificate */ - gnutls_x509_privkey key; /* Encryption key */ - cups_lang_t *language; /* Default language info */ - cups_file_t *fp; /* Key/cert file */ - unsigned char buffer[8192]; /* Buffer for x509 data */ - size_t bytes; /* Number of bytes of data */ - unsigned char serial[4]; /* Serial number buffer */ - time_t curtime; /* Current time */ - int result; /* Result of GNU TLS calls */ - - - /* - * Create the encryption key... - */ - - cupsdLogMessage(CUPSD_LOG_INFO, "Generating SSL server key..."); - - gnutls_x509_privkey_init(&key); - gnutls_x509_privkey_generate(key, GNUTLS_PK_RSA, 2048, 0); - - /* - * Save it... - */ - - bytes = sizeof(buffer); - - if ((result = gnutls_x509_privkey_export(key, GNUTLS_X509_FMT_PEM, - buffer, &bytes)) < 0) - { - cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to export SSL server key - %s", - gnutls_strerror(result)); - gnutls_x509_privkey_deinit(key); - return (0); - } - else if ((fp = cupsFileOpen(ServerKey, "w")) != NULL) - { - cupsFileWrite(fp, (char *)buffer, bytes); - cupsFileClose(fp); - - cupsdLogMessage(CUPSD_LOG_INFO, "Created SSL server key file \"%s\"...", - ServerKey); - } - else - { - cupsdLogMessage(CUPSD_LOG_ERROR, - "Unable to create SSL server key file \"%s\" - %s", - ServerKey, strerror(errno)); - gnutls_x509_privkey_deinit(key); - return (0); - } - - /* - * Create the self-signed certificate... - */ - - cupsdLogMessage(CUPSD_LOG_INFO, "Generating self-signed SSL certificate..."); - - language = cupsLangDefault(); - curtime = time(NULL); - serial[0] = curtime >> 24; - serial[1] = curtime >> 16; - serial[2] = curtime >> 8; - serial[3] = curtime; - - gnutls_x509_crt_init(&crt); - if (strlen(language->language) == 5) - gnutls_x509_crt_set_dn_by_oid(crt, GNUTLS_OID_X520_COUNTRY_NAME, 0, - language->language + 3, 2); - else - gnutls_x509_crt_set_dn_by_oid(crt, GNUTLS_OID_X520_COUNTRY_NAME, 0, - "US", 2); - gnutls_x509_crt_set_dn_by_oid(crt, GNUTLS_OID_X520_COMMON_NAME, 0, - ServerName, strlen(ServerName)); - gnutls_x509_crt_set_dn_by_oid(crt, GNUTLS_OID_X520_ORGANIZATION_NAME, 0, - ServerName, strlen(ServerName)); - gnutls_x509_crt_set_dn_by_oid(crt, GNUTLS_OID_X520_ORGANIZATIONAL_UNIT_NAME, - 0, "Unknown", 7); - gnutls_x509_crt_set_dn_by_oid(crt, GNUTLS_OID_X520_STATE_OR_PROVINCE_NAME, 0, - "Unknown", 7); - gnutls_x509_crt_set_dn_by_oid(crt, GNUTLS_OID_X520_LOCALITY_NAME, 0, - "Unknown", 7); - gnutls_x509_crt_set_dn_by_oid(crt, GNUTLS_OID_PKCS9_EMAIL, 0, - ServerAdmin, strlen(ServerAdmin)); - gnutls_x509_crt_set_key(crt, key); - gnutls_x509_crt_set_serial(crt, serial, sizeof(serial)); - gnutls_x509_crt_set_activation_time(crt, curtime); - gnutls_x509_crt_set_expiration_time(crt, curtime + 10 * 365 * 86400); - gnutls_x509_crt_set_ca_status(crt, 0); - gnutls_x509_crt_set_subject_alternative_name(crt, GNUTLS_SAN_DNSNAME, - ServerName); - gnutls_x509_crt_set_key_purpose_oid(crt, GNUTLS_KP_TLS_WWW_SERVER, 0); - gnutls_x509_crt_set_key_usage(crt, GNUTLS_KEY_KEY_ENCIPHERMENT); - gnutls_x509_crt_set_version(crt, 3); - - bytes = sizeof(buffer); - if (gnutls_x509_crt_get_key_id(crt, 0, buffer, &bytes) >= 0) - gnutls_x509_crt_set_subject_key_id(crt, buffer, bytes); - - gnutls_x509_crt_sign(crt, crt, key); - - /* - * Save it... - */ - - bytes = sizeof(buffer); - if ((result = gnutls_x509_crt_export(crt, GNUTLS_X509_FMT_PEM, - buffer, &bytes)) < 0) - cupsdLogMessage(CUPSD_LOG_ERROR, - "Unable to export SSL server certificate - %s", - gnutls_strerror(result)); - else if ((fp = cupsFileOpen(ServerCertificate, "w")) != NULL) - { - cupsFileWrite(fp, (char *)buffer, bytes); - cupsFileClose(fp); - - cupsdLogMessage(CUPSD_LOG_INFO, - "Created SSL server certificate file \"%s\"...", - ServerCertificate); - } - else - cupsdLogMessage(CUPSD_LOG_ERROR, - "Unable to create SSL server certificate file \"%s\" - %s", - ServerCertificate, strerror(errno)); - - /* - * Cleanup... - */ - - gnutls_x509_crt_deinit(crt); - gnutls_x509_privkey_deinit(key); - - return (1); - -#elif defined(HAVE_CDSASSL) && defined(HAVE_WAITPID) - int pid, /* Process ID of command */ - status; /* Status of command */ - char command[1024], /* Command */ - *argv[4], /* Command-line arguments */ - *envp[MAX_ENV + 1], /* Environment variables */ - keychain[1024], /* Keychain argument */ - infofile[1024], /* Type-in information for cert */ - localname[1024], /* Local hostname */ - *servername; /* Name of server in cert */ - cups_file_t *fp; /* Seed/info file */ - int infofd; /* Info file descriptor */ - - - if (con->servername && isdigit(con->servername[0] & 255) && DNSSDHostName) - { - snprintf(localname, sizeof(localname), "%s.local", DNSSDHostName); - servername = localname; - } - else - servername = con->servername; - - /* - * Run the "certtool" command to generate a self-signed certificate... - */ - - if (!cupsFileFind("certtool", getenv("PATH"), 1, command, sizeof(command))) - { - cupsdLogMessage(CUPSD_LOG_ERROR, - "No SSL certificate and certtool command not found!"); - return (0); - } - - /* - * Create a file with the certificate information fields... - * - * Note: This assumes that the default questions are asked by the certtool - * command... - */ - - if ((fp = cupsTempFile2(infofile, sizeof(infofile))) == NULL) - { - cupsdLogMessage(CUPSD_LOG_ERROR, - "Unable to create certificate information file %s - %s", - infofile, strerror(errno)); - return (0); - } - - cupsFilePrintf(fp, - "%s\n" /* Enter key and certificate label */ - "r\n" /* Generate RSA key pair */ - "2048\n" /* Key size in bits */ - "y\n" /* OK (y = yes) */ - "b\n" /* Usage (b=signing/encryption) */ - "s\n" /* Sign with SHA1 */ - "y\n" /* OK (y = yes) */ - "%s\n" /* Common name */ - "\n" /* Country (default) */ - "\n" /* Organization (default) */ - "\n" /* Organizational unit (default) */ - "\n" /* State/Province (default) */ - "%s\n" /* Email address */ - "y\n", /* OK (y = yes) */ - servername, servername, ServerAdmin); - cupsFileClose(fp); - - cupsdLogMessage(CUPSD_LOG_INFO, - "Generating SSL server key and certificate..."); - - snprintf(keychain, sizeof(keychain), "k=%s", ServerCertificate); - - argv[0] = "certtool"; - argv[1] = "c"; - argv[2] = keychain; - argv[3] = NULL; - - cupsdLoadEnv(envp, MAX_ENV); - - infofd = open(infofile, O_RDONLY); - - if (!cupsdStartProcess(command, argv, envp, infofd, -1, -1, -1, -1, 1, NULL, - NULL, &pid)) - { - close(infofd); - unlink(infofile); - return (0); - } - - close(infofd); - unlink(infofile); - - while (waitpid(pid, &status, 0) < 0) - if (errno != EINTR) - { - status = 1; - break; - } - - cupsdFinishProcess(pid, command, sizeof(command), NULL); - - if (status) - { - if (WIFEXITED(status)) - cupsdLogMessage(CUPSD_LOG_ERROR, - "Unable to create SSL server key and certificate - " - "the certtool command stopped with status %d!", - WEXITSTATUS(status)); - else - cupsdLogMessage(CUPSD_LOG_ERROR, - "Unable to create SSL server key and certificate - " - "the certtool command crashed on signal %d!", - WTERMSIG(status)); - } - else - { - cupsdLogMessage(CUPSD_LOG_INFO, - "Created SSL server certificate file \"%s\"...", - ServerCertificate); - } - - return (!status); - -#else - return (0); -#endif /* HAVE_LIBSSL && HAVE_WAITPID */ -} -#endif /* HAVE_SSL */ - - /* * 'pipe_command()' - Pipe the output of a command to the remote client. */ @@ -4625,9 +3643,9 @@ pipe_command(cupsd_client_t *con, /* I - Client connection */ */ cupsdLogMessage(CUPSD_LOG_DEBUG2, - "pipe_command(con=%p(%d), infile=%d, outfile=%p, " - "command=\"%s\", options=\"%s\", root=%d)", - con, con->http.fd, infile, outfile, command, + "[Client %d] pipe_command infile=%d, outfile=%p, " + "command=\"%s\", options=\"%s\", root=%d", + con->http.fd, infile, outfile, command, options ? options : "(null)", root); argv[0] = command; @@ -5008,9 +4026,19 @@ valid_host(cupsd_client_t *con) /* I - Client connection */ * Check if the hostname is something.local (Bonjour); if so, allow it. */ - if ((end = strrchr(host, '.')) != NULL && - (!_cups_strcasecmp(end, ".local") || !_cups_strncasecmp(end, ".local:", 7) || - !_cups_strcasecmp(end, ".local.") || !_cups_strncasecmp(end, ".local.:", 8))) + if ((end = strrchr(host, '.')) != NULL && end > host && + (!end[1] || end[1] == ':')) + { + /* + * "." on end, work back to second-to-last "."... + */ + for (end --; end > host && *end != '.'; end --); + } + + if (end && (!_cups_strcasecmp(end, ".local") || + !_cups_strncasecmp(end, ".local:", 7) || + !_cups_strcasecmp(end, ".local.") || + !_cups_strncasecmp(end, ".local.:", 8))) return (1); #endif /* HAVE_DNSSD */ @@ -5140,8 +4168,8 @@ write_file(cupsd_client_t *con, /* I - Client connection */ con->file = open(filename, O_RDONLY); cupsdLogMessage(CUPSD_LOG_DEBUG2, - "write_file(con=%p(%d), code=%d, filename=\"%s\" (%d), " - "type=\"%s\", filestats=%p)", con, con->http.fd, + "[Client %d] write_file code=%d, filename=\"%s\" (%d), " + "type=\"%s\", filestats=%p", con->http.fd, code, filename, con->file, type ? type : "(null)", filestats); if (con->file < 0) @@ -5189,8 +4217,8 @@ static void write_pipe(cupsd_client_t *con) /* I - Client connection */ { cupsdLogMessage(CUPSD_LOG_DEBUG2, - "write_pipe(con=%p(%d)) CGI output on fd %d", - con, con->http.fd, con->file); + "[Client %d] write_pipe CGI output on fd %d", + con->http.fd, con->file); con->file_ready = 1; @@ -5200,5 +4228,5 @@ write_pipe(cupsd_client_t *con) /* I - Client connection */ /* - * End of "$Id: client.c 10338 2012-03-07 06:05:39Z mike $". + * End of "$Id: client.c 10455 2012-05-07 22:41:30Z mike $". */ |