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

+ +

Examples

+ +
+SSLOptions None
+SSLOptions AllowSSL3
+SSLOptions AllowRC4
+
+ +

Description

+ +

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.

+

CUPS 1.6/OS X 10.8User

Examples

diff -up cups-1.6.3/doc/help/ref-cupsd-conf.html.in.str4476 cups-1.6.3/doc/help/ref-cupsd-conf.html.in --- cups-1.6.3/doc/help/ref-cupsd-conf.html.in.str4476 2013-05-10 17:52:10.000000000 +0100 +++ cups-1.6.3/doc/help/ref-cupsd-conf.html.in 2015-06-23 14:05:39.873805409 +0100 @@ -2011,23 +2011,23 @@ SetEnv MY_ENV_VAR foo variable that should be passed to child processes.

-

SSLListen

+

SSLOptions

Examples

-SSLListen 127.0.0.1:443
-SSLListen 192.0.2.1:443
+SSLOptions 127.0.0.1:443
+SSLOptions 192.0.2.1:443
 

Description

-

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.

@@ -2039,15 +2039,22 @@ to restrict access to specific interface
 SSLOptions None
 SSLOptions NoEmptyFragments
+SSLOptions AllowSSL3
+SSLOptions AllowRC4
 

Description

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.

+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 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.

SSLPort

diff -up cups-1.6.3/man/client.conf.man.in.str4476 cups-1.6.3/man/client.conf.man.in --- cups-1.6.3/man/client.conf.man.in.str4476 2013-06-25 15:38:12.000000000 +0100 +++ cups-1.6.3/man/client.conf.man.in 2015-06-23 14:05:39.874805401 +0100 @@ -53,6 +53,15 @@ Specifies the address and optionally the server running CUPS 1.3.12 and earlier. \fBNote: Not supported on 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 User name .br Specifies the default user name to use for requests. diff -up cups-1.6.3/man/cupsd.conf.man.in.str4476 cups-1.6.3/man/cupsd.conf.man.in --- cups-1.6.3/man/cupsd.conf.man.in.str4476 2015-06-23 14:04:45.278229909 +0100 +++ cups-1.6.3/man/cupsd.conf.man.in 2015-06-23 14:05:39.874805401 +0100 @@ -480,9 +480,16 @@ Listens on the specified address and por .TP 5 SSLOptions None .TP 5 -SSLOptions NoEmptyFragments +SSLOptions \fR[\fINoEmptyFragments\fR] [\fIAllowRC4\fR] [\fIAllow SSL3\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 diff -up cups-1.6.3/scheduler/conf.c.str4476 cups-1.6.3/scheduler/conf.c --- cups-1.6.3/scheduler/conf.c.str4476 2015-06-23 14:04:45.298229754 +0100 +++ cups-1.6.3/scheduler/conf.c 2015-06-23 14:05:39.874805401 +0100 @@ -3361,17 +3361,54 @@ read_cupsd_conf(cups_file_t *fp) /* I - 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") || diff -up cups-1.6.3/scheduler/conf.h.str4476 cups-1.6.3/scheduler/conf.h --- cups-1.6.3/scheduler/conf.h.str4476 2015-06-23 14:04:45.298229754 +0100 +++ cups-1.6.3/scheduler/conf.h 2015-06-23 14:05:39.874805401 +0100 @@ -78,6 +78,8 @@ typedef enum #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 */ /* diff -up cups-1.6.3/scheduler/tls-gnutls.c.str4476 cups-1.6.3/scheduler/tls-gnutls.c --- cups-1.6.3/scheduler/tls-gnutls.c.str4476 2013-06-07 02:12:52.000000000 +0100 +++ cups-1.6.3/scheduler/tls-gnutls.c 2015-06-23 14:05:39.874805401 +0100 @@ -114,7 +114,15 @@ cupsdStartTLS(cupsd_client_t *con) /* I 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)); diff -up cups-1.6.3/scheduler/tls-openssl.c.str4476 cups-1.6.3/scheduler/tls-openssl.c --- cups-1.6.3/scheduler/tls-openssl.c.str4476 2013-06-07 02:12:52.000000000 +0100 +++ cups-1.6.3/scheduler/tls-openssl.c 2015-06-23 14:05:39.875805393 +0100 @@ -107,6 +107,10 @@ cupsdStartTLS(cupsd_client_t *con) /* I 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);