From cd27f0aa54831d808f08b9dda18a438e92669a8e Mon Sep 17 00:00:00 2001 From: Takeshi Nakatani Date: Tue, 6 May 2014 14:23:05 +0000 Subject: [PATCH] Supported another crypt libraries as GnuTLS and NSS, and added configure options --- configure.ac | 208 +++++++++++++++++++++++--------- src/Makefile.am | 15 ++- src/common_auth.cpp | 105 ++++++++++++++++ src/curl.cpp | 280 +++---------------------------------------- src/curl.h | 13 -- src/fdcache.cpp | 4 +- src/gnutls_auth.cpp | 259 +++++++++++++++++++++++++++++++++++++++ src/nss_auth.cpp | 195 ++++++++++++++++++++++++++++++ src/openssl_auth.cpp | 250 ++++++++++++++++++++++++++++++++++++++ src/s3fs.cpp | 15 ++- src/s3fs.h | 32 ----- src/s3fs_auth.h | 26 ++++ src/s3fs_util.cpp | 7 +- 13 files changed, 1034 insertions(+), 375 deletions(-) create mode 100644 src/common_auth.cpp create mode 100644 src/gnutls_auth.cpp create mode 100644 src/nss_auth.cpp create mode 100644 src/openssl_auth.cpp create mode 100644 src/s3fs_auth.h diff --git a/configure.ac b/configure.ac index 465a54a..6353040 100644 --- a/configure.ac +++ b/configure.ac @@ -26,81 +26,181 @@ AC_CANONICAL_SYSTEM AM_INIT_AUTOMAKE() AC_PROG_CXX +AC_PROG_CC CXXFLAGS="$CXXFLAGS -Wall -D_FILE_OFFSET_BITS=64" -PKG_CHECK_MODULES([DEPS], [fuse >= 2.8.4 libcurl >= 7.0 libxml-2.0 >= 2.6 libcrypto >= 0.9]) +dnl ---------------------------------------------- +dnl Choice SSL library +dnl ---------------------------------------------- +auth_lib=na +nettle_lib=no -dnl malloc_trim function -AC_CHECK_FUNCS(malloc_trim, , ) - -dnl Initializing NSS(temporally) -AC_MSG_CHECKING([Initializing libcurl build with NSS]) +dnl +dnl nettle library +dnl +AC_MSG_CHECKING([s3fs build with nettle(GnuTLS)]) AC_ARG_ENABLE( - nss-init, - [ - AS_HELP_STRING( - [--enable-nss-init], - [Inilializing libcurl with NSS (default is no)] - ) - ], + nettle-lib, + [AS_HELP_STRING([--enable-nettle-lib], [s3fs build with nettle in GnuTLS(default no)])], [ case "${enableval}" in yes) AC_MSG_RESULT(yes) - nss_init_enabled=yes + nettle_lib=yes + ;; + *) + AC_MSG_RESULT(no) + ;; + esac + ], + [ + AC_MSG_RESULT(no) + ]) + +dnl +dnl use openssl library for ssl +dnl +AC_MSG_CHECKING([s3fs build with OpenSSL]) +AC_ARG_ENABLE( + openssl-lib, + [AS_HELP_STRING([--enable-openssl-lib], [s3fs build with OpenSSL(default is no)])], + [ + case "${enableval}" in + yes) + AC_MSG_RESULT(yes) + AS_IF( + [test $nettle_lib = no], + [auth_lib=openssl], + [AC_MSG_ERROR([could not set openssl with nettle, nettle is only for gnutls library])]) + ;; + *) + AC_MSG_RESULT(no) + ;; + esac + ], + [ + AC_MSG_RESULT(no) + ]) + +dnl +dnl use GnuTLS library for ssl +dnl +AC_MSG_CHECKING([s3fs build with GnuTLS]) +AC_ARG_ENABLE( + gnutls-lib, + [AS_HELP_STRING([--enable-gnutls-lib], [s3fs build with GnuTLS(default is no)])], + [ + case "${enableval}" in + yes) + AC_MSG_RESULT(yes) + AS_IF( + [test $auth_lib = na], + [ + AS_IF( + [test $nettle_lib = no], + [auth_lib=gnutls], + [auth_lib=nettle]) + ], + [AC_MSG_ERROR([could not set gnutls because already set another ssl library])]) + ;; + *) + AC_MSG_RESULT(no) + ;; + esac + ], + [ + AC_MSG_RESULT(no) + ]) + +dnl +dnl use nss library for ssl +dnl +AC_MSG_CHECKING([s3fs build with NSS]) +AC_ARG_ENABLE( + nss-lib, + [AS_HELP_STRING([--enable-nss-lib], [s3fs build with NSS(default is no)])], + [ + case "${enableval}" in + yes) + AC_MSG_RESULT(yes) + AS_IF( + [test $auth_lib = na], + [ + AS_IF( + [test $nettle_lib = no], + [auth_lib=nss], + [AC_MSG_ERROR([could not set openssl with nettle, nettle is only for gnutls library])]) + ], + [AC_MSG_ERROR([could not set nss because already set another ssl library])]) ;; *) AC_MSG_RESULT(no) - nss_init_enabled=no ;; esac ], [ AC_MSG_RESULT(no) - nss_init_enabled=no ]) AS_IF( - [test $nss_init_enabled = yes], - [ - AC_DEFINE(NSS_INIT_ENABLED, 1) - AC_CHECK_LIB(nss3, NSS_NoDB_Init, , [AC_MSG_ERROR(not found NSS libraries)]) - AC_CHECK_LIB(plds4, PL_ArenaFinish, , [AC_MSG_ERROR(not found PL_ArenaFinish)]) - AC_CHECK_LIB(nspr4, PR_Cleanup, , [AC_MSG_ERROR(not found PR_Cleanup)]) - AC_CHECK_HEADER(nss.h, , [AC_MSG_ERROR(not found nss.h)]) - AC_CHECK_HEADER(nspr4/prinit.h, , [AC_MSG_ERROR(not found prinit.h)]) - AC_PATH_PROG(NSSCONFIG, [nss-config], no) - AS_IF( - [test $NSSCONFIG = no], - [ - DEPS_CFLAGS="$DEPS_CFLAGS -I/usr/include/nss3" - DEPS_LIBS="$DEPS_LIBS -lnss3" - ], - [ - addcflags=`nss-config --cflags` - DEPS_CFLAGS="$DEPS_CFLAGS $addcflags" - dnl addlib=`nss-config --libs` - dnl DEPS_LIBS="$DEPS_LIBS $addlib" - DEPS_LIBS="$DEPS_LIBS -lnss3" - ]) - AC_PATH_PROG(NSPRCONFIG, [nspr-config], no) - AS_IF( - [test $NSPRCONFIG = no], - [ - DEPS_CFLAGS="$DEPS_CFLAGS -I/usr/include/nspr4" - DEPS_LIBS="$DEPS_LIBS -lnspr4 -lplds4" - ], - [ - addcflags=`nspr-config --cflags` - DEPS_CFLAGS="$DEPS_CFLAGS $addcflags" - dnl addlib=`nspr-config --libs` - dnl DEPS_LIBS="$DEPS_LIBS $addlib" - DEPS_LIBS="$DEPS_LIBS -lnspr4 -lplds4" - ]) - ]) + [test $auth_lib = na], + [auth_lib=openssl]) -AS_UNSET(nss_enabled) +AC_MSG_CHECKING([compile s3fs with]) +case "${auth_lib}" in +openssl) + AC_MSG_RESULT(OpenSSL) + PKG_CHECK_MODULES([DEPS], [fuse >= 2.8.4 libcurl >= 7.0 libxml-2.0 >= 2.6 libcrypto >= 0.9]) + ;; +gnutls) + AC_MSG_RESULT(GnuTLS-gcrypt) + gnutls_nettle="" + AC_CHECK_LIB(gnutls, gcry_control, [gnutls_nettle=0]) + AS_IF([test "$gnutls_nettle" = ""], [AC_CHECK_LIB(gcrypt, gcry_control, [gnutls_nettle=0])]) + AS_IF([test $gnutls_nettle = 0], + [ + PKG_CHECK_MODULES([DEPS], [fuse >= 2.8.4 libcurl >= 7.0 libxml-2.0 >= 2.6 gnutls >= 2.12.0 ]) + LIBS="-lgnutls -lgcrypt $LIBS" + AC_MSG_CHECKING([gnutls is build with]) + AC_MSG_RESULT(gcrypt) + ], + [AC_MSG_ERROR([GnuTLS found, but gcrypt not found])]) + ;; +nettle) + AC_MSG_RESULT(GnuTLS-nettle) + gnutls_nettle="" + AC_CHECK_LIB(gnutls, nettle_MD5Init, [gnutls_nettle=1]) + AS_IF([test "$gnutls_nettle" = ""], [AC_CHECK_LIB(nettle, nettle_MD5Init, [gnutls_nettle=1])]) + AS_IF([test $gnutls_nettle = 1], + [ + PKG_CHECK_MODULES([DEPS], [fuse >= 2.8.4 libcurl >= 7.0 libxml-2.0 >= 2.6 nettle >= 2.7.1 ]) + LIBS="-lgnutls -lnettle $LIBS" + AC_MSG_CHECKING([gnutls is build with]) + AC_MSG_RESULT(nettle) + ], + [AC_MSG_ERROR([GnuTLS found, but nettle not found])]) + ;; +nss) + AC_MSG_RESULT(NSS) + PKG_CHECK_MODULES([DEPS], [fuse >= 2.8.4 libcurl >= 7.0 libxml-2.0 >= 2.6 nss >= 3.15.0 ]) + ;; +*) + AC_MSG_ERROR([unknown ssl library type.]) + ;; +esac + +AM_CONDITIONAL([USE_SSL_OPENSSL], [test "$auth_lib" = openssl]) +AM_CONDITIONAL([USE_SSL_GNUTLS], [test "$auth_lib" = gnutls -o "$auth_lib" = nettle]) +AM_CONDITIONAL([USE_GNUTLS_NETTLE], [test "$auth_lib" = nettle]) +AM_CONDITIONAL([USE_SSL_NSS], [test "$auth_lib" = nss]) + +dnl ---------------------------------------------- +dnl end of ssl library +dnl ---------------------------------------------- + +dnl malloc_trim function +AC_CHECK_FUNCS(malloc_trim, , ) AC_CONFIG_FILES(Makefile src/Makefile test/Makefile doc/Makefile) AC_OUTPUT diff --git a/src/Makefile.am b/src/Makefile.am index 6ea78cb..b8085d7 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,7 +1,20 @@ bin_PROGRAMS=s3fs AM_CPPFLAGS = $(DEPS_CFLAGS) +if USE_GNUTLS_NETTLE + AM_CPPFLAGS += -DUSE_GNUTLS_NETTLE +endif + +s3fs_SOURCES = s3fs.cpp s3fs.h curl.cpp curl.h cache.cpp cache.h string_util.cpp string_util.h s3fs_util.cpp s3fs_util.h fdcache.cpp fdcache.h common_auth.cpp s3fs_auth.h common.h +if USE_SSL_OPENSSL + s3fs_SOURCES += openssl_auth.cpp +endif +if USE_SSL_GNUTLS + s3fs_SOURCES += gnutls_auth.cpp +endif +if USE_SSL_NSS + s3fs_SOURCES += nss_auth.cpp +endif -s3fs_SOURCES = s3fs.cpp s3fs.h curl.cpp curl.h cache.cpp cache.h string_util.cpp string_util.h s3fs_util.cpp s3fs_util.h fdcache.cpp fdcache.h common.h s3fs_LDADD = $(DEPS_LIBS) diff --git a/src/common_auth.cpp b/src/common_auth.cpp new file mode 100644 index 0000000..dd54772 --- /dev/null +++ b/src/common_auth.cpp @@ -0,0 +1,105 @@ +/* + * s3fs - FUSE-based file system backed by Amazon S3 + * + * Copyright 2007-2008 Randy Rizun + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include +#include +#include +#include + +#include "s3fs_auth.h" + +using namespace std; + +//------------------------------------------------------------------- +// Utility Function +//------------------------------------------------------------------- +char* s3fs_base64(unsigned char* input, size_t length) +{ + static const char* base = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; + char* result; + + if(!input || '\0' == input[0] || 0 >= length){ + return NULL; + } + if(NULL == (result = (char*)malloc((((length / 3) + 1) * 4 + 1) * sizeof(char)))){ + return NULL; // ENOMEM + } + + unsigned char parts[4]; + size_t rpos; + size_t wpos; + for(rpos = 0, wpos = 0; rpos < length; rpos += 3){ + parts[0] = (input[rpos] & 0xfc) >> 2; + parts[1] = ((input[rpos] & 0x03) << 4) | ((((rpos + 1) < length ? input[rpos + 1] : 0x00) & 0xf0) >> 4); + parts[2] = (rpos + 1) < length ? (((input[rpos + 1] & 0x0f) << 2) | ((((rpos + 2) < length ? input[rpos + 2] : 0x00) & 0xc0) >> 6)) : 0x40; + parts[3] = (rpos + 2) < length ? (input[rpos + 2] & 0x3f) : 0x40; + + result[wpos++] = base[parts[0]]; + result[wpos++] = base[parts[1]]; + result[wpos++] = base[parts[2]]; + result[wpos++] = base[parts[3]]; + } + result[wpos] = '\0'; + + return result; +} + +string s3fs_get_content_md5(int fd) +{ + unsigned char* md5hex; + char* base64; + string Signature; + + if(NULL == (md5hex = s3fs_md5hexsum(fd, 0, -1))){ + return string(""); + } + if(NULL == (base64 = s3fs_base64(md5hex, get_md5_digest_length()))){ + return string(""); // ENOMEM + } + free(md5hex); + + Signature = base64; + free(base64); + + return Signature; +} + +string s3fs_md5sum(int fd, off_t start, ssize_t size) +{ + size_t digestlen = get_md5_digest_length(); + char md5[2 * digestlen + 1]; + char hexbuf[3]; + unsigned char* md5hex; + + if(NULL == (md5hex = s3fs_md5hexsum(fd, start, size))){ + return string(""); + } + + memset(md5, 0, 2 * digestlen + 1); + for(size_t pos = 0; pos < digestlen; pos++){ + snprintf(hexbuf, 3, "%02x", md5hex[pos]); + strncat(md5, hexbuf, 2); + } + free(md5hex); + + return string(md5); +} + +/// END diff --git a/src/curl.cpp b/src/curl.cpp index 08a1cf6..7b62e9e 100644 --- a/src/curl.cpp +++ b/src/curl.cpp @@ -31,11 +31,6 @@ #include #include #include -#include -#include -#include -#include -#include #include #include #include @@ -52,6 +47,7 @@ #include "string_util.h" #include "s3fs.h" #include "s3fs_util.h" +#include "s3fs_auth.h" using namespace std; @@ -148,7 +144,6 @@ const char* BodyData::str(void) const pthread_mutex_t S3fsCurl::curl_handles_lock; pthread_mutex_t S3fsCurl::curl_share_lock[SHARE_MUTEX_MAX]; -pthread_mutex_t* S3fsCurl::crypt_mutex = NULL; bool S3fsCurl::is_initglobal_done = false; CURLSH* S3fsCurl::hCurlShare = NULL; bool S3fsCurl::is_dns_cache = true; // default @@ -168,7 +163,6 @@ string S3fsCurl::AWSAccessToken; time_t S3fsCurl::AWSAccessTokenExpire= 0; string S3fsCurl::IAM_role; long S3fsCurl::ssl_verify_hostname = 1; // default(original code...) -const EVP_MD* S3fsCurl::evp_md = EVP_sha1(); curltime_t S3fsCurl::curl_times; curlprogress_t S3fsCurl::curl_progress; string S3fsCurl::curl_ca_bundle; @@ -340,97 +334,12 @@ void S3fsCurl::UnlockCurlShare(CURL* handle, curl_lock_data nLockData, void* use bool S3fsCurl::InitCryptMutex(void) { - if(S3fsCurl::crypt_mutex){ - FPRNNN("crypt_mutex is not NULL, destory it."); - if(!S3fsCurl::DestroyCryptMutex()){ - DPRN("Failed to destroy crypt mutex"); - return false; - } - } - if(NULL == (S3fsCurl::crypt_mutex = static_cast(malloc(CRYPTO_num_locks() * sizeof(pthread_mutex_t))))){ - DPRNCRIT("Could not allocate memory for crypt mutex"); - return false; - } - for(int cnt = 0; cnt < CRYPTO_num_locks(); cnt++){ - pthread_mutex_init(&S3fsCurl::crypt_mutex[cnt], NULL); - } - // static lock - CRYPTO_set_locking_callback(S3fsCurl::CryptMutexLock); - CRYPTO_set_id_callback(S3fsCurl::CryptGetThreadid); - // dynamic lock - CRYPTO_set_dynlock_create_callback(S3fsCurl::CreateDynCryptMutex); - CRYPTO_set_dynlock_lock_callback(S3fsCurl::DynCryptMutexLock); - CRYPTO_set_dynlock_destroy_callback(S3fsCurl::DestoryDynCryptMutex); - - return true; + return s3fs_init_crypt_mutex(); } bool S3fsCurl::DestroyCryptMutex(void) { - if(!S3fsCurl::crypt_mutex){ - return true; - } - - CRYPTO_set_dynlock_destroy_callback(NULL); - CRYPTO_set_dynlock_lock_callback(NULL); - CRYPTO_set_dynlock_create_callback(NULL); - CRYPTO_set_id_callback(NULL); - CRYPTO_set_locking_callback(NULL); - - for(int cnt = 0; cnt < CRYPTO_num_locks(); cnt++){ - pthread_mutex_destroy(&S3fsCurl::crypt_mutex[cnt]); - } - CRYPTO_cleanup_all_ex_data(); - free(S3fsCurl::crypt_mutex); - S3fsCurl::crypt_mutex = NULL; - - return true; -} - -void S3fsCurl::CryptMutexLock(int mode, int pos, const char* file, int line) -{ - if(S3fsCurl::crypt_mutex){ - if(mode & CRYPTO_LOCK){ - pthread_mutex_lock(&S3fsCurl::crypt_mutex[pos]); - }else{ - pthread_mutex_unlock(&S3fsCurl::crypt_mutex[pos]); - } - } -} - -unsigned long S3fsCurl::CryptGetThreadid(void) -{ - return (unsigned long)pthread_self(); -} - -struct CRYPTO_dynlock_value* S3fsCurl::CreateDynCryptMutex(const char* file, int line) -{ - struct CRYPTO_dynlock_value* dyndata; - - if(NULL == (dyndata = (struct CRYPTO_dynlock_value*)malloc(sizeof(struct CRYPTO_dynlock_value)))){ - return NULL; - } - pthread_mutex_init(&(dyndata->dyn_mutex), NULL); - return dyndata; -} - -void S3fsCurl::DynCryptMutexLock(int mode, struct CRYPTO_dynlock_value* dyndata, const char* file, int line) -{ - if(dyndata){ - if(mode & CRYPTO_LOCK){ - pthread_mutex_lock(&(dyndata->dyn_mutex)); - }else{ - pthread_mutex_unlock(&(dyndata->dyn_mutex)); - } - } -} - -void S3fsCurl::DestoryDynCryptMutex(struct CRYPTO_dynlock_value* dyndata, const char* file, int line) -{ - if(dyndata){ - pthread_mutex_destroy(&(dyndata->dyn_mutex)); - free(dyndata); - } + return s3fs_destroy_crypt_mutex(); } // homegrown timeout mechanism @@ -1651,10 +1560,6 @@ int S3fsCurl::RequestPerform(void) // string S3fsCurl::CalcSignature(string method, string strMD5, string content_type, string date, string resource) { - int ret; - int bytes_written; - int offset; - int write_attempts = 0; string Signature; string StringToSign; @@ -1682,74 +1587,20 @@ string S3fsCurl::CalcSignature(string method, string strMD5, string content_type int key_len = S3fsCurl::AWSSecretAccessKey.size(); const unsigned char* sdata = reinterpret_cast(StringToSign.data()); int sdata_len = StringToSign.size(); - unsigned char md[EVP_MAX_MD_SIZE]; - unsigned int md_len; + unsigned char* md = NULL; + unsigned int md_len = 0;; - HMAC(S3fsCurl::evp_md, key, key_len, sdata, sdata_len, md, &md_len); + s3fs_HMAC(key, key_len, sdata, sdata_len, &md, &md_len); - BIO* b64 = BIO_new(BIO_f_base64()); - BIO* bmem = BIO_new(BIO_s_mem()); - b64 = BIO_push(b64, bmem); - - offset = 0; - for(;;){ - bytes_written = BIO_write(b64, &(md[offset]), md_len); - write_attempts++; - // -1 indicates that an error occurred, or a temporary error, such as - // the server is busy, occurred and we need to retry later. - // BIO_write can do a short write, this code addresses this condition - if(bytes_written <= 0){ - // Indicates whether a temporary error occurred or a failure to - // complete the operation occurred - if((ret = BIO_should_retry(b64))){ - // Wait until the write can be accomplished - if(write_attempts <= 10){ - continue; - } - // Too many write attempts - DPRNNN("Failure during BIO_write, returning null String"); - CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, b64, &b64->ex_data); - BIO_free_all(b64); - Signature.clear(); - return Signature; - - }else{ - // If not a retry then it is an error - DPRNNN("Failure during BIO_write, returning null String"); - CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, b64, &b64->ex_data); - BIO_free_all(b64); - Signature.clear(); - return Signature; - } - } - - // The write request succeeded in writing some Bytes - offset += bytes_written; - md_len -= bytes_written; - - // If there is no more data to write, the request sending has been - // completed - if(md_len <= 0){ - break; - } + char* base64; + if(NULL == (base64 = s3fs_base64(md, md_len))){ + free(md); + return string(""); // ENOMEM } + free(md); - // Flush the data - ret = BIO_flush(b64); - if(ret <= 0){ - DPRNNN("Failure during BIO_flush, returning null String"); - CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, b64, &b64->ex_data); - BIO_free_all(b64); - Signature.clear(); - return Signature; - } - - BUF_MEM *bptr; - BIO_get_mem_ptr(b64, &bptr); - Signature.assign(bptr->data, bptr->length - 1); - - CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, b64, &b64->ex_data); - BIO_free_all(b64); + Signature = base64; + free(base64); return Signature; } @@ -2094,7 +1945,7 @@ int S3fsCurl::PutRequest(const char* tpath, headers_t& meta, int fd, bool ow_sse string strMD5; if(-1 != fd && S3fsCurl::is_content_md5){ - strMD5 = GetContentMD5(fd); + strMD5 = s3fs_get_content_md5(fd); requestHeaders = curl_slist_sort_insert(requestHeaders, string("Content-MD5: " + strMD5).c_str()); } @@ -2617,7 +2468,7 @@ int S3fsCurl::UploadMultipartPostSetup(const char* tpath, int part_num, string& } // make md5 and file pointer - partdata.etag = md5sum(partdata.fd, partdata.startpos, partdata.size); + partdata.etag = s3fs_md5sum(partdata.fd, partdata.startpos, partdata.size); if(partdata.etag.empty()){ DPRN("Could not make md5 for file(part %d)", part_num); return -1; @@ -3407,107 +3258,6 @@ bool AdditionalHeader::Dump(void) const //------------------------------------------------------------------- // Utility functions //------------------------------------------------------------------- -string GetContentMD5(int fd) -{ - BIO* b64; - BIO* bmem; - BUF_MEM* bptr; - string Signature; - unsigned char* md5hex; - - if(NULL == (md5hex = md5hexsum(fd, 0, -1))){ - return string(""); - } - - b64 = BIO_new(BIO_f_base64()); - bmem = BIO_new(BIO_s_mem()); - b64 = BIO_push(b64, bmem); - - BIO_write(b64, md5hex, MD5_DIGEST_LENGTH); - free(md5hex); - if(1 != BIO_flush(b64)){ - CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, b64, &b64->ex_data); - BIO_free_all(b64); - return string(""); - } - BIO_get_mem_ptr(b64, &bptr); - Signature.assign(bptr->data, bptr->length - 1); - - CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, b64, &b64->ex_data); - BIO_free_all(b64); - - return Signature; -} - -unsigned char* md5hexsum(int fd, off_t start, ssize_t size) -{ - MD5_CTX c; - char buf[512]; - ssize_t bytes; - unsigned char* result; - - if(-1 == size){ - struct stat st; - if(-1 == fstat(fd, &st)){ - return NULL; - } - size = static_cast(st.st_size); - } - - // seek to top of file. - if(-1 == lseek(fd, start, SEEK_SET)){ - return NULL; - } - if(NULL == (result = (unsigned char*)malloc(MD5_DIGEST_LENGTH))){ - return NULL; - } - - memset(buf, 0, 512); - MD5_Init(&c); - for(ssize_t total = 0; total < size; total += bytes){ - bytes = 512 < (size - total) ? 512 : (size - total); - bytes = read(fd, buf, bytes); - if(0 == bytes){ - // end of file - break; - }else if(-1 == bytes){ - // error - DPRNNN("file read error(%d)", errno); - free(result); - return NULL; - } - MD5_Update(&c, buf, bytes); - memset(buf, 0, 512); - } - MD5_Final(result, &c); - - if(-1 == lseek(fd, start, SEEK_SET)){ - free(result); - return NULL; - } - return result; -} - -string md5sum(int fd, off_t start, ssize_t size) -{ - char md5[2 * MD5_DIGEST_LENGTH + 1]; - char hexbuf[3]; - unsigned char* md5hex; - - if(NULL == (md5hex = md5hexsum(fd, start, size))){ - return string(""); - } - - memset(md5, 0, 2 * MD5_DIGEST_LENGTH + 1); - for(int i = 0; i < MD5_DIGEST_LENGTH; i++) { - snprintf(hexbuf, 3, "%02x", md5hex[i]); - strncat(md5, hexbuf, 2); - } - free(md5hex); - - return string(md5); -} - // // curl_slist_sort_insert // This function is like curl_slist_append function, but this adds data by a-sorting. diff --git a/src/curl.h b/src/curl.h index 169d9ce..9b5143c 100644 --- a/src/curl.h +++ b/src/curl.h @@ -106,12 +106,6 @@ typedef std::map iamcredmap_t; #define SHARE_MUTEX_SSL_SESSION 1 #define SHARE_MUTEX_MAX 2 -// internal use struct for openssl -struct CRYPTO_dynlock_value -{ - pthread_mutex_t dyn_mutex; -}; - // Class for lapping curl // class S3fsCurl @@ -140,7 +134,6 @@ class S3fsCurl // class variables static pthread_mutex_t curl_handles_lock; static pthread_mutex_t curl_share_lock[SHARE_MUTEX_MAX]; - static pthread_mutex_t* crypt_mutex; static bool is_initglobal_done; static CURLSH* hCurlShare; static bool is_dns_cache; @@ -160,7 +153,6 @@ class S3fsCurl static time_t AWSAccessTokenExpire; static std::string IAM_role; static long ssl_verify_hostname; - static const EVP_MD* evp_md; static curltime_t curl_times; static curlprogress_t curl_progress; static std::string curl_ca_bundle; @@ -206,11 +198,6 @@ class S3fsCurl static void UnlockCurlShare(CURL* handle, curl_lock_data nLockData, void* useptr); static bool InitCryptMutex(void); static bool DestroyCryptMutex(void); - static void CryptMutexLock(int mode, int pos, const char* file, int line); - static unsigned long CryptGetThreadid(void); - static struct CRYPTO_dynlock_value* CreateDynCryptMutex(const char* file, int line); - static void DynCryptMutexLock(int mode, struct CRYPTO_dynlock_value* dyndata, const char* file, int line); - static void DestoryDynCryptMutex(struct CRYPTO_dynlock_value* dyndata, const char* file, int line); static int CurlProgress(void *clientp, double dltotal, double dlnow, double ultotal, double ulnow); static bool InitMimeType(const char* MimeFile = NULL); diff --git a/src/fdcache.cpp b/src/fdcache.cpp index f290931..6240b64 100644 --- a/src/fdcache.cpp +++ b/src/fdcache.cpp @@ -31,7 +31,6 @@ #include #include #include -#include #include #include #include @@ -797,7 +796,7 @@ int FdEntity::Load(off_t start, off_t size) break; } // download - if((*iter)->bytes >= (2 * S3fsCurl::GetMultipartSize()) && !nomultipart){ // default 20MB + if((*iter)->bytes >= static_cast(2 * S3fsCurl::GetMultipartSize()) && !nomultipart){ // default 20MB // parallel request // Additional time is needed for large files time_t backup = 0; @@ -1197,3 +1196,4 @@ bool FdManager::Close(FdEntity* ent) return false; } +/// END diff --git a/src/gnutls_auth.cpp b/src/gnutls_auth.cpp new file mode 100644 index 0000000..2a53cdc --- /dev/null +++ b/src/gnutls_auth.cpp @@ -0,0 +1,259 @@ +/* + * s3fs - FUSE-based file system backed by Amazon S3 + * + * Copyright 2007-2008 Randy Rizun + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef USE_GNUTLS_NETTLE +#include +#include +#include +#endif +#include +#include + +#include "common.h" +#include "s3fs_auth.h" + +using namespace std; + +//------------------------------------------------------------------- +// Utility Function for version +//------------------------------------------------------------------- +#ifdef USE_GNUTLS_NETTLE + +const char* s3fs_crypt_lib_name(void) +{ + static const char version[] = "GnuTLS(nettle)"; + + return version; +} + +#else // USE_GNUTLS_NETTLE + +const char* s3fs_crypt_lib_name(void) +{ + static const char version[] = "GnuTLS(gcrypt)"; + + return version; +} + +#endif // USE_GNUTLS_NETTLE + +//------------------------------------------------------------------- +// Utility Function for global init +//------------------------------------------------------------------- +bool s3fs_init_global_ssl(void) +{ + if(GNUTLS_E_SUCCESS != gnutls_global_init()){ + return false; + } + return true; +} + +bool s3fs_destroy_global_ssl(void) +{ + gnutls_global_deinit(); + return true; +} + +//------------------------------------------------------------------- +// Utility Function for crypt lock +//------------------------------------------------------------------- +bool s3fs_init_crypt_mutex(void) +{ + return true; +} + +bool s3fs_destroy_crypt_mutex(void) +{ + return true; +} + +//------------------------------------------------------------------- +// Utility Function for HMAC +//------------------------------------------------------------------- +#ifdef USE_GNUTLS_NETTLE + +bool s3fs_HMAC(const void* key, size_t keylen, const unsigned char* data, size_t datalen, unsigned char** digest, unsigned int* digestlen) +{ + if(!key || 0 >= keylen || !data || 0 >= datalen || !digest || !digestlen){ + return false; + } + + if(NULL == (*digest = (unsigned char*)malloc(SHA1_DIGEST_SIZE))){ + return false; + } + + struct hmac_sha1_ctx ctx_hmac; + hmac_sha1_set_key(&ctx_hmac, keylen, reinterpret_cast(key)); + hmac_sha1_update(&ctx_hmac, datalen, reinterpret_cast(data)); + hmac_sha1_digest(&ctx_hmac, SHA1_DIGEST_SIZE, reinterpret_cast(*digest)); + *digestlen = SHA1_DIGEST_SIZE; + + return true; +} + +#else // USE_GNUTLS_NETTLE + +bool s3fs_HMAC(const void* key, size_t keylen, const unsigned char* data, size_t datalen, unsigned char** digest, unsigned int* digestlen) +{ + if(!key || 0 >= keylen || !data || 0 >= datalen || !digest || !digestlen){ + return false; + } + + if(0 >= (*digestlen = gnutls_hmac_get_len(GNUTLS_MAC_SHA1))){ + return false; + } + if(NULL == (*digest = (unsigned char*)malloc(*digestlen + 1))){ + return false; + } + if(0 > gnutls_hmac_fast(GNUTLS_MAC_SHA1, key, keylen, data, datalen, *digest)){ + free(*digest); + *digest = NULL; + return false; + } + return true; +} + +#endif // USE_GNUTLS_NETTLE + +//------------------------------------------------------------------- +// Utility Function for MD5 +//------------------------------------------------------------------- +#define MD5_DIGEST_LENGTH 16 + +size_t get_md5_digest_length(void) +{ + return MD5_DIGEST_LENGTH; +} + +#ifdef USE_GNUTLS_NETTLE +unsigned char* s3fs_md5hexsum(int fd, off_t start, ssize_t size) +{ + struct md5_ctx ctx_md5; + unsigned char buf[512]; + ssize_t bytes; + unsigned char* result; + + // seek to top of file. + if(-1 == lseek(fd, start, SEEK_SET)){ + return NULL; + } + + memset(buf, 0, 512); + md5_init(&ctx_md5); + + for(ssize_t total = 0; total < size; total += bytes){ + bytes = 512 < (size - total) ? 512 : (size - total); + bytes = read(fd, buf, bytes); + if(0 == bytes){ + // end of file + break; + }else if(-1 == bytes){ + // error + DPRNNN("file read error(%d)", errno); + return NULL; + } + md5_update(&ctx_md5, bytes, buf); + memset(buf, 0, 512); + } + if(NULL == (result = (unsigned char*)malloc(get_md5_digest_length()))){ + return NULL; + } + md5_digest(&ctx_md5, get_md5_digest_length(), result); + + if(-1 == lseek(fd, start, SEEK_SET)){ + free(result); + return NULL; + } + + return result; +} + +#else // USE_GNUTLS_NETTLE + +unsigned char* s3fs_md5hexsum(int fd, off_t start, ssize_t size) +{ + gcry_md_hd_t ctx_md5; + gcry_error_t err; + char buf[512]; + ssize_t bytes; + unsigned char* result; + + if(-1 == size){ + struct stat st; + if(-1 == fstat(fd, &st)){ + return NULL; + } + size = static_cast(st.st_size); + } + + // seek to top of file. + if(-1 == lseek(fd, start, SEEK_SET)){ + return NULL; + } + + memset(buf, 0, 512); + if(GPG_ERR_NO_ERROR != (err = gcry_md_open(&ctx_md5, GCRY_MD_MD5, 0))){ + DPRNN("MD5 context creation failure: %s/%s", gcry_strsource(err), gcry_strerror(err)); + return NULL; + } + + for(ssize_t total = 0; total < size; total += bytes){ + bytes = 512 < (size - total) ? 512 : (size - total); + bytes = read(fd, buf, bytes); + if(0 == bytes){ + // end of file + break; + }else if(-1 == bytes){ + // error + DPRNNN("file read error(%d)", errno); + return NULL; + } + gcry_md_write(ctx_md5, buf, bytes); + memset(buf, 0, 512); + } + if(NULL == (result = (unsigned char*)malloc(get_md5_digest_length()))){ + return NULL; + } + memcpy(result, gcry_md_read(ctx_md5, 0), get_md5_digest_length()); + gcry_md_close(ctx_md5); + + if(-1 == lseek(fd, start, SEEK_SET)){ + free(result); + return NULL; + } + + return result; +} + +#endif // USE_GNUTLS_NETTLE + +/// END diff --git a/src/nss_auth.cpp b/src/nss_auth.cpp new file mode 100644 index 0000000..7e955ea --- /dev/null +++ b/src/nss_auth.cpp @@ -0,0 +1,195 @@ +/* + * s3fs - FUSE-based file system backed by Amazon S3 + * + * Copyright 2007-2008 Randy Rizun + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "common.h" +#include "s3fs_auth.h" + +using namespace std; + +//------------------------------------------------------------------- +// Utility Function for version +//------------------------------------------------------------------- +const char* s3fs_crypt_lib_name(void) +{ + static const char version[] = "NSS"; + + return version; +} + +//------------------------------------------------------------------- +// Utility Function for global init +//------------------------------------------------------------------- +bool s3fs_init_global_ssl(void) +{ + NSS_NoDB_Init(NULL); + return true; +} + +bool s3fs_destroy_global_ssl(void) +{ + NSS_Shutdown(); + PL_ArenaFinish(); + PR_Cleanup(); + return true; +} + +//------------------------------------------------------------------- +// Utility Function for crypt lock +//------------------------------------------------------------------- +bool s3fs_init_crypt_mutex(void) +{ + return true; +} + +bool s3fs_destroy_crypt_mutex(void) +{ + return true; +} + +//------------------------------------------------------------------- +// Utility Function for HMAC +//------------------------------------------------------------------- +bool s3fs_HMAC(const void* key, size_t keylen, const unsigned char* data, size_t datalen, unsigned char** digest, unsigned int* digestlen) +{ + if(!key || 0 >= keylen || !data || 0 >= datalen || !digest || !digestlen){ + return false; + } + + PK11SlotInfo* Slot; + PK11SymKey* pKey; + PK11Context* Context; + SECStatus SecStatus; + unsigned char tmpdigest[64]; + SECItem KeySecItem = {siBuffer, reinterpret_cast(const_cast(key)), keylen}; + SECItem NullSecItem = {siBuffer, NULL, 0}; + + if(NULL == (Slot = PK11_GetInternalKeySlot())){ + return false; + } + if(NULL == (pKey = PK11_ImportSymKey(Slot, CKM_SHA_1_HMAC, PK11_OriginUnwrap, CKA_SIGN, &KeySecItem, NULL))){ + PK11_FreeSlot(Slot); + return false; + } + if(NULL == (Context = PK11_CreateContextBySymKey(CKM_SHA_1_HMAC, CKA_SIGN, pKey, &NullSecItem))){ + PK11_FreeSymKey(pKey); + PK11_FreeSlot(Slot); + return false; + } + + *digestlen = 0; + if(SECSuccess != (SecStatus = PK11_DigestBegin(Context)) || + SECSuccess != (SecStatus = PK11_DigestOp(Context, data, datalen)) || + SECSuccess != (SecStatus = PK11_DigestFinal(Context, tmpdigest, digestlen, sizeof(tmpdigest))) ) + { + PK11_DestroyContext(Context, PR_TRUE); + PK11_FreeSymKey(pKey); + PK11_FreeSlot(Slot); + return false; + } + PK11_DestroyContext(Context, PR_TRUE); + PK11_FreeSymKey(pKey); + PK11_FreeSlot(Slot); + + if(NULL == (*digest = (unsigned char*)malloc(*digestlen))){ + return false; + } + memcpy(*digest, tmpdigest, *digestlen); + + return true; +} + +//------------------------------------------------------------------- +// Utility Function for MD5 +//------------------------------------------------------------------- +size_t get_md5_digest_length(void) +{ + return MD5_LENGTH; +} + +unsigned char* s3fs_md5hexsum(int fd, off_t start, ssize_t size) +{ + PK11Context* md5ctx; + unsigned char buf[512]; + ssize_t bytes; + unsigned char* result; + unsigned int md5outlen; + + if(-1 == size){ + struct stat st; + if(-1 == fstat(fd, &st)){ + return NULL; + } + size = static_cast(st.st_size); + } + + // seek to top of file. + if(-1 == lseek(fd, start, SEEK_SET)){ + return NULL; + } + + memset(buf, 0, 512); + md5ctx = PK11_CreateDigestContext(SEC_OID_MD5); + + for(ssize_t total = 0; total < size; total += bytes){ + bytes = 512 < (size - total) ? 512 : (size - total); + bytes = read(fd, buf, bytes); + if(0 == bytes){ + // end of file + break; + }else if(-1 == bytes){ + // error + DPRNNN("file read error(%d)", errno); + return NULL; + } + PK11_DigestOp(md5ctx, buf, bytes); + memset(buf, 0, 512); + } + if(NULL == (result = (unsigned char*)malloc(get_md5_digest_length()))){ + PK11_DestroyContext(md5ctx, PR_TRUE); + return NULL; + } + PK11_DigestFinal(md5ctx, result, &md5outlen, get_md5_digest_length()); + PK11_DestroyContext(md5ctx, PR_TRUE); + + if(-1 == lseek(fd, start, SEEK_SET)){ + free(result); + return NULL; + } + + return result; +} + +/// END diff --git a/src/openssl_auth.cpp b/src/openssl_auth.cpp new file mode 100644 index 0000000..eea79d6 --- /dev/null +++ b/src/openssl_auth.cpp @@ -0,0 +1,250 @@ +/* + * s3fs - FUSE-based file system backed by Amazon S3 + * + * Copyright 2007-2008 Randy Rizun + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "common.h" +#include "s3fs_auth.h" + +using namespace std; + +//------------------------------------------------------------------- +// Utility Function for version +//------------------------------------------------------------------- +const char* s3fs_crypt_lib_name(void) +{ + static const char version[] = "OpenSSL"; + + return version; +} + +//------------------------------------------------------------------- +// Utility Function for global init +//------------------------------------------------------------------- +bool s3fs_init_global_ssl(void) +{ + return true; +} + +bool s3fs_destroy_global_ssl(void) +{ + return true; +} + +//------------------------------------------------------------------- +// Utility Function for crypt lock +//------------------------------------------------------------------- +// internal use struct for openssl +struct CRYPTO_dynlock_value +{ + pthread_mutex_t dyn_mutex; +}; + +static pthread_mutex_t* s3fs_crypt_mutex = NULL; + +static void s3fs_crypt_mutex_lock(int mode, int pos, const char* file, int line) +{ + if(s3fs_crypt_mutex){ + if(mode & CRYPTO_LOCK){ + pthread_mutex_lock(&s3fs_crypt_mutex[pos]); + }else{ + pthread_mutex_unlock(&s3fs_crypt_mutex[pos]); + } + } +} + +static unsigned long s3fs_crypt_get_threadid(void) +{ + return static_cast(pthread_self()); +} + +static struct CRYPTO_dynlock_value* s3fs_dyn_crypt_mutex(const char* file, int line) +{ + struct CRYPTO_dynlock_value* dyndata; + + if(NULL == (dyndata = static_cast(malloc(sizeof(struct CRYPTO_dynlock_value))))){ + DPRNCRIT("Could not allocate memory for CRYPTO_dynlock_value"); + return NULL; + } + pthread_mutex_init(&(dyndata->dyn_mutex), NULL); + return dyndata; +} + +static void s3fs_dyn_crypt_mutex_lock(int mode, struct CRYPTO_dynlock_value* dyndata, const char* file, int line) +{ + if(dyndata){ + if(mode & CRYPTO_LOCK){ + pthread_mutex_lock(&(dyndata->dyn_mutex)); + }else{ + pthread_mutex_unlock(&(dyndata->dyn_mutex)); + } + } +} + +static void s3fs_destroy_dyn_crypt_mutex(struct CRYPTO_dynlock_value* dyndata, const char* file, int line) +{ + if(dyndata){ + pthread_mutex_destroy(&(dyndata->dyn_mutex)); + free(dyndata); + } +} + +bool s3fs_init_crypt_mutex(void) +{ + if(s3fs_crypt_mutex){ + FPRNNN("s3fs_crypt_mutex is not NULL, destory it."); + if(!s3fs_destroy_crypt_mutex()){ + DPRN("Failed to s3fs_crypt_mutex"); + return false; + } + } + if(NULL == (s3fs_crypt_mutex = static_cast(malloc(CRYPTO_num_locks() * sizeof(pthread_mutex_t))))){ + DPRNCRIT("Could not allocate memory for s3fs_crypt_mutex"); + return false; + } + for(int cnt = 0; cnt < CRYPTO_num_locks(); cnt++){ + pthread_mutex_init(&s3fs_crypt_mutex[cnt], NULL); + } + // static lock + CRYPTO_set_locking_callback(s3fs_crypt_mutex_lock); + CRYPTO_set_id_callback(s3fs_crypt_get_threadid); + // dynamic lock + CRYPTO_set_dynlock_create_callback(s3fs_dyn_crypt_mutex); + CRYPTO_set_dynlock_lock_callback(s3fs_dyn_crypt_mutex_lock); + CRYPTO_set_dynlock_destroy_callback(s3fs_destroy_dyn_crypt_mutex); + + return true; +} + +bool s3fs_destroy_crypt_mutex(void) +{ + if(!s3fs_crypt_mutex){ + return true; + } + + CRYPTO_set_dynlock_destroy_callback(NULL); + CRYPTO_set_dynlock_lock_callback(NULL); + CRYPTO_set_dynlock_create_callback(NULL); + CRYPTO_set_id_callback(NULL); + CRYPTO_set_locking_callback(NULL); + + for(int cnt = 0; cnt < CRYPTO_num_locks(); cnt++){ + pthread_mutex_destroy(&s3fs_crypt_mutex[cnt]); + } + CRYPTO_cleanup_all_ex_data(); + free(s3fs_crypt_mutex); + s3fs_crypt_mutex = NULL; + + return true; +} + +//------------------------------------------------------------------- +// Utility Function for HMAC +//------------------------------------------------------------------- +bool s3fs_HMAC(const void* key, size_t keylen, const unsigned char* data, size_t datalen, unsigned char** digest, unsigned int* digestlen) +{ + if(!key || 0 >= keylen || !data || 0 >= datalen || !digest || !digestlen){ + return false; + } + (*digestlen) = EVP_MAX_MD_SIZE * sizeof(unsigned char); + if(NULL == ((*digest) = (unsigned char*)malloc(*digestlen))){ + return false; + } + HMAC(EVP_sha1(), key, keylen, data, datalen, *digest, digestlen); + + return true; +} + +//------------------------------------------------------------------- +// Utility Function for MD5 +//------------------------------------------------------------------- +size_t get_md5_digest_length(void) +{ + return MD5_DIGEST_LENGTH; +} + +unsigned char* s3fs_md5hexsum(int fd, off_t start, ssize_t size) +{ + MD5_CTX md5ctx; + char buf[512]; + ssize_t bytes; + unsigned char* result; + + if(-1 == size){ + struct stat st; + if(-1 == fstat(fd, &st)){ + return NULL; + } + size = static_cast(st.st_size); + } + + // seek to top of file. + if(-1 == lseek(fd, start, SEEK_SET)){ + return NULL; + } + + memset(buf, 0, 512); + MD5_Init(&md5ctx); + + for(ssize_t total = 0; total < size; total += bytes){ + bytes = 512 < (size - total) ? 512 : (size - total); + bytes = read(fd, buf, bytes); + if(0 == bytes){ + // end of file + break; + }else if(-1 == bytes){ + // error + DPRNNN("file read error(%d)", errno); + return NULL; + } + MD5_Update(&md5ctx, buf, bytes); + memset(buf, 0, 512); + } + + if(NULL == (result = (unsigned char*)malloc(get_md5_digest_length()))){ + return NULL; + } + MD5_Final(result, &md5ctx); + + if(-1 == lseek(fd, start, SEEK_SET)){ + free(result); + return NULL; + } + + return result; +} + +/// END diff --git a/src/s3fs.cpp b/src/s3fs.cpp index 52be4f9..2b9d16f 100644 --- a/src/s3fs.cpp +++ b/src/s3fs.cpp @@ -31,7 +31,6 @@ #include #include #include -#include #include #include #include @@ -50,6 +49,7 @@ #include "string_util.h" #include "s3fs_util.h" #include "fdcache.h" +#include "s3fs_auth.h" using namespace std; @@ -2595,7 +2595,7 @@ static int remote_mountpath_exists(const char* path) static void* s3fs_init(struct fuse_conn_info* conn) { FPRN("init"); - LOWSYSLOGPRINT(LOG_ERR, "init $Rev$"); + LOWSYSLOGPRINT(LOG_ERR, "init v%s (%s)", VERSION, s3fs_crypt_lib_name()); // init curl if(!S3fsCurl::InitS3fsCurl("/etc/mime.types")){ @@ -3872,15 +3872,17 @@ int main(int argc, char* argv[]) s3fs_oper.access = s3fs_access; s3fs_oper.create = s3fs_create; - // init NSS - S3FS_INIT_NSS(); + if(!s3fs_init_global_ssl()){ + fprintf(stderr, "%s: could not initialize for ssl libraries.\n", program_name.c_str()); + exit(EXIT_FAILURE); + } // now passing things off to fuse, fuse will finish evaluating the command line args fuse_res = fuse_main(custom_args.argc, custom_args.argv, &s3fs_oper, NULL); fuse_opt_free_args(&custom_args); - // cleanup NSS - S3FS_CLEANUP_NSS(); + s3fs_destroy_global_ssl(); + // cleanup xml2 xmlCleanupParser(); S3FS_MALLOCTRIM(0); @@ -3888,3 +3890,4 @@ int main(int argc, char* argv[]) exit(fuse_res); } +/// END diff --git a/src/s3fs.h b/src/s3fs.h index 0bf9256..b292b0a 100644 --- a/src/s3fs.h +++ b/src/s3fs.h @@ -65,36 +65,4 @@ #endif // HAVE_MALLOC_TRIM -// -// For initializing libcurl with NSS -// Normally libcurl initializes the NSS library, but usually allows -// you to initialize s3fs forcibly. Because Memory leak is reported -// in valgrind(about curl_global_init() function), and this is for -// the cancellation. When "--enable-nss-init" option is specified -// at configurarion, it makes NSS_INIT_ENABLED flag into Makefile. -// NOTICE -// This defines and macros is temporary, and this should be deleted. -// -#ifdef NSS_INIT_ENABLED -#include -#include - -#define S3FS_INIT_NSS() \ - { \ - NSS_NoDB_Init(NULL); \ - } -#define S3FS_CLEANUP_NSS() \ - { \ - NSS_Shutdown(); \ - PL_ArenaFinish(); \ - PR_Cleanup(); \ - } - -#else // NSS_INIT_ENABLED - -#define S3FS_INIT_NSS() -#define S3FS_CLEANUP_NSS() - -#endif // NSS_INIT_ENABLED - #endif // S3FS_S3_H_ diff --git a/src/s3fs_auth.h b/src/s3fs_auth.h new file mode 100644 index 0000000..4a45aa6 --- /dev/null +++ b/src/s3fs_auth.h @@ -0,0 +1,26 @@ +#ifndef S3FS_AUTH_H_ +#define S3FS_AUTH_H_ + +//------------------------------------------------------------------- +// Utility functions for Authentication +//------------------------------------------------------------------- +// +// in common_auth.cpp +// +char* s3fs_base64(unsigned char* input, size_t length); +std::string s3fs_get_content_md5(int fd); +std::string s3fs_md5sum(int fd, off_t start, ssize_t size); + +// +// in xxxxxx_auth.cpp +// +const char* s3fs_crypt_lib_name(void); +bool s3fs_init_global_ssl(void); +bool s3fs_destroy_global_ssl(void); +bool s3fs_init_crypt_mutex(void); +bool s3fs_destroy_crypt_mutex(void); +bool s3fs_HMAC(const void* key, size_t keylen, const unsigned char* data, size_t datalen, unsigned char** digest, unsigned int* digestlen); +size_t get_md5_digest_length(void); +unsigned char* s3fs_md5hexsum(int fd, off_t start, ssize_t size); + +#endif // S3FS_AUTH_H_ diff --git a/src/s3fs_util.cpp b/src/s3fs_util.cpp index e279e88..85687ae 100644 --- a/src/s3fs_util.cpp +++ b/src/s3fs_util.cpp @@ -41,6 +41,7 @@ #include "s3fs_util.h" #include "string_util.h" #include "s3fs.h" +#include "s3fs_auth.h" using namespace std; @@ -997,11 +998,13 @@ void show_help (void) void show_version(void) { printf( - "Amazon Simple Storage Service File System %s\n" + "Amazon Simple Storage Service File System V%s with %s\n" "Copyright (C) 2010 Randy Rizun \n" "License GPL2: GNU GPL version 2 \n" "This is free software: you are free to change and redistribute it.\n" - "There is NO WARRANTY, to the extent permitted by law.\n", VERSION ); + "There is NO WARRANTY, to the extent permitted by law.\n", + VERSION, s3fs_crypt_lib_name()); return; } +/// END