38
37
#define _FILE_OFFSET_BITS 64
39
38
#endif /* not _FILE_OFFSET_BITS */
41
#define _GNU_SOURCE /* program_invocation_short_name,
42
TEMP_FAILURE_RETRY(), O_CLOEXEC,
43
scandirat(), asprintf() */
40
#define _GNU_SOURCE /* TEMP_FAILURE_RETRY(), asprintf() */
42
#include <stdio.h> /* fprintf(), stderr, fwrite(),
44
#include <stdint.h> /* uint16_t, uint32_t, intptr_t */
45
#include <stddef.h> /* NULL, size_t, ssize_t */
46
#include <stdlib.h> /* free(), EXIT_SUCCESS, srand(),
44
48
#include <stdbool.h> /* bool, false, true */
45
#include <argp.h> /* argp_program_version,
46
argp_program_bug_address,
48
struct argp_state, argp_error(),
52
ARGP_HELP_EXIT_OK, ARGP_HELP_USAGE,
54
ARGP_ERR_UNKNOWN, struct argp,
55
argp_parse(), ARGP_IN_ORDER,
57
#include <stddef.h> /* NULL, size_t */
58
#include <sys/types.h> /* uid_t, gid_t, sig_atomic_t,
59
seteuid(), setuid(), pid_t,
60
setgid(), getuid(), getgid() */
61
#include <unistd.h> /* uid_t, gid_t, TEMP_FAILURE_RETRY(),
62
seteuid(), setuid(), close(),
63
ssize_t, read(), fork(), setgid(),
64
_exit(), dup2(), STDIN_FILENO,
65
STDERR_FILENO, STDOUT_FILENO,
66
fexecve(), write(), getuid(),
67
getgid(), fchown(), symlink(),
68
sleep(), unlinkat(), pause() */
69
#include <netinet/in.h> /* in_port_t, struct sockaddr_in6,
70
sa_family_t, struct sockaddr_in,
71
htons(), IN6_IS_ADDR_LINKLOCAL,
72
INET_ADDRSTRLEN, INET6_ADDRSTRLEN,
73
ntohl(), IPPROTO_IP */
74
#include <time.h> /* struct timespec, clock_gettime(),
75
CLOCK_MONOTONIC, time_t, struct tm,
76
gmtime_r(), clock_settime(),
77
CLOCK_REALTIME, nanosleep() */
78
#include <errno.h> /* errno,
79
program_invocation_short_name,
80
EINTR, EINVAL, ENETUNREACH,
81
EHOSTUNREACH, ECONNREFUSED, EPROTO,
82
EIO, ENOENT, ENXIO, error_t,
83
ENOMEM, EISDIR, ENOTEMPTY */
84
#include <stdio.h> /* fprintf(), stderr, perror(), FILE,
85
vfprintf(), off_t, SEEK_SET,
86
stdout, fwrite(), ferror(),
87
fflush(), asprintf() */
88
#include <stdarg.h> /* va_list, va_start(), vfprintf() */
89
#include <stdlib.h> /* realloc(), free(), malloc(),
90
getenv(), EXIT_FAILURE, setenv(),
91
EXIT_SUCCESS, strtof(), strtod(),
92
srand(), mkdtemp(), abort() */
93
#include <string.h> /* strdup(), strcmp(), strlen(),
94
strerror(), strncpy(), strspn(),
95
memcpy(), strrchr(), strchr(),
97
#include <fcntl.h> /* open(), O_RDONLY, O_DIRECTORY,
98
O_PATH, O_CLOEXEC, openat(),
99
O_NOFOLLOW, AT_REMOVEDIR */
100
#include <iso646.h> /* or, and, not */
101
#include <sys/stat.h> /* struct stat, fstat(), fstatat(),
102
S_ISREG(), S_IXUSR, S_IXGRP,
104
#include <net/if.h> /* IF_NAMESIZE, if_indextoname(),
105
if_nametoindex(), SIOCGIFFLAGS,
106
IFF_LOOPBACK, IFF_POINTOPOINT,
107
IFF_BROADCAST, IFF_NOARP, IFF_UP,
108
IFF_RUNNING, SIOCSIFFLAGS */
109
#include <sysexits.h> /* EX_NOPERM, EX_OSERR,
110
EX_UNAVAILABLE, EX_USAGE */
49
#include <string.h> /* strcmp(), strlen(), strerror(),
50
asprintf(), strcpy() */
51
#include <sys/ioctl.h> /* ioctl */
52
#include <sys/types.h> /* socket(), inet_pton(), sockaddr,
53
sockaddr_in6, PF_INET6,
54
SOCK_STREAM, uid_t, gid_t, open(),
56
#include <sys/stat.h> /* open(), S_ISREG */
57
#include <sys/socket.h> /* socket(), struct sockaddr_in6,
58
inet_pton(), connect(),
60
#include <fcntl.h> /* open(), unlinkat() */
61
#include <dirent.h> /* opendir(), struct dirent, readdir()
63
#include <inttypes.h> /* PRIu16, PRIdMAX, intmax_t,
65
#include <errno.h> /* perror(), errno,
66
program_invocation_short_name */
67
#include <time.h> /* nanosleep(), time(), sleep() */
68
#include <net/if.h> /* ioctl, ifreq, SIOCGIFFLAGS, IFF_UP,
69
SIOCSIFFLAGS, if_indextoname(),
70
if_nametoindex(), IF_NAMESIZE */
71
#include <netinet/in.h> /* IN6_IS_ADDR_LINKLOCAL,
72
INET_ADDRSTRLEN, INET6_ADDRSTRLEN
74
#include <unistd.h> /* close(), SEEK_SET, off_t, write(),
75
getuid(), getgid(), seteuid(),
76
setgid(), pause(), _exit(),
78
#include <arpa/inet.h> /* inet_pton(), htons() */
79
#include <iso646.h> /* not, or, and */
80
#include <argp.h> /* struct argp_option, error_t, struct
81
argp_state, struct argp,
82
argp_parse(), ARGP_KEY_ARG,
83
ARGP_KEY_END, ARGP_ERR_UNKNOWN */
84
#include <signal.h> /* sigemptyset(), sigaddset(),
85
sigaction(), SIGTERM, sig_atomic_t,
87
#include <sysexits.h> /* EX_OSERR, EX_USAGE, EX_UNAVAILABLE,
88
EX_NOHOST, EX_IOERR, EX_PROTOCOL */
89
#include <sys/wait.h> /* waitpid(), WIFEXITED(),
90
WEXITSTATUS(), WTERMSIG() */
111
91
#include <grp.h> /* setgroups() */
112
#include <sys/wait.h> /* waitpid(), WIFEXITED(),
113
WEXITSTATUS(), WIFSIGNALED(),
115
#include <signal.h> /* kill(), SIGTERM, struct sigaction,
116
SIG_DFL, sigemptyset(),
117
sigaddset(), SIGINT, SIGHUP,
119
#include <sys/socket.h> /* struct sockaddr_storage, AF_INET6,
120
PF_INET6, AF_INET, PF_INET,
121
socket(), SOCK_STREAM,
122
SOCK_CLOEXEC, struct sockaddr,
123
connect(), SOCK_DGRAM */
124
#include <argz.h> /* argz_next(), argz_add_sep(),
125
argz_delete(), argz_stringify(),
126
argz_add(), argz_count() */
127
#include <inttypes.h> /* PRIuMAX, uintmax_t, uint32_t,
128
PRIdMAX, PRIu16, intmax_t,
130
#include <arpa/inet.h> /* inet_pton() */
131
#include <stdint.h> /* uint32_t, intptr_t, uint16_t */
92
#include <argz.h> /* argz_add_sep(), argz_next(),
93
argz_delete(), argz_append(),
94
argz_stringify(), argz_add(),
132
96
#include <netdb.h> /* getnameinfo(), NI_NUMERICHOST,
133
97
EAI_SYSTEM, gai_strerror() */
134
#include <sys/ioctl.h> /* ioctl() */
135
#include <dirent.h> /* struct dirent, scandirat(),
136
alphasort(), scandir() */
137
#include <limits.h> /* INT_MAX */
140
100
#include <sys/klog.h> /* klogctl() */
449
304
gpgme_strsource(rc), gpgme_strerror(rc));
453
gpgme_import_result_t import_result
454
= gpgme_op_import_result(mc->ctx);
455
if((import_result->imported < 1
456
or import_result->not_imported > 0)
457
and import_result->unchanged == 0){
458
fprintf_plus(stderr, "bad gpgme_op_import_results:\n");
460
"The total number of considered keys: %d\n",
461
import_result->considered);
463
"The number of keys without user ID: %d\n",
464
import_result->no_user_id);
466
"The total number of imported keys: %d\n",
467
import_result->imported);
468
fprintf_plus(stderr, "The number of imported RSA keys: %d\n",
469
import_result->imported_rsa);
470
fprintf_plus(stderr, "The number of unchanged keys: %d\n",
471
import_result->unchanged);
472
fprintf_plus(stderr, "The number of new user IDs: %d\n",
473
import_result->new_user_ids);
474
fprintf_plus(stderr, "The number of new sub keys: %d\n",
475
import_result->new_sub_keys);
476
fprintf_plus(stderr, "The number of new signatures: %d\n",
477
import_result->new_signatures);
478
fprintf_plus(stderr, "The number of new revocations: %d\n",
479
import_result->new_revocations);
481
"The total number of secret keys read: %d\n",
482
import_result->secret_read);
484
"The number of imported secret keys: %d\n",
485
import_result->secret_imported);
487
"The number of unchanged secret keys: %d\n",
488
import_result->secret_unchanged);
489
fprintf_plus(stderr, "The number of keys not imported: %d\n",
490
import_result->not_imported);
491
for(gpgme_import_status_t import_status
492
= import_result->imports;
493
import_status != NULL;
494
import_status = import_status->next){
495
fprintf_plus(stderr, "Import status for key: %s\n",
497
if(import_status->result != GPG_ERR_NO_ERROR){
498
fprintf_plus(stderr, "Import result: %s: %s\n",
499
gpgme_strsource(import_status->result),
500
gpgme_strerror(import_status->result));
502
fprintf_plus(stderr, "Key status:\n");
504
import_status->status & GPGME_IMPORT_NEW
505
? "The key was new.\n"
506
: "The key was not new.\n");
508
import_status->status & GPGME_IMPORT_UID
509
? "The key contained new user IDs.\n"
510
: "The key did not contain new user IDs.\n");
512
import_status->status & GPGME_IMPORT_SIG
513
? "The key contained new signatures.\n"
514
: "The key did not contain new signatures.\n");
516
import_status->status & GPGME_IMPORT_SUBKEY
517
? "The key contained new sub keys.\n"
518
: "The key did not contain new sub keys.\n");
520
import_status->status & GPGME_IMPORT_SECRET
521
? "The key contained a secret key.\n"
522
: "The key did not contain a secret key.\n");
308
ret = (int)TEMP_FAILURE_RETRY(close(fd));
530
310
perror_plus("close");
3312
3040
free(interfaces_to_take_down);
3313
3041
free(interfaces_hooks);
3315
void clean_dir_at(int base, const char * const dirname,
3317
struct dirent **direntries = NULL;
3319
int dir_fd = (int)TEMP_FAILURE_RETRY(openat(base, dirname,
3325
perror_plus("open");
3328
int numentries = scandirat(dir_fd, ".", &direntries,
3329
notdotentries, alphasort);
3330
if(numentries >= 0){
3331
for(int i = 0; i < numentries; i++){
3333
fprintf_plus(stderr, "Unlinking \"%s/%s\"\n",
3334
dirname, direntries[i]->d_name);
3336
dret = unlinkat(dir_fd, direntries[i]->d_name, 0);
3338
if(errno == EISDIR){
3339
dret = unlinkat(dir_fd, direntries[i]->d_name,
3342
if((dret == -1) and (errno == ENOTEMPTY)
3343
and (strcmp(direntries[i]->d_name, "private-keys-v1.d")
3344
== 0) and (level == 0)){
3345
/* Recurse only in this special case */
3346
clean_dir_at(dir_fd, direntries[i]->d_name, level+1);
3349
if((dret == -1) and (errno != ENOENT)){
3350
fprintf_plus(stderr, "unlink(\"%s/%s\"): %s\n", dirname,
3351
direntries[i]->d_name, strerror(errno));
3354
free(direntries[i]);
3357
/* need to clean even if 0 because man page doesn't specify */
3359
dret = unlinkat(base, dirname, AT_REMOVEDIR);
3360
if(dret == -1 and errno != ENOENT){
3361
perror_plus("rmdir");
3364
perror_plus("scandirat");
3369
3043
/* Removes the GPGME temp directory and all files inside */
3370
3044
if(tempdir != NULL){
3371
clean_dir_at(-1, tempdir, 0);
3045
struct dirent **direntries = NULL;
3046
int tempdir_fd = (int)TEMP_FAILURE_RETRY(open(tempdir, O_RDONLY
3050
if(tempdir_fd == -1){
3051
perror_plus("open");
3054
#if __GLIBC_PREREQ(2, 15)
3055
int numentries = scandirat(tempdir_fd, ".", &direntries,
3056
notdotentries, alphasort);
3057
#else /* not __GLIBC_PREREQ(2, 15) */
3058
int numentries = scandir(tempdir, &direntries, notdotentries,
3060
#endif /* not __GLIBC_PREREQ(2, 15) */
3061
#else /* not __GLIBC__ */
3062
int numentries = scandir(tempdir, &direntries, notdotentries,
3064
#endif /* not __GLIBC__ */
3065
if(numentries >= 0){
3066
for(int i = 0; i < numentries; i++){
3067
ret = unlinkat(tempdir_fd, direntries[i]->d_name, 0);
3069
fprintf_plus(stderr, "unlinkat(open(\"%s\", O_RDONLY),"
3070
" \"%s\", 0): %s\n", tempdir,
3071
direntries[i]->d_name, strerror(errno));
3073
free(direntries[i]);
3076
/* need to clean even if 0 because man page doesn't specify */
3078
if(numentries == -1){
3079
perror_plus("scandir");
3081
ret = rmdir(tempdir);
3082
if(ret == -1 and errno != ENOENT){
3083
perror_plus("rmdir");
3086
TEMP_FAILURE_RETRY(close(tempdir_fd));