From: Ken Hornstein Date: Thu, 8 Sep 2016 19:40:04 +0000 (-0400) Subject: Started ... not quite working yet. X-Git-Url: https://diplodocus.org/git/nmh/commitdiff_plain/8560fb33a3727d4bea4cec722c7af2cede5f0dca?ds=inline;hp=-c Started ... not quite working yet. --- 8560fb33a3727d4bea4cec722c7af2cede5f0dca diff --git a/uip/popsbr.c b/uip/popsbr.c index 5b99c8cf..0e2f211f 100644 --- a/uip/popsbr.c +++ b/uip/popsbr.c @@ -22,6 +22,11 @@ # endif /* SASL_VERSION_FULL < 0x020125 */ #endif /* CYRUS_SASL */ +#ifdef TLS_SUPPORT +#include +#include +#endif /* TLS_SUPPORT */ + #include #include @@ -59,8 +64,6 @@ static sasl_callback_t callbacks[] = { #define SASL_BUFFER_SIZE 262144 }; -#else /* CYRUS_SASL */ -# define sasl_fgetc fgetc #endif /* CYRUS_SASL */ /* @@ -75,6 +78,18 @@ static int pop_auth_sasl(char *, char *, char *); static int sasl_fgetc(FILE *); #endif /* CYRUS_SASL */ +#ifdef TLS_SUPPORT +static SSL_CTX *sslctx = NULL; +static SSL *ssl = NULL; +static BIO *sbior = NULL; +static BIO *sbiow = NULL; +static BIO *io = NULL; + +static int tls_negotiate(void); +#endif /* TLS_SUPPORT */ + +static int tls_active = 0; + static int traverse (int (*)(char *), const char *, ...); static int vcommand(const char *, va_list); static int sasl_getline (char *, int, FILE *); @@ -507,7 +522,7 @@ parse_proxy(char *proxy, char *host) int pop_init (char *host, char *port, char *user, char *pass, char *proxy, - int snoop, int sasl, char *mech, const char *oauth_svc) + int snoop, int sasl, int tls, char *mech, const char *oauth_svc) { int fd1, fd2; char buffer[BUFSIZ]; @@ -599,6 +614,9 @@ pop_init (char *host, char *port, char *user, char *pass, char *proxy, SIGNAL (SIGPIPE, SIG_IGN); + if (tls && tls_negotiate()) + return NOTOK; + switch (sasl_getline (response, sizeof response, input)) { case OK: if (poprint) @@ -1078,3 +1096,103 @@ sasl_fgetc(FILE *f) return (int) buffer[0]; } #endif /* CYRUS_SASL */ + +#ifdef TLS_SUPPORT +/* + * Negotiate TLS at this point. Will call pop_done() on failure. + */ + +static int +tls_negotiate(void) +{ + BIO *ssl_bio; + + if (! sslctx) { + SSL_METHOD *method; + + SSL_library_init(); + SSL_load_error_strings(); + + method = TLS_client_method(); + + sslctx = SSL_CTX_new(method); + + if (! sslctx()) { + pop_done(); + advise(NULL, "Unable to initialize OpenSSL context: %s", + ERR_error_string(ERR_get_error(), NULL)); + return NOTOK; + } + } + + ssl = SSL_new(sslctx); + + if (! ssl) { + pop_done(); + advise(NULL, "Unable to create SSL connection: %s", + ERR_error_string(ERR_get_error(), NULL)); + return NOTOK; + } + + sbior = BIO_new_socket(fileno(input), BIO_NOCLOSE); + sbiow = BIO_new_socket(fileno(output), BIO_NOCLOSE); + + if (sbior == NULL || sbiow == NULL) { + pop_done(); + advise(NULL, "Unable to create BIO endpoints: %s", + ERR_error_string(ERR_get_error(), NULL); + return NOTOK; + } + + SSL_set_bio(ssl, sbior, sbiow); + SSL_set_connect_state(ssl); + + /* + * Set up a BIO to do buffering for us + */ + + io = BIO_new(BIO_f_buffer()); + + if (! io) { + pop_done(); + advise(NULL, "Unable to create a buffer BIO: %s", + ERR_error_string(ERR_get_error(), NULL); + return NOTOK; + } + + ssl_bio = BIO_new(BIO_f_ssl()); + + if (! ssl_bio) { + pop_done(); + advise(NULL, "Unable to create a SSL BIO: %s", + ERR_error_string(ERR_get_error(), NULL); + return NOTOK; + } + + BIO_set_ssl(ssl_bio, ssl, BIO_CLOSE); + BIO_push(io, ssl_bio); + + /* + * Try doing the handshake now + */ + + if (BIO_do_handshake(io) < 1) { + pop_done(); + advise(NULL, "Unable to negotiate SSL connection: %s", + ERR_error_string(ERR_get_error(), NULL); + return NOTOK; + } + + if (popprint) { + const SSL_CIPHER *cipher = SSL_get_current_cipher(ssl); + printf("SSL negotiation successful: %s(%d) %s\n", + SSL_CIPHER_get_name(cipher); + SSL_CIPHER_get_bits(cipher, NULL); + SSL_CIPHER_get_version(cipher); + } + + tls_active = 1; + + return OK; +} +#endif /* TLS_SUPPORT */