added CRAM-MD5 authentication support.
parse server capability string to determine if STARTTLS is available
This commit is contained in:
		
							parent
							
								
									074298d482
								
							
						
					
					
						commit
						b3eb5661eb
					
				
					 5 changed files with 161 additions and 10 deletions
				
			
		| 
						 | 
					@ -1,5 +1,5 @@
 | 
				
			||||||
bin_PROGRAMS=isync
 | 
					bin_PROGRAMS=isync
 | 
				
			||||||
isync_SOURCES=main.c imap.c sync.c maildir.c isync.h list.c
 | 
					isync_SOURCES=main.c imap.c sync.c maildir.c isync.h list.c cram.c
 | 
				
			||||||
man_MANS=isync.1
 | 
					man_MANS=isync.1
 | 
				
			||||||
EXTRA_DIST=sample.isyncrc $(man_MANS)
 | 
					EXTRA_DIST=sample.isyncrc $(man_MANS)
 | 
				
			||||||
CPPFLAGS=$(RPM_OPT_FLAGS)
 | 
					CPPFLAGS=$(RPM_OPT_FLAGS)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										3
									
								
								README
									
										
									
									
									
								
							
							
						
						
									
										3
									
								
								README
									
										
									
									
									
								
							| 
						 | 
					@ -18,8 +18,9 @@ maintained, and all flags are synchronized.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	* Fast mode for fetching new mail only
 | 
						* Fast mode for fetching new mail only
 | 
				
			||||||
	* Supports imaps: (port 993) TLS/SSL connections
 | 
						* Supports imaps: (port 993) TLS/SSL connections
 | 
				
			||||||
	* Supports STARTTLS (RFC2595)
 | 
						* Supports STARTTLS (RFC2595) for confidentiality
 | 
				
			||||||
	* Supports NAMESPACE (RFC2342)
 | 
						* Supports NAMESPACE (RFC2342)
 | 
				
			||||||
 | 
						* Supports CRAM-MD5 (RFC2095) for authentication
 | 
				
			||||||
 | 
					
 | 
				
			||||||
* Compatibility
 | 
					* Compatibility
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										85
									
								
								cram.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										85
									
								
								cram.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,85 @@
 | 
				
			||||||
 | 
					/* $Id$
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * isync - IMAP4 to maildir mailbox synchronizer
 | 
				
			||||||
 | 
					 * Copyright (C) 2000 Michael R. Elkins <me@mutt.org>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *  This program is free software; you can redistribute it and/or modify
 | 
				
			||||||
 | 
					 *  it under the terms of the GNU General Public License as published by
 | 
				
			||||||
 | 
					 *  the Free Software Foundation; either version 2 of the License, or
 | 
				
			||||||
 | 
					 *  (at your option) any later version.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *  This program is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
				
			||||||
 | 
					 *  GNU General Public License for more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *  You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					 *  along with this program; if not, write to the Free Software
 | 
				
			||||||
 | 
					 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <assert.h>
 | 
				
			||||||
 | 
					#include "isync.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if HAVE_LIBSSL
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <openssl/hmac.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define ENCODED_SIZE(n)	(4*((n+2)/3))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static char
 | 
				
			||||||
 | 
					hexchar (unsigned int b)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (b < 10)
 | 
				
			||||||
 | 
						return '0' + b;
 | 
				
			||||||
 | 
					    return 'a' + (b - 10);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					char *
 | 
				
			||||||
 | 
					cram (const char *challenge, const char *user, const char *pass)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    HMAC_CTX hmac;
 | 
				
			||||||
 | 
					    char hash[16];
 | 
				
			||||||
 | 
					    char hex[33];
 | 
				
			||||||
 | 
					    int i;
 | 
				
			||||||
 | 
					    unsigned int hashlen = sizeof (hash);
 | 
				
			||||||
 | 
					    char buf[256];
 | 
				
			||||||
 | 
					    int len = strlen (challenge);
 | 
				
			||||||
 | 
					    char *response = calloc (1, 1 + len);
 | 
				
			||||||
 | 
					    char *final;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* response will always be smaller than challenge because we are
 | 
				
			||||||
 | 
					     * decoding.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    len = EVP_DecodeBlock ((unsigned char *) response, (unsigned char *) challenge, strlen (challenge));
 | 
				
			||||||
 | 
					//    printf ("CRAM-MD5 challege is %s\n", response);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    HMAC_Init (&hmac, (unsigned char *) pass, strlen (pass), EVP_md5 ());
 | 
				
			||||||
 | 
					    HMAC_Update (&hmac, (unsigned char *) response, strlen(response));
 | 
				
			||||||
 | 
					    HMAC_Final (&hmac, (unsigned char *) hash, &hashlen);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    assert (hashlen == sizeof (hash));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    free (response);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    hex[32] = 0;
 | 
				
			||||||
 | 
					    for (i = 0; i < 16; i++)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
						hex[2 * i] = hexchar ((hash[i] >> 4) & 0xf);
 | 
				
			||||||
 | 
						hex[2 * i + 1] = hexchar (hash[i] & 0xf);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    snprintf (buf, sizeof (buf), "%s %s", user, hex);
 | 
				
			||||||
 | 
					//    printf ("Response: %s\n", buf);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    len = strlen (buf);
 | 
				
			||||||
 | 
					    len = ENCODED_SIZE (len) + 1;
 | 
				
			||||||
 | 
					    final = malloc (len);
 | 
				
			||||||
 | 
					    final[len - 1] = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    assert (EVP_EncodeBlock ((unsigned char *) final, (unsigned char *) buf, strlen (buf)) == len - 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return final;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										64
									
								
								imap.c
									
										
									
									
									
								
							
							
						
						
									
										64
									
								
								imap.c
									
										
									
									
									
								
							| 
						 | 
					@ -401,6 +401,18 @@ imap_exec (imap_t * imap, const char *fmt, ...)
 | 
				
			||||||
	    {
 | 
						    {
 | 
				
			||||||
		parse_response_code (imap, cmd);
 | 
							parse_response_code (imap, cmd);
 | 
				
			||||||
	    }
 | 
						    }
 | 
				
			||||||
 | 
						    else if (!strcmp ("CAPABILITY", arg))
 | 
				
			||||||
 | 
						    {
 | 
				
			||||||
 | 
					#if HAVE_LIBSSL
 | 
				
			||||||
 | 
							while ((arg = next_arg (&cmd)))
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
							    if (!strcmp ("STARTTLS", arg))
 | 
				
			||||||
 | 
								imap->have_starttls = 1;
 | 
				
			||||||
 | 
							    else if (!strcmp ("AUTH=CRAM-MD5", arg))
 | 
				
			||||||
 | 
								imap->have_cram = 1;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
						    }
 | 
				
			||||||
	    else if ((arg1 = next_arg (&cmd)))
 | 
						    else if ((arg1 = next_arg (&cmd)))
 | 
				
			||||||
	    {
 | 
						    {
 | 
				
			||||||
		if (!strcmp ("EXISTS", arg1))
 | 
							if (!strcmp ("EXISTS", arg1))
 | 
				
			||||||
| 
						 | 
					@ -428,6 +440,26 @@ imap_exec (imap_t * imap, const char *fmt, ...)
 | 
				
			||||||
		return -1;
 | 
							return -1;
 | 
				
			||||||
	    }
 | 
						    }
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					#if HAVE_LIBSSL
 | 
				
			||||||
 | 
						else if (*arg == '+')
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
						    char *resp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						    if (!imap->cram)
 | 
				
			||||||
 | 
						    {
 | 
				
			||||||
 | 
							puts ("Error, not doing CRAM-MD5 authentication");
 | 
				
			||||||
 | 
							return -1;
 | 
				
			||||||
 | 
						    }
 | 
				
			||||||
 | 
						    resp = cram (cmd, imap->box->user, imap->box->pass);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						    socket_write (imap->sock, resp, strlen (resp));
 | 
				
			||||||
 | 
						    if (Verbose)
 | 
				
			||||||
 | 
							puts (resp);
 | 
				
			||||||
 | 
						    socket_write (imap->sock, "\r\n", 2);
 | 
				
			||||||
 | 
						    free (resp);
 | 
				
			||||||
 | 
						    imap->cram = 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
	else if ((size_t) atol (arg) != Tag)
 | 
						else if ((size_t) atol (arg) != Tag)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
	    puts ("wrong tag");
 | 
						    puts ("wrong tag");
 | 
				
			||||||
| 
						 | 
					@ -510,11 +542,16 @@ imap_open (config_t * box, unsigned int minuid)
 | 
				
			||||||
#if HAVE_LIBSSL
 | 
					#if HAVE_LIBSSL
 | 
				
			||||||
    if (!box->use_imaps)
 | 
					    if (!box->use_imaps)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
						/* let's see what this puppy can do... */
 | 
				
			||||||
 | 
						ret = imap_exec (imap, "CAPABILITY");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* always try to select SSL support if available */
 | 
						/* always try to select SSL support if available */
 | 
				
			||||||
	ret = imap_exec (imap, "STARTTLS");
 | 
						if (imap->have_starttls && !imap_exec (imap, "STARTTLS"))
 | 
				
			||||||
	if (!ret)
 | 
					 | 
				
			||||||
	    use_ssl = 1;
 | 
						    use_ssl = 1;
 | 
				
			||||||
	else if (box->require_ssl)
 | 
					
 | 
				
			||||||
 | 
						if (!use_ssl)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
						    if (box->require_ssl)
 | 
				
			||||||
	    {
 | 
						    {
 | 
				
			||||||
		puts ("Error, SSL support not available");
 | 
							puts ("Error, SSL support not available");
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
| 
						 | 
					@ -522,6 +559,7 @@ imap_open (config_t * box, unsigned int minuid)
 | 
				
			||||||
	    else
 | 
						    else
 | 
				
			||||||
		puts ("Warning, SSL support not available");
 | 
							puts ("Warning, SSL support not available");
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    else
 | 
					    else
 | 
				
			||||||
	use_ssl = 1;
 | 
						use_ssl = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -543,11 +581,31 @@ imap_open (config_t * box, unsigned int minuid)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	imap->sock->use_ssl = 1;
 | 
						imap->sock->use_ssl = 1;
 | 
				
			||||||
	puts ("SSL support enabled");
 | 
						puts ("SSL support enabled");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (box->use_imaps)
 | 
				
			||||||
 | 
						    ret = imap_exec (imap, "CAPABILITY");
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					    ret = imap_exec (imap, "CAPABILITY");
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    puts ("Logging in...");
 | 
					    puts ("Logging in...");
 | 
				
			||||||
 | 
					#if HAVE_LIBSSL
 | 
				
			||||||
 | 
					    if (imap->have_cram)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
						puts ("Authenticating with CRAM-MD5");
 | 
				
			||||||
 | 
						imap->cram = 1;
 | 
				
			||||||
 | 
						ret = imap_exec (imap, "AUTHENTICATE CRAM-MD5");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					#if HAVE_LIBSSL
 | 
				
			||||||
 | 
						if (!use_ssl)
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
						    puts ("*** Warning *** Password is being sent in the clear");
 | 
				
			||||||
	ret = imap_exec (imap, "LOGIN \"%s\" \"%s\"", box->user, box->pass);
 | 
						ret = imap_exec (imap, "LOGIN \"%s\" \"%s\"", box->user, box->pass);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!ret)
 | 
					    if (!ret)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										7
									
								
								isync.h
									
										
									
									
									
								
							
							
						
						
									
										7
									
								
								isync.h
									
										
									
									
									
								
							| 
						 | 
					@ -130,6 +130,11 @@ typedef struct
 | 
				
			||||||
    list_t *ns_personal;
 | 
					    list_t *ns_personal;
 | 
				
			||||||
    list_t *ns_other;
 | 
					    list_t *ns_other;
 | 
				
			||||||
    list_t *ns_shared;
 | 
					    list_t *ns_shared;
 | 
				
			||||||
 | 
					#if HAVE_LIBSSL
 | 
				
			||||||
 | 
					    unsigned int have_cram:1;
 | 
				
			||||||
 | 
					    unsigned int have_starttls:1;
 | 
				
			||||||
 | 
					    unsigned int cram:1;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
imap_t;
 | 
					imap_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -144,6 +149,8 @@ extern int Verbose;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if HAVE_LIBSSL
 | 
					#if HAVE_LIBSSL
 | 
				
			||||||
extern SSL_CTX *SSLContext;
 | 
					extern SSL_CTX *SSLContext;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					char *cram (const char *, const char *, const char *);
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
char *next_arg (char **);
 | 
					char *next_arg (char **);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		
		Reference in a new issue