Hello,
On 1/5/2017 4:47 PM, Emeric Brun wrote:
> On 01/05/2017 04:22 AM, Nenad Merdanovic wrote:
>> I have a working patch for this, but it's very ugly currently (minimal
>> error checking, no warnings/messages, no docs, very basic tests done
>> only, etc.)
>>
>> I expect to have a version for review by EOW (depending on the workload,
>> maybe a bit sooner).
>>
>> Regards,
>> Nenad
>
> Great news Nenad!
I haven't really had as much time as I wanted for this, but I am
attaching a patch that I think is good enough for review as I don't
expect design decisions to change.
There are some minor things I want to improve (rename things like
'psk_key'), add some ifdefs for OPENSSL_NO_PSK and write the
documentation of course. Depending on the client/server side:
- On the bind line, there is a psk-file keyword that loads a series of
PSKs and any can be used
- On the server line, there is a psk keyword, that takes the same format
as the file (:) and is used for the backend connection.
I'll send a full Git patch if this looks OK within the next few days.
Regards,
Nenad
diff --git a/include/types/listener.h b/include/types/listener.h
index 03f4a72b..4dc5a05b 100644
--- a/include/types/listener.h
+++ b/include/types/listener.h
@@ -134,6 +134,7 @@ struct bind_conf {
int strict_sni;/* refuse negotiation if sni doesn't match a
certificate */
struct eb_root sni_ctx;/* sni_ctx tree of all known certs
full-names sorted by name */
struct eb_root sni_w_ctx; /* sni_ctx tree of all known certs wildcards
sorted by name */
+ struct eb_root psk;/* PSK tree, keyed by identity */
struct tls_keys_ref *keys_ref; /* TLS ticket keys reference */
char *ca_sign_file;/* CAFile used to generate and sign server
certificates */
diff --git a/include/types/server.h b/include/types/server.h
index 5092eb7d..f0cf8bd4 100644
--- a/include/types/server.h
+++ b/include/types/server.h
@@ -261,6 +261,8 @@ struct server {
char *ca_file; /* CAfile to use on verify */
char *crl_file; /* CRLfile to use on verify */
char *client_crt; /* client certificate to send */
+ char *psk_identity; /* PSK identity */
+ char *psk_key; /* PSK key */
struct sample_expr *sni;/* sample expression for SNI */
} ssl_ctx;
#endif
diff --git a/include/types/ssl_sock.h b/include/types/ssl_sock.h
index e71ba793..6a24a2ec 100644
--- a/include/types/ssl_sock.h
+++ b/include/types/ssl_sock.h
@@ -25,6 +25,12 @@
#include
#include
+struct psk_pair {
+ char *key;
+ char *identity;
+ struct ebmb_node node;
+};
+
struct sni_ctx {
SSL_CTX *ctx; /* context associated to the certificate */
int order;/* load order for the certificate */
diff --git a/src/ssl_sock.c b/src/ssl_sock.c
index acf1c39c..717ad323 100644
--- a/src/ssl_sock.c
+++ b/src/ssl_sock.c
@@ -531,6 +531,29 @@ end:
return ret;
}
+static int ssl_srv_psk_cb(SSL *ssl, char *identity, unsigned char *psk,
unsigned int max_psk_len)
+{
+ struct connection *conn;
+ struct ebmb_node *node;
+ struct psk_pair *pp;
+
+ conn = SSL_get_app_data(ssl);
+
+ node = ebst_lookup(_listener(conn->target)->bind_conf->psk,
identity);
+
+ if (!node)
+ return 0;
+
+ pp = ebmb_entry(node, struct psk_pair, node);
+
+ if(strlen(pp->key) > max_psk_len)
+ return 0;
+
+ memcpy(psk, pp->key, strlen(pp->key));
+
+ return(strlen(pp->key));
+}
+
#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
static int ssl_tlsext_ticket_key_cb(SSL *s, unsigned char key_name[16],
unsigned char *iv, EVP_CIPHER_CTX *ectx, HMAC_CTX *hctx, int enc)
{
@@ -2827,6 +2850,9 @@ int ssl_sock_prepare_ctx(struct bind_conf *bind_conf,
SSL_CTX *ctx)
}
#endif
+ if(ebmb_first(_conf->psk))
+ SSL_CTX_set_psk_server_callback(ctx, ssl_srv_psk_cb);
+
if (global_ssl.life_time)
SSL_CTX_set_timeout(ctx, global_ssl.life_time);
@@ -2988,6 +3014,30 @@ static int ssl_sock_srv_hostcheck(const char *pattern,
const char *hostname)
return 1;
}
+static int ssl_sock_client_psk_cb(SSL *ssl, const char *hint, char *identity,
unsigned int max_identity_len, unsigned char *psk, unsigned int max_psk_len)
+{
+ struct connection *conn;
+ struct server *srv;
+ int ret;
+
+ (void) hint;
+
+ conn = SSL_get_app_data(ssl);
+ srv = objt_server(conn->target);
+
+ if(strlen(srv->ssl_ctx.psk_identity) + 1 > max_identity_len)
+ return 0;
+
+ strncpy(identity, srv->ssl_ctx.psk_identity, max_identity_len);
+
+ if(strlen(srv->ssl_ctx.psk_key) > max_psk_len)
+ return 0;
+
+ memcpy(psk, srv->ssl_ctx.psk_key,