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
3638enum 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
4163static 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
0 commit comments