/mandos/trunk

To get this branch, use:
bzr branch http://bzr.recompile.se/loggerhead/mandos/trunk

« back to all changes in this revision

Viewing changes to plugins.d/mandosclient.c

  • Committer: Teddy Hogeborn
  • Date: 2008-07-31 19:51:44 UTC
  • mfrom: (24.1.5 mandos)
  • Revision ID: teddy@fukt.bsnet.se-20080731195144-yb37wz2sr1e6b3m4
Merge.

Show diffs side-by-side

added added

removed removed

Lines of Context:
25
25
 * along with this program.  If not, see
26
26
 * <http://www.gnu.org/licenses/>.
27
27
 * 
28
 
 * Contact the authors at <mandos@fukt.bsnet.se>.
 
28
 * Contact the authors at <https://www.fukt.bsnet.se/~belorn/> and
 
29
 * <https://www.fukt.bsnet.se/~teddy/>.
29
30
 */
30
31
 
31
32
/* Needed by GPGME, specifically gpgme_data_seek() */
37
38
#include <stdlib.h>
38
39
#include <time.h>
39
40
#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
42
41
 
43
42
#include <avahi-core/core.h>
44
43
#include <avahi-core/lookup.h>
65
64
#include <errno.h>              /* perror() */
66
65
#include <gpgme.h>
67
66
 
68
 
// getopt_long
 
67
// getopt long
69
68
#include <getopt.h>
70
69
 
71
70
#define BUFFER_SIZE 256
 
71
#define DH_BITS 1024
72
72
 
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";
76
76
 
77
77
bool debug = false;
78
78
 
79
 
/* Used for passing in values through all the callback functions */
80
79
typedef struct {
81
 
  AvahiSimplePoll *simple_poll;
82
 
  AvahiServer *server;
 
80
  gnutls_session_t session;
83
81
  gnutls_certificate_credentials_t cred;
84
 
  unsigned int dh_bits;
85
 
  const char *priority;
86
 
} mandos_context;
87
 
 
88
 
static ssize_t pgp_packet_decrypt (char *packet, size_t packet_size,
89
 
                                   char **new_packet,
90
 
                                   const char *homedir){
 
82
  gnutls_dh_params_t dh_params;
 
83
} encrypted_session;
 
84
 
 
85
 
 
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;
92
89
  gpgme_ctx_t ctx;
93
90
  gpgme_error_t rc;
249
246
  return ret;
250
247
}
251
248
 
252
 
static void debuggnutls(__attribute__((unused)) int level,
253
 
                        const char* string){
 
249
void debuggnutls(__attribute__((unused)) int level,
 
250
                 const char* string){
254
251
  fprintf(stderr, "%s", string);
255
252
}
256
253
 
257
 
static int initgnutls(mandos_context *mc, gnutls_session_t *session,
258
 
                      gnutls_dh_params_t *dh_params){
 
254
int initgnutls(encrypted_session *es){
259
255
  const char *err;
260
256
  int ret;
261
257
  
268
264
    fprintf (stderr, "global_init: %s\n", safer_gnutls_strerror(ret));
269
265
    return -1;
270
266
  }
271
 
  
 
267
 
272
268
  if (debug){
273
269
    gnutls_global_set_log_level(11);
274
270
    gnutls_global_set_log_function(debuggnutls);
275
271
  }
276
272
  
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));
284
280
  
285
281
  if(debug){
286
282
    fprintf(stderr, "Attempting to use OpenPGP certificate %s"
287
 
            " and keyfile %s as GnuTLS credentials\n", pubkeyfile,
288
 
            seckeyfile);
 
283
            " and keyfile %s as GnuTLS credentials\n", certfile,
 
284
            certkey);
289
285
  }
290
286
  
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) {
294
290
    fprintf
295
291
      (stderr, "Error[%d] while reading the OpenPGP key pair ('%s',"
296
292
       " '%s')\n",
297
 
       ret, pubkeyfile, seckeyfile);
 
293
       ret, certfile, certkey);
298
294
    fprintf(stdout, "The Error is: %s\n",
299
295
            safer_gnutls_strerror(ret));
300
296
    return -1;
301
297
  }
302
298
  
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));
308
304
    return -1;
309
305
  }
310
306
  
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));
315
311
    return -1;
316
312
  }
317
313
  
318
 
  gnutls_certificate_set_dh_params(mc->cred, *dh_params);
 
314
  gnutls_certificate_set_dh_params (es->cred, es->dh_params);
319
315
  
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));
325
321
  }
326
322
  
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",
332
328
    return -1;
333
329
  }
334
330
  
335
 
  if ((ret = gnutls_credentials_set(*session, GNUTLS_CRD_CERTIFICATE,
336
 
                                    mc->cred))
 
331
  if ((ret = gnutls_credentials_set
 
332
       (es->session, GNUTLS_CRD_CERTIFICATE, es->cred))
337
333
      != GNUTLS_E_SUCCESS) {
338
334
    fprintf(stderr, "Error setting a credentials set: %s\n",
339
335
            safer_gnutls_strerror(ret));
341
337
  }
342
338
  
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);
346
342
  
347
 
  gnutls_dh_set_prime_bits (*session, mc->dh_bits);
 
343
  gnutls_dh_set_prime_bits (es->session, DH_BITS);
348
344
  
349
345
  return 0;
350
346
}
351
347
 
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){}
354
350
 
355
 
static int start_mandos_communication(const char *ip, uint16_t port,
356
 
                                      AvahiIfIndex if_index,
357
 
                                      mandos_context *mc){
 
351
int start_mandos_communication(const char *ip, uint16_t port,
 
352
                               AvahiIfIndex if_index){
358
353
  int ret, tcp_sd;
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;
365
361
  size_t written = 0;
366
362
  int retval = 0;
367
363
  char interface[IF_NAMESIZE];
368
 
  gnutls_session_t session;
369
 
  gnutls_dh_params_t dh_params;
370
364
  
371
365
  if(debug){
372
366
    fprintf(stderr, "Setting up a tcp connection to %s, port %d\n",
378
372
    perror("socket");
379
373
    return -1;
380
374
  }
381
 
 
382
 
  if(debug){
383
 
    if(if_indextoname((unsigned int)if_index, interface) == NULL){
 
375
  
 
376
  if(if_indextoname((unsigned int)if_index, interface) == NULL){
 
377
    if(debug){
384
378
      perror("if_indextoname");
385
 
      return -1;
386
379
    }
 
380
    return -1;
 
381
  }
 
382
  
 
383
  if(debug){
387
384
    fprintf(stderr, "Binding to interface %s\n", interface);
388
385
  }
389
386
  
393
390
  if (ret < 0 ){
394
391
    perror("inet_pton");
395
392
    return -1;
396
 
  }
 
393
  }  
397
394
  if(ret == 0){
398
395
    fprintf(stderr, "Bad address: %s\n", ip);
399
396
    return -1;
404
401
  
405
402
  if(debug){
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){
410
 
      perror("inet_ntop");
411
 
    } else {
412
 
      if(strcmp(addrstr, ip) != 0){
413
 
        fprintf(stderr, "Canonical address form: %s\n", addrstr);
414
 
      }
415
 
    }
 
404
/*     char addrstr[INET6_ADDRSTRLEN]; */
 
405
/*     if(inet_ntop(to.sin6_family, &(to.sin6_addr), addrstr, */
 
406
/*               sizeof(addrstr)) == NULL){ */
 
407
/*       perror("inet_ntop"); */
 
408
/*     } else { */
 
409
/*       fprintf(stderr, "Really connecting to: %s, port %d\n", */
 
410
/*            addrstr, ntohs(to.sin6_port)); */
 
411
/*     } */
416
412
  }
417
413
  
418
414
  ret = connect(tcp_sd, (struct sockaddr *) &to, sizeof(to));
421
417
    return -1;
422
418
  }
423
419
  
424
 
  ret = initgnutls (mc, &session, &dh_params);
 
420
  ret = initgnutls (&es);
425
421
  if (ret != 0){
426
422
    retval = -1;
427
423
    return -1;
428
424
  }
429
425
  
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);
431
428
  
432
429
  if(debug){
433
430
    fprintf(stderr, "Establishing TLS session with %s\n", ip);
434
431
  }
435
432
  
436
 
  ret = gnutls_handshake (session);
 
433
  ret = gnutls_handshake (es.session);
437
434
  
438
435
  if (ret != GNUTLS_E_SUCCESS){
439
436
    if(debug){
461
458
      buffer_capacity += BUFFER_SIZE;
462
459
    }
463
460
    
464
 
    ret = gnutls_record_recv(session, buffer+buffer_length,
465
 
                             BUFFER_SIZE);
 
461
    ret = gnutls_record_recv
 
462
      (es.session, buffer+buffer_length, BUFFER_SIZE);
466
463
    if (ret == 0){
467
464
      break;
468
465
    }
472
469
      case GNUTLS_E_AGAIN:
473
470
        break;
474
471
      case GNUTLS_E_REHANDSHAKE:
475
 
        ret = gnutls_handshake (session);
 
472
        ret = gnutls_handshake (es.session);
476
473
        if (ret < 0){
477
474
          fprintf(stderr, "\n*** Handshake failed ***\n");
478
475
          gnutls_perror (ret);
484
481
        fprintf(stderr, "Unknown error while reading data from"
485
482
                " encrypted session with mandos server\n");
486
483
        retval = -1;
487
 
        gnutls_bye (session, GNUTLS_SHUT_RDWR);
 
484
        gnutls_bye (es.session, GNUTLS_SHUT_RDWR);
488
485
        goto exit;
489
486
      }
490
487
    } else {
496
493
    decrypted_buffer_size = pgp_packet_decrypt(buffer,
497
494
                                               buffer_length,
498
495
                                               &decrypted_buffer,
499
 
                                               keydir);
 
496
                                               certdir);
500
497
    if (decrypted_buffer_size >= 0){
501
498
      while(written < (size_t) decrypted_buffer_size){
502
499
        ret = (int)fwrite (decrypted_buffer + written, 1,
525
522
  }
526
523
 
527
524
  free(buffer);
528
 
  gnutls_bye (session, GNUTLS_SHUT_RDWR);
 
525
  gnutls_bye (es.session, GNUTLS_SHUT_RDWR);
529
526
 exit:
530
527
  close(tcp_sd);
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 ();
534
531
  return retval;
535
532
}
536
533
 
537
 
static void resolve_callback( AvahiSServiceResolver *r,
538
 
                              AvahiIfIndex interface,
539
 
                              AVAHI_GCC_UNUSED AvahiProtocol protocol,
540
 
                              AvahiResolverEvent event,
541
 
                              const char *name,
542
 
                              const char *type,
543
 
                              const char *domain,
544
 
                              const char *host_name,
545
 
                              const AvahiAddress *address,
546
 
                              uint16_t port,
547
 
                              AVAHI_GCC_UNUSED AvahiStringList *txt,
548
 
                              AVAHI_GCC_UNUSED AvahiLookupResultFlags flags,
549
 
                              void* userdata) {
550
 
  mandos_context *mc = userdata;
 
534
static AvahiSimplePoll *simple_poll = NULL;
 
535
static AvahiServer *server = NULL;
 
536
 
 
537
static void resolve_callback(
 
538
    AvahiSServiceResolver *r,
 
539
    AvahiIfIndex interface,
 
540
    AVAHI_GCC_UNUSED AvahiProtocol protocol,
 
541
    AvahiResolverEvent event,
 
542
    const char *name,
 
543
    const char *type,
 
544
    const char *domain,
 
545
    const char *host_name,
 
546
    const AvahiAddress *address,
 
547
    uint16_t port,
 
548
    AVAHI_GCC_UNUSED AvahiStringList *txt,
 
549
    AVAHI_GCC_UNUSED AvahiLookupResultFlags flags,
 
550
    AVAHI_GCC_UNUSED void* userdata) {
 
551
    
551
552
  assert(r);                    /* Spurious warning */
552
553
  
553
554
  /* Called whenever a service has been resolved successfully or
558
559
  case AVAHI_RESOLVER_FAILURE:
559
560
    fprintf(stderr, "(Resolver) Failed to resolve service '%s' of"
560
561
            " type '%s' in domain '%s': %s\n", name, type, domain,
561
 
            avahi_strerror(avahi_server_errno(mc->server)));
 
562
            avahi_strerror(avahi_server_errno(server)));
562
563
    break;
563
564
    
564
565
  case AVAHI_RESOLVER_FOUND:
569
570
        fprintf(stderr, "Mandos server \"%s\" found on %s (%s) on"
570
571
                " port %d\n", name, host_name, ip, port);
571
572
      }
572
 
      int ret = start_mandos_communication(ip, port, interface, mc);
 
573
      int ret = start_mandos_communication(ip, port, interface);
573
574
      if (ret == 0){
574
575
        exit(EXIT_SUCCESS);
575
576
      }
578
579
  avahi_s_service_resolver_free(r);
579
580
}
580
581
 
581
 
static void browse_callback( AvahiSServiceBrowser *b,
582
 
                             AvahiIfIndex interface,
583
 
                             AvahiProtocol protocol,
584
 
                             AvahiBrowserEvent event,
585
 
                             const char *name,
586
 
                             const char *type,
587
 
                             const char *domain,
588
 
                             AVAHI_GCC_UNUSED AvahiLookupResultFlags flags,
589
 
                             void* userdata) {
590
 
  mandos_context *mc = userdata;
591
 
  assert(b);                    /* Spurious warning */
592
 
  
593
 
  /* Called whenever a new services becomes available on the LAN or
594
 
     is removed from the LAN */
595
 
  
596
 
  switch (event) {
597
 
  default:
598
 
  case AVAHI_BROWSER_FAILURE:
599
 
    
600
 
    fprintf(stderr, "(Browser) %s\n",
601
 
            avahi_strerror(avahi_server_errno(mc->server)));
602
 
    avahi_simple_poll_quit(mc->simple_poll);
603
 
    return;
604
 
    
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. */
610
 
    
611
 
    if (!(avahi_s_service_resolver_new(mc->server, interface, protocol, name,
612
 
                                       type, domain,
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)));
617
 
    break;
618
 
    
619
 
  case AVAHI_BROWSER_REMOVE:
620
 
    break;
621
 
    
622
 
  case AVAHI_BROWSER_ALL_FOR_NOW:
623
 
  case AVAHI_BROWSER_CACHE_EXHAUSTED:
624
 
    break;
625
 
  }
 
582
static void browse_callback(
 
583
    AvahiSServiceBrowser *b,
 
584
    AvahiIfIndex interface,
 
585
    AvahiProtocol protocol,
 
586
    AvahiBrowserEvent event,
 
587
    const char *name,
 
588
    const char *type,
 
589
    const char *domain,
 
590
    AVAHI_GCC_UNUSED AvahiLookupResultFlags flags,
 
591
    void* userdata) {
 
592
    
 
593
    AvahiServer *s = userdata;
 
594
    assert(b);                  /* Spurious warning */
 
595
    
 
596
    /* Called whenever a new services becomes available on the LAN or
 
597
       is removed from the LAN */
 
598
    
 
599
    switch (event) {
 
600
    default:
 
601
    case AVAHI_BROWSER_FAILURE:
 
602
      
 
603
      fprintf(stderr, "(Browser) %s\n",
 
604
              avahi_strerror(avahi_server_errno(server)));
 
605
      avahi_simple_poll_quit(simple_poll);
 
606
      return;
 
607
      
 
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. */
 
613
      
 
614
      if (!(avahi_s_service_resolver_new(s, interface, protocol, name,
 
615
                                         type, domain,
 
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)));
 
620
      break;
 
621
      
 
622
    case AVAHI_BROWSER_REMOVE:
 
623
      break;
 
624
      
 
625
    case AVAHI_BROWSER_ALL_FOR_NOW:
 
626
    case AVAHI_BROWSER_CACHE_EXHAUSTED:
 
627
      break;
 
628
    }
626
629
}
627
630
 
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){
 
633
  char *tmp;
 
634
  tmp = malloc(strlen(first) + strlen(second) + 2);
634
635
  if (tmp == NULL){
 
636
    perror("malloc");
635
637
    return NULL;
636
638
  }
637
 
  if(f_len > 0){
638
 
    memcpy(tmp, first, f_len);  /* Spurious warning */
639
 
  }
640
 
  tmp[f_len] = '/';
641
 
  if(s_len > 0){
642
 
    memcpy(tmp + f_len + 1, second, s_len); /* Spurious warning */
643
 
  }
644
 
  tmp[f_len + 1 + s_len] = '\0';
 
639
  strcpy(tmp, first);
 
640
  if (first[0] != '\0' and first[strlen(first) - 1] != '/'){
 
641
    strcat(tmp, "/");
 
642
  }
 
643
  strcat(tmp, second);
645
644
  return tmp;
646
645
}
647
646
 
651
650
    AvahiSServiceBrowser *sb = NULL;
652
651
    int error;
653
652
    int ret;
654
 
    int debug_int;
655
653
    int returncode = EXIT_SUCCESS;
656
 
    const char *interface = "eth0";
657
 
    struct ifreq network;
658
 
    int sd;
 
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"};
663
657
    
664
 
    debug_int = debug ? 1 : 0;
665
658
    while (true){
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'},
675
666
        {0, 0, 0, 0} };
676
667
      
677
668
      int option_index = 0;
688
679
      case 'i':
689
680
        interface = optarg;
690
681
        break;
691
 
      case 'c':
 
682
      case 'C':
692
683
        connect_to = optarg;
693
684
        break;
694
685
      case 'd':
695
 
        keydir = optarg;
696
 
        break;
697
 
      case 'p':
698
 
        pubkeyfile = optarg;
699
 
        break;
700
 
      case 's':
701
 
        seckeyfile = optarg;
702
 
        break;
703
 
      case 'D':
704
 
        errno = 0;
705
 
        mc.dh_bits = (unsigned int) strtol(optarg, NULL, 10);
706
 
        if (errno){
707
 
          perror("strtol");
708
 
          exit(EXIT_FAILURE);
709
 
        }
710
 
        break;
711
 
      case 'P':
712
 
        mc.priority = optarg;
713
 
        break;
714
 
      case '?':
 
686
        certdir = optarg;
 
687
        break;
 
688
      case 'c':
 
689
        certfile = optarg;
 
690
        break;
 
691
      case 'k':
 
692
        certkey = optarg;
 
693
        break;
715
694
      default:
716
695
        exit(EXIT_FAILURE);
717
696
      }
718
697
    }
719
 
    debug = debug_int ? true : false;
720
 
    
721
 
    pubkeyfile = combinepath(keydir, pubkeyfile);
722
 
    if (pubkeyfile == NULL){
723
 
      perror("combinepath");
724
 
      returncode = EXIT_FAILURE;
725
 
      goto exit;
726
 
    }
727
 
    
728
 
    seckeyfile = combinepath(keydir, seckeyfile);
729
 
    if (seckeyfile == NULL){
730
 
      perror("combinepath");
731
 
      goto exit;
732
 
    }
733
 
    
734
 
    if_index = (AvahiIfIndex) if_nametoindex(interface);
735
 
    if(if_index == 0){
736
 
      fprintf(stderr, "No such interface: \"%s\"\n", interface);
737
 
      exit(EXIT_FAILURE);
 
698
 
 
699
    certfile = combinepath(certdir, certfile);
 
700
    if (certfile == NULL){
 
701
      goto exit;
 
702
    }
 
703
    
 
704
    if(interface != NULL){
 
705
      if_index = (AvahiIfIndex) if_nametoindex(interface);
 
706
      if(if_index == 0){
 
707
        fprintf(stderr, "No such interface: \"%s\"\n", interface);
 
708
        exit(EXIT_FAILURE);
 
709
      }
738
710
    }
739
711
    
740
712
    if(connect_to != NULL){
753
725
      }
754
726
      *address = '\0';
755
727
      address = connect_to;
756
 
      ret = start_mandos_communication(address, port, if_index, &mc);
 
728
      ret = start_mandos_communication(address, port, if_index);
757
729
      if(ret < 0){
758
730
        exit(EXIT_FAILURE);
759
731
      } else {
761
733
      }
762
734
    }
763
735
    
764
 
    sd = socket(PF_INET6, SOCK_DGRAM, IPPROTO_IP);
765
 
    if(sd < 0) {
766
 
      perror("socket");
767
 
      returncode = EXIT_FAILURE;
768
 
      goto exit;
769
 
    }
770
 
    strcpy(network.ifr_name, interface); /* Spurious warning */
771
 
    ret = ioctl(sd, SIOCGIFFLAGS, &network);
772
 
    if(ret == -1){
773
 
      
774
 
      perror("ioctl SIOCGIFFLAGS");
775
 
      returncode = EXIT_FAILURE;
776
 
      goto exit;
777
 
    }
778
 
    if((network.ifr_flags & IFF_UP) == 0){
779
 
      network.ifr_flags |= IFF_UP;
780
 
      ret = ioctl(sd, SIOCSIFFLAGS, &network);
781
 
      if(ret == -1){
782
 
        perror("ioctl SIOCSIFFLAGS");
783
 
        returncode = EXIT_FAILURE;
784
 
        goto exit;
785
 
      }
786
 
    }
787
 
    close(sd);
 
736
    certkey = combinepath(certdir, certkey);
 
737
    if (certkey == NULL){
 
738
      goto exit;
 
739
    }
788
740
    
789
741
    if (not debug){
790
742
      avahi_set_log_function(empty_log);
794
746
    srand((unsigned int) time(NULL));
795
747
 
796
748
    /* Allocate main loop object */
797
 
    if (!(mc.simple_poll = avahi_simple_poll_new())) {
 
749
    if (!(simple_poll = avahi_simple_poll_new())) {
798
750
        fprintf(stderr, "Failed to create simple poll object.\n");
799
 
        returncode = EXIT_FAILURE;
 
751
        
800
752
        goto exit;
801
753
    }
802
754
 
808
760
    config.publish_domain = 0;
809
761
 
810
762
    /* Allocate a new server */
811
 
    mc.server=avahi_server_new(avahi_simple_poll_get(mc.simple_poll),
812
 
                               &config, NULL, NULL, &error);
813
 
    
 
763
    server = avahi_server_new(avahi_simple_poll_get(simple_poll),
 
764
                              &config, NULL, NULL, &error);
 
765
 
814
766
    /* Free the configuration data */
815
767
    avahi_server_config_free(&config);
816
 
    
 
768
 
817
769
    /* Check if creating the server object succeeded */
818
 
    if (!mc.server) {
 
770
    if (!server) {
819
771
        fprintf(stderr, "Failed to create server: %s\n",
820
772
                avahi_strerror(error));
821
773
        returncode = EXIT_FAILURE;
823
775
    }
824
776
    
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);
830
782
    if (!sb) {
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;
834
786
        goto exit;
835
787
    }
840
792
      fprintf(stderr, "Starting avahi loop search\n");
841
793
    }
842
794
    
843
 
    avahi_simple_poll_loop(mc.simple_poll);
 
795
    avahi_simple_poll_loop(simple_poll);
844
796
    
845
797
 exit:
846
798
 
852
804
    if (sb)
853
805
        avahi_s_service_browser_free(sb);
854
806
    
855
 
    if (mc.server)
856
 
        avahi_server_free(mc.server);
 
807
    if (server)
 
808
        avahi_server_free(server);
857
809
 
858
 
    if (mc.simple_poll)
859
 
        avahi_simple_poll_free(mc.simple_poll);
860
 
    free(pubkeyfile);
861
 
    free(seckeyfile);
 
810
    if (simple_poll)
 
811
        avahi_simple_poll_free(simple_poll);
 
812
    free(certfile);
 
813
    free(certkey);
862
814
    
863
815
    return returncode;
864
816
}