Git development
 help / color / mirror / Atom feed
* Re: Completion of error handling
From: Markus Elfring @ 2010-02-11 13:08 UTC (permalink / raw)
  To: Nicolas Pitre; +Cc: git
In-Reply-To: <alpine.LFD.2.00.1002021324290.1681@xanadu.home>


>
> What is the likelihood for those function calls to actually fail?
>   

How do you think about the usual design choices that are described in
the article "Exception Handling Alternatives" by Detlef Vollmann.
http://accu.org/index.php/journals/546


I propose to write pointcuts for all functions that can return values.
Some corresponding error codes are checked already. But there a places
in the source files with open issues for complete software robustness.

Are there any chances to encapsulate more cross-cutting concerns as
reusable aspects?

Would you like to integrate tools like the following into your software
development process?
- AspectC++
  http://aspectc.org/

- ACC
 
http://research.msrg.utoronto.ca/ACC/Tutorial#A_Reusable_Aspect_for_Memory_All

- Coccinelle
  http://coccinelle.lip6.fr/

Regards,
Markus

^ permalink raw reply

* Re: git-subtree.sh - regression introduced by da949cc55
From: Jakub Suder @ 2010-02-11 13:26 UTC (permalink / raw)
  To: Marc Fournier; +Cc: Avery Pennarun, git
In-Reply-To: <20100211130837.GA29916@lonquimay.wrk.lsn.camptocamp.com>

On Thu, Feb 11, 2010 at 14:08, Marc Fournier
<marc.fournier@camptocamp.com> wrote:
> Jakub, I'm not sure I understand what this patch is supposed to fix. Could
> you provide an example ? Or a test case ?

Hi,

there is a test case for the change you're talking about - it's near
the end of test.sh, between "check if split can find proper base
without --onto" and "check_equal ..." (it was added a few commits
later). The problem was that without this commit, in some cases if I
called subtree split for an external project which was earlier added
with git subtree (in order to backport some changes to the original
project) it didn't create the new commits on top of the existing ones
like it should (just look at the test case).

I'll take a closer look at this in the evening...

Jakub Suder

^ permalink raw reply

* git-subtree.sh - regression introduced by da949cc55
From: Marc Fournier @ 2010-02-11 13:08 UTC (permalink / raw)
  To: Avery Pennarun, Jakub Suder; +Cc: git

Hello,

Up to this commit, I was able to split out new trees out of sub-directories
of my project.

I used this to create a subproject out of a directory, without necessarily
knowing in advance that I could need the content of this directory in other
projects.

Since da949cc55, older unrelated commits get prepended to the history.

This issue is quite easy to reproduce:

 1. choose a directory in your project which hasn't been added with
    "git subtree add". Let's say it's called my/directory/.
 2. "git subtree split --prefix=my/directory --branch the-new-tree"
 3. "git log --stat the-new-tree"
 4. notice the mess which happens at the first commit concerning
    my/directory/ and how it then includes random older commits which have
    nothing related to my/directory.

Jakub, I'm not sure I understand what this patch is supposed to fix. Could
you provide an example ? Or a test case ?

Thanks !
Marc

^ permalink raw reply

* Re: [Announce] bup 0.09: git-based backup system for really huge datasets
From: Stephen R. van den Berg @ 2010-02-11 13:51 UTC (permalink / raw)
  To: Avery Pennarun; +Cc: Git Mailing List
In-Reply-To: <32541b131002091448o6f809322x1d86d2d7f74a80ed@mail.gmail.com>

Avery Pennarun wrote:
>bup is a file backup tool based on the git packfile format.  If you're
>interested in git, you might find bup interesting because:

Interesting concept.  It has some killer features which make it a good
competitor to any of the existing solutions.
The only obvious thing missing for unattended backup-operation is a way
to purge specific or old backups.
-- 
Sincerely,
           Stephen R. van den Berg.

^ permalink raw reply

* Re: [PATCH 1/4] Add base64 encoder and decoder
From: Hitoshi Mitake @ 2010-02-11 14:37 UTC (permalink / raw)
  To: kusmabite
  Cc: Erik Faye-Lund, gitster, git, Jeremy White, Robert Shearman, peff
In-Reply-To: <40aa078e1002090645s63449057hf88c89a232933680@mail.gmail.com>

(2010年02月09日 23:45), Erik Faye-Lund wrote:
> On Tue, Feb 9, 2010 at 1:09 PM, Hitoshi Mitake
> <mitake@dcl.info.waseda.ac.jp>  wrote:
>> +void base64_encode(char *out, const char *in, int inlen)
>> +{
>> +       const char *inp = in;
>> +       char *outp = out;
>
> ...Why? It's copying the pointers to pointers of identical type with
> different names, and never using the originals again... Looks like a
> sloppy extraction from another code-base to me.
>
>> +
>> +       while (inlen>= 3) {
>> +               *outp++ = base64char[(inp[0]>>  2)&  0x3f];
>> +               *outp++ = base64char[((inp[0]&  0x03)<<  4) |
>> +                                    ((inp[1]>>  4)&  0x0f)];
>> +               *outp++ = base64char[((inp[1]&  0x0f)<<  2) |
>> +                                    ((inp[2]>>  6)&  0x03)];
>> +               *outp++ = base64char[inp[2]&  0x3f];
>> +
>> +               inp += 3;
>> +               inlen -= 3;
>> +       }
>> +
>> +       if (inlen>  0) {
>> +               *outp++ = base64char[(inp[0]>>  2)&  0x3f];
>> +               if (inlen == 1) {
>> +                       *outp++ = base64char[(inp[0]&  0x03)<<  4];
>> +                       *outp++ = '=';
>> +               } else {
>> +                       *outp++ = base64char[((inp[0]&  0x03)<<  4) |
>> +                                            ((inp[1]>>  4)&  0x0f)];
>> +                       *outp++ = base64char[((inp[1]&  0x0f)<<  2)];
>> +               }
>> +               *outp++ = '=';
>> +       }
>> +
>> +       *outp = '\0';
>> +}
>
> If inlen is 0, a single '=' should be emitted (plus the obvious zero
> termination). It could be that the code deals with that by making sure
> that inlen never is zero, though.
>


Thanks for your review, I was careless...

I decided to use base64 and md5 stuffs OpenSSL provides.
I'll remove 1 and 2 of my patch series.

Thanks,

^ permalink raw reply

* Re: [PATCH 4/4] git-imap-send: Add method to convert from LF to CRLF
From: Hitoshi Mitake @ 2010-02-11 14:37 UTC (permalink / raw)
  To: Jakub Narebski; +Cc: gitster, git, Jeremy White, Robert Shearman
In-Reply-To: <m31vgu9yjk.fsf@localhost.localdomain>

(2010年02月10日 01:15), Jakub Narebski wrote:
> Hitoshi Mitake<mitake@dcl.info.waseda.ac.jp>  writes:
>
>> Some strict IMAP servers (e.g. Cyrus) don't
>> allow "bare newlines ('\n')" in messages.
>> So I added new boolean option "lf-to-crlf" to imap section.
>> If this option enabled, git-imap-send converts LF to CRLF("\r\n").
>>
>> If you want to use it, add line:
>> 	lf-to-crlf
>> to [imap] section of your .gitconfig .
>>
>> This patch also adds description to Documentation/git-imap-send.txt .
>
>> +imap.lf-to-crlf::
>> +	If you use strict IMAP server (e.g. Cyrus),
>> +	"bare newlines ('\n')" in messages are not allowed.
>> +	If this option enabled, git-imap-send converts LF to CRLF("\r\n").
>> +
>
> If you take a look at Documentation/config.txt at the names of other
> config variables, you would see that they have
>
>    core.fileMode::
>    core.ignoreCygwinFSTricks::
>    core.quotepath::
>    core.safecrlf::
>
> names, i.e. either camelCase or allsmallcase, and not
>
>    imap.lf-to-crlf::
>
> with '-' to separate parts.  Values can and do use this syntax, like
> e.g. `blank-at-eol` for core.whitespace.
>
> The only outlier is add.ignore-errors (not add.ignoreerrors or
> add.ignoreErrors).
>
>
> The same is true for the other config variable you propsed in 3/4
> patch.

Thanks for your review, I'll rename these values
based on custom of Git.

^ permalink raw reply

* Re: [PATCH 4/4] git-imap-send: Add method to convert from LF to CRLF
From: Hitoshi Mitake @ 2010-02-11 14:38 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Linus Torvalds, git, Jeremy White, Robert Shearman
In-Reply-To: <7vbpfye0e5.fsf@alter.siamese.dyndns.org>

(2010年02月10日 03:20), Junio C Hamano wrote:
> Linus Torvalds<torvalds@linux-foundation.org>  writes:
>
>> So I suspect that CRLF should be unconditional.
>
> That matches my reading of the RFC.  Thanks.

OK. I'll make converting LF to CRLF default behaviour.

>
> Hitoshi, can we have a modified version of 4/4 as a separate patch, so
> that we can apply it independently from the rest of the series?

Yeah, but as I describe below, I'll rewrite
my patch series and these only has 2 parts.

>
> As to the MD5 implementation, I am somewhat torn.
>
> Even if your md5 implementation were vastly superiour and faster than
> OpenSSL one (I don't know), the use of MD5 is not performance critical
> like SHA-1 is (for which we uniformly use Linus's block SHA-1 these days);
> the only thing it would be buying us to have our own implementation is one
> less dependency for people who do want to use imap-send with CRAM-MD5 but
> without SSL support.  How common is that combination?

Yes, using OpenSSL's md5 is better implementation.
But git-imap-send.c also asuumes non existence of OpenSSL.

And in theory, CRAM-MD5 and STARTTLS are independent things.
So I import MD5 things from libsylph.
But, as you told, CRAM-MD5 without STARTTLS
is not so common situation.
If you permit, I'd like to use MD5 functions of OpenSSL.

It seems that OpenSSL also provides base64 stuffs,
so I will be able to reduce patch series into 2 part.

I'll send these later. Please discard my previous series.

^ permalink raw reply

* [PATCH v2 1/2] git-imap-send: Add CRAM-MD5 authenticate method support
From: Hitoshi Mitake @ 2010-02-11 14:38 UTC (permalink / raw)
  To: gitster, gitster
  Cc: git, Hitoshi Mitake, Erik Faye-Lund, Jakub Narebski,
	Linus Torvalds, Jeff King
In-Reply-To: <1265717345-2118-1-git-send-email-mitake@dcl.info.waseda.ac.jp>

This patch makes git-imap-send CRAM-MD5 authenticate method ready.
In theory, CRAM-MD5 authenticate method doesn't depend on SSL,
but for easy of maintainance, this patch uses base64 and md5 stuffs of OpenSSL.
So if you want to use CRAM-MD5 authenticate method,
you have to build git-imap-send with OpenSSL library.

Cc: Erik Faye-Lund <kusmabite@googlemail.com>
Cc: Jakub Narebski <jnareb@gmail.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Jeff King <peff@peff.org>
Signed-off-by: Hitoshi Mitake <mitake@dcl.info.waseda.ac.jp>
---
 Documentation/git-imap-send.txt |    4 +
 imap-send.c                     |  144 ++++++++++++++++++++++++++++++++++-----
 2 files changed, 131 insertions(+), 17 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..dcd8a2a 100644
--- a/imap-send.c
+++ b/imap-send.c
@@ -25,10 +25,16 @@
 #include "cache.h"
 #include "exec_cmd.h"
 #include "run-command.h"
+
 #ifdef NO_OPENSSL
 typedef void *SSL;
+#else
+#include <openssl/evp.h>
+#include <openssl/hmac.h>
 #endif
 
+static int login;
+
 struct store_conf {
 	char *name;
 	const char *path; /* should this be here? its interpretation is driver-specific */
@@ -140,6 +146,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 +234,7 @@ enum CAPABILITY {
 	LITERALPLUS,
 	NAMESPACE,
 	STARTTLS,
+	AUTH_CRAM_MD5,
 };
 
 static const char *cap_list[] = {
@@ -222,6 +243,7 @@ static const char *cap_list[] = {
 	"LITERAL+",
 	"NAMESPACE",
 	"STARTTLS",
+	"AUTH=CRAM-MD5",
 };
 
 #define RESP_OK    0
@@ -526,8 +548,9 @@ static struct imap_cmd *v_issue_imap_cmd(struct imap_store *ctx,
 		get_cmd_result(ctx, NULL);
 
 	bufl = nfsnprintf(buf, sizeof(buf), cmd->cb.data ? CAP(LITERALPLUS) ?
-			   "%d %s{%d+}\r\n" : "%d %s{%d}\r\n" : "%d %s\r\n",
-			   cmd->tag, cmd->cmd, cmd->cb.dlen);
+			  "%d %s{%d+}\r\n" : "%d %s{%d}\r\n" : "%d %s\r\n",
+			  cmd->tag, cmd->cmd, cmd->cb.dlen);
+
 	if (Verbose) {
 		if (imap->num_in_progress)
 			printf("(%d in progress) ", imap->num_in_progress);
@@ -949,6 +972,72 @@ static void imap_close_store(struct store *ctx)
 	free(ctx);
 }
 
+/*
+ * hexchar() and cram() functions are
+ * based on ones of isync project ... http://isync.sf.net/
+ * Thanks!
+ */
+static char hexchar(unsigned int b)
+{
+	return b < 10 ? '0' + b : 'a' + (b - 10);
+}
+
+#ifndef NO_OPENSSL
+
+static char *cram(const char *challenge_64, const char *user, const char *pass)
+{
+	int i;
+	HMAC_CTX hmac;
+	char hash[16], hex[33], challenge[256], response[256];
+	char *response_64;
+
+	memset(challenge, 0, 256);
+	EVP_DecodeBlock((unsigned char *)challenge, (unsigned char *)challenge_64, strlen(challenge_64));
+	HMAC_Init(&hmac, (unsigned char *)pass, strlen(pass), EVP_md5());
+	HMAC_Update(&hmac, (unsigned char *)challenge, strlen(challenge));
+	HMAC_Final(&hmac, (unsigned char *)hash, NULL);
+
+	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);
+	}
+
+	memset(response, 0, 256);
+	snprintf(response, 256, "%s %s", user, hex);
+
+	response_64 = calloc(256 , sizeof(char));
+	EVP_EncodeBlock((unsigned char *)response_64, (unsigned char *)response, strlen(response));
+	return response_64;
+}
+
+#else
+
+static char *cram(const char *challenge_64 __used, const char *user __used, const char *pass __used)
+{
+	fprintf(stderr, "If you want to use CRAM-MD5 authenticate method,"
+		"you have to build git-imap-send with OpenSSL library\n");
+	exit(0);
+}
+
+#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)) {
+		fprintf(stderr, "IMAP error: sending response failed\n");
+		return -1;
+	}
+	free(response);
+
+	return 0;
+}
+
 static struct store *imap_open_store(struct imap_server_conf *srvc)
 {
 	struct imap_store *ctx;
@@ -1101,6 +1190,7 @@ static struct store *imap_open_store(struct imap_server_conf *srvc)
 		}
 #endif
 		imap_info("Logging in...\n");
+
 		if (!srvc->user) {
 			fprintf(stderr, "Skipping server %s, no user\n", srvc->host);
 			goto bail;
@@ -1130,10 +1220,37 @@ 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;
+				}
+				login = 1;
+			} else {
+				fprintf(stderr, "Unknown authentication method:%s\n", srvc->host);
+				goto bail;
+			}
 		}
+
+		if (!login)
+			if (imap_exec(ctx, NULL, "LOGIN \"%s\" \"%s\"", srvc->user, srvc->pass) != RESP_OK) {
+				fprintf(stderr, "IMAP error: LOGIN failed\n");
+				goto bail;
+			}
 	} /* !preauth */
 
 	ctx->prefix = "";
@@ -1258,6 +1375,7 @@ static int read_message(FILE *f, struct msg_data *msg)
 
 	msg->len  = buf.len;
 	msg->data = strbuf_detach(&buf, NULL);
+
 	return msg->len;
 }
 
@@ -1307,21 +1425,10 @@ static int split_msg(struct msg_data *all_msgs, struct msg_data *msg, int *ofs)
 
 	msg->data = xmemdupz(data, msg->len);
 	*ofs += msg->len;
+
 	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 +1468,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;
 }
 
-- 
1.6.5.2


^ permalink raw reply related

* [PATCH v2 2/2] git-imap-send: Convert LF to CRLF before storing patch to draft box
From: Hitoshi Mitake @ 2010-02-11 14:38 UTC (permalink / raw)
  To: gitster, gitster
  Cc: git, Hitoshi Mitake, Erik Faye-Lund, Jakub Narebski,
	Linus Torvalds, Jeff King
In-Reply-To: <1265717345-2118-1-git-send-email-mitake@dcl.info.waseda.ac.jp>

According to RFC of IMAP, all messages must not have "bare newlines ('\n')".
'\n' should be converted to "\r\n" before storing messages to IMAP's mailbox.
This patch implements the converting function to git-imap-send.

Cc: Erik Faye-Lund <kusmabite@googlemail.com>
Cc: Jakub Narebski <jnareb@gmail.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Jeff King <peff@peff.org>
Signed-off-by: Hitoshi Mitake <mitake@dcl.info.waseda.ac.jp>
---
 imap-send.c |   25 +++++++++++++++++++++++++
 1 files changed, 25 insertions(+), 0 deletions(-)

diff --git a/imap-send.c b/imap-send.c
index dcd8a2a..dbc72ca 100644
--- a/imap-send.c
+++ b/imap-send.c
@@ -1279,6 +1279,30 @@ static int imap_make_flags(int flags, char *buf)
 	return d;
 }
 
+static void lf_to_crlf(struct msg_data *msg)
+{
+	char *new;
+	int i, j, lfnum = 0;
+
+	for (i = 0; i < msg->len; i++) {
+		if (msg->data[i] == '\n')
+			lfnum++;
+	}
+	new = xcalloc(msg->len + lfnum, sizeof(char));
+	for (i = 0, j = 0; i < msg->len; i++) {
+		if (msg->data[i] != '\n') {
+			new[j++] = msg->data[i];
+			continue;
+		}
+		new[j++] = '\r';
+		new[j++] = '\n';
+	}
+	msg->len += lfnum;
+	free(msg->data);
+	msg->data = new;
+	msg->crlf = 1;
+}
+
 static int imap_store_msg(struct store *gctx, struct msg_data *data)
 {
 	struct imap_store *ctx = (struct imap_store *)gctx;
@@ -1288,6 +1312,7 @@ static int imap_store_msg(struct store *gctx, struct msg_data *data)
 	int ret, d;
 	char flagstr[128];
 
+	lf_to_crlf(data);
 	memset(&cb, 0, sizeof(cb));
 
 	cb.dlen = data->len;
-- 
1.6.5.2


^ permalink raw reply related

* [PATCH v2 1/2] git-imap-send: Add CRAM-MD5 authenticate method support
From: Hitoshi Mitake @ 2010-02-11 14:45 UTC (permalink / raw)
  To: gitster, gitster
  Cc: git, Hitoshi Mitake, Erik Faye-Lund, Jakub Narebski,
	Linus Torvalds, Jeff King
In-Reply-To: <1265717345-2118-1-git-send-email-mitake@dcl.info.waseda.ac.jp>

Sorry, I wrote wrong address of Jeff King,
copying email address from Thunderbird is irritant thing for me...
This is resending.

This patch makes git-imap-send CRAM-MD5 authenticate method ready.
In theory, CRAM-MD5 authenticate method doesn't depend on SSL,
but for easy of maintainance, this patch uses base64 and md5 stuffs of OpenSSL.
So if you want to use CRAM-MD5 authenticate method,
you have to build git-imap-send with OpenSSL library.

Cc: Erik Faye-Lund <kusmabite@googlemail.com>
Cc: Jakub Narebski <jnareb@gmail.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Jeff King <peff@peff.net>
Signed-off-by: Hitoshi Mitake <mitake@dcl.info.waseda.ac.jp>
---
 Documentation/git-imap-send.txt |    4 +
 imap-send.c                     |  144 ++++++++++++++++++++++++++++++++++-----
 2 files changed, 131 insertions(+), 17 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..dcd8a2a 100644
--- a/imap-send.c
+++ b/imap-send.c
@@ -25,10 +25,16 @@
 #include "cache.h"
 #include "exec_cmd.h"
 #include "run-command.h"
+
 #ifdef NO_OPENSSL
 typedef void *SSL;
+#else
+#include <openssl/evp.h>
+#include <openssl/hmac.h>
 #endif
 
+static int login;
+
 struct store_conf {
 	char *name;
 	const char *path; /* should this be here? its interpretation is driver-specific */
@@ -140,6 +146,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 +234,7 @@ enum CAPABILITY {
 	LITERALPLUS,
 	NAMESPACE,
 	STARTTLS,
+	AUTH_CRAM_MD5,
 };
 
 static const char *cap_list[] = {
@@ -222,6 +243,7 @@ static const char *cap_list[] = {
 	"LITERAL+",
 	"NAMESPACE",
 	"STARTTLS",
+	"AUTH=CRAM-MD5",
 };
 
 #define RESP_OK    0
@@ -526,8 +548,9 @@ static struct imap_cmd *v_issue_imap_cmd(struct imap_store *ctx,
 		get_cmd_result(ctx, NULL);
 
 	bufl = nfsnprintf(buf, sizeof(buf), cmd->cb.data ? CAP(LITERALPLUS) ?
-			   "%d %s{%d+}\r\n" : "%d %s{%d}\r\n" : "%d %s\r\n",
-			   cmd->tag, cmd->cmd, cmd->cb.dlen);
+			  "%d %s{%d+}\r\n" : "%d %s{%d}\r\n" : "%d %s\r\n",
+			  cmd->tag, cmd->cmd, cmd->cb.dlen);
+
 	if (Verbose) {
 		if (imap->num_in_progress)
 			printf("(%d in progress) ", imap->num_in_progress);
@@ -949,6 +972,72 @@ static void imap_close_store(struct store *ctx)
 	free(ctx);
 }
 
+/*
+ * hexchar() and cram() functions are
+ * based on ones of isync project ... http://isync.sf.net/
+ * Thanks!
+ */
+static char hexchar(unsigned int b)
+{
+	return b < 10 ? '0' + b : 'a' + (b - 10);
+}
+
+#ifndef NO_OPENSSL
+
+static char *cram(const char *challenge_64, const char *user, const char *pass)
+{
+	int i;
+	HMAC_CTX hmac;
+	char hash[16], hex[33], challenge[256], response[256];
+	char *response_64;
+
+	memset(challenge, 0, 256);
+	EVP_DecodeBlock((unsigned char *)challenge, (unsigned char *)challenge_64, strlen(challenge_64));
+	HMAC_Init(&hmac, (unsigned char *)pass, strlen(pass), EVP_md5());
+	HMAC_Update(&hmac, (unsigned char *)challenge, strlen(challenge));
+	HMAC_Final(&hmac, (unsigned char *)hash, NULL);
+
+	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);
+	}
+
+	memset(response, 0, 256);
+	snprintf(response, 256, "%s %s", user, hex);
+
+	response_64 = calloc(256 , sizeof(char));
+	EVP_EncodeBlock((unsigned char *)response_64, (unsigned char *)response, strlen(response));
+	return response_64;
+}
+
+#else
+
+static char *cram(const char *challenge_64 __used, const char *user __used, const char *pass __used)
+{
+	fprintf(stderr, "If you want to use CRAM-MD5 authenticate method,"
+		"you have to build git-imap-send with OpenSSL library\n");
+	exit(0);
+}
+
+#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)) {
+		fprintf(stderr, "IMAP error: sending response failed\n");
+		return -1;
+	}
+	free(response);
+
+	return 0;
+}
+
 static struct store *imap_open_store(struct imap_server_conf *srvc)
 {
 	struct imap_store *ctx;
@@ -1101,6 +1190,7 @@ static struct store *imap_open_store(struct imap_server_conf *srvc)
 		}
 #endif
 		imap_info("Logging in...\n");
+
 		if (!srvc->user) {
 			fprintf(stderr, "Skipping server %s, no user\n", srvc->host);
 			goto bail;
@@ -1130,10 +1220,37 @@ 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;
+				}
+				login = 1;
+			} else {
+				fprintf(stderr, "Unknown authentication method:%s\n", srvc->host);
+				goto bail;
+			}
 		}
+
+		if (!login)
+			if (imap_exec(ctx, NULL, "LOGIN \"%s\" \"%s\"", srvc->user, srvc->pass) != RESP_OK) {
+				fprintf(stderr, "IMAP error: LOGIN failed\n");
+				goto bail;
+			}
 	} /* !preauth */
 
 	ctx->prefix = "";
@@ -1258,6 +1375,7 @@ static int read_message(FILE *f, struct msg_data *msg)
 
 	msg->len  = buf.len;
 	msg->data = strbuf_detach(&buf, NULL);
+
 	return msg->len;
 }
 
@@ -1307,21 +1425,10 @@ static int split_msg(struct msg_data *all_msgs, struct msg_data *msg, int *ofs)
 
 	msg->data = xmemdupz(data, msg->len);
 	*ofs += msg->len;
+
 	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 +1468,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;
 }
 
-- 
1.6.5.2


^ permalink raw reply related

* [PATCH v2 2/2] git-imap-send: Convert LF to CRLF before storing patch to draft box
From: Hitoshi Mitake @ 2010-02-11 14:45 UTC (permalink / raw)
  To: gitster, gitster
  Cc: git, Hitoshi Mitake, Erik Faye-Lund, Jakub Narebski,
	Linus Torvalds, Jeff King
In-Reply-To: <1265717345-2118-1-git-send-email-mitake@dcl.info.waseda.ac.jp>

Sorry, I wrote wrong address of Jeff King,
copying email address from Thunderbird is irritant thing for me...
This is resending.

According to RFC of IMAP, all messages must not have "bare newlines ('\n')".
'\n' should be converted to "\r\n" before storing messages to IMAP's mailbox.
This patch implements the converting function to git-imap-send.

Cc: Erik Faye-Lund <kusmabite@googlemail.com>
Cc: Jakub Narebski <jnareb@gmail.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Jeff King <peff@peff.net>
Signed-off-by: Hitoshi Mitake <mitake@dcl.info.waseda.ac.jp>
---
 imap-send.c |   25 +++++++++++++++++++++++++
 1 files changed, 25 insertions(+), 0 deletions(-)

diff --git a/imap-send.c b/imap-send.c
index dcd8a2a..dbc72ca 100644
--- a/imap-send.c
+++ b/imap-send.c
@@ -1279,6 +1279,30 @@ static int imap_make_flags(int flags, char *buf)
 	return d;
 }
 
+static void lf_to_crlf(struct msg_data *msg)
+{
+	char *new;
+	int i, j, lfnum = 0;
+
+	for (i = 0; i < msg->len; i++) {
+		if (msg->data[i] == '\n')
+			lfnum++;
+	}
+	new = xcalloc(msg->len + lfnum, sizeof(char));
+	for (i = 0, j = 0; i < msg->len; i++) {
+		if (msg->data[i] != '\n') {
+			new[j++] = msg->data[i];
+			continue;
+		}
+		new[j++] = '\r';
+		new[j++] = '\n';
+	}
+	msg->len += lfnum;
+	free(msg->data);
+	msg->data = new;
+	msg->crlf = 1;
+}
+
 static int imap_store_msg(struct store *gctx, struct msg_data *data)
 {
 	struct imap_store *ctx = (struct imap_store *)gctx;
@@ -1288,6 +1312,7 @@ static int imap_store_msg(struct store *gctx, struct msg_data *data)
 	int ret, d;
 	char flagstr[128];
 
+	lf_to_crlf(data);
 	memset(&cb, 0, sizeof(cb));
 
 	cb.dlen = data->len;
-- 
1.6.5.2


^ permalink raw reply related

* [PATCH 2/5] init-db, rev-parse --git-dir: do not append redundant slash
From: Nguyễn Thái Ngọc Duy @ 2010-02-11 14:43 UTC (permalink / raw)
  To: git, João Carlos Mendes Luís, Junio C Hamano,
	Johannes Sixt
  Cc: Nguyễn Thái Ngọc Duy
In-Reply-To: <1265899403-15904-1-git-send-email-pclouds@gmail.com>

If git_dir already has the trailing slash, don't put another one
before .git. This only happens when git_dir is '/' or 'C:/'

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 builtin-init-db.c   |    9 ++++++---
 builtin-rev-parse.c |    4 +++-
 2 files changed, 9 insertions(+), 4 deletions(-)

diff --git a/builtin-init-db.c b/builtin-init-db.c
index dd84cae..aae7a4d 100644
--- a/builtin-init-db.c
+++ b/builtin-init-db.c
@@ -331,11 +331,14 @@ int init_db(const char *template_dir, unsigned int flags)
 		git_config_set("receive.denyNonFastforwards", "true");
 	}
 
-	if (!(flags & INIT_DB_QUIET))
-		printf("%s%s Git repository in %s/\n",
+	if (!(flags & INIT_DB_QUIET)) {
+		const char *git_dir = get_git_dir();
+		int len = strlen(git_dir);
+		printf("%s%s Git repository in %s%s\n",
 		       reinit ? "Reinitialized existing" : "Initialized empty",
 		       shared_repository ? " shared" : "",
-		       get_git_dir());
+		       git_dir, len && git_dir[len-1] != '/' ? "/" : "");
+	}
 
 	return 0;
 }
diff --git a/builtin-rev-parse.c b/builtin-rev-parse.c
index a8c5043..88bad9a 100644
--- a/builtin-rev-parse.c
+++ b/builtin-rev-parse.c
@@ -637,6 +637,7 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
 			if (!strcmp(arg, "--git-dir")) {
 				const char *gitdir = getenv(GIT_DIR_ENVIRONMENT);
 				static char cwd[PATH_MAX];
+				int len;
 				if (gitdir) {
 					puts(gitdir);
 					continue;
@@ -647,7 +648,8 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
 				}
 				if (!getcwd(cwd, PATH_MAX))
 					die_errno("unable to get current working directory");
-				printf("%s/.git\n", cwd);
+				len = strlen(cwd);
+				printf("%s%s.git\n", cwd, len && cwd[len-1] != '/' ? "/" : "");
 				continue;
 			}
 			if (!strcmp(arg, "--is-inside-git-dir")) {
-- 
1.7.0.rc2.182.g3adef

^ permalink raw reply related

* [PATCH 5/5] Add test for using Git at root directory
From: Nguyễn Thái Ngọc Duy @ 2010-02-11 14:43 UTC (permalink / raw)
  To: git, João Carlos Mendes Luís, Junio C Hamano,
	Johannes Sixt
  Cc: Nguyễn Thái Ngọc Duy
In-Reply-To: <1265899403-15904-1-git-send-email-pclouds@gmail.com>

This kind of test requires a throw-away root filesystem so that it can
play on. If you have such a system, go ahead, "chmod 777 /" and run
this test manually. Because this is a dangerous test, you are required
to set an env variable, and not to use root to run it.

Script prepare-root.sh may help you set up a chroot environment with
Git test suite inside. You will need Linux, static linked busybox,
rsync and root permission to use it.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 t/t1509-root-worktree.sh  |  249 +++++++++++++++++++++++++++++++++++++++++++++
 t/t1509/excludes          |   14 +++
 t/t1509/prepare-chroot.sh |   38 +++++++
 3 files changed, 301 insertions(+), 0 deletions(-)
 create mode 100755 t/t1509-root-worktree.sh
 create mode 100644 t/t1509/excludes
 create mode 100755 t/t1509/prepare-chroot.sh

diff --git a/t/t1509-root-worktree.sh b/t/t1509-root-worktree.sh
new file mode 100755
index 0000000..5322a3b
--- /dev/null
+++ b/t/t1509-root-worktree.sh
@@ -0,0 +1,249 @@
+#!/bin/sh
+
+test_description='Test Git when git repository is located at root
+
+This test requires write access in root. Do not bother if you do not
+have a throwaway chroot or VM.
+
+Script t1509/prepare-chroot.sh may help you setup chroot, then you
+can chroot in and execute this test from there.
+'
+
+. ./test-lib.sh
+
+test_cmp_val() {
+	echo "$1" > expected
+	echo "$2" > result
+	test_cmp expected result
+}
+
+test_vars() {
+	test_expect_success "$1: gitdir" '
+		test_cmp_val "'"$2"'" "$(git rev-parse --git-dir)"
+	'
+
+	test_expect_success "$1: worktree" '
+		test_cmp_val "'"$3"'" "$(git rev-parse --show-toplevel)"
+	'
+
+	test_expect_success "$1: prefix" '
+		test_cmp_val "'"$4"'" "$(git rev-parse --show-prefix)"
+	'
+}
+
+test_foobar_root() {
+	test_expect_success 'add relative' '
+		test -z "$(cd / && git ls-files)" &&
+		git add foo/foome &&
+		git add foo/bar/barme &&
+		git add me &&
+		( cd / && git ls-files --stage ) > result &&
+		test_cmp /ls.expected result &&
+		rm "$(git rev-parse --git-dir)/index"
+	'
+
+	test_expect_success 'add absolute' '
+		test -z "$(cd / && git ls-files)" &&
+		git add /foo/foome &&
+		git add /foo/bar/barme &&
+		git add /me &&
+		( cd / && git ls-files --stage ) > result &&
+		test_cmp /ls.expected result &&
+		rm "$(git rev-parse --git-dir)/index"
+	'
+
+}
+
+test_foobar_foo() {
+	test_expect_success 'add relative' '
+		test -z "$(cd / && git ls-files)" &&
+		git add foome &&
+		git add bar/barme &&
+		git add ../me &&
+		( cd / && git ls-files --stage ) > result &&
+		test_cmp /ls.expected result &&
+		rm "$(git rev-parse --git-dir)/index"
+	'
+
+	test_expect_success 'add absolute' '
+		test -z "$(cd / && git ls-files)" &&
+		git add /foo/foome &&
+		git add /foo/bar/barme &&
+		git add /me &&
+		( cd / && git ls-files --stage ) > result &&
+		test_cmp /ls.expected result &&
+		rm "$(git rev-parse --git-dir)/index"
+	'
+}
+
+test_foobar_foobar() {
+	test_expect_success 'add relative' '
+		test -z "$(cd / && git ls-files)" &&
+		git add ../foome &&
+		git add barme &&
+		git add ../../me &&
+		( cd / && git ls-files --stage ) > result &&
+		test_cmp /ls.expected result &&
+		rm "$(git rev-parse --git-dir)/index"
+	'
+
+	test_expect_success 'add absolute' '
+		test -z "$(cd / && git ls-files)" &&
+		git add /foo/foome &&
+		git add /foo/bar/barme &&
+		git add /me &&
+		( cd / && git ls-files --stage ) > result &&
+		test_cmp /ls.expected result &&
+		rm "$(git rev-parse --git-dir)/index"
+	'
+}
+
+if ! test_have_prereq POSIXPERM || ! [ -w / ]; then
+	say "Dangerous test skipped. Read this test if you want to execute it"
+	test_done
+fi
+
+if [ "$IKNOWWHATIAMDOING" != "YES" ]; then
+	say "You must set env var IKNOWWHATIAMDOING=YES in order to run this test"
+	test_done
+fi
+
+if [ "$UID" = 0 ]; then
+	say "No you can't run this with root"
+	test_done
+fi
+
+ONE_SHA1=d00491fd7e5bb6fa28c517a0bb32b8b506539d4d
+
+test_expect_success 'setup' '
+	rm -rf /foo
+	mkdir /foo &&
+	mkdir /foo/bar &&
+	echo 1 > /foo/foome &&
+	echo 1 > /foo/bar/barme &&
+	echo 1 > /me
+'
+
+say "GIT_DIR absolute, GIT_WORK_TREE set"
+
+test_expect_success 'go to /' 'cd /'
+
+cat >ls.expected <<EOF
+100644 $ONE_SHA1 0	foo/bar/barme
+100644 $ONE_SHA1 0	foo/foome
+100644 $ONE_SHA1 0	me
+EOF
+
+export GIT_DIR="$TRASH_DIRECTORY/.git"
+export GIT_WORK_TREE=/
+
+test_vars 'abs gitdir, root' "$GIT_DIR" "/" ""
+test_foobar_root
+
+test_expect_success 'go to /foo' 'cd /foo'
+
+test_vars 'abs gitdir, foo' "$GIT_DIR" "/" "foo/"
+test_foobar_foo
+
+test_expect_success 'go to /foo/bar' 'cd /foo/bar'
+
+test_vars 'abs gitdir, foo/bar' "$GIT_DIR" "/" "foo/bar/"
+test_foobar_foobar
+
+say "GIT_DIR relative, GIT_WORK_TREE set"
+
+test_expect_success 'go to /' 'cd /'
+
+export GIT_DIR="$(echo $TRASH_DIRECTORY|sed 's,^/,,')/.git"
+export GIT_WORK_TREE=/
+
+test_vars 'rel gitdir, root' "$GIT_DIR" "/" ""
+test_foobar_root
+
+test_expect_success 'go to /foo' 'cd /foo'
+
+export GIT_DIR="../$TRASH_DIRECTORY/.git"
+export GIT_WORK_TREE=/
+
+test_vars 'rel gitdir, foo' "$TRASH_DIRECTORY/.git" "/" "foo/"
+test_foobar_foo
+
+test_expect_success 'go to /foo/bar' 'cd /foo/bar'
+
+export GIT_DIR="../../$TRASH_DIRECTORY/.git"
+export GIT_WORK_TREE=/
+
+test_vars 'rel gitdir, foo/bar' "$TRASH_DIRECTORY/.git" "/" "foo/bar/"
+test_foobar_foobar
+
+say "GIT_DIR relative, GIT_WORK_TREE relative"
+
+test_expect_success 'go to /' 'cd /'
+
+export GIT_DIR="$(echo $TRASH_DIRECTORY|sed 's,^/,,')/.git"
+export GIT_WORK_TREE=.
+
+test_vars 'rel gitdir, root' "$GIT_DIR" "/" ""
+test_foobar_root
+
+test_expect_success 'go to /' 'cd /foo'
+
+export GIT_DIR="../$TRASH_DIRECTORY/.git"
+export GIT_WORK_TREE=..
+
+test_vars 'rel gitdir, foo' "$TRASH_DIRECTORY/.git" "/" "foo/"
+test_foobar_foo
+
+test_expect_success 'go to /foo/bar' 'cd /foo/bar'
+
+export GIT_DIR="../../$TRASH_DIRECTORY/.git"
+export GIT_WORK_TREE=../..
+
+test_vars 'rel gitdir, foo/bar' "$TRASH_DIRECTORY/.git" "/" "foo/bar/"
+test_foobar_foobar
+
+say ".git at root"
+
+unset GIT_DIR
+unset GIT_WORK_TREE
+
+test_expect_success 'go to /' 'cd /'
+test_expect_success 'setup' '
+	rm -rf /.git
+	echo "Initialized empty Git repository in /.git/" > expected &&
+	git init > result &&
+	test_cmp expected result
+'
+
+test_vars 'auto gitdir, root' ".git" "/" ""
+test_foobar_root
+
+test_expect_success 'go to /foo' 'cd /foo'
+test_vars 'auto gitdir, foo' "/.git" "/" "foo/"
+test_foobar_foo
+
+test_expect_success 'go to /foo/bar' 'cd /foo/bar'
+test_vars 'auto gitdir, foo/bar' "/.git" "/" "foo/bar/"
+test_foobar_foobar
+
+test_expect_success 'cleanup' 'rm -rf /.git'
+
+say "auto bare gitdir"
+
+# DESTROYYYYY!!!!!
+test_expect_success 'setup' '
+	rm -rf /refs /objects /info /hooks
+	rm /*
+	cd / &&
+	echo "Initialized empty Git repository in /" > expected &&
+	git init --bare > result &&
+	test_cmp expected result
+'
+
+test_vars 'auto gitdir, root' "." "" ""
+
+test_expect_success 'go to /foo' 'cd /foo'
+
+test_vars 'auto gitdir, root' "/" "" ""
+
+test_done
diff --git a/t/t1509/excludes b/t/t1509/excludes
new file mode 100644
index 0000000..d4d21d3
--- /dev/null
+++ b/t/t1509/excludes
@@ -0,0 +1,14 @@
+*.o
+*~
+*.bak
+*.c
+*.h
+.git
+contrib
+Documentation
+git-gui
+gitk-git
+gitweb
+t/t4013
+t/t5100
+t/t5515
diff --git a/t/t1509/prepare-chroot.sh b/t/t1509/prepare-chroot.sh
new file mode 100755
index 0000000..407f2d2
--- /dev/null
+++ b/t/t1509/prepare-chroot.sh
@@ -0,0 +1,38 @@
+#!/bin/sh
+
+die() {
+	echo >&2 "$@"
+	exit 1
+}
+
+xmkdir() {
+	while [ -n "$1" ]; do
+		[ -d "$1" ] || mkdir "$1" || die "Unable to mkdir $1"
+		shift
+	done
+}
+
+R="$1"
+
+[ -n "$R" ] || die "Usage: prepare-chroot.sh <root>"
+[ -x git ] || die "This script needs to be executed at git source code's top directory"
+[ -x /bin/busybox ] || die "You need busybox"
+
+xmkdir "$R" "$R/bin" "$R/etc" "$R/lib" "$R/dev"
+[ -c "$R/dev/null" ] || die "/dev/null is missing. Do mknod $R/dev/null c 1 3 && chmod 666 $R/dev/null"
+echo "root:x:0:0:root:/:/bin/sh" > "$R/etc/passwd"
+echo "$(id -nu):x:$(id -u):$(id -g)::$(pwd)/t:/bin/sh" >> "$R/etc/passwd"
+echo "root::0:root" > "$R/etc/group"
+echo "$(id -ng)::$(id -g):$(id -nu)" >> "$R/etc/group"
+
+[ -x "$R/bin/busybox" ] || cp /bin/busybox "$R/bin/busybox"
+[ -x "$R/bin/sh" ] || ln -s /bin/busybox "$R/bin/sh"
+[ -x "$R/bin/su" ] || ln -s /bin/busybox "$R/bin/su"
+
+mkdir -p "$R$(pwd)"
+rsync --exclude-from t/t1509/excludes -Ha . "$R$(pwd)"
+ldd git | grep '=> /' | sed 's,.* => *\([^ ]*\) .*,\1,' | while read i; do
+	mkdir -p "$R$(dirname $i)"
+	cp "$i" "$R/$i"
+done
+echo "Execute this in root: 'chroot $R /bin/su - $(id -nu)'"
-- 
1.7.0.rc2.182.g3adef

^ permalink raw reply related

* [PATCH 0/5 v2] Worktree/Gitdir at root directory
From: Nguyễn Thái Ngọc Duy @ 2010-02-11 14:43 UTC (permalink / raw)
  To: git, João Carlos Mendes Luís, Junio C Hamano,
	Johannes Sixt
  Cc: Nguyễn Thái Ngọc Duy

So here we go again. Changes are:

 - Support DOS drives as root path (Thanks Hannes)
 - Fix one "broken" test that I was too lazy to do last time
 - t1509-root-worktree.sh will refuse to run under root permission

I did not test it on Windows, so an Ack from someone who actually tests it on Windows
is really appreciated.

Nguyễn Thái Ngọc Duy (5):
  make_absolute_path(): Do not append redundant slash
  init-db, rev-parse --git-dir: do not append redundant slash
  Add is_root_path()
  Support working directory located at root
  Add test for using Git at root directory

 abspath.c                 |    5 +-
 builtin-init-db.c         |    9 +-
 builtin-rev-parse.c       |    4 +-
 git-compat-util.h         |   11 ++
 setup.c                   |   13 ++-
 t/t1509-root-worktree.sh  |  249 +++++++++++++++++++++++++++++++++++++++++++++
 t/t1509/excludes          |   14 +++
 t/t1509/prepare-chroot.sh |   38 +++++++
 8 files changed, 332 insertions(+), 11 deletions(-)
 create mode 100755 t/t1509-root-worktree.sh
 create mode 100644 t/t1509/excludes
 create mode 100755 t/t1509/prepare-chroot.sh

^ permalink raw reply

* [PATCH 1/5] make_absolute_path(): Do not append redundant slash
From: Nguyễn Thái Ngọc Duy @ 2010-02-11 14:43 UTC (permalink / raw)
  To: git, João Carlos Mendes Luís, Junio C Hamano,
	Johannes Sixt
  Cc: Nguyễn Thái Ngọc Duy
In-Reply-To: <1265899403-15904-1-git-send-email-pclouds@gmail.com>

When concatenating two paths, if the first one already have '/', do
not put another '/' in between the two paths.

Usually this is not the case as getcwd() won't return '/foo/bar/',
except when you are standing at root, then it will return '/'.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 abspath.c |    5 +++--
 1 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/abspath.c b/abspath.c
index b88122c..c91a29c 100644
--- a/abspath.c
+++ b/abspath.c
@@ -54,8 +54,9 @@ const char *make_absolute_path(const char *path)
 			if (len + strlen(last_elem) + 2 > PATH_MAX)
 				die ("Too long path name: '%s/%s'",
 						buf, last_elem);
-			buf[len] = '/';
-			strcpy(buf + len + 1, last_elem);
+			if (len && buf[len-1] != '/')
+				buf[len++] = '/';
+			strcpy(buf + len, last_elem);
 			free(last_elem);
 			last_elem = NULL;
 		}
-- 
1.7.0.rc2.182.g3adef

^ permalink raw reply related

* [PATCH 3/5] Add is_root_path()
From: Nguyễn Thái Ngọc Duy @ 2010-02-11 14:43 UTC (permalink / raw)
  To: git, João Carlos Mendes Luís, Junio C Hamano,
	Johannes Sixt
  Cc: Nguyễn Thái Ngọc Duy
In-Reply-To: <1265899403-15904-1-git-send-email-pclouds@gmail.com>

This function returns the length of the root part of a path, or zero if
there is no root.

"The root part" is the leading slash on Linux/Unix, or 'C:/' on Windows.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 ... and can be extended to recognize "//machine/share/" as a root part?

 git-compat-util.h |   11 +++++++++++
 1 files changed, 11 insertions(+), 0 deletions(-)

diff --git a/git-compat-util.h b/git-compat-util.h
index a3c4537..4d0398d 100644
--- a/git-compat-util.h
+++ b/git-compat-util.h
@@ -210,6 +210,17 @@ static inline const char *skip_prefix(const char *str, const char *prefix)
 	return strncmp(str, prefix, len) ? NULL : str + len;
 }
 
+/* path must be canonical */
+static inline int is_root_path(const char *path)
+{
+	int len = 0;
+	if (has_dos_drive_prefix(path))
+		len += 2;
+	if (is_dir_sep(path[len]))
+		len++;
+	return len;
+}
+
 #if defined(NO_MMAP) || defined(USE_WIN32_MMAP)
 
 #ifndef PROT_READ
-- 
1.7.0.rc2.182.g3adef

^ permalink raw reply related

* [PATCH 4/5] Support working directory located at root
From: Nguyễn Thái Ngọc Duy @ 2010-02-11 14:43 UTC (permalink / raw)
  To: git, João Carlos Mendes Luís, Junio C Hamano,
	Johannes Sixt
  Cc: Nguyễn Thái Ngọc Duy
In-Reply-To: <1265899403-15904-1-git-send-email-pclouds@gmail.com>

Git should work regardless where the working directory is located,
even at root. This patch fixes two places where it assumes working
directory always have parent directory.

In setup_git_directory_gently(), when Git goes up to root and finds
.git there, it happily sets worktree to "" instead of "/".

In prefix_path(), loosen the outside repo check a little bit. Usually
when a path XXX is inside worktree /foo, it must be either "/foo", or
"/foo/...". When worktree is simply "/", we can safely ignore the
check: we have a slash at the beginning already.

Not related to worktree, but also set gitdir correctly if a bare repo
is placed (insanely?) at root.

Thanks João Carlos Mendes Luís for pointing out this problem.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 setup.c |   13 ++++++++-----
 1 files changed, 8 insertions(+), 5 deletions(-)

diff --git a/setup.c b/setup.c
index b38cbee..cdad176 100644
--- a/setup.c
+++ b/setup.c
@@ -18,14 +18,15 @@ const char *prefix_path(const char *prefix, int len, const char *path)
 	if (normalize_path_copy(sanitized, sanitized))
 		goto error_out;
 	if (is_absolute_path(orig)) {
-		size_t len, total;
+		size_t root_len, len, total;
 		const char *work_tree = get_git_work_tree();
 		if (!work_tree)
 			goto error_out;
 		len = strlen(work_tree);
+		root_len = is_root_path(work_tree);
 		total = strlen(sanitized) + 1;
 		if (strncmp(sanitized, work_tree, len) ||
-		    (sanitized[len] != '\0' && sanitized[len] != '/')) {
+		    (len > root_len && sanitized[len] != '\0' && sanitized[len] != '/')) {
 		error_out:
 			die("'%s' is outside repository", orig);
 		}
@@ -321,7 +322,7 @@ const char *setup_git_directory_gently(int *nongit_ok)
 	static char cwd[PATH_MAX+1];
 	const char *gitdirenv;
 	const char *gitfile_dir;
-	int len, offset, ceil_offset;
+	int len, offset, ceil_offset, root_len;
 
 	/*
 	 * Let's assume that we are in a git repository.
@@ -403,7 +404,8 @@ const char *setup_git_directory_gently(int *nongit_ok)
 			if (!work_tree_env)
 				inside_work_tree = 0;
 			if (offset != len) {
-				cwd[offset] = '\0';
+				root_len = is_root_path(cwd);
+				cwd[offset > root_len ? offset : root_len] = '\0';
 				set_git_dir(cwd);
 			} else
 				set_git_dir(".");
@@ -427,7 +429,8 @@ const char *setup_git_directory_gently(int *nongit_ok)
 	inside_git_dir = 0;
 	if (!work_tree_env)
 		inside_work_tree = 1;
-	git_work_tree_cfg = xstrndup(cwd, offset);
+	root_len = is_root_path(cwd);
+	git_work_tree_cfg = xstrndup(cwd, offset > root_len ? offset : root_len);
 	if (check_repository_format_gently(nongit_ok))
 		return NULL;
 	if (offset == len)
-- 
1.7.0.rc2.182.g3adef

^ permalink raw reply related

* Re: [PATCH v2 1/2] git-imap-send: Add CRAM-MD5 authenticate method  support
From: Erik Faye-Lund @ 2010-02-11 14:55 UTC (permalink / raw)
  To: Hitoshi Mitake; +Cc: gitster, git, Jakub Narebski, Linus Torvalds, Jeff King
In-Reply-To: <1265899135-11488-1-git-send-email-mitake@dcl.info.waseda.ac.jp>

On Thu, Feb 11, 2010 at 3:38 PM, Hitoshi Mitake
<mitake@dcl.info.waseda.ac.jp> wrote:
> @@ -1101,6 +1190,7 @@ static struct store *imap_open_store(struct imap_server_conf *srvc)
>                }
>  #endif
>                imap_info("Logging in...\n");
> +
>                if (!srvc->user) {
>                        fprintf(stderr, "Skipping server %s, no user\n", srvc->host);
>                        goto bail;
> @@ -1258,6 +1375,7 @@ static int read_message(FILE *f, struct msg_data *msg)
>
>        msg->len  = buf.len;
>        msg->data = strbuf_detach(&buf, NULL);
> +
>        return msg->len;
>  }
>
> @@ -1307,21 +1425,10 @@ static int split_msg(struct msg_data *all_msgs, struct msg_data *msg, int *ofs)
>
>        msg->data = xmemdupz(data, msg->len);
>        *ofs += msg->len;
> +
>        return 1;
>  }
>

There's not much point in having three hunks with a single added
newline in each...


-- 
Erik "kusma" Faye-Lund

^ permalink raw reply

* Re: [PATCH 3/4] git-imap-send: Implement CRAM-MD5 auth method
From: Hitoshi Mitake @ 2010-02-11 14:55 UTC (permalink / raw)
  To: kusmabite; +Cc: Erik Faye-Lund, gitster, git, Jeremy White, Robert Shearman
In-Reply-To: <40aa078e1002090622vb65027xa53acff95557a183@mail.gmail.com>

(2010年02月09日 23:22), Erik Faye-Lund wrote:
> On Tue, Feb 9, 2010 at 1:09 PM, Hitoshi Mitake
> <mitake@dcl.info.waseda.ac.jp>  wrote:
>> +static int auth_cram_md5(struct imap_store *ctx, struct imap_cmd *cmd, const char *prompt)
>> +{
>> +       int ret;
>> +       char digest[DIGEST_HEX_LEN];
>> +       char buf[256], base64_out[256];
>> +
>> +       memset(buf, 0, 256);
>> +       base64_decode(buf, prompt, strlen(prompt));
>> +
>> +       memset(digest, 0, DIGEST_HEX_LEN);
>> +       md5_hex_hmac(digest, (const unsigned char *)buf, strlen(buf),
>> +                    (const unsigned char *)server.pass, strlen(server.pass));
>> +
>> +       memset(buf, 0, 256);
>> +       strcpy(buf, server.user);
>> +       strcpy(buf + strlen(buf), " ");
>> +       strcpy(buf + strlen(buf), digest);
>> +       memset(base64_out, 0, 256);
>> +       base64_encode(base64_out, buf, strlen(buf));
>> +
>> +       ret = socket_write(&ctx->imap->buf.sock, base64_out, strlen(base64_out));
>
> Since this is the only location in this function that accesses
> anything inside ctx, how about just passing the imap_socket itself to
> the function? That'd make it a bit simpler if, say, I was rewriting
> send-email in C and wanted to add CRAM-MD5 AUTH support (given that
> I'd done the work to use imap_socket first)...
>

Do you mean that
  auth_cram_md5(struct imap_store *ctx, struct imap_cmd *cmd, const char 
*prompt)
should be,
  auth_cram_md5(struct imap_socket *socket, struct imap_cmd *cmd, const 
char *prompt)
  ?

If this improves portability of cram-md5 auth, of course I agree.
But struct imap_socket is defined in imap-send.c yet.

If you want to separate imap-send.c and cram-md5 auth for 
git-send-email, I'll cooperate :)

^ permalink raw reply

* Re: [PATCH 3/4] git-imap-send: Implement CRAM-MD5 auth method
From: Erik Faye-Lund @ 2010-02-11 14:59 UTC (permalink / raw)
  To: Hitoshi Mitake; +Cc: gitster, git, Jeremy White, Robert Shearman
In-Reply-To: <4B741A44.7060003@dcl.info.waseda.ac.jp>

On Thu, Feb 11, 2010 at 3:55 PM, Hitoshi Mitake
<mitake@dcl.info.waseda.ac.jp> wrote:
> (2010年02月09日 23:22), Erik Faye-Lund wrote:
>>
>> On Tue, Feb 9, 2010 at 1:09 PM, Hitoshi Mitake
>> <mitake@dcl.info.waseda.ac.jp>  wrote:
>>>
>>> +static int auth_cram_md5(struct imap_store *ctx, struct imap_cmd *cmd,
>>> const char *prompt)
>>> +{
>>> +       int ret;
>>> +       char digest[DIGEST_HEX_LEN];
>>> +       char buf[256], base64_out[256];
>>> +
>>> +       memset(buf, 0, 256);
>>> +       base64_decode(buf, prompt, strlen(prompt));
>>> +
>>> +       memset(digest, 0, DIGEST_HEX_LEN);
>>> +       md5_hex_hmac(digest, (const unsigned char *)buf, strlen(buf),
>>> +                    (const unsigned char *)server.pass,
>>> strlen(server.pass));
>>> +
>>> +       memset(buf, 0, 256);
>>> +       strcpy(buf, server.user);
>>> +       strcpy(buf + strlen(buf), " ");
>>> +       strcpy(buf + strlen(buf), digest);
>>> +       memset(base64_out, 0, 256);
>>> +       base64_encode(base64_out, buf, strlen(buf));
>>> +
>>> +       ret = socket_write(&ctx->imap->buf.sock, base64_out,
>>> strlen(base64_out));
>>
>> Since this is the only location in this function that accesses
>> anything inside ctx, how about just passing the imap_socket itself to
>> the function? That'd make it a bit simpler if, say, I was rewriting
>> send-email in C and wanted to add CRAM-MD5 AUTH support (given that
>> I'd done the work to use imap_socket first)...
>>
>
> Do you mean that
>  auth_cram_md5(struct imap_store *ctx, struct imap_cmd *cmd, const char
> *prompt)
> should be,
>  auth_cram_md5(struct imap_socket *socket, struct imap_cmd *cmd, const char
> *prompt)
>  ?
>
> If this improves portability of cram-md5 auth, of course I agree.
> But struct imap_socket is defined in imap-send.c yet.
>

Yes, it's what I meant. It's only a minor nit-pick, as some
refactoring would have to be done anyway. But I think it'd be a good
change to only pull in the state needed, but that's my personal
opinion.

> If you want to separate imap-send.c and cram-md5 auth for git-send-email,
> I'll cooperate :)
>

Not at this point, if ever. I'm fine with you not doing anything about
my comment. I was merely thinking out loud... ;)

-- 
Erik "kusma" Faye-Lund

^ permalink raw reply

* Re: [PATCH v2 1/2] git-imap-send: Add CRAM-MD5 authenticate method support
From: Hitoshi Mitake @ 2010-02-11 14:59 UTC (permalink / raw)
  To: kusmabite
  Cc: Erik Faye-Lund, gitster, git, Jakub Narebski, Linus Torvalds,
	Jeff King
In-Reply-To: <40aa078e1002110655n120b14b9y242a57d0e1bd3e96@mail.gmail.com>

(2010年02月11日 23:55), Erik Faye-Lund wrote:
> On Thu, Feb 11, 2010 at 3:38 PM, Hitoshi Mitake
> <mitake@dcl.info.waseda.ac.jp>  wrote:
>> @@ -1101,6 +1190,7 @@ static struct store *imap_open_store(struct imap_server_conf *srvc)
>>                 }
>>   #endif
>>                 imap_info("Logging in...\n");
>> +
>>                 if (!srvc->user) {
>>                         fprintf(stderr, "Skipping server %s, no user\n", srvc->host);
>>                         goto bail;
>> @@ -1258,6 +1375,7 @@ static int read_message(FILE *f, struct msg_data *msg)
>>
>>         msg->len  = buf.len;
>>         msg->data = strbuf_detach(&buf, NULL);
>> +
>>         return msg->len;
>>   }
>>
>> @@ -1307,21 +1425,10 @@ static int split_msg(struct msg_data *all_msgs, struct msg_data *msg, int *ofs)
>>
>>         msg->data = xmemdupz(data, msg->len);
>>         *ofs += msg->len;
>> +
>>         return 1;
>>   }
>>
>
> There's not much point in having three hunks with a single added
> newline in each...
>
>

grr.. sorry, it is completely my mistake.
I'll send v3 later.

^ permalink raw reply

* Re: [PATCH 8/6 v2] receive-pack: Send internal errors over side-band #2
From: Shawn O. Pearce @ 2010-02-11 15:05 UTC (permalink / raw)
  To: Johannes Sixt; +Cc: Junio C Hamano, git
In-Reply-To: <4B73C0FF.5020503@viscovery.net>

Johannes Sixt <j.sixt@viscovery.net> wrote:
> Shawn O. Pearce schrieb:
>> +static void report_message(const char *prefix, const char *err, va_list params)
>> +{
>> +	int sz = strlen(prefix);
>> +	char msg[4096];
>> +
>> +	strncpy(msg, prefix, sz);
>> +	sz += vsnprintf(msg + sz, sizeof(msg) - sz, err, params);
>> +	if (sz > (sizeof(msg) - 1))
>> +		sz = sizeof(msg) - 1;
>> +	msg[sz++] = '\n';
>
> Sorry, still no joy - the terminating NUL is missing (I should have  
> noticed this in your v1 already).

Why is it necessary?

Once the msg buffer is prepared, its written using its length, sz,
not its NUL termination status.  Neither send_sideband() nor xwrite()
care about NUL termination.

The only reason to put a NUL onto this buffer is so you can do
"p msg" within GDB and get a useful result.  We don't typically do
this in these contexts.

Or did my MTA inject additional C code I didn't write?

> I suggest to forgo the length check for 
> simplicity because this function is only called with data that is already 
> guaranteed to be less than 1000 bytes, i.e.:
>
> 	strncpy(msg, prefix, sz);
> 	/* data is guaranteed to fit due to packet length limit in  
> read_head_info() */

Yea, that's true now.  We probably could have used 1200 bytes for
the msg buffer, rather than 4096.  Even the huge warnings about
current branch behavior are broken up into one string per line.

-- 
Shawn.

^ permalink raw reply

* [PATCH v3 1/2] git-imap-send: Add CRAM-MD5 authenticate method support
From: Hitoshi Mitake @ 2010-02-11 15:06 UTC (permalink / raw)
  To: gitster
  Cc: git, Hitoshi Mitake, Erik Faye-Lund, Jakub Narebski,
	Linus Torvalds, Jeff King
In-Reply-To: <40aa078e1002110655n120b14b9y242a57d0e1bd3e96@mail.gmail.com>

This patch makes git-imap-send CRAM-MD5 authenticate method ready.
In theory, CRAM-MD5 authenticate method doesn't depend on SSL,
but for easy of maintainance, this patch uses base64 and md5 stuffs of OpenSSL.
So if you want to use CRAM-MD5 authenticate method,
you have to build git-imap-send with OpenSSL library.

v3: Erik's noticed that there were some garbage lines in this patch.
I removed these. And 2/2 wasn't changed, I'm sending 1/2 only.

Cc: Erik Faye-Lund <kusmabite@googlemail.com>
Cc: Jakub Narebski <jnareb@gmail.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Jeff King <peff@peff.net>
Signed-off-by: Hitoshi Mitake <mitake@dcl.info.waseda.ac.jp>
---
 Documentation/git-imap-send.txt |    4 +
 imap-send.c                     |  141 ++++++++++++++++++++++++++++++++++-----
 2 files changed, 128 insertions(+), 17 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..caa4e1b 100644
--- a/imap-send.c
+++ b/imap-send.c
@@ -25,10 +25,16 @@
 #include "cache.h"
 #include "exec_cmd.h"
 #include "run-command.h"
+
 #ifdef NO_OPENSSL
 typedef void *SSL;
+#else
+#include <openssl/evp.h>
+#include <openssl/hmac.h>
 #endif
 
+static int login;
+
 struct store_conf {
 	char *name;
 	const char *path; /* should this be here? its interpretation is driver-specific */
@@ -140,6 +146,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 +234,7 @@ enum CAPABILITY {
 	LITERALPLUS,
 	NAMESPACE,
 	STARTTLS,
+	AUTH_CRAM_MD5,
 };
 
 static const char *cap_list[] = {
@@ -222,6 +243,7 @@ static const char *cap_list[] = {
 	"LITERAL+",
 	"NAMESPACE",
 	"STARTTLS",
+	"AUTH=CRAM-MD5",
 };
 
 #define RESP_OK    0
@@ -526,8 +548,9 @@ static struct imap_cmd *v_issue_imap_cmd(struct imap_store *ctx,
 		get_cmd_result(ctx, NULL);
 
 	bufl = nfsnprintf(buf, sizeof(buf), cmd->cb.data ? CAP(LITERALPLUS) ?
-			   "%d %s{%d+}\r\n" : "%d %s{%d}\r\n" : "%d %s\r\n",
-			   cmd->tag, cmd->cmd, cmd->cb.dlen);
+			  "%d %s{%d+}\r\n" : "%d %s{%d}\r\n" : "%d %s\r\n",
+			  cmd->tag, cmd->cmd, cmd->cb.dlen);
+
 	if (Verbose) {
 		if (imap->num_in_progress)
 			printf("(%d in progress) ", imap->num_in_progress);
@@ -949,6 +972,72 @@ static void imap_close_store(struct store *ctx)
 	free(ctx);
 }
 
+/*
+ * hexchar() and cram() functions are
+ * based on ones of isync project ... http://isync.sf.net/
+ * Thanks!
+ */
+static char hexchar(unsigned int b)
+{
+	return b < 10 ? '0' + b : 'a' + (b - 10);
+}
+
+#ifndef NO_OPENSSL
+
+static char *cram(const char *challenge_64, const char *user, const char *pass)
+{
+	int i;
+	HMAC_CTX hmac;
+	char hash[16], hex[33], challenge[256], response[256];
+	char *response_64;
+
+	memset(challenge, 0, 256);
+	EVP_DecodeBlock((unsigned char *)challenge, (unsigned char *)challenge_64, strlen(challenge_64));
+	HMAC_Init(&hmac, (unsigned char *)pass, strlen(pass), EVP_md5());
+	HMAC_Update(&hmac, (unsigned char *)challenge, strlen(challenge));
+	HMAC_Final(&hmac, (unsigned char *)hash, NULL);
+
+	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);
+	}
+
+	memset(response, 0, 256);
+	snprintf(response, 256, "%s %s", user, hex);
+
+	response_64 = calloc(256 , sizeof(char));
+	EVP_EncodeBlock((unsigned char *)response_64, (unsigned char *)response, strlen(response));
+	return response_64;
+}
+
+#else
+
+static char *cram(const char *challenge_64 __used, const char *user __used, const char *pass __used)
+{
+	fprintf(stderr, "If you want to use CRAM-MD5 authenticate method,"
+		"you have to build git-imap-send with OpenSSL library\n");
+	exit(0);
+}
+
+#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)) {
+		fprintf(stderr, "IMAP error: sending response failed\n");
+		return -1;
+	}
+	free(response);
+
+	return 0;
+}
+
 static struct store *imap_open_store(struct imap_server_conf *srvc)
 {
 	struct imap_store *ctx;
@@ -1130,10 +1219,37 @@ 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;
+				}
+				login = 1;
+			} else {
+				fprintf(stderr, "Unknown authentication method:%s\n", srvc->host);
+				goto bail;
+			}
 		}
+
+		if (!login)
+			if (imap_exec(ctx, NULL, "LOGIN \"%s\" \"%s\"", srvc->user, srvc->pass) != RESP_OK) {
+				fprintf(stderr, "IMAP error: LOGIN failed\n");
+				goto bail;
+			}
 	} /* !preauth */
 
 	ctx->prefix = "";
@@ -1310,18 +1426,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 +1465,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;
 }
 
-- 
1.6.5.2

^ permalink raw reply related

* Re: [PATCH 3/4] git-imap-send: Implement CRAM-MD5 auth method
From: Hitoshi Mitake @ 2010-02-11 15:11 UTC (permalink / raw)
  To: kusmabite; +Cc: Erik Faye-Lund, gitster, git, Jeremy White, Robert Shearman
In-Reply-To: <40aa078e1002110659y9493052l3752c7e0afb6eb3c@mail.gmail.com>

(2010年02月11日 23:59), Erik Faye-Lund wrote:
> On Thu, Feb 11, 2010 at 3:55 PM, Hitoshi Mitake
> <mitake@dcl.info.waseda.ac.jp>  wrote:
>> (2010年02月09日 23:22), Erik Faye-Lund wrote:
>>>
>>> On Tue, Feb 9, 2010 at 1:09 PM, Hitoshi Mitake
>>> <mitake@dcl.info.waseda.ac.jp>    wrote:
>>>>
>>>> +static int auth_cram_md5(struct imap_store *ctx, struct imap_cmd *cmd,
>>>> const char *prompt)
>>>> +{
>>>> +       int ret;
>>>> +       char digest[DIGEST_HEX_LEN];
>>>> +       char buf[256], base64_out[256];
>>>> +
>>>> +       memset(buf, 0, 256);
>>>> +       base64_decode(buf, prompt, strlen(prompt));
>>>> +
>>>> +       memset(digest, 0, DIGEST_HEX_LEN);
>>>> +       md5_hex_hmac(digest, (const unsigned char *)buf, strlen(buf),
>>>> +                    (const unsigned char *)server.pass,
>>>> strlen(server.pass));
>>>> +
>>>> +       memset(buf, 0, 256);
>>>> +       strcpy(buf, server.user);
>>>> +       strcpy(buf + strlen(buf), " ");
>>>> +       strcpy(buf + strlen(buf), digest);
>>>> +       memset(base64_out, 0, 256);
>>>> +       base64_encode(base64_out, buf, strlen(buf));
>>>> +
>>>> +       ret = socket_write(&ctx->imap->buf.sock, base64_out,
>>>> strlen(base64_out));
>>>
>>> Since this is the only location in this function that accesses
>>> anything inside ctx, how about just passing the imap_socket itself to
>>> the function? That'd make it a bit simpler if, say, I was rewriting
>>> send-email in C and wanted to add CRAM-MD5 AUTH support (given that
>>> I'd done the work to use imap_socket first)...
>>>
>>
>> Do you mean that
>>   auth_cram_md5(struct imap_store *ctx, struct imap_cmd *cmd, const char
>> *prompt)
>> should be,
>>   auth_cram_md5(struct imap_socket *socket, struct imap_cmd *cmd, const char
>> *prompt)
>>   ?
>>
>> If this improves portability of cram-md5 auth, of course I agree.
>> But struct imap_socket is defined in imap-send.c yet.
>>
>
> Yes, it's what I meant. It's only a minor nit-pick, as some
> refactoring would have to be done anyway. But I think it'd be a good
> change to only pull in the state needed, but that's my personal
> opinion.

My latest patch doesn't change the point.
Because auth_cram_md5() is a call back, so changing type of it
needs some works...

>
>> If you want to separate imap-send.c and cram-md5 auth for git-send-email,
>> I'll cooperate :)
>>
>
> Not at this point, if ever. I'm fine with you not doing anything about
> my comment. I was merely thinking out loud... ;)
>

I'm looking forward to using your new git-send-email.
I'm also a heavy user of it :)

^ permalink raw reply

* Separate default push/pull?
From: David Abrahams @ 2010-02-11 16:36 UTC (permalink / raw)
  To: git


If I am collaborating mostly with one other person, I typically want to
pull from his publicly-readable repo and push to mine (on which I have
write permission).  Is there any way to set things up so “git pull” and
“git push” without additional arguments will do this by default?

Thanks,

-- 
Dave Abrahams           Meet me at BoostCon: http://www.boostcon.com
BoostPro Computing
http://www.boostpro.com

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox