-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.
-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
-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"
*/
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__ */
{
(void)prompt;
- if (password)
+ if (password && password_tries < 3)
+ {
+ password_tries ++;
+
return (password);
+ }
else
{
/*
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);
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;
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();
setup_cfLanguage();
- parse_options(options, serial, &location, &g.wait_eof);
+ parse_options(options, serial, sizeof(serial), &location, &g.wait_eof);
if (resource[0] == '/')
resource++;
static void parse_options(const char *options,
char *serial,
+ int serial_size,
UInt32 *location,
Boolean *wait_eof)
{
- char *serialnumber; /* ?serial=<serial> or ?location=<location> */
char optionName[255], /* Name of option */
value[255], /* Value of option */
*ptr; /* Pointer into name or value */
if (!options)
return;
- serialnumber = NULL;
-
while (*options != '\0')
{
/* Get the name... */
}
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);
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'`"
CUPS to use Kerberos authentication and provides helpful links to the MIT
help pages for configuring Kerberos on your systems and network.</P>
+<BLOCKQUOTE><B>Note:</B>
+
+<P>In order to use Kerberos-authenticated shared printers, you <EM>must</EM> be
+running a version of MIT Kerberos with the <TT>krb5_cc_new_unique()</TT>
+function or Heimdal Kerberos. Otherwise, only local Kerberos authentication
+is supported.</P>
+
+</BLOCKQUOTE>
+
<H2 CLASS="title"><A NAME="KRB5">Configuring Kerberos on Your System</A></H2>
<H2 CLASS="title"><A NAME="IMPLEMENT">Implementation Information</A></H2>
<P>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.</P>
+"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.</P>
<P>After getting a user's Kerberos credentials, CUPS strips the "@KDC"
portion of the username so that it can check the group membership locally,
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)
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;
}
/* 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);
{
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
{ "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 },
{ "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 }
};
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;
{
cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to create new credentials (%d/%s)",
error, strerror(errno));
+ job->ccache = NULL;
return;
}
cupsdLogGSSMessage(CUPSD_LOG_ERROR, major_status, minor_status,
"Unable to import client credentials cache");
krb5_cc_destroy(KerberosContext, job->ccache);
+ job->ccache = NULL;
return;
}
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 */
/*
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)
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...");
lis;
lis = (cupsd_listener_t *)cupsArrayNext(Listeners))
cupsdRemoveSelect(lis->fd);
+
+ ListeningPaused = time(NULL) + 30;
}
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...");
lis;
lis = (cupsd_listener_t *)cupsArrayNext(Listeners))
cupsdAddSelect(lis->fd, (cupsd_selfunc_t)cupsdAcceptClient, NULL, lis);
+
+ ListeningPaused = 0;
}
}
#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...
*/
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...
*/
"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)
{
#include <cups/string.h>
#include <stdlib.h>
#include <sys/stat.h>
+#include <sys/wait.h>
#include <errno.h>
#include <signal.h>
#include <unistd.h>