/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",
310
419
                   gpgme_strsource(rc), gpgme_strerror(rc));
311
420
      return false;
312
421
    }
 
422
    {
 
423
      gpgme_import_result_t import_result
 
424
        = gpgme_op_import_result(mc->ctx);
 
425
      if((import_result->imported < 1
 
426
          or import_result->not_imported > 0)
 
427
         and import_result->unchanged == 0){
 
428
        fprintf_plus(stderr, "bad gpgme_op_import_results:\n");
 
429
        fprintf_plus(stderr,
 
430
                     "The total number of considered keys: %d\n",
 
431
                     import_result->considered);
 
432
        fprintf_plus(stderr,
 
433
                     "The number of keys without user ID: %d\n",
 
434
                     import_result->no_user_id);
 
435
        fprintf_plus(stderr,
 
436
                     "The total number of imported keys: %d\n",
 
437
                     import_result->imported);
 
438
        fprintf_plus(stderr, "The number of imported RSA keys: %d\n",
 
439
                     import_result->imported_rsa);
 
440
        fprintf_plus(stderr, "The number of unchanged keys: %d\n",
 
441
                     import_result->unchanged);
 
442
        fprintf_plus(stderr, "The number of new user IDs: %d\n",
 
443
                     import_result->new_user_ids);
 
444
        fprintf_plus(stderr, "The number of new sub keys: %d\n",
 
445
                     import_result->new_sub_keys);
 
446
        fprintf_plus(stderr, "The number of new signatures: %d\n",
 
447
                     import_result->new_signatures);
 
448
        fprintf_plus(stderr, "The number of new revocations: %d\n",
 
449
                     import_result->new_revocations);
 
450
        fprintf_plus(stderr,
 
451
                     "The total number of secret keys read: %d\n",
 
452
                     import_result->secret_read);
 
453
        fprintf_plus(stderr,
 
454
                     "The number of imported secret keys: %d\n",
 
455
                     import_result->secret_imported);
 
456
        fprintf_plus(stderr,
 
457
                     "The number of unchanged secret keys: %d\n",
 
458
                     import_result->secret_unchanged);
 
459
        fprintf_plus(stderr, "The number of keys not imported: %d\n",
 
460
                     import_result->not_imported);
 
461
        for(gpgme_import_status_t import_status
 
462
              = import_result->imports;
 
463
            import_status != NULL;
 
464
            import_status = import_status->next){
 
465
          fprintf_plus(stderr, "Import status for key: %s\n",
 
466
                       import_status->fpr);
 
467
          if(import_status->result != GPG_ERR_NO_ERROR){
 
468
            fprintf_plus(stderr, "Import result: %s: %s\n",
 
469
                         gpgme_strsource(import_status->result),
 
470
                         gpgme_strerror(import_status->result));
 
471
          }
 
472
          fprintf_plus(stderr, "Key status:\n");
 
473
          fprintf_plus(stderr,
 
474
                       import_status->status & GPGME_IMPORT_NEW
 
475
                       ? "The key was new.\n"
 
476
                       : "The key was not new.\n");
 
477
          fprintf_plus(stderr,
 
478
                       import_status->status & GPGME_IMPORT_UID
 
479
                       ? "The key contained new user IDs.\n"
 
480
                       : "The key did not contain new user IDs.\n");
 
481
          fprintf_plus(stderr,
 
482
                       import_status->status & GPGME_IMPORT_SIG
 
483
                       ? "The key contained new signatures.\n"
 
484
                       : "The key did not contain new signatures.\n");
 
485
          fprintf_plus(stderr,
 
486
                       import_status->status & GPGME_IMPORT_SUBKEY
 
487
                       ? "The key contained new sub keys.\n"
 
488
                       : "The key did not contain new sub keys.\n");
 
489
          fprintf_plus(stderr,
 
490
                       import_status->status & GPGME_IMPORT_SECRET
 
491
                       ? "The key contained a secret key.\n"
 
492
                       : "The key did not contain a secret key.\n");
 
493
        }
 
494
        return false;
 
495
      }
 
496
    }
313
497
    
314
498
    ret = close(fd);
315
499
    if(ret == -1){
356
540
  /* Create new GPGME "context" */
357
541
  rc = gpgme_new(&(mc->ctx));
358
542
  if(rc != GPG_ERR_NO_ERROR){
359
 
    fprintf_plus(stderr, "Mandos plugin mandos-client: "
360
 
                 "bad gpgme_new: %s: %s\n", gpgme_strsource(rc),
361
 
                 gpgme_strerror(rc));
 
543
    fprintf_plus(stderr, "bad gpgme_new: %s: %s\n",
 
544
                 gpgme_strsource(rc), gpgme_strerror(rc));
362
545
    return false;
363
546
  }
364
547
  
400
583
  /* Create new empty GPGME data buffer for the plaintext */
401
584
  rc = gpgme_data_new(&dh_plain);
402
585
  if(rc != GPG_ERR_NO_ERROR){
403
 
    fprintf_plus(stderr, "Mandos plugin mandos-client: "
404
 
                 "bad gpgme_data_new: %s: %s\n",
 
586
    fprintf_plus(stderr, "bad gpgme_data_new: %s: %s\n",
405
587
                 gpgme_strsource(rc), gpgme_strerror(rc));
406
588
    gpgme_data_release(dh_crypto);
407
589
    return -1;
420
602
      if(result == NULL){
421
603
        fprintf_plus(stderr, "gpgme_op_decrypt_result failed\n");
422
604
      } else {
423
 
        fprintf_plus(stderr, "Unsupported algorithm: %s\n",
424
 
                     result->unsupported_algorithm);
425
 
        fprintf_plus(stderr, "Wrong key usage: %u\n",
426
 
                     result->wrong_key_usage);
 
605
        if(result->unsupported_algorithm != NULL) {
 
606
          fprintf_plus(stderr, "Unsupported algorithm: %s\n",
 
607
                       result->unsupported_algorithm);
 
608
        }
 
609
        fprintf_plus(stderr, "Wrong key usage: %s\n",
 
610
                     result->wrong_key_usage ? "Yes" : "No");
427
611
        if(result->file_name != NULL){
428
612
          fprintf_plus(stderr, "File name: %s\n", result->file_name);
429
613
        }
430
 
        gpgme_recipient_t recipient;
431
 
        recipient = result->recipients;
432
 
        while(recipient != NULL){
 
614
 
 
615
        for(gpgme_recipient_t r = result->recipients; r != NULL;
 
616
            r = r->next){
433
617
          fprintf_plus(stderr, "Public key algorithm: %s\n",
434
 
                       gpgme_pubkey_algo_name
435
 
                       (recipient->pubkey_algo));
436
 
          fprintf_plus(stderr, "Key ID: %s\n", recipient->keyid);
 
618
                       gpgme_pubkey_algo_name(r->pubkey_algo));
 
619
          fprintf_plus(stderr, "Key ID: %s\n", r->keyid);
437
620
          fprintf_plus(stderr, "Secret key available: %s\n",
438
 
                       recipient->status == GPG_ERR_NO_SECKEY
439
 
                       ? "No" : "Yes");
440
 
          recipient = recipient->next;
 
621
                       r->status == GPG_ERR_NO_SECKEY ? "No" : "Yes");
441
622
        }
442
623
      }
443
624
    }
525
706
                              const char *dhparamsfilename,
526
707
                              mandos_context *mc){
527
708
  int ret;
528
 
  unsigned int uret;
529
709
  
530
710
  if(debug){
531
711
    fprintf_plus(stderr, "Initializing GnuTLS\n");
548
728
  }
549
729
  
550
730
  if(debug){
551
 
    fprintf_plus(stderr, "Attempting to use OpenPGP public key %s and"
552
 
                 " 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",
553
733
                 pubkeyfilename,
554
734
                 seckeyfilename);
555
735
  }
556
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
557
750
  ret = gnutls_certificate_set_openpgp_key_file
558
751
    (mc->cred, pubkeyfilename, seckeyfilename,
559
752
     GNUTLS_OPENPGP_FMT_BASE64);
 
753
#else
 
754
#error "Needs GnuTLS 3.6.6 or later, or before 3.6.0"
 
755
#endif
560
756
  if(ret != GNUTLS_E_SUCCESS){
561
757
    fprintf_plus(stderr,
562
 
                 "Error[%d] while reading the OpenPGP key pair ('%s',"
 
758
                 "Error[%d] while reading the key pair ('%s',"
563
759
                 " '%s')\n", ret, pubkeyfilename, seckeyfilename);
564
760
    fprintf_plus(stderr, "The GnuTLS error is: %s\n",
565
761
                 safer_gnutls_strerror(ret));
613
809
        }
614
810
        params.size += (unsigned int)bytes_read;
615
811
      }
 
812
      ret = close(dhpfile);
 
813
      if(ret == -1){
 
814
        perror_plus("close");
 
815
      }
616
816
      if(params.data == NULL){
617
817
        dhparamsfilename = NULL;
618
818
      }
632
832
  }
633
833
  if(dhparamsfilename == NULL){
634
834
    if(mc->dh_bits == 0){
 
835
#if GNUTLS_VERSION_NUMBER < 0x030600
635
836
      /* Find out the optimal number of DH bits */
636
837
      /* Try to read the private key file */
637
838
      gnutls_datum_t buffer = { .data = NULL, .size = 0 };
717
918
          }
718
919
        }
719
920
      }
720
 
      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);
721
922
      if(uret != 0){
722
923
        mc->dh_bits = uret;
723
924
        if(debug){
735
936
                     safer_gnutls_strerror(ret));
736
937
        goto globalfail;
737
938
      }
738
 
    } else if(debug){
739
 
      fprintf_plus(stderr, "DH bits explicitly set to %u\n",
740
 
                   mc->dh_bits);
741
 
    }
742
 
    ret = gnutls_dh_params_generate2(mc->dh_params, mc->dh_bits);
743
 
    if(ret != GNUTLS_E_SUCCESS){
744
 
      fprintf_plus(stderr, "Error in GnuTLS prime generation (%u"
745
 
                   " bits): %s\n", mc->dh_bits,
746
 
                   safer_gnutls_strerror(ret));
747
 
      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);
748
953
    }
749
954
  }
750
 
  gnutls_certificate_set_dh_params(mc->cred, mc->dh_params);
751
955
  
752
956
  return 0;
753
957
  
764
968
  int ret;
765
969
  /* GnuTLS session creation */
766
970
  do {
767
 
    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
                                ));
768
979
    if(quit_now){
769
980
      return -1;
770
981
    }
818
1029
static void empty_log(__attribute__((unused)) AvahiLogLevel level,
819
1030
                      __attribute__((unused)) const char *txt){}
820
1031
 
821
 
/* Set effective uid to 0, return errno */
822
 
__attribute__((warn_unused_result))
823
 
int raise_privileges(void){
824
 
  int old_errno = errno;
825
 
  int ret = 0;
826
 
  if(seteuid(0) == -1){
827
 
    ret = errno;
828
 
  }
829
 
  errno = old_errno;
830
 
  return ret;
831
 
}
832
 
 
833
 
/* Set effective and real user ID to 0.  Return errno. */
834
 
__attribute__((warn_unused_result))
835
 
int raise_privileges_permanently(void){
836
 
  int old_errno = errno;
837
 
  int ret = raise_privileges();
838
 
  if(ret != 0){
839
 
    errno = old_errno;
840
 
    return ret;
841
 
  }
842
 
  if(setuid(0) == -1){
843
 
    ret = errno;
844
 
  }
845
 
  errno = old_errno;
846
 
  return ret;
847
 
}
848
 
 
849
 
/* Set effective user ID to unprivileged saved user ID */
850
 
__attribute__((warn_unused_result))
851
 
int lower_privileges(void){
852
 
  int old_errno = errno;
853
 
  int ret = 0;
854
 
  if(seteuid(uid) == -1){
855
 
    ret = errno;
856
 
  }
857
 
  errno = old_errno;
858
 
  return ret;
859
 
}
860
 
 
861
 
/* Lower privileges permanently */
862
 
__attribute__((warn_unused_result))
863
 
int lower_privileges_permanently(void){
864
 
  int old_errno = errno;
865
 
  int ret = 0;
866
 
  if(setuid(uid) == -1){
867
 
    ret = errno;
868
 
  }
869
 
  errno = old_errno;
870
 
  return ret;
871
 
}
872
 
 
873
1032
/* Helper function to add_local_route() and delete_local_route() */
874
1033
__attribute__((nonnull, warn_unused_result))
875
1034
static bool add_delete_local_route(const bool add,
914
1073
      ret = setgid(0);
915
1074
      if(ret == -1){
916
1075
        perror_plus("setgid");
 
1076
        close(devnull);
917
1077
        _exit(EX_NOPERM);
918
1078
      }
919
1079
      /* Reset supplementary groups */
921
1081
      ret = setgroups(0, NULL);
922
1082
      if(ret == -1){
923
1083
        perror_plus("setgroups");
 
1084
        close(devnull);
924
1085
        _exit(EX_NOPERM);
925
1086
      }
926
1087
    }
927
1088
    ret = dup2(devnull, STDIN_FILENO);
928
1089
    if(ret == -1){
929
1090
      perror_plus("dup2(devnull, STDIN_FILENO)");
 
1091
      close(devnull);
930
1092
      _exit(EX_OSERR);
931
1093
    }
932
1094
    ret = close(devnull);
933
1095
    if(ret == -1){
934
1096
      perror_plus("close");
935
 
      _exit(EX_OSERR);
936
1097
    }
937
1098
    ret = dup2(STDERR_FILENO, STDOUT_FILENO);
938
1099
    if(ret == -1){
973
1134
  }
974
1135
  if(pid == -1){
975
1136
    perror_plus("fork");
 
1137
    close(devnull);
976
1138
    return false;
977
1139
  }
 
1140
  ret = close(devnull);
 
1141
  if(ret == -1){
 
1142
    perror_plus("close");
 
1143
  }
978
1144
  int status;
979
1145
  pid_t pret = -1;
980
1146
  errno = 0;
1655
1821
      perror_plus("ioctl SIOCGIFFLAGS");
1656
1822
      errno = old_errno;
1657
1823
    }
 
1824
    if((close(s) == -1) and debug){
 
1825
      old_errno = errno;
 
1826
      perror_plus("close");
 
1827
      errno = old_errno;
 
1828
    }
1658
1829
    return false;
1659
1830
  }
 
1831
  if((close(s) == -1) and debug){
 
1832
    old_errno = errno;
 
1833
    perror_plus("close");
 
1834
    errno = old_errno;
 
1835
  }
1660
1836
  return true;
1661
1837
}
1662
1838
 
1923
2099
      return;
1924
2100
    }
1925
2101
  }
 
2102
  int devnull = (int)TEMP_FAILURE_RETRY(open("/dev/null", O_RDONLY));
 
2103
  if(devnull == -1){
 
2104
    perror_plus("open(\"/dev/null\", O_RDONLY)");
 
2105
    return;
 
2106
  }
1926
2107
  int numhooks = scandirat(hookdir_fd, ".", &direntries,
1927
2108
                           runnable_hook, alphasort);
1928
2109
  if(numhooks == -1){
1929
2110
    perror_plus("scandir");
 
2111
    close(devnull);
1930
2112
    return;
1931
2113
  }
1932
2114
  struct dirent *direntry;
1933
2115
  int ret;
1934
 
  int devnull = (int)TEMP_FAILURE_RETRY(open("/dev/null", O_RDONLY));
1935
 
  if(devnull == -1){
1936
 
    perror_plus("open(\"/dev/null\", O_RDONLY)");
1937
 
    return;
1938
 
  }
1939
2116
  for(int i = 0; i < numhooks; i++){
1940
2117
    direntry = direntries[i];
1941
2118
    if(debug){
2290
2467
 
2291
2468
int main(int argc, char *argv[]){
2292
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
2293
2475
                        .priority = "SECURE256:!CTYPE-X.509"
2294
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
2295
2480
                        .current_server = NULL, .interfaces = NULL,
2296
2481
                        .interfaces_size = 0 };
2297
2482
  AvahiSServiceBrowser *sb = NULL;
2308
2493
  AvahiIfIndex if_index = AVAHI_IF_UNSPEC;
2309
2494
  const char *seckey = PATHDIR "/" SECKEY;
2310
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
2311
2500
  const char *dh_params_file = NULL;
2312
2501
  char *interfaces_hooks = NULL;
2313
2502
  
2361
2550
      { .name = "pubkey", .key = 'p',
2362
2551
        .arg = "FILE",
2363
2552
        .doc = "OpenPGP public key file base name",
2364
 
        .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 },
2365
2570
      { .name = "dh-bits", .key = 129,
2366
2571
        .arg = "BITS",
2367
2572
        .doc = "Bit length of the prime number used in the"
2423
2628
      case 'p':                 /* --pubkey */
2424
2629
        pubkey = arg;
2425
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;
2426
2641
      case 129:                 /* --dh-bits */
2427
2642
        errno = 0;
2428
2643
        tmpmax = strtoimax(arg, &tmp, 10);
2463
2678
        argp_state_help(state, state->out_stream,
2464
2679
                        (ARGP_HELP_STD_HELP | ARGP_HELP_EXIT_ERR)
2465
2680
                        & ~(unsigned int)ARGP_HELP_EXIT_OK);
 
2681
        __builtin_unreachable();
2466
2682
      case -3:                  /* --usage */
2467
2683
        argp_state_help(state, state->out_stream,
2468
2684
                        ARGP_HELP_USAGE | ARGP_HELP_EXIT_ERR);
 
2685
        __builtin_unreachable();
2469
2686
      case 'V':                 /* --version */
2470
2687
        fprintf_plus(state->out_stream, "%s\n", argp_program_version);
2471
2688
        exit(argp_err_exit_status);
2498
2715
  }
2499
2716
  
2500
2717
  {
2501
 
    /* Work around Debian bug #633582:
2502
 
       <https://bugs.debian.org/633582> */
2503
 
    
2504
2718
    /* Re-raise privileges */
2505
2719
    ret = raise_privileges();
2506
2720
    if(ret != 0){
2509
2723
    } else {
2510
2724
      struct stat st;
2511
2725
      
 
2726
      /* Work around Debian bug #633582:
 
2727
         <https://bugs.debian.org/633582> */
 
2728
 
2512
2729
      if(strcmp(seckey, PATHDIR "/" SECKEY) == 0){
2513
2730
        int seckey_fd = open(seckey, O_RDONLY);
2514
2731
        if(seckey_fd == -1){
2573
2790
        }
2574
2791
      }
2575
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
 
2576
2802
      /* Lower privileges */
2577
2803
      ret = lower_privileges();
2578
2804
      if(ret != 0){
2782
3008
    goto end;
2783
3009
  }
2784
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
2785
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
2786
3018
  if(ret == -1){
2787
3019
    fprintf_plus(stderr, "init_gnutls_global failed\n");
2788
3020
    exitcode = EX_UNAVAILABLE;
3061
3293
                                                | O_PATH));
3062
3294
    if(dir_fd == -1){
3063
3295
      perror_plus("open");
 
3296
      return;
3064
3297
    }
3065
3298
    int numentries = scandirat(dir_fd, ".", &direntries,
3066
3299
                               notdotentries, alphasort);
3083
3316
            clean_dir_at(dir_fd, direntries[i]->d_name, level+1);
3084
3317
            dret = 0;
3085
3318
          }
3086
 
          if(dret == -1){
 
3319
          if((dret == -1) and (errno != ENOENT)){
3087
3320
            fprintf_plus(stderr, "unlink(\"%s/%s\"): %s\n", dirname,
3088
3321
                         direntries[i]->d_name, strerror(errno));
3089
3322
          }
3093
3326
      
3094
3327
      /* need to clean even if 0 because man page doesn't specify */
3095
3328
      free(direntries);
3096
 
      if(numentries == -1){
3097
 
        perror_plus("scandirat");
3098
 
      }
3099
3329
      dret = unlinkat(base, dirname, AT_REMOVEDIR);
3100
3330
      if(dret == -1 and errno != ENOENT){
3101
3331
        perror_plus("rmdir");