/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:
214
214
    fprintf(stderr, "bad gpgme_op_decrypt: %s: %s\n",
215
215
            gpgme_strsource(rc), gpgme_strerror(rc));
216
216
    plaintext_length = -1;
217
 
    if (debug){
218
 
      gpgme_decrypt_result_t result;
219
 
      result = gpgme_op_decrypt_result(ctx);
220
 
      if (result == NULL){
221
 
        fprintf(stderr, "gpgme_op_decrypt_result failed\n");
222
 
      } else {
223
 
        fprintf(stderr, "Unsupported algorithm: %s\n",
224
 
                result->unsupported_algorithm);
225
 
        fprintf(stderr, "Wrong key usage: %u\n",
226
 
                result->wrong_key_usage);
227
 
        if(result->file_name != NULL){
228
 
          fprintf(stderr, "File name: %s\n", result->file_name);
229
 
        }
230
 
        gpgme_recipient_t recipient;
231
 
        recipient = result->recipients;
232
 
        if(recipient){
233
 
          while(recipient != NULL){
234
 
            fprintf(stderr, "Public key algorithm: %s\n",
235
 
                    gpgme_pubkey_algo_name(recipient->pubkey_algo));
236
 
            fprintf(stderr, "Key ID: %s\n", recipient->keyid);
237
 
            fprintf(stderr, "Secret key available: %s\n",
238
 
                    recipient->status == GPG_ERR_NO_SECKEY
239
 
                    ? "No" : "Yes");
240
 
            recipient = recipient->next;
241
 
          }
242
 
        }
243
 
      }
244
 
    }
245
217
    goto decrypt_end;
246
218
  }
247
219
  
249
221
    fprintf(stderr, "Decryption of OpenPGP data succeeded\n");
250
222
  }
251
223
  
 
224
  if (debug){
 
225
    gpgme_decrypt_result_t result;
 
226
    result = gpgme_op_decrypt_result(ctx);
 
227
    if (result == NULL){
 
228
      fprintf(stderr, "gpgme_op_decrypt_result failed\n");
 
229
    } else {
 
230
      fprintf(stderr, "Unsupported algorithm: %s\n",
 
231
              result->unsupported_algorithm);
 
232
      fprintf(stderr, "Wrong key usage: %u\n",
 
233
              result->wrong_key_usage);
 
234
      if(result->file_name != NULL){
 
235
        fprintf(stderr, "File name: %s\n", result->file_name);
 
236
      }
 
237
      gpgme_recipient_t recipient;
 
238
      recipient = result->recipients;
 
239
      if(recipient){
 
240
        while(recipient != NULL){
 
241
          fprintf(stderr, "Public key algorithm: %s\n",
 
242
                  gpgme_pubkey_algo_name(recipient->pubkey_algo));
 
243
          fprintf(stderr, "Key ID: %s\n", recipient->keyid);
 
244
          fprintf(stderr, "Secret key available: %s\n",
 
245
                  recipient->status == GPG_ERR_NO_SECKEY
 
246
                  ? "No" : "Yes");
 
247
          recipient = recipient->next;
 
248
        }
 
249
      }
 
250
    }
 
251
  }
 
252
  
252
253
  /* Seek back to the beginning of the GPGME plaintext data buffer */
253
254
  if (gpgme_data_seek(dh_plain, (off_t) 0, SEEK_SET) == -1){
254
255
    perror("pgpme_data_seek");
281
282
    }
282
283
    plaintext_length += ret;
283
284
  }
284
 
  
 
285
 
285
286
  if(debug){
286
287
    fprintf(stderr, "Decrypted password is: ");
287
288
    for(ssize_t i = 0; i < plaintext_length; i++){
301
302
}
302
303
 
303
304
static const char * safer_gnutls_strerror (int value) {
304
 
  const char *ret = gnutls_strerror (value); /* Spurious warning */
 
305
  const char *ret = gnutls_strerror (value);
305
306
  if (ret == NULL)
306
307
    ret = "(unknown)";
307
308
  return ret;
340
341
  /* OpenPGP credentials */
341
342
  gnutls_certificate_allocate_credentials(&mc->cred);
342
343
  if (ret != GNUTLS_E_SUCCESS){
343
 
    fprintf (stderr, "GnuTLS memory error: %s\n", /* Spurious
344
 
                                                     warning */
 
344
    fprintf (stderr, "GnuTLS memory error: %s\n",
345
345
             safer_gnutls_strerror(ret));
346
346
    gnutls_global_deinit ();
347
347
    return -1;
380
380
  }
381
381
  
382
382
  gnutls_certificate_set_dh_params(mc->cred, mc->dh_params);
383
 
  
 
383
 
384
384
  return 0;
385
 
  
 
385
 
386
386
 globalfail:
387
 
  
 
387
 
388
388
  gnutls_certificate_free_credentials(mc->cred);
389
389
  gnutls_global_deinit();
390
390
  return -1;
 
391
 
391
392
}
392
393
 
393
394
static int init_gnutls_session(mandos_context *mc,
465
466
    perror("socket");
466
467
    return -1;
467
468
  }
468
 
  
 
469
 
469
470
  if(debug){
470
471
    if(if_indextoname((unsigned int)if_index, interface) == NULL){
471
472
      perror("if_indextoname");
474
475
    fprintf(stderr, "Binding to interface %s\n", interface);
475
476
  }
476
477
  
477
 
  memset(&to, 0, sizeof(to));
 
478
  memset(&to, 0, sizeof(to));   /* Spurious warning */
478
479
  to.in6.sin6_family = AF_INET6;
479
480
  /* It would be nice to have a way to detect if we were passed an
480
481
     IPv4 address here.   Now we assume an IPv6 address. */
510
511
    perror("connect");
511
512
    return -1;
512
513
  }
513
 
  
 
514
 
514
515
  const char *out = mandos_protocol_version;
515
516
  written = 0;
516
517
  while (true){
534
535
      }
535
536
    }
536
537
  }
537
 
  
 
538
 
538
539
  if(debug){
539
540
    fprintf(stderr, "Establishing TLS session with %s\n", ip);
540
541
  }
541
542
  
542
543
  gnutls_transport_set_ptr (session, (gnutls_transport_ptr_t) tcp_sd);
543
 
  
 
544
 
544
545
  do{
545
546
    ret = gnutls_handshake (session);
546
547
  } while(ret == GNUTLS_E_AGAIN or ret == GNUTLS_E_INTERRUPTED);
560
561
    fprintf(stderr, "Retrieving pgp encrypted password from %s\n",
561
562
            ip);
562
563
  }
563
 
  
 
564
 
564
565
  while(true){
565
566
    buffer_capacity = adjustbuffer(&buffer, buffer_length,
566
567
                                   buffer_capacity);
634
635
    } else {
635
636
      retval = -1;
636
637
    }
637
 
  } else {
638
 
    retval = -1;
639
638
  }
640
639
  
641
640
  /* Shutdown procedure */
662
661
                             flags,
663
662
                             void* userdata) {
664
663
  mandos_context *mc = userdata;
665
 
  assert(r);
 
664
  assert(r);                    /* Spurious warning */
666
665
  
667
666
  /* Called whenever a service has been resolved successfully or
668
667
     timed out */
704
703
                             flags,
705
704
                             void* userdata) {
706
705
  mandos_context *mc = userdata;
707
 
  assert(b);
 
706
  assert(b);                    /* Spurious warning */
708
707
  
709
708
  /* Called whenever a new services becomes available on the LAN or
710
709
     is removed from the LAN */
773
772
    const char *pubkeyname = "pubkey.txt";
774
773
    const char *seckeyname = "seckey.txt";
775
774
    mandos_context mc = { .simple_poll = NULL, .server = NULL,
776
 
                          .dh_bits = 1024, .priority = "SECURE256"
777
 
                          ":!CTYPE-X.509:+CTYPE-OPENPGP" };
 
775
                          .dh_bits = 1024, .priority = "SECURE256"};
778
776
    bool gnutls_initalized = false;
779
777
    
780
778
    {
782
780
        { .name = "debug", .key = 128,
783
781
          .doc = "Debug mode", .group = 3 },
784
782
        { .name = "connect", .key = 'c',
785
 
          .arg = "ADDRESS:PORT",
786
 
          .doc = "Connect directly to a specific Mandos server",
 
783
          .arg = "IP",
 
784
          .doc = "Connect directly to a sepcified mandos server",
787
785
          .group = 1 },
788
786
        { .name = "interface", .key = 'i',
789
 
          .arg = "NAME",
790
 
          .doc = "Interface that will be used to search for Mandos"
791
 
          " servers",
 
787
          .arg = "INTERFACE",
 
788
          .doc = "Interface that Avahi will conntect through",
792
789
          .group = 1 },
793
790
        { .name = "keydir", .key = 'd',
794
 
          .arg = "DIRECTORY",
795
 
          .doc = "Directory to read the OpenPGP key files from",
 
791
          .arg = "KEYDIR",
 
792
          .doc = "Directory where the openpgp keyring is",
796
793
          .group = 1 },
797
794
        { .name = "seckey", .key = 's',
798
 
          .arg = "FILE",
799
 
          .doc = "OpenPGP secret key file base name",
 
795
          .arg = "SECKEY",
 
796
          .doc = "Secret openpgp key for gnutls authentication",
800
797
          .group = 1 },
801
798
        { .name = "pubkey", .key = 'p',
802
 
          .arg = "FILE",
803
 
          .doc = "OpenPGP public key file base name",
 
799
          .arg = "PUBKEY",
 
800
          .doc = "Public openpgp key for gnutls authentication",
804
801
          .group = 2 },
805
802
        { .name = "dh-bits", .key = 129,
806
803
          .arg = "BITS",
807
 
          .doc = "Bit length of the prime number used in the"
808
 
          " Diffie-Hellman key exchange",
 
804
          .doc = "dh-bits to use in gnutls communication",
809
805
          .group = 2 },
810
806
        { .name = "priority", .key = 130,
811
 
          .arg = "STRING",
812
 
          .doc = "GnuTLS priority string for the TLS handshake",
813
 
          .group = 1 },
 
807
          .arg = "PRIORITY",
 
808
          .doc = "GNUTLS priority", .group = 1 },
814
809
        { .name = NULL }
815
810
      };
 
811
 
816
812
      
817
813
      error_t parse_opt (int key, char *arg,
818
814
                         struct argp_state *state) {
819
815
        /* Get the INPUT argument from `argp_parse', which we know is
820
816
           a pointer to our plugin list pointer. */
821
817
        switch (key) {
822
 
        case 128:               /* --debug */
 
818
        case 128:
823
819
          debug = true;
824
820
          break;
825
 
        case 'c':               /* --connect */
 
821
        case 'c':
826
822
          connect_to = arg;
827
823
          break;
828
 
        case 'i':               /* --interface */
 
824
        case 'i':
829
825
          interface = arg;
830
826
          break;
831
 
        case 'd':               /* --keydir */
 
827
        case 'd':
832
828
          keydir = arg;
833
829
          break;
834
 
        case 's':               /* --seckey */
 
830
        case 's':
835
831
          seckeyname = arg;
836
832
          break;
837
 
        case 'p':               /* --pubkey */
 
833
        case 'p':
838
834
          pubkeyname = arg;
839
835
          break;
840
 
        case 129:               /* --dh-bits */
 
836
        case 129:
841
837
          errno = 0;
842
838
          mc.dh_bits = (unsigned int) strtol(arg, NULL, 10);
843
839
          if (errno){
845
841
            exit(EXIT_FAILURE);
846
842
          }
847
843
          break;
848
 
        case 130:               /* --priority */
 
844
        case 130:
849
845
          mc.priority = arg;
850
846
          break;
851
847
        case ARGP_KEY_ARG:
857
853
        }
858
854
        return 0;
859
855
      }
860
 
      
 
856
 
861
857
      struct argp argp = { .options = options, .parser = parse_opt,
862
858
                           .args_doc = "",
863
859
                           .doc = "Mandos client -- Get and decrypt"
864
 
                           " passwords from a Mandos server" };
 
860
                           " passwords from mandos server" };
865
861
      ret = argp_parse (&argp, argc, argv, 0, 0, NULL);
866
862
      if (ret == ARGP_ERR_UNKNOWN){
867
863
        fprintf(stderr, "Unknown error while parsing arguments\n");
869
865
        goto end;
870
866
      }
871
867
    }
872
 
    
 
868
      
873
869
    pubkeyfilename = combinepath(keydir, pubkeyname);
874
870
    if (pubkeyfilename == NULL){
875
871
      perror("combinepath");
883
879
      exitcode = EXIT_FAILURE;
884
880
      goto end;
885
881
    }
886
 
    
 
882
 
887
883
    ret = init_gnutls_global(&mc, pubkeyfilename, seckeyfilename);
888
884
    if (ret == -1){
889
885
      fprintf(stderr, "init_gnutls_global failed\n");
901
897
        exitcode = EXIT_FAILURE;
902
898
        goto end;
903
899
      }
904
 
      strcpy(network.ifr_name, interface);
 
900
      strcpy(network.ifr_name, interface); /* Spurious warning */
905
901
      ret = ioctl(sd, SIOCGIFFLAGS, &network);
906
902
      if(ret == -1){
907
903
        perror("ioctl SIOCGIFFLAGS");
981
977
        exitcode = EXIT_FAILURE;
982
978
        goto end;
983
979
    }
984
 
    
 
980
 
985
981
    {
986
982
      AvahiServerConfig config;
987
983
      /* Do not publish any local Zeroconf records */
990
986
      config.publish_addresses = 0;
991
987
      config.publish_workstation = 0;
992
988
      config.publish_domain = 0;
993
 
      
 
989
 
994
990
      /* Allocate a new server */
995
991
      mc.server = avahi_server_new(avahi_simple_poll_get
996
992
                                   (mc.simple_poll), &config, NULL,
997
993
                                   NULL, &error);
998
 
      
 
994
    
999
995
      /* Free the Avahi configuration data */
1000
996
      avahi_server_config_free(&config);
1001
997
    }
1021
1017
    }
1022
1018
    
1023
1019
    /* Run the main loop */
1024
 
    
 
1020
 
1025
1021
    if (debug){
1026
1022
      fprintf(stderr, "Starting Avahi loop search\n");
1027
1023
    }
1029
1025
    avahi_simple_poll_loop(mc.simple_poll);
1030
1026
    
1031
1027
 end:
1032
 
    
 
1028
 
1033
1029
    if (debug){
1034
1030
      fprintf(stderr, "%s exiting\n", argv[0]);
1035
1031
    }
1040
1036
    
1041
1037
    if (mc.server != NULL)
1042
1038
        avahi_server_free(mc.server);
1043
 
    
 
1039
 
1044
1040
    if (mc.simple_poll != NULL)
1045
1041
        avahi_simple_poll_free(mc.simple_poll);
1046
1042
    free(pubkeyfilename);
1047
1043
    free(seckeyfilename);
1048
 
    
 
1044
 
1049
1045
    if (gnutls_initalized){
1050
1046
      gnutls_certificate_free_credentials(mc.cred);
1051
1047
      gnutls_global_deinit ();