diff options
Diffstat (limited to 'imap/src')
-rw-r--r-- | imap/src/c-client/imap4r1.c | 6 | ||||
-rw-r--r-- | imap/src/c-client/mail.c | 38 | ||||
-rw-r--r-- | imap/src/c-client/mail.h | 12 | ||||
-rw-r--r-- | imap/src/c-client/nntp.c | 8 | ||||
-rw-r--r-- | imap/src/c-client/pop3.c | 2 | ||||
-rw-r--r-- | imap/src/osdep/unix/ssl_unix.c | 168 |
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); |