/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-29 05:53:59 UTC
  • Revision ID: teddy@fukt.bsnet.se-20080829055359-wkdasnyxtylmnxus
* mandos.xml (EXAMPLE): Replaced all occurences of command name with
                        "&COMMANDNAME;".

* plugins.d/password-prompt.c (main): Improved some documentation
                                      strings.  Do perror() of
                                      tcgetattr() fails.  Add debug
                                      output if interrupted by signal.
                                      Loop over write() instead of
                                      using fwrite() when outputting
                                      password.  Add debug output if
                                      getline() returns 0, unless it
                                      was caused by a signal.  Add
                                      exit status code to debug
                                      output.

* plugins.d/password-prompt.xml: Changed all single quotes to double
                                 quotes for consistency.  Removed
                                 <?xml-stylesheet>.
  (ENTITY TIMESTAMP): New.  Automatically updated by Emacs time-stamp
                      by using Emacs local variables.
  (/refentry/refentryinfo/title): Changed to "Mandos Manual".
  (/refentry/refentryinfo/productname): Changed to "Mandos".
  (/refentry/refentryinfo/date): New; set to "&TIMESTAMP;".
  (/refentry/refentryinfo/copyright): Split copyright holders.
  (/refentry/refnamediv/refpurpose): Improved wording.
  (SYNOPSIS): Fix to use correct markup.  Add short options.
  (DESCRIPTION, OPTIONS): Improved wording.
  (OPTIONS): Improved wording.  Use more correct markup.  Document
             short options.
  (EXIT STATUS): Add text.
  (ENVIRONMENT): Document use of "cryptsource" and "crypttarget".
  (FILES): REMOVED.
  (BUGS): Add text.
  (EXAMPLE): Added some examples.
  (SECURITY): Added text.
  (SEE ALSO): Remove reference to mandos(8).  Add reference to
              crypttab(5).

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,
83
81
#include <avahi-common/error.h>
84
82
 
85
83
/* GnuTLS */
86
 
#include <gnutls/gnutls.h>      /* All GnuTLS types, constants and functions
 
84
#include <gnutls/gnutls.h>      /* All GnuTLS types, constants and
 
85
                                   functions:
87
86
                                   gnutls_*
88
87
                                   init_gnutls_session(),
89
88
                                   GNUTLS_* */
91
90
                                   GNUTLS_OPENPGP_FMT_BASE64 */
92
91
 
93
92
/* GPGME */
94
 
#include <gpgme.h>              /* All GPGME types, constants and functions
 
93
#include <gpgme.h>              /* All GPGME types, constants and
 
94
                                   functions:
95
95
                                   gpgme_*
96
96
                                   GPGME_PROTOCOL_OpenPGP,
97
97
                                   GPG_ERR_NO_* */
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
    }
217
245
    goto decrypt_end;
218
246
  }
219
247
  
221
249
    fprintf(stderr, "Decryption of OpenPGP data succeeded\n");
222
250
  }
223
251
  
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
 
  
253
252
  /* Seek back to the beginning of the GPGME plaintext data buffer */
254
253
  if (gpgme_data_seek(dh_plain, (off_t) 0, SEEK_SET) == -1){
255
254
    perror("pgpme_data_seek");
302
301
}
303
302
 
304
303
static const char * safer_gnutls_strerror (int value) {
305
 
  const char *ret = gnutls_strerror (value);
 
304
  const char *ret = gnutls_strerror (value); /* Spurious warning */
306
305
  if (ret == NULL)
307
306
    ret = "(unknown)";
308
307
  return ret;
315
314
}
316
315
 
317
316
static int init_gnutls_global(mandos_context *mc,
318
 
                              const char *pubkeyfile,
319
 
                              const char *seckeyfile){
 
317
                              const char *pubkeyfilename,
 
318
                              const char *seckeyfilename){
320
319
  int ret;
321
320
  
322
321
  if(debug){
341
340
  /* OpenPGP credentials */
342
341
  gnutls_certificate_allocate_credentials(&mc->cred);
343
342
  if (ret != GNUTLS_E_SUCCESS){
344
 
    fprintf (stderr, "GnuTLS memory error: %s\n",
 
343
    fprintf (stderr, "GnuTLS memory error: %s\n", /* Spurious
 
344
                                                     warning */
345
345
             safer_gnutls_strerror(ret));
346
346
    gnutls_global_deinit ();
347
347
    return -1;
349
349
  
350
350
  if(debug){
351
351
    fprintf(stderr, "Attempting to use OpenPGP certificate %s"
352
 
            " and keyfile %s as GnuTLS credentials\n", pubkeyfile,
353
 
            seckeyfile);
 
352
            " and keyfile %s as GnuTLS credentials\n", pubkeyfilename,
 
353
            seckeyfilename);
354
354
  }
355
355
  
356
356
  ret = gnutls_certificate_set_openpgp_key_file
357
 
    (mc->cred, pubkeyfile, seckeyfile, GNUTLS_OPENPGP_FMT_BASE64);
 
357
    (mc->cred, pubkeyfilename, seckeyfilename,
 
358
     GNUTLS_OPENPGP_FMT_BASE64);
358
359
  if (ret != GNUTLS_E_SUCCESS) {
359
360
    fprintf(stderr,
360
361
            "Error[%d] while reading the OpenPGP key pair ('%s',"
361
 
            " '%s')\n", ret, pubkeyfile, seckeyfile);
 
362
            " '%s')\n", ret, pubkeyfilename, seckeyfilename);
362
363
    fprintf(stdout, "The GnuTLS error is: %s\n",
363
364
            safer_gnutls_strerror(ret));
364
365
    goto globalfail;
474
475
    fprintf(stderr, "Binding to interface %s\n", interface);
475
476
  }
476
477
  
477
 
  memset(&to,0,sizeof(to));     /* Spurious warning */
 
478
  memset(&to, 0, sizeof(to));
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. */
487
488
    fprintf(stderr, "Bad address: %s\n", ip);
488
489
    return -1;
489
490
  }
490
 
  to.in6.sin6_port = htons(port);       /* Spurious warning */
 
491
  to.in6.sin6_port = htons(port); /* Spurious warning */
491
492
  
492
493
  to.in6.sin6_scope_id = (uint32_t)if_index;
493
494
  
634
635
    } else {
635
636
      retval = -1;
636
637
    }
 
638
  } else {
 
639
    retval = -1;
637
640
  }
638
641
  
639
642
  /* Shutdown procedure */
660
663
                             flags,
661
664
                             void* userdata) {
662
665
  mandos_context *mc = userdata;
663
 
  assert(r);                    /* Spurious warning */
 
666
  assert(r);
664
667
  
665
668
  /* Called whenever a service has been resolved successfully or
666
669
     timed out */
684
687
      }
685
688
      int ret = start_mandos_communication(ip, port, interface, mc);
686
689
      if (ret == 0){
687
 
        exit(EXIT_SUCCESS);
 
690
        avahi_simple_poll_quit(mc->simple_poll);
688
691
      }
689
692
    }
690
693
  }
702
705
                             flags,
703
706
                             void* userdata) {
704
707
  mandos_context *mc = userdata;
705
 
  assert(b);                    /* Spurious warning */
 
708
  assert(b);
706
709
  
707
710
  /* Called whenever a new services becomes available on the LAN or
708
711
     is removed from the LAN */
744
747
 
745
748
/* Combines file name and path and returns the malloced new
746
749
   string. some sane checks could/should be added */
747
 
static const char *combinepath(const char *first, const char *second){
748
 
  size_t f_len = strlen(first);
749
 
  size_t s_len = strlen(second);
750
 
  char *tmp = malloc(f_len + s_len + 2);
751
 
  if (tmp == NULL){
 
750
static char *combinepath(const char *first, const char *second){
 
751
  char *tmp;
 
752
  int ret = asprintf(&tmp, "%s/%s", first, second);
 
753
  if(ret < 0){
752
754
    return NULL;
753
755
  }
754
 
  if(f_len > 0){
755
 
    memcpy(tmp, first, f_len);  /* Spurious warning */
756
 
  }
757
 
  tmp[f_len] = '/';
758
 
  if(s_len > 0){
759
 
    memcpy(tmp + f_len + 1, second, s_len); /* Spurious warning */
760
 
  }
761
 
  tmp[f_len + 1 + s_len] = '\0';
762
756
  return tmp;
763
757
}
764
758
 
775
769
    gid_t gid;
776
770
    char *connect_to = NULL;
777
771
    AvahiIfIndex if_index = AVAHI_IF_UNSPEC;
778
 
    const char *pubkeyfile = "pubkey.txt";
779
 
    const char *seckeyfile = "seckey.txt";
 
772
    char *pubkeyfilename = NULL;
 
773
    char *seckeyfilename = NULL;
 
774
    const char *pubkeyname = "pubkey.txt";
 
775
    const char *seckeyname = "seckey.txt";
780
776
    mandos_context mc = { .simple_poll = NULL, .server = NULL,
781
777
                          .dh_bits = 1024, .priority = "SECURE256"};
782
778
    bool gnutls_initalized = false;
834
830
          keydir = arg;
835
831
          break;
836
832
        case 's':
837
 
          seckeyfile = arg;
 
833
          seckeyname = arg;
838
834
          break;
839
835
        case 'p':
840
 
          pubkeyfile = arg;
 
836
          pubkeyname = arg;
841
837
          break;
842
838
        case 129:
843
839
          errno = 0;
852
848
          break;
853
849
        case ARGP_KEY_ARG:
854
850
          argp_usage (state);
 
851
        case ARGP_KEY_END:
855
852
          break;
856
 
          case ARGP_KEY_END:
857
 
            break;
858
853
        default:
859
854
          return ARGP_ERR_UNKNOWN;
860
855
        }
867
862
                           " passwords from mandos server" };
868
863
      ret = argp_parse (&argp, argc, argv, 0, 0, NULL);
869
864
      if (ret == ARGP_ERR_UNKNOWN){
870
 
        fprintf(stderr, "Unkown error while parsing arguments\n");
 
865
        fprintf(stderr, "Unknown error while parsing arguments\n");
871
866
        exitcode = EXIT_FAILURE;
872
867
        goto end;
873
868
      }
874
869
    }
875
870
      
876
 
    pubkeyfile = combinepath(keydir, pubkeyfile);
877
 
    if (pubkeyfile == NULL){
 
871
    pubkeyfilename = combinepath(keydir, pubkeyname);
 
872
    if (pubkeyfilename == NULL){
878
873
      perror("combinepath");
879
874
      exitcode = EXIT_FAILURE;
880
875
      goto end;
881
876
    }
882
877
    
883
 
    seckeyfile = combinepath(keydir, seckeyfile);
884
 
    if (seckeyfile == NULL){
 
878
    seckeyfilename = combinepath(keydir, seckeyname);
 
879
    if (seckeyfilename == NULL){
885
880
      perror("combinepath");
 
881
      exitcode = EXIT_FAILURE;
886
882
      goto end;
887
883
    }
888
884
 
889
 
    ret = init_gnutls_global(&mc, pubkeyfile, seckeyfile);
 
885
    ret = init_gnutls_global(&mc, pubkeyfilename, seckeyfilename);
890
886
    if (ret == -1){
891
 
      fprintf(stderr, "init_gnutls_global\n");
 
887
      fprintf(stderr, "init_gnutls_global failed\n");
 
888
      exitcode = EXIT_FAILURE;
892
889
      goto end;
893
890
    } else {
894
891
      gnutls_initalized = true;
895
892
    }
896
 
 
 
893
    
 
894
    /* If the interface is down, bring it up */
 
895
    {
 
896
      sd = socket(PF_INET6, SOCK_DGRAM, IPPROTO_IP);
 
897
      if(sd < 0) {
 
898
        perror("socket");
 
899
        exitcode = EXIT_FAILURE;
 
900
        goto end;
 
901
      }
 
902
      strcpy(network.ifr_name, interface);
 
903
      ret = ioctl(sd, SIOCGIFFLAGS, &network);
 
904
      if(ret == -1){
 
905
        perror("ioctl SIOCGIFFLAGS");
 
906
        exitcode = EXIT_FAILURE;
 
907
        goto end;
 
908
      }
 
909
      if((network.ifr_flags & IFF_UP) == 0){
 
910
        network.ifr_flags |= IFF_UP;
 
911
        ret = ioctl(sd, SIOCSIFFLAGS, &network);
 
912
        if(ret == -1){
 
913
          perror("ioctl SIOCSIFFLAGS");
 
914
          exitcode = EXIT_FAILURE;
 
915
          goto end;
 
916
        }
 
917
      }
 
918
      close(sd);
 
919
    }
 
920
    
897
921
    uid = getuid();
898
922
    gid = getgid();
899
 
 
 
923
    
900
924
    ret = setuid(uid);
901
925
    if (ret == -1){
902
926
      perror("setuid");
940
964
      goto end;
941
965
    }
942
966
    
943
 
    /* If the interface is down, bring it up */
944
 
    {
945
 
      sd = socket(PF_INET6, SOCK_DGRAM, IPPROTO_IP);
946
 
      if(sd < 0) {
947
 
        perror("socket");
948
 
        exitcode = EXIT_FAILURE;
949
 
        goto end;
950
 
      }
951
 
      strcpy(network.ifr_name, interface); /* Spurious warning */
952
 
      ret = ioctl(sd, SIOCGIFFLAGS, &network);
953
 
      if(ret == -1){
954
 
        perror("ioctl SIOCGIFFLAGS");
955
 
        exitcode = EXIT_FAILURE;
956
 
        goto end;
957
 
      }
958
 
      if((network.ifr_flags & IFF_UP) == 0){
959
 
        network.ifr_flags |= IFF_UP;
960
 
        ret = ioctl(sd, SIOCSIFFLAGS, &network);
961
 
        if(ret == -1){
962
 
          perror("ioctl SIOCSIFFLAGS");
963
 
          exitcode = EXIT_FAILURE;
964
 
          goto end;
965
 
        }
966
 
      }
967
 
      close(sd);
968
 
    }
969
 
    
970
967
    if (not debug){
971
968
      avahi_set_log_function(empty_log);
972
969
    }
1044
1041
 
1045
1042
    if (mc.simple_poll != NULL)
1046
1043
        avahi_simple_poll_free(mc.simple_poll);
1047
 
    free(pubkeyfile);
1048
 
    free(seckeyfile);
 
1044
    free(pubkeyfilename);
 
1045
    free(seckeyfilename);
1049
1046
 
1050
1047
    if (gnutls_initalized){
1051
1048
      gnutls_certificate_free_credentials(mc.cred);