summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBryan Ischo <bryan@ischo.com>2008-08-13 13:27:47 +0000
committerBryan Ischo <bryan@ischo.com>2008-08-13 13:27:47 +0000
commit7fd73adff17c0511cf2c09da16d46d1a8e608866 (patch)
treefe09fe3dcdc6c68d9a17d80e64424c0e241c5247
parent06fcf9839f35d1bbac18819886375b8232d73f35 (diff)
downloadceph-libs3-7fd73adff17c0511cf2c09da16d46d1a8e608866.tar.gz
* Replaced openssl library with GnuTLS, libgcrypt, and hand-written base 64
encoding routine
-rw-r--r--GNUmakefile17
-rw-r--r--inc/libs3.h14
-rw-r--r--inc/util.h20
-rw-r--r--src/general.c106
-rw-r--r--src/request.c65
-rw-r--r--src/util.c38
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)
/** **************************************************************************
diff --git a/inc/util.h b/inc/util.h
index 6d24dcd..f400d4b 100644
--- a/inc/util.h
+++ b/inc/util.h
@@ -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;
}
diff --git a/src/util.c b/src/util.c
index 341c931..3c4f3c3 100644
--- a/src/util.c
+++ b/src/util.c
@@ -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);
+}