git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: [PATCH v4 1/2] git-imap-send: Add CRAM-MD5 authenticate method support

From
HMHitoshi Mitake <mitake@dcl.info.waseda.ac.jp>
Date
Feb 17, 2010, 09:17 UTC
Message-ID
<4B7BB437.1060608@dcl.info.waseda.ac.jp>
In-Reply-To
<7v8watg04g.fsf@alter.siamese.dyndns.org>
On 2010年02月16日 15:34, Junio C Hamano wrote:
Show 18 quoted lines
>
> So here is a replacement version to see if I remember all the points
> raised in the thread.
>
>   * Use of HMAC_Init() is kept, so people with ancient OpenSSL can use it;
>
>   * Lose "overallocate with xcalloc() and use strlen() to see how long the
>     result is" pattern; EVP_DecodeBlock() and EVP_EncodeBlock() should be
>     returning the length anyway, so use that directly;
>
>   * Comment style fixes;
>
>   * Lose "fprintf() then exit()"; die() instead; and
>
>   * Call HMAC_CTX_cleanup() when done;
>
> I didn't check the validity of the last one at all.  Please see if there
> is any funnies.
Thanks for your repairing.
I tested it and found one point have to be repaired,
     response_64 = xmalloc(ENCODED_SIZE(resp_len));
should be,
     response_64 = xmalloc(ENCODED_SIZE(resp_len) + 1);
for '\0'. This was the problem in my previous patch.
I noticed it by your indication, thanks.
And it seems that rest part of this patch doesn't contain problem.

I prepared the patch to repair this point. I'll send it later. If you like it, please use.

Show 242 quoted lines
>
> -- >8 --
> Subject: imap-send: support CRAM-MD5 authentication
>
> CRAM-MD5 authentication ought to be independent from SSL, but NO_OPENSSL
> build will not support this because the base64 and md5 code are used from
> the OpenSSL library in this implementation.
>
> Signed-off-by: Hitoshi Mitake<mitake@dcl.info.waseda.ac.jp>
> Signed-off-by: Junio C Hamano<gitster@pobox.com>
>
> ---
>   Documentation/git-imap-send.txt |    4 +
>   imap-send.c                     |  146 +++++++++++++++++++++++++++++++++++----
>   2 files changed, 135 insertions(+), 15 deletions(-)
>
> diff --git a/Documentation/git-imap-send.txt b/Documentation/git-imap-send.txt
> index 57db955..6cafbe2 100644
> --- a/Documentation/git-imap-send.txt
> +++ b/Documentation/git-imap-send.txt
> @@ -71,6 +71,10 @@ imap.preformattedHTML::
>   	option causes Thunderbird to send the patch as a plain/text,
>   	format=fixed email.  Default is `false`.
>
> +imap.authMethod::
> +	Specify authenticate method for authentication with IMAP server.
> +	Current supported method is 'CRAM-MD5' only.
> +
>   Examples
>   ~~~~~~~~
>
> diff --git a/imap-send.c b/imap-send.c
> index ba72fa4..bf1cd73 100644
> --- a/imap-send.c
> +++ b/imap-send.c
> @@ -27,6 +27,9 @@
>   #include "run-command.h"
>   #ifdef NO_OPENSSL
>   typedef void *SSL;
> +#else
> +#include<openssl/evp.h>
> +#include<openssl/hmac.h>
>   #endif
>
>   struct store_conf {
> @@ -140,6 +143,20 @@ struct imap_server_conf {
>   	int use_ssl;
>   	int ssl_verify;
>   	int use_html;
> +	char *auth_method;
> +};
> +
> +static struct imap_server_conf server = {
> +	NULL,	/* name */
> +	NULL,	/* tunnel */
> +	NULL,	/* host */
> +	0,	/* port */
> +	NULL,	/* user */
> +	NULL,	/* pass */
> +	0,   	/* use_ssl */
> +	1,   	/* ssl_verify */
> +	0,   	/* use_html */
> +	NULL,	/* auth_method */
>   };
>
>   struct imap_store_conf {
> @@ -214,6 +231,7 @@ enum CAPABILITY {
>   	LITERALPLUS,
>   	NAMESPACE,
>   	STARTTLS,
> +	AUTH_CRAM_MD5,
>   };
>
>   static const char *cap_list[] = {
> @@ -222,6 +240,7 @@ static const char *cap_list[] = {
>   	"LITERAL+",
>   	"NAMESPACE",
>   	"STARTTLS",
> +	"AUTH=CRAM-MD5",
>   };
>
>   #define RESP_OK    0
> @@ -949,6 +968,87 @@ static void imap_close_store(struct store *ctx)
>   	free(ctx);
>   }
>
> +#ifndef NO_OPENSSL
> +
> +/*
> + * hexchar() and cram() functions are based on the code from the isync
> + * project (http://isync.sf.net/).
> + */
> +static char hexchar(unsigned int b)
> +{
> +	return b<  10 ? '0' + b : 'a' + (b - 10);
> +}
> +
> +#define ENCODED_SIZE(n) (4*((n+2)/3))
> +static char *cram(const char *challenge_64, const char *user, const char *pass)
> +{
> +	int i, resp_len, encoded_len, decoded_len;
> +	HMAC_CTX hmac;
> +	unsigned char hash[16];
> +	char hex[33];
> +	char *response, *response_64, *challenge;
> +
> +	/*
> +	 * length of challenge_64 (i.e. base-64 encoded string) is a good
> +	 * enough upper bound for challenge (decoded result).
> +	 */
> +	encoded_len = strlen(challenge_64);
> +	challenge = xmalloc(encoded_len);
> +	decoded_len = EVP_DecodeBlock((unsigned char *)challenge,
> +				      (unsigned char *)challenge_64, encoded_len);
> +	if (decoded_len<  0)
> +		die("invalid challenge %s", challenge_64);
> +	HMAC_Init(&hmac, (unsigned char *)pass, strlen(pass), EVP_md5());
> +	HMAC_Update(&hmac, (unsigned char *)challenge, decoded_len);
> +	HMAC_Final(&hmac, hash, NULL);
> +	HMAC_CTX_cleanup(&hmac);
> +
> +	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);
> +	}
> +
> +	/* response: "<user>  <digest in hex>" */
> +	resp_len = strlen(user) + 1 + strlen(hex) + 1;
> +	response = xmalloc(resp_len);
> +	sprintf(response, "%s %s", user, hex);
> +
> +	response_64 = xmalloc(ENCODED_SIZE(resp_len));
> +	encoded_len = EVP_EncodeBlock((unsigned char *)response_64,
> +				      (unsigned char *)response, resp_len);
> +	if (encoded_len<  0)
> +		die("EVP_EncodeBlock error");
> +	response_64[encoded_len] = '\0';
> +	return (char *)response_64;
> +}
> +
> +#else
> +
> +static char *cram(const char *challenge_64, const char *user, const char *pass)
> +{
> +	die("If you want to use CRAM-MD5 authenticate method, "
> +	    "you have to build git-imap-send with OpenSSL library.");
> +}
> +
> +#endif
> +
> +static int auth_cram_md5(struct imap_store *ctx, struct imap_cmd *cmd, const char *prompt)
> +{
> +	int ret;
> +	char *response;
> +
> +	response = cram(prompt, server.user, server.pass);
> +
> +	ret = socket_write(&ctx->imap->buf.sock, response, strlen(response));
> +	if (ret != strlen(response))
> +		return error("IMAP error: sending response failed\n");
> +
> +	free(response);
> +
> +	return 0;
> +}
> +
>   static struct store *imap_open_store(struct imap_server_conf *srvc)
>   {
>   	struct imap_store *ctx;
> @@ -1130,9 +1230,34 @@ static struct store *imap_open_store(struct imap_server_conf *srvc)
>   		if (!imap->buf.sock.ssl)
>   			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;
> +
> +		if (srvc->auth_method) {
> +			struct imap_cmd_cb cb;
> +
> +			if (!strcmp(srvc->auth_method, "CRAM-MD5")) {
> +				if (!CAP(AUTH_CRAM_MD5)) {
> +					fprintf(stderr, "You specified"
> +						"CRAM-MD5 as authentication method, "
> +						"but %s doesn't support it.\n", srvc->host);
> +					goto bail;
> +				}
> +				/* CRAM-MD5 */
> +
> +				memset(&cb, 0, sizeof(cb));
> +				cb.cont = auth_cram_md5;
> +				if (imap_exec(ctx,&cb, "AUTHENTICATE CRAM-MD5") != RESP_OK) {
> +					fprintf(stderr, "IMAP error: AUTHENTICATE CRAM-MD5 failed\n");
> +					goto bail;
> +				}
> +			} else {
> +				fprintf(stderr, "Unknown authentication method:%s\n", srvc->host);
> +				goto bail;
> +			}
> +		} else {
> +			if (imap_exec(ctx, NULL, "LOGIN \"%s\" \"%s\"", srvc->user, srvc->pass) != RESP_OK) {
> +				fprintf(stderr, "IMAP error: LOGIN failed\n");
> +				goto bail;
> +			}
>   		}
>   	} /* !preauth */
>
> @@ -1310,18 +1435,6 @@ static int split_msg(struct msg_data *all_msgs, struct msg_data *msg, int *ofs)
>   	return 1;
>   }
>
> -static struct imap_server_conf server = {
> -	NULL,	/* name */
> -	NULL,	/* tunnel */
> -	NULL,	/* host */
> -	0,	/* port */
> -	NULL,	/* user */
> -	NULL,	/* pass */
> -	0,   	/* use_ssl */
> -	1,   	/* ssl_verify */
> -	0,   	/* use_html */
> -};
> -
>   static char *imap_folder;
>
>   static int git_imap_config(const char *key, const char *val, void *cb)
> @@ -1361,6 +1474,9 @@ static int 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("authmethod", key))
> +		server.auth_method = xstrdup(val);
> +
>   	return 0;
>   }
>
> --
> To unsubscribe from this list: send the line "unsubscribe git" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>
Previous: Junio C HamanoNext: Hitoshi Mitake
Message 29 of 49 in “imap.preformattedHTML and imap.sslverify”
  1. Junio C HamanoFeb 6, 2010
  2. Jeremy WhiteFeb 8, 2010
  3. Junio C HamanoFeb 8, 2010
  4. 0/4 Some improvements for git-imap-sendHitoshi Mitake, Feb 9, 2010
  5. Jeff KingFeb 9, 2010
  6. Erik Faye-LundFeb 9, 2010
  7. Jeff KingFeb 9, 2010
  8. Erik Faye-LundFeb 9, 2010
  9. Jeff KingFeb 9, 2010
  10. 1/2 git-imap-send: Add CRAM-MD5 authenticate method supportHitoshi Mitake, Feb 11, 2010
  11. Erik Faye-LundFeb 11, 2010
  12. Hitoshi MitakeFeb 11, 2010
  13. 1/2 git-imap-send: Add CRAM-MD5 authenticate method supportHitoshi Mitake, Feb 11, 2010
  14. Junio C HamanoFeb 11, 2010
  15. Hitoshi MitakeFeb 12, 2010
  16. 2/2 git-imap-send: Convert LF to CRLF before storing patch to draft boxHitoshi Mitake, Feb 11, 2010
  17. Junio C HamanoFeb 11, 2010
  18. Hitoshi MitakeFeb 12, 2010
  19. 1/2 git-imap-send: Add CRAM-MD5 authenticate method supportHitoshi Mitake, Feb 11, 2010
  20. 2/2 git-imap-send: Convert LF to CRLF before storing patch to draft boxHitoshi Mitake, Feb 11, 2010
  21. 1/2 git-imap-send: Add CRAM-MD5 authenticate method supportHitoshi Mitake, Feb 12, 2010
  22. Erik Faye-LundFeb 12, 2010
  23. Hitoshi MitakeFeb 13, 2010
  24. Junio C HamanoFeb 12, 2010
  25. Hitoshi MitakeFeb 13, 2010
  26. 1/2 git-imap-send: Add CRAM-MD5 authenticate method supportHitoshi Mitake, Feb 13, 2010
  27. Junio C HamanoFeb 13, 2010
  28. Junio C HamanoFeb 16, 2010
  29. Hitoshi MitakeFeb 17, 2010
  30. 1/2 git-imap-send: Add CRAM-MD5 authenticate method supportHitoshi Mitake, Feb 17, 2010
  31. Junio C HamanoFeb 17, 2010
  32. Hitoshi MitakeFeb 18, 2010
  33. Hitoshi MitakeFeb 17, 2010
  34. 2/2 git-imap-send: Convert LF to CRLF before storing patch to draft boxHitoshi Mitake, Feb 12, 2010
  35. 1/4 Add base64 encoder and decoderHitoshi Mitake, Feb 9, 2010
  36. Erik Faye-LundFeb 9, 2010
  37. Hitoshi MitakeFeb 11, 2010
  38. 2/4 Add stuffs for MD5 hash algorithmHitoshi Mitake, Feb 9, 2010
  39. 3/4 git-imap-send: Implement CRAM-MD5 auth methodHitoshi Mitake, Feb 9, 2010
  40. Erik Faye-LundFeb 9, 2010
  41. Hitoshi MitakeFeb 11, 2010
  42. Erik Faye-LundFeb 11, 2010
  43. Hitoshi MitakeFeb 11, 2010
  44. 4/4 git-imap-send: Add method to convert from LF to CRLFHitoshi Mitake, Feb 9, 2010
  45. Jakub NarebskiFeb 9, 2010
  46. Hitoshi MitakeFeb 11, 2010
  47. Linus TorvaldsFeb 9, 2010
  48. Junio C HamanoFeb 9, 2010
  49. Hitoshi MitakeFeb 11, 2010

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.