Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 67 additions & 3 deletions TLS.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ curl -v --cacert server.pub --url https://localhost:35800
```


## Certificate Information
## Server Certificate Information

Information about the used server certificate can be queried during runtime. The data is available
via the thread local storage which is a noxDB graph and can be queried with the noxDB API, see
Expand All @@ -81,10 +81,74 @@ certificate values can be accessed via their corresponding keys. The keys are ba
GSKit certificate data ids. The value for `CERT_COMMON_NAME` can be access by the key `common_name`.
All values are strings.

The certificate is only available if it has been enabled by calling `il_setTlsServerCertEnabled`.
The certificate information is only available if it has been enabled by calling `il_setTlsServerCertEnabled`,
`Tls` in this case means thread local storage.

```
il_setTlsServerCertEnabled(config : IL_TRUE);
```

For more information and available keys see the GSKit API [gsk_attribute_get_cert_info](https://www.ibm.com/docs/en/i/7.4.0?topic=ssw_ibm_i_74/apis/gsk_attribute_get_cert_info.html).
For more information and available keys see the GSKit API [gsk_attribute_get_cert_info](https://www.ibm.com/docs/en/i/7.4.0?topic=ssw_ibm_i_74/apis/gsk_attribute_get_cert_info.html).



## mTLS

ILEastic supports mutual TLS which means that not only the server certificate is checked by the
client but the client must also send a certficiate which is validated by the server).

This can be enabled by setting the `client auth mode` to something other than NONE.

With the configuration set to IL_CLIENT_AUTH_MODE_REQUIRED the client must provide a valid client
certificate to establish a TLS connection.

With the configuration set to IL_CLIENT_AUTH_MODE_PASSTHRU the client is asked for a client
certficate but does not need to provide one.

A requirement for this is having TLS enabled by providing a server certificate in the
configured keystore file.

All client certificates must also be available in the same keystore file.

### Client Certificate Information

Information about the provided client certificate can be queried during runtime. The data is available
via the thread local storage which is a noxDB graph and can be queried with the noxDB API, see
`il_getThreadMem`.

Example:

```
dcl-s tls pointer;
dcl-s value varchar(100);

tls = il_getThreadMem(request);
value = jx_getStr(tls : '/ileastic/certificate/client/common_name');
```

The client certificate information is stored at the path `/ileastic/certificate/client`. The
certificate values can be accessed via their corresponding keys. The keys are based on the
GSKit certificate data ids. The value for `CERT_COMMON_NAME` can be access by the key `common_name`.
All values are strings.

The certificate information is only available if it has been enabled by calling `il_setTlsClientCertEnabled`,
`Tls` in this case means thread local storage.

```
il_setTlsClientCertEnabled(config : IL_TRUE);
```

For more information and available keys see the GSKit API [gsk_attribute_get_cert_info](https://www.ibm.com/docs/en/i/7.4.0?topic=ssw_ibm_i_74/apis/gsk_attribute_get_cert_info.html).

### Client Certifcate Validation Result

The result of the validation of the client certificate can be queried via the thread local storage
at `/ileastic/certificate/client/validationcode`. The value is the returned value of the call to
`gsk_attribute_get_numeric_value` with enum id `GSK_CERTIFICATE_VALIDATION_CODE`.

TLDR: validationcode = 0 means client certificate is valid

### Plugins

Plugins can access the certificate information by querying the thread local store. This can be used
to further filter requests by custom criterias.
2 changes: 2 additions & 0 deletions headers/ileastic.bnd
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,6 @@ STRPGMEXP PGMLVL(*CURRENT) SIGNATURE('ILEastic 1.1.2')
EXPORT SYMBOL("il_mediatype_parseMediaType")
EXPORT SYMBOL("il_setKeyfile")
EXPORT SYMBOL("il_setTlsServerCertEnabled")
EXPORT SYMBOL("il_setTlsClientCertEnabled")
EXPORT SYMBOL("il_setClientAuthMode")
ENDPGMEXP
71 changes: 69 additions & 2 deletions headers/ileastic.rpgle
Original file line number Diff line number Diff line change
Expand Up @@ -366,9 +366,28 @@ dcl-c IL_MEDIA_TYPE_JSON 'application/json';
///
dcl-c IL_MEDIA_TYPE_XML 'application/xml';

///
// Generic <code>true</code> constant
///
dcl-c IL_TRUE 1;
///
// Generic <code>false</code> constant
///
dcl-c IL_FALSE 0;

///
// mTLS : No client certificate requested (no mTLS)
///
dcl-c IL_CLIENT_AUTH_MODE_NONE 0;
///
// mTLS : client certificate is required else TLS session will not be started
///
dcl-c IL_CLIENT_AUTH_MODE_REQUIRED 1;
///
// mTLS : client certificate is always request but does not need to be provided by the client. TLS session is always started.
///
dcl-c IL_CLIENT_AUTH_MODE_PASSTHRU 2;

///
// Configuration
///
Expand All @@ -382,6 +401,8 @@ dcl-ds il_config qualified template;
isWorker ind;
threadingMode int(5);
tlsServerCertEnabled int(3);
tlsClientCertEnabled int(3);
clientAuthMode int(3);
filler char(4096); // required - contains the private internal handlers
end-ds;

Expand Down Expand Up @@ -1067,7 +1088,7 @@ dcl-pr il_setKeyfile extproc(*dclcase);
end-pr;

///
// Enable Server Certificate Infos in TLS
// Enable server certificate infos in TLS
//
// If enabled the available infos about the used server certificate for the TLS
// connection are copied to the thread local storage avaiable in the request,
Expand All @@ -1083,5 +1104,51 @@ end-pr;
///
dcl-pr il_setTlsServerCertEnabled extproc(*dclcase);
config likeds(il_config);
enabled int(5) value;
enabled int(3) value;
end-pr;

///
// Enable client certificate infos in TLS
//
// If enabled the available infos about the used client certificate for the TLS
// connection are copied to the thread local storage avaiable in the request,
// see il_getThreadMem.
// <p>
// The information will be copied to the path /ileastic/certificate/client.
// The information is only available if the connection uses TLS (HTTPS).
//
// @param Configuration
// @param IL_TRUE = enabled , IL_FALSE = disable (default)
//
// @info This setting has no effect if no TLS is used.
///
dcl-pr il_setTlsClientCertEnabled extproc(*dclcase);
config likeds(il_config);
enabled int(3) value;
end-pr;

///
// Set client auth mode (mTLS)
//
// Sets the client auth mode. The client auth mode defines if the client is asked
// for a client certificate which will be validated using the configured key
// store.
// <br/><br/>
// By default the client is not asked for a certificated (no mTLS).
// <br/><br/>
// With the configuration set to IL_CLIENT_AUTH_MODE_REQUIRED the client must
// provide a valid client certificate to establish a TLS connection.
// <br/><br/>
// With the configuration set to IL_CLIENT_AUTH_MODE_PASSTHRU the client is
// asked for a client certficate but does not need to provide one.
// <br/><br/>
// The result of the client certificate validation is provided via the thread
// local storage at <code>/ileastic/certificate/client/validationcode</code>.
//
// @param Configuration
// @param mTLS client auth mode (see IL_CLIENT_AUTH_MODE_xyz)
///
dcl-pr il_setClientAuthMode extproc(*dclcase);
config likeds(il_config);
mode int(3) value;
end-pr;
12 changes: 11 additions & 1 deletion headers/sysdef.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,14 @@ typedef enum _THREADING_MODE {
} THREADING_MODE , *PTHREADING_MODE;
#pragma enum (pop)

#pragma enum (1)
typedef enum _CLIENT_AUTH_MODE {
CLIENT_AUTH_MODE_NONE = 0,
CLIENT_AUTH_MODE_REQUIRED = 1,
CLIENT_AUTH_MODE_PASSTHRU = 2
} CLIENT_AUTH_MODE;
#pragma enum (pop)

typedef _Packed struct {
FCGX_Stream * out;
FCGX_Stream * in;
Expand All @@ -66,7 +74,9 @@ typedef _Packed struct _CONFIG {
BOOL isWorker;
THREADING_MODE threadingMode;
BOOL tlsServerCertEnabled;
UCHAR filler[1022];
BOOL tlsClientCertEnabled;
CLIENT_AUTH_MODE clientAuthMode;
UCHAR filler[1021];
// Private:
int mainSocket;
int clientSocket;
Expand Down
21 changes: 21 additions & 0 deletions itests/ilbasics.rpgle
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@ dcl-proc main;
endif;

il_setTlsServerCertEnabled(config : IL_TRUE);
il_setTlsClientCertEnabled(config : IL_TRUE);
il_setClientAuthMode(config : IL_CLIENT_AUTH_MODE_PASSTHRU);

il_addRoute(config : %paddr(test_getBookExcerpt) : IL_GET : REGEX_START + '/book/excerpt' + REGEX_END);
il_addRoute(config : %paddr(test_deleteBook) : IL_DELETE: REGEX_START + '/book/' + CURLY_OPEN + 'isbn' + CURLY_CLOSE + REGEX_END);
Expand All @@ -90,6 +92,7 @@ dcl-proc main;
il_addRoute(config : %paddr(test_search) : IL_GET : REGEX_START + '/book' + REGEX_END);
il_addRoute(config : %paddr(test_bookOptions) : IL_OPTIONS : REGEX_START + '/book' + REGEX_END);
il_addRoute(config : %paddr(test_getServerCertInfos) : IL_GET : REGEX_START + '/cert/server' + REGEX_END);
il_addRoute(config : %paddr(test_getClientCertInfos) : IL_GET : REGEX_START + '/cert/client' + REGEX_END);
il_addRoute(config : %paddr(test_notFound));

il_listen (config);
Expand Down Expand Up @@ -295,3 +298,21 @@ dcl-proc test_getServerCertInfos;
response.contentType = 'application/json';
il_responseWriteStream(response: jx_stream(serverCertInfos));
end-proc;


dcl-proc test_getClientCertInfos;
dcl-pi *n;
request likeds(IL_REQUEST);
response likeds(IL_RESPONSE);
end-pi;

dcl-s tls pointer;
dcl-s clientCertInfos pointer;

tls = il_getThreadMem(request);
clientCertInfos = jx_locate(tls : '/ileastic/certificate/client');

response.status = 200;
response.contentType = 'application/json';
il_responseWriteStream(response: jx_stream(clientCertInfos));
end-proc;
8 changes: 8 additions & 0 deletions src/api.c
Original file line number Diff line number Diff line change
Expand Up @@ -456,3 +456,11 @@ void il_setKeyfile(PCONFIG config, PVARCHAR256 keyfilePath , PVARCHAR64 keyfileP
void il_setTlsServerCertEnabled(PCONFIG config, BOOL enabled) {
config->tlsServerCertEnabled = enabled;
}

void il_setTlsClientCertEnabled(PCONFIG config, BOOL enabled) {
config->tlsClientCertEnabled = enabled;
}

void il_setClientAuthMode(PCONFIG config, CLIENT_AUTH_MODE mode) {
config->clientAuthMode = mode;
}
Loading