65
65
#include <errno.h> /* perror() */
69
69
#include <getopt.h>
71
71
#define BUFFER_SIZE 256
74
static const char *certdir = "/conf/conf.d/mandos";
75
static const char *certfile = "openpgp-client.txt";
76
static const char *certkey = "openpgp-client-key.txt";
73
static const char *keydir = "/conf/conf.d/mandos";
74
static const char *pubkeyfile = "pubkey.txt";
75
static const char *seckeyfile = "seckey.txt";
78
77
bool debug = false;
79
/* Used for passing in values through all the callback functions */
81
gnutls_session_t session;
81
AvahiSimplePoll *simple_poll;
82
83
gnutls_certificate_credentials_t cred;
83
gnutls_dh_params_t dh_params;
87
88
static ssize_t pgp_packet_decrypt (char *packet, size_t packet_size,
266
268
fprintf (stderr, "global_init: %s\n", safer_gnutls_strerror(ret));
271
273
gnutls_global_set_log_level(11);
272
274
gnutls_global_set_log_function(debuggnutls);
275
277
/* openpgp credentials */
276
if ((ret = gnutls_certificate_allocate_credentials (&es->cred))
278
if ((ret = gnutls_certificate_allocate_credentials (&mc->cred))
277
279
!= GNUTLS_E_SUCCESS) {
278
280
fprintf (stderr, "memory error: %s\n",
279
281
safer_gnutls_strerror(ret));
284
286
fprintf(stderr, "Attempting to use OpenPGP certificate %s"
285
" and keyfile %s as GnuTLS credentials\n", certfile,
287
" and keyfile %s as GnuTLS credentials\n", pubkeyfile,
289
291
ret = gnutls_certificate_set_openpgp_key_file
290
(es->cred, certfile, certkey, GNUTLS_OPENPGP_FMT_BASE64);
292
(mc->cred, pubkeyfile, seckeyfile, GNUTLS_OPENPGP_FMT_BASE64);
291
293
if (ret != GNUTLS_E_SUCCESS) {
293
295
(stderr, "Error[%d] while reading the OpenPGP key pair ('%s',"
295
ret, certfile, certkey);
297
ret, pubkeyfile, seckeyfile);
296
298
fprintf(stdout, "The Error is: %s\n",
297
299
safer_gnutls_strerror(ret));
301
303
//GnuTLS server initialization
302
if ((ret = gnutls_dh_params_init (&es->dh_params))
304
if ((ret = gnutls_dh_params_init(dh_params))
303
305
!= GNUTLS_E_SUCCESS) {
304
306
fprintf (stderr, "Error in dh parameter initialization: %s\n",
305
307
safer_gnutls_strerror(ret));
309
if ((ret = gnutls_dh_params_generate2 (es->dh_params, DH_BITS))
311
if ((ret = gnutls_dh_params_generate2(*dh_params, mc->dh_bits))
310
312
!= GNUTLS_E_SUCCESS) {
311
313
fprintf (stderr, "Error in prime generation: %s\n",
312
314
safer_gnutls_strerror(ret));
316
gnutls_certificate_set_dh_params (es->cred, es->dh_params);
318
gnutls_certificate_set_dh_params(mc->cred, *dh_params);
318
320
// GnuTLS session creation
319
if ((ret = gnutls_init (&es->session, GNUTLS_SERVER))
321
if ((ret = gnutls_init(session, GNUTLS_SERVER))
320
322
!= GNUTLS_E_SUCCESS){
321
323
fprintf(stderr, "Error in GnuTLS session initialization: %s\n",
322
324
safer_gnutls_strerror(ret));
325
if ((ret = gnutls_priority_set_direct (es->session, "NORMAL", &err))
327
if ((ret = gnutls_priority_set_direct(*session, mc->priority, &err))
326
328
!= GNUTLS_E_SUCCESS) {
327
329
fprintf(stderr, "Syntax error at: %s\n", err);
328
330
fprintf(stderr, "GnuTLS error: %s\n",
333
if ((ret = gnutls_credentials_set
334
(es->session, GNUTLS_CRD_CERTIFICATE, es->cred))
335
if ((ret = gnutls_credentials_set(*session, GNUTLS_CRD_CERTIFICATE,
335
337
!= GNUTLS_E_SUCCESS) {
336
338
fprintf(stderr, "Error setting a credentials set: %s\n",
337
339
safer_gnutls_strerror(ret));
341
343
/* ignore client certificate if any. */
342
gnutls_certificate_server_set_request (es->session,
344
gnutls_certificate_server_set_request (*session,
343
345
GNUTLS_CERT_IGNORE);
345
gnutls_dh_set_prime_bits (es->session, DH_BITS);
347
gnutls_dh_set_prime_bits (*session, mc->dh_bits);
405
406
fprintf(stderr, "Connection to: %s, port %d\n", ip, port);
406
/* char addrstr[INET6_ADDRSTRLEN]; */
407
/* if(inet_ntop(to.sin6_family, &(to.sin6_addr), addrstr, */
408
/* sizeof(addrstr)) == NULL){ */
409
/* perror("inet_ntop"); */
411
/* fprintf(stderr, "Really connecting to: %s, port %d\n", */
412
/* addrstr, ntohs(to.sin6_port)); */
407
char addrstr[INET6_ADDRSTRLEN] = "";
408
if(inet_ntop(to.sin6_family, &(to.sin6_addr), addrstr,
409
sizeof(addrstr)) == NULL){
412
if(strcmp(addrstr, ip) != 0){
413
fprintf(stderr, "Canonical address form: %s\n", addrstr);
416
418
ret = connect(tcp_sd, (struct sockaddr *) &to, sizeof(to));
422
ret = initgnutls (&es);
424
ret = initgnutls (mc, &session, &dh_params);
428
gnutls_transport_set_ptr (es.session,
429
(gnutls_transport_ptr_t) tcp_sd);
430
gnutls_transport_set_ptr (session, (gnutls_transport_ptr_t) tcp_sd);
432
433
fprintf(stderr, "Establishing TLS session with %s\n", ip);
435
ret = gnutls_handshake (es.session);
436
ret = gnutls_handshake (session);
437
438
if (ret != GNUTLS_E_SUCCESS){
527
gnutls_bye (es.session, GNUTLS_SHUT_RDWR);
528
gnutls_bye (session, GNUTLS_SHUT_RDWR);
530
gnutls_deinit (es.session);
531
gnutls_certificate_free_credentials (es.cred);
531
gnutls_deinit (session);
532
gnutls_certificate_free_credentials (mc->cred);
532
533
gnutls_global_deinit ();
536
static AvahiSimplePoll *simple_poll = NULL;
537
static AvahiServer *server = NULL;
539
static void resolve_callback(
540
AvahiSServiceResolver *r,
541
AvahiIfIndex interface,
542
AVAHI_GCC_UNUSED AvahiProtocol protocol,
543
AvahiResolverEvent event,
547
const char *host_name,
548
const AvahiAddress *address,
550
AVAHI_GCC_UNUSED AvahiStringList *txt,
551
AVAHI_GCC_UNUSED AvahiLookupResultFlags flags,
552
AVAHI_GCC_UNUSED void* userdata) {
537
static void resolve_callback( AvahiSServiceResolver *r,
538
AvahiIfIndex interface,
539
AVAHI_GCC_UNUSED AvahiProtocol protocol,
540
AvahiResolverEvent event,
544
const char *host_name,
545
const AvahiAddress *address,
547
AVAHI_GCC_UNUSED AvahiStringList *txt,
548
AVAHI_GCC_UNUSED AvahiLookupResultFlags flags,
550
mandos_context *mc = userdata;
554
551
assert(r); /* Spurious warning */
556
553
/* Called whenever a service has been resolved successfully or
561
558
case AVAHI_RESOLVER_FAILURE:
562
559
fprintf(stderr, "(Resolver) Failed to resolve service '%s' of"
563
560
" type '%s' in domain '%s': %s\n", name, type, domain,
564
avahi_strerror(avahi_server_errno(server)));
561
avahi_strerror(avahi_server_errno(mc->server)));
567
564
case AVAHI_RESOLVER_FOUND:
572
569
fprintf(stderr, "Mandos server \"%s\" found on %s (%s) on"
573
570
" port %d\n", name, host_name, ip, port);
575
int ret = start_mandos_communication(ip, port, interface);
572
int ret = start_mandos_communication(ip, port, interface, mc);
577
574
exit(EXIT_SUCCESS);
581
578
avahi_s_service_resolver_free(r);
584
static void browse_callback(
585
AvahiSServiceBrowser *b,
586
AvahiIfIndex interface,
587
AvahiProtocol protocol,
588
AvahiBrowserEvent event,
592
AVAHI_GCC_UNUSED AvahiLookupResultFlags flags,
595
AvahiServer *s = userdata;
596
assert(b); /* Spurious warning */
598
/* Called whenever a new services becomes available on the LAN or
599
is removed from the LAN */
603
case AVAHI_BROWSER_FAILURE:
605
fprintf(stderr, "(Browser) %s\n",
606
avahi_strerror(avahi_server_errno(server)));
607
avahi_simple_poll_quit(simple_poll);
610
case AVAHI_BROWSER_NEW:
611
/* We ignore the returned resolver object. In the callback
612
function we free it. If the server is terminated before
613
the callback function is called the server will free
614
the resolver for us. */
616
if (!(avahi_s_service_resolver_new(s, interface, protocol, name,
618
AVAHI_PROTO_INET6, 0,
619
resolve_callback, s)))
620
fprintf(stderr, "Failed to resolve service '%s': %s\n", name,
621
avahi_strerror(avahi_server_errno(s)));
624
case AVAHI_BROWSER_REMOVE:
627
case AVAHI_BROWSER_ALL_FOR_NOW:
628
case AVAHI_BROWSER_CACHE_EXHAUSTED:
581
static void browse_callback( AvahiSServiceBrowser *b,
582
AvahiIfIndex interface,
583
AvahiProtocol protocol,
584
AvahiBrowserEvent event,
588
AVAHI_GCC_UNUSED AvahiLookupResultFlags flags,
590
mandos_context *mc = userdata;
591
assert(b); /* Spurious warning */
593
/* Called whenever a new services becomes available on the LAN or
594
is removed from the LAN */
598
case AVAHI_BROWSER_FAILURE:
600
fprintf(stderr, "(Browser) %s\n",
601
avahi_strerror(avahi_server_errno(mc->server)));
602
avahi_simple_poll_quit(mc->simple_poll);
605
case AVAHI_BROWSER_NEW:
606
/* We ignore the returned resolver object. In the callback
607
function we free it. If the server is terminated before
608
the callback function is called the server will free
609
the resolver for us. */
611
if (!(avahi_s_service_resolver_new(mc->server, interface, protocol, name,
613
AVAHI_PROTO_INET6, 0,
614
resolve_callback, mc)))
615
fprintf(stderr, "Failed to resolve service '%s': %s\n", name,
616
avahi_strerror(avahi_server_errno(mc->server)));
619
case AVAHI_BROWSER_REMOVE:
622
case AVAHI_BROWSER_ALL_FOR_NOW:
623
case AVAHI_BROWSER_CACHE_EXHAUSTED:
633
628
/* Combines file name and path and returns the malloced new
643
memcpy(tmp, first, f_len);
638
memcpy(tmp, first, f_len); /* Spurious warning */
645
640
tmp[f_len] = '/';
647
memcpy(tmp + f_len + 1, second, s_len);
642
memcpy(tmp + f_len + 1, second, s_len); /* Spurious warning */
649
644
tmp[f_len + 1 + s_len] = '\0';
656
651
AvahiSServiceBrowser *sb = NULL;
659
655
int returncode = EXIT_SUCCESS;
660
656
const char *interface = "eth0";
661
657
struct ifreq network;
663
659
char *connect_to = NULL;
664
660
AvahiIfIndex if_index = AVAHI_IF_UNSPEC;
661
mandos_context mc = { .simple_poll = NULL, .server = NULL,
662
.dh_bits = 1024, .priority = "SECURE256"};
664
debug_int = debug ? 1 : 0;
667
static struct option long_options[] = {
668
{"debug", no_argument, (int *)&debug, 1},
669
{"connect", required_argument, 0, 'C'},
670
{"interface", required_argument, 0, 'i'},
671
{"certdir", required_argument, 0, 'd'},
672
{"certkey", required_argument, 0, 'c'},
673
{"certfile", required_argument, 0, 'k'},
666
struct option long_options[] = {
667
{"debug", no_argument, &debug_int, 1},
668
{"connect", required_argument, NULL, 'c'},
669
{"interface", required_argument, NULL, 'i'},
670
{"keydir", required_argument, NULL, 'd'},
671
{"seckey", required_argument, NULL, 's'},
672
{"pubkey", required_argument, NULL, 'p'},
673
{"dh-bits", required_argument, NULL, 'D'},
674
{"priority", required_argument, NULL, 'P'},
676
677
int option_index = 0;
688
689
interface = optarg;
691
692
connect_to = optarg;
705
mc.dh_bits = (unsigned int) strtol(optarg, NULL, 10);
712
mc.priority = optarg;
703
716
exit(EXIT_FAILURE);
719
debug = debug_int ? true : false;
707
certfile = combinepath(certdir, certfile);
708
if (certfile == NULL){
721
pubkeyfile = combinepath(keydir, pubkeyfile);
722
if (pubkeyfile == NULL){
709
723
perror("combinepath");
710
724
returncode = EXIT_FAILURE;
714
certkey = combinepath(certdir, certkey);
715
if (certkey == NULL){
728
seckeyfile = combinepath(keydir, seckeyfile);
729
if (seckeyfile == NULL){
716
730
perror("combinepath");
717
returncode = EXIT_FAILURE;
781
794
srand((unsigned int) time(NULL));
783
796
/* Allocate main loop object */
784
if (!(simple_poll = avahi_simple_poll_new())) {
797
if (!(mc.simple_poll = avahi_simple_poll_new())) {
785
798
fprintf(stderr, "Failed to create simple poll object.\n");
786
returncode = EXIT_FAILURE;
799
returncode = EXIT_FAILURE;
795
808
config.publish_domain = 0;
797
810
/* Allocate a new server */
798
server = avahi_server_new(avahi_simple_poll_get(simple_poll),
799
&config, NULL, NULL, &error);
811
mc.server=avahi_server_new(avahi_simple_poll_get(mc.simple_poll),
812
&config, NULL, NULL, &error);
801
814
/* Free the configuration data */
802
815
avahi_server_config_free(&config);
804
817
/* Check if creating the server object succeeded */
806
819
fprintf(stderr, "Failed to create server: %s\n",
807
820
avahi_strerror(error));
808
821
returncode = EXIT_FAILURE;
812
825
/* Create the service browser */
813
sb = avahi_s_service_browser_new(server, if_index,
826
sb = avahi_s_service_browser_new(mc.server, if_index,
814
827
AVAHI_PROTO_INET6,
815
828
"_mandos._tcp", NULL, 0,
816
browse_callback, server);
829
browse_callback, &mc);
818
831
fprintf(stderr, "Failed to create service browser: %s\n",
819
avahi_strerror(avahi_server_errno(server)));
832
avahi_strerror(avahi_server_errno(mc.server)));
820
833
returncode = EXIT_FAILURE;