File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / strongswan / src / pt-tls-client / pt-tls-client.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Jun 3 09:46:44 2020 UTC (4 years, 4 months ago) by misho
Branches: strongswan, MAIN
CVS tags: v5_9_2p0, v5_8_4p7, HEAD
Strongswan

    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>