/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/password-request.c

  • Committer: Teddy Hogeborn
  • Date: 2008-08-16 03:29:08 UTC
  • Revision ID: teddy@fukt.bsnet.se-20080816032908-ihw7c05r2mnyk389
Add feature to specify custom environment variables for plugins.

* plugin-runner.c (plugin): New members "environ" and "envc" to
                            contain possible custom environment.
  (getplugin): Return NULL on failure instead of doing exit(); all
               callers changed.
  (add_to_char_array): New helper function for "add_argument" and
                       "add_environment".
  (addargument): Renamed to "add_argument".  Return bool.  Call
                 "add_to_char_array" to actually do things.
  (add_environment): New; analogous to "add_argument".
  (addcustomargument): Renamed to "add_to_argv" to avoid confusion
                       with "add_argument".
  (main): New options "--global-envs" and "--envs-for" to specify
          custom environment for plugins.  Print environment for
          plugins in debug mode.  Use asprintf instead of strcpy and
          strcat.  Use execve() for plugins with custom environments.
          Free environment for plugin when freeing plugin list.

Show diffs side-by-side

added added

removed removed

Lines of Context:
32
32
#define _LARGEFILE_SOURCE
33
33
#define _FILE_OFFSET_BITS 64
34
34
 
35
 
#define _GNU_SOURCE             /* TEMP_FAILURE_RETRY() */
 
35
#define _GNU_SOURCE             /* TEMP_FAILURE_RETRY(), asprintf() */
36
36
 
37
 
#include <stdio.h>
38
 
#include <assert.h>
39
 
#include <stdlib.h>
40
 
#include <time.h>
41
 
#include <net/if.h>             /* if_nametoindex */
42
 
#include <sys/ioctl.h>          /* ioctl, ifreq, SIOCGIFFLAGS, IFF_UP,
43
 
                                   SIOCSIFFLAGS */
 
37
#include <stdio.h>              /* fprintf(), stderr, fwrite(),
 
38
                                   stdout, ferror() */
 
39
#include <stdint.h>             /* uint16_t, uint32_t */
 
40
#include <stddef.h>             /* NULL, size_t, ssize_t */
 
41
#include <stdlib.h>             /* free(), EXIT_SUCCESS, EXIT_FAILURE,
 
42
                                   srand() */
 
43
#include <stdbool.h>            /* bool, true */
 
44
#include <string.h>             /* memset(), strcmp(), strlen(),
 
45
                                   strerror(), asprintf(), strcpy() */
 
46
#include <sys/ioctl.h>          /* ioctl */
 
47
#include <sys/types.h>          /* socket(), inet_pton(), sockaddr,
 
48
                                   sockaddr_in6, PF_INET6,
 
49
                                   SOCK_STREAM, INET6_ADDRSTRLEN,
 
50
                                   uid_t, gid_t */
 
51
#include <inttypes.h>           /* PRIu16 */
 
52
#include <sys/socket.h>         /* socket(), struct sockaddr_in6,
 
53
                                   struct in6_addr, inet_pton(),
 
54
                                   connect() */
 
55
#include <assert.h>             /* assert() */
 
56
#include <errno.h>              /* perror(), errno */
 
57
#include <time.h>               /* time() */
44
58
#include <net/if.h>             /* ioctl, ifreq, SIOCGIFFLAGS, IFF_UP,
45
 
                                   SIOCSIFFLAGS */
 
59
                                   SIOCSIFFLAGS, if_indextoname(),
 
60
                                   if_nametoindex(), IF_NAMESIZE */
 
61
#include <unistd.h>             /* close(), SEEK_SET, off_t, write(),
 
62
                                   getuid(), getgid(), setuid(),
 
63
                                   setgid() */
 
64
#include <netinet/in.h>
 
65
#include <arpa/inet.h>          /* inet_pton(), htons */
 
66
#include <iso646.h>             /* not, and */
 
67
#include <argp.h>               /* struct argp_option, error_t, struct
 
68
                                   argp_state, struct argp,
 
69
                                   argp_parse(), ARGP_KEY_ARG,
 
70
                                   ARGP_KEY_END, ARGP_ERR_UNKNOWN */
46
71
 
 
72
/* Avahi */
 
73
/* All Avahi types, constants and functions
 
74
 Avahi*, avahi_*,
 
75
 AVAHI_* */
47
76
#include <avahi-core/core.h>
48
77
#include <avahi-core/lookup.h>
49
78
#include <avahi-core/log.h>
51
80
#include <avahi-common/malloc.h>
52
81
#include <avahi-common/error.h>
53
82
 
54
 
/* Mandos client part */
55
 
#include <sys/types.h>          /* socket(), inet_pton() */
56
 
#include <sys/socket.h>         /* socket(), struct sockaddr_in6,
57
 
                                   struct in6_addr, inet_pton() */
58
 
#include <gnutls/gnutls.h>      /* All GnuTLS stuff */
59
 
#include <gnutls/openpgp.h>     /* GnuTLS with openpgp stuff */
 
83
/* GnuTLS */
 
84
#include <gnutls/gnutls.h>      /* All GnuTLS types, constants and
 
85
                                   functions:
 
86
                                   gnutls_*
 
87
                                   init_gnutls_session(),
 
88
                                   GNUTLS_* */
 
89
#include <gnutls/openpgp.h>     /* gnutls_certificate_set_openpgp_key_file(),
 
90
                                   GNUTLS_OPENPGP_FMT_BASE64 */
60
91
 
61
 
#include <unistd.h>             /* close() */
62
 
#include <netinet/in.h>
63
 
#include <stdbool.h>            /* true */
64
 
#include <string.h>             /* memset */
65
 
#include <arpa/inet.h>          /* inet_pton() */
66
 
#include <iso646.h>             /* not */
67
 
#include <net/if.h>             /* IF_NAMESIZE */
68
 
#include <argp.h>               /* struct argp_option,
69
 
                                   struct argp_state, struct argp,
70
 
                                   argp_parse() */
71
92
/* GPGME */
72
 
#include <errno.h>              /* perror() */
73
 
#include <gpgme.h>
 
93
#include <gpgme.h>              /* All GPGME types, constants and
 
94
                                   functions:
 
95
                                   gpgme_*
 
96
                                   GPGME_PROTOCOL_OpenPGP,
 
97
                                   GPG_ERR_NO_* */
74
98
 
75
99
#define BUFFER_SIZE 256
76
100
 
77
101
bool debug = false;
78
102
static const char *keydir = "/conf/conf.d/mandos";
79
103
static const char mandos_protocol_version[] = "1";
80
 
const char *argp_program_version = "mandosclient 0.9";
 
104
const char *argp_program_version = "password-request 1.0";
81
105
const char *argp_program_bug_address = "<mandos@fukt.bsnet.se>";
82
106
 
83
107
/* Used for passing in values through the Avahi callback functions */
205
229
    } else {
206
230
      fprintf(stderr, "Unsupported algorithm: %s\n",
207
231
              result->unsupported_algorithm);
208
 
      fprintf(stderr, "Wrong key usage: %d\n",
 
232
      fprintf(stderr, "Wrong key usage: %u\n",
209
233
              result->wrong_key_usage);
210
234
      if(result->file_name != NULL){
211
235
        fprintf(stderr, "File name: %s\n", result->file_name);
291
315
}
292
316
 
293
317
static int init_gnutls_global(mandos_context *mc,
294
 
                              const char *pubkeyfile,
295
 
                              const char *seckeyfile){
 
318
                              const char *pubkeyfilename,
 
319
                              const char *seckeyfilename){
296
320
  int ret;
297
321
  
298
322
  if(debug){
299
323
    fprintf(stderr, "Initializing GnuTLS\n");
300
324
  }
301
 
 
302
 
  if ((ret = gnutls_global_init ())
303
 
      != GNUTLS_E_SUCCESS) {
 
325
  
 
326
  ret = gnutls_global_init();
 
327
  if (ret != GNUTLS_E_SUCCESS) {
304
328
    fprintf (stderr, "GnuTLS global_init: %s\n",
305
329
             safer_gnutls_strerror(ret));
306
330
    return -1;
315
339
  }
316
340
  
317
341
  /* OpenPGP credentials */
318
 
  if ((ret = gnutls_certificate_allocate_credentials (&mc->cred))
319
 
      != GNUTLS_E_SUCCESS) {
 
342
  gnutls_certificate_allocate_credentials(&mc->cred);
 
343
  if (ret != GNUTLS_E_SUCCESS){
320
344
    fprintf (stderr, "GnuTLS memory error: %s\n",
321
345
             safer_gnutls_strerror(ret));
322
346
    gnutls_global_deinit ();
325
349
  
326
350
  if(debug){
327
351
    fprintf(stderr, "Attempting to use OpenPGP certificate %s"
328
 
            " and keyfile %s as GnuTLS credentials\n", pubkeyfile,
329
 
            seckeyfile);
 
352
            " and keyfile %s as GnuTLS credentials\n", pubkeyfilename,
 
353
            seckeyfilename);
330
354
  }
331
355
  
332
356
  ret = gnutls_certificate_set_openpgp_key_file
333
 
    (mc->cred, pubkeyfile, seckeyfile, GNUTLS_OPENPGP_FMT_BASE64);
 
357
    (mc->cred, pubkeyfilename, seckeyfilename,
 
358
     GNUTLS_OPENPGP_FMT_BASE64);
334
359
  if (ret != GNUTLS_E_SUCCESS) {
335
360
    fprintf(stderr,
336
361
            "Error[%d] while reading the OpenPGP key pair ('%s',"
337
 
            " '%s')\n", ret, pubkeyfile, seckeyfile);
 
362
            " '%s')\n", ret, pubkeyfilename, seckeyfilename);
338
363
    fprintf(stdout, "The GnuTLS error is: %s\n",
339
364
            safer_gnutls_strerror(ret));
340
365
    goto globalfail;
360
385
 
361
386
 globalfail:
362
387
 
363
 
  gnutls_certificate_free_credentials (mc->cred);
364
 
  gnutls_global_deinit ();
 
388
  gnutls_certificate_free_credentials(mc->cred);
 
389
  gnutls_global_deinit();
365
390
  return -1;
366
391
 
367
392
}
432
457
  }
433
458
  
434
459
  if(debug){
435
 
    fprintf(stderr, "Setting up a tcp connection to %s, port %d\n",
436
 
            ip, port);
 
460
    fprintf(stderr, "Setting up a tcp connection to %s, port %" PRIu16
 
461
            "\n", ip, port);
437
462
  }
438
463
  
439
464
  tcp_sd = socket(PF_INET6, SOCK_STREAM, 0);
450
475
    fprintf(stderr, "Binding to interface %s\n", interface);
451
476
  }
452
477
  
453
 
  memset(&to,0,sizeof(to));     /* Spurious warning */
 
478
  memset(&to, 0, sizeof(to));   /* Spurious warning */
454
479
  to.in6.sin6_family = AF_INET6;
455
480
  /* It would be nice to have a way to detect if we were passed an
456
481
     IPv4 address here.   Now we assume an IPv6 address. */
463
488
    fprintf(stderr, "Bad address: %s\n", ip);
464
489
    return -1;
465
490
  }
466
 
  to.in6.sin6_port = htons(port);       /* Spurious warning */
 
491
  to.in6.sin6_port = htons(port); /* Spurious warning */
467
492
  
468
493
  to.in6.sin6_scope_id = (uint32_t)if_index;
469
494
  
470
495
  if(debug){
471
 
    fprintf(stderr, "Connection to: %s, port %d\n", ip, port);
 
496
    fprintf(stderr, "Connection to: %s, port %" PRIu16 "\n", ip,
 
497
            port);
472
498
    char addrstr[INET6_ADDRSTRLEN] = "";
473
499
    if(inet_ntop(to.in6.sin6_family, &(to.in6.sin6_addr), addrstr,
474
500
                 sizeof(addrstr)) == NULL){
515
541
  }
516
542
  
517
543
  gnutls_transport_set_ptr (session, (gnutls_transport_ptr_t) tcp_sd);
518
 
  
519
 
  ret = gnutls_handshake (session);
 
544
 
 
545
  do{
 
546
    ret = gnutls_handshake (session);
 
547
  } while(ret == GNUTLS_E_AGAIN or ret == GNUTLS_E_INTERRUPTED);
520
548
  
521
549
  if (ret != GNUTLS_E_SUCCESS){
522
550
    if(debug){
554
582
      case GNUTLS_E_AGAIN:
555
583
        break;
556
584
      case GNUTLS_E_REHANDSHAKE:
557
 
        ret = gnutls_handshake (session);
 
585
        do{
 
586
          ret = gnutls_handshake (session);
 
587
        } while(ret == GNUTLS_E_AGAIN or ret == GNUTLS_E_INTERRUPTED);
558
588
        if (ret < 0){
559
589
          fprintf(stderr, "*** GnuTLS Re-handshake failed ***\n");
560
590
          gnutls_perror (ret);
649
679
      char ip[AVAHI_ADDRESS_STR_MAX];
650
680
      avahi_address_snprint(ip, sizeof(ip), address);
651
681
      if(debug){
652
 
        fprintf(stderr, "Mandos server \"%s\" found on %s (%s, %d) on"
653
 
                " port %d\n", name, host_name, ip, interface, port);
 
682
        fprintf(stderr, "Mandos server \"%s\" found on %s (%s, %"
 
683
                PRIu16 ") on port %d\n", name, host_name, ip,
 
684
                interface, port);
654
685
      }
655
686
      int ret = start_mandos_communication(ip, port, interface, mc);
656
687
      if (ret == 0){
657
 
        exit(EXIT_SUCCESS);
 
688
        avahi_simple_poll_quit(mc->simple_poll);
658
689
      }
659
690
    }
660
691
  }
714
745
 
715
746
/* Combines file name and path and returns the malloced new
716
747
   string. some sane checks could/should be added */
717
 
static const char *combinepath(const char *first, const char *second){
718
 
  size_t f_len = strlen(first);
719
 
  size_t s_len = strlen(second);
720
 
  char *tmp = malloc(f_len + s_len + 2);
721
 
  if (tmp == NULL){
 
748
static char *combinepath(const char *first, const char *second){
 
749
  char *tmp;
 
750
  int ret = asprintf(&tmp, "%s/%s", first, second);
 
751
  if(ret < 0){
722
752
    return NULL;
723
753
  }
724
 
  if(f_len > 0){
725
 
    memcpy(tmp, first, f_len);  /* Spurious warning */
726
 
  }
727
 
  tmp[f_len] = '/';
728
 
  if(s_len > 0){
729
 
    memcpy(tmp + f_len + 1, second, s_len); /* Spurious warning */
730
 
  }
731
 
  tmp[f_len + 1 + s_len] = '\0';
732
754
  return tmp;
733
755
}
734
756
 
745
767
    gid_t gid;
746
768
    char *connect_to = NULL;
747
769
    AvahiIfIndex if_index = AVAHI_IF_UNSPEC;
748
 
    const char *pubkeyfile = "pubkey.txt";
749
 
    const char *seckeyfile = "seckey.txt";
 
770
    char *pubkeyfilename = NULL;
 
771
    char *seckeyfilename = NULL;
 
772
    const char *pubkeyname = "pubkey.txt";
 
773
    const char *seckeyname = "seckey.txt";
750
774
    mandos_context mc = { .simple_poll = NULL, .server = NULL,
751
775
                          .dh_bits = 1024, .priority = "SECURE256"};
752
776
    bool gnutls_initalized = false;
804
828
          keydir = arg;
805
829
          break;
806
830
        case 's':
807
 
          seckeyfile = arg;
 
831
          seckeyname = arg;
808
832
          break;
809
833
        case 'p':
810
 
          pubkeyfile = arg;
 
834
          pubkeyname = arg;
811
835
          break;
812
836
        case 129:
813
837
          errno = 0;
822
846
          break;
823
847
        case ARGP_KEY_ARG:
824
848
          argp_usage (state);
 
849
        case ARGP_KEY_END:
825
850
          break;
826
 
          case ARGP_KEY_END:
827
 
            break;
828
851
        default:
829
852
          return ARGP_ERR_UNKNOWN;
830
853
        }
835
858
                           .args_doc = "",
836
859
                           .doc = "Mandos client -- Get and decrypt"
837
860
                           " passwords from mandos server" };
838
 
      argp_parse (&argp, argc, argv, 0, 0, NULL);
 
861
      ret = argp_parse (&argp, argc, argv, 0, 0, NULL);
 
862
      if (ret == ARGP_ERR_UNKNOWN){
 
863
        fprintf(stderr, "Unknown error while parsing arguments\n");
 
864
        exitcode = EXIT_FAILURE;
 
865
        goto end;
 
866
      }
839
867
    }
840
868
      
841
 
    pubkeyfile = combinepath(keydir, pubkeyfile);
842
 
    if (pubkeyfile == NULL){
 
869
    pubkeyfilename = combinepath(keydir, pubkeyname);
 
870
    if (pubkeyfilename == NULL){
843
871
      perror("combinepath");
844
872
      exitcode = EXIT_FAILURE;
845
873
      goto end;
846
874
    }
847
875
    
848
 
    seckeyfile = combinepath(keydir, seckeyfile);
849
 
    if (seckeyfile == NULL){
 
876
    seckeyfilename = combinepath(keydir, seckeyname);
 
877
    if (seckeyfilename == NULL){
850
878
      perror("combinepath");
 
879
      exitcode = EXIT_FAILURE;
851
880
      goto end;
852
881
    }
853
882
 
854
 
    ret = init_gnutls_global(&mc, pubkeyfile, seckeyfile);
 
883
    ret = init_gnutls_global(&mc, pubkeyfilename, seckeyfilename);
855
884
    if (ret == -1){
856
 
      fprintf(stderr, "init_gnutls_global\n");
 
885
      fprintf(stderr, "init_gnutls_global failed\n");
 
886
      exitcode = EXIT_FAILURE;
857
887
      goto end;
858
888
    } else {
859
889
      gnutls_initalized = true;
860
890
    }
861
 
 
 
891
    
 
892
    /* If the interface is down, bring it up */
 
893
    {
 
894
      sd = socket(PF_INET6, SOCK_DGRAM, IPPROTO_IP);
 
895
      if(sd < 0) {
 
896
        perror("socket");
 
897
        exitcode = EXIT_FAILURE;
 
898
        goto end;
 
899
      }
 
900
      strcpy(network.ifr_name, interface); /* Spurious warning */
 
901
      ret = ioctl(sd, SIOCGIFFLAGS, &network);
 
902
      if(ret == -1){
 
903
        perror("ioctl SIOCGIFFLAGS");
 
904
        exitcode = EXIT_FAILURE;
 
905
        goto end;
 
906
      }
 
907
      if((network.ifr_flags & IFF_UP) == 0){
 
908
        network.ifr_flags |= IFF_UP;
 
909
        ret = ioctl(sd, SIOCSIFFLAGS, &network);
 
910
        if(ret == -1){
 
911
          perror("ioctl SIOCSIFFLAGS");
 
912
          exitcode = EXIT_FAILURE;
 
913
          goto end;
 
914
        }
 
915
      }
 
916
      close(sd);
 
917
    }
 
918
    
862
919
    uid = getuid();
863
920
    gid = getgid();
864
 
 
 
921
    
865
922
    ret = setuid(uid);
866
923
    if (ret == -1){
867
924
      perror("setuid");
905
962
      goto end;
906
963
    }
907
964
    
908
 
    /* If the interface is down, bring it up */
909
 
    {
910
 
      sd = socket(PF_INET6, SOCK_DGRAM, IPPROTO_IP);
911
 
      if(sd < 0) {
912
 
        perror("socket");
913
 
        exitcode = EXIT_FAILURE;
914
 
        goto end;
915
 
      }
916
 
      strcpy(network.ifr_name, interface); /* Spurious warning */
917
 
      ret = ioctl(sd, SIOCGIFFLAGS, &network);
918
 
      if(ret == -1){
919
 
        perror("ioctl SIOCGIFFLAGS");
920
 
        exitcode = EXIT_FAILURE;
921
 
        goto end;
922
 
      }
923
 
      if((network.ifr_flags & IFF_UP) == 0){
924
 
        network.ifr_flags |= IFF_UP;
925
 
        ret = ioctl(sd, SIOCSIFFLAGS, &network);
926
 
        if(ret == -1){
927
 
          perror("ioctl SIOCSIFFLAGS");
928
 
          exitcode = EXIT_FAILURE;
929
 
          goto end;
930
 
        }
931
 
      }
932
 
      close(sd);
933
 
    }
934
 
    
935
965
    if (not debug){
936
966
      avahi_set_log_function(empty_log);
937
967
    }
1009
1039
 
1010
1040
    if (mc.simple_poll != NULL)
1011
1041
        avahi_simple_poll_free(mc.simple_poll);
1012
 
    free(pubkeyfile);
1013
 
    free(seckeyfile);
 
1042
    free(pubkeyfilename);
 
1043
    free(seckeyfilename);
1014
1044
 
1015
1045
    if (gnutls_initalized){
1016
 
      gnutls_certificate_free_credentials (mc.cred);
 
1046
      gnutls_certificate_free_credentials(mc.cred);
1017
1047
      gnutls_global_deinit ();
1018
1048
    }
1019
1049