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
 | 
			
		||||
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
 | 
			
		||||
EXTRA_DIST=sample.isyncrc $(man_MANS)
 | 
			
		||||
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
 | 
			
		||||
	* Supports imaps: (port 993) TLS/SSL connections
 | 
			
		||||
	* Supports STARTTLS (RFC2595)
 | 
			
		||||
	* Supports STARTTLS (RFC2595) for confidentiality
 | 
			
		||||
	* Supports NAMESPACE (RFC2342)
 | 
			
		||||
	* Supports CRAM-MD5 (RFC2095) for authentication
 | 
			
		||||
 | 
			
		||||
* 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
 | 
			
		||||
							
								
								
									
										74
									
								
								imap.c
									
										
									
									
									
								
							
							
						
						
									
										74
									
								
								imap.c
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -401,6 +401,18 @@ imap_exec (imap_t * imap, const char *fmt, ...)
 | 
			
		|||
	    {
 | 
			
		||||
		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)))
 | 
			
		||||
	    {
 | 
			
		||||
		if (!strcmp ("EXISTS", arg1))
 | 
			
		||||
| 
						 | 
				
			
			@ -428,6 +440,26 @@ imap_exec (imap_t * imap, const char *fmt, ...)
 | 
			
		|||
		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)
 | 
			
		||||
	{
 | 
			
		||||
	    puts ("wrong tag");
 | 
			
		||||
| 
						 | 
				
			
			@ -510,17 +542,23 @@ imap_open (config_t * box, unsigned int minuid)
 | 
			
		|||
#if HAVE_LIBSSL
 | 
			
		||||
    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 */
 | 
			
		||||
	ret = imap_exec (imap, "STARTTLS");
 | 
			
		||||
	if (!ret)
 | 
			
		||||
	if (imap->have_starttls && !imap_exec (imap, "STARTTLS"))
 | 
			
		||||
	    use_ssl = 1;
 | 
			
		||||
	else if (box->require_ssl)
 | 
			
		||||
 | 
			
		||||
	if (!use_ssl)
 | 
			
		||||
	{
 | 
			
		||||
	    puts ("Error, SSL support not available");
 | 
			
		||||
	    return 0;
 | 
			
		||||
	    if (box->require_ssl)
 | 
			
		||||
	    {
 | 
			
		||||
		puts ("Error, SSL support not available");
 | 
			
		||||
		return 0;
 | 
			
		||||
	    }
 | 
			
		||||
	    else
 | 
			
		||||
		puts ("Warning, SSL support not available");
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	    puts ("Warning, SSL support not available");
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
	use_ssl = 1;
 | 
			
		||||
| 
						 | 
				
			
			@ -543,11 +581,31 @@ imap_open (config_t * box, unsigned int minuid)
 | 
			
		|||
 | 
			
		||||
	imap->sock->use_ssl = 1;
 | 
			
		||||
	puts ("SSL support enabled");
 | 
			
		||||
 | 
			
		||||
	if (box->use_imaps)
 | 
			
		||||
	    ret = imap_exec (imap, "CAPABILITY");
 | 
			
		||||
    }
 | 
			
		||||
#else
 | 
			
		||||
    ret = imap_exec (imap, "CAPABILITY");
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    puts ("Logging in...");
 | 
			
		||||
    ret = imap_exec (imap, "LOGIN \"%s\" \"%s\"", box->user, box->pass);
 | 
			
		||||
#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);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (!ret)
 | 
			
		||||
    {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										7
									
								
								isync.h
									
										
									
									
									
								
							
							
						
						
									
										7
									
								
								isync.h
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -130,6 +130,11 @@ typedef struct
 | 
			
		|||
    list_t *ns_personal;
 | 
			
		||||
    list_t *ns_other;
 | 
			
		||||
    list_t *ns_shared;
 | 
			
		||||
#if HAVE_LIBSSL
 | 
			
		||||
    unsigned int have_cram:1;
 | 
			
		||||
    unsigned int have_starttls:1;
 | 
			
		||||
    unsigned int cram:1;
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
imap_t;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -144,6 +149,8 @@ extern int Verbose;
 | 
			
		|||
 | 
			
		||||
#if HAVE_LIBSSL
 | 
			
		||||
extern SSL_CTX *SSLContext;
 | 
			
		||||
 | 
			
		||||
char *cram (const char *, const char *, const char *);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
char *next_arg (char **);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		
		Reference in a new issue