65
64
#include <errno.h> /* perror() */
69
68
#include <getopt.h>
71
70
#define BUFFER_SIZE 256
73
static const char *keydir = "/conf/conf.d/mandos";
74
static const char *pubkeyfile = "pubkey.txt";
75
static const char *seckeyfile = "seckey.txt";
73
const char *certdir = "/conf/conf.d/cryptkeyreq/";
74
const char *certfile = "openpgp-client.txt";
75
const char *certkey = "openpgp-client-key.txt";
77
77
bool debug = false;
79
/* Used for passing in values through all the callback functions */
81
AvahiSimplePoll *simple_poll;
80
gnutls_session_t session;
83
81
gnutls_certificate_credentials_t cred;
88
static ssize_t pgp_packet_decrypt (char *packet, size_t packet_size,
82
gnutls_dh_params_t dh_params;
86
ssize_t pgp_packet_decrypt (char *packet, size_t packet_size,
87
char **new_packet, const char *homedir){
91
88
gpgme_data_t dh_crypto, dh_plain;
268
264
fprintf (stderr, "global_init: %s\n", safer_gnutls_strerror(ret));
273
269
gnutls_global_set_log_level(11);
274
270
gnutls_global_set_log_function(debuggnutls);
277
273
/* openpgp credentials */
278
if ((ret = gnutls_certificate_allocate_credentials (&mc->cred))
274
if ((ret = gnutls_certificate_allocate_credentials (&es->cred))
279
275
!= GNUTLS_E_SUCCESS) {
280
276
fprintf (stderr, "memory error: %s\n",
281
277
safer_gnutls_strerror(ret));
286
282
fprintf(stderr, "Attempting to use OpenPGP certificate %s"
287
" and keyfile %s as GnuTLS credentials\n", pubkeyfile,
283
" and keyfile %s as GnuTLS credentials\n", certfile,
291
287
ret = gnutls_certificate_set_openpgp_key_file
292
(mc->cred, pubkeyfile, seckeyfile, GNUTLS_OPENPGP_FMT_BASE64);
288
(es->cred, certfile, certkey, GNUTLS_OPENPGP_FMT_BASE64);
293
289
if (ret != GNUTLS_E_SUCCESS) {
295
291
(stderr, "Error[%d] while reading the OpenPGP key pair ('%s',"
297
ret, pubkeyfile, seckeyfile);
293
ret, certfile, certkey);
298
294
fprintf(stdout, "The Error is: %s\n",
299
295
safer_gnutls_strerror(ret));
303
299
//GnuTLS server initialization
304
if ((ret = gnutls_dh_params_init(dh_params))
300
if ((ret = gnutls_dh_params_init (&es->dh_params))
305
301
!= GNUTLS_E_SUCCESS) {
306
302
fprintf (stderr, "Error in dh parameter initialization: %s\n",
307
303
safer_gnutls_strerror(ret));
311
if ((ret = gnutls_dh_params_generate2(*dh_params, mc->dh_bits))
307
if ((ret = gnutls_dh_params_generate2 (es->dh_params, DH_BITS))
312
308
!= GNUTLS_E_SUCCESS) {
313
309
fprintf (stderr, "Error in prime generation: %s\n",
314
310
safer_gnutls_strerror(ret));
318
gnutls_certificate_set_dh_params(mc->cred, *dh_params);
314
gnutls_certificate_set_dh_params (es->cred, es->dh_params);
320
316
// GnuTLS session creation
321
if ((ret = gnutls_init(session, GNUTLS_SERVER))
317
if ((ret = gnutls_init (&es->session, GNUTLS_SERVER))
322
318
!= GNUTLS_E_SUCCESS){
323
319
fprintf(stderr, "Error in GnuTLS session initialization: %s\n",
324
320
safer_gnutls_strerror(ret));
327
if ((ret = gnutls_priority_set_direct(*session, mc->priority, &err))
323
if ((ret = gnutls_priority_set_direct (es->session, "NORMAL", &err))
328
324
!= GNUTLS_E_SUCCESS) {
329
325
fprintf(stderr, "Syntax error at: %s\n", err);
330
326
fprintf(stderr, "GnuTLS error: %s\n",
343
339
/* ignore client certificate if any. */
344
gnutls_certificate_server_set_request (*session,
340
gnutls_certificate_server_set_request (es->session,
345
341
GNUTLS_CERT_IGNORE);
347
gnutls_dh_set_prime_bits (*session, mc->dh_bits);
343
gnutls_dh_set_prime_bits (es->session, DH_BITS);
352
static void empty_log(__attribute__((unused)) AvahiLogLevel level,
353
__attribute__((unused)) const char *txt){}
348
void empty_log(__attribute__((unused)) AvahiLogLevel level,
349
__attribute__((unused)) const char *txt){}
355
static int start_mandos_communication(const char *ip, uint16_t port,
356
AvahiIfIndex if_index,
351
int start_mandos_communication(const char *ip, uint16_t port,
352
AvahiIfIndex if_index){
359
354
struct sockaddr_in6 to;
355
encrypted_session es;
360
356
char *buffer = NULL;
361
357
char *decrypted_buffer;
362
358
size_t buffer_length = 0;
406
403
fprintf(stderr, "Connection to: %s, port %d\n", ip, 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);
404
/* char addrstr[INET6_ADDRSTRLEN]; */
405
/* if(inet_ntop(to.sin6_family, &(to.sin6_addr), addrstr, */
406
/* sizeof(addrstr)) == NULL){ */
407
/* perror("inet_ntop"); */
409
/* fprintf(stderr, "Really connecting to: %s, port %d\n", */
410
/* addrstr, ntohs(to.sin6_port)); */
418
414
ret = connect(tcp_sd, (struct sockaddr *) &to, sizeof(to));
424
ret = initgnutls (mc, &session, &dh_params);
420
ret = initgnutls (&es);
430
gnutls_transport_set_ptr (session, (gnutls_transport_ptr_t) tcp_sd);
426
gnutls_transport_set_ptr (es.session,
427
(gnutls_transport_ptr_t) tcp_sd);
433
430
fprintf(stderr, "Establishing TLS session with %s\n", ip);
436
ret = gnutls_handshake (session);
433
ret = gnutls_handshake (es.session);
438
435
if (ret != GNUTLS_E_SUCCESS){
528
gnutls_bye (session, GNUTLS_SHUT_RDWR);
525
gnutls_bye (es.session, GNUTLS_SHUT_RDWR);
531
gnutls_deinit (session);
532
gnutls_certificate_free_credentials (mc->cred);
528
gnutls_deinit (es.session);
529
gnutls_certificate_free_credentials (es.cred);
533
530
gnutls_global_deinit ();
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;
534
static AvahiSimplePoll *simple_poll = NULL;
535
static AvahiServer *server = NULL;
537
static void resolve_callback(
538
AvahiSServiceResolver *r,
539
AvahiIfIndex interface,
540
AVAHI_GCC_UNUSED AvahiProtocol protocol,
541
AvahiResolverEvent event,
545
const char *host_name,
546
const AvahiAddress *address,
548
AVAHI_GCC_UNUSED AvahiStringList *txt,
549
AVAHI_GCC_UNUSED AvahiLookupResultFlags flags,
550
AVAHI_GCC_UNUSED void* userdata) {
551
552
assert(r); /* Spurious warning */
553
554
/* Called whenever a service has been resolved successfully or
578
579
avahi_s_service_resolver_free(r);
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:
582
static void browse_callback(
583
AvahiSServiceBrowser *b,
584
AvahiIfIndex interface,
585
AvahiProtocol protocol,
586
AvahiBrowserEvent event,
590
AVAHI_GCC_UNUSED AvahiLookupResultFlags flags,
593
AvahiServer *s = userdata;
594
assert(b); /* Spurious warning */
596
/* Called whenever a new services becomes available on the LAN or
597
is removed from the LAN */
601
case AVAHI_BROWSER_FAILURE:
603
fprintf(stderr, "(Browser) %s\n",
604
avahi_strerror(avahi_server_errno(server)));
605
avahi_simple_poll_quit(simple_poll);
608
case AVAHI_BROWSER_NEW:
609
/* We ignore the returned resolver object. In the callback
610
function we free it. If the server is terminated before
611
the callback function is called the server will free
612
the resolver for us. */
614
if (!(avahi_s_service_resolver_new(s, interface, protocol, name,
616
AVAHI_PROTO_INET6, 0,
617
resolve_callback, s)))
618
fprintf(stderr, "Failed to resolve service '%s': %s\n", name,
619
avahi_strerror(avahi_server_errno(s)));
622
case AVAHI_BROWSER_REMOVE:
625
case AVAHI_BROWSER_ALL_FOR_NOW:
626
case AVAHI_BROWSER_CACHE_EXHAUSTED:
628
/* Combines file name and path and returns the malloced new
629
string. some sane checks could/should be added */
630
static const char *combinepath(const char *first, const char *second){
631
size_t f_len = strlen(first);
632
size_t s_len = strlen(second);
633
char *tmp = malloc(f_len + s_len + 2);
631
/* combinds file name and path and returns the malloced new string. som sane checks could/should be added */
632
const char *combinepath(const char *first, const char *second){
634
tmp = malloc(strlen(first) + strlen(second) + 2);
634
635
if (tmp == NULL){
638
memcpy(tmp, first, f_len); /* Spurious warning */
642
memcpy(tmp + f_len + 1, second, s_len); /* Spurious warning */
644
tmp[f_len + 1 + s_len] = '\0';
640
if (first[0] != '\0' and first[strlen(first) - 1] != '/'){
651
650
AvahiSServiceBrowser *sb = NULL;
655
653
int returncode = EXIT_SUCCESS;
656
const char *interface = "eth0";
657
struct ifreq network;
654
const char *interface = NULL;
655
AvahiIfIndex if_index = AVAHI_IF_UNSPEC;
659
656
char *connect_to = NULL;
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;
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'},
659
static struct option long_options[] = {
660
{"debug", no_argument, (int *)&debug, 1},
661
{"connect", required_argument, 0, 'C'},
662
{"interface", required_argument, 0, 'i'},
663
{"certdir", required_argument, 0, 'd'},
664
{"certkey", required_argument, 0, 'c'},
665
{"certfile", required_argument, 0, 'k'},
677
668
int option_index = 0;
689
680
interface = optarg;
692
683
connect_to = optarg;
705
mc.dh_bits = (unsigned int) strtol(optarg, NULL, 10);
712
mc.priority = optarg;
716
695
exit(EXIT_FAILURE);
719
debug = debug_int ? true : false;
721
pubkeyfile = combinepath(keydir, pubkeyfile);
722
if (pubkeyfile == NULL){
723
perror("combinepath");
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);
699
certfile = combinepath(certdir, certfile);
700
if (certfile == NULL){
704
if(interface != NULL){
705
if_index = (AvahiIfIndex) if_nametoindex(interface);
707
fprintf(stderr, "No such interface: \"%s\"\n", interface);
740
712
if(connect_to != NULL){
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;
736
certkey = combinepath(certdir, certkey);
737
if (certkey == NULL){
790
742
avahi_set_log_function(empty_log);
808
760
config.publish_domain = 0;
810
762
/* Allocate a new server */
811
mc.server=avahi_server_new(avahi_simple_poll_get(mc.simple_poll),
812
&config, NULL, NULL, &error);
763
server = avahi_server_new(avahi_simple_poll_get(simple_poll),
764
&config, NULL, NULL, &error);
814
766
/* Free the configuration data */
815
767
avahi_server_config_free(&config);
817
769
/* Check if creating the server object succeeded */
819
771
fprintf(stderr, "Failed to create server: %s\n",
820
772
avahi_strerror(error));
821
773
returncode = EXIT_FAILURE;
825
777
/* Create the service browser */
826
sb = avahi_s_service_browser_new(mc.server, if_index,
778
sb = avahi_s_service_browser_new(server, if_index,
827
779
AVAHI_PROTO_INET6,
828
780
"_mandos._tcp", NULL, 0,
829
browse_callback, &mc);
781
browse_callback, server);
831
783
fprintf(stderr, "Failed to create service browser: %s\n",
832
avahi_strerror(avahi_server_errno(mc.server)));
784
avahi_strerror(avahi_server_errno(server)));
833
785
returncode = EXIT_FAILURE;