From a5a1c54b7c982978dd8e4cdb3745841f4fef4a34 Mon Sep 17 00:00:00 2001 From: Bryan Ischo Date: Tue, 28 Oct 2008 09:41:27 +0000 Subject: * Implemented Authenticated Query String support * Implemented Server Access Logging support * Added "Log Delivery" S3 Group to support Server Access Logging * Fixed some minor compiler warnings, due to red-herring signedness issues --- inc/libs3.h | 174 ++++++++++++++++++++++++++++++++++++++++++++++++++-------- inc/request.h | 16 +----- inc/util.h | 2 +- 3 files changed, 153 insertions(+), 39 deletions(-) (limited to 'inc') diff --git a/inc/libs3.h b/inc/libs3.h index 39d4d7b..c16f9da 100644 --- a/inc/libs3.h +++ b/inc/libs3.h @@ -128,6 +128,12 @@ extern "C" { #define S3_HOSTNAME "s3.amazonaws.com" +/** + * S3_MAX_BUCKET_NAME_SIZE is the maximum size of a bucket name. + **/ + +#define S3_MAX_BUCKET_NAME_SIZE 255 + /** * S3_MAX_KEY_SIZE is the maximum size of keys that Amazon S3 supports. **/ @@ -187,6 +193,17 @@ extern "C" { #define S3_MAX_GRANTEE_DISPLAY_NAME_SIZE 128 +/** + * This is the maximum number of characters that will be stored in the + * return buffer for the utility function which computes an HTTP authenticated + * query string + **/ +#define S3_MAX_AUTHENTICATED_QUERY_STRING_SIZE \ + (sizeof("https://" S3_HOSTNAME "/") + (S3_MAX_KEY_SIZE * 3) + \ + sizeof("?AWSAccessKeyId=") + 32 + sizeof("&Expires=") + 32 + \ + sizeof("&Signature=") + 28 + 1) + + /** * This constant is used by the S3_initialize() function, to specify that * the winsock library should be initialized by libs3; only relevent on @@ -250,15 +267,17 @@ typedef enum S3StatusKeyTooLong , S3StatusUriTooLong , S3StatusXmlParseFailure , - S3StatusBadAclEmailAddressTooLong , - S3StatusBadAclUserIdTooLong , - S3StatusBadAclUserDisplayNameTooLong , - S3StatusBadAclGroupUriTooLong , - S3StatusBadAclPermissionTooLong , - S3StatusTooManyAclGrants , - S3StatusBadAclGrantee , - S3StatusBadAclPermission , - S3StatusAclXmlDocumentTooLarge , + S3StatusEmailAddressTooLong , + S3StatusUserIdTooLong , + S3StatusUserDisplayNameTooLong , + S3StatusGroupUriTooLong , + S3StatusPermissionTooLong , + S3StatusTargetBucketTooLong , + S3StatusTargetPrefixTooLong , + S3StatusTooManyGrants , + S3StatusBadGrantee , + S3StatusBadPermission , + S3StatusXmlDocumentTooLarge , S3StatusNameLookupError , S3StatusFailedToConnect , S3StatusServerFailedVerification , @@ -391,13 +410,16 @@ typedef enum * listing owned buckets * All AWS Users - identifies all authenticated AWS users * All Users - identifies all users + * Log Delivery - identifies the Amazon group responsible for writing + * server access logs into buckets **/ typedef enum { S3GranteeTypeAmazonCustomerByEmail = 0, S3GranteeTypeCanonicalUser = 1, S3GranteeTypeAllAwsUsers = 2, - S3GranteeTypeAllUsers = 3 + S3GranteeTypeAllUsers = 3, + S3GranteeTypeLogDelivery = 4 } S3GranteeType; @@ -1365,6 +1387,40 @@ S3Status S3_get_request_context_fdsets(S3RequestContext *requestContext, int64_t S3_get_request_context_timeout(S3RequestContext *requestContext); +/** ************************************************************************** + * S3 Utility Functions + ************************************************************************** **/ + +/** + * Generates an HTTP authenticated query string, which may then be used by + * a browser (or other web client) to issue the request. The request is + * implicitly a GET request; Amazon S3 is documented to only support this type + * of authenticated query string request. + * + * @param buffer is the output buffer for the authenticated query string. + * It must be at least S3_MAX_AUTHENTICATED_QUERY_STRING_SIZE bytes in + * length. + * @param bucketContext gives the bucket and associated parameters for the + * request to generate. + * @param key gives the key which the authenticated request will GET. + * @param expires gives the number of seconds since Unix epoch for the + * expiration date of the request; after this time, the request will + * no longer be valid. If this value is negative, the largest + * expiration date possible is used (currently, Jan 19, 2038). + * @param resource gives a sub-resource to be fetched for the request, or NULL + * for none. This should be of the form "?", i.e. + * "?torrent". + * @return One of: + * S3StatusUriTooLong if, due to an internal error, the generated URI + * is longer than S3_MAX_AUTHENTICATED_QUERY_STRING_SIZE bytes in + * length and thus will not fit into the supplied buffer + * S3StatusOK on success + **/ +S3Status S3_generate_authenticated_query_string + (char *buffer, const S3BucketContext *bucketContext, + const char *key, int64_t expires, const char *resource); + + /** ************************************************************************** * Service Functions ************************************************************************** **/ @@ -1391,7 +1447,7 @@ void S3_list_service(S3Protocol protocol, const char *accessKeyId, const S3ListServiceHandler *handler, void *callbackData); - + /** ************************************************************************** * Bucket Functions ************************************************************************** **/ @@ -1719,23 +1775,93 @@ void S3_set_acl(const S3BucketContext *bucketContext, const char *key, const S3ResponseHandler *handler, void *callbackData); -/** - * xxx todo - * Service Logging ... - **/ - +/** ************************************************************************** + * Server Access Log Functions + ************************************************************************** **/ /** - * xxx todo - * function for generating an HTTP authenticated query string + * Gets the service access logging settings for a bucket. The service access + * logging settings specify whether or not the S3 service will write service + * access logs for requests made for the given bucket, and if so, several + * settings controlling how these logs will be written. + * + * @param bucketContext gives the bucket and associated parameters for this + * request; this is the bucket for which service access logging is + * being requested + * @param targetBucketReturn must be passed in as a buffer of at least + * (S3_MAX_BUCKET_NAME_SIZE + 1) bytes in length, and will be filled + * in with the target bucket name for access logging for the given + * bucket, which is the bucket into which access logs for the specified + * bucket will be written. This is returned as an empty string if + * service access logging is not enabled for the given bucket. + * @param targetPrefixReturn must be passed in as a buffer of at least + * (S3_MAX_KEY_SIZE + 1) bytes in length, and will be filled in + * with the key prefix for server access logs for the given bucket, + * or the empty string if no such prefix is specified. + * @param aclGrantCountReturn returns the number of ACL grants that are + * associated with the server access logging for the given bucket. + * @param aclGrants must be passed in as an array of at least + * S3_MAX_ACL_GRANT_COUNT S3AclGrant structures, and these will be + * filled in with the target grants associated with the server access + * logging for the given bucket, whose number is returned in the + * aclGrantCountReturn parameter. These grants will be applied to the + * ACL of any server access logging log files generated by the S3 + * service for the given bucket. + * @param requestContext if non-NULL, gives the S3RequestContext to add this + * request to, and does not perform the request immediately. If NULL, + * performs the request immediately and synchronously. + * @param handler gives the callbacks to call as the request is processed and + * completed + * @param callbackData will be passed in as the callbackData parameter to + * all callbacks for this request **/ - - -/** - * xxx todo - * functions for generating form stuff for posting to s3 +void S3_get_server_access_logging(const S3BucketContext *bucketContext, + char *targetBucketReturn, + char *targetPrefixReturn, + int *aclGrantCountReturn, + S3AclGrant *aclGrants, + S3RequestContext *requestContext, + const S3ResponseHandler *handler, + void *callbackData); + + +/** + * Sets the service access logging settings for a bucket. The service access + * logging settings specify whether or not the S3 service will write service + * access logs for requests made for the given bucket, and if so, several + * settings controlling how these logs will be written. + * + * @param bucketContext gives the bucket and associated parameters for this + * request; this is the bucket for which service access logging is + * being set + * @param targetBucket gives the target bucket name for access logging for the + * given bucket, which is the bucket into which access logs for the + * specified bucket will be written. + * @param targetPrefix is an option parameter which specifies the key prefix + * for server access logs for the given bucket, or NULL if no such + * prefix is to be used. + * @param aclGrantCount specifies the number of ACL grants that are to be + * associated with the server access logging for the given bucket. + * @param aclGrants is as an array of S3AclGrant structures, whose number is + * given by the aclGrantCount parameter. These grants will be applied + * to the ACL of any server access logging log files generated by the + * S3 service for the given bucket. + * @param requestContext if non-NULL, gives the S3RequestContext to add this + * request to, and does not perform the request immediately. If NULL, + * performs the request immediately and synchronously. + * @param handler gives the callbacks to call as the request is processed and + * completed + * @param callbackData will be passed in as the callbackData parameter to + * all callbacks for this request **/ - +void S3_set_server_access_logging(const S3BucketContext *bucketContext, + const char *targetBucket, + const char *targetPrefix, int aclGrantCount, + const S3AclGrant *aclGrants, + S3RequestContext *requestContext, + const S3ResponseHandler *handler, + void *callbackData); + #ifdef __cplusplus } diff --git a/inc/request.h b/inc/request.h index 706001b..afb4929 100644 --- a/inc/request.h +++ b/inc/request.h @@ -51,14 +51,8 @@ typedef struct RequestParams // Request type, affects the HTTP verb used HttpRequestType httpRequestType; - // Protocol to use for request - S3Protocol protocol; - - // URI style to use for request - S3UriStyle uriStyle; - - // Bucket name, if any - const char *bucketName; + // Bucket context for request + S3BucketContext bucketContext; // Key, if any const char *key; @@ -69,12 +63,6 @@ typedef struct RequestParams // sub resource, like ?acl, ?location, ?torrent, ?logging const char *subResource; - // AWS Access Key ID - const char *accessKeyId; - - // AWS Secret Access Key - const char *secretAccessKey; - // If this is a copy operation, this gives the source bucket const char *copySourceBucketName; diff --git a/inc/util.h b/inc/util.h index bcd10f3..0ed580e 100644 --- a/inc/util.h +++ b/inc/util.h @@ -73,7 +73,7 @@ uint64_t parseUnsignedInt(const char *str); // base64 encode bytes. The output buffer must have at least // ((4 * (inLen + 1)) / 3) bytes in it. Returns the number of bytes written // to [out]. -int base64Encode(const unsigned char *in, int inLen, unsigned char *out); +int base64Encode(const unsigned char *in, int inLen, char *out); // Compute HMAC-SHA-1 with key [key] and message [message], storing result // in [hmac] -- cgit v1.2.1