2 * Copyright (C) 2013-2015 Andreas Steffen
3 * HSR Hochschule fuer Technik Rapperswil
5 * Copyright (C) 2010-2013 Martin Willi
6 * Copyright (C) 2010-2013 revosec AG
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 #include <sys/types.h>
31 #include <pt_tls_client.h>
36 #include <utils/debug.h>
37 #include <credentials/sets/mem_cred.h>
38 #include <utils/optionsfrom.h>
41 * Print usage information
43 static void usage(FILE *out
)
46 "Usage: pt-tls --connect <hostname|address> [--port <port>]\n"
47 " [--certid <hex>|--cert <file>]+ [--keyid <hex>|--key <file>]\n"
48 " [--key-type rsa|ecdsa] [--client <client-id>]\n"
49 " [--secret <password>] [--mutual] [--quiet]\n"
50 " [--debug <level>] [--options <filename>]\n");
56 static int client(char *address
, uint16_t port
, char *identity
)
58 pt_tls_client_t
*assessment
;
60 identification_t
*server_id
, *client_id
;
61 host_t
*server_ip
, *client_ip
;
64 server_ip
= host_create_from_dns(address
, AF_UNSPEC
, port
);
70 client_ip
= host_create_any(server_ip
->get_family(server_ip
));
73 server_ip
->destroy(server_ip
);
76 server_id
= identification_create_from_string(address
);
77 client_id
= identification_create_from_string(identity
);
79 tnccs
= (tls_t
*)tnc
->tnccs
->create_instance(tnc
->tnccs
, TNCCS_2_0
, FALSE
,
80 server_id
, client_id
, server_ip
, client_ip
,
81 TNC_IFT_TLS_2_0
, NULL
);
82 client_ip
->destroy(client_ip
);
86 fprintf(stderr
, "loading TNCCS failed: %s\n", PLUGINS
);
87 server_ip
->destroy(server_ip
);
88 server_id
->destroy(server_id
);
89 client_id
->destroy(client_id
);
92 assessment
= pt_tls_client_create(server_ip
, server_id
, client_id
);
93 status
= assessment
->run_assessment(assessment
, (tnccs_t
*)tnccs
);
94 assessment
->destroy(assessment
);
95 tnccs
->destroy(tnccs
);
97 return (status
!= SUCCESS
);
102 * In-Memory credential set
104 static mem_cred_t
*creds
;
107 * Load certificate from file
109 static bool load_certificate(char *certid
, char *filename
)
116 chunk
= chunk_from_hex(chunk_create(certid
, strlen(certid
)), NULL
);
117 cert
= lib
->creds
->create(lib
->creds
, CRED_CERTIFICATE
, CERT_X509
,
118 BUILD_PKCS11_KEYID
, chunk
, BUILD_END
);
122 cert
= lib
->creds
->create(lib
->creds
, CRED_CERTIFICATE
, CERT_X509
,
123 BUILD_FROM_FILE
, filename
, BUILD_END
);
127 DBG1(DBG_TLS
, "loading certificate from '%s' failed",
128 certid ? certid
: filename
);
131 creds
->add_cert(creds
, TRUE
, cert
);
136 * Load private key from file
138 static bool load_key(char *keyid
, char *filename
, key_type_t type
)
145 chunk
= chunk_from_hex(chunk_create(keyid
, strlen(keyid
)), NULL
);
146 key
= lib
->creds
->create(lib
->creds
, CRED_PRIVATE_KEY
, KEY_ANY
,
147 BUILD_PKCS11_KEYID
, chunk
, BUILD_END
);
152 key
= lib
->creds
->create(lib
->creds
, CRED_PRIVATE_KEY
, type
,
153 BUILD_FROM_FILE
, filename
, BUILD_END
);
157 DBG1(DBG_TLS
, "loading key from '%s' failed", keyid ? keyid
: filename
);
160 creds
->add_key(creds
, key
);
165 * Logging and debug level
167 static bool log_to_stderr
= TRUE
;
169 static bool log_to_syslog
= TRUE
;
170 #endif /* HAVE_SYSLOG */
171 static level_t default_loglevel
= 1;
173 static void dbg_pt_tls(debug_t group
, level_t level
, char *fmt
, ...)
177 if (level
<= default_loglevel
)
182 vfprintf(stderr
, fmt
, args
);
184 fprintf(stderr
, "\n");
190 char *current
= buffer
, *next
;
192 /* write in memory buffer first */
194 vsnprintf(buffer
, sizeof(buffer
), fmt
, args
);
197 /* do a syslog with every line */
200 next
= strchr(current
, '\n');
205 syslog(LOG_INFO
, "%s\n", current
);
209 #endif /* HAVE_SYSLOG */
214 * Initialize logging to stderr/syslog
216 static void init_log(const char *program
)
222 setbuf(stderr
, NULL
);
227 openlog(program
, LOG_CONS
| LOG_NDELAY
| LOG_PID
, LOG_AUTHPRIV
);
229 #endif /* HAVE_SYSLOG */
233 * Handles --optionsfrom arguments
240 static void cleanup()
242 lib
->processor
->cancel(lib
->processor
);
243 lib
->credmgr
->remove_set(lib
->credmgr
, &creds
->set
);
244 creds
->destroy(creds
);
245 options
->destroy(options
);
255 plugin_feature_t features
[] = {
257 PLUGIN_PROVIDE(CUSTOM
, "pt-tls-client"),
258 PLUGIN_DEPENDS(CUSTOM
, "tnccs-manager"),
260 library_init(NULL
, "pt-tls-client");
263 init_log("pt-tls-client");
264 options
= options_create();
266 lib
->plugins
->add_static_features(lib
->plugins
, "pt-tls-client", features
,
267 countof(features
), TRUE
, NULL
, NULL
);
268 if (!lib
->plugins
->load(lib
->plugins
,
269 lib
->settings
->get_str(lib
->settings
, "pt-tls-client.load", PLUGINS
)))
271 exit(SS_RC_INITIALIZATION_FAILED
);
273 lib
->plugins
->status(lib
->plugins
, LEVEL_CTRL
);
275 creds
= mem_cred_create();
276 lib
->credmgr
->add_set(lib
->credmgr
, &creds
->set
);
281 int main(int argc
, char *argv
[])
283 char *address
= NULL
, *identity
= "%any", *secret
= NULL
;
284 char *keyid
= NULL
, *key_file
= NULL
;
285 key_type_t key_type
= KEY_RSA
;
286 int port
= PT_TLS_PORT
;
292 struct option long_opts
[] = {
293 {"help", no_argument
, NULL
, 'h' },
294 {"connect", required_argument
, NULL
, 'c' },
295 {"client", required_argument
, NULL
, 'i' },
296 {"secret", required_argument
, NULL
, 's' },
297 {"port", required_argument
, NULL
, 'p' },
298 {"certid", required_argument
, NULL
, 'X' },
299 {"cert", required_argument
, NULL
, 'x' },
300 {"keyid", required_argument
, NULL
, 'K' },
301 {"key", required_argument
, NULL
, 'k' },
302 {"key-type", required_argument
, NULL
, 't' },
303 {"mutual", no_argument
, NULL
, 'm' },
304 {"quiet", no_argument
, NULL
, 'q' },
305 {"debug", required_argument
, NULL
, 'd' },
306 {"options", required_argument
, NULL
, '+' },
307 {"optionsfrom", required_argument
, NULL
, '+' },
310 switch (getopt_long(argc
, argv
, "hc:i:s:p:x:K:k:t:mqd:+:", long_opts
,
315 case 'h': /* --help */
318 case 'X': /* --certid <hex> */
319 if (!load_certificate(optarg
, NULL
))
324 case 'x': /* --cert <file> */
325 if (!load_certificate(NULL
, optarg
))
330 case 'K': /* --keyid <hex> */
333 case 'k': /* --key <file> */
336 case 't': /* --key-type <type> */
337 if (strcaseeq(optarg
, "ecdsa"))
339 key_type
= KEY_ECDSA
;
341 else if (strcaseeq(optarg
, "rsa"))
350 case 'c': /* --connect <hostname|address> */
358 case 'i': /* --client <client-id> */
361 case 's': /* --secret <password> */
364 case 'p': /* --port <port> */
367 case 'm': /* --mutual */
368 lib
->settings
->set_bool(lib
->settings
,
369 "%s.plugins.tnccs-20.mutual", TRUE
, lib
->ns
);
371 case 'q': /* --quiet */
372 log_to_stderr
= FALSE
;
374 case 'd': /* --debug <level> */
375 default_loglevel
= atoi(optarg
);
377 case '+': /* --optionsfrom <filename> */
378 if (!options
->from(options
, optarg
, &argc
, &argv
, optind
))
394 if ((keyid
|| key_file
) && !load_key(keyid
, key_file
, key_type
))
400 creds
->add_shared(creds
, shared_key_create(SHARED_EAP
,
401 chunk_clone(chunk_from_str(secret
))),
402 identification_create_from_string(identity
), NULL
);
404 return client(address
, port
, identity
);