diff -up cups-1.6.3/cups/http.c.str4476 cups-1.6.3/cups/http.c --- cups-1.6.3/cups/http.c.str4476 2013-06-07 02:12:52.000000000 +0100 +++ cups-1.6.3/cups/http.c 2015-06-23 14:05:39.872805417 +0100 @@ -175,6 +175,8 @@ static int http_write_ssl(http_t *http, * Local globals... */ +static int tls_options = 0; /* Options for TLS connections */ + static const char * const http_fields[] = { "Accept-Language", @@ -3722,7 +3724,10 @@ http_send(http_t *http, /* I - Con 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 */ @@ -3959,6 +3964,10 @@ http_setup_ssl(http_t *http) /* I - Con 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); @@ -4018,7 +4027,16 @@ http_setup_ssl(http_t *http) /* I - Con 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); @@ -4433,7 +4451,10 @@ http_upgrade(http_t *http) /* I - Conne 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) { @@ -4764,6 +4785,16 @@ http_write_ssl(http_t *http, /* I - } #endif /* HAVE_SSL */ +/* + * '_httpTLSSetOptions()' - Set TLS/SSL options. + */ + +void +_httpTLSSetOptions(int options) +{ + tls_options = options; +} + /* * End of "$Id: http.c 7850 2008-08-20 00:07:25Z mike $". diff -up cups-1.6.3/cups/http-private.h.str4476 cups-1.6.3/cups/http-private.h --- cups-1.6.3/cups/http-private.h.str4476 2015-06-23 14:04:45.244230171 +0100 +++ cups-1.6.3/cups/http-private.h 2015-06-23 14:05:39.873805409 +0100 @@ -140,6 +140,10 @@ extern "C" { #define _HTTP_RESOLVE_FQDN 2 /* Resolve to a FQDN */ #define _HTTP_RESOLVE_FAXOUT 4 /* Resolve FaxOut service? */ +/* care - these should be the same values as the CUPSD_SSL_* equivalents */ +#define _HTTP_TLS_ALLOW_RC4 2 +#define _HTTP_TLS_ALLOW_SSL3 4 + /* * Types and functions for SSL support... @@ -377,6 +381,8 @@ extern const char *_httpResolveURI(const 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... diff -up cups-1.6.3/cups/usersys.c.str4476 cups-1.6.3/cups/usersys.c --- cups-1.6.3/cups/usersys.c.str4476 2015-06-23 14:04:45.268229986 +0100 +++ cups-1.6.3/cups/usersys.c 2015-06-23 14:05:39.873805409 +0100 @@ -72,7 +72,8 @@ static void cups_read_client_conf(cups_f #endif /* HAVE_GSSAPI */ const char *cups_anyroot, const char *cups_expiredroot, - const char *cups_expiredcerts); + const char *cups_expiredcerts, + int ssl_options); /* @@ -257,6 +258,9 @@ cupsSetEncryption(http_encryption_t e) / _cups_globals_t *cg = _cupsGlobals(); /* Pointer to library globals */ + if (cg->encryption == (http_encryption_t)-1) + _cupsSetDefaults(); + cg->encryption = e; if (cg->http) @@ -823,7 +827,36 @@ _cupsSetDefaults(void) if (cg->encryption == (http_encryption_t)-1 || !cg->server[0] || !cg->user[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, cups_user, +#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... @@ -831,33 +864,20 @@ _cupsSetDefaults(void) 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_user, + cups_read_client_conf(fp, cg, cups_encryption, cups_server, cups_user, #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); + } } } @@ -879,7 +899,8 @@ cups_read_client_conf( #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 */ @@ -952,6 +973,43 @@ cups_read_client_conf( 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); + } } /* diff -up cups-1.6.3/doc/help/ref-client-conf.html.str4476 cups-1.6.3/doc/help/ref-client-conf.html --- cups-1.6.3/doc/help/ref-client-conf.html.str4476 2013-06-25 15:38:12.000000000 +0100 +++ cups-1.6.3/doc/help/ref-client-conf.html 2015-06-23 14:05:39.873805409 +0100 @@ -76,6 +76,26 @@ present, only the last one is used. This +
+SSLOptions None +SSLOptions AllowSSL3 +SSLOptions AllowRC4 ++ +
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 AllowRC4 option enables the +128-bit RC4 cipher suites, which are required for some older clients +that do not implement newer ones. The AllowSSL3 option enables +SSL v3.0, which is required for some older clients that do not support +TLS v1.0.
+-SSLListen 127.0.0.1:443 -SSLListen 192.0.2.1:443 +SSLOptions 127.0.0.1:443 +SSLOptions 192.0.2.1:443
The SSLListen
directive specifies a network
+
The SSLOptions
directive specifies a network
address and port to listen for secure connections. Multiple
-SSLListen
directives can be provided to listen on
+SSLOptions
directives can be provided to listen on
multiple addresses.
The SSLListen
directive is similar to the The SSLOptions
directive is similar to the SSLPort
directive but allows you
to restrict access to specific interfaces or networks.
SSLOptions None SSLOptions NoEmptyFragments +SSLOptions AllowSSL3 +SSLOptions AllowRC4
The SSLOptions
directive specifies additional SSL/TLS
-protocol options to use for encrypted connected. Currently only two
-options are supported - None
(the default) for the most
-secure mode and NoEmptyFragments
to allow CUPS to work with
-Microsoft Windows with the FIPS conformance mode enabled.
NoEmptyFragments
option allows CUPS to work
+with Microsoft Windows with the FIPS conformance mode
+enabled. The AllowRC4
option enables the 128-bit RC4
+cipher suites, which are required for some older clients that do not
+implement newer ones. The AllowSSL3
option enables SSL
+v3.0, which is required for some older clients that do not support TLS
+v1.0.