Skip to content

Commit cf7331a

Browse files
committed
TCP input TLS - Add TLS configuration.
1 parent 5cd6906 commit cf7331a

File tree

2 files changed

+128
-6
lines changed

2 files changed

+128
-6
lines changed

src/plugins/input/tcp/src/Config.cpp

Lines changed: 100 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include <string> // string
1616
#include <cassert> // assert
1717
#include <cstdint> // UINT16_MAX
18+
#include <cstring>
1819

1920
#include <libfds.h> // fds_*, FDS_*
2021

@@ -30,19 +31,41 @@ namespace tcp_in {
3031
* <params>
3132
* <localPort>...</localPort> <!-- optional -->
3233
* <localIPAddress>...</localIPAddress> <!-- optional, multiple times -->
34+
* <certificatePath>...</certificatePath> <!-- optional -->
3335
* </params>
3436
*/
3537

3638
enum ParamsXmlNodes {
3739
PARAM_PORT,
3840
PARAM_IPADDR,
41+
PARAM_TLS,
42+
43+
PARAM_TLS_CERTIFICATE,
44+
PARAM_TLS_PRIVATE_KEY,
45+
PARAM_TLS_VERIFY_PEER,
46+
PARAM_TLS_CA_FILE,
47+
PARAM_TLS_CA_DIR,
48+
PARAM_TLS_CA_STORE,
49+
PARAM_TLS_INSECURE,
50+
};
51+
52+
static const struct fds_xml_args args_tls[] = {
53+
FDS_OPTS_ELEM(PARAM_TLS_CERTIFICATE, "certificateFile", FDS_OPTS_T_STRING, 0),
54+
FDS_OPTS_ELEM(PARAM_TLS_PRIVATE_KEY, "privateKeyFile" , FDS_OPTS_T_STRING, FDS_OPTS_P_OPT),
55+
FDS_OPTS_ELEM(PARAM_TLS_VERIFY_PEER, "verifyPeer" , FDS_OPTS_T_BOOL , FDS_OPTS_P_OPT),
56+
FDS_OPTS_ELEM(PARAM_TLS_CA_FILE , "caFile" , FDS_OPTS_T_STRING, FDS_OPTS_P_OPT),
57+
FDS_OPTS_ELEM(PARAM_TLS_CA_DIR , "caDir" , FDS_OPTS_T_STRING, FDS_OPTS_P_OPT),
58+
FDS_OPTS_ELEM(PARAM_TLS_CA_STORE , "caStore" , FDS_OPTS_T_STRING, FDS_OPTS_P_OPT),
59+
FDS_OPTS_ELEM(PARAM_TLS_INSECURE , "allowInsecure" , FDS_OPTS_T_BOOL , FDS_OPTS_P_OPT),
60+
FDS_OPTS_END,
3961
};
4062

4163
static const struct fds_xml_args args_params[] = {
4264
FDS_OPTS_ROOT("params"),
4365
FDS_OPTS_ELEM(PARAM_PORT , "localPort" , FDS_OPTS_T_UINT , FDS_OPTS_P_OPT),
4466
FDS_OPTS_ELEM(PARAM_IPADDR, "localIPAddress", FDS_OPTS_T_STRING, FDS_OPTS_P_OPT
4567
| FDS_OPTS_P_MULTI),
68+
FDS_OPTS_NESTED(PARAM_TLS , "tls" , args_tls , FDS_OPTS_P_OPT),
4669
FDS_OPTS_END,
4770
};
4871

@@ -85,13 +108,17 @@ void Config::parse_params(ipx_ctx *ctx, fds_xml_ctx_t *params) {
85108
break;
86109
case PARAM_IPADDR:
87110
assert(content->type == FDS_OPTS_T_STRING);
88-
// check if the string is not empty
89-
if (*content->ptr_string) {
90-
local_addrs.push_back(IpAddress(content->ptr_string));
91-
} else {
111+
// check if the string is empty
112+
if (std::strcmp(content->ptr_string, "") == 0) {
92113
empty_address = true;
114+
} else {
115+
local_addrs.push_back(IpAddress(content->ptr_string));
93116
}
94117
break;
118+
case PARAM_TLS:
119+
assert(content->type == FDS_OPTS_T_CONTEXT);
120+
parse_tls(ctx, content->ptr_ctx);
121+
break;
95122
default:
96123
throw std::invalid_argument("Unexpected element within <params>.");
97124
}
@@ -100,11 +127,79 @@ void Config::parse_params(ipx_ctx *ctx, fds_xml_ctx_t *params) {
100127
if (empty_address && local_addrs.size() != 0) {
101128
IPX_CTX_WARNING(
102129
ctx,
103-
"Empty address in configuration ignored. Tcp plugin will NOT "
130+
"Empty address in configuration ignored. TCP plugin will NOT "
104131
"listen on all interfaces but only on the specified addresses."
105132
);
106133
}
107134
}
108135

136+
void Config::parse_tls(ipx_ctx *ctx, fds_xml_ctx_t *params) {
137+
const struct fds_xml_cont *content;
138+
bool empty_private_key;
139+
140+
// The default when TCP is enabled.
141+
allow_insecure = false;
142+
143+
while (fds_xml_next(params, &content) != FDS_EOC) {
144+
switch (content->id) {
145+
case PARAM_TLS_CERTIFICATE:
146+
assert(content->type == FDS_OPTS_T_STRING);
147+
// check if the string is empty
148+
if (std::strcmp(content->ptr_string, "") == 0) {
149+
throw std::invalid_argument("TLS certificate path must not be empty.");
150+
} else {
151+
certificate_file = content->ptr_string;
152+
}
153+
break;
154+
case PARAM_TLS_PRIVATE_KEY:
155+
assert(content->type == FDS_OPTS_T_STRING);
156+
empty_private_key = std::strcmp(content->ptr_string, "") == 0;
157+
private_key_file = content->ptr_string;
158+
break;
159+
case PARAM_TLS_VERIFY_PEER:
160+
assert(content->type == FDS_OPTS_T_BOOL);
161+
verify_peer = content->val_bool;
162+
break;
163+
case PARAM_TLS_CA_FILE:
164+
assert(content->type == FDS_OPTS_T_STRING);
165+
default_ca_file = std::strcmp(content->ptr_string, "") == 0;
166+
ca_file = content->ptr_string;
167+
break;
168+
case PARAM_TLS_CA_DIR:
169+
assert(content->type == FDS_OPTS_T_STRING);
170+
default_ca_dir = std::strcmp(content->ptr_string, "") == 0;
171+
ca_dir = content->ptr_string;
172+
break;
173+
case PARAM_TLS_CA_STORE:
174+
assert(content->type == FDS_OPTS_T_STRING);
175+
default_ca_store = std::strcmp(content->ptr_string, "") == 0;
176+
ca_store = content->ptr_string;
177+
break;
178+
case PARAM_TLS_INSECURE:
179+
assert(content->type == FDS_OPTS_T_BOOL);
180+
allow_insecure = content->val_bool;
181+
break;
182+
default:
183+
throw std::invalid_argument("Unexpected element within <params>.");
184+
}
185+
}
186+
187+
if (empty_private_key) {
188+
IPX_CTX_WARNING(
189+
ctx,
190+
"Empty private key ignored. Ipfixcol will use the same file as "
191+
"certificate."
192+
);
193+
}
194+
195+
if (private_key_file.empty()) {
196+
private_key_file = certificate_file;
197+
}
198+
199+
use_default_ca = !default_ca_file && ca_file.empty()
200+
&& !default_ca_dir && ca_dir.empty()
201+
&& !default_ca_store && ca_store.empty();
202+
}
203+
109204
} // namespace tcp_in
110205

src/plugins/input/tcp/src/Config.hpp

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,9 @@
1010

1111
#pragma once
1212

13-
#include <vector> // std::vector
1413
#include <cstdint> // uint16_t
14+
#include <string>
15+
#include <vector> // std::vector
1516

1617
#include <libfds.h> // fds_xml_ctx_t
1718

@@ -25,6 +26,31 @@ namespace tcp_in {
2526
struct Config {
2627
uint16_t local_port;
2728
std::vector<IpAddress> local_addrs;
29+
/**
30+
* @brief Path to file in pem format which contains certificate and private key for TLS. If
31+
* empty, TLS connections are not accepted.
32+
*/
33+
std::string certificate_file;
34+
/** Path to private key. */
35+
std::string private_key_file;
36+
/** If true, ipfixcol server will require certificate verification of clients */
37+
bool verify_peer = false;
38+
/** Path to certificate authority. */
39+
std::string ca_file;
40+
/** If true, load default ca file. */
41+
bool default_ca_file = false;
42+
/** Path to certificate authority directory. */
43+
std::string ca_dir;
44+
/** If true, load default ca directory. */
45+
bool default_ca_dir = false;
46+
/** Path to certificate authority store. */
47+
std::string ca_store;
48+
/** If true, load default ca store. */
49+
bool default_ca_store;
50+
/** If set, ignore any other ca configuration paths and use system defaults. */
51+
bool use_default_ca = true;
52+
/** If set to false, only TCP connections are accepted. */
53+
bool allow_insecure = true;
2854

2955
/**
3056
* @brief Parse configuration of the TCP plugin
@@ -36,6 +62,7 @@ struct Config {
3662

3763
private:
3864
void parse_params(ipx_ctx *ctx, fds_xml_ctx_t *params);
65+
void parse_tls(ipx_ctx *ctx, fds_xml_ctx_t *params);
3966
};
4067

4168
} // namespace tcp_in

0 commit comments

Comments
 (0)