Skip to content

Commit

Permalink
README edits and site update
Browse files Browse the repository at this point in the history
  • Loading branch information
attipaci committed Jan 14, 2025
1 parent 67d5a2c commit ca41c37
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 15 deletions.
54 changes: 54 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,60 @@ network errors (and keep track of changes locally until then):
smaxSetResilient(TRUE);
```
### TLS configuration
You can also use SMA-X with a TLS encrypted connection. (We don't recommend using TLS with SMA-X in general though,
since it may adversely affect the performance / throughput of the database.) When enabled, Redis normally uses mutual
TLS (mTLS), but it may be configured otherwise also. Depending on the server configuration, and the level of security
required, you may configure some or all of the following options:
```c
int status;
// Use TLS with the specified CA certificate file and path
status = smaxSetTLS("path/to/certificates", "ca.crt");
if(status) {
// Oops, the CA certificate is not accessible...
...
}
// (optional) If servers requires mutual TLS, you will need to provide
// a certificate and private key also
status = smaxSetMutualTLS("path/to/redis.crt", "path/to/redis.key");
if(status) {
// Oops, the certificate or key file is not accessible...
...
}
// (optional) Skip verification of the certificate (insecure!)
smaxSetTLSVerify(FALSE);
// (optional) Set server name for SNI
smaxSetTLSServerName("my.smax-server.com");
// (optional) Set ciphers to use (TLSv1.2 and earlier)
smaxSetTLSCiphers("HIGH:!aNULL:!kRSA:!PSK:!SRP:!MD5:!RC4");
// (optional) Set cipher suites to use (TLSv1.3 and later)
smaxSetTLSCipherSuites("ECDHE-RSA-AES256-GCM-SHA384:TLS_AES_256_GCM_SHA384");
// (optional) Set parameters for DH-based ciphers
status = smaxSetDHCypherParams("path/to/redis.dh");
if(status) {
// Oops, the parameter file is not accessible...
...
}
```

### Reconfiguration

The SMA-X configuration is activated at the time of connection (see below), after which it persists, through
successive connections also. That means, that once you have connected to the server, you cannot alter the
configuration prior to another connection attempt, unless you call `smaxReset()` first while disconnected.
`smaxReset()` will discard the currently configured Redis instance, so the next connection will create a new one, with
the current configuration.


------------------------------------------------------------------------------

<a name="connecting"></a>
Expand Down
10 changes: 8 additions & 2 deletions include/smax.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@
*
* \date Jan 26, 2018
* \author Attila Kovacs
* \version 1.0
*
* smax-clib C/C++ client library to an SMA-X database, available on GitHub as:
*
* https://github.com/Smithsonian/redisx
*
*/

#ifndef SMAX_H_
Expand Down Expand Up @@ -214,9 +220,9 @@ int smaxDisableTLS();
int smaxSetTLSVerify(boolean value);
int smaxSetMutualTLS(const char *cert_file, const char *key_file);
int smaxSetTLSServerName(const char *host);
int smaxSetTLSCiphers(const char *cipher_list);
int smaxSetTLSCiphers(const char *list);
int smaxSetTLSCipherSuites(const char *list);
int smaxSetDHCipherParams(const char *dh_params_file);
int smaxSetDHCipherParams(const char *dh_file);

int smaxConnect();
int smaxConnectTo(const char *server);
Expand Down
38 changes: 25 additions & 13 deletions src/smax-tls.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>

#include "smax-private.h"
Expand Down Expand Up @@ -63,7 +64,6 @@ int smaxConfigTLSAsync(Redis *redis) {
}
/// \endcond


/**
* Configures a TLS-encrypted connection to thr SMA-X server with the specified CA certificate file.
* Normally you will want to set up mutual TLS with smaxSetMutualTLS() also, unless the server is not
Expand All @@ -73,7 +73,8 @@ int smaxConfigTLSAsync(Redis *redis) {
* @param ca_path Directory containing CA certificates. It may be NULL to use the default locations.
* @param ca_file CA certificate file relative to specified directory. It may be NULL to use default
* certificate.
* @return X_SUCCESS (0) if successful, or else X_FAILURE (-1) if the SMA-X library was built
* @return X_SUCCESS (0) if successful, or X_NAME_INVALID if the path or CA certificate file
* is not accessible, or else X_FAILURE (-1) if the SMA-X library was built
* without TLS support.
*
* @sa smaxDisableTLS()
Expand All @@ -85,7 +86,12 @@ int smaxConfigTLSAsync(Redis *redis) {
* @sa smaxSetTLSVerify()
*/
int smaxSetTLS(const char *ca_path, const char *ca_file) {
static const char *fn = "smaxSetTLS";

#if WITH_TLS
if(ca_path) if(access(ca_path, R_OK) != 0) return x_error(X_NAME_INVALID, EINVAL, fn, "certificate directory not accessible: %s", ca_path);
if(ca_file) if(access(ca_file, R_OK) != 0) return x_error(X_NAME_INVALID, EINVAL, fn, "CA certificate not accessible: %s", ca_file);

smaxLockConfig();
if(config.ca_path) free(config.ca_path);
config.ca_path = xStringCopyOf(ca_path);
Expand All @@ -97,7 +103,7 @@ int smaxSetTLS(const char *ca_path, const char *ca_file) {
#else
(void) ca_path;
(void) ca_file;
return x_error(X_FAILURE, ENOSYS, "smaxSetTLS", "smax-clib was built without TLS support");
return x_error(X_FAILURE, ENOSYS, fn, "smax-clib was built without TLS support");
#endif
}

Expand Down Expand Up @@ -139,7 +145,6 @@ int smaxSetTLSVerify(boolean value) {
#endif
}


/**
* Set a TLS certificate and private key for mutual TLS. You will still need to call smaxSetTLS() also to create a
* complete TLS configuration. Redis normally uses mutual TLS, which requires both the client and the server to
Expand All @@ -151,13 +156,18 @@ int smaxSetTLSVerify(boolean value) {
*
* @param cert_file Path to the server's certificate file.
* @param key_file Path to the server'sprivate key file.
* @return X_SUCCESS (0) if successful, or else X_FAILURE (-1) if the SMA-X library was built without TLS
* support.
* @return X_SUCCESS (0) if successful, or, X_NAME_INVALID if the certificate or private key file is not
* accessible, or else X_FAILURE (-1) if the SMA-X library was built without TLS support.
*
* @sa smaxSetTLS()
*/
int smaxSetMutualTLS(const char *cert_file, const char *key_file) {
static const char *fn = "smaxSetMutualTLS";

#if WITH_TLS
if(cert_file) if(access(cert_file, R_OK) != 0) return x_error(X_NAME_INVALID, EINVAL, fn, "certificate not accessible: %s", cert_file);
if(key_file) if(access(key_file, R_OK) != 0) return x_error(X_NAME_INVALID, EINVAL, fn, "private key not accessible: %s", key_file);

smaxLockConfig();
if(config.certificate) free(config.certificate);
config.certificate = xStringCopyOf(cert_file);
Expand All @@ -168,7 +178,7 @@ int smaxSetMutualTLS(const char *cert_file, const char *key_file) {
#else
(void) cert_file;
(void) key_file;
return x_error(X_FAILURE, ENOSYS, "smaxSetMutualTLS", "smax-clib was built without TLS support");
return x_error(X_FAILURE, ENOSYS, fn, "smax-clib was built without TLS support");
#endif
}

Expand Down Expand Up @@ -245,20 +255,22 @@ int smaxSetTLSCipherSuites(const char *list) {
/**
* Sets parameters for DH-based cyphers when using a TLS encrypted connection.
*
* @param dh_params_file Path to the DH-based cypher parameters file (in PEM format; we don't support
* the old DER format), or NULL for no params.
* @return X_SUCCESS (0) if successful, or else X_FAILURE (-1) if the SMA-X library was built
* without TLS support.
* @param dh_file Path to the DH-based cypher parameters file (in PEM format; we don't support
* the old DER format), or NULL for no params.
* @return X_SUCCESS (0) if successful, or X_NAME_INVALID if the file is not accessible, or else
* X_FAILURE (-1) if the SMA-X library was built without TLS support.
*
* @sa smaxSetTLS()
* @sa smaxSetTLSCiphers()
* @sa smaxSetTLSCipherSuites()
*/
int smaxSetDHCipherParams(const char *dh_params_file) {
int smaxSetDHCipherParams(const char *dh_file) {
#if WITH_TLS
if(dh_file) if(access(dh_file, R_OK) != 0) return x_error(X_NAME_INVALID, EINVAL, "smaxSetDHCipherParams", "DH parameters not accessible: %s", dh_file);

smaxLockConfig();
if(config.dh_params) free(config.dh_params);
config.dh_params = xStringCopyOf(dh_params_file);
config.dh_params = xStringCopyOf(dh_file);
smaxUnlockConfig();
return X_SUCCESS;
#else
Expand Down

0 comments on commit ca41c37

Please sign in to comment.