From 76cd9e37aaf496aab887d499f4917b60e91d6d25 Mon Sep 17 00:00:00 2001
From: msweet
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.
+ +
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