Annotation of embedaddon/strongswan/src/pt-tls-client/pt-tls-client.c, revision 1.1.1.1
1.1 misho 1: /*
2: * Copyright (C) 2013-2015 Andreas Steffen
3: * HSR Hochschule fuer Technik Rapperswil
4: *
5: * Copyright (C) 2010-2013 Martin Willi
6: * Copyright (C) 2010-2013 revosec AG
7: *
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>.
12: *
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
16: * for more details.
17: */
18:
19: #include <unistd.h>
20: #include <stdio.h>
21: #include <sys/types.h>
22: #include <getopt.h>
23: #include <errno.h>
24: #include <string.h>
25: #include <stdlib.h>
26: #ifdef HAVE_SYSLOG
27: #include <syslog.h>
28: #endif
29:
30: #include <pt_tls.h>
31: #include <pt_tls_client.h>
32: #include <tnc/tnc.h>
33: #include <tls.h>
34:
35: #include <library.h>
36: #include <utils/debug.h>
37: #include <credentials/sets/mem_cred.h>
38: #include <utils/optionsfrom.h>
39:
40: /**
41: * Print usage information
42: */
43: static void usage(FILE *out)
44: {
45: fprintf(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");
51: }
52:
53: /**
54: * Client routine
55: */
56: static int client(char *address, uint16_t port, char *identity)
57: {
58: pt_tls_client_t *assessment;
59: tls_t *tnccs;
60: identification_t *server_id, *client_id;
61: host_t *server_ip, *client_ip;
62: status_t status;
63:
64: server_ip = host_create_from_dns(address, AF_UNSPEC, port);
65: if (!server_ip)
66: {
67: return 1;
68: }
69:
70: client_ip = host_create_any(server_ip->get_family(server_ip));
71: if (!client_ip)
72: {
73: server_ip->destroy(server_ip);
74: return 1;
75: }
76: server_id = identification_create_from_string(address);
77: client_id = identification_create_from_string(identity);
78:
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);
83:
84: if (!tnccs)
85: {
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);
90: return 1;
91: }
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);
96:
97: return (status != SUCCESS);
98: }
99:
100:
101: /**
102: * In-Memory credential set
103: */
104: static mem_cred_t *creds;
105:
106: /**
107: * Load certificate from file
108: */
109: static bool load_certificate(char *certid, char *filename)
110: {
111: certificate_t *cert;
112: chunk_t chunk;
113:
114: if (certid)
115: {
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);
119: }
120: else
121: {
122: cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
123: BUILD_FROM_FILE, filename, BUILD_END);
124: }
125: if (!cert)
126: {
127: DBG1(DBG_TLS, "loading certificate from '%s' failed",
128: certid ? certid : filename);
129: return FALSE;
130: }
131: creds->add_cert(creds, TRUE, cert);
132: return TRUE;
133: }
134:
135: /**
136: * Load private key from file
137: */
138: static bool load_key(char *keyid, char *filename, key_type_t type)
139: {
140: private_key_t *key;
141: chunk_t chunk;
142:
143: if (keyid)
144: {
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);
148: chunk_free(&chunk);
149: }
150: else
151: {
152: key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, type,
153: BUILD_FROM_FILE, filename, BUILD_END);
154: }
155: if (!key)
156: {
157: DBG1(DBG_TLS, "loading key from '%s' failed", keyid ? keyid : filename);
158: return FALSE;
159: }
160: creds->add_key(creds, key);
161: return TRUE;
162: }
163:
164: /**
165: * Logging and debug level
166: */
167: static bool log_to_stderr = TRUE;
168: #ifdef HAVE_SYSLOG
169: static bool log_to_syslog = TRUE;
170: #endif /* HAVE_SYSLOG */
171: static level_t default_loglevel = 1;
172:
173: static void dbg_pt_tls(debug_t group, level_t level, char *fmt, ...)
174: {
175: va_list args;
176:
177: if (level <= default_loglevel)
178: {
179: if (log_to_stderr)
180: {
181: va_start(args, fmt);
182: vfprintf(stderr, fmt, args);
183: va_end(args);
184: fprintf(stderr, "\n");
185: }
186: #ifdef HAVE_SYSLOG
187: if (log_to_syslog)
188: {
189: char buffer[8192];
190: char *current = buffer, *next;
191:
192: /* write in memory buffer first */
193: va_start(args, fmt);
194: vsnprintf(buffer, sizeof(buffer), fmt, args);
195: va_end(args);
196:
197: /* do a syslog with every line */
198: while (current)
199: {
200: next = strchr(current, '\n');
201: if (next)
202: {
203: *(next++) = '\0';
204: }
205: syslog(LOG_INFO, "%s\n", current);
206: current = next;
207: }
208: }
209: #endif /* HAVE_SYSLOG */
210: }
211: }
212:
213: /**
214: * Initialize logging to stderr/syslog
215: */
216: static void init_log(const char *program)
217: {
218: dbg = dbg_pt_tls;
219:
220: if (log_to_stderr)
221: {
222: setbuf(stderr, NULL);
223: }
224: #ifdef HAVE_SYSLOG
225: if (log_to_syslog)
226: {
227: openlog(program, LOG_CONS | LOG_NDELAY | LOG_PID, LOG_AUTHPRIV);
228: }
229: #endif /* HAVE_SYSLOG */
230: }
231:
232: /**
233: * Handles --optionsfrom arguments
234: */
235: options_t *options;
236:
237: /**
238: * Cleanup
239: */
240: static void cleanup()
241: {
242: lib->processor->cancel(lib->processor);
243: lib->credmgr->remove_set(lib->credmgr, &creds->set);
244: creds->destroy(creds);
245: options->destroy(options);
246: libtnccs_deinit();
247: library_deinit();
248: }
249:
250: /**
251: * Initialize library
252: */
253: static void init()
254: {
255: plugin_feature_t features[] = {
256: PLUGIN_NOOP,
257: PLUGIN_PROVIDE(CUSTOM, "pt-tls-client"),
258: PLUGIN_DEPENDS(CUSTOM, "tnccs-manager"),
259: };
260: library_init(NULL, "pt-tls-client");
261: libtnccs_init();
262:
263: init_log("pt-tls-client");
264: options = options_create();
265:
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)))
270: {
271: exit(SS_RC_INITIALIZATION_FAILED);
272: }
273: lib->plugins->status(lib->plugins, LEVEL_CTRL);
274:
275: creds = mem_cred_create();
276: lib->credmgr->add_set(lib->credmgr, &creds->set);
277:
278: atexit(cleanup);
279: }
280:
281: int main(int argc, char *argv[])
282: {
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;
287:
288: init();
289:
290: while (TRUE)
291: {
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, '+' },
308: {0,0,0,0 }
309: };
310: switch (getopt_long(argc, argv, "hc:i:s:p:x:K:k:t:mqd:+:", long_opts,
311: NULL))
312: {
313: case EOF:
314: break;
315: case 'h': /* --help */
316: usage(stdout);
317: return 0;
318: case 'X': /* --certid <hex> */
319: if (!load_certificate(optarg, NULL))
320: {
321: return 1;
322: }
323: continue;
324: case 'x': /* --cert <file> */
325: if (!load_certificate(NULL, optarg))
326: {
327: return 1;
328: }
329: continue;
330: case 'K': /* --keyid <hex> */
331: keyid = optarg;
332: continue;
333: case 'k': /* --key <file> */
334: key_file = optarg;
335: continue;
336: case 't': /* --key-type <type> */
337: if (strcaseeq(optarg, "ecdsa"))
338: {
339: key_type = KEY_ECDSA;
340: }
341: else if (strcaseeq(optarg, "rsa"))
342: {
343: key_type = KEY_RSA;
344: }
345: else
346: {
347: key_type = KEY_ANY;
348: }
349: continue;
350: case 'c': /* --connect <hostname|address> */
351: if (address)
352: {
353: usage(stderr);
354: return 1;
355: }
356: address = optarg;
357: continue;
358: case 'i': /* --client <client-id> */
359: identity = optarg;
360: continue;
361: case 's': /* --secret <password> */
362: secret = optarg;
363: continue;
364: case 'p': /* --port <port> */
365: port = atoi(optarg);
366: continue;
367: case 'm': /* --mutual */
368: lib->settings->set_bool(lib->settings,
369: "%s.plugins.tnccs-20.mutual", TRUE, lib->ns);
370: continue;
371: case 'q': /* --quiet */
372: log_to_stderr = FALSE;
373: continue;
374: case 'd': /* --debug <level> */
375: default_loglevel = atoi(optarg);
376: continue;
377: case '+': /* --optionsfrom <filename> */
378: if (!options->from(options, optarg, &argc, &argv, optind))
379: {
380: return 1;
381: }
382: continue;
383: default:
384: usage(stderr);
385: return 1;
386: }
387: break;
388: }
389: if (!address)
390: {
391: usage(stderr);
392: return 1;
393: }
394: if ((keyid || key_file) && !load_key(keyid, key_file, key_type))
395: {
396: return 1;
397: }
398: if (secret)
399: {
400: creds->add_shared(creds, shared_key_create(SHARED_EAP,
401: chunk_clone(chunk_from_str(secret))),
402: identification_create_from_string(identity), NULL);
403: }
404: return client(address, port, identity);
405: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>