summaryrefslogtreecommitdiff
path: root/imap/src
diff options
context:
space:
mode:
Diffstat (limited to 'imap/src')
-rw-r--r--imap/src/c-client/imap4r1.c6
-rw-r--r--imap/src/c-client/mail.c38
-rw-r--r--imap/src/c-client/mail.h12
-rw-r--r--imap/src/c-client/nntp.c8
-rw-r--r--imap/src/c-client/pop3.c2
-rw-r--r--imap/src/osdep/unix/ssl_unix.c168
6 files changed, 131 insertions, 103 deletions
diff --git a/imap/src/c-client/imap4r1.c b/imap/src/c-client/imap4r1.c
index f443cb9b..b7423056 100644
--- a/imap/src/c-client/imap4r1.c
+++ b/imap/src/c-client/imap4r1.c
@@ -88,7 +88,7 @@ typedef struct imap_local {
unsigned int tls1 : 1; /* using TLSv1 over SSL */
unsigned int tls1_1 : 1; /* using TLSv1_1 over SSL */
unsigned int tls1_2 : 1; /* using TLSv1_2 over SSL */
- unsigned int dtls1 : 1; /* using DTLSv1 over SSL */
+ unsigned int tls1_3 : 1; /* using TLSv1_3 over SSL */
unsigned int novalidate : 1; /* certificate not validated */
unsigned int filter : 1; /* filter SEARCH/SORT/THREAD results */
unsigned int loser : 1; /* server is a loser */
@@ -955,9 +955,9 @@ MAILSTREAM *imap_open (MAILSTREAM *stream)
/* save state for future recycling */
if (mb.tlsflag) LOCAL->tlsflag = T;
if (mb.tls1) LOCAL->tls1 = T;
- if (mb.dtls1) LOCAL->dtls1 = T;
if (mb.tls1_1) LOCAL->tls1_1 = T;
if (mb.tls1_2) LOCAL->tls1_2 = T;
+ if (mb.tls1_3) LOCAL->tls1_3 = T;
if (mb.tlssslv23) LOCAL->tlssslv23 = T;
if (mb.notlsflag) LOCAL->notlsflag = T;
if (mb.sslflag) LOCAL->sslflag = T;
@@ -979,7 +979,7 @@ MAILSTREAM *imap_open (MAILSTREAM *stream)
if (LOCAL->tls1) strcat (tmp,"/tls1");
if (LOCAL->tls1_1) strcat (tmp,"/tls1_1");
if (LOCAL->tls1_2) strcat (tmp,"/tls1_2");
- if (LOCAL->dtls1) strcat (tmp,"/dtls1");
+ if (LOCAL->tls1_3) strcat (tmp,"/tls1_3");
if (LOCAL->tlssslv23) strcat (tmp,"/tls-sslv23");
if (LOCAL->notlsflag) strcat (tmp,"/notls");
if (LOCAL->sslflag) strcat (tmp,"/ssl");
diff --git a/imap/src/c-client/mail.c b/imap/src/c-client/mail.c
index ae828751..8f0373ed 100644
--- a/imap/src/c-client/mail.c
+++ b/imap/src/c-client/mail.c
@@ -36,6 +36,10 @@ char *UW_copyright = "Copyright 1988-2008 University of Washington\n\nLicensed u
/* c-client global data */
/* version of this library */
static char *mailcclientversion = CCLIENTVERSION;
+ /* Minimum in range of encryption supported */
+static int encryption_range_min = 0;
+ /* Maximum in range of encryption supported */
+static int encryption_range_max = 0;
/* app identity */
static IDLIST *idapp = NIL;
/* list of mail drivers */
@@ -541,6 +545,16 @@ void *mail_parameters (MAILSTREAM *stream,long function,void *value)
case GET_SSLFAILURE:
ret = (void *) mailsslfailure;
break;
+ case SET_ENCRYPTION_RANGE_MIN:
+ encryption_range_min = *(int *) value;
+ case GET_ENCRYPTION_RANGE_MIN:
+ ret = (void *) &encryption_range_min;
+ break;
+ case SET_ENCRYPTION_RANGE_MAX:
+ encryption_range_max = *(int *) value;
+ case GET_ENCRYPTION_RANGE_MAX:
+ ret = (void *) &encryption_range_max;
+ break;
case SET_KINIT:
mailkinit = (kinit_t) value;
case GET_KINIT:
@@ -829,29 +843,17 @@ long mail_valid_net_parse_work (char *name,NETMBX *mb,char *service)
else if (mailssldriver && !compare_cstring (s,"ssl") && !mb->tlsflag)
mb->sslflag = mb->notlsflag = T;
else if (!compare_cstring(s, "tls1")
- && !mb->tls1_1 && !mb->tls1_2 && !mb->tls1_3
- && !mb->dtls1 && !mb->dtls1_2)
+ && !mb->tls1_1 && !mb->tls1_2 && !mb->tls1_3)
mb->sslflag = mb->notlsflag = mb->tls1 = T;
else if (!compare_cstring(s, "tls1_1")
- && !mb->tls1 && !mb->tls1_2 && !mb->tls1_3
- && !mb->dtls1 && !mb->dtls1_2)
+ && !mb->tls1 && !mb->tls1_2 && !mb->tls1_3)
mb->sslflag = mb->notlsflag = mb->tls1_1 = T;
else if (!compare_cstring(s, "tls1_2")
- && !mb->tls1 && !mb->tls1_1 && !mb->tls1_3
- && !mb->dtls1 && !mb->dtls1_2)
+ && !mb->tls1 && !mb->tls1_1 && !mb->tls1_3)
mb->sslflag = mb->notlsflag = mb->tls1_2 = T;
else if (!compare_cstring(s, "tls1_3")
- && !mb->tls1 && !mb->tls1_1 && !mb->tls1_2
- && !mb->dtls1 && !mb->dtls1_2)
+ && !mb->tls1 && !mb->tls1_1 && !mb->tls1_2)
mb->sslflag = mb->notlsflag = mb->tls1_3 = T;
- else if (!compare_cstring(s, "dtls1")
- && !mb->tls1 && !mb->tls1_1 && !mb->tls1_2
- && !mb->tls1_3 && !mb->dtls1_2)
- mb->sslflag = mb->notlsflag = mb->dtls1 = T;
- else if (!compare_cstring(s, "dtls1_2")
- && !mb->tls1 && !mb->tls1_1 && !mb->tls1_2
- && !mb->tls1_3 && !mb->dtls1)
- mb->sslflag = mb->notlsflag = mb->dtls1_2 = T;
else if (mailssldriver && !compare_cstring (s,"novalidate-cert"))
mb->novalidate = T;
/* hack for compatibility with the past */
@@ -1263,7 +1265,7 @@ MAILSTREAM *mail_open (MAILSTREAM *stream,char *name,long options)
if (mb.tls1) strcat (tmp,"/tls1");
if (mb.tls1_1) strcat (tmp,"/tls1_1");
if (mb.tls1_2) strcat (tmp,"/tls1_2");
- if (mb.dtls1) strcat (tmp,"/dtls1");
+ if (mb.tls1_3) strcat (tmp,"/tls1_3");
if (mb.trysslflag) strcat (tmp,"/tryssl");
if (mb.novalidate) strcat (tmp,"/novalidate-cert");
strcat (tmp,"/pop3/loser}");
@@ -6233,8 +6235,6 @@ NETSTREAM *net_open (NETMBX *mb,NETDRIVER *dv,unsigned long port,
flags |= mb->tls1_1 ? NET_TRYTLS1_1 : 0;
flags |= mb->tls1_2 ? NET_TRYTLS1_2 : 0;
flags |= mb->tls1_3 ? NET_TRYTLS1_3 : 0;
- flags |= mb->dtls1 ? NET_TRYDTLS1 : 0;
- flags |= mb->dtls1_2 ? NET_TRYDTLS1_2 : 0;
if (strlen (mb->host) >= NETMAXHOST) {
sprintf (tmp,"Invalid host name: %.80s",mb->host);
MM_LOG (tmp,ERROR);
diff --git a/imap/src/c-client/mail.h b/imap/src/c-client/mail.h
index 73f6521c..58d2979c 100644
--- a/imap/src/c-client/mail.h
+++ b/imap/src/c-client/mail.h
@@ -230,6 +230,10 @@
#define SET_SSLCLIENTKEY (long) 335
#define GET_KERBEROS_CP_SVR_NAME (long) 336
#define SET_KERBEROS_CP_SVR_NAME (long) 337
+#define GET_ENCRYPTION_RANGE_MIN (long) 338
+#define SET_ENCRYPTION_RANGE_MIN (long) 339
+#define GET_ENCRYPTION_RANGE_MAX (long) 340
+#define SET_ENCRYPTION_RANGE_MAX (long) 341
/* 4xx: network drivers */
#define GET_MAXLOGINTRIALS (long) 400
@@ -449,10 +453,6 @@
#define NET_TRYTLS1_2 ((unsigned long) 0x1000000)
/* try TLS1_3 mode */
#define NET_TRYTLS1_3 ((unsigned long) 0x800000)
- /* try DTLS1 mode */
-#define NET_TRYDTLS1 ((unsigned long) 0x400000)
- /* try DTLS1_2 mode */
-#define NET_TRYDTLS1_2 ((unsigned long) 0x200000)
/* Close options */
@@ -698,8 +698,6 @@ typedef struct net_mailbox {
unsigned int tls1_1 : 1; /* Use TLSv1.1 */
unsigned int tls1_2 : 1; /* Use TLSV1.2 */
unsigned int tls1_3 : 1; /* Use TLSV1.3 */
- unsigned int dtls1 : 1; /* Use DTLSv1 */
- unsigned int dtls1_2 : 1; /* Use DTLSv1.2 */
unsigned int trysslflag : 1; /* try SSL driver first flag */
unsigned int novalidate : 1; /* don't validate certificates */
unsigned int tlsflag : 1; /* TLS flag */
@@ -714,7 +712,7 @@ typedef struct net_mailbox {
: (M).tls1 ? NET_TRYTLS1 \
: (M).tls1_1 ? NET_TRYTLS1_1 \
: (M).tls1_2 ? NET_TRYTLS1_2 \
- : (M).dtls1 ? NET_TRYDTLS1 \
+ : (M).tls1_3 ? NET_TRYTLS1_3 \
: NET_TLSCLIENT)
diff --git a/imap/src/c-client/nntp.c b/imap/src/c-client/nntp.c
index 8fa32df1..b1d08024 100644
--- a/imap/src/c-client/nntp.c
+++ b/imap/src/c-client/nntp.c
@@ -70,9 +70,9 @@ typedef struct nntp_local {
unsigned int notlsflag : 1; /* TLS not used in session */
unsigned int sslflag : 1; /* SSL session */
unsigned int tls1 : 1; /* TLSv1 on SSL port */
- unsigned int dtls1 : 1; /* DTLSv1 on SSL port */
unsigned int tls1_1 : 1; /* TLSv1_1 on SSL port */
unsigned int tls1_2 : 1; /* TLSv1_2 on SSL port */
+ unsigned int tls1_3 : 1; /* TLSv1_3 on SSL port */
unsigned int novalidate : 1; /* certificate not validated */
unsigned int xover : 1; /* supports XOVER */
unsigned int xhdr : 1; /* supports XHDR */
@@ -667,9 +667,9 @@ MAILSTREAM *nntp_mopen (MAILSTREAM *stream)
if (LOCAL->notlsflag) mb.notlsflag = T;
if (LOCAL->sslflag) mb.sslflag = T;
if (LOCAL->tls1) mb.tls1 = T;
- if (LOCAL->dtls1) mb.dtls1 = T;
if (LOCAL->tls1_1) mb.tls1_1 = T;
if (LOCAL->tls1_2) mb.tls1_2 = T;
+ if (LOCAL->tls1_3) mb.tls1_3 = T;
if (LOCAL->novalidate) mb.novalidate = T;
if (LOCAL->nntpstream->loser) mb.loser = T;
if (stream->secure) mb.secflag = T;
@@ -694,7 +694,7 @@ MAILSTREAM *nntp_mopen (MAILSTREAM *stream)
if (mb.tls1) strcat (tmp,"/tls1");
if (mb.tls1_1) strcat (tmp,"/tls1_1");
if (mb.tls1_2) strcat (tmp,"/tls1_2");
- if (mb.dtls1) strcat (tmp,"/dtls1");
+ if (mb.tls1_3) strcat (tmp,"/tls1_3");
if (mb.novalidate) strcat (tmp,"/novalidate-cert");
if (mb.loser) strcat (tmp,"/loser");
if (mb.secflag) strcat (tmp,"/secure");
@@ -765,9 +765,9 @@ MAILSTREAM *nntp_mopen (MAILSTREAM *stream)
if (LOCAL->notlsflag) strcat (tmp,"/notls");
if (LOCAL->sslflag) strcat (tmp,"/ssl");
if (LOCAL->tls1) strcat (tmp,"/tls1");
- if (LOCAL->dtls1) strcat (tmp,"/dtls1");
if (LOCAL->tls1_1) strcat (tmp,"/tls1_1");
if (LOCAL->tls1_2) strcat (tmp,"/tls1_2");
+ if (LOCAL->tls1_3) strcat (tmp,"/tls1_3");
if (LOCAL->novalidate) strcat (tmp,"/novalidate-cert");
if (LOCAL->nntpstream->loser) strcat (tmp,"/loser");
if (stream->secure) strcat (tmp,"/secure");
diff --git a/imap/src/c-client/pop3.c b/imap/src/c-client/pop3.c
index 80f1858d..dfc4f925 100644
--- a/imap/src/c-client/pop3.c
+++ b/imap/src/c-client/pop3.c
@@ -424,7 +424,7 @@ MAILSTREAM *pop3_open (MAILSTREAM *stream)
if (mb.tls1) strcat (tmp,"/tls1");
if (mb.tls1_1) strcat (tmp,"/tls1_1");
if (mb.tls1_2) strcat (tmp,"/tls1_2");
- if (mb.dtls1) strcat (tmp,"/dtls1");
+ if (mb.tls1_3) strcat (tmp,"/tls1_3");
if (mb.notlsflag) strcat (tmp,"/notls");
if (mb.sslflag) strcat (tmp,"/ssl");
if (mb.novalidate) strcat (tmp,"/novalidate-cert");
diff --git a/imap/src/osdep/unix/ssl_unix.c b/imap/src/osdep/unix/ssl_unix.c
index efbe8392..11454cbd 100644
--- a/imap/src/osdep/unix/ssl_unix.c
+++ b/imap/src/osdep/unix/ssl_unix.c
@@ -33,42 +33,10 @@
#include <bio.h>
#include <crypto.h>
#include <rand.h>
-#ifndef TLS_client_method
-#ifdef TLSv1_2_client_method
-#define TLS_client_method TLSv1_2_client_method
-#elif defined(TLSv1_1_client_method)
-#define TLS_client_method TLSv1_1_client_method
-#else
-#define TLS_client_method TLSv1_client_method
-#endif /* TLSv1_2_client_method */
-#endif /* TLS_client_method */
#ifdef OPENSSL_1_1_0
#include <rsa.h>
#include <bn.h>
-#ifdef TLSv1_client_method
-#undef TLSv1_client_method
-#endif /* TLSv1_client_method */
-#ifdef TLSv1_1_client_method
-#undef TLSv1_1_client_method
-#endif /* TLSv1_1_client_method */
-#ifdef TLSv1_2_client_method
-#undef TLSv1_2_client_method
-#endif /* TLSv1_2_client_method */
-#ifdef DTLSv1_client_method
-#undef DTLSv1_client_method
-#endif /* DTLSv1_client_method */
-#ifdef DTLSv1_2_client_method
-#undef DTLSv1_2_client_method
-#endif /* DTLSv1_2_client_method */
-#define TLSv1_client_method TLS_client_method
-#define TLSv1_1_client_method TLS_client_method
-#define TLSv1_2_client_method TLS_client_method
-#define DTLSv1_client_method DTLS_client_method
-#define DTLSv1_2_client_method DTLS_client_method
#endif /* OPENSSL_1_1_0 */
-#ifndef DTLSv1_2_client_method
-#define DTLSv1_2_client_method DTLSv1_client_method
-#endif /* DTLSv1_2_client_method */
#undef STRING
#undef crypt
@@ -105,7 +73,8 @@ typedef struct ssl_stream {
#include "sslio.h"
/* Function prototypes */
-const SSL_METHOD *ssl_connect_mthd(int flag);
+int ssl_disable_mask(int ssl_version, int direction);
+const SSL_METHOD *ssl_connect_mthd(int flag, int *min, int *max);
static SSLSTREAM *ssl_start(TCPSTREAM *tstream,char *host,unsigned long flags);
static char *ssl_start_work (SSLSTREAM *stream,char *host,unsigned long flags);
static int ssl_open_verify (int ok,X509_STORE_CTX *ctx);
@@ -205,50 +174,95 @@ SSLSTREAM *ssl_aopen (NETMBX *mb,char *service,char *usrbuf)
return NIL; /* don't use this mechanism with SSL */
}
+typedef struct ssl_disable_s {
+ int version;
+ int disable_code;
+} SSL_DISABLE_S;
+
+SSL_DISABLE_S ssl_disable[] = {
+ {SSL2_VERSION, SSL_OP_NO_SSLv2},
+ {SSL3_VERSION, SSL_OP_NO_SSLv3},
+ {TLS1_VERSION, SSL_OP_NO_TLSv1},
+ {TLS1_1_VERSION, SSL_OP_NO_TLSv1_1},
+ {TLS1_2_VERSION, SSL_OP_NO_TLSv1_2},
+#ifdef TLS1_3_VERSION
+ {TLS1_3_VERSION, SSL_OP_NO_TLSv1_3},
+#endif /* TLS1_3_VERSION */
+ {0, 0}
+};
+
+#define NUMBER_SSL_VERSIONS (sizeof(ssl_disable)/sizeof(ssl_disable[0]) - 1)
+
+/* returns the mask to disable a specific version.
+ * If version not found, returns 0.
+ *
+ * Arguments: version, and direction.
+ * If direction is -1, returns mask to disable versions less than given version.
+ * If direction is +1, returns mask to disable versions bigger than given version.
+ */
+int ssl_disable_mask(int ssl_version, int direction)
+{
+ int rv = 0;
+ int i;
+ for(i = 0; ssl_disable[i].version != 0
+ && ssl_disable[i].version != ssl_version; i++);
+ if(i == 0
+ || i == NUMBER_SSL_VERSIONS - 1
+ || ssl_disable[i].version == 0)
+ return rv;
+ i += direction; /* move in the direction */
+ for(; i >= 0 && i <= NUMBER_SSL_VERSIONS - 1; i += direction)
+ rv |= ssl_disable[i].disable_code;
+ return rv;
+}
+
+
/* ssl_connect_mthd: returns a context pointer to the connection to
* a ssl server
*/
-const SSL_METHOD *ssl_connect_mthd(int flag)
+const SSL_METHOD *ssl_connect_mthd(int flag, int *min, int *max)
{
- if (flag & NET_TRYTLS1)
-#ifndef OPENSSL_NO_TLS1_METHOD
- return TLSv1_client_method();
+ char tmp[10000];
+ int client_request;
+ client_request = (flag & NET_TRYTLS1) ? TLS1_VERSION
+ : (flag & NET_TRYTLS1_1) ? TLS1_1_VERSION
+ : (flag & NET_TRYTLS1_2) ? TLS1_2_VERSION
+#ifdef TLS1_3_VERSION
+ : (flag & NET_TRYTLS1_3) ? TLS1_3_VERSION
#else
- return TLS_client_method();
-#endif /* OPENSSL_NO_TLS1_METHOD */
-
- else if(flag & NET_TRYTLS1_1)
-#ifndef OPENSSL_NO_TLS1_1_METHOD
+ : (flag & NET_TRYTLS1_3) ? INT_MAX
+#endif
+ : 0L;
+
+ *min = *(int *) mail_parameters(NULL, GET_ENCRYPTION_RANGE_MIN, NULL);
+ *max = *(int *) mail_parameters(NULL, GET_ENCRYPTION_RANGE_MAX, NULL);
+
+ /*
+ * if no special request, negotiate the maximum the client is configured
+ * to negotiate
+ */
+ if(client_request == 0)
+ client_request = *max;
+
+ if(client_request < *min || client_request > *max)
+ return NIL; /* out of range? bail out */
+
+#ifndef OPENSSL_1_1_0
+ if(client_request == SSL3_VERSION)
+ return SSLv3_client_method();
+ if(client_request == TLS1_VERSION)
+ return TLSv1_client_method();
+ else if(client_request == TLS1_1_VERSION)
return TLSv1_1_client_method();
-#else
- return TLS_client_method();
-#endif /* OPENSSL_NO_TLS1_1_METHOD */
-
- else if(flag & NET_TRYTLS1_2)
-#ifndef OPENSSL_NO_TLS1_2_METHOD
+ else if(client_request == TLS1_2_VERSION)
return TLSv1_2_client_method();
-#else
- return TLS_client_method();
-#endif /* OPENSSL_NO_TLS1_2_METHOD */
-
- else if(flag & NET_TRYTLS1_3)
+#ifdef TLS1_3_VERSION /* this is only reachable if TLS1_3 support exists */
+ else if(client_request == TLS1_3_VERSION)
return TLS_client_method();
+#endif /* TLS1_3_VERSION */
+#endif /* ifndef OPENSSL_1_1_0 */
- else if(flag & NET_TRYDTLS1)
-#ifndef OPENSSL_NO_DTLS1_METHOD
- return DTLSv1_client_method();
-#else
- return DTLS_client_method();
-#endif /* OPENSSL_NO_DTLS1_METHOD */
-
- else if(flag & NET_TRYDTLS1_2)
-#ifndef OPENSSL_NO_DTLS1_METHOD
- return DTLSv1_2_client_method();
-#else
- return DTLS_client_method();
-#endif /* OPENSSL_NO_DTLS1_METHOD */
-
- else return SSLv23_client_method();
+ return SSLv23_client_method();
}
/* Start SSL/TLS negotiations
@@ -317,6 +331,7 @@ static char *ssl_start_work (SSLSTREAM *stream,char *host,unsigned long flags)
BIO *bio;
X509 *cert;
unsigned long sl,tl;
+ int min, max;
char *s,*t,*err,tmp[MAILTMPLEN], buf[256];
sslcertificatequery_t scq =
(sslcertificatequery_t) mail_parameters (NIL,GET_SSLCERTIFICATEQUERY,NIL);
@@ -326,9 +341,21 @@ static char *ssl_start_work (SSLSTREAM *stream,char *host,unsigned long flags)
(sslclientkey_t) mail_parameters (NIL,GET_SSLCLIENTKEY,NIL);
if (ssl_last_error) fs_give ((void **) &ssl_last_error);
ssl_last_host = host;
- if (!(stream->context = SSL_CTX_new (ssl_connect_mthd(flags))))
+ if (!(stream->context = SSL_CTX_new (ssl_connect_mthd(flags, &min, &max))))
return "SSL context failed";
SSL_CTX_set_options (stream->context,0);
+#ifdef OPENSSL_1_1_0
+ if(stream->context != NIL &&
+ ((min != 0 && SSL_CTX_set_min_proto_version(stream->context, min) == 0) ||
+ (max != 0 && SSL_CTX_set_max_proto_version(stream->context, max) == 0)))
+ return "SSL set protocol version Failed";
+#else
+ { int masklow, maskhigh;
+ masklow = ssl_disable_mask(min, -1);
+ maskhigh = ssl_disable_mask(max, 1);
+ SSL_CTX_set_options(stream->context, masklow|maskhigh);
+ }
+#endif /* OPENSSL_1_1_0 */
/* disable certificate validation? */
if (flags & NET_NOVALIDATECERT)
SSL_CTX_set_verify (stream->context,SSL_VERIFY_NONE,NIL);
@@ -363,6 +390,9 @@ static char *ssl_start_work (SSLSTREAM *stream,char *host,unsigned long flags)
/* create connection */
if (!(stream->con = (SSL *) SSL_new (stream->context)))
return "SSL connection failed";
+ if (host && !SSL_set_tlsext_host_name(stream->con, host)){
+ return "Server Name Identification (SNI) failed";
+ }
bio = BIO_new_socket (stream->tcpstream->tcpsi,BIO_NOCLOSE);
SSL_set_bio (stream->con,bio,bio);
SSL_set_connect_state (stream->con);