From 76cd9e37aaf496aab887d499f4917b60e91d6d25 Mon Sep 17 00:00:00 2001 From: msweet Date: Mon, 13 Aug 2007 21:04:11 +0000 Subject: Merge changes from r6781 to r6792 (CUPS 1.3.0) git-svn-id: svn+ssh://src.apple.com/svn/cups/easysw/current@405 a1ca3aef-8c08-0410-bb20-df032aa958be --- CHANGES.txt | 7 ++++++- INSTALL.txt | 2 +- README.txt | 2 +- backend/ipp.c | 7 ++++++- backend/socket.c | 9 +++++++++ backend/usb-darwin.c | 11 ++++------- config-scripts/cups-common.m4 | 2 +- doc/help/kerberos.html | 14 ++++++++++++-- scheduler/auth.c | 10 +++++++++- scheduler/client.c | 4 ++++ scheduler/client.h | 2 ++ scheduler/conf.c | 29 ++++++++++++++++++++++------- scheduler/ipp.c | 2 ++ scheduler/job.c | 30 ++++++++++++++++-------------- scheduler/listen.c | 12 +++++++++--- scheduler/main.c | 23 +++++++++++++++++++++++ scheduler/process.c | 7 +++++++ scheduler/testlpd.c | 1 + 18 files changed, 135 insertions(+), 39 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index 9d71580cd..68404a28a 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,9 +1,14 @@ -CHANGES.txt - 2007-08-08 +CHANGES.txt - 2007-08-13 ------------------------ CHANGES IN CUPS V1.3.0 + - The scheduler did not handle out-of-file conditions + gracefully when accepting new connections, leading to + heavy CPU usage. + - The scheduler did not detect ServerBin misconfigurations + (STR #2470) - "AuthType Default" did not work as expected when the "DefaultAuthType foo" line appeared after it in the cupsd.conf file. diff --git a/INSTALL.txt b/INSTALL.txt index 92416a182..5732830f3 100644 --- a/INSTALL.txt +++ b/INSTALL.txt @@ -1,4 +1,4 @@ -INSTALL - CUPS v1.3.0 - 2007-08-03 +INSTALL - CUPS v1.3.0 - 2007-08-13 ---------------------------------- This file describes how to compile and install CUPS from source diff --git a/README.txt b/README.txt index 37fc68451..48fee5a99 100644 --- a/README.txt +++ b/README.txt @@ -1,4 +1,4 @@ -README - CUPS v1.3.0 - 2007-08-03 +README - CUPS v1.3.0 - 2007-08-13 --------------------------------- Looking for compile instructions? Read the file "INSTALL.txt" diff --git a/backend/ipp.c b/backend/ipp.c index df55c5cbb..ed82f4d33 100644 --- a/backend/ipp.c +++ b/backend/ipp.c @@ -51,6 +51,7 @@ */ static char *password = NULL; /* Password for device URI */ +static int password_tries = 0; /* Password tries */ #ifdef __APPLE__ static char pstmpname[1024] = ""; /* Temporary PostScript file name */ #endif /* __APPLE__ */ @@ -1372,8 +1373,12 @@ password_cb(const char *prompt) /* I - Prompt (not used) */ { (void)prompt; - if (password) + if (password && password_tries < 3) + { + password_tries ++; + return (password); + } else { /* diff --git a/backend/socket.c b/backend/socket.c index 68f9a29c5..06790d96c 100644 --- a/backend/socket.c +++ b/backend/socket.c @@ -432,6 +432,7 @@ side_cb(int print_fd, /* I - Print file */ cups_sc_status_t status; /* Request/response status */ char data[2048]; /* Request/response data */ int datalen; /* Request/response data size */ + const char *device_id; /* 1284DEVICEID env var */ datalen = sizeof(data); @@ -462,6 +463,14 @@ side_cb(int print_fd, /* I - Print file */ datalen = 1; break; + case CUPS_SC_CMD_GET_DEVICE_ID : + if ((device_id = getenv("1284DEVICEID")) != NULL) + { + strlcpy(data, device_id, sizeof(data)); + datalen = (int)strlen(data); + break; + } + default : status = CUPS_SC_STATUS_NOT_IMPLEMENTED; datalen = 0; diff --git a/backend/usb-darwin.c b/backend/usb-darwin.c index e71965d8c..dc628fea3 100644 --- a/backend/usb-darwin.c +++ b/backend/usb-darwin.c @@ -267,7 +267,7 @@ static void copy_devicestring(io_service_t usbInterface, CFStringRef *deviceID, static void device_added(void *userdata, io_iterator_t iterator); static void get_device_id(cups_sc_status_t *status, char *data, int *datalen); static void iterate_printers(iterator_callback_t callBack, void *userdata); -static void parse_options(const char *options, char *serial, UInt32 *location, Boolean *wait_eof); +static void parse_options(const char *options, char *serial, int serial_size, UInt32 *location, Boolean *wait_eof); static void release_deviceinfo(CFStringRef *make, CFStringRef *model, CFStringRef *serial); static void setup_cfLanguage(void); static void soft_reset(); @@ -329,7 +329,7 @@ print_device(const char *uri, /* I - Device URI */ setup_cfLanguage(); - parse_options(options, serial, &location, &g.wait_eof); + parse_options(options, serial, sizeof(serial), &location, &g.wait_eof); if (resource[0] == '/') resource++; @@ -1546,10 +1546,10 @@ CFStringRef cfstr_create_trim(const char *cstr) static void parse_options(const char *options, char *serial, + int serial_size, UInt32 *location, Boolean *wait_eof) { - char *serialnumber; /* ?serial= or ?location= */ char optionName[255], /* Name of option */ value[255], /* Value of option */ *ptr; /* Pointer into name or value */ @@ -1562,8 +1562,6 @@ static void parse_options(const char *options, if (!options) return; - serialnumber = NULL; - while (*options != '\0') { /* Get the name... */ @@ -1607,8 +1605,7 @@ static void parse_options(const char *options, } else if (strcasecmp(optionName, "serial") == 0) { - strcpy(serial, value); - serialnumber = serial; + strlcpy(serial, value, serial_size); } else if (strcasecmp(optionName, "location") == 0 && location) *location = strtol(value, NULL, 16); diff --git a/config-scripts/cups-common.m4 b/config-scripts/cups-common.m4 index 88c153200..27835e87c 100644 --- a/config-scripts/cups-common.m4 +++ b/config-scripts/cups-common.m4 @@ -20,7 +20,7 @@ dnl Set the name of the config header file... AC_CONFIG_HEADER(config.h) dnl Versio number information... -CUPS_VERSION="1.3rc2" +CUPS_VERSION="1.3.0" CUPS_REVISION="" #if test -z "$CUPS_REVISION" -a -d .svn; then # CUPS_REVISION="-r`svnversion . | awk -F: '{print $NF}' | sed -e '1,$s/[[a-zA-Z]]*//g'`" diff --git a/doc/help/kerberos.html b/doc/help/kerberos.html index a7b0e5ed0..83c5fe8f0 100644 --- a/doc/help/kerberos.html +++ b/doc/help/kerberos.html @@ -11,6 +11,15 @@ to a remote authenticated queue. This document describes how to configure CUPS to use Kerberos authentication and provides helpful links to the MIT help pages for configuring Kerberos on your systems and network.

+
Note: + +

In order to use Kerberos-authenticated shared printers, you must be +running a version of MIT Kerberos with the krb5_cc_new_unique() +function or Heimdal Kerberos. Otherwise, only local Kerberos authentication +is supported.

+ +
+

Configuring Kerberos on Your System

@@ -126,8 +135,9 @@ lines to the policies you want to protect with authentication, for example:

Implementation Information

CUPS implements Kerberos over HTTP using GSS API and the service name -"ipp". Delegation of credentials (needed for remote printers with -authentication) is only supported when using a single KDC on your network.

+"ipp". Delegation of credentials, which is needed when printing to a +remote/shared printer with Kerberos authentication, is currently only supported +when using a single KDC on your network.

After getting a user's Kerberos credentials, CUPS strips the "@KDC" portion of the username so that it can check the group membership locally, diff --git a/scheduler/auth.c b/scheduler/auth.c index 12ea711c0..03f875be6 100644 --- a/scheduler/auth.c +++ b/scheduler/auth.c @@ -1026,11 +1026,19 @@ cupsdAuthorize(cupsd_client_t *con) /* I - Client connection */ if (context != GSS_C_NO_CONTEXT) gss_delete_sec_context(&minor_status, &context, GSS_C_NO_BUFFER); + + gss_release_cred(&minor_status, &server_creds); return; } /* - * Get the username associated with the credentials... + * Release our credentials... + */ + + gss_release_cred(&minor_status, &server_creds); + + /* + * Get the username associated with the client's credentials... */ if (!con->gss_delegated_cred) diff --git a/scheduler/client.c b/scheduler/client.c index dfe1546de..f8316a79e 100644 --- a/scheduler/client.c +++ b/scheduler/client.c @@ -161,9 +161,13 @@ cupsdAcceptClient(cupsd_listener_t *lis)/* I - Listener socket */ if ((con->http.fd = accept(lis->fd, (struct sockaddr *)con->http.hostaddr, &addrlen)) < 0) { + if (errno == ENFILE || errno == EMFILE) + cupsdPauseListening(); + cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to accept client connection - %s.", strerror(errno)); free(con); + return; } diff --git a/scheduler/client.h b/scheduler/client.h index d439276db..f3c0f3a32 100644 --- a/scheduler/client.h +++ b/scheduler/client.h @@ -90,6 +90,8 @@ VAR http_encryption_t LocalEncryption VALUE(HTTP_ENCRYPT_IF_REQUESTED); /* Local port encryption to use */ VAR cups_array_t *Listeners VALUE(NULL); /* Listening sockets */ +VAR time_t ListeningPaused VALUE(0); + /* Time when listening was paused */ VAR cups_array_t *Clients VALUE(NULL); /* HTTP clients */ VAR http_addrlist_t *ServerAddrs VALUE(NULL); diff --git a/scheduler/conf.c b/scheduler/conf.c index 9a2188b62..26d6037bf 100644 --- a/scheduler/conf.c +++ b/scheduler/conf.c @@ -56,7 +56,8 @@ typedef enum { CUPSD_VARTYPE_INTEGER, /* Integer option */ CUPSD_VARTYPE_STRING, /* String option */ - CUPSD_VARTYPE_BOOLEAN /* Boolean option */ + CUPSD_VARTYPE_BOOLEAN, /* Boolean option */ + CUPSD_VARTYPE_PATHNAME /* File/directory name option */ } cupsd_vartype_t; typedef struct @@ -81,7 +82,7 @@ static cupsd_var_t variables[] = { "BrowseInterval", &BrowseInterval, CUPSD_VARTYPE_INTEGER }, #ifdef HAVE_LDAP { "BrowseLDAPBindDN", &BrowseLDAPBindDN, CUPSD_VARTYPE_STRING }, - { "BrowseLDAPCACertFile", &BrowseLDAPCACertFile, CUPSD_VARTYPE_STRING }, + { "BrowseLDAPCACertFile", &BrowseLDAPCACertFile, CUPSD_VARTYPE_PATHNAME }, { "BrowseLDAPDN", &BrowseLDAPDN, CUPSD_VARTYPE_STRING }, { "BrowseLDAPPassword", &BrowseLDAPPassword, CUPSD_VARTYPE_STRING }, { "BrowseLDAPServer", &BrowseLDAPServer, CUPSD_VARTYPE_STRING }, @@ -152,20 +153,20 @@ static cupsd_var_t variables[] = { "RIPCache", &RIPCache, CUPSD_VARTYPE_STRING }, { "RootCertDuration", &RootCertDuration, CUPSD_VARTYPE_INTEGER }, { "ServerAdmin", &ServerAdmin, CUPSD_VARTYPE_STRING }, - { "ServerBin", &ServerBin, CUPSD_VARTYPE_STRING }, + { "ServerBin", &ServerBin, CUPSD_VARTYPE_PATHNAME }, #ifdef HAVE_SSL - { "ServerCertificate", &ServerCertificate, CUPSD_VARTYPE_STRING }, + { "ServerCertificate", &ServerCertificate, CUPSD_VARTYPE_PATHNAME }, # if defined(HAVE_LIBSSL) || defined(HAVE_GNUTLS) - { "ServerKey", &ServerKey, CUPSD_VARTYPE_STRING }, + { "ServerKey", &ServerKey, CUPSD_VARTYPE_PATHNAME }, # endif /* HAVE_LIBSSL || HAVE_GNUTLS */ #endif /* HAVE_SSL */ { "ServerName", &ServerName, CUPSD_VARTYPE_STRING }, - { "ServerRoot", &ServerRoot, CUPSD_VARTYPE_STRING }, + { "ServerRoot", &ServerRoot, CUPSD_VARTYPE_PATHNAME }, { "StateDir", &StateDir, CUPSD_VARTYPE_STRING }, #ifdef HAVE_AUTHORIZATION_H { "SystemGroupAuthKey", &SystemGroupAuthKey, CUPSD_VARTYPE_STRING }, #endif /* HAVE_AUTHORIZATION_H */ - { "TempDir", &TempDir, CUPSD_VARTYPE_STRING }, + { "TempDir", &TempDir, CUPSD_VARTYPE_PATHNAME }, { "Timeout", &Timeout, CUPSD_VARTYPE_INTEGER }, { "UseNetworkDefault", &UseNetworkDefault, CUPSD_VARTYPE_BOOLEAN } }; @@ -3076,6 +3077,20 @@ read_configuration(cups_file_t *fp) /* I - File to read from */ value, linenum); break; + case CUPSD_VARTYPE_PATHNAME : + if (value[0] == '/') + strlcpy(temp, value, sizeof(temp)); + else + snprintf(temp, sizeof(temp), "%s/%s", ServerRoot, value); + + if (access(temp, 0)) + { + cupsdLogMessage(CUPSD_LOG_ERROR, + "File or directory for \"%s %s\" on line %d " + "does not exist!", line, value, linenum); + break; + } + case CUPSD_VARTYPE_STRING : cupsdSetString((char **)var->ptr, value); break; diff --git a/scheduler/ipp.c b/scheduler/ipp.c index 04bb9d0fe..fd8c797db 100644 --- a/scheduler/ipp.c +++ b/scheduler/ipp.c @@ -8299,6 +8299,7 @@ save_krb5_creds(cupsd_client_t *con, /* I - Client connection */ { cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to create new credentials (%d/%s)", error, strerror(errno)); + job->ccache = NULL; return; } @@ -8314,6 +8315,7 @@ save_krb5_creds(cupsd_client_t *con, /* I - Client connection */ cupsdLogGSSMessage(CUPSD_LOG_ERROR, major_status, minor_status, "Unable to import client credentials cache"); krb5_cc_destroy(KerberosContext, job->ccache); + job->ccache = NULL; return; } diff --git a/scheduler/job.c b/scheduler/job.c index 407e752aa..ed1982c9c 100644 --- a/scheduler/job.c +++ b/scheduler/job.c @@ -230,16 +230,17 @@ cupsdCancelJob(cupsd_job_t *job, /* I - Job to cancel */ cupsdClearString(&job->auth_password); #ifdef HAVE_GSSAPI - if (job->ccname) - { - /* - * Destroy the credential cache and clear the KRB5CCNAME env var string. - */ + /* + * Destroy the credential cache and clear the KRB5CCNAME env var string. + */ + if (job->ccache) + { krb5_cc_destroy(KerberosContext, job->ccache); - - cupsdClearString(&job->ccname); + job->ccache = NULL; } + + cupsdClearString(&job->ccname); #endif /* HAVE_GSSAPI */ /* @@ -1803,16 +1804,17 @@ free_job(cupsd_job_t *job) /* I - Job */ cupsdClearString(&job->auth_domain); cupsdClearString(&job->auth_password); #ifdef HAVE_GSSAPI - if (job->ccname) - { - /* - * Destroy the credential cache and clear the KRB5CCNAME env var string. - */ + /* + * Destroy the credential cache and clear the KRB5CCNAME env var string. + */ + if (job->ccache) + { krb5_cc_destroy(KerberosContext, job->ccache); - - cupsdClearString(&job->ccname); + job->ccache = NULL; } + + cupsdClearString(&job->ccname); #endif /* HAVE_GSSAPI */ if (job->num_files > 0) diff --git a/scheduler/listen.c b/scheduler/listen.c index 6e938a65c..0a3158db4 100644 --- a/scheduler/listen.c +++ b/scheduler/listen.c @@ -75,6 +75,10 @@ cupsdPauseListening(void) if (cupsArrayCount(Clients) == MaxClients) cupsdLogMessage(CUPSD_LOG_WARN, "Max clients reached, holding new connections..."); + else if (errno == ENFILE || errno == EMFILE) + cupsdLogMessage(CUPSD_LOG_WARN, + "Too many open files, holding new connections for " + "30 seconds..."); cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdPauseListening: Clearing input bits..."); @@ -82,6 +86,8 @@ cupsdPauseListening(void) lis; lis = (cupsd_listener_t *)cupsArrayNext(Listeners)) cupsdRemoveSelect(lis->fd); + + ListeningPaused = time(NULL) + 30; } @@ -98,9 +104,7 @@ cupsdResumeListening(void) if (cupsArrayCount(Listeners) < 1) return; - if (cupsArrayCount(Clients) >= (MaxClients - 1)) - cupsdLogMessage(CUPSD_LOG_WARN, "Resuming new connection processing..."); - + cupsdLogMessage(CUPSD_LOG_INFO, "Resuming new connection processing..."); cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdResumeListening: Setting input bits..."); @@ -108,6 +112,8 @@ cupsdResumeListening(void) lis; lis = (cupsd_listener_t *)cupsArrayNext(Listeners)) cupsdAddSelect(lis->fd, (cupsd_selfunc_t)cupsdAcceptClient, NULL, lis); + + ListeningPaused = 0; } diff --git a/scheduler/main.c b/scheduler/main.c index aee1b1111..f9f1ba9b1 100644 --- a/scheduler/main.c +++ b/scheduler/main.c @@ -801,6 +801,14 @@ main(int argc, /* I - Number of command-line args */ } #endif /* HAVE_LAUNCHD */ + /* + * Resume listening for new connections as needed... + */ + + if (ListeningPaused && ListeningPaused <= current_time && + cupsArrayCount(Clients) < MaxClients) + cupsdResumeListening(); + /* * Expire subscriptions and unload completed jobs as needed... */ @@ -1707,6 +1715,21 @@ select_timeout(int fds) /* I - Number of descriptors returned */ timeout = now + 86400; /* 86400 == 1 day */ why = "do nothing"; + /* + * Check whether we are accepting new connections... + */ + + if (ListeningPaused > 0 && cupsArrayCount(Clients) < MaxClients && + ListeningPaused < timeout) + { + if (ListeningPaused <= now) + timeout = now; + else + timeout = ListeningPaused; + + why = "resume listening"; + } + /* * Check the activity and close old clients... */ diff --git a/scheduler/process.c b/scheduler/process.c index 6ea6e150a..5e0933f15 100644 --- a/scheduler/process.c +++ b/scheduler/process.c @@ -131,6 +131,13 @@ cupsdStartProcess( "cupsdStartProcess(\"%s\", %p, %p, %d, %d, %d)", command, argv, envp, infd, outfd, errfd); + if (access(command, X_OK)) + { + cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to execute %s: %s", command, + strerror(errno)); + return (0); + } + #if defined(__APPLE__) if (envp) { diff --git a/scheduler/testlpd.c b/scheduler/testlpd.c index 7cf094f4b..fbc99e10c 100644 --- a/scheduler/testlpd.c +++ b/scheduler/testlpd.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include -- cgit v1.2.1