/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/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>              /* fprintf(), stderr, fwrite(), stdout,
38
 
                                   ferror() */
 
37
#include <stdio.h>              /* fprintf(), stderr, fwrite(),
 
38
                                   stdout, ferror() */
39
39
#include <stdint.h>             /* uint16_t, uint32_t */
40
40
#include <stddef.h>             /* NULL, size_t, ssize_t */
41
41
#include <stdlib.h>             /* free(), EXIT_SUCCESS, EXIT_FAILURE,
42
42
                                   srand() */
43
43
#include <stdbool.h>            /* bool, true */
44
44
#include <string.h>             /* memset(), strcmp(), strlen(),
45
 
                                   strerror(), memcpy(), strcpy() */
 
45
                                   strerror(), asprintf(), strcpy() */
46
46
#include <sys/ioctl.h>          /* ioctl */
47
 
#include <net/if.h>             /* ifreq, SIOCGIFFLAGS, SIOCSIFFLAGS,
48
 
                                   IFF_UP */
49
47
#include <sys/types.h>          /* socket(), inet_pton(), sockaddr,
50
48
                                   sockaddr_in6, PF_INET6,
51
49
                                   SOCK_STREAM, INET6_ADDRSTRLEN,
52
50
                                   uid_t, gid_t */
 
51
#include <inttypes.h>           /* PRIu16 */
53
52
#include <sys/socket.h>         /* socket(), struct sockaddr_in6,
54
53
                                   struct in6_addr, inet_pton(),
55
54
                                   connect() */
82
81
#include <avahi-common/error.h>
83
82
 
84
83
/* GnuTLS */
85
 
#include <gnutls/gnutls.h>      /* All GnuTLS types, constants and functions
 
84
#include <gnutls/gnutls.h>      /* All GnuTLS types, constants and
 
85
                                   functions:
86
86
                                   gnutls_*
87
87
                                   init_gnutls_session(),
88
88
                                   GNUTLS_* */
90
90
                                   GNUTLS_OPENPGP_FMT_BASE64 */
91
91
 
92
92
/* GPGME */
93
 
#include <gpgme.h>              /* All GPGME types, constants and functions
 
93
#include <gpgme.h>              /* All GPGME types, constants and
 
94
                                   functions:
94
95
                                   gpgme_*
95
96
                                   GPGME_PROTOCOL_OpenPGP,
96
97
                                   GPG_ERR_NO_* */
228
229
    } else {
229
230
      fprintf(stderr, "Unsupported algorithm: %s\n",
230
231
              result->unsupported_algorithm);
231
 
      fprintf(stderr, "Wrong key usage: %d\n",
 
232
      fprintf(stderr, "Wrong key usage: %u\n",
232
233
              result->wrong_key_usage);
233
234
      if(result->file_name != NULL){
234
235
        fprintf(stderr, "File name: %s\n", result->file_name);
314
315
}
315
316
 
316
317
static int init_gnutls_global(mandos_context *mc,
317
 
                              const char *pubkeyfile,
318
 
                              const char *seckeyfile){
 
318
                              const char *pubkeyfilename,
 
319
                              const char *seckeyfilename){
319
320
  int ret;
320
321
  
321
322
  if(debug){
348
349
  
349
350
  if(debug){
350
351
    fprintf(stderr, "Attempting to use OpenPGP certificate %s"
351
 
            " and keyfile %s as GnuTLS credentials\n", pubkeyfile,
352
 
            seckeyfile);
 
352
            " and keyfile %s as GnuTLS credentials\n", pubkeyfilename,
 
353
            seckeyfilename);
353
354
  }
354
355
  
355
356
  ret = gnutls_certificate_set_openpgp_key_file
356
 
    (mc->cred, pubkeyfile, seckeyfile, GNUTLS_OPENPGP_FMT_BASE64);
 
357
    (mc->cred, pubkeyfilename, seckeyfilename,
 
358
     GNUTLS_OPENPGP_FMT_BASE64);
357
359
  if (ret != GNUTLS_E_SUCCESS) {
358
360
    fprintf(stderr,
359
361
            "Error[%d] while reading the OpenPGP key pair ('%s',"
360
 
            " '%s')\n", ret, pubkeyfile, seckeyfile);
 
362
            " '%s')\n", ret, pubkeyfilename, seckeyfilename);
361
363
    fprintf(stdout, "The GnuTLS error is: %s\n",
362
364
            safer_gnutls_strerror(ret));
363
365
    goto globalfail;
455
457
  }
456
458
  
457
459
  if(debug){
458
 
    fprintf(stderr, "Setting up a tcp connection to %s, port %d\n",
459
 
            ip, port);
 
460
    fprintf(stderr, "Setting up a tcp connection to %s, port %" PRIu16
 
461
            "\n", ip, port);
460
462
  }
461
463
  
462
464
  tcp_sd = socket(PF_INET6, SOCK_STREAM, 0);
473
475
    fprintf(stderr, "Binding to interface %s\n", interface);
474
476
  }
475
477
  
476
 
  memset(&to,0,sizeof(to));     /* Spurious warning */
 
478
  memset(&to, 0, sizeof(to));   /* Spurious warning */
477
479
  to.in6.sin6_family = AF_INET6;
478
480
  /* It would be nice to have a way to detect if we were passed an
479
481
     IPv4 address here.   Now we assume an IPv6 address. */
486
488
    fprintf(stderr, "Bad address: %s\n", ip);
487
489
    return -1;
488
490
  }
489
 
  to.in6.sin6_port = htons(port);       /* Spurious warning */
 
491
  to.in6.sin6_port = htons(port); /* Spurious warning */
490
492
  
491
493
  to.in6.sin6_scope_id = (uint32_t)if_index;
492
494
  
493
495
  if(debug){
494
 
    fprintf(stderr, "Connection to: %s, port %d\n", ip, port);
 
496
    fprintf(stderr, "Connection to: %s, port %" PRIu16 "\n", ip,
 
497
            port);
495
498
    char addrstr[INET6_ADDRSTRLEN] = "";
496
499
    if(inet_ntop(to.in6.sin6_family, &(to.in6.sin6_addr), addrstr,
497
500
                 sizeof(addrstr)) == NULL){
676
679
      char ip[AVAHI_ADDRESS_STR_MAX];
677
680
      avahi_address_snprint(ip, sizeof(ip), address);
678
681
      if(debug){
679
 
        fprintf(stderr, "Mandos server \"%s\" found on %s (%s, %d) on"
680
 
                " 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);
681
685
      }
682
686
      int ret = start_mandos_communication(ip, port, interface, mc);
683
687
      if (ret == 0){
684
 
        exit(EXIT_SUCCESS);
 
688
        avahi_simple_poll_quit(mc->simple_poll);
685
689
      }
686
690
    }
687
691
  }
741
745
 
742
746
/* Combines file name and path and returns the malloced new
743
747
   string. some sane checks could/should be added */
744
 
static const char *combinepath(const char *first, const char *second){
745
 
  size_t f_len = strlen(first);
746
 
  size_t s_len = strlen(second);
747
 
  char *tmp = malloc(f_len + s_len + 2);
748
 
  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){
749
752
    return NULL;
750
753
  }
751
 
  if(f_len > 0){
752
 
    memcpy(tmp, first, f_len);  /* Spurious warning */
753
 
  }
754
 
  tmp[f_len] = '/';
755
 
  if(s_len > 0){
756
 
    memcpy(tmp + f_len + 1, second, s_len); /* Spurious warning */
757
 
  }
758
 
  tmp[f_len + 1 + s_len] = '\0';
759
754
  return tmp;
760
755
}
761
756
 
772
767
    gid_t gid;
773
768
    char *connect_to = NULL;
774
769
    AvahiIfIndex if_index = AVAHI_IF_UNSPEC;
775
 
    const char *pubkeyfile = "pubkey.txt";
776
 
    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";
777
774
    mandos_context mc = { .simple_poll = NULL, .server = NULL,
778
775
                          .dh_bits = 1024, .priority = "SECURE256"};
779
776
    bool gnutls_initalized = false;
831
828
          keydir = arg;
832
829
          break;
833
830
        case 's':
834
 
          seckeyfile = arg;
 
831
          seckeyname = arg;
835
832
          break;
836
833
        case 'p':
837
 
          pubkeyfile = arg;
 
834
          pubkeyname = arg;
838
835
          break;
839
836
        case 129:
840
837
          errno = 0;
849
846
          break;
850
847
        case ARGP_KEY_ARG:
851
848
          argp_usage (state);
 
849
        case ARGP_KEY_END:
852
850
          break;
853
 
          case ARGP_KEY_END:
854
 
            break;
855
851
        default:
856
852
          return ARGP_ERR_UNKNOWN;
857
853
        }
864
860
                           " passwords from mandos server" };
865
861
      ret = argp_parse (&argp, argc, argv, 0, 0, NULL);
866
862
      if (ret == ARGP_ERR_UNKNOWN){
867
 
        fprintf(stderr, "Unkown error while parsing arguments\n");
 
863
        fprintf(stderr, "Unknown error while parsing arguments\n");
868
864
        exitcode = EXIT_FAILURE;
869
865
        goto end;
870
866
      }
871
867
    }
872
868
      
873
 
    pubkeyfile = combinepath(keydir, pubkeyfile);
874
 
    if (pubkeyfile == NULL){
 
869
    pubkeyfilename = combinepath(keydir, pubkeyname);
 
870
    if (pubkeyfilename == NULL){
875
871
      perror("combinepath");
876
872
      exitcode = EXIT_FAILURE;
877
873
      goto end;
878
874
    }
879
875
    
880
 
    seckeyfile = combinepath(keydir, seckeyfile);
881
 
    if (seckeyfile == NULL){
 
876
    seckeyfilename = combinepath(keydir, seckeyname);
 
877
    if (seckeyfilename == NULL){
882
878
      perror("combinepath");
 
879
      exitcode = EXIT_FAILURE;
883
880
      goto end;
884
881
    }
885
882
 
886
 
    ret = init_gnutls_global(&mc, pubkeyfile, seckeyfile);
 
883
    ret = init_gnutls_global(&mc, pubkeyfilename, seckeyfilename);
887
884
    if (ret == -1){
888
 
      fprintf(stderr, "init_gnutls_global\n");
 
885
      fprintf(stderr, "init_gnutls_global failed\n");
 
886
      exitcode = EXIT_FAILURE;
889
887
      goto end;
890
888
    } else {
891
889
      gnutls_initalized = true;
892
890
    }
893
 
 
 
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
    
894
919
    uid = getuid();
895
920
    gid = getgid();
896
 
 
 
921
    
897
922
    ret = setuid(uid);
898
923
    if (ret == -1){
899
924
      perror("setuid");
937
962
      goto end;
938
963
    }
939
964
    
940
 
    /* If the interface is down, bring it up */
941
 
    {
942
 
      sd = socket(PF_INET6, SOCK_DGRAM, IPPROTO_IP);
943
 
      if(sd < 0) {
944
 
        perror("socket");
945
 
        exitcode = EXIT_FAILURE;
946
 
        goto end;
947
 
      }
948
 
      strcpy(network.ifr_name, interface); /* Spurious warning */
949
 
      ret = ioctl(sd, SIOCGIFFLAGS, &network);
950
 
      if(ret == -1){
951
 
        perror("ioctl SIOCGIFFLAGS");
952
 
        exitcode = EXIT_FAILURE;
953
 
        goto end;
954
 
      }
955
 
      if((network.ifr_flags & IFF_UP) == 0){
956
 
        network.ifr_flags |= IFF_UP;
957
 
        ret = ioctl(sd, SIOCSIFFLAGS, &network);
958
 
        if(ret == -1){
959
 
          perror("ioctl SIOCSIFFLAGS");
960
 
          exitcode = EXIT_FAILURE;
961
 
          goto end;
962
 
        }
963
 
      }
964
 
      close(sd);
965
 
    }
966
 
    
967
965
    if (not debug){
968
966
      avahi_set_log_function(empty_log);
969
967
    }
1041
1039
 
1042
1040
    if (mc.simple_poll != NULL)
1043
1041
        avahi_simple_poll_free(mc.simple_poll);
1044
 
    free(pubkeyfile);
1045
 
    free(seckeyfile);
 
1042
    free(pubkeyfilename);
 
1043
    free(seckeyfilename);
1046
1044
 
1047
1045
    if (gnutls_initalized){
1048
1046
      gnutls_certificate_free_credentials(mc.cred);