/mandos/release

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

« back to all changes in this revision

Viewing changes to plugins.d/mandosclient.c

  • Committer: Teddy Hogeborn
  • Date: 2008-08-01 06:33:15 UTC
  • Revision ID: teddy@fukt.bsnet.se-20080801063315-4k33q3ek28hjc3tu
* plugins.d/plugbasedclient.c: Update include file comments.
  (struct process.disable): Renamed to "disabled".  All users changed.
  (addarguments): Renamed to "addargument".  All callers changed.
  (doc, args_doc): Removed.
  (main): Changed default "plugindir" to
          "/conf/conf.d/mandos/plugins.d".  Renamed "rfds_orig" to
           "rfds_all"; all users changed.  New "debug" and
           "exitstatus" variables.  New "--debug" option.  Removed
           unnecessary ".flags = 0" from all options.  Changed so that
           "--disable-plugin" only takes one plugin.  Check for
           non-existence of ":" in argument to "--options-for".  Added
           some debugging outputs.  Set the FD_CLOEXEC flag on the
           directory FD.  More capable code for dealing with
           disallowed plugin file name prefixes and suffixes.  Bug
           fix: check for some malloc failures.  Moved allocating the
           "struct process *new_process" to after the fork.  Do
           _exit() instead of exit() in the child.

* plugins.d/mandosclient.c: Updated contact information.

Show diffs side-by-side

added added

removed removed

Lines of Context:
37
37
#include <stdlib.h>
38
38
#include <time.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
42
40
 
43
41
#include <avahi-core/core.h>
44
42
#include <avahi-core/lookup.h>
71
69
#define BUFFER_SIZE 256
72
70
#define DH_BITS 1024
73
71
 
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";
 
72
const char *certdir = "/conf/conf.d/cryptkeyreq/";
 
73
const char *certfile = "openpgp-client.txt";
 
74
const char *certkey = "openpgp-client-key.txt";
77
75
 
78
76
bool debug = false;
79
77
 
80
78
typedef struct {
81
 
  AvahiSimplePoll *simple_poll;
82
 
  AvahiServer *server;
 
79
  gnutls_session_t session;
83
80
  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){
 
81
  gnutls_dh_params_t dh_params;
 
82
} encrypted_session;
 
83
 
 
84
 
 
85
ssize_t pgp_packet_decrypt (char *packet, size_t packet_size,
 
86
                            char **new_packet, const char *homedir){
91
87
  gpgme_data_t dh_crypto, dh_plain;
92
88
  gpgme_ctx_t ctx;
93
89
  gpgme_error_t rc;
249
245
  return ret;
250
246
}
251
247
 
252
 
static void debuggnutls(__attribute__((unused)) int level,
253
 
                        const char* string){
 
248
void debuggnutls(__attribute__((unused)) int level,
 
249
                 const char* string){
254
250
  fprintf(stderr, "%s", string);
255
251
}
256
252
 
257
 
static int initgnutls(mandos_context *mc){
 
253
int initgnutls(encrypted_session *es){
258
254
  const char *err;
259
255
  int ret;
260
256
  
323
319
            safer_gnutls_strerror(ret));
324
320
  }
325
321
  
326
 
  if ((ret = gnutls_priority_set_direct (es->session, mc->priority, &err))
 
322
  if ((ret = gnutls_priority_set_direct (es->session, "NORMAL", &err))
327
323
      != GNUTLS_E_SUCCESS) {
328
324
    fprintf(stderr, "Syntax error at: %s\n", err);
329
325
    fprintf(stderr, "GnuTLS error: %s\n",
348
344
  return 0;
349
345
}
350
346
 
351
 
static void empty_log(__attribute__((unused)) AvahiLogLevel level,
352
 
                      __attribute__((unused)) const char *txt){}
 
347
void empty_log(__attribute__((unused)) AvahiLogLevel level,
 
348
               __attribute__((unused)) const char *txt){}
353
349
 
354
 
static int start_mandos_communication(const char *ip, uint16_t port,
355
 
                                      AvahiIfIndex if_index,
356
 
                                      mandos_context *mc){
 
350
int start_mandos_communication(const char *ip, uint16_t port,
 
351
                               AvahiIfIndex if_index){
357
352
  int ret, tcp_sd;
358
353
  struct sockaddr_in6 to;
359
354
  encrypted_session es;
376
371
    perror("socket");
377
372
    return -1;
378
373
  }
379
 
 
 
374
  
 
375
  if(if_indextoname((unsigned int)if_index, interface) == NULL){
 
376
    if(debug){
 
377
      perror("if_indextoname");
 
378
    }
 
379
    return -1;
 
380
  }
 
381
  
380
382
  if(debug){
381
 
    if(if_indextoname((unsigned int)if_index, interface) == NULL){
382
 
      if(debug){
383
 
        perror("if_indextoname");
384
 
      }
385
 
      return -1;
386
 
    }
387
 
    
388
383
    fprintf(stderr, "Binding to interface %s\n", interface);
389
384
  }
390
385
  
535
530
  return retval;
536
531
}
537
532
 
538
 
static void resolve_callback( 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
 
  mandos_context *mc = userdata;
 
533
static AvahiSimplePoll *simple_poll = NULL;
 
534
static AvahiServer *server = NULL;
 
535
 
 
536
static void resolve_callback(
 
537
    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
    AVAHI_GCC_UNUSED void* userdata) {
 
550
    
552
551
  assert(r);                    /* Spurious warning */
553
552
  
554
553
  /* Called whenever a service has been resolved successfully or
559
558
  case AVAHI_RESOLVER_FAILURE:
560
559
    fprintf(stderr, "(Resolver) Failed to resolve service '%s' of"
561
560
            " type '%s' in domain '%s': %s\n", name, type, domain,
562
 
            avahi_strerror(avahi_server_errno(mc->server)));
 
561
            avahi_strerror(avahi_server_errno(server)));
563
562
    break;
564
563
    
565
564
  case AVAHI_RESOLVER_FOUND:
570
569
        fprintf(stderr, "Mandos server \"%s\" found on %s (%s) on"
571
570
                " port %d\n", name, host_name, ip, port);
572
571
      }
573
 
      int ret = start_mandos_communication(ip, port, interface, mc);
 
572
      int ret = start_mandos_communication(ip, port, interface);
574
573
      if (ret == 0){
575
574
        exit(EXIT_SUCCESS);
576
575
      }
579
578
  avahi_s_service_resolver_free(r);
580
579
}
581
580
 
582
 
static void browse_callback( AvahiSServiceBrowser *b,
583
 
                             AvahiIfIndex interface,
584
 
                             AvahiProtocol protocol,
585
 
                             AvahiBrowserEvent event,
586
 
                             const char *name,
587
 
                             const char *type,
588
 
                             const char *domain,
589
 
                             AVAHI_GCC_UNUSED AvahiLookupResultFlags flags,
590
 
                             void* userdata) {
591
 
  mandos_context *mc = userdata;
592
 
  assert(b);                    /* Spurious warning */
593
 
  
594
 
  /* Called whenever a new services becomes available on the LAN or
595
 
     is removed from the LAN */
596
 
  
597
 
  switch (event) {
598
 
  default:
599
 
  case AVAHI_BROWSER_FAILURE:
600
 
      
601
 
    fprintf(stderr, "(Browser) %s\n",
602
 
            avahi_strerror(avahi_server_errno(mc->server)));
603
 
    avahi_simple_poll_quit(mc->simple_poll);
604
 
    return;
605
 
      
606
 
  case AVAHI_BROWSER_NEW:
607
 
    /* We ignore the returned resolver object. In the callback
608
 
       function we free it. If the server is terminated before
609
 
       the callback function is called the server will free
610
 
       the resolver for us. */
611
 
      
612
 
    if (!(avahi_s_service_resolver_new(mc->server, interface, protocol, name,
613
 
                                       type, domain,
614
 
                                       AVAHI_PROTO_INET6, 0,
615
 
                                       resolve_callback, mc)))
616
 
      fprintf(stderr, "Failed to resolve service '%s': %s\n", name,
617
 
              avahi_strerror(avahi_server_errno(s)));
618
 
    break;
619
 
      
620
 
  case AVAHI_BROWSER_REMOVE:
621
 
    break;
622
 
      
623
 
  case AVAHI_BROWSER_ALL_FOR_NOW:
624
 
  case AVAHI_BROWSER_CACHE_EXHAUSTED:
625
 
    break;
626
 
  }
 
581
static void browse_callback(
 
582
    AvahiSServiceBrowser *b,
 
583
    AvahiIfIndex interface,
 
584
    AvahiProtocol protocol,
 
585
    AvahiBrowserEvent event,
 
586
    const char *name,
 
587
    const char *type,
 
588
    const char *domain,
 
589
    AVAHI_GCC_UNUSED AvahiLookupResultFlags flags,
 
590
    void* userdata) {
 
591
    
 
592
    AvahiServer *s = userdata;
 
593
    assert(b);                  /* Spurious warning */
 
594
    
 
595
    /* Called whenever a new services becomes available on the LAN or
 
596
       is removed from the LAN */
 
597
    
 
598
    switch (event) {
 
599
    default:
 
600
    case AVAHI_BROWSER_FAILURE:
 
601
      
 
602
      fprintf(stderr, "(Browser) %s\n",
 
603
              avahi_strerror(avahi_server_errno(server)));
 
604
      avahi_simple_poll_quit(simple_poll);
 
605
      return;
 
606
      
 
607
    case AVAHI_BROWSER_NEW:
 
608
      /* We ignore the returned resolver object. In the callback
 
609
         function we free it. If the server is terminated before
 
610
         the callback function is called the server will free
 
611
         the resolver for us. */
 
612
      
 
613
      if (!(avahi_s_service_resolver_new(s, interface, protocol, name,
 
614
                                         type, domain,
 
615
                                         AVAHI_PROTO_INET6, 0,
 
616
                                         resolve_callback, s)))
 
617
        fprintf(stderr, "Failed to resolve service '%s': %s\n", name,
 
618
                avahi_strerror(avahi_server_errno(s)));
 
619
      break;
 
620
      
 
621
    case AVAHI_BROWSER_REMOVE:
 
622
      break;
 
623
      
 
624
    case AVAHI_BROWSER_ALL_FOR_NOW:
 
625
    case AVAHI_BROWSER_CACHE_EXHAUSTED:
 
626
      break;
 
627
    }
627
628
}
628
629
 
629
 
/* Combines file name and path and returns the malloced new
630
 
   string. some sane checks could/should be added */
631
 
static const char *combinepath(const char *first, const char *second){
632
 
  size_t f_len = strlen(first);
633
 
  size_t s_len = strlen(second);
634
 
  char *tmp = malloc(f_len + s_len + 2);
 
630
/* combinds file name and path and returns the malloced new string. som sane checks could/should be added */
 
631
const char *combinepath(const char *first, const char *second){
 
632
  char *tmp;
 
633
  tmp = malloc(strlen(first) + strlen(second) + 2);
635
634
  if (tmp == NULL){
 
635
    perror("malloc");
636
636
    return NULL;
637
637
  }
638
 
  if(f_len > 0){
639
 
    memcpy(tmp, first, f_len);
640
 
  }
641
 
  tmp[f_len] = '/';
642
 
  if(s_len > 0){
643
 
    memcpy(tmp + f_len + 1, second, s_len);
644
 
  }
645
 
  tmp[f_len + 1 + s_len] = '\0';
 
638
  strcpy(tmp, first);
 
639
  if (first[0] != '\0' and first[strlen(first) - 1] != '/'){
 
640
    strcat(tmp, "/");
 
641
  }
 
642
  strcat(tmp, second);
646
643
  return tmp;
647
644
}
648
645
 
653
650
    int error;
654
651
    int ret;
655
652
    int returncode = EXIT_SUCCESS;
656
 
    const char *interface = "eth0";
657
 
    struct ifreq network;
658
 
    int sd;
 
653
    const char *interface = NULL;
 
654
    AvahiIfIndex if_index = AVAHI_IF_UNSPEC;
659
655
    char *connect_to = NULL;
660
 
    AvahiIfIndex if_index = AVAHI_IF_UNSPEC;
661
 
    mandos_context mc = { .simple_poll = NULL, .server = NULL,
662
 
                          .dh_bits = 2048, .priority = "SECURE256"};
663
656
    
664
657
    while (true){
665
658
      static struct option long_options[] = {
669
662
        {"certdir", required_argument, 0, 'd'},
670
663
        {"certkey", required_argument, 0, 'c'},
671
664
        {"certfile", required_argument, 0, 'k'},
672
 
        {"dh_bits", required_argument, 0, 'D'},
673
 
        {"priority", required_argument, 0, 'p'},
674
665
        {0, 0, 0, 0} };
675
666
      
676
667
      int option_index = 0;
699
690
      case 'k':
700
691
        certkey = optarg;
701
692
        break;
702
 
      case 'D':
703
 
        {
704
 
          long int tmp;
705
 
          errno = 0;
706
 
          tmp = strtol(optarg, NULL, 10);
707
 
          if (errno == ERANGE){
708
 
            perror("strtol");
709
 
            exit(EXIT_FAILURE);
710
 
          }
711
 
          mc.dh_bits = tmp;
712
 
        }
713
 
        break;
714
 
      case 'p':
715
 
        mc.priority = optarg;
716
 
        break;
717
693
      default:
718
694
        exit(EXIT_FAILURE);
719
695
      }
720
696
    }
721
 
    
 
697
 
722
698
    certfile = combinepath(certdir, certfile);
723
699
    if (certfile == NULL){
724
 
      perror("combinepath");
725
 
      returncode = EXIT_FAILURE;
726
 
      goto exit;
727
 
    }
728
 
 
729
 
    certkey = combinepath(certdir, certkey);
730
 
    if (certkey == NULL){
731
 
      perror("combinepath");
732
 
      returncode = EXIT_FAILURE;
733
700
      goto exit;
734
701
    }
735
702
    
736
 
    if_index = (AvahiIfIndex) if_nametoindex(interface);
737
 
    if(if_index == 0){
738
 
      fprintf(stderr, "No such interface: \"%s\"\n", interface);
739
 
      exit(EXIT_FAILURE);
 
703
    if(interface != NULL){
 
704
      if_index = (AvahiIfIndex) if_nametoindex(interface);
 
705
      if(if_index == 0){
 
706
        fprintf(stderr, "No such interface: \"%s\"\n", interface);
 
707
        exit(EXIT_FAILURE);
 
708
      }
740
709
    }
741
710
    
742
711
    if(connect_to != NULL){
763
732
      }
764
733
    }
765
734
    
766
 
    sd = socket(PF_INET6, SOCK_DGRAM, IPPROTO_IP);
767
 
    if(sd < 0) {
768
 
      perror("socket");
769
 
      returncode = EXIT_FAILURE;
770
 
      goto exit;
771
 
    }
772
 
    strcpy(network.ifr_name, interface);    
773
 
    ret = ioctl(sd, SIOCGIFFLAGS, &network);
774
 
    if(ret == -1){
775
 
      
776
 
      perror("ioctl SIOCGIFFLAGS");
777
 
      returncode = EXIT_FAILURE;
778
 
      goto exit;
779
 
    }
780
 
    if((network.ifr_flags & IFF_UP) == 0){
781
 
      network.ifr_flags |= IFF_UP;
782
 
      ret = ioctl(sd, SIOCSIFFLAGS, &network);
783
 
      if(ret == -1){
784
 
        perror("ioctl SIOCSIFFLAGS");
785
 
        returncode = EXIT_FAILURE;
786
 
        goto exit;
787
 
      }
788
 
    }
789
 
    close(sd);
 
735
    certkey = combinepath(certdir, certkey);
 
736
    if (certkey == NULL){
 
737
      goto exit;
 
738
    }
790
739
    
791
740
    if (not debug){
792
741
      avahi_set_log_function(empty_log);
796
745
    srand((unsigned int) time(NULL));
797
746
 
798
747
    /* Allocate main loop object */
799
 
    if (!(mc.simple_poll = avahi_simple_poll_new())) {
 
748
    if (!(simple_poll = avahi_simple_poll_new())) {
800
749
        fprintf(stderr, "Failed to create simple poll object.\n");
801
 
        returncode = EXIT_FAILURE;      
 
750
        
802
751
        goto exit;
803
752
    }
804
753
 
810
759
    config.publish_domain = 0;
811
760
 
812
761
    /* Allocate a new server */
813
 
    mc.server = avahi_server_new(avahi_simple_poll_get(simple_poll),
 
762
    server = avahi_server_new(avahi_simple_poll_get(simple_poll),
814
763
                              &config, NULL, NULL, &error);
815
764
 
816
765
    /* Free the configuration data */
817
766
    avahi_server_config_free(&config);
818
767
 
819
768
    /* Check if creating the server object succeeded */
820
 
    if (!mc.server) {
 
769
    if (!server) {
821
770
        fprintf(stderr, "Failed to create server: %s\n",
822
771
                avahi_strerror(error));
823
772
        returncode = EXIT_FAILURE;
825
774
    }
826
775
    
827
776
    /* Create the service browser */
828
 
    sb = avahi_s_service_browser_new(mc.server, if_index,
 
777
    sb = avahi_s_service_browser_new(server, if_index,
829
778
                                     AVAHI_PROTO_INET6,
830
779
                                     "_mandos._tcp", NULL, 0,
831
 
                                     browse_callback, &mc);
 
780
                                     browse_callback, server);
832
781
    if (!sb) {
833
782
        fprintf(stderr, "Failed to create service browser: %s\n",
834
 
                avahi_strerror(avahi_server_errno(mc.server)));
 
783
                avahi_strerror(avahi_server_errno(server)));
835
784
        returncode = EXIT_FAILURE;
836
785
        goto exit;
837
786
    }
854
803
    if (sb)
855
804
        avahi_s_service_browser_free(sb);
856
805
    
857
 
    if (mc.server)
858
 
        avahi_server_free(mc.server);
 
806
    if (server)
 
807
        avahi_server_free(server);
859
808
 
860
809
    if (simple_poll)
861
810
        avahi_simple_poll_free(simple_poll);