244
void debuggnutls(__attribute__((unused)) int level,
252
static void debuggnutls(__attribute__((unused)) int level,
246
254
fprintf(stderr, "%s", string);
249
int initgnutls(encrypted_session *es){
257
static int initgnutls(mandos_context *mc, gnutls_session_t *session,
258
gnutls_dh_params_t *dh_params){
254
263
fprintf(stderr, "Initializing GnuTLS\n");
257
266
if ((ret = gnutls_global_init ())
258
267
!= GNUTLS_E_SUCCESS) {
259
268
fprintf (stderr, "global_init: %s\n", safer_gnutls_strerror(ret));
264
273
gnutls_global_set_log_level(11);
265
274
gnutls_global_set_log_function(debuggnutls);
268
277
/* openpgp credentials */
269
if ((ret = gnutls_certificate_allocate_credentials (&es->cred))
278
if ((ret = gnutls_certificate_allocate_credentials (&mc->cred))
270
279
!= GNUTLS_E_SUCCESS) {
271
280
fprintf (stderr, "memory error: %s\n",
272
281
safer_gnutls_strerror(ret));
277
286
fprintf(stderr, "Attempting to use OpenPGP certificate %s"
278
" and keyfile %s as GnuTLS credentials\n", CERTFILE,
287
" and keyfile %s as GnuTLS credentials\n", pubkeyfile,
282
291
ret = gnutls_certificate_set_openpgp_key_file
283
(es->cred, CERTFILE, KEYFILE, GNUTLS_OPENPGP_FMT_BASE64);
292
(mc->cred, pubkeyfile, seckeyfile, GNUTLS_OPENPGP_FMT_BASE64);
284
293
if (ret != GNUTLS_E_SUCCESS) {
286
295
(stderr, "Error[%d] while reading the OpenPGP key pair ('%s',"
288
ret, CERTFILE, KEYFILE);
297
ret, pubkeyfile, seckeyfile);
289
298
fprintf(stdout, "The Error is: %s\n",
290
299
safer_gnutls_strerror(ret));
294
303
//GnuTLS server initialization
295
if ((ret = gnutls_dh_params_init (&es->dh_params))
304
if ((ret = gnutls_dh_params_init(dh_params))
296
305
!= GNUTLS_E_SUCCESS) {
297
306
fprintf (stderr, "Error in dh parameter initialization: %s\n",
298
307
safer_gnutls_strerror(ret));
302
if ((ret = gnutls_dh_params_generate2 (es->dh_params, DH_BITS))
311
if ((ret = gnutls_dh_params_generate2(*dh_params, mc->dh_bits))
303
312
!= GNUTLS_E_SUCCESS) {
304
313
fprintf (stderr, "Error in prime generation: %s\n",
305
314
safer_gnutls_strerror(ret));
309
gnutls_certificate_set_dh_params (es->cred, es->dh_params);
318
gnutls_certificate_set_dh_params(mc->cred, *dh_params);
311
320
// GnuTLS session creation
312
if ((ret = gnutls_init (&es->session, GNUTLS_SERVER))
321
if ((ret = gnutls_init(session, GNUTLS_SERVER))
313
322
!= GNUTLS_E_SUCCESS){
314
323
fprintf(stderr, "Error in GnuTLS session initialization: %s\n",
315
324
safer_gnutls_strerror(ret));
318
if ((ret = gnutls_priority_set_direct (es->session, "NORMAL", &err))
327
if ((ret = gnutls_priority_set_direct(*session, mc->priority, &err))
319
328
!= GNUTLS_E_SUCCESS) {
320
329
fprintf(stderr, "Syntax error at: %s\n", err);
321
330
fprintf(stderr, "GnuTLS error: %s\n",
509
gnutls_bye (es.session, GNUTLS_SHUT_RDWR);
528
gnutls_bye (session, GNUTLS_SHUT_RDWR);
512
gnutls_deinit (es.session);
513
gnutls_certificate_free_credentials (es.cred);
531
gnutls_deinit (session);
532
gnutls_certificate_free_credentials (mc->cred);
514
533
gnutls_global_deinit ();
518
static AvahiSimplePoll *simple_poll = NULL;
519
static AvahiServer *server = NULL;
521
static void resolve_callback(
522
AvahiSServiceResolver *r,
523
AvahiIfIndex interface,
524
AVAHI_GCC_UNUSED AvahiProtocol protocol,
525
AvahiResolverEvent event,
529
const char *host_name,
530
const AvahiAddress *address,
532
AVAHI_GCC_UNUSED AvahiStringList *txt,
533
AVAHI_GCC_UNUSED AvahiLookupResultFlags flags,
534
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;
536
551
assert(r); /* Spurious warning */
538
553
/* Called whenever a service has been resolved successfully or
551
566
char ip[AVAHI_ADDRESS_STR_MAX];
552
567
avahi_address_snprint(ip, sizeof(ip), address);
554
fprintf(stderr, "Mandos server found on %s (%s) on port %d\n",
555
host_name, ip, port);
569
fprintf(stderr, "Mandos server \"%s\" found on %s (%s) on"
570
" port %d\n", name, host_name, ip, port);
557
int ret = start_mandos_communication(ip, port,
558
(unsigned int) interface);
572
int ret = start_mandos_communication(ip, port, interface, mc);
560
574
exit(EXIT_SUCCESS);
566
578
avahi_s_service_resolver_free(r);
569
static void browse_callback(
570
AvahiSServiceBrowser *b,
571
AvahiIfIndex interface,
572
AvahiProtocol protocol,
573
AvahiBrowserEvent event,
577
AVAHI_GCC_UNUSED AvahiLookupResultFlags flags,
580
AvahiServer *s = userdata;
581
assert(b); /* Spurious warning */
583
/* Called whenever a new services becomes available on the LAN or
584
is removed from the LAN */
588
case AVAHI_BROWSER_FAILURE:
590
fprintf(stderr, "(Browser) %s\n",
591
avahi_strerror(avahi_server_errno(server)));
592
avahi_simple_poll_quit(simple_poll);
595
case AVAHI_BROWSER_NEW:
596
/* We ignore the returned resolver object. In the callback
597
function we free it. If the server is terminated before
598
the callback function is called the server will free
599
the resolver for us. */
601
if (!(avahi_s_service_resolver_new(s, interface, protocol, name,
603
AVAHI_PROTO_INET6, 0,
604
resolve_callback, s)))
605
fprintf(stderr, "Failed to resolve service '%s': %s\n", name,
606
avahi_strerror(avahi_server_errno(s)));
609
case AVAHI_BROWSER_REMOVE:
612
case AVAHI_BROWSER_ALL_FOR_NOW:
613
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:
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);
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';
618
649
int main(AVAHI_GCC_UNUSED int argc, AVAHI_GCC_UNUSED char*argv[]) {
619
650
AvahiServerConfig config;
620
651
AvahiSServiceBrowser *sb = NULL;
623
655
int returncode = EXIT_SUCCESS;
624
656
const char *interface = "eth0";
657
struct ifreq network;
659
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;
627
static struct option long_options[] = {
628
{"debug", no_argument, (int *)&debug, 1},
629
{"interface", required_argument, 0, 'i'},
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'},
632
677
int option_index = 0;
644
689
interface = optarg;
705
mc.dh_bits = (unsigned int) strtol(optarg, NULL, 10);
712
mc.priority = optarg;
647
716
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);
740
if(connect_to != NULL){
741
/* Connect directly, do not use Zeroconf */
742
/* (Mainly meant for debugging) */
743
char *address = strrchr(connect_to, ':');
745
fprintf(stderr, "No colon in address\n");
749
uint16_t port = (uint16_t) strtol(address+1, NULL, 10);
751
perror("Bad port number");
755
address = connect_to;
756
ret = start_mandos_communication(address, port, if_index, &mc);
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;
652
790
avahi_set_log_function(empty_log);