Support SSL client cert and added ssl_client_cert option
This commit is contained in:
parent
9ab5a2ea73
commit
95026804e9
|
@ -179,6 +179,18 @@ server certificate won't be checked against the available certificate authoritie
|
||||||
\fB\-o\fR ssl_verify_hostname (default="2")
|
\fB\-o\fR ssl_verify_hostname (default="2")
|
||||||
When 0, do not verify the SSL certificate against the hostname.
|
When 0, do not verify the SSL certificate against the hostname.
|
||||||
.TP
|
.TP
|
||||||
|
\fB\-o\fR ssl_client_cert (default="")
|
||||||
|
Specify an SSL client certificate.
|
||||||
|
Specify this optional parameter in the following format:
|
||||||
|
"<SSL Cert>[:<Cert Type>[:<Private Key>[:<Key Type>
|
||||||
|
[:<Password>]]]]"
|
||||||
|
<SSL Cert>: Client certificate.
|
||||||
|
Specify the file path or NickName(for NSS, etc.).
|
||||||
|
<Cert Type>: Type of certificate, default is "PEM"(optional).
|
||||||
|
<Private Key>: Certificate's private key file(optional).
|
||||||
|
<Key Type>: Type of private key, default is "PEM"(optional).
|
||||||
|
<Password>: Passphrase of the private key(optional). It is also possible to omit this value and specify it using the environment variable "S3FS_SSL_PRIVKEY_PASSWORD".
|
||||||
|
.TP
|
||||||
\fB\-o\fR nodnscache - disable DNS cache.
|
\fB\-o\fR nodnscache - disable DNS cache.
|
||||||
s3fs is always using DNS cache, this option make DNS cache disable.
|
s3fs is always using DNS cache, this option make DNS cache disable.
|
||||||
.TP
|
.TP
|
||||||
|
|
106
src/curl.cpp
106
src/curl.cpp
|
@ -83,6 +83,7 @@ static constexpr char SPECIAL_DARWIN_MIME_FILE[] = "/etc/apache2/mime.typ
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
// Class S3fsCurl
|
// Class S3fsCurl
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
|
constexpr char S3fsCurl::S3FS_SSL_PRIVKEY_PASSWORD[];
|
||||||
pthread_mutex_t S3fsCurl::curl_warnings_lock;
|
pthread_mutex_t S3fsCurl::curl_warnings_lock;
|
||||||
pthread_mutex_t S3fsCurl::curl_handles_lock;
|
pthread_mutex_t S3fsCurl::curl_handles_lock;
|
||||||
S3fsCurl::callback_locks_t S3fsCurl::callback_locks;
|
S3fsCurl::callback_locks_t S3fsCurl::callback_locks;
|
||||||
|
@ -107,6 +108,12 @@ bool S3fsCurl::is_verbose = false;
|
||||||
bool S3fsCurl::is_dump_body = false;
|
bool S3fsCurl::is_dump_body = false;
|
||||||
S3fsCred* S3fsCurl::ps3fscred = nullptr;
|
S3fsCred* S3fsCurl::ps3fscred = nullptr;
|
||||||
long S3fsCurl::ssl_verify_hostname = 1; // default(original code...)
|
long S3fsCurl::ssl_verify_hostname = 1; // default(original code...)
|
||||||
|
// SSL client cert options
|
||||||
|
std::string S3fsCurl::client_cert;
|
||||||
|
std::string S3fsCurl::client_cert_type;
|
||||||
|
std::string S3fsCurl::client_priv_key;
|
||||||
|
std::string S3fsCurl::client_priv_key_type;
|
||||||
|
std::string S3fsCurl::client_key_password;
|
||||||
|
|
||||||
// protected by curl_warnings_lock
|
// protected by curl_warnings_lock
|
||||||
bool S3fsCurl::curl_warnings_once = false;
|
bool S3fsCurl::curl_warnings_once = false;
|
||||||
|
@ -1013,6 +1020,75 @@ long S3fsCurl::SetSslVerifyHostname(long value)
|
||||||
return old;
|
return old;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool S3fsCurl::SetSSLClientCertOptions(const std::string& values)
|
||||||
|
{
|
||||||
|
// Parse values:
|
||||||
|
// <values> = "<SSL Client Cert>:<SSL Cert Type>:<SSL Cert Private Key>:<SSL Cert Private Type>:<Key Password>"
|
||||||
|
//
|
||||||
|
if(values.empty()){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::list<std::string> valarr;
|
||||||
|
std::string::size_type start_pos = 0;
|
||||||
|
std::string::size_type pos;
|
||||||
|
do{
|
||||||
|
if(std::string::npos == (pos = values.find(':', start_pos))){
|
||||||
|
valarr.push_back(values.substr(start_pos));
|
||||||
|
start_pos = pos;
|
||||||
|
}else{
|
||||||
|
if(0 < (pos - start_pos)){
|
||||||
|
valarr.push_back(values.substr(start_pos, (pos - start_pos)));
|
||||||
|
}else{
|
||||||
|
valarr.emplace_back("");
|
||||||
|
}
|
||||||
|
start_pos = ++pos;
|
||||||
|
}
|
||||||
|
}while(std::string::npos != start_pos);
|
||||||
|
|
||||||
|
// set client cert
|
||||||
|
if(!valarr.empty() && !valarr.front().empty()){
|
||||||
|
S3fsCurl::client_cert = valarr.front();
|
||||||
|
valarr.pop_front();
|
||||||
|
|
||||||
|
// set client cert type
|
||||||
|
if(!valarr.empty()){
|
||||||
|
S3fsCurl::client_cert_type = valarr.front(); // allow empty(default: PEM)
|
||||||
|
valarr.pop_front();
|
||||||
|
|
||||||
|
// set client private key
|
||||||
|
if(!valarr.empty()){
|
||||||
|
S3fsCurl::client_priv_key = valarr.front(); // allow empty
|
||||||
|
valarr.pop_front();
|
||||||
|
|
||||||
|
// set client private key type
|
||||||
|
if(!valarr.empty()){
|
||||||
|
S3fsCurl::client_priv_key_type = valarr.front(); // allow empty(default: PEM)
|
||||||
|
valarr.pop_front();
|
||||||
|
|
||||||
|
// set key password
|
||||||
|
if(!valarr.empty()){
|
||||||
|
S3fsCurl::client_key_password = valarr.front(); // allow empty
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// [NOTE]
|
||||||
|
// If the private key is set but the password is not set,
|
||||||
|
// check the environment variables.
|
||||||
|
//
|
||||||
|
if(!S3fsCurl::client_priv_key.empty() && S3fsCurl::client_key_password.empty()){
|
||||||
|
const char* pass = std::getenv(S3fsCurl::S3FS_SSL_PRIVKEY_PASSWORD);
|
||||||
|
if(pass != nullptr){
|
||||||
|
S3fsCurl::client_key_password = pass;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool S3fsCurl::SetMultipartSize(off_t size)
|
bool S3fsCurl::SetMultipartSize(off_t size)
|
||||||
{
|
{
|
||||||
size = size * 1024 * 1024;
|
size = size * 1024 * 1024;
|
||||||
|
@ -1985,6 +2061,36 @@ bool S3fsCurl::ResetHandle(AutoLock::Type locktype)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// SSL Client Cert
|
||||||
|
if(!S3fsCurl::client_cert.empty()){
|
||||||
|
if(CURLE_OK != curl_easy_setopt(hCurl, CURLOPT_SSLCERT, S3fsCurl::client_cert.c_str())){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if(!S3fsCurl::client_cert_type.empty() && 0 != strcasecmp(S3fsCurl::client_cert_type.c_str(), "PEM")){ // "PEM" is default
|
||||||
|
if(CURLE_OK != curl_easy_setopt(hCurl, CURLOPT_SSLCERTTYPE, S3fsCurl::client_cert_type.c_str())){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Private key
|
||||||
|
if(!S3fsCurl::client_priv_key.empty()){
|
||||||
|
if(CURLE_OK != curl_easy_setopt(hCurl, CURLOPT_SSLKEY, S3fsCurl::client_priv_key.c_str())){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if(!S3fsCurl::client_priv_key_type.empty() && 0 != strcasecmp(S3fsCurl::client_priv_key_type.c_str(), "PEM")){ // "PEM" is default
|
||||||
|
if(CURLE_OK != curl_easy_setopt(hCurl, CURLOPT_SSLKEYTYPE, S3fsCurl::client_priv_key_type.c_str())){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Password
|
||||||
|
if(!S3fsCurl::client_key_password.empty()){
|
||||||
|
if(CURLE_OK != curl_easy_setopt(hCurl, CURLOPT_KEYPASSWD, S3fsCurl::client_key_password.c_str())){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if((S3fsCurl::is_dns_cache || S3fsCurl::is_ssl_session_cache) && S3fsCurl::hCurlShare){
|
if((S3fsCurl::is_dns_cache || S3fsCurl::is_ssl_session_cache) && S3fsCurl::hCurlShare){
|
||||||
if(CURLE_OK != curl_easy_setopt(hCurl, CURLOPT_SHARE, S3fsCurl::hCurlShare)){
|
if(CURLE_OK != curl_easy_setopt(hCurl, CURLOPT_SHARE, S3fsCurl::hCurlShare)){
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -110,6 +110,9 @@ class S3fsCurl
|
||||||
IAMROLE
|
IAMROLE
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Environment name
|
||||||
|
static constexpr char S3FS_SSL_PRIVKEY_PASSWORD[] = "S3FS_SSL_PRIVKEY_PASSWORD";
|
||||||
|
|
||||||
// class variables
|
// class variables
|
||||||
static pthread_mutex_t curl_warnings_lock;
|
static pthread_mutex_t curl_warnings_lock;
|
||||||
static bool curl_warnings_once; // emit older curl warnings only once
|
static bool curl_warnings_once; // emit older curl warnings only once
|
||||||
|
@ -139,6 +142,11 @@ class S3fsCurl
|
||||||
static bool is_dump_body;
|
static bool is_dump_body;
|
||||||
static S3fsCred* ps3fscred;
|
static S3fsCred* ps3fscred;
|
||||||
static long ssl_verify_hostname;
|
static long ssl_verify_hostname;
|
||||||
|
static std::string client_cert;
|
||||||
|
static std::string client_cert_type;
|
||||||
|
static std::string client_priv_key;
|
||||||
|
static std::string client_priv_key_type;
|
||||||
|
static std::string client_key_password;
|
||||||
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;
|
||||||
|
@ -317,6 +325,7 @@ class S3fsCurl
|
||||||
static bool IsDumpBody() { return S3fsCurl::is_dump_body; }
|
static bool IsDumpBody() { return S3fsCurl::is_dump_body; }
|
||||||
static long SetSslVerifyHostname(long value);
|
static long SetSslVerifyHostname(long value);
|
||||||
static long GetSslVerifyHostname() { return S3fsCurl::ssl_verify_hostname; }
|
static long GetSslVerifyHostname() { return S3fsCurl::ssl_verify_hostname; }
|
||||||
|
static bool SetSSLClientCertOptions(const std::string& values);
|
||||||
static void ResetOffset(S3fsCurl* pCurl);
|
static void ResetOffset(S3fsCurl* pCurl);
|
||||||
// maximum parallel GET and PUT requests
|
// maximum parallel GET and PUT requests
|
||||||
static int SetMaxParallelCount(int value);
|
static int SetMaxParallelCount(int value);
|
||||||
|
|
|
@ -5085,6 +5085,14 @@ static int my_fuse_opt_proc(void* data, const char* arg, int key, struct fuse_ar
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
else if(is_prefix(arg, "ssl_client_cert=")){
|
||||||
|
std::string values = strchr(arg, '=') + sizeof(char);
|
||||||
|
if(!S3fsCurl::SetSSLClientCertOptions(values)){
|
||||||
|
S3FS_PRN_EXIT("failed to set SSL client certification options.");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
//
|
//
|
||||||
// Detect options for credential
|
// Detect options for credential
|
||||||
//
|
//
|
||||||
|
|
|
@ -217,6 +217,21 @@ static constexpr char help_string[] =
|
||||||
" ssl_verify_hostname (default=\"2\")\n"
|
" ssl_verify_hostname (default=\"2\")\n"
|
||||||
" - When 0, do not verify the SSL certificate against the hostname.\n"
|
" - When 0, do not verify the SSL certificate against the hostname.\n"
|
||||||
"\n"
|
"\n"
|
||||||
|
" ssl_client_cert (default=\"\")\n"
|
||||||
|
" - Specify an SSL client certificate.\n"
|
||||||
|
" Specify this optional parameter in the following format:\n"
|
||||||
|
" \"<SSL Cert>[:<Cert Type>[:<Private Key>[:<Key Type>\n"
|
||||||
|
" [:<Password>]]]]\"\n"
|
||||||
|
" <SSL Cert>: Client certificate.\n"
|
||||||
|
" Specify the file path or NickName(for NSS, etc.).\n"
|
||||||
|
" <Cert Type>: Type of certificate, default is \"PEM\"(optional).\n"
|
||||||
|
" <Private Key>: Certificate's private key file(optional).\n"
|
||||||
|
" <Key Type>: Type of private key, default is \"PEM\"(optional).\n"
|
||||||
|
" <Password>: Passphrase of the private key(optional).\n"
|
||||||
|
" It is also possible to omit this value and specify\n"
|
||||||
|
" it using the environment variable\n"
|
||||||
|
" \"S3FS_SSL_PRIVKEY_PASSWORD\".\n"
|
||||||
|
"\n"
|
||||||
" nodnscache (disable DNS cache)\n"
|
" nodnscache (disable DNS cache)\n"
|
||||||
" - s3fs is always using DNS cache, this option make DNS cache disable.\n"
|
" - s3fs is always using DNS cache, this option make DNS cache disable.\n"
|
||||||
"\n"
|
"\n"
|
||||||
|
|
Loading…
Reference in New Issue