From: "Rob Shearman" <robertshearman@gmail.com>
To: git@vger.kernel.org
Subject: [PATCH] git-imap-send: Add support for SSL.
Date: Sun, 1 Jun 2008 16:29:58 +0100 [thread overview]
Message-ID: <1096648c0806010829n71de92dcmc19ddb87da19931d@mail.gmail.com> (raw)
[-- Attachment #1: Type: text/plain, Size: 517 bytes --]
Allow SSL to be used when a new config setting, imap.ssl, is set to true.
Also, automatically use TLS when imap.ssl is not set by using the IMAP
STARTTLS command, if the server supports it.
Tested with Courier and Gimap IMAP servers.
Signed-off-by: Robert Shearman <robertshearman@gmail.com>
---
Documentation/git-imap-send.txt | 1 +
Makefile | 4 +-
imap-send.c | 165 +++++++++++++++++++++++++++++++++++----
3 files changed, 153 insertions(+), 17 deletions(-)
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 2b61990fac685caf27b906cb0b7ed66463b1c11b.diff --]
[-- Type: text/x-patch; name=2b61990fac685caf27b906cb0b7ed66463b1c11b.diff, Size: 7878 bytes --]
diff --git a/Documentation/git-imap-send.txt b/Documentation/git-imap-send.txt
index 522b73c..1c93339 100644
--- a/Documentation/git-imap-send.txt
+++ b/Documentation/git-imap-send.txt
@@ -41,6 +41,7 @@ configuration file (shown with examples):
User = bob
Pass = pwd
Port = 143
+ Ssl = false
..........................
diff --git a/Makefile b/Makefile
index cce5a6e..e3950ac 100644
--- a/Makefile
+++ b/Makefile
@@ -1118,7 +1118,9 @@ endif
git-%$X: %.o $(GITLIBS)
$(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) $(LIBS)
-git-imap-send$X: imap-send.o $(LIB_FILE)
+git-imap-send$X: imap-send.o $(GITLIBS)
+ $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \
+ $(LIBS) $(OPENSSL_LINK) $(OPENSSL_LIBSSL)
http.o http-walker.o http-push.o transport.o: http.h
diff --git a/imap-send.c b/imap-send.c
index 89a1532..f3db0c1 100644
--- a/imap-send.c
+++ b/imap-send.c
@@ -23,6 +23,10 @@
*/
#include "cache.h"
+#ifndef NO_OPENSSL
+# include <openssl/ssl.h>
+# include <openssl/err.h>
+#endif
typedef struct store_conf {
char *name;
@@ -129,6 +133,7 @@ typedef struct imap_server_conf {
int port;
char *user;
char *pass;
+ int use_ssl;
} imap_server_conf_t;
typedef struct imap_store_conf {
@@ -148,6 +153,9 @@ typedef struct _list {
typedef struct {
int fd;
+#ifndef NO_OPENSSL
+ SSL *ssl;
+#endif
} Socket_t;
typedef struct {
@@ -201,6 +209,7 @@ enum CAPABILITY {
UIDPLUS,
LITERALPLUS,
NAMESPACE,
+ STARTTLS,
};
static const char *cap_list[] = {
@@ -208,6 +217,7 @@ static const char *cap_list[] = {
"UIDPLUS",
"LITERAL+",
"NAMESPACE",
+ "STARTTLS",
};
#define RESP_OK 0
@@ -225,19 +235,104 @@ static const char *Flags[] = {
"Deleted",
};
+#ifndef NO_OPENSSL
+static void
+ssl_socket_perror( const char *func )
+{
+ fprintf( stderr, "%s: %s\n", func, ERR_error_string(ERR_get_error(), 0));
+}
+#endif
+
static void
socket_perror( const char *func, Socket_t *sock, int ret )
{
- if (ret < 0)
- perror( func );
+#ifndef NO_OPENSSL
+ if (sock->ssl) {
+ int sslerr = SSL_get_error( sock->ssl, ret );
+ switch (sslerr) {
+ case SSL_ERROR_NONE:
+ break;
+ case SSL_ERROR_SYSCALL:
+ perror( "SSL_connect" );
+ break;
+ default:
+ ssl_socket_perror( "SSL_connect" );
+ break;
+ }
+ } else
+#endif
+ {
+ if (ret < 0)
+ perror( func );
+ else
+ fprintf( stderr, "%s: unexpected EOF\n", func );
+ }
+}
+
+static int
+ssl_socket_connect( Socket_t *sock, int use_tls_only )
+{
+#ifdef NO_OPENSSL
+ fprintf( stderr, "SSL requested but SSL support not compiled in\n" );
+ return 1;
+#else
+ SSL_METHOD *meth;
+ SSL_CTX *ctx;
+ int ret;
+
+ SSL_library_init();
+ SSL_load_error_strings();
+
+ if (use_tls_only)
+ meth = TLSv1_method();
else
- fprintf( stderr, "%s: unexpected EOF\n", func );
+ meth = SSLv23_method();
+
+ if (!meth) {
+ ssl_socket_perror( "SSLv23_method" );
+ return 1;
+ }
+
+ ctx = SSL_CTX_new( meth );
+
+ /* FIXME! Add a config option for this */
+ if (0)
+ SSL_CTX_set_verify( ctx, SSL_VERIFY_PEER, NULL );
+
+ if (!SSL_CTX_set_default_verify_paths( ctx )) {
+ ssl_socket_perror( "SSL_CTX_set_default_verify_paths" );
+ return 1;
+ }
+ sock->ssl = SSL_new( ctx );
+ if (!sock->ssl) {
+ ssl_socket_perror( "SSL_new" );
+ return 1;
+ }
+ if (!SSL_set_fd( sock->ssl, sock->fd )) {
+ ssl_socket_perror( "SSL_set_fd" );
+ return 1;
+ }
+
+ ret = SSL_connect( sock->ssl );
+ if (ret <= 0) {
+ socket_perror( "SSL_connect", sock, ret );
+ return 1;
+ }
+
+ return 0;
+#endif
}
static int
socket_read( Socket_t *sock, char *buf, int len )
{
- ssize_t n = xread( sock->fd, buf, len );
+ ssize_t n;
+#ifndef NO_OPENSSL
+ if (sock->ssl)
+ n = SSL_read( sock->ssl, buf, len );
+ else
+#endif
+ n = xread( sock->fd, buf, len );
if (n <= 0) {
socket_perror( "read", sock, n );
close( sock->fd );
@@ -249,7 +344,13 @@ socket_read( Socket_t *sock, char *buf, int len )
static int
socket_write( Socket_t *sock, const char *buf, int len )
{
- int n = write_in_full( sock->fd, buf, len );
+ int n;
+#ifndef NO_OPENSSL
+ if (sock->ssl)
+ n = SSL_write( sock->ssl, buf, len );
+ else
+#endif
+ n = write_in_full( sock->fd, buf, len );
if (n != len) {
socket_perror( "write", sock, n );
close( sock->fd );
@@ -258,6 +359,18 @@ socket_write( Socket_t *sock, const char *buf, int len )
return n;
}
+static void
+socket_shutdown( Socket_t *sock )
+{
+#ifndef NO_OPENSSL
+ if (sock->ssl) {
+ SSL_shutdown( sock->ssl );
+ SSL_free( sock->ssl );
+ }
+#endif
+ close( sock->fd );
+}
+
/* simple line buffering */
static int
buffer_gets( buffer_t * b, char **s )
@@ -875,7 +988,7 @@ imap_close_server( imap_store_t *ictx )
if (imap->buf.sock.fd != -1) {
imap_exec( ictx, NULL, "LOGOUT" );
- close( imap->buf.sock.fd );
+ socket_shutdown( &imap->buf.sock );
}
free_list( imap->ns_personal );
free_list( imap->ns_other );
@@ -958,10 +1071,15 @@ imap_open_store( imap_server_conf_t *srvc )
perror( "connect" );
goto bail;
}
- imap_info( "ok\n" );
-
+
imap->buf.sock.fd = s;
+ if (srvc->use_ssl && ssl_socket_connect( &imap->buf.sock, 0 )) {
+ close( s );
+ goto bail;
+ }
+ imap_info( "ok\n" );
+
}
/* read the greeting string */
@@ -986,7 +1104,17 @@ imap_open_store( imap_server_conf_t *srvc )
goto bail;
if (!preauth) {
-
+#ifndef NO_OPENSSL
+ if (!srvc->use_ssl && CAP(STARTTLS)) {
+ if (imap_exec( ctx, 0, "STARTTLS" ) != RESP_OK)
+ goto bail;
+ if (ssl_socket_connect( &imap->buf.sock, 1 ))
+ goto bail;
+ /* capabilities may have changed, so get the new capabilities */
+ if (imap_exec( ctx, 0, "CAPABILITY" ) != RESP_OK)
+ goto bail;
+ }
+#endif
imap_info ("Logging in...\n");
if (!srvc->user) {
fprintf( stderr, "Skipping server %s, no user\n", srvc->host );
@@ -1014,7 +1142,10 @@ imap_open_store( imap_server_conf_t *srvc )
fprintf( stderr, "Skipping account %s@%s, server forbids LOGIN\n", srvc->user, srvc->host );
goto bail;
}
- imap_warn( "*** IMAP Warning *** Password is being sent in the clear\n" );
+#ifndef NO_OPENSSL
+ if (!imap->buf.sock.ssl)
+#endif
+ imap_warn( "*** IMAP Warning *** Password is being sent in the clear\n" );
if (imap_exec( ctx, NULL, "LOGIN \"%s\" \"%s\"", srvc->user, srvc->pass ) != RESP_OK) {
fprintf( stderr, "IMAP error: LOGIN failed\n" );
goto bail;
@@ -1242,6 +1373,7 @@ static imap_server_conf_t server =
0, /* port */
NULL, /* user */
NULL, /* pass */
+ 0, /* use_ssl */
};
static char *imap_folder;
@@ -1262,12 +1394,8 @@ git_imap_config(const char *key, const char *val, void *cb)
if (!strcmp( "folder", key )) {
imap_folder = xstrdup( val );
} else if (!strcmp( "host", key )) {
- {
- if (!prefixcmp(val, "imap:"))
- val += 5;
- if (!server.port)
- server.port = 143;
- }
+ if (!prefixcmp(val, "imap:"))
+ val += 5;
if (!prefixcmp(val, "//"))
val += 2;
server.host = xstrdup( val );
@@ -1280,6 +1408,8 @@ git_imap_config(const char *key, const char *val, void *cb)
server.port = git_config_int( key, val );
else if (!strcmp( "tunnel", key ))
server.tunnel = xstrdup( val );
+ else if (!strcmp( "ssl", key ))
+ server.use_ssl = git_config_bool( key, val );
return 0;
}
@@ -1299,6 +1429,9 @@ main(int argc, char **argv)
setup_git_directory_gently( NULL );
git_config(git_imap_config, NULL);
+ if (!server.port)
+ server.port = server.use_ssl ? 993 : 143;
+
if (!imap_folder) {
fprintf( stderr, "no imap store specified\n" );
return 1;
next reply other threads:[~2008-06-01 15:31 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-06-01 15:29 Rob Shearman [this message]
2008-06-22 19:27 ` [PATCH v2] git-imap-send: Add support for SSL Alam Arias
2008-06-22 20:41 ` Junio C Hamano
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1096648c0806010829n71de92dcmc19ddb87da19931d@mail.gmail.com \
--to=robertshearman@gmail.com \
--cc=git@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).