37
37
#include <stdlib.h>
39
39
#include <net/if.h> /* if_nametoindex */
40
#include <sys/ioctl.h> // ioctl, ifreq, SIOCGIFFLAGS, IFF_UP, SIOCSIFFLAGS
41
#include <net/if.h> // ioctl, ifreq, SIOCGIFFLAGS, IFF_UP, SIOCSIFFLAGS
41
43
#include <avahi-core/core.h>
42
44
#include <avahi-core/lookup.h>
69
71
#define BUFFER_SIZE 256
71
static int dh_bits = 1024;
73
73
static const char *keydir = "/conf/conf.d/mandos";
74
74
static const char *pubkeyfile = "pubkey.txt";
75
75
static const char *seckeyfile = "seckey.txt";
77
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));
289
291
ret = gnutls_certificate_set_openpgp_key_file
290
(es->cred, pubkeyfile, seckeyfile, 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',"
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);
424
ret = initgnutls (&es);
424
ret = initgnutls (mc, &session, &dh_params);
430
gnutls_transport_set_ptr (es.session,
431
(gnutls_transport_ptr_t) tcp_sd);
430
gnutls_transport_set_ptr (session, (gnutls_transport_ptr_t) tcp_sd);
434
433
fprintf(stderr, "Establishing TLS session with %s\n", ip);
437
ret = gnutls_handshake (es.session);
436
ret = gnutls_handshake (session);
439
438
if (ret != GNUTLS_E_SUCCESS){
529
gnutls_bye (es.session, GNUTLS_SHUT_RDWR);
528
gnutls_bye (session, GNUTLS_SHUT_RDWR);
532
gnutls_deinit (es.session);
533
gnutls_certificate_free_credentials (es.cred);
531
gnutls_deinit (session);
532
gnutls_certificate_free_credentials (mc->cred);
534
533
gnutls_global_deinit ();
538
static AvahiSimplePoll *simple_poll = NULL;
539
static AvahiServer *server = NULL;
541
static void resolve_callback(
542
AvahiSServiceResolver *r,
543
AvahiIfIndex interface,
544
AVAHI_GCC_UNUSED AvahiProtocol protocol,
545
AvahiResolverEvent event,
549
const char *host_name,
550
const AvahiAddress *address,
552
AVAHI_GCC_UNUSED AvahiStringList *txt,
553
AVAHI_GCC_UNUSED AvahiLookupResultFlags flags,
554
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;
556
551
assert(r); /* Spurious warning */
558
553
/* Called whenever a service has been resolved successfully or
563
558
case AVAHI_RESOLVER_FAILURE:
564
559
fprintf(stderr, "(Resolver) Failed to resolve service '%s' of"
565
560
" type '%s' in domain '%s': %s\n", name, type, domain,
566
avahi_strerror(avahi_server_errno(server)));
561
avahi_strerror(avahi_server_errno(mc->server)));
569
564
case AVAHI_RESOLVER_FOUND:
574
569
fprintf(stderr, "Mandos server \"%s\" found on %s (%s) on"
575
570
" port %d\n", name, host_name, ip, port);
577
int ret = start_mandos_communication(ip, port, interface);
572
int ret = start_mandos_communication(ip, port, interface, mc);
579
574
exit(EXIT_SUCCESS);
583
578
avahi_s_service_resolver_free(r);
586
static void browse_callback(
587
AvahiSServiceBrowser *b,
588
AvahiIfIndex interface,
589
AvahiProtocol protocol,
590
AvahiBrowserEvent event,
594
AVAHI_GCC_UNUSED AvahiLookupResultFlags flags,
597
AvahiServer *s = userdata;
598
assert(b); /* Spurious warning */
600
/* Called whenever a new services becomes available on the LAN or
601
is removed from the LAN */
605
case AVAHI_BROWSER_FAILURE:
607
fprintf(stderr, "(Browser) %s\n",
608
avahi_strerror(avahi_server_errno(server)));
609
avahi_simple_poll_quit(simple_poll);
612
case AVAHI_BROWSER_NEW:
613
/* We ignore the returned resolver object. In the callback
614
function we free it. If the server is terminated before
615
the callback function is called the server will free
616
the resolver for us. */
618
if (!(avahi_s_service_resolver_new(s, interface, protocol, name,
620
AVAHI_PROTO_INET6, 0,
621
resolve_callback, s)))
622
fprintf(stderr, "Failed to resolve service '%s': %s\n", name,
623
avahi_strerror(avahi_server_errno(s)));
626
case AVAHI_BROWSER_REMOVE:
629
case AVAHI_BROWSER_ALL_FOR_NOW:
630
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:
635
628
/* Combines file name and path and returns the malloced new
645
memcpy(tmp, first, f_len);
638
memcpy(tmp, first, f_len); /* Spurious warning */
647
640
tmp[f_len] = '/';
649
memcpy(tmp + f_len + 1, second, s_len);
642
memcpy(tmp + f_len + 1, second, s_len); /* Spurious warning */
651
644
tmp[f_len + 1 + s_len] = '\0';
658
651
AvahiSServiceBrowser *sb = NULL;
662
655
int returncode = EXIT_SUCCESS;
663
const char *interface = NULL;
656
const char *interface = "eth0";
657
struct ifreq network;
659
char *connect_to = NULL;
664
660
AvahiIfIndex if_index = AVAHI_IF_UNSPEC;
665
char *connect_to = NULL;
661
mandos_context mc = { .simple_poll = NULL, .server = NULL,
662
.dh_bits = 1024, .priority = "SECURE256"};
667
664
debug_int = debug ? 1 : 0;
669
static struct option long_options[] = {
666
struct option long_options[] = {
670
667
{"debug", no_argument, &debug_int, 1},
671
{"connect", required_argument, NULL, 'C'},
668
{"connect", required_argument, NULL, 'c'},
672
669
{"interface", required_argument, NULL, 'i'},
673
670
{"keydir", required_argument, NULL, 'd'},
674
{"seckey", required_argument, NULL, 'c'},
675
{"pubkey", required_argument, NULL, 'k'},
671
{"seckey", required_argument, NULL, 's'},
672
{"pubkey", required_argument, NULL, 'p'},
676
673
{"dh-bits", required_argument, NULL, 'D'},
674
{"priority", required_argument, NULL, 'P'},
679
677
int option_index = 0;
716
721
pubkeyfile = combinepath(keydir, pubkeyfile);
717
722
if (pubkeyfile == NULL){
718
723
perror("combinepath");
722
if(interface != NULL){
723
if_index = (AvahiIfIndex) if_nametoindex(interface);
725
fprintf(stderr, "No such interface: \"%s\"\n", interface);
724
returncode = EXIT_FAILURE;
728
seckeyfile = combinepath(keydir, seckeyfile);
729
if (seckeyfile == NULL){
730
perror("combinepath");
734
if_index = (AvahiIfIndex) if_nametoindex(interface);
736
fprintf(stderr, "No such interface: \"%s\"\n", interface);
730
740
if(connect_to != NULL){
754
seckeyfile = combinepath(keydir, seckeyfile);
755
if (seckeyfile == NULL){
756
perror("combinepath");
764
sd = socket(PF_INET6, SOCK_DGRAM, IPPROTO_IP);
767
returncode = EXIT_FAILURE;
770
strcpy(network.ifr_name, interface); /* Spurious warning */
771
ret = ioctl(sd, SIOCGIFFLAGS, &network);
774
perror("ioctl SIOCGIFFLAGS");
775
returncode = EXIT_FAILURE;
778
if((network.ifr_flags & IFF_UP) == 0){
779
network.ifr_flags |= IFF_UP;
780
ret = ioctl(sd, SIOCSIFFLAGS, &network);
782
perror("ioctl SIOCSIFFLAGS");
783
returncode = EXIT_FAILURE;
761
790
avahi_set_log_function(empty_log);
779
808
config.publish_domain = 0;
781
810
/* Allocate a new server */
782
server = avahi_server_new(avahi_simple_poll_get(simple_poll),
783
&config, NULL, NULL, &error);
811
mc.server=avahi_server_new(avahi_simple_poll_get(mc.simple_poll),
812
&config, NULL, NULL, &error);
785
814
/* Free the configuration data */
786
815
avahi_server_config_free(&config);
788
817
/* Check if creating the server object succeeded */
790
819
fprintf(stderr, "Failed to create server: %s\n",
791
820
avahi_strerror(error));
792
821
returncode = EXIT_FAILURE;
796
825
/* Create the service browser */
797
sb = avahi_s_service_browser_new(server, if_index,
826
sb = avahi_s_service_browser_new(mc.server, if_index,
798
827
AVAHI_PROTO_INET6,
799
828
"_mandos._tcp", NULL, 0,
800
browse_callback, server);
829
browse_callback, &mc);
802
831
fprintf(stderr, "Failed to create service browser: %s\n",
803
avahi_strerror(avahi_server_errno(server)));
832
avahi_strerror(avahi_server_errno(mc.server)));
804
833
returncode = EXIT_FAILURE;