/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/mandos-client.c

  • Committer: Teddy Hogeborn
  • Date: 2021-02-01 19:30:45 UTC
  • Revision ID: teddy@recompile.se-20210201193045-lpg6aprpc4srem6k
Fix issue with french translation

Initial white space was missing in both msgid and msgstr of the french
translation, leading to checking tools reporing an incomplete
translation.  The string is a raw command line command, and therefore
did not need translation, so this was never a user-visible issue.

* debian/po/fr.po: Add missing whitespace to the id and translation
  for msgid " mandos-keygen -F/dev/null|grep ^key_id".

Show diffs side-by-side

added added

removed removed

Lines of Context:
9
9
 * "browse_callback", and parts of "main".
10
10
 * 
11
11
 * Everything else is
12
 
 * Copyright © 2008-2018 Teddy Hogeborn
13
 
 * Copyright © 2008-2018 Björn Påhlsson
 
12
 * Copyright © 2008-2020 Teddy Hogeborn
 
13
 * Copyright © 2008-2020 Björn Påhlsson
14
14
 * 
15
15
 * This file is part of Mandos.
16
16
 * 
80
80
#include <unistd.h>             /* close(), SEEK_SET, off_t, write(),
81
81
                                   getuid(), getgid(), seteuid(),
82
82
                                   setgid(), pause(), _exit(),
83
 
                                   unlinkat() */
 
83
                                   unlinkat(), lstat(), symlink() */
84
84
#include <arpa/inet.h>          /* inet_pton(), htons() */
85
85
#include <iso646.h>             /* not, or, and */
86
86
#include <argp.h>               /* struct argp_option, error_t, struct
123
123
                                   gnutls_*
124
124
                                   init_gnutls_session(),
125
125
                                   GNUTLS_* */
 
126
#if GNUTLS_VERSION_NUMBER < 0x030600
126
127
#include <gnutls/openpgp.h>
127
128
                         /* gnutls_certificate_set_openpgp_key_file(),
128
129
                            GNUTLS_OPENPGP_FMT_BASE64 */
 
130
#elif GNUTLS_VERSION_NUMBER >= 0x030606
 
131
#include <gnutls/x509.h>        /* gnutls_pkcs_encrypt_flags_t,
 
132
                                 GNUTLS_PKCS_PLAIN,
 
133
                                 GNUTLS_PKCS_NULL_PASSWORD */
 
134
#endif
129
135
 
130
136
/* GPGME */
131
137
#include <gpgme.h>              /* All GPGME types, constants and
139
145
#define PATHDIR "/conf/conf.d/mandos"
140
146
#define SECKEY "seckey.txt"
141
147
#define PUBKEY "pubkey.txt"
 
148
#define TLS_PRIVKEY "tls-privkey.pem"
 
149
#define TLS_PUBKEY "tls-pubkey.pem"
142
150
#define HOOKDIR "/lib/mandos/network-hooks.d"
143
151
 
144
152
bool debug = false;
272
280
  return true;
273
281
}
274
282
 
 
283
/* Set effective uid to 0, return errno */
 
284
__attribute__((warn_unused_result))
 
285
int raise_privileges(void){
 
286
  int old_errno = errno;
 
287
  int ret = 0;
 
288
  if(seteuid(0) == -1){
 
289
    ret = errno;
 
290
  }
 
291
  errno = old_errno;
 
292
  return ret;
 
293
}
 
294
 
 
295
/* Set effective and real user ID to 0.  Return errno. */
 
296
__attribute__((warn_unused_result))
 
297
int raise_privileges_permanently(void){
 
298
  int old_errno = errno;
 
299
  int ret = raise_privileges();
 
300
  if(ret != 0){
 
301
    errno = old_errno;
 
302
    return ret;
 
303
  }
 
304
  if(setuid(0) == -1){
 
305
    ret = errno;
 
306
  }
 
307
  errno = old_errno;
 
308
  return ret;
 
309
}
 
310
 
 
311
/* Set effective user ID to unprivileged saved user ID */
 
312
__attribute__((warn_unused_result))
 
313
int lower_privileges(void){
 
314
  int old_errno = errno;
 
315
  int ret = 0;
 
316
  if(seteuid(uid) == -1){
 
317
    ret = errno;
 
318
  }
 
319
  errno = old_errno;
 
320
  return ret;
 
321
}
 
322
 
 
323
/* Lower privileges permanently */
 
324
__attribute__((warn_unused_result))
 
325
int lower_privileges_permanently(void){
 
326
  int old_errno = errno;
 
327
  int ret = 0;
 
328
  if(setuid(uid) == -1){
 
329
    ret = errno;
 
330
  }
 
331
  errno = old_errno;
 
332
  return ret;
 
333
}
 
334
 
275
335
/* 
276
336
 * Initialize GPGME.
277
337
 */
297
357
      return false;
298
358
    }
299
359
    
 
360
    /* Workaround for systems without a real-time clock; see also
 
361
       Debian bug #894495: <https://bugs.debian.org/894495> */
 
362
    do {
 
363
      {
 
364
        time_t currtime = time(NULL);
 
365
        if(currtime != (time_t)-1){
 
366
          struct tm tm;
 
367
          if(gmtime_r(&currtime, &tm) == NULL) {
 
368
            perror_plus("gmtime_r");
 
369
            break;
 
370
          }
 
371
          if(tm.tm_year != 70 or tm.tm_mon != 0){
 
372
            break;
 
373
          }
 
374
          if(debug){
 
375
            fprintf_plus(stderr, "System clock is January 1970");
 
376
          }
 
377
        } else {
 
378
          if(debug){
 
379
            fprintf_plus(stderr, "System clock is invalid");
 
380
          }
 
381
        }
 
382
      }
 
383
      struct stat keystat;
 
384
      ret = fstat(fd, &keystat);
 
385
      if(ret != 0){
 
386
        perror_plus("fstat");
 
387
        break;
 
388
      }
 
389
      ret = raise_privileges();
 
390
      if(ret != 0){
 
391
        errno = ret;
 
392
        perror_plus("Failed to raise privileges");
 
393
        break;
 
394
      }
 
395
      if(debug){
 
396
        fprintf_plus(stderr,
 
397
                     "Setting system clock to key file mtime");
 
398
      }
 
399
      if(clock_settime(CLOCK_REALTIME, &keystat.st_mtim) != 0){
 
400
        perror_plus("clock_settime");
 
401
      }
 
402
      ret = lower_privileges();
 
403
      if(ret != 0){
 
404
        errno = ret;
 
405
        perror_plus("Failed to lower privileges");
 
406
      }
 
407
    } while(false);
 
408
 
300
409
    rc = gpgme_data_new_from_fd(&pgp_data, fd);
301
410
    if(rc != GPG_ERR_NO_ERROR){
302
411
      fprintf_plus(stderr, "bad gpgme_data_new_from_fd: %s: %s\n",
597
706
                              const char *dhparamsfilename,
598
707
                              mandos_context *mc){
599
708
  int ret;
600
 
  unsigned int uret;
601
709
  
602
710
  if(debug){
603
711
    fprintf_plus(stderr, "Initializing GnuTLS\n");
620
728
  }
621
729
  
622
730
  if(debug){
623
 
    fprintf_plus(stderr, "Attempting to use OpenPGP public key %s and"
624
 
                 " secret key %s as GnuTLS credentials\n",
 
731
    fprintf_plus(stderr, "Attempting to use public key %s and"
 
732
                 " private key %s as GnuTLS credentials\n",
625
733
                 pubkeyfilename,
626
734
                 seckeyfilename);
627
735
  }
628
736
  
 
737
#if GNUTLS_VERSION_NUMBER >= 0x030606
 
738
  ret = gnutls_certificate_set_rawpk_key_file
 
739
    (mc->cred, pubkeyfilename, seckeyfilename,
 
740
     GNUTLS_X509_FMT_PEM,       /* format */
 
741
     NULL,                      /* pass */
 
742
     /* key_usage */
 
743
     GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT,
 
744
     NULL,                      /* names */
 
745
     0,                         /* names_length */
 
746
     /* privkey_flags */
 
747
     GNUTLS_PKCS_PLAIN | GNUTLS_PKCS_NULL_PASSWORD,
 
748
     0);                        /* pkcs11_flags */
 
749
#elif GNUTLS_VERSION_NUMBER < 0x030600
629
750
  ret = gnutls_certificate_set_openpgp_key_file
630
751
    (mc->cred, pubkeyfilename, seckeyfilename,
631
752
     GNUTLS_OPENPGP_FMT_BASE64);
 
753
#else
 
754
#error "Needs GnuTLS 3.6.6 or later, or before 3.6.0"
 
755
#endif
632
756
  if(ret != GNUTLS_E_SUCCESS){
633
757
    fprintf_plus(stderr,
634
 
                 "Error[%d] while reading the OpenPGP key pair ('%s',"
 
758
                 "Error[%d] while reading the key pair ('%s',"
635
759
                 " '%s')\n", ret, pubkeyfilename, seckeyfilename);
636
760
    fprintf_plus(stderr, "The GnuTLS error is: %s\n",
637
761
                 safer_gnutls_strerror(ret));
708
832
  }
709
833
  if(dhparamsfilename == NULL){
710
834
    if(mc->dh_bits == 0){
 
835
#if GNUTLS_VERSION_NUMBER < 0x030600
711
836
      /* Find out the optimal number of DH bits */
712
837
      /* Try to read the private key file */
713
838
      gnutls_datum_t buffer = { .data = NULL, .size = 0 };
793
918
          }
794
919
        }
795
920
      }
796
 
      uret = gnutls_sec_param_to_pk_bits(GNUTLS_PK_DH, sec_param);
 
921
      unsigned int uret = gnutls_sec_param_to_pk_bits(GNUTLS_PK_DH, sec_param);
797
922
      if(uret != 0){
798
923
        mc->dh_bits = uret;
799
924
        if(debug){
811
936
                     safer_gnutls_strerror(ret));
812
937
        goto globalfail;
813
938
      }
814
 
    } else if(debug){
815
 
      fprintf_plus(stderr, "DH bits explicitly set to %u\n",
816
 
                   mc->dh_bits);
817
 
    }
818
 
    ret = gnutls_dh_params_generate2(mc->dh_params, mc->dh_bits);
819
 
    if(ret != GNUTLS_E_SUCCESS){
820
 
      fprintf_plus(stderr, "Error in GnuTLS prime generation (%u"
821
 
                   " bits): %s\n", mc->dh_bits,
822
 
                   safer_gnutls_strerror(ret));
823
 
      goto globalfail;
 
939
#endif
 
940
    } else {                    /* dh_bits != 0 */
 
941
      if(debug){
 
942
        fprintf_plus(stderr, "DH bits explicitly set to %u\n",
 
943
                     mc->dh_bits);
 
944
      }
 
945
      ret = gnutls_dh_params_generate2(mc->dh_params, mc->dh_bits);
 
946
      if(ret != GNUTLS_E_SUCCESS){
 
947
        fprintf_plus(stderr, "Error in GnuTLS prime generation (%u"
 
948
                     " bits): %s\n", mc->dh_bits,
 
949
                     safer_gnutls_strerror(ret));
 
950
        goto globalfail;
 
951
      }
 
952
      gnutls_certificate_set_dh_params(mc->cred, mc->dh_params);
824
953
    }
825
954
  }
826
 
  gnutls_certificate_set_dh_params(mc->cred, mc->dh_params);
827
955
  
828
956
  return 0;
829
957
  
840
968
  int ret;
841
969
  /* GnuTLS session creation */
842
970
  do {
843
 
    ret = gnutls_init(session, GNUTLS_SERVER);
 
971
    ret = gnutls_init(session, (GNUTLS_SERVER
 
972
#if GNUTLS_VERSION_NUMBER >= 0x030506
 
973
                                | GNUTLS_NO_TICKETS
 
974
#endif
 
975
#if GNUTLS_VERSION_NUMBER >= 0x030606
 
976
                                | GNUTLS_ENABLE_RAWPK
 
977
#endif
 
978
                                ));
844
979
    if(quit_now){
845
980
      return -1;
846
981
    }
894
1029
static void empty_log(__attribute__((unused)) AvahiLogLevel level,
895
1030
                      __attribute__((unused)) const char *txt){}
896
1031
 
897
 
/* Set effective uid to 0, return errno */
898
 
__attribute__((warn_unused_result))
899
 
int raise_privileges(void){
900
 
  int old_errno = errno;
901
 
  int ret = 0;
902
 
  if(seteuid(0) == -1){
903
 
    ret = errno;
904
 
  }
905
 
  errno = old_errno;
906
 
  return ret;
907
 
}
908
 
 
909
 
/* Set effective and real user ID to 0.  Return errno. */
910
 
__attribute__((warn_unused_result))
911
 
int raise_privileges_permanently(void){
912
 
  int old_errno = errno;
913
 
  int ret = raise_privileges();
914
 
  if(ret != 0){
915
 
    errno = old_errno;
916
 
    return ret;
917
 
  }
918
 
  if(setuid(0) == -1){
919
 
    ret = errno;
920
 
  }
921
 
  errno = old_errno;
922
 
  return ret;
923
 
}
924
 
 
925
 
/* Set effective user ID to unprivileged saved user ID */
926
 
__attribute__((warn_unused_result))
927
 
int lower_privileges(void){
928
 
  int old_errno = errno;
929
 
  int ret = 0;
930
 
  if(seteuid(uid) == -1){
931
 
    ret = errno;
932
 
  }
933
 
  errno = old_errno;
934
 
  return ret;
935
 
}
936
 
 
937
 
/* Lower privileges permanently */
938
 
__attribute__((warn_unused_result))
939
 
int lower_privileges_permanently(void){
940
 
  int old_errno = errno;
941
 
  int ret = 0;
942
 
  if(setuid(uid) == -1){
943
 
    ret = errno;
944
 
  }
945
 
  errno = old_errno;
946
 
  return ret;
947
 
}
948
 
 
949
1032
/* Helper function to add_local_route() and delete_local_route() */
950
1033
__attribute__((nonnull, warn_unused_result))
951
1034
static bool add_delete_local_route(const bool add,
990
1073
      ret = setgid(0);
991
1074
      if(ret == -1){
992
1075
        perror_plus("setgid");
 
1076
        close(devnull);
993
1077
        _exit(EX_NOPERM);
994
1078
      }
995
1079
      /* Reset supplementary groups */
997
1081
      ret = setgroups(0, NULL);
998
1082
      if(ret == -1){
999
1083
        perror_plus("setgroups");
 
1084
        close(devnull);
1000
1085
        _exit(EX_NOPERM);
1001
1086
      }
1002
1087
    }
1003
1088
    ret = dup2(devnull, STDIN_FILENO);
1004
1089
    if(ret == -1){
1005
1090
      perror_plus("dup2(devnull, STDIN_FILENO)");
 
1091
      close(devnull);
1006
1092
      _exit(EX_OSERR);
1007
1093
    }
1008
1094
    ret = close(devnull);
1009
1095
    if(ret == -1){
1010
1096
      perror_plus("close");
1011
 
      _exit(EX_OSERR);
1012
1097
    }
1013
1098
    ret = dup2(STDERR_FILENO, STDOUT_FILENO);
1014
1099
    if(ret == -1){
1049
1134
  }
1050
1135
  if(pid == -1){
1051
1136
    perror_plus("fork");
 
1137
    close(devnull);
1052
1138
    return false;
1053
1139
  }
 
1140
  ret = close(devnull);
 
1141
  if(ret == -1){
 
1142
    perror_plus("close");
 
1143
  }
1054
1144
  int status;
1055
1145
  pid_t pret = -1;
1056
1146
  errno = 0;
2377
2467
 
2378
2468
int main(int argc, char *argv[]){
2379
2469
  mandos_context mc = { .server = NULL, .dh_bits = 0,
 
2470
#if GNUTLS_VERSION_NUMBER >= 0x030606
 
2471
                        .priority = "SECURE128:!CTYPE-X.509"
 
2472
                        ":+CTYPE-RAWPK:!RSA:!VERS-ALL:+VERS-TLS1.3"
 
2473
                        ":%PROFILE_ULTRA",
 
2474
#elif GNUTLS_VERSION_NUMBER < 0x030600
2380
2475
                        .priority = "SECURE256:!CTYPE-X.509"
2381
2476
                        ":+CTYPE-OPENPGP:!RSA:+SIGN-DSA-SHA256",
 
2477
#else
 
2478
#error "Needs GnuTLS 3.6.6 or later, or before 3.6.0"
 
2479
#endif
2382
2480
                        .current_server = NULL, .interfaces = NULL,
2383
2481
                        .interfaces_size = 0 };
2384
2482
  AvahiSServiceBrowser *sb = NULL;
2395
2493
  AvahiIfIndex if_index = AVAHI_IF_UNSPEC;
2396
2494
  const char *seckey = PATHDIR "/" SECKEY;
2397
2495
  const char *pubkey = PATHDIR "/" PUBKEY;
 
2496
#if GNUTLS_VERSION_NUMBER >= 0x030606
 
2497
  const char *tls_privkey = PATHDIR "/" TLS_PRIVKEY;
 
2498
  const char *tls_pubkey = PATHDIR "/" TLS_PUBKEY;
 
2499
#endif
2398
2500
  const char *dh_params_file = NULL;
2399
2501
  char *interfaces_hooks = NULL;
2400
2502
  
2448
2550
      { .name = "pubkey", .key = 'p',
2449
2551
        .arg = "FILE",
2450
2552
        .doc = "OpenPGP public key file base name",
2451
 
        .group = 2 },
 
2553
        .group = 1 },
 
2554
      { .name = "tls-privkey", .key = 't',
 
2555
        .arg = "FILE",
 
2556
#if GNUTLS_VERSION_NUMBER >= 0x030606
 
2557
        .doc = "TLS private key file base name",
 
2558
#else
 
2559
        .doc = "Dummy; ignored (requires GnuTLS 3.6.6)",
 
2560
#endif
 
2561
        .group = 1 },
 
2562
      { .name = "tls-pubkey", .key = 'T',
 
2563
        .arg = "FILE",
 
2564
#if GNUTLS_VERSION_NUMBER >= 0x030606
 
2565
        .doc = "TLS public key file base name",
 
2566
#else
 
2567
        .doc = "Dummy; ignored (requires GnuTLS 3.6.6)",
 
2568
#endif
 
2569
        .group = 1 },
2452
2570
      { .name = "dh-bits", .key = 129,
2453
2571
        .arg = "BITS",
2454
2572
        .doc = "Bit length of the prime number used in the"
2510
2628
      case 'p':                 /* --pubkey */
2511
2629
        pubkey = arg;
2512
2630
        break;
 
2631
      case 't':                 /* --tls-privkey */
 
2632
#if GNUTLS_VERSION_NUMBER >= 0x030606
 
2633
        tls_privkey = arg;
 
2634
#endif
 
2635
        break;
 
2636
      case 'T':                 /* --tls-pubkey */
 
2637
#if GNUTLS_VERSION_NUMBER >= 0x030606
 
2638
        tls_pubkey = arg;
 
2639
#endif
 
2640
        break;
2513
2641
      case 129:                 /* --dh-bits */
2514
2642
        errno = 0;
2515
2643
        tmpmax = strtoimax(arg, &tmp, 10);
2550
2678
        argp_state_help(state, state->out_stream,
2551
2679
                        (ARGP_HELP_STD_HELP | ARGP_HELP_EXIT_ERR)
2552
2680
                        & ~(unsigned int)ARGP_HELP_EXIT_OK);
 
2681
        __builtin_unreachable();
2553
2682
      case -3:                  /* --usage */
2554
2683
        argp_state_help(state, state->out_stream,
2555
2684
                        ARGP_HELP_USAGE | ARGP_HELP_EXIT_ERR);
 
2685
        __builtin_unreachable();
2556
2686
      case 'V':                 /* --version */
2557
2687
        fprintf_plus(state->out_stream, "%s\n", argp_program_version);
2558
2688
        exit(argp_err_exit_status);
2585
2715
  }
2586
2716
  
2587
2717
  {
2588
 
    /* Work around Debian bug #633582:
2589
 
       <https://bugs.debian.org/633582> */
2590
 
    
2591
2718
    /* Re-raise privileges */
2592
2719
    ret = raise_privileges();
2593
2720
    if(ret != 0){
2596
2723
    } else {
2597
2724
      struct stat st;
2598
2725
      
 
2726
      /* Work around Debian bug #633582:
 
2727
         <https://bugs.debian.org/633582> */
 
2728
 
2599
2729
      if(strcmp(seckey, PATHDIR "/" SECKEY) == 0){
2600
2730
        int seckey_fd = open(seckey, O_RDONLY);
2601
2731
        if(seckey_fd == -1){
2660
2790
        }
2661
2791
      }
2662
2792
      
 
2793
      /* Work around Debian bug #981302
 
2794
         <https://bugs.debian.org/981302> */
 
2795
      if(lstat("/dev/fd", &st) != 0 and errno == ENOENT){
 
2796
        ret = symlink("/proc/self/fd", "/dev/fd");
 
2797
        if(ret == -1){
 
2798
          perror_plus("Failed to create /dev/fd symlink");
 
2799
        }
 
2800
      }
 
2801
 
2663
2802
      /* Lower privileges */
2664
2803
      ret = lower_privileges();
2665
2804
      if(ret != 0){
2869
3008
    goto end;
2870
3009
  }
2871
3010
  
 
3011
#if GNUTLS_VERSION_NUMBER >= 0x030606
 
3012
  ret = init_gnutls_global(tls_pubkey, tls_privkey, dh_params_file, &mc);
 
3013
#elif GNUTLS_VERSION_NUMBER < 0x030600
2872
3014
  ret = init_gnutls_global(pubkey, seckey, dh_params_file, &mc);
 
3015
#else
 
3016
#error "Needs GnuTLS 3.6.6 or later, or before 3.6.0"
 
3017
#endif
2873
3018
  if(ret == -1){
2874
3019
    fprintf_plus(stderr, "init_gnutls_global failed\n");
2875
3020
    exitcode = EX_UNAVAILABLE;