diff options
author | Bryan Ischo <bryan@ischo.com> | 2008-08-13 13:27:47 +0000 |
---|---|---|
committer | Bryan Ischo <bryan@ischo.com> | 2008-08-13 13:27:47 +0000 |
commit | 7fd73adff17c0511cf2c09da16d46d1a8e608866 (patch) | |
tree | fe09fe3dcdc6c68d9a17d80e64424c0e241c5247 | |
parent | 06fcf9839f35d1bbac18819886375b8232d73f35 (diff) | |
download | ceph-libs3-7fd73adff17c0511cf2c09da16d46d1a8e608866.tar.gz |
* Replaced openssl library with GnuTLS, libgcrypt, and hand-written base 64
encoding routine
-rw-r--r-- | GNUmakefile | 17 | ||||
-rw-r--r-- | inc/libs3.h | 14 | ||||
-rw-r--r-- | inc/util.h | 20 | ||||
-rw-r--r-- | src/general.c | 106 | ||||
-rw-r--r-- | src/request.c | 65 | ||||
-rw-r--r-- | src/util.c | 38 |
6 files changed, 126 insertions, 134 deletions
diff --git a/GNUmakefile b/GNUmakefile index 70e8b37..6d75d0d 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -76,6 +76,18 @@ ifndef LIBXML2_CFLAGS LIBXML2_CFLAGS := $(shell xml2-config --cflags) endif +ifndef GCRYPT_CFLAGS + GCRYPT_CFLAGS := $(shell libgcrypt-config --cflags) +endif + +ifndef GCRYPT_LIBS + GCRYPT_LIBS := $(shell libgcrypt-config --libs) +endif + +ifndef GNUTLS_LIBS + GNUTLS_LIBS := $(shell pkg-config gnutls --libs) +endif + # -------------------------------------------------------------------------- # These CFLAGS assume a GNU compiler. For other compilers, write a script @@ -86,11 +98,12 @@ ifndef CFLAGS CFLAGS = -O3 endif -CFLAGS += -Wall -Werror -std=c99 -Iinc $(CURL_CFLAGS) $(LIBXML2_CFLAGS) \ +CFLAGS += -Wall -Werror -std=c99 -Iinc \ + $(CURL_CFLAGS) $(LIBXML2_CFLAGS) $(GCRYPT_CFLAGS) \ -DLIBS3_VER_MAJOR=\"$(LIBS3_VER_MAJOR)\" \ -DLIBS3_VER_MINOR=\"$(LIBS3_VER_MINOR)\" -LDFLAGS = $(CURL_LIBS) $(LIBXML2_LIBS) -lpthread +LDFLAGS = $(CURL_LIBS) $(LIBXML2_LIBS) $(GCRYPT_LIBS) $(GNUTLS_LIBS) -lpthread # -------------------------------------------------------------------------- diff --git a/inc/libs3.h b/inc/libs3.h index 5d2054b..8c222c6 100644 --- a/inc/libs3.h +++ b/inc/libs3.h @@ -189,11 +189,21 @@ **/ #define S3_INIT_WINSOCK 1 + +/** + * This constant is used by the S3_initialize() function, to specify that + * the gcrypt library should be initialized by libs3; should always be + * specified by the caller unless the caller specifically initializes the + * gcrypt library elsewhere. + **/ +#define S3_INIT_GCRYPT 2 + + /** * This convenience constant is used by the S3_initialize() function to - * indicate that alllibraries required by libs3 should be initialized. + * indicate that all libraries required by libs3 should be initialized. **/ -#define S3_INIT_ALL (S3_INIT_WINSOCK) +#define S3_INIT_ALL (S3_INIT_WINSOCK | S3_INIT_GCRYPT) /** ************************************************************************** @@ -56,21 +56,6 @@ (1 + 255 + 1 + MAX_URLENCODED_KEY_SIZE + (sizeof("?torrent") - 1) + 1) -// Mutex functions ----------------------------------------------------------- - -// Create a mutex. Returns 0 if none could be created. -struct S3Mutex *mutex_create(); - -// Lock a mutex -void mutex_lock(struct S3Mutex *mutex); - -// Unlock a mutex -void mutex_unlock(struct S3Mutex *mutex); - -// Destroy a mutex -void mutex_destroy(struct S3Mutex *mutex); - - // Utilities ----------------------------------------------------------------- // URL-encodes a string from [src] into [dest]. [dest] must have at least @@ -84,5 +69,10 @@ time_t parseIso8601Time(const char *str); 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); + #endif /* UTIL_H */ diff --git a/src/general.c b/src/general.c index 9904e5a..8f9996a 100644 --- a/src/general.c +++ b/src/general.c @@ -25,13 +25,10 @@ ************************************************************************** **/ #include <ctype.h> -#include <openssl/crypto.h> -#define OPENSSL_THREAD_DEFINES -#include <openssl/opensslconf.h> -#ifndef OPENSSL_THREADS -#error "Threading support required in OpenSSL library, but not provided" -#endif +#include <errno.h> // For gcrypt, which should include it itself +#include <gcrypt.h> #include <pthread.h> +#include <stdlib.h> // For gcrypt, which should include it itself #include <string.h> #include "request.h" #include "simplexml.h" @@ -39,71 +36,8 @@ static int initializeCountG = 0; -typedef pthread_mutex_t CRYPTO_dynlock_value; - -static pthread_mutex_t *pLocksG; - - -static unsigned long id_callback() -{ - return (unsigned long) pthread_self(); -} - - -static void locking_callback(int mode, int index, const char *file, int line) -{ - if (mode & CRYPTO_LOCK) { - pthread_mutex_lock(&(pLocksG[index])); - } - else { - pthread_mutex_unlock(&(pLocksG[index])); - } -} - - -static struct CRYPTO_dynlock_value *dynlock_create(const char *file, int line) -{ - pthread_mutex_t *ret = (pthread_mutex_t *) malloc(sizeof(pthread_mutex_t)); - pthread_mutex_init(ret, 0); - return (struct CRYPTO_dynlock_value *) ret; -} - - -static void dynlock_lock(int mode, struct CRYPTO_dynlock_value *pLock, - const char *file, int line) -{ - if (mode & CRYPTO_LOCK) { - pthread_mutex_lock((pthread_mutex_t *) pLock); - } - else { - pthread_mutex_unlock((pthread_mutex_t *) pLock); - } -} - - -static void dynlock_destroy(struct CRYPTO_dynlock_value *pLock, - const char *file, int line) -{ - pthread_mutex_destroy((pthread_mutex_t *) pLock); - free(pLock); -} - - -static void deinitialize_locks() -{ - CRYPTO_set_dynlock_destroy_callback(NULL); - CRYPTO_set_dynlock_lock_callback(NULL); - CRYPTO_set_dynlock_create_callback(NULL); - CRYPTO_set_locking_callback(NULL); - CRYPTO_set_id_callback(NULL); - - int count = CRYPTO_num_locks(); - for (int i = 0; i < count; i++) { - pthread_mutex_destroy(&(pLocksG[i])); - } - - free(pLocksG); -} +// libgcrypt macro which generates boilerplate for using pthreads +GCRY_THREAD_OPTION_PTHREAD_IMPL; S3Status S3_initialize(const char *userAgentInfo, int flags) @@ -112,31 +46,13 @@ S3Status S3_initialize(const char *userAgentInfo, int flags) return S3StatusOK; } - /* As required by the openssl library for thread support */ - int count = CRYPTO_num_locks(), i; - - if (!(pLocksG = - (pthread_mutex_t *) malloc(count * sizeof(pthread_mutex_t)))) { - return S3StatusOutOfMemory; - } - - for (i = 0; i < count; i++) { - pthread_mutex_init(&(pLocksG[i]), 0); + if (flags & S3_INIT_GCRYPT) { + gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread); + gcry_control(GCRYCTL_DISABLE_SECMEM); + gcry_check_version(0); } - CRYPTO_set_id_callback(&id_callback); - CRYPTO_set_locking_callback(&locking_callback); - CRYPTO_set_dynlock_create_callback(dynlock_create); - CRYPTO_set_dynlock_lock_callback(dynlock_lock); - CRYPTO_set_dynlock_destroy_callback(dynlock_destroy); - - S3Status status = request_api_initialize(userAgentInfo, flags); - if (status != S3StatusOK) { - deinitialize_locks(); - return status; - } - - return S3StatusOK; + return request_api_initialize(userAgentInfo, flags); } @@ -147,8 +63,6 @@ void S3_deinitialize() } request_api_deinitialize(); - - deinitialize_locks(); } const char *S3_get_status_name(S3Status status) diff --git a/src/request.c b/src/request.c index 40a16fc..a7c1347 100644 --- a/src/request.c +++ b/src/request.c @@ -25,10 +25,7 @@ ************************************************************************** **/ #include <ctype.h> -#include <openssl/bio.h> -#include <openssl/buffer.h> -#include <openssl/evp.h> -#include <openssl/hmac.h> +#include <gcrypt.h> #include <pthread.h> #include <stdlib.h> #include <string.h> @@ -708,26 +705,56 @@ static S3Status compose_auth_header(const RequestParams *params, signbuf_append("%s", values->canonicalizedResource); - unsigned int md_len; - unsigned char md[EVP_MAX_MD_SIZE]; - - HMAC(EVP_sha1(), params->secretAccessKey, strlen(params->secretAccessKey), - (unsigned char *) signbuf, len, md, &md_len); +// unsigned int md_len; +// unsigned char md[EVP_MAX_MD_SIZE]; +// +// HMAC(EVP_sha1(), params->secretAccessKey, strlen(params->secretAccessKey), +// (unsigned char *) signbuf, len, md, &md_len); +// +// BIO *base64 = BIO_push(BIO_new(BIO_f_base64()), BIO_new(BIO_s_mem())); +// BIO_write(base64, md, md_len); +// if (BIO_flush(base64) != 1) { +// BIO_free_all(base64); +// return S3StatusInternalError; +// } +// BUF_MEM *base64mem; +// BIO_get_mem_ptr(base64, &base64mem); + + // Generate a SHA-1 of the signbuf + + // Message Digest handle + gcry_md_hd_t mdh; + + // "Open" the Message Digest Handle - SHA-1 with HMAC feature + if (gcry_md_open + (&mdh, GCRY_MD_SHA1, GCRY_MD_FLAG_HMAC) != GPG_ERR_NO_ERROR) { + return S3StatusInternalError; + } - BIO *base64 = BIO_push(BIO_new(BIO_f_base64()), BIO_new(BIO_s_mem())); - BIO_write(base64, md, md_len); - if (BIO_flush(base64) != 1) { - BIO_free_all(base64); + // Set the key that will be used with the HMAC feature + if (gcry_md_setkey + (mdh, params->secretAccessKey, + strlen(params->secretAccessKey)) != GPG_ERR_NO_ERROR) { + gcry_md_close(mdh); return S3StatusInternalError; } - BUF_MEM *base64mem; - BIO_get_mem_ptr(base64, &base64mem); - snprintf(values->authorizationHeader, sizeof(values->authorizationHeader), - "Authorization: AWS %s:%.*s", params->accessKeyId, - base64mem->length - 1, base64mem->data); + // Specify the signbuf data to compute SHA-1 of + gcry_md_write(mdh, signbuf, len); + + // Get the results + unsigned int md_len = gcry_md_get_algo_dlen(GCRY_MD_SHA1); + unsigned char *md = gcry_md_read(mdh, GCRY_MD_SHA1); - BIO_free_all(base64); + // Now base-64 encode the results + unsigned char b64[((md_len + 1) * 4) / 3]; + int b64Len = base64Encode(md, md_len, b64); + + // Be sure to release the Message Digest handle + gcry_md_close(mdh); + + snprintf(values->authorizationHeader, sizeof(values->authorizationHeader), + "Authorization: AWS %s:%.*s", params->accessKeyId, b64Len, b64); return S3StatusOK; } @@ -171,3 +171,41 @@ uint64_t parseUnsignedInt(const char *str) return ret; } + + +int base64Encode(const unsigned char *in, int inLen, unsigned char *out) +{ + static const char *ENC = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + + unsigned char *original_out = out; + + while (inLen) { + // first 6 bits of char 1 + *out++ = ENC[*in >> 2]; + if (!--inLen) { + // last 2 bits of char 1, 4 bits of 0 + *out++ = ENC[(*in & 0x3) << 4]; + *out++ = '='; + *out++ = '='; + break; + } + // last 2 bits of char 1, first 4 bits of char 2 + *out++ = ENC[((*in & 0x3) << 4) | (*(in + 1) >> 4)]; + in++; + if (!--inLen) { + // last 4 bits of char 2, 2 bits of 0 + *out++ = ENC[(*in & 0xF) << 2]; + *out++ = '='; + break; + } + // last 4 bits of char 2, first 2 bits of char 3 + *out++ = ENC[((*in & 0xF) << 2) | (*(in + 1) >> 6)]; + in++; + // last 6 bits of char 3 + *out++ = ENC[*in & 0x3F]; + in++, inLen--; + } + + return (out - original_out); +} |