MINOR: ssl/cli: implement "add ssl ca-file"
In ticket #1805 an user is impacted by the limitation of size of the CLI buffer when updating a ca-file. This patch allows a user to append new certificates to a ca-file instead of trying to put them all with "set ssl ca-file" The implementation use a new function ssl_store_dup_cafile_entry() which duplicates a cafile_entry and its X509_STORE. ssl_store_load_ca_from_buf() was modified to take an apped parameter so we could share the function for "set" and "add".
This commit is contained in:
parent
d4774d3cfa
commit
62c0b99e3b
|
@ -1679,6 +1679,21 @@ add server <backend>/<server> [args]*
|
|||
Their syntax is similar to the server line from the configuration file,
|
||||
please refer to their individual documentation for details.
|
||||
|
||||
add ssl ca-file <cafile> <payload>
|
||||
Add a new certificate to a ca-file. This command is useful when you reached
|
||||
the buffer size limit on the CLI and want to add multiple certicates.
|
||||
Instead of doing a "set" with all the certificates you are able to add each
|
||||
certificate individually. A "set ssl ca-file" will reset the ca-file.
|
||||
|
||||
Example:
|
||||
echo -e "set ssl ca-file cafile.pem <<\n$(cat rootCA.crt)\n" | \
|
||||
socat /var/run/haproxy.stat -
|
||||
echo -e "add ssl ca-file cafile.pem <<\n$(cat intermediate1.crt)\n" | \
|
||||
socat /var/run/haproxy.stat -
|
||||
echo -e "add ssl ca-file cafile.pem <<\n$(cat intermediate2.crt)\n" | \
|
||||
socat /var/run/haproxy.stat -
|
||||
echo "commit ssl ca-file cafile.pem" | socat /var/run/haproxy.stat -
|
||||
|
||||
add ssl crt-list <crtlist> <certificate>
|
||||
add ssl crt-list <crtlist> <payload>
|
||||
Add an certificate in a crt-list. It can also be used for directories since
|
||||
|
@ -1821,8 +1836,8 @@ commit ssl ca-file <cafile>
|
|||
contexts that use it, you will need to add it to a crt-list with "add ssl
|
||||
crt-list".
|
||||
|
||||
See also "new ssl ca-file", "set ssl ca-file", "abort ssl ca-file" and
|
||||
"add ssl crt-list".
|
||||
See also "new ssl ca-file", "set ssl ca-file", "add ssl ca-file",
|
||||
"abort ssl ca-file" and "add ssl crt-list".
|
||||
|
||||
commit ssl cert <filename>
|
||||
Commit a temporary SSL certificate update transaction.
|
||||
|
@ -2127,7 +2142,7 @@ httpclient <method> <URI>
|
|||
new ssl ca-file <cafile>
|
||||
Create a new empty CA file tree entry to be filled with a set of CA
|
||||
certificates and added to a crt-list. This command should be used in
|
||||
combination with "set ssl ca-file" and "add ssl crt-list".
|
||||
combination with "set ssl ca-file", "add ssl ca-file" and "add ssl crt-list".
|
||||
|
||||
new ssl cert <filename>
|
||||
Create a new empty SSL certificate store to be filled with a certificate and
|
||||
|
@ -2309,15 +2324,16 @@ set severity-output [ none | number | string ]
|
|||
duration of the current session.
|
||||
|
||||
set ssl ca-file <cafile> <payload>
|
||||
This command is part of a transaction system, the "commit ssl ca-file" and
|
||||
this command is part of a transaction system, the "commit ssl ca-file" and
|
||||
"abort ssl ca-file" commands could be required.
|
||||
If there is no on-going transaction, it will create a CA file tree entry into
|
||||
which the certificates contained in the payload will be stored. The CA file
|
||||
entry will not be stored in the CA file tree and will only be kept in a
|
||||
temporary transaction. If a transaction with the same filename already exists,
|
||||
the previous CA file entry will be deleted and replaced by the new one.
|
||||
Once the modifications are done, you have to commit the transaction through
|
||||
a "commit ssl ca-file" call.
|
||||
if there is no on-going transaction, it will create a ca file tree entry into
|
||||
which the certificates contained in the payload will be stored. the ca file
|
||||
entry will not be stored in the ca file tree and will only be kept in a
|
||||
temporary transaction. if a transaction with the same filename already exists,
|
||||
the previous ca file entry will be deleted and replaced by the new one.
|
||||
once the modifications are done, you have to commit the transaction through
|
||||
a "commit ssl ca-file" call. If you want to add multiple certificates
|
||||
separately, you can use the "add ssl ca-file" command
|
||||
|
||||
Example:
|
||||
echo -e "set ssl ca-file cafile.pem <<\n$(cat rootCA.crt)\n" | \
|
||||
|
|
|
@ -63,6 +63,7 @@ struct cafile_entry *ssl_store_get_cafile_entry(char *path, int oldest_entry);
|
|||
X509_STORE* ssl_store_get0_locations_file(char *path);
|
||||
int ssl_store_add_uncommitted_cafile_entry(struct cafile_entry *entry);
|
||||
struct cafile_entry *ssl_store_create_cafile_entry(char *path, X509_STORE *store, enum cafile_type type);
|
||||
struct cafile_entry *ssl_store_dup_cafile_entry(struct cafile_entry *src);
|
||||
void ssl_store_delete_cafile_entry(struct cafile_entry *ca_e);
|
||||
int ssl_store_load_ca_from_buf(struct cafile_entry *ca_e, char *cert_buf, int append);
|
||||
int ssl_store_load_locations_file(char *path, int create_if_none, enum cafile_type type);
|
||||
|
|
|
@ -81,6 +81,26 @@ shell {
|
|||
echo "commit ssl ca-file new_cafile.crt" | socat "${tmpdir}/h1/stats" -
|
||||
}
|
||||
|
||||
# Remove the unliked CA file and create a new one with the "add ssl ca-file method"
|
||||
|
||||
haproxy h1 -cli {
|
||||
send "del ssl ca-file new_cafile.crt"
|
||||
expect ~ "CA file 'new_cafile.crt' deleted!"
|
||||
|
||||
send "new ssl ca-file new_cafile.crt"
|
||||
expect ~ "New CA file created 'new_cafile.crt'!"
|
||||
}
|
||||
|
||||
shell {
|
||||
printf "add ssl ca-file new_cafile.crt <<\n$(cat ${testdir}/set_cafile_interCA1.crt)\n\n" | socat "${tmpdir}/h1/stats" -
|
||||
echo "commit ssl ca-file new_cafile.crt" | socat "${tmpdir}/h1/stats" -
|
||||
}
|
||||
|
||||
shell {
|
||||
printf "set ssl ca-file new_cafile.crt <<\n$(cat ${testdir}/set_cafile_interCA1.crt)\n\n" | socat "${tmpdir}/h1/stats" -
|
||||
echo "commit ssl ca-file new_cafile.crt" | socat "${tmpdir}/h1/stats" -
|
||||
}
|
||||
|
||||
haproxy h1 -cli {
|
||||
send "show ssl ca-file"
|
||||
expect ~ ".*new_cafile.crt - 1 certificate.*"
|
||||
|
|
|
@ -138,7 +138,9 @@ client c1 -connect ${h1_clearverifiedlst_sock} {
|
|||
# Update the server line's ca-file. The server certificate should now be accepted by
|
||||
# the frontend. We replace the single CA by a list of CAs that includes the correct one.
|
||||
shell {
|
||||
printf "set ssl ca-file ${testdir}/set_cafile_interCA1.crt <<\n$(cat ${testdir}/set_cafile_interCA1.crt)\n$(cat ${testdir}/set_cafile_interCA2.crt)\n$(cat ${testdir}/set_cafile_rootCA.crt)\n\n" | socat "${tmpdir}/h1/stats" -
|
||||
printf "set ssl ca-file ${testdir}/set_cafile_interCA1.crt <<\n$(cat ${testdir}/set_cafile_interCA1.crt)\n\n" | socat "${tmpdir}/h1/stats" -
|
||||
printf "add ssl ca-file ${testdir}/set_cafile_interCA1.crt <<\n$(cat ${testdir}/set_cafile_interCA2.crt)\n\n" | socat "${tmpdir}/h1/stats" -
|
||||
printf "add ssl ca-file ${testdir}/set_cafile_interCA1.crt <<\n$(cat ${testdir}/set_cafile_rootCA.crt)\n\n" | socat "${tmpdir}/h1/stats" -
|
||||
echo "commit ssl ca-file ${testdir}/set_cafile_interCA1.crt" | socat "${tmpdir}/h1/stats" -
|
||||
}
|
||||
|
||||
|
|
|
@ -1076,6 +1076,67 @@ struct cafile_entry *ssl_store_create_cafile_entry(char *path, X509_STORE *store
|
|||
return ca_e;
|
||||
}
|
||||
|
||||
|
||||
/* Duplicate a cafile_entry
|
||||
* Allocate the X509_STORE and copy the X509 and CRL inside.
|
||||
*
|
||||
* Return the newly allocated cafile_entry or NULL.
|
||||
*
|
||||
*/
|
||||
struct cafile_entry *ssl_store_dup_cafile_entry(struct cafile_entry *src)
|
||||
{
|
||||
struct cafile_entry *dst = NULL;
|
||||
X509_STORE *store = NULL;
|
||||
STACK_OF(X509_OBJECT) *objs;
|
||||
int i;
|
||||
|
||||
if (!src)
|
||||
return NULL;
|
||||
|
||||
if (src->ca_store) {
|
||||
/* if there was a store in the src, copy it */
|
||||
store = X509_STORE_new();
|
||||
if (!store)
|
||||
goto err;
|
||||
|
||||
objs = X509_STORE_get0_objects(src->ca_store);
|
||||
for (i = 0; i < sk_X509_OBJECT_num(objs); i++) {
|
||||
X509 *cert;
|
||||
X509_CRL *crl;
|
||||
|
||||
cert = X509_OBJECT_get0_X509(sk_X509_OBJECT_value(objs, i));
|
||||
if (cert) {
|
||||
if (X509_STORE_add_cert(store, cert) == 0) {
|
||||
/* only exits on error if the error is not about duplicate certificates */
|
||||
if (!(ERR_GET_REASON(ERR_get_error()) == X509_R_CERT_ALREADY_IN_HASH_TABLE)) {
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
crl = X509_OBJECT_get0_X509_CRL(sk_X509_OBJECT_value(objs, i));
|
||||
if (crl) {
|
||||
if (X509_STORE_add_crl(store, crl) == 0) {
|
||||
/* only exits on error if the error is not about duplicate certificates */
|
||||
if (!(ERR_GET_REASON(ERR_get_error()) == X509_R_CERT_ALREADY_IN_HASH_TABLE)) {
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
dst = ssl_store_create_cafile_entry(src->path, store, src->type);
|
||||
|
||||
return dst;
|
||||
|
||||
err:
|
||||
X509_STORE_free(store);
|
||||
ha_free(&dst);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Delete a cafile_entry. The caller is responsible from removing this entry
|
||||
* from the cafile_tree first if is was previously added into it. */
|
||||
void ssl_store_delete_cafile_entry(struct cafile_entry *ca_e)
|
||||
|
@ -2584,10 +2645,15 @@ static int cli_parse_set_cafile(char **args, char *payload, struct appctx *appct
|
|||
char *err = NULL;
|
||||
int errcode = 0;
|
||||
struct buffer *buf;
|
||||
int add_cmd = 0;
|
||||
|
||||
if (!cli_has_level(appctx, ACCESS_LVL_ADMIN))
|
||||
return 1;
|
||||
|
||||
/* this is "add ssl ca-file" */
|
||||
if (*args[0] == 'a')
|
||||
add_cmd = 1;
|
||||
|
||||
if (!*args[3] || !payload)
|
||||
return cli_err(appctx, "'set ssl ca-file expects a filename and CAs as a payload\n");
|
||||
|
||||
|
@ -2620,8 +2686,7 @@ static int cli_parse_set_cafile(char **args, char *payload, struct appctx *appct
|
|||
goto end;
|
||||
}
|
||||
old_cafile_entry = cafile_transaction.old_cafile_entry;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
/* lookup for the certificate in the tree */
|
||||
old_cafile_entry = ssl_store_get_cafile_entry(buf->area, 0);
|
||||
}
|
||||
|
@ -2633,17 +2698,21 @@ static int cli_parse_set_cafile(char **args, char *payload, struct appctx *appct
|
|||
goto end;
|
||||
}
|
||||
|
||||
/* Create a new cafile_entry without adding it to the cafile tree. */
|
||||
new_cafile_entry = ssl_store_create_cafile_entry(old_cafile_entry->path, NULL, CAFILE_CERT);
|
||||
/* if the transaction is new, duplicate the old_ca_file_entry, otherwise duplicate the cafile in the current transaction */
|
||||
if (cafile_transaction.new_cafile_entry)
|
||||
new_cafile_entry = ssl_store_dup_cafile_entry(cafile_transaction.new_cafile_entry);
|
||||
else
|
||||
new_cafile_entry = ssl_store_dup_cafile_entry(old_cafile_entry);
|
||||
|
||||
if (!new_cafile_entry) {
|
||||
memprintf(&err, "%sCannot allocate memory!\n",
|
||||
err ? err : "");
|
||||
memprintf(&err, "%sCan't allocate memory\n", err ? err : "");
|
||||
errcode |= ERR_ALERT | ERR_FATAL;
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* Fill the new entry with the new CAs. */
|
||||
if (ssl_store_load_ca_from_buf(new_cafile_entry, payload, 0)) {
|
||||
/* Fill the new entry with the new CAs. The add_cmd variable determine
|
||||
if we flush the X509_STORE or not */
|
||||
if (ssl_store_load_ca_from_buf(new_cafile_entry, payload, add_cmd)) {
|
||||
memprintf(&err, "%sInvalid payload\n", err ? err : "");
|
||||
errcode |= ERR_ALERT | ERR_FATAL;
|
||||
goto end;
|
||||
|
@ -3853,6 +3922,7 @@ static struct cli_kw_list cli_kws = {{ },{
|
|||
{ { "show", "ssl", "cert", NULL }, "show ssl cert [<certfile>] : display the SSL certificates used in memory, or the details of a file", cli_parse_show_cert, cli_io_handler_show_cert, cli_release_show_cert },
|
||||
|
||||
{ { "new", "ssl", "ca-file", NULL }, "new ssl ca-file <cafile> : create a new CA file to be used in a crt-list", cli_parse_new_cafile, NULL, NULL },
|
||||
{ { "add", "ssl", "ca-file", NULL }, "add ssl ca-file <cafile> <payload> : add a certificate into the CA file", cli_parse_set_cafile, NULL, NULL },
|
||||
{ { "set", "ssl", "ca-file", NULL }, "set ssl ca-file <cafile> <payload> : replace a CA file", cli_parse_set_cafile, NULL, NULL },
|
||||
{ { "commit", "ssl", "ca-file", NULL }, "commit ssl ca-file <cafile> : commit a CA file", cli_parse_commit_cafile, cli_io_handler_commit_cafile_crlfile, cli_release_commit_cafile },
|
||||
{ { "abort", "ssl", "ca-file", NULL }, "abort ssl ca-file <cafile> : abort a transaction for a CA file", cli_parse_abort_cafile, NULL, NULL },
|
||||
|
|
Loading…
Reference in New Issue