{"thread":{"id":"13754","subject":"[PATCH] git-imap-send: Add support for SSL.","startedAt":"2008-06-01T15:29:58Z","lastAt":"2008-06-22T20:41:52Z","messageCount":3,"participants":["Rob Shearman","Alam Arias","Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"78292","messageId":"1096648c0806010829n71de92dcmc19ddb87da19931d@mail.gmail.com","threadId":"13754","inReplyTo":null,"subject":"[PATCH] git-imap-send: Add support for SSL.","fromName":"Rob Shearman","fromEmail":"robertshearman@gmail.com","sentAt":"2008-06-01T15:29:58Z","receivedAt":"2008-06-01T15:29:58Z","isPatch":true,"sender":{"key":"robertshearman@gmail.com","avatar":null},"body":"Allow SSL to be used when a new config setting, imap.ssl, is set to true.\n\nAlso, automatically use TLS when imap.ssl is not set by using the IMAP\nSTARTTLS command, if the server supports it.\n\nTested with Courier and Gimap IMAP servers.\n\nSigned-off-by: Robert Shearman <robertshearman@gmail.com>\n---\n Documentation/git-imap-send.txt |    1 +\n Makefile                        |    4 +-\n imap-send.c                     |  165 +++++++++++++++++++++++++++++++++++----\n 3 files changed, 153 insertions(+), 17 deletions(-)\n\n\ndiff --git a/Documentation/git-imap-send.txt b/Documentation/git-imap-send.txt\nindex 522b73c..1c93339 100644\n--- a/Documentation/git-imap-send.txt\n+++ b/Documentation/git-imap-send.txt\n@@ -41,6 +41,7 @@ configuration file (shown with examples):\n     User = bob\n     Pass = pwd\n     Port = 143\n+    Ssl  = false\n ..........................\n \n \ndiff --git a/Makefile b/Makefile\nindex cce5a6e..e3950ac 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -1118,7 +1118,9 @@ endif\n git-%$X: %.o $(GITLIBS)\n \t$(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) $(LIBS)\n \n-git-imap-send$X: imap-send.o $(LIB_FILE)\n+git-imap-send$X: imap-send.o $(GITLIBS)\n+\t$(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \\\n+\t\t$(LIBS) $(OPENSSL_LINK) $(OPENSSL_LIBSSL)\n \n http.o http-walker.o http-push.o transport.o: http.h\n \ndiff --git a/imap-send.c b/imap-send.c\nindex 89a1532..f3db0c1 100644\n--- a/imap-send.c\n+++ b/imap-send.c\n@@ -23,6 +23,10 @@\n  */\n \n #include \"cache.h\"\n+#ifndef NO_OPENSSL\n+# include <openssl/ssl.h>\n+# include <openssl/err.h>\n+#endif\n \n typedef struct store_conf {\n \tchar *name;\n@@ -129,6 +133,7 @@ typedef struct imap_server_conf {\n \tint port;\n \tchar *user;\n \tchar *pass;\n+\tint use_ssl;\n } imap_server_conf_t;\n \n typedef struct imap_store_conf {\n@@ -148,6 +153,9 @@ typedef struct _list {\n \n typedef struct {\n \tint fd;\n+#ifndef NO_OPENSSL\n+\tSSL *ssl;\n+#endif\n } Socket_t;\n \n typedef struct {\n@@ -201,6 +209,7 @@ enum CAPABILITY {\n \tUIDPLUS,\n \tLITERALPLUS,\n \tNAMESPACE,\n+\tSTARTTLS,\n };\n \n static const char *cap_list[] = {\n@@ -208,6 +217,7 @@ static const char *cap_list[] = {\n \t\"UIDPLUS\",\n \t\"LITERAL+\",\n \t\"NAMESPACE\",\n+\t\"STARTTLS\",\n };\n \n #define RESP_OK    0\n@@ -225,19 +235,104 @@ static const char *Flags[] = {\n \t\"Deleted\",\n };\n \n+#ifndef NO_OPENSSL\n+static void\n+ssl_socket_perror( const char *func )\n+{\n+\tfprintf( stderr, \"%s: %s\\n\", func, ERR_error_string(ERR_get_error(), 0));\n+}\n+#endif\n+\n static void\n socket_perror( const char *func, Socket_t *sock, int ret )\n {\n-\tif (ret < 0)\n-\t\tperror( func );\n+#ifndef NO_OPENSSL\n+\tif (sock->ssl) {\n+\t\tint sslerr = SSL_get_error( sock->ssl, ret );\n+\t\tswitch (sslerr) {\n+\t\t\tcase SSL_ERROR_NONE:\n+\t\t\t\tbreak;\n+\t\t\tcase SSL_ERROR_SYSCALL:\n+\t\t\t\tperror( \"SSL_connect\" );\n+\t\t\t\tbreak;\n+\t\t\tdefault:\n+\t\t\t\tssl_socket_perror( \"SSL_connect\" );\n+\t\t\t\tbreak;\n+\t\t}\n+\t} else\n+#endif\n+\t{\n+\t\tif (ret < 0)\n+\t\t\tperror( func );\n+\t\telse\n+\t\t\tfprintf( stderr, \"%s: unexpected EOF\\n\", func );\n+\t}\n+}\n+\n+static int\n+ssl_socket_connect( Socket_t *sock, int use_tls_only )\n+{\n+#ifdef NO_OPENSSL\n+\tfprintf( stderr, \"SSL requested but SSL support not compiled in\\n\" );\n+\treturn 1;\n+#else\n+\tSSL_METHOD *meth;\n+\tSSL_CTX *ctx;\n+\tint ret;\n+\n+\tSSL_library_init();\n+\tSSL_load_error_strings();\n+\n+\tif (use_tls_only)\n+\t\tmeth = TLSv1_method();\n \telse\n-\t\tfprintf( stderr, \"%s: unexpected EOF\\n\", func );\n+\t\tmeth = SSLv23_method();\n+\n+\tif (!meth) {\n+\t\tssl_socket_perror( \"SSLv23_method\" );\n+\t\treturn 1;\n+\t}\n+\n+\tctx = SSL_CTX_new( meth );\n+\n+\t/* FIXME! Add a config option for this */\n+\tif (0)\n+\t\tSSL_CTX_set_verify( ctx, SSL_VERIFY_PEER, NULL );\n+\n+\tif (!SSL_CTX_set_default_verify_paths( ctx )) {\n+\t\tssl_socket_perror( \"SSL_CTX_set_default_verify_paths\" );\n+\t\treturn 1;\n+\t}\n+\tsock->ssl = SSL_new( ctx );\n+\tif (!sock->ssl) {\n+\t\tssl_socket_perror( \"SSL_new\" );\n+\t\treturn 1;\n+\t}\n+\tif (!SSL_set_fd( sock->ssl, sock->fd )) {\n+\t\tssl_socket_perror( \"SSL_set_fd\" );\n+\t\treturn 1;\n+\t}\n+\n+\tret = SSL_connect( sock->ssl );\n+\tif (ret <= 0) {\n+\t\tsocket_perror( \"SSL_connect\", sock, ret );\n+\t\treturn 1;\n+\t}\n+\n+\treturn 0;\n+#endif\n }\n \n static int\n socket_read( Socket_t *sock, char *buf, int len )\n {\n-\tssize_t n = xread( sock->fd, buf, len );\n+\tssize_t n;\n+#ifndef NO_OPENSSL\n+\tif (sock->ssl)\n+\t\tn = SSL_read( sock->ssl, buf, len );\n+\telse\n+#endif\n+\t\tn = xread( sock->fd, buf, len );\n \tif (n <= 0) {\n \t\tsocket_perror( \"read\", sock, n );\n \t\tclose( sock->fd );\n@@ -249,7 +344,13 @@ socket_read( Socket_t *sock, char *buf, int len )\n static int\n socket_write( Socket_t *sock, const char *buf, int len )\n {\n-\tint n = write_in_full( sock->fd, buf, len );\n+\tint n;\n+#ifndef NO_OPENSSL\n+\tif (sock->ssl)\n+\t\tn = SSL_write( sock->ssl, buf, len );\n+\telse\n+#endif\n+\t\tn = write_in_full( sock->fd, buf, len );\n \tif (n != len) {\n \t\tsocket_perror( \"write\", sock, n );\n \t\tclose( sock->fd );\n@@ -258,6 +359,18 @@ socket_write( Socket_t *sock, const char *buf, int len )\n \treturn n;\n }\n \n+static void\n+socket_shutdown( Socket_t *sock )\n+{\n+#ifndef NO_OPENSSL\n+\tif (sock->ssl) {\n+\t\tSSL_shutdown( sock->ssl );\n+\t\tSSL_free( sock->ssl );\n+\t}\n+#endif\n+\tclose( sock->fd );\n+}\n+\n /* simple line buffering */\n static int\n buffer_gets( buffer_t * b, char **s )\n@@ -875,7 +988,7 @@ imap_close_server( imap_store_t *ictx )\n \n \tif (imap->buf.sock.fd != -1) {\n \t\timap_exec( ictx, NULL, \"LOGOUT\" );\n-\t\tclose( imap->buf.sock.fd );\n+\t\tsocket_shutdown( &imap->buf.sock );\n \t}\n \tfree_list( imap->ns_personal );\n \tfree_list( imap->ns_other );\n@@ -958,10 +1071,15 @@ imap_open_store( imap_server_conf_t *srvc )\n \t\t\tperror( \"connect\" );\n \t\t\tgoto bail;\n \t\t}\n-\t\timap_info( \"ok\\n\" );\n-\n+\t\t\n \t\timap->buf.sock.fd = s;\n \n+\t\tif (srvc->use_ssl && ssl_socket_connect( &imap->buf.sock, 0 )) {\n+\t\t\tclose( s );\n+\t\t\tgoto bail;\n+\t\t}\n+\t\timap_info( \"ok\\n\" );\n+\n \t}\n \n \t/* read the greeting string */\n@@ -986,7 +1104,17 @@ imap_open_store( imap_server_conf_t *srvc )\n \t\tgoto bail;\n \n \tif (!preauth) {\n-\n+#ifndef NO_OPENSSL\n+\t\tif (!srvc->use_ssl && CAP(STARTTLS)) {\n+\t\t\tif (imap_exec( ctx, 0, \"STARTTLS\" ) != RESP_OK)\n+\t\t\t\tgoto bail;\n+\t\t\tif (ssl_socket_connect( &imap->buf.sock, 1 ))\n+\t\t\t\tgoto bail;\n+\t\t\t/* capabilities may have changed, so get the new capabilities */\n+\t\t\tif (imap_exec( ctx, 0, \"CAPABILITY\" ) != RESP_OK)\n+\t\t\t\tgoto bail;\n+\t\t}\n+#endif\n \t\timap_info (\"Logging in...\\n\");\n \t\tif (!srvc->user) {\n \t\t\tfprintf( stderr, \"Skipping server %s, no user\\n\", srvc->host );\n@@ -1014,7 +1142,10 @@ imap_open_store( imap_server_conf_t *srvc )\n \t\t\tfprintf( stderr, \"Skipping account %s@%s, server forbids LOGIN\\n\", srvc->user, srvc->host );\n \t\t\tgoto bail;\n \t\t}\n-\t\timap_warn( \"*** IMAP Warning *** Password is being sent in the clear\\n\" );\n+#ifndef NO_OPENSSL\n+\t\tif (!imap->buf.sock.ssl)\n+#endif\n+\t\t\timap_warn( \"*** IMAP Warning *** Password is being sent in the clear\\n\" );\n \t\tif (imap_exec( ctx, NULL, \"LOGIN \\\"%s\\\" \\\"%s\\\"\", srvc->user, srvc->pass ) != RESP_OK) {\n \t\t\tfprintf( stderr, \"IMAP error: LOGIN failed\\n\" );\n \t\t\tgoto bail;\n@@ -1242,6 +1373,7 @@ static imap_server_conf_t server =\n \t0,\t/* port */\n \tNULL,\t/* user */\n \tNULL,\t/* pass */\n+\t0,   \t/* use_ssl */\n };\n \n static char *imap_folder;\n@@ -1262,12 +1394,8 @@ git_imap_config(const char *key, const char *val, void *cb)\n \tif (!strcmp( \"folder\", key )) {\n \t\timap_folder = xstrdup( val );\n \t} else if (!strcmp( \"host\", key )) {\n-\t\t{\n-\t\t\tif (!prefixcmp(val, \"imap:\"))\n-\t\t\t\tval += 5;\n-\t\t\tif (!server.port)\n-\t\t\t\tserver.port = 143;\n-\t\t}\n+\t\tif (!prefixcmp(val, \"imap:\"))\n+\t\t\tval += 5;\n \t\tif (!prefixcmp(val, \"//\"))\n \t\t\tval += 2;\n \t\tserver.host = xstrdup( val );\n@@ -1280,6 +1408,8 @@ git_imap_config(const char *key, const char *val, void *cb)\n \t\tserver.port = git_config_int( key, val );\n \telse if (!strcmp( \"tunnel\", key ))\n \t\tserver.tunnel = xstrdup( val );\n+\telse if (!strcmp( \"ssl\", key ))\n+\t\tserver.use_ssl = git_config_bool( key, val );\n \treturn 0;\n }\n \n@@ -1299,6 +1429,9 @@ main(int argc, char **argv)\n \tsetup_git_directory_gently( NULL );\n \tgit_config(git_imap_config, NULL);\n \n+\tif (!server.port)\n+\t\tserver.port = server.use_ssl ? 993 : 143;\n+\n \tif (!imap_folder) {\n \t\tfprintf( stderr, \"no imap store specified\\n\" );\n \t\treturn 1;\n"},{"id":"80638","messageId":"20080622152747.77a0baee@gmail.com","threadId":"13754","inReplyTo":"1096648c0806010829n71de92dcmc19ddb87da19931d@mail.gmail.com","subject":"[PATCH v2] git-imap-send: Add support for SSL.","fromName":"Alam Arias","fromEmail":"alam.gbc@gmail.com","sentAt":"2008-06-22T19:27:47Z","receivedAt":"2008-06-22T19:27:47Z","isPatch":true,"sender":{"key":"alam.gbc@gmail.com","avatar":null},"body":"\nAllow SSL to be used when a new config setting, imap.ssl, is set to\ntrue.\n\nAlso, automatically use TLS when imap.ssl is not set by using the IMAP\nSTARTTLS command, if the server supports it.\n\nTested with Courier and Gimap IMAP servers.\n\nSigned-off-by: Robert Shearman <robertshearman@gmail.com>\n---\n Documentation/git-imap-send.txt |    1 +\n Makefile                        |    4 +-\n imap-send.c                     |  163\n+++++++++++++++++++++++++++++++++++---- 3 files changed, 152\ninsertions(+), 16 deletions(-)\n\ndiff --git a/Documentation/git-imap-send.txt b/Documentation/git-imap-send.txt\nindex f4fdc24..ecf2958 100644\n--- a/Documentation/git-imap-send.txt\n+++ b/Documentation/git-imap-send.txt\n@@ -41,6 +41,7 @@ configuration file (shown with examples):\n     User = bob\n     Pass = pwd\n     Port = 143\n+    Ssl  = false\n ..........................\n \n \ndiff --git a/Makefile b/Makefile\nindex 6a31c9f..0bd18fa 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -1157,7 +1157,9 @@ endif\n git-%$X: %.o $(GITLIBS)\n \t$(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) $(LIBS)\n \n-git-imap-send$X: imap-send.o $(LIB_FILE)\n+git-imap-send$X: imap-send.o $(GITLIBS)\n+\t$(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \\\n+\t\t$(LIBS) $(OPENSSL_LINK) $(OPENSSL_LIBSSL)\n \n http.o http-walker.o http-push.o transport.o: http.h\n \ndiff --git a/imap-send.c b/imap-send.c\nindex 1ec1310..7c95c5c 100644\n--- a/imap-send.c\n+++ b/imap-send.c\n@@ -23,6 +23,10 @@\n  */\n \n #include \"cache.h\"\n+#ifndef NO_OPENSSL\n+# include <openssl/ssl.h>\n+# include <openssl/err.h>\n+#endif\n \n typedef struct store_conf {\n \tchar *name;\n@@ -129,6 +133,7 @@ typedef struct imap_server_conf {\n \tint port;\n \tchar *user;\n \tchar *pass;\n+\tint use_ssl;\n } imap_server_conf_t;\n \n typedef struct imap_store_conf {\n@@ -148,6 +153,9 @@ typedef struct _list {\n \n typedef struct {\n \tint fd;\n+#ifndef NO_OPENSSL\n+\tSSL *ssl;\n+#endif\n } Socket_t;\n \n typedef struct {\n@@ -201,6 +209,7 @@ enum CAPABILITY {\n \tUIDPLUS,\n \tLITERALPLUS,\n \tNAMESPACE,\n+\tSTARTTLS,\n };\n \n static const char *cap_list[] = {\n@@ -208,6 +217,7 @@ static const char *cap_list[] = {\n \t\"UIDPLUS\",\n \t\"LITERAL+\",\n \t\"NAMESPACE\",\n+\t\"STARTTLS\",\n };\n \n #define RESP_OK    0\n@@ -225,19 +235,104 @@ static const char *Flags[] = {\n \t\"Deleted\",\n };\n \n+#ifndef NO_OPENSSL\n+static void\n+ssl_socket_perror( const char *func )\n+{\n+\tfprintf( stderr, \"%s: %s\\n\", func, ERR_error_string(ERR_get_error(), 0));\n+}\n+#endif\n+\n static void\n socket_perror( const char *func, Socket_t *sock, int ret )\n {\n-\tif (ret < 0)\n-\t\tperror( func );\n+#ifndef NO_OPENSSL\n+\tif (sock->ssl) {\n+\t\tint sslerr = SSL_get_error( sock->ssl, ret );\n+\t\tswitch (sslerr) {\n+\t\t\tcase SSL_ERROR_NONE:\n+\t\t\t\tbreak;\n+\t\t\tcase SSL_ERROR_SYSCALL:\n+\t\t\t\tperror( \"SSL_connect\" );\n+\t\t\t\tbreak;\n+\t\t\tdefault:\n+\t\t\t\tssl_socket_perror( \"SSL_connect\" );\n+\t\t\t\tbreak;\n+\t\t}\n+\t} else\n+#endif\n+\t{\n+\t\tif (ret < 0)\n+\t\t\tperror( func );\n+\t\telse\n+\t\t\tfprintf( stderr, \"%s: unexpected EOF\\n\", func );\n+\t}\n+}\n+\n+static int\n+ssl_socket_connect( Socket_t *sock, int use_tls_only )\n+{\n+#ifdef NO_OPENSSL\n+\tfprintf( stderr, \"SSL requested but SSL support not compiled in\\n\" );\n+\treturn 1;\n+#else\n+\tSSL_METHOD *meth;\n+\tSSL_CTX *ctx;\n+\tint ret;\n+\n+\tSSL_library_init();\n+\tSSL_load_error_strings();\n+\n+\tif (use_tls_only)\n+\t\tmeth = TLSv1_method();\n \telse\n-\t\tfprintf( stderr, \"%s: unexpected EOF\\n\", func );\n+\t\tmeth = SSLv23_method();\n+\n+\tif (!meth) {\n+\t\tssl_socket_perror( \"SSLv23_method\" );\n+\t\treturn 1;\n+\t}\n+\n+\tctx = SSL_CTX_new( meth );\n+\n+\t/* FIXME! Add a config option for this */\n+\tif (0)\n+\t\tSSL_CTX_set_verify( ctx, SSL_VERIFY_PEER, NULL );\n+\n+\tif (!SSL_CTX_set_default_verify_paths( ctx )) {\n+\t\tssl_socket_perror( \"SSL_CTX_set_default_verify_paths\" );\n+\t\treturn 1;\n+\t}\n+\tsock->ssl = SSL_new( ctx );\n+\tif (!sock->ssl) {\n+\t\tssl_socket_perror( \"SSL_new\" );\n+\t\treturn 1;\n+\t}\n+\tif (!SSL_set_fd( sock->ssl, sock->fd )) {\n+\t\tssl_socket_perror( \"SSL_set_fd\" );\n+\t\treturn 1;\n+\t}\n+\n+\tret = SSL_connect( sock->ssl );\n+\tif (ret <= 0) {\n+\t\tsocket_perror( \"SSL_connect\", sock, ret );\n+\t\treturn 1;\n+\t}\n+\n+\treturn 0;\n+#endif\n }\n \n static int\n socket_read( Socket_t *sock, char *buf, int len )\n {\n-\tssize_t n = xread( sock->fd, buf, len );\n+\tint n;\n+#ifndef NO_OPENSSL\n+\tif (sock->ssl)\n+\t\tn = SSL_read( sock->ssl, buf, len );\n+\telse\n+#endif\n+\t\tn = xread( sock->fd, buf, len );\n \tif (n <= 0) {\n \t\tsocket_perror( \"read\", sock, n );\n \t\tclose( sock->fd );\n@@ -249,7 +344,13 @@ socket_read( Socket_t *sock, char *buf, int len )\n static int\n socket_write( Socket_t *sock, const char *buf, int len )\n {\n-\tint n = write_in_full( sock->fd, buf, len );\n+\tint n;\n+#ifndef NO_OPENSSL\n+\tif (sock->ssl)\n+\t\tn = SSL_write( sock->ssl, buf, len );\n+\telse\n+#endif\n+\t\tn = write_in_full( sock->fd, buf, len );\n \tif (n != len) {\n \t\tsocket_perror( \"write\", sock, n );\n \t\tclose( sock->fd );\n@@ -258,6 +359,18 @@ socket_write( Socket_t *sock, const char *buf, int len )\n \treturn n;\n }\n \n+static void\n+socket_shutdown( Socket_t *sock )\n+{\n+#ifndef NO_OPENSSL\n+\tif (sock->ssl) {\n+\t\tSSL_shutdown( sock->ssl );\n+\t\tSSL_free( sock->ssl );\n+\t}\n+#endif\n+\tclose( sock->fd );\n+}\n+\n /* simple line buffering */\n static int\n buffer_gets( buffer_t * b, char **s )\n@@ -875,7 +988,7 @@ imap_close_server( imap_store_t *ictx )\n \n \tif (imap->buf.sock.fd != -1) {\n \t\timap_exec( ictx, NULL, \"LOGOUT\" );\n-\t\tclose( imap->buf.sock.fd );\n+\t\tsocket_shutdown( &imap->buf.sock );\n \t}\n \tfree_list( imap->ns_personal );\n \tfree_list( imap->ns_other );\n@@ -958,10 +1071,15 @@ imap_open_store( imap_server_conf_t *srvc )\n \t\t\tperror( \"connect\" );\n \t\t\tgoto bail;\n \t\t}\n-\t\timap_info( \"ok\\n\" );\n \n \t\timap->buf.sock.fd = s;\n \n+\t\tif (srvc->use_ssl && ssl_socket_connect( &imap->buf.sock, 0 )) {\n+\t\t\tclose( s );\n+\t\t\tgoto bail;\n+\t\t}\n+\t\timap_info( \"ok\\n\" );\n+\n \t}\n \n \t/* read the greeting string */\n@@ -986,7 +1104,17 @@ imap_open_store( imap_server_conf_t *srvc )\n \t\tgoto bail;\n \n \tif (!preauth) {\n-\n+#ifndef NO_OPENSSL\n+\t\tif (!srvc->use_ssl && CAP(STARTTLS)) {\n+\t\t\tif (imap_exec( ctx, 0, \"STARTTLS\" ) != RESP_OK)\n+\t\t\t\tgoto bail;\n+\t\t\tif (ssl_socket_connect( &imap->buf.sock, 1 ))\n+\t\t\t\tgoto bail;\n+\t\t\t/* capabilities may have changed, so get the new capabilities */\n+\t\t\tif (imap_exec( ctx, 0, \"CAPABILITY\" ) != RESP_OK)\n+\t\t\t\tgoto bail;\n+\t\t}\n+#endif\n \t\timap_info (\"Logging in...\\n\");\n \t\tif (!srvc->user) {\n \t\t\tfprintf( stderr, \"Skipping server %s, no user\\n\", srvc->host );\n@@ -1014,7 +1142,10 @@ imap_open_store( imap_server_conf_t *srvc )\n \t\t\tfprintf( stderr, \"Skipping account %s@%s, server forbids LOGIN\\n\", srvc->user, srvc->host );\n \t\t\tgoto bail;\n \t\t}\n-\t\timap_warn( \"*** IMAP Warning *** Password is being sent in the clear\\n\" );\n+#ifndef NO_OPENSSL\n+\t\tif (!imap->buf.sock.ssl)\n+#endif\n+\t\t\timap_warn( \"*** IMAP Warning *** Password is being sent in the clear\\n\" );\n \t\tif (imap_exec( ctx, NULL, \"LOGIN \\\"%s\\\" \\\"%s\\\"\", srvc->user, srvc->pass ) != RESP_OK) {\n \t\t\tfprintf( stderr, \"IMAP error: LOGIN failed\\n\" );\n \t\t\tgoto bail;\n@@ -1242,6 +1373,7 @@ static imap_server_conf_t server =\n \t0,\t/* port */\n \tNULL,\t/* user */\n \tNULL,\t/* pass */\n+\t0,\t/* use_ssl */\n };\n \n static char *imap_folder;\n@@ -1262,12 +1394,8 @@ git_imap_config(const char *key, const char *val, void *cb)\n \tif (!strcmp( \"folder\", key )) {\n \t\timap_folder = xstrdup( val );\n \t} else if (!strcmp( \"host\", key )) {\n-\t\t{\n-\t\t\tif (!prefixcmp(val, \"imap:\"))\n-\t\t\t\tval += 5;\n-\t\t\tif (!server.port)\n-\t\t\t\tserver.port = 143;\n-\t\t}\n+\t\tif (!prefixcmp(val, \"imap:\"))\n+\t\t\tval += 5;\n \t\tif (!prefixcmp(val, \"//\"))\n \t\t\tval += 2;\n \t\tserver.host = xstrdup( val );\n@@ -1280,6 +1408,8 @@ git_imap_config(const char *key, const char *val, void *cb)\n \t\tserver.port = git_config_int( key, val );\n \telse if (!strcmp( \"tunnel\", key ))\n \t\tserver.tunnel = xstrdup( val );\n+\telse if (!strcmp( \"ssl\", key ))\n+\t\tserver.use_ssl = git_config_bool( key, val );\n \treturn 0;\n }\n \n@@ -1298,6 +1428,9 @@ main(int argc, char **argv)\n \n \tgit_config(git_imap_config, NULL);\n \n+\tif (!server.port)\n+\t\tserver.port = server.use_ssl ? 993 : 143;\n+\n \tif (!imap_folder) {\n \t\tfprintf( stderr, \"no imap store specified\\n\" );\n \t\treturn 1;\n"},{"id":"80640","messageId":"7vej6pmcbz.fsf@gitster.siamese.dyndns.org","threadId":"13754","inReplyTo":"20080622152747.77a0baee@gmail.com","subject":"Re: [PATCH v2] git-imap-send: Add support for SSL.","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-06-22T20:41:52Z","receivedAt":"2008-06-22T20:41:52Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Alam Arias <Alam.GBC@gmail.com> writes:\n\n> Allow SSL to be used when a new config setting, imap.ssl, is set to\n> true.\n>\n> Also, automatically use TLS when imap.ssl is not set by using the IMAP\n> STARTTLS command, if the server supports it.\n>\n> Tested with Courier and Gimap IMAP servers.\n>\n> Signed-off-by: Robert Shearman <robertshearman@gmail.com>\n> ---\n>  Documentation/git-imap-send.txt |    1 +\n>  Makefile                        |    4 +-\n>  imap-send.c                     |  163\n> +++++++++++++++++++++++++++++++++++---- 3 files changed, 152\n> insertions(+), 16 deletions(-)\n>\n\nNext time please do _not_ attach *.diff but follow the style of patch\nsubmission other people do (see recent patch from Linus for example).\n\n> diff --git a/Documentation/git-imap-send.txt b/Documentation/git-imap-send.txt\n> index f4fdc24..ecf2958 100644\n> --- a/Documentation/git-imap-send.txt\n> +++ b/Documentation/git-imap-send.txt\n> @@ -41,6 +41,7 @@ configuration file (shown with examples):\n>      User = bob\n>      Pass = pwd\n>      Port = 143\n> +    Ssl  = false\n>  ..........................\n\nThis is \"start talking plain imap to the standard imap port and then say\nSTARTTLS to start SSL\", not \"imap over ssl (aka imaps = 993/tcp)\", right?\n\nIs support for the latter (1) widely needed, and/or (2) easy to add on top\nof this?  I presume the latter would use imaps:// URL scheme (in which\ncase the user does not need an extra config)?\n\n> diff --git a/Makefile b/Makefile\n> index 6a31c9f..0bd18fa 100644\n> --- a/Makefile\n> +++ b/Makefile\n> @@ -1157,7 +1157,9 @@ endif\n>  git-%$X: %.o $(GITLIBS)\n>  \t$(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) $(LIBS)\n>  \n> -git-imap-send$X: imap-send.o $(LIB_FILE)\n> +git-imap-send$X: imap-send.o $(GITLIBS)\n> +\t$(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \\\n> +\t\t$(LIBS) $(OPENSSL_LINK) $(OPENSSL_LIBSSL)\n\nThis looks enough to make it link both with and without NO_OPENSSL, but\nhas it actually been tested with both configurations?\n\n> diff --git a/imap-send.c b/imap-send.c\n> index 1ec1310..7c95c5c 100644\n> --- a/imap-send.c\n> +++ b/imap-send.c\n> @@ -225,19 +235,104 @@ static const char *Flags[] = {\n>  \t\"Deleted\",\n>  };\n>  \n> +#ifndef NO_OPENSSL\n> +static void\n> +ssl_socket_perror( const char *func )\n> +{\n> +\tfprintf( stderr, \"%s: %s\\n\", func, ERR_error_string(ERR_get_error(), 0));\n> +}\n> +#endif\n\nThe original code has tons of style violations like this, but please do\nnot introduce more of them.  I'd even like a follow-up patch after this\none to clean up the style of existing code (you can choose to do the other\nway around, first clean up the style of existing code without adding\nanything new, and then this patch without the style violations).\n\n * function name in definition does not start a new line, but follows its\n   return type on the same line;\n\n * open and close parentheses for function parameter list and argument\n   list are not followed/preceded by any space;\n\n>  static void\n>  socket_perror( const char *func, Socket_t *sock, int ret )\n>  {\n> -\tif (ret < 0)\n> -\t\tperror( func );\n> +#ifndef NO_OPENSSL\n> +\tif (sock->ssl) {\n> +\t\tint sslerr = SSL_get_error( sock->ssl, ret );\n> +\t\tswitch (sslerr) {\n> +\t\t\tcase SSL_ERROR_NONE:\n> +\t\t\t\tbreak;\n> +\t\t\tcase SSL_ERROR_SYSCALL:\n> +\t\t\t\tperror( \"SSL_connect\" );\n> +\t\t\t\tbreak;\n> +\t\t\tdefault:\n> +\t\t\t\tssl_socket_perror( \"SSL_connect\" );\n> +\t\t\t\tbreak;\n> +\t\t}\n\n * \"case\" arms of switch statement align with \"switch\" without extra\n   indentation;\n\n> +\t/* FIXME! Add a config option for this */\n> +\tif (0)\n> +\t\tSSL_CTX_set_verify( ctx, SSL_VERIFY_PEER, NULL );\n\nIndeed ;-).\n\n> +\tif (!SSL_CTX_set_default_verify_paths( ctx )) {\n> +\t\tssl_socket_perror( \"SSL_CTX_set_default_verify_paths\" );\n> +\t\treturn 1;\n> +\t}\n> +\tsock->ssl = SSL_new( ctx );\n> +\tif (!sock->ssl) {\n> +\t\tssl_socket_perror( \"SSL_new\" );\n> +\t\treturn 1;\n> +\t}\n\n * We usually signal error by returning negative (e.g. -1) unless there\n   otherwise a reason not to.\n\n> @@ -1014,7 +1142,10 @@ imap_open_store( imap_server_conf_t *srvc )\n>  \t\t\tfprintf( stderr, \"Skipping account %s@%s, server forbids LOGIN\\n\", srvc->user, srvc->host );\n>  \t\t\tgoto bail;\n>  \t\t}\n> -\t\timap_warn( \"*** IMAP Warning *** Password is being sent in the clear\\n\" );\n> +#ifndef NO_OPENSSL\n> +\t\tif (!imap->buf.sock.ssl)\n> +#endif\n\nHmm.  If NO_OPENSSL compilation had \".ssl\" member that is a dummy \"int\" or\nsomething, you can use this ifndef and it might make it easier to read.\n"}]}