Index: configure.ac
===================================================================
RCS file: /cvsroot/curl/curl/configure.ac,v
retrieving revision 1.241
diff -u -r1.241 configure.ac
--- configure.ac	22 Apr 2007 09:37:05 -0000	1.241
+++ configure.ac	24 Apr 2007 11:26:48 -0000
@@ -1069,12 +1069,14 @@
 
     dnl these can only exist if openssl exists
     dnl yassl doesn't have SSL_get_shutdown
+    dnl HMAC_CTX_init was added in OpenSSL 0.9.7
 
     AC_CHECK_FUNCS( RAND_status \
                     RAND_screen \
                     RAND_egd \
                     CRYPTO_cleanup_all_ex_data \
-                    SSL_get_shutdown )
+                    SSL_get_shutdown \
+                    HMAC_CTX_init )
 
     dnl Make an attempt to detect if this is actually yassl's headers and
     dnl OpenSSL emulation layer. We still leave everything else believing
Index: curl-config.in
===================================================================
RCS file: /cvsroot/curl/curl/curl-config.in,v
retrieving revision 1.28
diff -u -r1.28 curl-config.in
--- curl-config.in	17 Feb 2007 17:55:19 -0000	1.28
+++ curl-config.in	24 Apr 2007 11:26:48 -0000
@@ -82,6 +82,7 @@
 	if test "@USE_SSLEAY@" = "1"; then
           echo "SSL"
           NTLM=1 # OpenSSL implies NTLM
+	  AWSAUTH=1 # OpenSSL implies AWS Auth
         elif test -n "@USE_GNUTLS@"; then
           echo "SSL"
         fi
@@ -107,6 +108,9 @@
 	if test "$NTLM" = "1"; then
           echo "NTLM"
         fi
+	if test "$AWSAUTH" = "1"; then
+          echo "AWSAUTH"
+        fi
 	;;
 
     --protocols)
Index: docs/FEATURES
===================================================================
RCS file: /cvsroot/curl/curl/docs/FEATURES,v
retrieving revision 1.20
diff -u -r1.20 FEATURES
--- docs/FEATURES	12 Feb 2007 22:32:37 -0000	1.20
+++ docs/FEATURES	24 Apr 2007 11:26:48 -0000
@@ -42,7 +42,7 @@
  - POST
  - multipart formpost (RFC1867-style)
  - authentication: Basic, Digest, NTLM(*1), GSS-Negotiate/Negotiate(*3) and
-   SPNEGO (*4) to server and proxy
+   SPNEGO (*4) to server and proxy, and AWSAUTH(*1)
  - resume (both GET and PUT)
  - follow redirects
  - maximum amount of redirects to follow
Index: docs/MANUAL
===================================================================
RCS file: /cvsroot/curl/curl/docs/MANUAL,v
retrieving revision 1.36
diff -u -r1.36 MANUAL
--- docs/MANUAL	29 Mar 2007 20:44:06 -0000	1.36
+++ docs/MANUAL	24 Apr 2007 11:26:48 -0000
@@ -98,10 +98,10 @@
         curl -u name:passwd http://machine.domain/full/path/to/file
 
    HTTP offers many different methods of authentication and curl supports
-   several: Basic, Digest, NTLM and Negotiate. Without telling which method to
-   use, curl defaults to Basic. You can also ask curl to pick the most secure
-   ones out of the ones that the server accepts for the given URL, by using
-   --anyauth.
+   several: Basic, Digest, NTLM, Amazon Web Service, and Negotiate. Without
+   telling which method to use, curl defaults to Basic. You can also ask
+   curl to pick the most secure ones out of the ones that the server accepts
+   for the given URL, by using --anyauth.
 
    NOTE! Since HTTP URLs don't support user and password, you can't use that
    style when using Curl via a proxy. You _must_ use the -u style fetch
Index: docs/TheArtOfHttpScripting
===================================================================
RCS file: /cvsroot/curl/curl/docs/TheArtOfHttpScripting,v
retrieving revision 1.10
diff -u -r1.10 TheArtOfHttpScripting
--- docs/TheArtOfHttpScripting	29 Jan 2005 13:54:15 -0000	1.10
+++ docs/TheArtOfHttpScripting	24 Apr 2007 11:26:48 -0000
@@ -216,8 +216,8 @@
         curl -u name:password www.secrets.com
 
  The site might require a different authentication method (check the headers
- returned by the server), and then --ntlm, --digest, --negotiate or even
- --anyauth might be options that suit you.
+ returned by the server), and then --ntlm, --awsauth, --digest, --negotiate or
+ even --anyauth might be options that suit you.
  
  Sometimes your HTTP access is only available through the use of a HTTP
  proxy. This seems to be especially common at various companies. A HTTP proxy
Index: docs/curl.1
===================================================================
RCS file: /cvsroot/curl/curl/docs/curl.1,v
retrieving revision 1.212
diff -u -r1.212 curl.1
--- docs/curl.1	22 Apr 2007 09:31:27 -0000	1.212
+++ docs/curl.1	24 Apr 2007 11:26:48 -0000
@@ -117,8 +117,8 @@
 most secure one the remote site claims it supports. This is done by first
 doing a request and checking the response-headers, thus inducing an extra
 network round-trip. This is used instead of setting a specific authentication
-method, which you can do with \fI--basic\fP, \fI--digest\fP, \fI--ntlm\fP, and
-\fI--negotiate\fP.
+method, which you can do with \fI--basic\fP, \fI--digest\fP, \fI--ntlm\fP,
+\fI--awsauth\fP, and \fI--negotiate\fP.
 
 Note that using --anyauth is not recommended if you do uploads from stdin,
 since it may require data to be sent twice and then the client must be able to
@@ -158,7 +158,7 @@
 (HTTP) Tells curl to use HTTP Basic authentication. This is the default and
 this option is usually pointless, unless you use it to override a previously
 set option that sets a different authentication method (such as \fI--ntlm\fP,
-\fI--digest\fP and \fI--negotiate\fP).
+\fI--awsauth\fP, \fI--digest\fP and \fI--negotiate\fP).
 
 If this option is used several times, the following occurrences make no
 difference.
@@ -264,8 +264,8 @@
 (HTTP) Enables HTTP Digest authentication. This is a authentication that
 prevents the password from being sent over the wire in clear text. Use this in
 combination with the normal \fI-u/--user\fP option to set user name and
-password. See also \fI--ntlm\fP, \fI--negotiate\fP and \fI--anyauth\fP for
-related options.
+password. See also \fI--ntlm\fP, \fI--awsauth\fP, \fI--negotiate\fP and
+\fI--anyauth\fP for related options.
 
 If this option is used several times, the following occurrences make no
 difference.
@@ -805,6 +805,20 @@
 
 If this option is used several times, the following occurrences make no
 difference.
+.IP "--awsauth"
+(HTTP) Enables Amazon Web Services authentication.
+
+Use this in combination with the normal \fI-u/--user\fP option to set
+user name and password.  The user name is the AWS Access Key ID and
+the password is the AWS Access Key Secret.  If the \fI-u/--user\fP
+parameter is set to ':', the id and secret are taken from the environment
+variables AWS_ACCESS_KEY_ID and AWS_ACCESS_KEY_SECRET.
+
+This option requires that the library was built with SSL support. Use
+\fI-V/--version\fP to see if your curl supports AWSAUTH.
+
+If this option is used several times, the following occurrences make no
+difference.
 .IP "-o/--output <file>"
 Write output to <file> instead of stdout. If you are using {} or [] to fetch
 multiple documents, you can use '#' followed by a number in the <file>
@@ -1095,6 +1109,11 @@
 force curl to pick up the user name and password from your environment by
 simply specifying a single colon with this option: "-u :".
 
+If you do AWSAUTH authentication, you can force curl to pick up the user
+name and password from the environment variables AWS_ACCESS_KEY_ID and
+AWS_ACCESS_KEY_SECRET by simply specifying a single colon with this
+option: "-u :".
+
 If this option is used several times, the last one will be used.
 .IP "-U/--proxy-user <user:password>"
 Specify user and password to use for proxy authentication.
@@ -1147,6 +1166,8 @@
 Automatic decompression of compressed files over HTTP is supported.
 .IP "NTLM"
 NTLM authentication is supported.
+.IP "AWSAUTH"
+Amazon Web Service authentication is supported.
 .IP "GSS-Negotiate"
 Negotiate authentication is supported.
 .IP "Debug"
Index: docs/libcurl/curl_easy_setopt.3
===================================================================
RCS file: /cvsroot/curl/curl/docs/libcurl/curl_easy_setopt.3,v
retrieving revision 1.176
diff -u -r1.176 curl_easy_setopt.3
--- docs/libcurl/curl_easy_setopt.3	23 Mar 2007 17:59:40 -0000	1.176
+++ docs/libcurl/curl_easy_setopt.3	24 Apr 2007 11:26:48 -0000
@@ -556,6 +556,12 @@
 
 You need to build libcurl with OpenSSL support for this option to work, or
 build libcurl on Windows.
+.IP CURLAUTH_AWSAUTH
+HTTP AWS AUTH authentication. A proprietary protocol invented and used by
+Amazon for Amazon Web Services such as S3. It uses a shared secret and a HMAC
+to prevent the secret from being eavesdropped.
+
+You need to build libcurl with OpenSSL support for this option to work.
 .IP CURLAUTH_ANY
 This is a convenience macro that sets all bits and thus makes libcurl pick any
 it finds suitable. libcurl will automatically select the one it finds most
Index: docs/libcurl/curl_version_info.3
===================================================================
RCS file: /cvsroot/curl/curl/docs/libcurl/curl_version_info.3,v
retrieving revision 1.11
diff -u -r1.11 curl_version_info.3
--- docs/libcurl/curl_version_info.3	2 Nov 2006 21:56:43 -0000	1.11
+++ docs/libcurl/curl_version_info.3	24 Apr 2007 11:26:48 -0000
@@ -102,6 +102,8 @@
 supports HTTP deflate using libz (Added in 7.10)
 .IP CURL_VERSION_NTLM
 supports HTTP NTLM (added in 7.10.6)
+.IP CURL_VERSION_AWSAUTH
+supports HTTP Amazon Web Services auth
 .IP CURL_VERSION_GSSNEGOTIATE
 supports HTTP GSS-Negotiate (added in 7.10.6)
 .IP CURL_VERSION_DEBUG
Index: docs/libcurl/libcurl-tutorial.3
===================================================================
RCS file: /cvsroot/curl/curl/docs/libcurl/libcurl-tutorial.3,v
retrieving revision 1.13
diff -u -r1.13 libcurl-tutorial.3
--- docs/libcurl/libcurl-tutorial.3	27 Feb 2007 12:44:14 -0000	1.13
+++ docs/libcurl/libcurl-tutorial.3	24 Apr 2007 11:26:48 -0000
@@ -426,8 +426,8 @@
 password in clear-text in the HTTP request, base64-encoded. This is insecure.
 
 At the time of this writing libcurl can be built to use: Basic, Digest, NTLM,
-Negotiate, GSS-Negotiate and SPNEGO. You can tell libcurl which one to use
-with CURLOPT_HTTPAUTH as in:
+AWSAUTH, Negotiate, GSS-Negotiate and SPNEGO. You can tell libcurl which one
+to use with CURLOPT_HTTPAUTH as in:
 
  curl_easy_setopt(easyhandle, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST);
 
Index: docs/libcurl/libcurl.m4
===================================================================
RCS file: /cvsroot/curl/curl/docs/libcurl/libcurl.m4,v
retrieving revision 1.6
diff -u -r1.6 libcurl.m4
--- docs/libcurl/libcurl.m4	19 Feb 2007 12:37:04 -0000	1.6
+++ docs/libcurl/libcurl.m4	24 Apr 2007 11:26:48 -0000
@@ -45,6 +45,7 @@
   AH_TEMPLATE([LIBCURL_FEATURE_IDN],[Defined if libcurl supports IDN])
   AH_TEMPLATE([LIBCURL_FEATURE_SSPI],[Defined if libcurl supports SSPI])
   AH_TEMPLATE([LIBCURL_FEATURE_NTLM],[Defined if libcurl supports NTLM])
+  AH_TEMPLATE([LIBCURL_FEATURE_AWSAUTH],[Defined if libcurl supports AWSAUTH])
 
   AH_TEMPLATE([LIBCURL_PROTOCOL_HTTP],[Defined if libcurl supports HTTP])
   AH_TEMPLATE([LIBCURL_PROTOCOL_HTTPS],[Defined if libcurl supports HTTPS])
Index: include/curl/curl.h
===================================================================
RCS file: /cvsroot/curl/curl/include/curl/curl.h,v
retrieving revision 1.317
diff -u -r1.317 curl.h
--- include/curl/curl.h	20 Apr 2007 07:19:36 -0000	1.317
+++ include/curl/curl.h	24 Apr 2007 11:26:48 -0000
@@ -435,6 +435,7 @@
 #define CURLAUTH_DIGEST       (1<<1)  /* Digest */
 #define CURLAUTH_GSSNEGOTIATE (1<<2)  /* GSS-Negotiate */
 #define CURLAUTH_NTLM         (1<<3)  /* NTLM */
+#define CURLAUTH_AWSAUTH      (1<<4)  /* Amazon Web Services */
 #define CURLAUTH_ANY ~0               /* all types set */
 #define CURLAUTH_ANYSAFE (~CURLAUTH_BASIC)
 
@@ -1605,6 +1606,7 @@
 #define CURL_VERSION_SSPI      (1<<11) /* SSPI is supported */
 #define CURL_VERSION_CONV      (1<<12) /* character conversions are
                                           supported */
+#define CURL_VERSION_AWSAUTH   (1<<13)  /* AWS auth is supported */
 
 /*
  * NAME curl_version_info()
Index: lib/Makefile.Watcom
===================================================================
RCS file: /cvsroot/curl/curl/lib/Makefile.Watcom,v
retrieving revision 1.10
diff -u -r1.10 Makefile.Watcom
--- lib/Makefile.Watcom	23 Sep 2006 19:07:20 -0000	1.10
+++ lib/Makefile.Watcom	24 Apr 2007 11:26:48 -0000
@@ -36,6 +36,7 @@
        $(OBJ_DIR)\md5.obj              $(OBJ_DIR)\ssluse.obj     &
        $(OBJ_DIR)\http_negotiate.obj   $(OBJ_DIR)\version.obj    &
        $(OBJ_DIR)\http_ntlm.obj        $(OBJ_DIR)\getenv.obj     &
+       $(OBJ_DIR)\http_awsauth.obj &
        $(OBJ_DIR)\inet_pton.obj        $(OBJ_DIR)\escape.obj     &
        $(OBJ_DIR)\strtoofft.obj        $(OBJ_DIR)\mprintf.obj    &
        $(OBJ_DIR)\strerror.obj         $(OBJ_DIR)\telnet.obj     &
@@ -132,6 +133,7 @@
   ..\include\curl\multi.h ..\include\curl\curl.h formdata.h timeval.h &
   http_chunks.h hostip.h hash.h llist.h splay.h transfer.h sendf.h &
   progress.h base64.h strequal.h sslgen.h http_digest.h http_ntlm.h &
+  http_awsauth.h &
   http_negotiate.h url.h share.h http.h memory.h select.h parsedate.h &
   strtoofft.h multiif.h ..\include\curl\mprintf.h memdebug.h .\memory.h
 $(OBJ_DIR)\sendf.obj: sendf.c setup.h config-win32.h setup_once.h ..\include\curl\curl.h &
@@ -156,6 +158,7 @@
   share.h content_encoding.h http_digest.h http_negotiate.h select.h &
   multiif.h ftp.h dict.h telnet.h tftp.h http.h file.h ldap.h url.h &
   connect.h inet_ntop.h http_ntlm.h .\ca-bundle.h &
+  http_awsauth.h &
   ..\include\curl\mprintf.h memory.h memdebug.h .\memory.h
 $(OBJ_DIR)\dict.obj: dict.c setup.h config-win32.h setup_once.h urldata.h cookie.h &
   ..\include\curl\curl.h ..\include\curl\curlver.h ..\include\curl\easy.h &
@@ -219,6 +222,7 @@
   cookie.h formdata.h timeval.h http_chunks.h hostip.h hash.h llist.h &
   splay.h netrc.h content_encoding.h transfer.h sendf.h speedcheck.h &
   progress.h http.h url.h getinfo.h sslgen.h http_digest.h http_ntlm.h &
+  http_awsauth.h &
   http_negotiate.h share.h memory.h select.h multiif.h easyif.h &
   ..\include\curl\mprintf.h memdebug.h .\memory.h
 $(OBJ_DIR)\strequal.obj: strequal.c setup.h config-win32.h setup_once.h strequal.h &
@@ -279,6 +283,7 @@
 $(OBJ_DIR)\md5.obj: md5.c setup.h config-win32.h setup_once.h md5.h
 $(OBJ_DIR)\http_negotiate.obj: http_negotiate.c setup.h config-win32.h setup_once.h
 $(OBJ_DIR)\http_ntlm.obj: http_ntlm.c setup.h config-win32.h setup_once.h
+$(OBJ_DIR)\http_awsauth.obj: http_awsauth.c setup.h config-win32.h setup_once.h
 $(OBJ_DIR)\inet_pton.obj: inet_pton.c setup.h config-win32.h setup_once.h
 $(OBJ_DIR)\strtoofft.obj: strtoofft.c setup.h config-win32.h setup_once.h strtoofft.h &
   ..\include\curl\curl.h ..\include\curl\curlver.h ..\include\curl\easy.h &
Index: lib/Makefile.inc
===================================================================
RCS file: /cvsroot/curl/curl/lib/Makefile.inc,v
retrieving revision 1.15
diff -u -r1.15 Makefile.inc
--- lib/Makefile.inc	12 Feb 2007 22:32:40 -0000	1.15
+++ lib/Makefile.inc	24 Apr 2007 11:26:48 -0000
@@ -8,7 +8,8 @@
   content_encoding.c share.c http_digest.c md5.c http_negotiate.c	\
   http_ntlm.c inet_pton.c strtoofft.c strerror.c hostares.c hostasyn.c	\
   hostip4.c hostip6.c hostsyn.c hostthre.c inet_ntop.c parsedate.c	\
-  select.c gtls.c sslgen.c tftp.c splay.c strdup.c socks.c ssh.c nss.c
+  select.c gtls.c sslgen.c tftp.c splay.c strdup.c socks.c ssh.c nss.c  \
+  http_awsauth.c
 
 HHEADERS = arpa_telnet.h netrc.h file.h timeval.h base64.h hostip.h	\
   progress.h formdata.h cookie.h http.h sendf.h ftp.h url.h dict.h	\
@@ -19,4 +20,4 @@
   inet_pton.h strtoofft.h strerror.h inet_ntop.h curlx.h memory.h	\
   setup.h transfer.h select.h easyif.h multiif.h parsedate.h sslgen.h   \
   gtls.h tftp.h sockaddr.h splay.h strdup.h setup_once.h socks.h ssh.h  \
-  nssg.h
+  nssg.h http_awsauth.h
Index: lib/Makefile.vc6
===================================================================
RCS file: /cvsroot/curl/curl/lib/Makefile.vc6,v
retrieving revision 1.75
diff -u -r1.75 Makefile.vc6
--- lib/Makefile.vc6	9 Mar 2007 22:26:59 -0000	1.75
+++ lib/Makefile.vc6	24 Apr 2007 11:26:49 -0000
@@ -478,6 +478,7 @@
 	$(DIROBJ)\http_digest.obj \
         $(DIROBJ)\http_negotiate.obj \
         $(DIROBJ)\http_ntlm.obj \
+ 	$(DIROBJ)\http_awsauth.obj \
 	$(DIROBJ)\md5.obj \
 	$(DIROBJ)\memdebug.obj \
 	$(DIROBJ)\strerror.obj \
Index: lib/http.c
===================================================================
RCS file: /cvsroot/curl/curl/lib/http.c,v
retrieving revision 1.325
diff -u -r1.325 http.c
--- lib/http.c	10 Apr 2007 22:52:50 -0000	1.325
+++ lib/http.c	24 Apr 2007 11:26:49 -0000
@@ -87,6 +87,7 @@
 #include "sslgen.h"
 #include "http_digest.h"
 #include "http_ntlm.h"
+#include "http_awsauth.h"
 #include "http_negotiate.h"
 #include "url.h"
 #include "share.h"
@@ -183,6 +184,8 @@
     pick->picked = CURLAUTH_GSSNEGOTIATE;
   else if(avail & CURLAUTH_DIGEST)
     pick->picked = CURLAUTH_DIGEST;
+  else if(avail & CURLAUTH_AWSAUTH)
+    pick->picked = CURLAUTH_AWSAUTH;
   else if(avail & CURLAUTH_NTLM)
     pick->picked = CURLAUTH_NTLM;
   else if(avail & CURLAUTH_BASIC)
@@ -502,6 +505,17 @@
       }
       else
 #endif
+#ifdef USE_AWSAUTH
+        if(authhost->picked == CURLAUTH_AWSAUTH) {
+          auth=(char *)"AWSAUTH";
+          result = Curl_output_awsauth(conn,
+                                       (unsigned char *)request,
+                                       (unsigned char *)path);
+          if(result)
+            return result;
+        }
+      else
+#endif
       {
 #ifndef CURL_DISABLE_CRYPTO_AUTH
         if(authhost->picked == CURLAUTH_DIGEST) {
Index: lib/http_awsauth.c
===================================================================
RCS file: lib/http_awsauth.c
diff -N lib/http_awsauth.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ lib/http_awsauth.c	24 Apr 2007 11:26:49 -0000
@@ -0,0 +1,359 @@
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2007, Mark Atwood <me@mark.atwood.name>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * $Id$
+ ***************************************************************************/
+#include "setup.h"
+
+#ifdef USE_AWSAUTH
+
+#define DEBUG_ME 0
+
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include "urldata.h"
+#include "easyif.h"  /* for Curl_convert_... prototypes */
+#include "sendf.h"
+#include "strequal.h"
+#include "base64.h"
+#include "http_awsauth.h"
+#include "url.h"
+#include "memory.h"
+#include "ssluse.h"
+#include "parsedate.h"  /* for Curl_wkday and Curl_month */
+
+#define _MPRINTF_REPLACE /* use our functions only */
+#include <curl/mprintf.h>
+
+/* todo, remove dependency on openssl, use publicdomain sha1 & hmac routines */
+#include <openssl/evp.h>
+#include <openssl/hmac.h>
+
+/* The last #include file should be: */
+#include "memdebug.h"
+
+
+#if DEBUG_ME
+# define DEBUG_OUT(x) x
+#else
+# define DEBUG_OUT(x)
+#endif
+
+
+/* search thru a curl_slist for a header, return the string */
+static char *checkheaders(struct curl_slist *head,
+			  const char *thisheader)
+{
+  size_t thislen = strlen(thisheader);
+
+  for(; head; head=head->next) {
+    if(strnequal(head->data, thisheader, thislen))
+      return head->data;
+  }
+  return NULL;
+}
+
+/* a "growable buffer", ie array of chars, a length, and an allocation size */
+typedef struct growbuf_st {
+  char *buf;
+  int z, l;
+} growbuf_t;
+
+/* insert stuff into a growbuf_t */
+void growbuf_in (growbuf_t *g, char *b, int bl)
+{
+  if ((g->z - g->l) <= bl) {
+    g->buf = realloc(g->buf, g->z+(2*bl));
+    g->z += 2*bl;
+  }
+  memcpy((g->buf)+(g->l), b, bl);
+  g->l += bl;
+}
+
+/* used by a qsort call in mk_awss3_canonicalstring */
+static int cmpstringp(const void *p1, const void *p2)
+{
+  return strcmp(* (char **) p1, * (char **) p2);
+}
+
+/* build the canonical string to be hmac hashed */
+growbuf_t *mk_awss3_canonicalstring (char *http_verb,
+				     struct curl_slist *hdr,
+				     char *uripath)
+{
+  growbuf_t *g;
+
+  g = malloc(sizeof(growbuf_t));
+  g->buf = NULL; g->z=0; g->l=0; 
+
+  /* the http_verb (GET, PUT, HEAD, etc) */
+  growbuf_in(g, http_verb, strlen(http_verb));
+  growbuf_in(g, "\012", 1);
+
+  /* the Content-Md5, from the headers, if known */
+  {
+    char *h = "Content-Md5:";
+    int l = strlen(h);
+    char *d = checkheaders(hdr, h);
+    if (d) {
+      growbuf_in(g, d+(l+1), strlen(d)-(l+1));
+    }
+    growbuf_in(g, "\012", 1);      
+  }
+
+  /* the Content-Type, from the headers, if known */
+  {
+    char *h = "Content-Type:";
+    int l = strlen(h);
+    char *d = checkheaders(hdr, h);
+    if (d) {
+      growbuf_in(g, d+(l+1), strlen(d)-(l+1));
+    }
+    growbuf_in(g, "\012", 1);      
+  }
+
+  /* the Date, from the headers, if known */
+  /*  If it's not set, keep going,
+      even tho the authentication will most likely fail.*/
+  {
+    char *h = "Date:";
+    int l = strlen(h);
+    char *d = checkheaders(hdr, "Date:");
+    if (d) {
+      growbuf_in(g, d+(l+1), strlen(d)-(l+1));
+    }
+    growbuf_in(g, "\012", 1);
+  }
+
+  /* process X-Amz- headers */
+  {
+    int count = 0;
+    int i,j;
+    struct curl_slist *sl=NULL;
+    struct curl_slist *s;
+    char **sa;
+
+    /* copy all the X-Amz- headers into sl */
+    for (s=hdr; s; s=s->next)
+      if (strncasecmp("x-amz-", s->data, 6) == 0) {
+	sl = curl_slist_append(sl, s->data);
+	count++;
+      }
+
+    if (count > 0) {
+      for (s=sl; s; s=s->next) {
+	/* fold down the case of the header name */
+	for (i=0; s->data[i] != ':'; i++) {
+	  if (isupper(s->data[i]))
+	    s->data[i] -= ('A' - 'a');
+	}
+	/* remove whitespace after colon */
+	for (j=i+1; isspace(s->data[j]); j++);
+	i += 1;
+	while (s->data[j]) s->data[i++] = s->data[j++];
+	s->data[i] = '\0';
+      }
+
+      /* todo, fold duplicates */
+
+      sa = malloc(count * (sizeof(char*)));
+      for (s=sl,i=0; s; s=s->next,i++)
+	sa[i] = s->data;
+      qsort(sa, count, sizeof(char *), &cmpstringp);
+      for (i=0; i<count; i++) {
+	growbuf_in(g, sa[i], strlen(sa[i]));
+	growbuf_in(g, "\012", 1);
+      }
+
+      curl_slist_free_all(sl);
+      free(sa);
+
+    } else {
+      /* there were no X-Amz- headers */
+      /* There is a documentation bug in the AWS S3 documentation.
+	 It seems to say that a newline should be here even if there
+	 are no X-Amz- headers, but apparently, there shouldn't.
+      */
+      if (0) growbuf_in(g, "\012", 1);
+    }
+  }
+
+  /* the uri path */
+  growbuf_in(g, uripath, strlen(uripath));
+
+  /* there is no newline at the end */
+
+  return g;
+}
+
+char *mk_awss3_auth (unsigned char *md_value,
+		     int *md_size,
+		     char *aws_access_key_id,
+		     char *aws_access_key_secret,
+		     char *http_verb,
+		     struct curl_slist *hdr,
+		     char *uripath)
+{
+  HMAC_CTX hmac_ctx;
+  char *r, *cry;
+  growbuf_t *g;
+
+  g = mk_awss3_canonicalstring(http_verb,
+			       hdr,
+			       uripath);
+
+  HMAC_CTX_init(&hmac_ctx);
+  HMAC_Init_ex(&hmac_ctx,
+	       aws_access_key_secret, strlen(aws_access_key_secret),
+	       EVP_sha1(), NULL);
+  HMAC_Update(&hmac_ctx, g->buf, g->l);
+  free(g->buf); free(g);
+  HMAC_Final(&hmac_ctx, md_value, md_size);
+  HMAC_CTX_cleanup(&hmac_ctx);
+  HMAC_cleanup(&hmac_ctx);
+
+  return md_value;
+}
+
+CURLcode Curl_output_awsauth(struct connectdata *conn,
+			     unsigned char *request,
+			     unsigned char *uripath)
+{
+  /* holds the string to be sent to the server */
+  char **allocuserpwd = &conn->allocptr.userpwd;
+
+  /* curl auth state */
+  struct auth *authp = &conn->data->state.authhost;
+
+  char *aws_access_key_id = conn->user;
+  char *aws_access_key_secret = conn->passwd;
+
+  /* the computed hash of the canonical string */
+  unsigned char md_value[EVP_MAX_MD_SIZE];
+  int md_size;
+
+  /* the base64 string of the hash */
+  char *b64 = NULL;
+  size_t b64_z;
+
+  DEBUGASSERT(conn);
+  DEBUGASSERT(conn->data);
+
+  authp->done = FALSE;
+
+  if ((!aws_access_key_id) || (!aws_access_key_id[0]))
+    aws_access_key_id = getenv("AWS_ACCESS_KEY_ID");
+  if ((!aws_access_key_secret) || (!aws_access_key_secret[0]))
+    aws_access_key_secret = getenv("AWS_ACCESS_KEY_SECRET");
+
+  if ((!aws_access_key_id) || (!aws_access_key_secret)) {
+    /* If cant get the id/secret from curl's username/password
+       (from --user or from .netrc), or from the environment variables,
+       then just punt.
+       Leave the allocuserpwd alone, set done to true, and return OK.
+       The access will probably fail, unless the bucket or object's
+       ACL allows unauth's access, at which point we didn't need
+       to do all this anyway.
+    */
+    authp->done = TRUE;
+    return CURLE_OK;
+  }
+
+  /* We must have the Date header in the HTTP request headers.  The
+     AWS auth uses the date string as part of it's canonical string,
+     and the auth verifier in the server compares it to the date in
+     the headers, and in the clock in the server, to prevent replay
+     attacks. */
+
+  if (!checkheaders(conn->data->set.headers, "Date:")) {
+    /* the Date header isn't in the headers
+       construct one and insert it
+       hope that our clock is correct */
+
+    char dtbuf[80];
+    struct tm *tm;
+    time_t t = time(NULL);  /* grab time from system */
+#ifdef HAVE_GMTIME_R
+    /* thread-safe version */
+    struct tm keeptime;
+    tm = (struct tm *)gmtime_r(&t, &keeptime);
+#else
+    tm = gmtime(&t);
+#endif
+
+    /* why not use strftime?
+       probably because of locale worries
+    */
+    snprintf(dtbuf, sizeof(dtbuf)-1,
+	     "Date: %s, %02d %s %4d %02d:%02d:%02d GMT",
+	     Curl_wkday[tm->tm_wday?tm->tm_wday-1:6],
+	     tm->tm_mday, Curl_month[tm->tm_mon], tm->tm_year + 1900,
+	     tm->tm_hour, tm->tm_min, tm->tm_sec);
+
+    conn->data->set.headers
+      = curl_slist_append(conn->data->set.headers, dtbuf);
+    if (!conn->data->set.headers) return CURLE_OUT_OF_MEMORY;
+
+  } else {
+    /* the Date header was already in the headers */
+    /* here's hoping that it's correct */
+  }
+
+  /* construct the hmac hash into md_value
+     using the aws id, the aws secret, the http verb, and the headers
+     (the Date, the Content-Md5, the Content-Type, and any X-Amz-),
+     and the uri path */
+  (void) mk_awss3_auth (md_value, &md_size,
+			aws_access_key_id,
+			aws_access_key_secret,
+			request,
+			conn->data->set.headers,
+			uripath);
+
+  /* encode the hmac hash into b64 format */
+  b64_z = Curl_base64_encode(NULL, (char *)md_value, md_size, &b64);
+  if (b64_z <= 0) return CURLE_OUT_OF_MEMORY;
+
+  Curl_safefree(*allocuserpwd);
+  *allocuserpwd = aprintf("Authorization: AWS %s:%s\r\n",
+			  aws_access_key_id, b64);
+  free(b64);
+
+  authp->done = TRUE;
+
+  return CURLE_OK;
+}
+
+void
+Curl_awsauth_cleanup(struct connectdata *conn)
+{
+  (void)conn;
+}
+
+#endif /* USE_AWSAUTH */
Index: lib/http_awsauth.h
===================================================================
RCS file: lib/http_awsauth.h
diff -N lib/http_awsauth.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ lib/http_awsauth.h	24 Apr 2007 11:26:49 -0000
@@ -0,0 +1,36 @@
+#ifndef __HTTP_AWSAUTH_H
+#define __HTTP_AWSAUTH_H
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2005, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * $Id$
+ ***************************************************************************/
+
+/* this is for creating awsauth header output */
+CURLcode Curl_output_awsauth(struct connectdata *conn,
+			     unsigned char *request,
+			     unsigned char *uripath);
+
+void Curl_awsauth_cleanup(struct connectdata *conn);
+#ifndef USE_AWSAUTH
+#define Curl_awsauth_cleanup(x)
+#endif
+
+#endif
Index: lib/setup.h
===================================================================
RCS file: /cvsroot/curl/curl/lib/setup.h,v
retrieving revision 1.130
diff -u -r1.130 setup.h
--- lib/setup.h	28 Feb 2007 14:45:49 -0000	1.130
+++ lib/setup.h	24 Apr 2007 11:26:49 -0000
@@ -339,6 +339,14 @@
 #endif
 #endif
 
+#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_AWSAUTH)
+#if defined(USE_SSLEAY) && defined(HAVE_HMAC_CTX_INIT)
+/* the AWS auth code uses OpenSSL functions and specifically the HMAC ones */
+#define USE_AWSAUTH
+#endif
+#endif
+
+
 /* non-configure builds may define CURL_WANTS_CA_BUNDLE_ENV */
 #if defined(CURL_WANTS_CA_BUNDLE_ENV) && !defined(CURL_CA_BUNDLE)
 #define CURL_CA_BUNDLE getenv("CURL_CA_BUNDLE")
Index: lib/version.c
===================================================================
RCS file: /cvsroot/curl/curl/lib/version.c,v
retrieving revision 1.52
diff -u -r1.52 version.c
--- lib/version.c	24 Nov 2006 22:14:40 -0000	1.52
+++ lib/version.c	24 Apr 2007 11:26:49 -0000
@@ -162,6 +162,9 @@
 #ifdef USE_NTLM
   | CURL_VERSION_NTLM
 #endif
+#ifdef USE_AWSAUTH
+  | CURL_VERSION_AWSAUTH
+#endif
 #ifdef USE_WINDOWS_SSPI
   | CURL_VERSION_SSPI
 #endif
Index: src/main.c
===================================================================
RCS file: /cvsroot/curl/curl/src/main.c,v
retrieving revision 1.414
diff -u -r1.414 main.c
--- src/main.c	22 Apr 2007 09:31:28 -0000	1.414
+++ src/main.c	24 Apr 2007 11:26:50 -0000
@@ -609,6 +609,7 @@
     "    --data-binary <data> HTTP POST binary data (H)",
     "    --negotiate     Use HTTP Negotiate Authentication (H)",
     "    --digest        Use HTTP Digest Authentication (H)",
+    "    --awsauth       Usage Amazon AWS Authentication (H)",
     "    --disable-eprt  Inhibit using EPRT or LPRT (F)",
     "    --disable-epsv  Inhibit using EPSV (F)",
     " -D/--dump-header <file> Write the headers to this file",
@@ -1440,6 +1441,7 @@
     /* all these ones, starting with "*" or "$" as a short-option have *no*
        short option to mention. */
     {"*", "url",         TRUE},
+    {"*A", "awsauth", FALSE},
     {"*a", "random-file", TRUE},
     {"*b", "egd-file",   TRUE},
     {"*c", "connect-timeout", TRUE},
@@ -1730,6 +1732,13 @@
         config->authtype = CURLAUTH_DIGEST;
         break;
 
+      case 'A': /* --awsauth */
+        if(curlinfo->features & CURL_VERSION_AWSAUTH)
+	  config->authtype = CURLAUTH_AWSAUTH;
+        else
+          return PARAM_LIBCURL_DOESNT_SUPPORT;
+        break;
+
       case 'l': /* --negotiate */
         if(curlinfo->features & CURL_VERSION_GSSNEGOTIATE)
           config->authtype = CURLAUTH_GSSNEGOTIATE;
@@ -2474,6 +2483,7 @@
           {"IPv6", CURL_VERSION_IPV6},
           {"Largefile", CURL_VERSION_LARGEFILE},
           {"NTLM", CURL_VERSION_NTLM},
+	  {"AWSAUTH", CURL_VERSION_AWSAUTH},
           {"SPNEGO", CURL_VERSION_SPNEGO},
           {"SSL",  CURL_VERSION_SSL},
           {"SSPI",  CURL_VERSION_SSPI},
