Merge pull request #35 from s3fs-fuse/cryptlibs

Supports more two SSL libraries for NSS and GnuTLS.
This commit is contained in:
Takeshi Nakatani 2014-06-01 23:15:59 +09:00
commit f1f7e76be5
13 changed files with 1067 additions and 377 deletions

View File

@ -26,81 +26,186 @@ AC_CANONICAL_SYSTEM
AM_INIT_AUTOMAKE() AM_INIT_AUTOMAKE()
AC_PROG_CXX AC_PROG_CXX
AC_PROG_CC
CXXFLAGS="$CXXFLAGS -Wall -D_FILE_OFFSET_BITS=64" 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 dnl
AC_CHECK_FUNCS(malloc_trim, , ) dnl nettle library
dnl
dnl Initializing NSS(temporally) AC_MSG_CHECKING([s3fs build with nettle(GnuTLS)])
AC_MSG_CHECKING([Initializing libcurl build with NSS]) AC_ARG_WITH(
AC_ARG_ENABLE( nettle,
nss-init, [AS_HELP_STRING([--with-nettle], [s3fs build with nettle in GnuTLS(default no)])],
[ [
AS_HELP_STRING( case "${withval}" in
[--enable-nss-init],
[Inilializing libcurl with NSS (default is no)]
)
],
[
case "${enableval}" in
yes) yes)
AC_MSG_RESULT(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_WITH(
openssl,
[AS_HELP_STRING([--with-openssl], [s3fs build with OpenSSL(default is no)])],
[
case "${withval}" 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_WITH(
gnutls,
[AS_HELP_STRING([--with-gnutls], [s3fs build with GnuTLS(default is no)])],
[
case "${withval}" 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_WITH(
nss,
[AS_HELP_STRING([--with-nss], [s3fs build with NSS(default is no)])],
[
case "${withval}" 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) AC_MSG_RESULT(no)
nss_init_enabled=no
;; ;;
esac esac
], ],
[ [
AC_MSG_RESULT(no) AC_MSG_RESULT(no)
nss_init_enabled=no
]) ])
AS_IF( AS_IF(
[test $nss_init_enabled = yes], [test $auth_lib = na],
[ AS_IF(
AC_DEFINE(NSS_INIT_ENABLED, 1) [test $nettle_lib = no],
AC_CHECK_LIB(nss3, NSS_NoDB_Init, , [AC_MSG_ERROR(not found NSS libraries)]) [auth_lib=openssl],
AC_CHECK_LIB(plds4, PL_ArenaFinish, , [AC_MSG_ERROR(not found PL_ArenaFinish)]) [AC_MSG_ERROR([could not set nettle without GnuTLS library])]
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"
])
])
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_CONFIG_FILES(Makefile src/Makefile test/Makefile doc/Makefile)
AC_OUTPUT AC_OUTPUT

View File

@ -1,7 +1,20 @@
bin_PROGRAMS=s3fs bin_PROGRAMS=s3fs
AM_CPPFLAGS = $(DEPS_CFLAGS) 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) s3fs_LDADD = $(DEPS_LIBS)

105
src/common_auth.cpp Normal file
View File

@ -0,0 +1,105 @@
/*
* s3fs - FUSE-based file system backed by Amazon S3
*
* Copyright 2007-2008 Randy Rizun <rrizun@gmail.com>
*
* 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string>
#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

View File

@ -31,11 +31,6 @@
#include <pthread.h> #include <pthread.h>
#include <assert.h> #include <assert.h>
#include <curl/curl.h> #include <curl/curl.h>
#include <openssl/bio.h>
#include <openssl/buffer.h>
#include <openssl/evp.h>
#include <openssl/hmac.h>
#include <openssl/md5.h>
#include <libxml/xpath.h> #include <libxml/xpath.h>
#include <libxml/xpathInternals.h> #include <libxml/xpathInternals.h>
#include <libxml/tree.h> #include <libxml/tree.h>
@ -52,6 +47,7 @@
#include "string_util.h" #include "string_util.h"
#include "s3fs.h" #include "s3fs.h"
#include "s3fs_util.h" #include "s3fs_util.h"
#include "s3fs_auth.h"
using namespace std; 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_handles_lock;
pthread_mutex_t S3fsCurl::curl_share_lock[SHARE_MUTEX_MAX]; pthread_mutex_t S3fsCurl::curl_share_lock[SHARE_MUTEX_MAX];
pthread_mutex_t* S3fsCurl::crypt_mutex = NULL;
bool S3fsCurl::is_initglobal_done = false; bool S3fsCurl::is_initglobal_done = false;
CURLSH* S3fsCurl::hCurlShare = NULL; CURLSH* S3fsCurl::hCurlShare = NULL;
bool S3fsCurl::is_dns_cache = true; // default bool S3fsCurl::is_dns_cache = true; // default
@ -168,7 +163,6 @@ string S3fsCurl::AWSAccessToken;
time_t S3fsCurl::AWSAccessTokenExpire= 0; time_t S3fsCurl::AWSAccessTokenExpire= 0;
string S3fsCurl::IAM_role; string S3fsCurl::IAM_role;
long S3fsCurl::ssl_verify_hostname = 1; // default(original code...) long S3fsCurl::ssl_verify_hostname = 1; // default(original code...)
const EVP_MD* S3fsCurl::evp_md = EVP_sha1();
curltime_t S3fsCurl::curl_times; curltime_t S3fsCurl::curl_times;
curlprogress_t S3fsCurl::curl_progress; curlprogress_t S3fsCurl::curl_progress;
string S3fsCurl::curl_ca_bundle; string S3fsCurl::curl_ca_bundle;
@ -340,97 +334,12 @@ void S3fsCurl::UnlockCurlShare(CURL* handle, curl_lock_data nLockData, void* use
bool S3fsCurl::InitCryptMutex(void) bool S3fsCurl::InitCryptMutex(void)
{ {
if(S3fsCurl::crypt_mutex){ return s3fs_init_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<pthread_mutex_t*>(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;
} }
bool S3fsCurl::DestroyCryptMutex(void) bool S3fsCurl::DestroyCryptMutex(void)
{ {
if(!S3fsCurl::crypt_mutex){ return s3fs_destroy_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);
}
} }
// homegrown timeout mechanism // 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) 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 Signature;
string StringToSign; string StringToSign;
@ -1682,74 +1587,20 @@ string S3fsCurl::CalcSignature(string method, string strMD5, string content_type
int key_len = S3fsCurl::AWSSecretAccessKey.size(); int key_len = S3fsCurl::AWSSecretAccessKey.size();
const unsigned char* sdata = reinterpret_cast<const unsigned char*>(StringToSign.data()); const unsigned char* sdata = reinterpret_cast<const unsigned char*>(StringToSign.data());
int sdata_len = StringToSign.size(); int sdata_len = StringToSign.size();
unsigned char md[EVP_MAX_MD_SIZE]; unsigned char* md = NULL;
unsigned int md_len; 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()); char* base64;
BIO* bmem = BIO_new(BIO_s_mem()); if(NULL == (base64 = s3fs_base64(md, md_len))){
b64 = BIO_push(b64, bmem); free(md);
return string(""); // ENOMEM
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;
}
} }
free(md);
// Flush the data Signature = base64;
ret = BIO_flush(b64); free(base64);
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);
return Signature; return Signature;
} }
@ -2094,7 +1945,7 @@ int S3fsCurl::PutRequest(const char* tpath, headers_t& meta, int fd, bool ow_sse
string strMD5; string strMD5;
if(-1 != fd && S3fsCurl::is_content_md5){ 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()); 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 // 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()){ if(partdata.etag.empty()){
DPRN("Could not make md5 for file(part %d)", part_num); DPRN("Could not make md5 for file(part %d)", part_num);
return -1; return -1;
@ -3407,107 +3258,6 @@ bool AdditionalHeader::Dump(void) const
//------------------------------------------------------------------- //-------------------------------------------------------------------
// Utility functions // 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<ssize_t>(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 // curl_slist_sort_insert
// This function is like curl_slist_append function, but this adds data by a-sorting. // This function is like curl_slist_append function, but this adds data by a-sorting.

View File

@ -106,12 +106,6 @@ typedef std::map<std::string, std::string> iamcredmap_t;
#define SHARE_MUTEX_SSL_SESSION 1 #define SHARE_MUTEX_SSL_SESSION 1
#define SHARE_MUTEX_MAX 2 #define SHARE_MUTEX_MAX 2
// internal use struct for openssl
struct CRYPTO_dynlock_value
{
pthread_mutex_t dyn_mutex;
};
// Class for lapping curl // Class for lapping curl
// //
class S3fsCurl class S3fsCurl
@ -140,7 +134,6 @@ class S3fsCurl
// class variables // class variables
static pthread_mutex_t curl_handles_lock; static pthread_mutex_t curl_handles_lock;
static pthread_mutex_t curl_share_lock[SHARE_MUTEX_MAX]; static pthread_mutex_t curl_share_lock[SHARE_MUTEX_MAX];
static pthread_mutex_t* crypt_mutex;
static bool is_initglobal_done; static bool is_initglobal_done;
static CURLSH* hCurlShare; static CURLSH* hCurlShare;
static bool is_dns_cache; static bool is_dns_cache;
@ -160,7 +153,6 @@ class S3fsCurl
static time_t AWSAccessTokenExpire; static time_t AWSAccessTokenExpire;
static std::string IAM_role; static std::string IAM_role;
static long ssl_verify_hostname; static long ssl_verify_hostname;
static const EVP_MD* evp_md;
static curltime_t curl_times; static curltime_t curl_times;
static curlprogress_t curl_progress; static curlprogress_t curl_progress;
static std::string curl_ca_bundle; static std::string curl_ca_bundle;
@ -206,11 +198,6 @@ class S3fsCurl
static void UnlockCurlShare(CURL* handle, curl_lock_data nLockData, void* useptr); static void UnlockCurlShare(CURL* handle, curl_lock_data nLockData, void* useptr);
static bool InitCryptMutex(void); static bool InitCryptMutex(void);
static bool DestroyCryptMutex(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 int CurlProgress(void *clientp, double dltotal, double dlnow, double ultotal, double ulnow);
static bool InitMimeType(const char* MimeFile = NULL); static bool InitMimeType(const char* MimeFile = NULL);

View File

@ -31,7 +31,6 @@
#include <string.h> #include <string.h>
#include <assert.h> #include <assert.h>
#include <curl/curl.h> #include <curl/curl.h>
#include <openssl/crypto.h>
#include <string> #include <string>
#include <iostream> #include <iostream>
#include <sstream> #include <sstream>
@ -797,7 +796,7 @@ int FdEntity::Load(off_t start, off_t size)
break; break;
} }
// download // download
if((*iter)->bytes >= (2 * S3fsCurl::GetMultipartSize()) && !nomultipart){ // default 20MB if((*iter)->bytes >= static_cast<size_t>(2 * S3fsCurl::GetMultipartSize()) && !nomultipart){ // default 20MB
// parallel request // parallel request
// Additional time is needed for large files // Additional time is needed for large files
time_t backup = 0; time_t backup = 0;
@ -1197,3 +1196,4 @@ bool FdManager::Close(FdEntity* ent)
return false; return false;
} }
/// END

259
src/gnutls_auth.cpp Normal file
View File

@ -0,0 +1,259 @@
/*
* s3fs - FUSE-based file system backed by Amazon S3
*
* Copyright 2007-2008 Randy Rizun <rrizun@gmail.com>
*
* 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 <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <pthread.h>
#include <unistd.h>
#include <syslog.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <gcrypt.h>
#include <gnutls/gnutls.h>
#include <gnutls/crypto.h>
#ifdef USE_GNUTLS_NETTLE
#include <nettle/md5.h>
#include <nettle/sha1.h>
#include <nettle/hmac.h>
#endif
#include <string>
#include <map>
#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<const uint8_t*>(key));
hmac_sha1_update(&ctx_hmac, datalen, reinterpret_cast<const uint8_t*>(data));
hmac_sha1_digest(&ctx_hmac, SHA1_DIGEST_SIZE, reinterpret_cast<uint8_t*>(*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<ssize_t>(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

196
src/nss_auth.cpp Normal file
View File

@ -0,0 +1,196 @@
/*
* s3fs - FUSE-based file system backed by Amazon S3
*
* Copyright 2007-2008 Randy Rizun <rrizun@gmail.com>
*
* 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 <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <pthread.h>
#include <unistd.h>
#include <syslog.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <nss.h>
#include <pk11pub.h>
#include <hasht.h>
#include <prinit.h>
#include <string>
#include <map>
#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_Init(NULL);
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<unsigned char*>(const_cast<void*>(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<ssize_t>(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

256
src/openssl_auth.cpp Normal file
View File

@ -0,0 +1,256 @@
/*
* s3fs - FUSE-based file system backed by Amazon S3
*
* Copyright 2007-2008 Randy Rizun <rrizun@gmail.com>
*
* 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 <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <pthread.h>
#include <unistd.h>
#include <syslog.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <openssl/bio.h>
#include <openssl/buffer.h>
#include <openssl/evp.h>
#include <openssl/hmac.h>
#include <openssl/md5.h>
#include <openssl/crypto.h>
#include <openssl/err.h>
#include <string>
#include <map>
#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)
{
ERR_load_crypto_strings();
ERR_load_BIO_strings();
OpenSSL_add_all_algorithms();
return true;
}
bool s3fs_destroy_global_ssl(void)
{
EVP_cleanup();
ERR_free_strings();
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<unsigned long>(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<struct CRYPTO_dynlock_value*>(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<pthread_mutex_t*>(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<ssize_t>(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

View File

@ -31,7 +31,6 @@
#include <libxml/xpathInternals.h> #include <libxml/xpathInternals.h>
#include <libxml/tree.h> #include <libxml/tree.h>
#include <curl/curl.h> #include <curl/curl.h>
#include <openssl/crypto.h>
#include <pwd.h> #include <pwd.h>
#include <grp.h> #include <grp.h>
#include <getopt.h> #include <getopt.h>
@ -50,6 +49,7 @@
#include "string_util.h" #include "string_util.h"
#include "s3fs_util.h" #include "s3fs_util.h"
#include "fdcache.h" #include "fdcache.h"
#include "s3fs_auth.h"
using namespace std; using namespace std;
@ -2595,7 +2595,13 @@ static int remote_mountpath_exists(const char* path)
static void* s3fs_init(struct fuse_conn_info* conn) static void* s3fs_init(struct fuse_conn_info* conn)
{ {
FPRN("init"); FPRN("init");
LOWSYSLOGPRINT(LOG_ERR, "init $Rev$"); LOWSYSLOGPRINT(LOG_ERR, "init v%s (%s)", VERSION, s3fs_crypt_lib_name());
// ssl init
if(!s3fs_init_global_ssl()){
fprintf(stderr, "%s: could not initialize for ssl libraries.\n", program_name.c_str());
exit(EXIT_FAILURE);
}
// init curl // init curl
if(!S3fsCurl::InitS3fsCurl("/etc/mime.types")){ if(!S3fsCurl::InitS3fsCurl("/etc/mime.types")){
@ -2637,6 +2643,8 @@ static void s3fs_destroy(void*)
if(is_remove_cache && !FdManager::DeleteCacheDirectory()){ if(is_remove_cache && !FdManager::DeleteCacheDirectory()){
DPRN("Could not remove cache directory."); DPRN("Could not remove cache directory.");
} }
// ssl
s3fs_destroy_global_ssl();
} }
static int s3fs_access(const char* path, int mask) static int s3fs_access(const char* path, int mask)
@ -2840,10 +2848,17 @@ static int s3fs_utility_mode(void)
return EXIT_FAILURE; return EXIT_FAILURE;
} }
// ssl init
if(!s3fs_init_global_ssl()){
fprintf(stderr, "%s: could not initialize for ssl libraries.\n", program_name.c_str());
return EXIT_FAILURE;
}
// init curl // init curl
if(!S3fsCurl::InitS3fsCurl("/etc/mime.types")){ if(!S3fsCurl::InitS3fsCurl("/etc/mime.types")){
fprintf(stderr, "%s: Could not initiate curl library.\n", program_name.c_str()); fprintf(stderr, "%s: Could not initiate curl library.\n", program_name.c_str());
LOWSYSLOGPRINT(LOG_ERR, "Could not initiate curl library."); LOWSYSLOGPRINT(LOG_ERR, "Could not initiate curl library.");
s3fs_destroy_global_ssl();
return EXIT_FAILURE; return EXIT_FAILURE;
} }
@ -2888,6 +2903,10 @@ static int s3fs_utility_mode(void)
if(!S3fsCurl::DestroyS3fsCurl()){ if(!S3fsCurl::DestroyS3fsCurl()){
DPRN("Could not release curl library."); DPRN("Could not release curl library.");
} }
// ssl
s3fs_destroy_global_ssl();
return result; return result;
} }
@ -3872,15 +3891,17 @@ int main(int argc, char* argv[])
s3fs_oper.access = s3fs_access; s3fs_oper.access = s3fs_access;
s3fs_oper.create = s3fs_create; s3fs_oper.create = s3fs_create;
// init NSS if(!s3fs_init_global_ssl()){
S3FS_INIT_NSS(); 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 // 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_res = fuse_main(custom_args.argc, custom_args.argv, &s3fs_oper, NULL);
fuse_opt_free_args(&custom_args); fuse_opt_free_args(&custom_args);
// cleanup NSS s3fs_destroy_global_ssl();
S3FS_CLEANUP_NSS();
// cleanup xml2 // cleanup xml2
xmlCleanupParser(); xmlCleanupParser();
S3FS_MALLOCTRIM(0); S3FS_MALLOCTRIM(0);
@ -3888,3 +3909,4 @@ int main(int argc, char* argv[])
exit(fuse_res); exit(fuse_res);
} }
/// END

View File

@ -65,36 +65,4 @@
#endif // HAVE_MALLOC_TRIM #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 <nss.h>
#include <prinit.h>
#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_ #endif // S3FS_S3_H_

26
src/s3fs_auth.h Normal file
View File

@ -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_

View File

@ -41,6 +41,7 @@
#include "s3fs_util.h" #include "s3fs_util.h"
#include "string_util.h" #include "string_util.h"
#include "s3fs.h" #include "s3fs.h"
#include "s3fs_auth.h"
using namespace std; using namespace std;
@ -997,11 +998,13 @@ void show_help (void)
void show_version(void) void show_version(void)
{ {
printf( 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 <rrizun@gmail.com>\n" "Copyright (C) 2010 Randy Rizun <rrizun@gmail.com>\n"
"License GPL2: GNU GPL version 2 <http://gnu.org/licenses/gpl.html>\n" "License GPL2: GNU GPL version 2 <http://gnu.org/licenses/gpl.html>\n"
"This is free software: you are free to change and redistribute it.\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; return;
} }
/// END