Package: cups Version: 1.5.3-5+deb7u6 Tags: patch --
Hi, would it be possible to review and maybe have this patch in wheezy ? (maybe also jessie as all cups < 2.1b1 are concerned). It has been applied in Redhat/Centos and Ubuntu in greater version (1.6.3 and 1.7.2). I disables SSLv3 by default but gives the possibility with AllowSSL3 to turns SSLv3 back on and also AllowRC4 turns on just the RC4 cyphers. I tried to backport it to 1.5.3, so double checking would be nice. I tried it and it seems to work (also options to re-enable SSL3/RC4 cyphers). For Jessie, it seems that the patch from Ubuntu cups-1.7.2-0ubuntu1.7 applies with some refresh. https://bugs.launchpad.net/ubuntu/+source/gnutls26/+bug/1510163 https://bugzilla.redhat.com/show_bug.cgi?id=1161172 https://www.cups.org/str.php?L4476 F.
Description: Disable SSLv3 with option to turn back on. This disables SSLv3 in cups. It also provided 2 configuration options to renable by specifying SSLOptions in the cupsd.conf file. AllowSSL3 turns SSLv3 back on and AllowRC4 turns on just the RC4 cypers. This patch was originally taken from https://git.centos.org/raw/rpms!cups/68a3ed04baba43d09f5cdd7557dda2480070feb0/SOURCES!cups-str4476.patch and backported to cups 1.5.3. Origin: vendor, https://bugzilla.redhat.com/show_bug.cgi?id=1161172 Bug: https://www.cups.org/str.php?L4476 Bug-Ubuntu: https://launchpad.net/bugs/1505328 --- This patch header follows DEP-3: http://dep.debian.net/deps/dep3/ --- a/cups/http.c +++ b/cups/http.c @@ -182,6 +182,8 @@ * Local globals... */ +static int tls_options = 0; /* Options for TLS connections */ + static const char * const http_fields[] = { "Accept-Language", @@ -3620,7 +3622,10 @@ if (http->encryption == HTTP_ENCRYPT_REQUIRED && !http->tls) { httpSetField(http, HTTP_FIELD_CONNECTION, "Upgrade"); - httpSetField(http, HTTP_FIELD_UPGRADE, "TLS/1.0,SSL/2.0,SSL/3.0"); + if (tls_options & _HTTP_TLS_ALLOW_SSL3) + httpSetField(http, HTTP_FIELD_UPGRADE, "TLS/1.1,TLS/1.0,SSL/3.0"); + else + httpSetField(http, HTTP_FIELD_UPGRADE, "TLS/1.1,TLS/1.0"); } #endif /* HAVE_SSL */ @@ -3906,6 +3911,10 @@ context = SSL_CTX_new(SSLv23_client_method()); SSL_CTX_set_options(context, SSL_OP_NO_SSLv2); /* Only use SSLv3 or TLS */ + if (!(tls_options & _HTTP_TLS_ALLOW_SSL3)) + SSL_CTX_set_options(context, SSL_OP_NO_SSLv3); /* Don't use SSLv3 */ + if (!(tls_options & _HTTP_TLS_ALLOW_RC4)) + SSL_CTX_set_cipher_list(context, "DEFAULT:-RC4"); bio = BIO_new(_httpBIOMethods()); BIO_ctrl(bio, BIO_C_SET_FILE_PTR, 0, (char *)http); @@ -3965,7 +3974,16 @@ gnutls_certificate_allocate_credentials(credentials); gnutls_init(&http->tls, GNUTLS_CLIENT); - gnutls_set_default_priority(http->tls); + if (!tls_options) + gnutls_priority_set_direct(http->tls, "NORMAL:-ARCFOUR-128:-VERS-SSL3.0", NULL); + else if ((tls_options & _HTTP_TLS_ALLOW_SSL3) && + (tls_options & _HTTP_TLS_ALLOW_RC4)) + gnutls_priority_set_direct(http->tls, "NORMAL", NULL); + else if (tls_options & _HTTP_TLS_ALLOW_SSL3) + gnutls_priority_set_direct(http->tls, "NORMAL:-ARCFOUR-128", NULL); + else + gnutls_priority_set_direct(http->tls, "NORMAL:-VERS-SSL3.0", NULL); + gnutls_server_name_set(http->tls, GNUTLS_NAME_DNS, hostname, strlen(hostname)); gnutls_credentials_set(http->tls, GNUTLS_CRD_CERTIFICATE, *credentials); @@ -4378,7 +4396,10 @@ httpClearFields(http); httpSetField(http, HTTP_FIELD_CONNECTION, "upgrade"); - httpSetField(http, HTTP_FIELD_UPGRADE, "TLS/1.2, TLS/1.1, TLS/1.0, SSL/3.0"); + if (tls_options & _HTTP_TLS_ALLOW_SSL3) + httpSetField(http, HTTP_FIELD_UPGRADE, "TLS/1.2, TLS/1.1, TLS/1.0, SSL/3.0"); + else + httpSetField(http, HTTP_FIELD_UPGRADE, "TLS/1.2, TLS/1.1, TLS/1.0"); if ((ret = httpOptions(http, "*")) == 0) { @@ -4704,6 +4725,16 @@ } #endif /* HAVE_SSL */ +/* + * '_httpTLSSetOptions()' - Set TLS/SSL options. + */ + +void +_httpTLSSetOptions(int options) +{ + tls_options = options; +} + /* * End of "$Id: http.c 10450 2012-05-04 22:52:56Z mike $". --- a/cups/http-private.h +++ b/cups/http-private.h @@ -136,6 +136,10 @@ # endif /* HAVE_GETIFADDRS */ # endif /* !WIN32 */ +/* care - these should be the same values as the CUPSD_SSL_* equivalents */ +#define _HTTP_TLS_ALLOW_RC4 2 +#define _HTTP_TLS_ALLOW_SSL3 4 + /* * C++ magic... @@ -392,6 +396,8 @@ extern int _httpUpdate(http_t *http, http_status_t *status); extern int _httpWait(http_t *http, int msec, int usessl); +extern void _httpTLSSetOptions(int options); + /* * C++ magic... --- a/cups/usersys.c +++ b/cups/usersys.c @@ -63,7 +63,8 @@ #endif /* HAVE_GSSAPI */ const char *cups_anyroot, const char *cups_expiredroot, - const char *cups_expiredcerts); + const char *cups_expiredcerts, + int ssl_options); /* @@ -248,6 +249,9 @@ _cups_globals_t *cg = _cupsGlobals(); /* Pointer to library globals */ + if (cg->encryption == (http_encryption_t)-1) + _cupsSetDefaults(); + cg->encryption = e; if (cg->http) @@ -575,7 +579,36 @@ if (cg->encryption == (http_encryption_t)-1 || !cg->server[0] || !cg->ipp_port) { + /* + * Look for CUPS_SERVERROOT/client.conf... + */ + + snprintf(filename, sizeof(filename), "%s/client.conf", + cg->cups_serverroot); + fp = cupsFileOpen(filename, "r"); + + /* + * Read the configuration file and apply any environment variables; both + * functions handle NULL cups_file_t pointers... + */ + + cups_read_client_conf(fp, cg, cups_encryption, cups_server, +#ifdef HAVE_GSSAPI + cups_gssservicename, +#endif /* HAVE_GSSAPI */ + cups_anyroot, cups_expiredroot, + cups_expiredcerts, 1); + + /* + * Then user defaults, if it is safe to do so... + */ + +#ifdef HAVE_GETEUID + if ((geteuid() == getuid() || !getuid()) && getegid() == getgid() && + (home = getenv("HOME")) != NULL) +#else if ((home = getenv("HOME")) != NULL) +#endif { /* * Look for ~/.cups/client.conf... @@ -583,33 +616,19 @@ snprintf(filename, sizeof(filename), "%s/.cups/client.conf", home); fp = cupsFileOpen(filename, "r"); - } - else - fp = NULL; - - if (!fp) - { /* - * Look for CUPS_SERVERROOT/client.conf... + * Read the configuration file and apply any environment variables; both + * functions handle NULL cups_file_t pointers... */ - snprintf(filename, sizeof(filename), "%s/client.conf", - cg->cups_serverroot); - fp = cupsFileOpen(filename, "r"); - } - - /* - * Read the configuration file and apply any environment variables; both - * functions handle NULL cups_file_t pointers... - */ - - cups_read_client_conf(fp, cg, cups_encryption, cups_server, + cups_read_client_conf(fp, cg, cups_encryption, cups_server, #ifdef HAVE_GSSAPI - cups_gssservicename, + cups_gssservicename, #endif /* HAVE_GSSAPI */ - cups_anyroot, cups_expiredroot, - cups_expiredcerts); - cupsFileClose(fp); + cups_anyroot, cups_expiredroot, + cups_expiredcerts, 0); + cupsFileClose(fp); + } } } @@ -630,7 +649,8 @@ #endif /* HAVE_GSSAPI */ const char *cups_anyroot, /* I - CUPS_ANYROOT env var */ const char *cups_expiredroot, /* I - CUPS_EXPIREDROOT env var */ - const char *cups_expiredcerts) /* I - CUPS_EXPIREDCERTS env var */ + const char *cups_expiredcerts, /* I - CUPS_EXPIREDCERTS env var */ + int ssl_options) /* I - Allow setting of SSLOptions? */ { int linenum; /* Current line number */ char line[1024], /* Line from file */ @@ -697,6 +717,43 @@ cups_gssservicename = gss_service_name; } #endif /* HAVE_GSSAPI */ + else if (ssl_options && !_cups_strcasecmp(line, "SSLOptions") && value) + { + /* + * SSLOptions [AllowRC4] [AllowSSL3] [None] + */ + + int options = 0; /* SSL/TLS options */ + char *start, /* Start of option */ + *end; /* End of option */ + + for (start = value; *start; start = end) + { + /* + * Find end of keyword... + */ + + end = start; + while (*end && !_cups_isspace(*end)) + end++; + + if (*end) + *end++ = '\0'; + + /* + * Compare... + */ + + if (!_cups_strcasecmp(start, "AllowRC4")) + options |= _HTTP_TLS_ALLOW_RC4; + else if (!_cups_strcasecmp(start, "AllowSSL3")) + options |= _HTTP_TLS_ALLOW_SSL3; + else if (!_cups_strcasecmp(start, "None")) + options = 0; + } + + _httpTLSSetOptions(options); + } } /* --- a/doc/help/ref-cupsd-conf.html.in +++ b/doc/help/ref-cupsd-conf.html.in @@ -2459,23 +2459,23 @@ variable that should be passed to child processes.</P> -<H2 CLASS="title"><A NAME="SSLListen">SSLListen</A></H2> +<H2 CLASS="title"><A NAME="SSLOptions">SSLOptions</A></H2> <H3>Examples</H3> <PRE CLASS="command"> -SSLListen 127.0.0.1:443 -SSLListen 192.0.2.1:443 +SSLOptions 127.0.0.1:443 +SSLOptions 192.0.2.1:443 </PRE> <H3>Description</H3> -<P>The <CODE>SSLListen</CODE> directive specifies a network +<P>The <CODE>SSLOptions</CODE> directive specifies a network address and port to listen for secure connections. Multiple -<CODE>SSLListen</CODE> directives can be provided to listen on +<CODE>SSLOptions</CODE> directives can be provided to listen on multiple addresses.</P> -<P>The <CODE>SSLListen</CODE> directive is similar to the <A +<P>The <CODE>SSLOptions</CODE> directive is similar to the <A HREF="#SSLPort"><CODE>SSLPort</CODE></A> directive but allows you to restrict access to specific interfaces or networks.</P> @@ -2487,15 +2487,22 @@ <PRE CLASS="command"> SSLOptions None SSLOptions NoEmptyFragments +SSLOptions AllowSSL3 +SSLOptions AllowRC4 </PRE> <H3>Description</H3> <P>The <CODE>SSLOptions</CODE> directive specifies additional SSL/TLS -protocol options to use for encrypted connected. Currently only two -options are supported - <code>None</code> (the default) for the most -secure mode and <code>NoEmptyFragments</code> to allow CUPS to work with -Microsoft Windows with the FIPS conformance mode enabled.</p> +protocol options to use for encrypted connected. By default, CUPS only +supports encryption using TLS v1.0 or higher using known secure cipher +suites. The <code>NoEmptyFragments</code> option allows CUPS to work +with Microsoft Windows with the FIPS conformance mode +enabled. The <code>AllowRC4</code> option enables the 128-bit RC4 +cipher suites, which are required for some older clients that do not +implement newer ones. The <code>AllowSSL3</code> option enables SSL +v3.0, which is required for some older clients that do not support TLS +v1.0.</p> <H2 CLASS="title"><A NAME="SSLPort">SSLPort</A></H2> --- a/man/cupsd.conf.man.in +++ b/man/cupsd.conf.man.in @@ -585,9 +585,16 @@ .TP 5 SSLOptions None .TP 5 -SSLOptions NoEmptyFragments +SSLOptions \fR[\fINoEmptyFragments\fR] [\fIAllowRC4\fR] [\fIAllowSSL3\fR] .br -Sets SSL/TLS protocol options for encrypted connections. +Sets SSL/TLS protocol options for encrypted connections. By default, +CUPS only supports encryption using TLS v1.0 or higher using known +secure cipher suites. The \fINoEmptyFragments\fR option allows CUPS to +work with Microsoft Windows with the FIPS conformance mode +enabled. The \fIAllowRC4\fR option enables the 128-bit RC4 cipher +suites, which are required for some older clients that do not +implement newer ones. The \fIAllowSSL3\fR option enables SSL v3.0, +which is required for some older clients that do not support TLS v1.0. .TP 5 SSLPort .br --- a/scheduler/conf.c +++ b/scheduler/conf.c @@ -3654,17 +3654,54 @@ else if (!_cups_strcasecmp(line, "SSLOptions")) { /* + * SSLOptions [AllowRC4] [AllowSSL3] [NoEmptyFragments] [None] + */ + + int options = 0; /* SSL/TLS options */ + + /* * SSLOptions options */ - if (!value || !_cups_strcasecmp(value, "none")) - SSLOptions = CUPSD_SSL_NONE; - else if (!_cups_strcasecmp(value, "noemptyfragments")) - SSLOptions = CUPSD_SSL_NOEMPTY; - else - cupsdLogMessage(CUPSD_LOG_ERROR, - "Unknown value \"%s\" for SSLOptions directive on " - "line %d.", value, linenum); + if (value) + { + char *start, /* Start of option */ + *end; /* End of option */ + + for (start = value; *start; start = end) + { + /* + * Find end of keyword... + */ + + end = start; + while (*end && !_cups_isspace(*end)) + end++; + + if (*end) + *end++ = '\0'; + + /* + * Compare... + */ + + if (!_cups_strcasecmp(start, "NoEmptyFragments")) + options |= CUPSD_SSL_NOEMPTY; + else if (!_cups_strcasecmp(start, "AllowRC4")) + options |= CUPSD_SSL_ALLOW_RC4; + else if (!_cups_strcasecmp(start, "AllowSSL3")) + options |= CUPSD_SSL_ALLOW_SSL3; + else if (!_cups_strcasecmp(start, "None")) + options = 0; + else + cupsdLogMessage(CUPSD_LOG_ERROR, + "Unknown value \"%s\" for SSLOptions directive on " + "line %d.", start, linenum); + } + } + + SSLOptions = options; + _httpTLSSetOptions (SSLOptions & ~CUPSD_SSL_NOEMPTY); } #endif /* HAVE_SSL */ else if (!_cups_strcasecmp(line, "AccessLog") || --- a/scheduler/conf.h +++ b/scheduler/conf.h @@ -78,6 +78,8 @@ #define CUPSD_SSL_NONE 0 /* No special options */ #define CUPSD_SSL_NOEMPTY 1 /* Do not insert empty fragments */ +#define CUPSD_SSL_ALLOW_RC4 2 /* Allow RC4 cipher suites */ +#define CUPSD_SSL_ALLOW_SSL3 4 /* Allow SSL 3.0 */ /* --- a/doc/help/ref-client-conf.html +++ b/doc/help/ref-client-conf.html @@ -33,6 +33,26 @@ <P>The default setting is <VAR>IfRequested</VAR>.</P> +<H2 CLASS="title"><A NAME="SSLOptions">SSLOptions</A></H2> + +<H3>Examples</H3> + +<PRE CLASS="command"> +SSLOptions None +SSLOptions AllowSSL3 +SSLOptions AllowRC4 +</PRE> + +<H3>Description</H3> + +<P>Sets encryption options (only in /etc/cups/client.conf). By +default, CUPS only supports encryption using TLS v1.0 or higher using +known secure cipher suites. The <i>AllowRC4</i> option enables the +128-bit RC4 cipher suites, which are required for some older clients +that do not implement newer ones. The <i>AllowSSL3</i> option enables +SSL v3.0, which is required for some older clients that do not support +TLS v1.0.</P> + <H2 CLASS="title"><A NAME="ServerName">ServerName</A></H2> --- a/man/client.conf.man.in +++ b/man/client.conf.man.in @@ -46,6 +46,16 @@ .br Specifies the address and optionally the port to use when connecting to the server. \fBNote: Not supported on Mac OS X 10.7 or later.\fR +.TP 5 +SSLOptions \fR[\fIAllowRC4\fR] [\fIAllow SSL3\fR] +.br +Sets SSL/TLS protocol options for encrypted connections. By default, +CUPS only supports encryption using TLS v1.0 or higher using known +secure cipher suites. The \fIAllowRC4\fR option enables the 128-bit +RC4 cipher suites, which are required for some older clients that do +not implement newer ones. The \fIAllowSSL3\fR option enables SSL v3.0, +which is required for some older clients that do not support TLS v1.0. +.TP 5 .SH SEE ALSO http://localhost:631/help .SH COPYRIGHT --- a/scheduler/client.c +++ b/scheduler/client.c @@ -3410,6 +3410,10 @@ 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); + if (!(SSLOptions & CUPSD_SSL_ALLOW_SSL3)) + SSL_CTX_set_options(context, SSL_OP_NO_SSLv3); /* Don't use SSLv3 */ + if (!(SSLOptions & CUPSD_SSL_ALLOW_RC4)) + SSL_CTX_set_cipher_list(context, "DEFAULT:-RC4"); SSL_CTX_use_PrivateKey_file(context, ServerKey, SSL_FILETYPE_PEM); SSL_CTX_use_certificate_chain_file(context, ServerCertificate); @@ -3481,7 +3485,15 @@ ServerKey, GNUTLS_X509_FMT_PEM); gnutls_init(&con->http.tls, GNUTLS_SERVER); - gnutls_set_default_priority(con->http.tls); + if (!SSLOptions) + gnutls_priority_set_direct(con->http.tls, "NORMAL:-ARCFOUR-128:-VERS-SSL3.0", NULL); + else if ((SSLOptions & CUPSD_SSL_ALLOW_SSL3) && + (SSLOptions & CUPSD_SSL_ALLOW_RC4)) + gnutls_priority_set_direct(con->http.tls, "NORMAL", NULL); + else if (SSLOptions & CUPSD_SSL_ALLOW_SSL3) + gnutls_priority_set_direct(con->http.tls, "NORMAL:-ARCFOUR-128", NULL); + else + gnutls_priority_set_direct(con->http.tls, "NORMAL:-VERS-SSL3.0", NULL); gnutls_credentials_set(con->http.tls, GNUTLS_CRD_CERTIFICATE, *credentials); gnutls_transport_set_ptr(con->http.tls, (gnutls_transport_ptr)HTTP(con));