cURL / Mailing Lists / curl-library / Single Mail

curl-library

Patch to add Amazon AWS authentication

From: Mark Atwood <me_at_mark.atwood.name>
Date: 22 Apr 2007 22:12:19 -0700

I've written a patch for Amazon AWS authentication, in the same spirit
as Digest, GSSAPI, and NTLM authentication.

diff -Naur curl-7.16.1/curl-config.in curl-7.16.1-aws/curl-config.in
--- curl-7.16.1/curl-config.in 2006-05-02 15:48:22.000000000 -0700
+++ curl-7.16.1-aws/curl-config.in 2007-04-06 18:38:46.000000000 -0700
@@ -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)
diff -Naur curl-7.16.1/docs/curl.1 curl-7.16.1-aws/docs/curl.1
--- curl-7.16.1/docs/curl.1 2007-01-25 07:58:00.000000000 -0800
+++ curl-7.16.1-aws/docs/curl.1 2007-04-10 09:46:33.000000000 -0700
@@ -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.
@@ -260,8 +260,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.
@@ -762,6 +762,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>
@@ -1033,6 +1047,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.
@@ -1083,6 +1102,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"
diff -Naur curl-7.16.1/docs/FEATURES curl-7.16.1-aws/docs/FEATURES
--- curl-7.16.1/docs/FEATURES 2006-10-12 01:54:48.000000000 -0700
+++ curl-7.16.1-aws/docs/FEATURES 2007-04-06 19:28:05.000000000 -0700
@@ -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
diff -Naur curl-7.16.1/docs/libcurl/curl_easy_setopt.3 curl-7.16.1-aws/docs/libcurl/curl_easy_setopt.3
--- curl-7.16.1/docs/libcurl/curl_easy_setopt.3 2007-01-17 00:57:20.000000000 -0800
+++ curl-7.16.1-aws/docs/libcurl/curl_easy_setopt.3 2007-04-06 19:43:55.000000000 -0700
@@ -554,6 +554,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
diff -Naur curl-7.16.1/docs/libcurl/curl_version_info.3 curl-7.16.1-aws/docs/libcurl/curl_version_info.3
--- curl-7.16.1/docs/libcurl/curl_version_info.3 2006-11-02 13:58:45.000000000 -0800
+++ curl-7.16.1-aws/docs/libcurl/curl_version_info.3 2007-04-06 19:45:34.000000000 -0700
@@ -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
diff -Naur curl-7.16.1/docs/libcurl/libcurl.m4 curl-7.16.1-aws/docs/libcurl/libcurl.m4
--- curl-7.16.1/docs/libcurl/libcurl.m4 2006-05-09 05:52:21.000000000 -0700
+++ curl-7.16.1-aws/docs/libcurl/libcurl.m4 2007-04-06 19:44:27.000000000 -0700
@@ -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])
diff -Naur curl-7.16.1/docs/libcurl/libcurl-tutorial.3 curl-7.16.1-aws/docs/libcurl/libcurl-tutorial.3
--- curl-7.16.1/docs/libcurl/libcurl-tutorial.3 2006-06-21 10:34:29.000000000 -0700
+++ curl-7.16.1-aws/docs/libcurl/libcurl-tutorial.3 2007-04-06 19:46:37.000000000 -0700
@@ -418,8 +418,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);
 
diff -Naur curl-7.16.1/docs/MANUAL curl-7.16.1-aws/docs/MANUAL
--- curl-7.16.1/docs/MANUAL 2006-09-05 23:58:56.000000000 -0700
+++ curl-7.16.1-aws/docs/MANUAL 2007-04-06 19:23:31.000000000 -0700
@@ -90,10 +90,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
diff -Naur curl-7.16.1/docs/TheArtOfHttpScripting curl-7.16.1-aws/docs/TheArtOfHttpScripting
--- curl-7.16.1/docs/TheArtOfHttpScripting 2005-01-29 05:53:53.000000000 -0800
+++ curl-7.16.1-aws/docs/TheArtOfHttpScripting 2007-04-06 19:26:14.000000000 -0700
@@ -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
diff -Naur curl-7.16.1/include/curl/curl.h curl-7.16.1-aws/include/curl/curl.h
--- curl-7.16.1/include/curl/curl.h 2007-01-10 04:16:46.000000000 -0800
+++ curl-7.16.1-aws/include/curl/curl.h 2007-04-06 19:48:36.000000000 -0700
@@ -431,6 +431,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)
 
@@ -1584,6 +1585,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()
diff -Naur curl-7.16.1/lib/http_awsauth.c curl-7.16.1-aws/lib/http_awsauth.c
--- curl-7.16.1/lib/http_awsauth.c 1969-12-31 16:00:00.000000000 -0800
+++ curl-7.16.1-aws/lib/http_awsauth.c 2007-04-10 12:12:01.000000000 -0700
@@ -0,0 +1,361 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel_at_haxx.se>, et al.
+ * Copyright (C) 2007, Mark Atwood <me_at_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"
+
+#ifndef CURL_DISABLE_HTTP
+#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;
+
+ curlassert(conn);
+ curlassert(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 */
+#endif /* !CURL_DISABLE_HTTP */
diff -Naur curl-7.16.1/lib/http_awsauth.h curl-7.16.1-aws/lib/http_awsauth.h
--- curl-7.16.1/lib/http_awsauth.h 1969-12-31 16:00:00.000000000 -0800
+++ curl-7.16.1-aws/lib/http_awsauth.h 2007-04-09 00:52:27.000000000 -0700
@@ -0,0 +1,36 @@
+#ifndef __HTTP_AWSAUTH_H
+#define __HTTP_AWSAUTH_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2005, Daniel Stenberg, <daniel_at_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
diff -Naur curl-7.16.1/lib/http.c curl-7.16.1-aws/lib/http.c
--- curl-7.16.1/lib/http.c 2007-01-29 01:26:37.000000000 -0800
+++ curl-7.16.1-aws/lib/http.c 2007-04-10 09:21:27.000000000 -0700
@@ -89,6 +89,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)
@@ -498,6 +501,18 @@
       }
       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) {
diff -Naur curl-7.16.1/lib/Makefile.in curl-7.16.1-aws/lib/Makefile.in
--- curl-7.16.1/lib/Makefile.in 2007-04-22 21:16:35.000000000 -0700
+++ curl-7.16.1-aws/lib/Makefile.in 2007-04-22 21:18:25.000000000 -0700
@@ -66,10 +66,11 @@
         strequal.lo easy.lo security.lo krb4.lo memdebug.lo \
         http_chunks.lo strtok.lo connect.lo llist.lo hash.lo multi.lo \
         content_encoding.lo share.lo http_digest.lo md5.lo \
- http_negotiate.lo http_ntlm.lo inet_pton.lo strtoofft.lo \
- strerror.lo hostares.lo hostasyn.lo hostip4.lo hostip6.lo \
- hostsyn.lo hostthre.lo inet_ntop.lo parsedate.lo select.lo \
- gtls.lo sslgen.lo tftp.lo splay.lo strdup.lo socks.lo ssh.lo
+ http_negotiate.lo http_awsauth.lo http_ntlm.lo inet_pton.lo \
+ strtoofft.lo strerror.lo hostares.lo hostasyn.lo hostip4.lo \
+ hostip6.lo hostsyn.lo hostthre.lo inet_ntop.lo parsedate.lo \
+ select.lo gtls.lo sslgen.lo tftp.lo splay.lo strdup.lo \
+ socks.lo ssh.lo
 am__objects_2 =
 am_libcurl_la_OBJECTS = $(am__objects_1) $(am__objects_2)
 libcurl_la_OBJECTS = $(am_libcurl_la_OBJECTS)
@@ -327,6 +328,7 @@
   netrc.c getinfo.c transfer.c strequal.c easy.c security.c krb4.c \
   memdebug.c http_chunks.c strtok.c connect.c llist.c hash.c multi.c \
   content_encoding.c share.c http_digest.c md5.c http_negotiate.c \
+ http_awsauth.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
@@ -337,6 +339,7 @@
   getinfo.h strequal.h krb4.h memdebug.h inet_ntoa_r.h \
   http_chunks.h strtok.h connect.h llist.h hash.h content_encoding.h \
   share.h md5.h http_digest.h http_negotiate.h http_ntlm.h ca-bundle.h \
+ http_awsauth.h \
   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
@@ -458,6 +461,7 @@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hostsyn.Plo_at_am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hostthre.Plo_at_am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/http.Plo_at_am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/http_awsauth.Plo_at_am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/http_chunks.Plo_at_am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/http_digest.Plo_at_am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/http_negotiate.Plo_at_am__quote@
diff -Naur curl-7.16.1/lib/Makefile.inc curl-7.16.1-aws/lib/Makefile.inc
--- curl-7.16.1/lib/Makefile.inc 2007-01-23 14:46:31.000000000 -0800
+++ curl-7.16.1-aws/lib/Makefile.inc 2007-04-09 15:17:30.000000000 -0700
@@ -6,6 +6,7 @@
   netrc.c getinfo.c transfer.c strequal.c easy.c security.c krb4.c \
   memdebug.c http_chunks.c strtok.c connect.c llist.c hash.c multi.c \
   content_encoding.c share.c http_digest.c md5.c http_negotiate.c \
+ http_awsauth.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
@@ -16,6 +17,7 @@
   getinfo.h strequal.h krb4.h memdebug.h inet_ntoa_r.h \
   http_chunks.h strtok.h connect.h llist.h hash.h content_encoding.h \
   share.h md5.h http_digest.h http_negotiate.h http_ntlm.h ca-bundle.h \
+ http_awsauth.h \
   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
diff -Naur curl-7.16.1/lib/Makefile.vc6 curl-7.16.1-aws/lib/Makefile.vc6
--- curl-7.16.1/lib/Makefile.vc6 2006-10-22 00:00:39.000000000 -0700
+++ curl-7.16.1-aws/lib/Makefile.vc6 2007-04-09 15:15:11.000000000 -0700
@@ -474,6 +474,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 \
diff -Naur curl-7.16.1/lib/Makefile.Watcom curl-7.16.1-aws/lib/Makefile.Watcom
--- curl-7.16.1/lib/Makefile.Watcom 2006-09-23 12:07:20.000000000 -0700
+++ curl-7.16.1-aws/lib/Makefile.Watcom 2007-04-09 15:15:09.000000000 -0700
@@ -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 &
diff -Naur curl-7.16.1/lib/setup.h curl-7.16.1-aws/lib/setup.h
--- curl-7.16.1/lib/setup.h 2007-01-29 01:25:30.000000000 -0800
+++ curl-7.16.1-aws/lib/setup.h 2007-04-10 09:21:30.000000000 -0700
@@ -358,6 +358,12 @@
 #endif
 #endif
 
+#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_AWSAUTH)
+#if defined(USE_SSLEAY)
+#define USE_AWSAUTH
+#endif
+#endif
+
 #ifdef CURLDEBUG
 #define DEBUGF(x) x
 #else
diff -Naur curl-7.16.1/lib/version.c curl-7.16.1-aws/lib/version.c
--- curl-7.16.1/lib/version.c 2006-11-24 14:15:14.000000000 -0800
+++ curl-7.16.1-aws/lib/version.c 2007-04-10 00:28:32.000000000 -0700
@@ -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
diff -Naur curl-7.16.1/src/main.c curl-7.16.1-aws/src/main.c
--- curl-7.16.1/src/main.c 2007-01-27 15:02:18.000000000 -0800
+++ curl-7.16.1-aws/src/main.c 2007-04-10 00:26:56.000000000 -0700
@@ -608,6 +608,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",
@@ -1417,6 +1418,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},
@@ -1699,6 +1701,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;
@@ -2415,6 +2424,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},
Received on 2007-04-23