/mandos/trunk

To get this branch, use:
bzr branch http://bzr.recompile.se/loggerhead/mandos/trunk
21 by Teddy Hogeborn
* Makefile (CFLAGS): Changed to use $(WARN), $(DEBUG), $(COVERAGE) and
1
/*  -*- coding: utf-8 -*- */
2
/*
261 by Teddy Hogeborn
* plugins.d/askpass-fifo.c: Fix name in header.
3
 * Mandos-client - get and decrypt data from a Mandos server
21 by Teddy Hogeborn
* Makefile (CFLAGS): Changed to use $(WARN), $(DEBUG), $(COVERAGE) and
4
 *
5
 * This program is partly derived from an example program for an Avahi
6
 * service browser, downloaded from
7
 * <http://avahi.org/browser/examples/core-browse-services.c>.  This
8
 * includes the following functions: "resolve_callback",
9
 * "browse_callback", and parts of "main".
10
 * 
28 by Teddy Hogeborn
* server.conf: New file.
11
 * Everything else is
969 by Teddy Hogeborn
Update copyright year to 2019
12
 * Copyright © 2008-2019 Teddy Hogeborn
13
 * Copyright © 2008-2019 Björn Påhlsson
21 by Teddy Hogeborn
* Makefile (CFLAGS): Changed to use $(WARN), $(DEBUG), $(COVERAGE) and
14
 * 
907 by Teddy Hogeborn
Alter copyright notices slightly. Actual license is unchanged!
15
 * This file is part of Mandos.
16
 * 
17
 * Mandos is free software: you can redistribute it and/or modify it
18
 * under the terms of the GNU General Public License as published by
19
 * the Free Software Foundation, either version 3 of the License, or
20
 * (at your option) any later version.
21
 * 
22
 * Mandos is distributed in the hope that it will be useful, but
21 by Teddy Hogeborn
* Makefile (CFLAGS): Changed to use $(WARN), $(DEBUG), $(COVERAGE) and
23
 * WITHOUT ANY WARRANTY; without even the implied warranty of
24
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
25
 * General Public License for more details.
26
 * 
27
 * You should have received a copy of the GNU General Public License
907 by Teddy Hogeborn
Alter copyright notices slightly. Actual license is unchanged!
28
 * along with Mandos.  If not, see <http://www.gnu.org/licenses/>.
21 by Teddy Hogeborn
* Makefile (CFLAGS): Changed to use $(WARN), $(DEBUG), $(COVERAGE) and
29
 * 
505.1.2 by Teddy Hogeborn
Change "fukt.bsnet.se" to "recompile.se" throughout.
30
 * Contact the authors at <mandos@recompile.se>.
21 by Teddy Hogeborn
* Makefile (CFLAGS): Changed to use $(WARN), $(DEBUG), $(COVERAGE) and
31
 */
32
28 by Teddy Hogeborn
* server.conf: New file.
33
/* Needed by GPGME, specifically gpgme_data_seek() */
317 by Teddy Hogeborn
Use "getconf" to get correct LFS compile and link flags.
34
#ifndef _LARGEFILE_SOURCE
13 by Björn Påhlsson
Added following support:
35
#define _LARGEFILE_SOURCE
691 by Teddy Hogeborn
Make mandos-client use scandirat() if it exists.
36
#endif	/* not _LARGEFILE_SOURCE */
317 by Teddy Hogeborn
Use "getconf" to get correct LFS compile and link flags.
37
#ifndef _FILE_OFFSET_BITS
13 by Björn Påhlsson
Added following support:
38
#define _FILE_OFFSET_BITS 64
691 by Teddy Hogeborn
Make mandos-client use scandirat() if it exists.
39
#endif	/* not _FILE_OFFSET_BITS */
13 by Björn Påhlsson
Added following support:
40
76 by Teddy Hogeborn
* plugins.d/password-request.c (init_gnutls_global): Renamed
41
#define _GNU_SOURCE		/* TEMP_FAILURE_RETRY(), asprintf() */
24.1.10 by Björn Påhlsson
merge commit
42
76 by Teddy Hogeborn
* plugins.d/password-request.c (init_gnutls_global): Renamed
43
#include <stdio.h>		/* fprintf(), stderr, fwrite(),
694 by Teddy Hogeborn
Make mandos-client use unlinkat() instead of remove().
44
				   stdout, ferror() */
588 by Teddy Hogeborn
* plugins.d/mandos-client.c (start_mandos_communication): Eliminate
45
#include <stdint.h> 		/* uint16_t, uint32_t, intptr_t */
24.1.26 by Björn Påhlsson
tally count of used symbols
46
#include <stddef.h>		/* NULL, size_t, ssize_t */
399 by Teddy Hogeborn
* Makefile (BROKEN_PIE): Add comment.
47
#include <stdlib.h> 		/* free(), EXIT_SUCCESS, srand(),
48
				   strtof(), abort() */
304 by Teddy Hogeborn
Four new interrelated features:
49
#include <stdbool.h>		/* bool, false, true */
773 by Teddy Hogeborn
mandos-client: Don't use memset().
50
#include <string.h>		/* strcmp(), strlen(), strerror(),
870 by Teddy Hogeborn
Show what signal, if any, made mandos-client exit.
51
				   asprintf(), strncpy(), strsignal()
52
				*/
304 by Teddy Hogeborn
Four new interrelated features:
53
#include <sys/ioctl.h>		/* ioctl */
24.1.26 by Björn Påhlsson
tally count of used symbols
54
#include <sys/types.h>		/* socket(), inet_pton(), sockaddr,
24.1.29 by Björn Påhlsson
Added more header file comments
55
				   sockaddr_in6, PF_INET6,
304 by Teddy Hogeborn
Four new interrelated features:
56
				   SOCK_STREAM, uid_t, gid_t, open(),
57
				   opendir(), DIR */
505.3.1 by teddy at bsnet
* plugins.d/mandos-client.c (good_interface): Add error message.
58
#include <sys/stat.h>		/* open(), S_ISREG */
24.1.26 by Björn Påhlsson
tally count of used symbols
59
#include <sys/socket.h>		/* socket(), struct sockaddr_in6,
667 by Teddy Hogeborn
Use getnameinfo() instead of inet_ntop() in mandos-client.
60
				   inet_pton(), connect(),
61
				   getnameinfo() */
813 by Teddy Hogeborn
Client: Remove new key directory introduced in GnuPG 2.1
62
#include <fcntl.h>		/* open(), unlinkat(), AT_REMOVEDIR */
266 by Teddy Hogeborn
* plugin-runner.c: Only space changes.
63
#include <dirent.h>		/* opendir(), struct dirent, readdir()
64
				 */
311 by Teddy Hogeborn
Overflows are not detected by sscanf(), so stop using it:
65
#include <inttypes.h>		/* PRIu16, PRIdMAX, intmax_t,
66
				   strtoimax() */
813 by Teddy Hogeborn
Client: Remove new key directory introduced in GnuPG 2.1
67
#include <errno.h>		/* perror(), errno, EINTR, EINVAL,
68
				   EAI_SYSTEM, ENETUNREACH,
69
				   EHOSTUNREACH, ECONNREFUSED, EPROTO,
70
				   EIO, ENOENT, ENXIO, ENOMEM, EISDIR,
71
				   ENOTEMPTY,
485 by Teddy Hogeborn
Merge from Björn.
72
				   program_invocation_short_name */
24.1.163 by Björn Påhlsson
mandos-client: Added never ending loop for --connect
73
#include <time.h>		/* nanosleep(), time(), sleep() */
39 by Teddy Hogeborn
* plugins.d/mandosclient.c (pgp_packet_decrypt): Renamed variables.
74
#include <net/if.h>		/* ioctl, ifreq, SIOCGIFFLAGS, IFF_UP,
24.1.26 by Björn Påhlsson
tally count of used symbols
75
				   SIOCSIFFLAGS, if_indextoname(),
76
				   if_nametoindex(), IF_NAMESIZE */
304 by Teddy Hogeborn
Four new interrelated features:
77
#include <netinet/in.h>		/* IN6_IS_ADDR_LINKLOCAL,
78
				   INET_ADDRSTRLEN, INET6_ADDRSTRLEN
79
				*/
24.1.29 by Björn Påhlsson
Added more header file comments
80
#include <unistd.h>		/* close(), SEEK_SET, off_t, write(),
365 by Teddy Hogeborn
* plugins.d/mandos-client.c (main): Bug fix: Check result of setgid().
81
				   getuid(), getgid(), seteuid(),
694 by Teddy Hogeborn
Make mandos-client use unlinkat() instead of remove().
82
				   setgid(), pause(), _exit(),
83
				   unlinkat() */
667 by Teddy Hogeborn
Use getnameinfo() instead of inet_ntop() in mandos-client.
84
#include <arpa/inet.h>		/* inet_pton(), htons() */
304 by Teddy Hogeborn
Four new interrelated features:
85
#include <iso646.h>		/* not, or, and */
24.1.29 by Björn Påhlsson
Added more header file comments
86
#include <argp.h>		/* struct argp_option, error_t, struct
87
				   argp_state, struct argp,
88
				   argp_parse(), ARGP_KEY_ARG,
89
				   ARGP_KEY_END, ARGP_ERR_UNKNOWN */
307 by Teddy Hogeborn
Merge from Björn:
90
#include <signal.h>		/* sigemptyset(), sigaddset(),
354 by Teddy Hogeborn
* plugins.d/mandos-client.c (signal_received): New.
91
				   sigaction(), SIGTERM, sig_atomic_t,
92
				   raise() */
399 by Teddy Hogeborn
* Makefile (BROKEN_PIE): Add comment.
93
#include <sysexits.h>		/* EX_OSERR, EX_USAGE, EX_UNAVAILABLE,
94
				   EX_NOHOST, EX_IOERR, EX_PROTOCOL */
505.3.3 by teddy at bsnet
* plugins.d/mandos-client.c: Prefix all printouts with "Mandos plugin
95
#include <sys/wait.h>		/* waitpid(), WIFEXITED(),
96
				   WEXITSTATUS(), WTERMSIG() */
505.3.16 by teddy at bsnet
* network-hooks.d/bridge: Use "/usr/sbin/brctl" explicitly.
97
#include <grp.h>		/* setgroups() */
594.1.4 by Teddy Hogeborn
* plugins.d/mandos-client.c (get_flags): Don't clobber errno.
98
#include <argz.h>		/* argz_add_sep(), argz_next(),
99
				   argz_delete(), argz_append(),
100
				   argz_stringify(), argz_add(),
101
				   argz_count() */
667 by Teddy Hogeborn
Use getnameinfo() instead of inet_ntop() in mandos-client.
102
#include <netdb.h>		/* getnameinfo(), NI_NUMERICHOST,
103
				   EAI_SYSTEM, gai_strerror() */
307 by Teddy Hogeborn
Merge from Björn:
104
293 by Teddy Hogeborn
* plugin-runner.c: Whitespace changes only.
105
#ifdef __linux__
24.1.124 by Björn Påhlsson
Added lower kernel loglevel to reduce clutter on system console.
106
#include <sys/klog.h> 		/* klogctl() */
308 by Teddy Hogeborn
* plugin-runner.c: Comment change.
107
#endif	/* __linux__ */
24.1.26 by Björn Påhlsson
tally count of used symbols
108
109
/* Avahi */
24.1.29 by Björn Påhlsson
Added more header file comments
110
/* All Avahi types, constants and functions
111
 Avahi*, avahi_*,
112
 AVAHI_* */
113
#include <avahi-core/core.h>
24.1.26 by Björn Påhlsson
tally count of used symbols
114
#include <avahi-core/lookup.h>
24.1.29 by Björn Påhlsson
Added more header file comments
115
#include <avahi-core/log.h>
24.1.26 by Björn Påhlsson
tally count of used symbols
116
#include <avahi-common/simple-watch.h>
117
#include <avahi-common/malloc.h>
118
#include <avahi-common/error.h>
119
120
/* GnuTLS */
76 by Teddy Hogeborn
* plugins.d/password-request.c (init_gnutls_global): Renamed
121
#include <gnutls/gnutls.h>	/* All GnuTLS types, constants and
122
				   functions:
24.1.29 by Björn Påhlsson
Added more header file comments
123
				   gnutls_*
24.1.26 by Björn Påhlsson
tally count of used symbols
124
				   init_gnutls_session(),
24.1.29 by Björn Påhlsson
Added more header file comments
125
				   GNUTLS_* */
962 by Teddy Hogeborn
Add support for using raw public keys in TLS (RFC 7250)
126
#if GNUTLS_VERSION_NUMBER < 0x030600
266 by Teddy Hogeborn
* plugin-runner.c: Only space changes.
127
#include <gnutls/openpgp.h>
505.3.6 by teddy at bsnet
* plugins.d/mandos-client.c: Some white space fixes.
128
			 /* gnutls_certificate_set_openpgp_key_file(),
129
			    GNUTLS_OPENPGP_FMT_BASE64 */
962 by Teddy Hogeborn
Add support for using raw public keys in TLS (RFC 7250)
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
24.1.26 by Björn Påhlsson
tally count of used symbols
135
40 by Teddy Hogeborn
* plugins.d/mandosclient.c (initgnutls): Moved "err" variable into its
136
/* GPGME */
76 by Teddy Hogeborn
* plugins.d/password-request.c (init_gnutls_global): Renamed
137
#include <gpgme.h> 		/* All GPGME types, constants and
138
				   functions:
24.1.29 by Björn Påhlsson
Added more header file comments
139
				   gpgme_*
24.1.26 by Björn Påhlsson
tally count of used symbols
140
				   GPGME_PROTOCOL_OpenPGP,
24.1.29 by Björn Påhlsson
Added more header file comments
141
				   GPG_ERR_NO_* */
13 by Björn Påhlsson
Added following support:
142
143
#define BUFFER_SIZE 256
37 by Teddy Hogeborn
Non-tested commit for merge purposes.
144
24.1.81 by Björn Påhlsson
removed keyring pre-requirement for starting password-request.
145
#define PATHDIR "/conf/conf.d/mandos"
146
#define SECKEY "seckey.txt"
168 by Teddy Hogeborn
* initramfs-tools-hook: Use long options where available. Use only
147
#define PUBKEY "pubkey.txt"
962 by Teddy Hogeborn
Add support for using raw public keys in TLS (RFC 7250)
148
#define TLS_PRIVKEY "tls-privkey.pem"
149
#define TLS_PUBKEY "tls-pubkey.pem"
505.2.3 by Teddy Hogeborn
Intermediate commit - this does *not* work yet.
150
#define HOOKDIR "/lib/mandos/network-hooks.d"
24.1.81 by Björn Påhlsson
removed keyring pre-requirement for starting password-request.
151
15.1.2 by Björn Påhlsson
Added debug options from passprompt as --debug and --debug=passprompt
152
bool debug = false;
43 by Teddy Hogeborn
* plugins.d/mandosclient.c: Cosmetic changes.
153
static const char mandos_protocol_version[] = "1";
680 by Teddy Hogeborn
Minor changes to minimize diff from last release.
154
const char *argp_program_version = "mandos-client " VERSION;
155
const char *argp_program_bug_address = "<mandos@recompile.se>";
237.2.33 by teddy at bsnet
* plugins.d/mandos-client.c: An empty interface name now means to
156
static const char sys_class_net[] = "/sys/class/net";
157
char *connect_to = NULL;
505.3.4 by teddy at bsnet
* plugins.d/mandos-client.c (runnable_hook): Bug fix: stat using the
158
const char *hookdir = HOOKDIR;
691 by Teddy Hogeborn
Make mandos-client use scandirat() if it exists.
159
int hookdir_fd = -1;
594.1.1 by Teddy Hogeborn
* plugins.d/mandos-client.c: Refactoring.
160
uid_t uid = 65534;
161
gid_t gid = 65534;
24.1.10 by Björn Påhlsson
merge commit
162
485 by Teddy Hogeborn
Merge from Björn.
163
/* Doubly linked list that need to be circularly linked when used */
24.1.174 by Björn Påhlsson
* Makefile (CFLAGS): Added "-lrt" to include real time library.
164
typedef struct server{
165
  const char *ip;
597 by Teddy Hogeborn
* plugins.d/mandos-client.c: Don't use assert(). Use in_port_t for
166
  in_port_t port;
24.1.174 by Björn Påhlsson
* Makefile (CFLAGS): Added "-lrt" to include real time library.
167
  AvahiIfIndex if_index;
168
  int af;
169
  struct timespec last_seen;
170
  struct server *next;
171
  struct server *prev;
172
} server;
173
42 by Teddy Hogeborn
* plugins.d/mandosclient.c (start_mandos_communication): Change "to"
174
/* Used for passing in values through the Avahi callback functions */
13 by Björn Påhlsson
Added following support:
175
typedef struct {
24.1.9 by Björn Påhlsson
not working midwork...
176
  AvahiServer *server;
13 by Björn Påhlsson
Added following support:
177
  gnutls_certificate_credentials_t cred;
24.1.9 by Björn Påhlsson
not working midwork...
178
  unsigned int dh_bits;
24.1.13 by Björn Påhlsson
mandosclient
179
  gnutls_dh_params_t dh_params;
24.1.9 by Björn Påhlsson
not working midwork...
180
  const char *priority;
24.1.81 by Björn Påhlsson
removed keyring pre-requirement for starting password-request.
181
  gpgme_ctx_t ctx;
24.1.174 by Björn Påhlsson
* Makefile (CFLAGS): Added "-lrt" to include real time library.
182
  server *current_server;
603 by Teddy Hogeborn
* plugins.d/mandos-client (mandos_context): New "interfaces" and
183
  char *interfaces;
184
  size_t interfaces_size;
24.1.9 by Björn Påhlsson
not working midwork...
185
} mandos_context;
13 by Björn Påhlsson
Added following support:
186
601 by Teddy Hogeborn
* plugins.d/mandos-client (mandos_context): Removed "simple_poll"
187
/* global so signal handler can reach it*/
188
AvahiSimplePoll *simple_poll;
24.1.134 by Björn Påhlsson
plugin-runner: Added support for empty string arguments
189
371 by Teddy Hogeborn
* plugins.d/mandos-client.c (init_gnutls_session): Always fail and
190
sig_atomic_t quit_now = 0;
191
int signal_received = 0;
192
24.1.174 by Björn Påhlsson
* Makefile (CFLAGS): Added "-lrt" to include real time library.
193
/* Function to use when printing errors */
194
void perror_plus(const char *print_text){
534 by teddy at bsnet
* plugin-runner.c (add_to_char_array): Added "nonnull" attribute.
195
  int e = errno;
485 by Teddy Hogeborn
Merge from Björn.
196
  fprintf(stderr, "Mandos plugin %s: ",
197
	  program_invocation_short_name);
534 by teddy at bsnet
* plugin-runner.c (add_to_char_array): Added "nonnull" attribute.
198
  errno = e;
24.1.174 by Björn Påhlsson
* Makefile (CFLAGS): Added "-lrt" to include real time library.
199
  perror(print_text);
200
}
201
672 by Teddy Hogeborn
Update GCC warning flags and function attributes to GCC 4.7.
202
__attribute__((format (gnu_printf, 2, 3), nonnull))
505.2.4 by Björn Påhlsson
New convinence error printer: fprintf_plus
203
int fprintf_plus(FILE *stream, const char *format, ...){
204
  va_list ap;
205
  va_start (ap, format);
206
  
505.3.9 by Teddy Hogeborn
* plugins.d/mandos-client.c: Merge unified printing system.
207
  TEMP_FAILURE_RETRY(fprintf(stream, "Mandos plugin %s: ",
208
			     program_invocation_short_name));
622 by Teddy Hogeborn
* debian/control (Build-Depends): Depend on debhelper 8.9.7 for using
209
  return (int)TEMP_FAILURE_RETRY(vfprintf(stream, format, ap));
505.2.4 by Björn Påhlsson
New convinence error printer: fprintf_plus
210
}
211
43 by Teddy Hogeborn
* plugins.d/mandosclient.c: Cosmetic changes.
212
/*
308 by Teddy Hogeborn
* plugin-runner.c: Comment change.
213
 * Make additional room in "buffer" for at least BUFFER_SIZE more
214
 * bytes. "buffer_capacity" is how much is currently allocated,
215
 * "buffer_length" is how much is already used.
43 by Teddy Hogeborn
* plugins.d/mandosclient.c: Cosmetic changes.
216
 */
672 by Teddy Hogeborn
Update GCC warning flags and function attributes to GCC 4.7.
217
__attribute__((nonnull, warn_unused_result))
24.1.132 by Björn Påhlsson
Fixed a bug in fallback handling
218
size_t incbuffer(char **buffer, size_t buffer_length,
505.3.6 by teddy at bsnet
* plugins.d/mandos-client.c: Some white space fixes.
219
		 size_t buffer_capacity){
266 by Teddy Hogeborn
* plugin-runner.c: Only space changes.
220
  if(buffer_length + BUFFER_SIZE > buffer_capacity){
666 by Teddy Hogeborn
Bug fix: Free all memory and give better messages when memory is full.
221
    char *new_buf = realloc(*buffer, buffer_capacity + BUFFER_SIZE);
222
    if(new_buf == NULL){
223
      int old_errno = errno;
224
      free(*buffer);
225
      errno = old_errno;
226
      *buffer = NULL;
24.1.10 by Björn Påhlsson
merge commit
227
      return 0;
228
    }
666 by Teddy Hogeborn
Bug fix: Free all memory and give better messages when memory is full.
229
    *buffer = new_buf;
24.1.10 by Björn Påhlsson
merge commit
230
    buffer_capacity += BUFFER_SIZE;
231
  }
232
  return buffer_capacity;
233
}
234
491 by teddy at bsnet
* plugins.d/mandos-client.c (avahi_loop_with_timeout): Fix warning.
235
/* Add server to set of servers to retry periodically */
672 by Teddy Hogeborn
Update GCC warning flags and function attributes to GCC 4.7.
236
__attribute__((nonnull, warn_unused_result))
597 by Teddy Hogeborn
* plugins.d/mandos-client.c: Don't use assert(). Use in_port_t for
237
bool add_server(const char *ip, in_port_t port, AvahiIfIndex if_index,
602 by Teddy Hogeborn
* plugins.d/mandos-client (mandos_context): Moved to inside "main()".
238
		int af, server **current_server){
24.1.174 by Björn Påhlsson
* Makefile (CFLAGS): Added "-lrt" to include real time library.
239
  int ret;
240
  server *new_server = malloc(sizeof(server));
241
  if(new_server == NULL){
242
    perror_plus("malloc");
505.1.27 by teddy at bsnet
* plugins.d/mandos-client.c (add_server): Return bool; all callers
243
    return false;
24.1.174 by Björn Påhlsson
* Makefile (CFLAGS): Added "-lrt" to include real time library.
244
  }
245
  *new_server = (server){ .ip = strdup(ip),
505.3.6 by teddy at bsnet
* plugins.d/mandos-client.c: Some white space fixes.
246
			  .port = port,
247
			  .if_index = if_index,
248
			  .af = af };
24.1.174 by Björn Påhlsson
* Makefile (CFLAGS): Added "-lrt" to include real time library.
249
  if(new_server->ip == NULL){
250
    perror_plus("strdup");
710 by Teddy Hogeborn
mandos-client: Fix minor memory leak on memory full or clock failure.
251
    free(new_server);
505.1.27 by teddy at bsnet
* plugins.d/mandos-client.c (add_server): Return bool; all callers
252
    return false;
24.1.174 by Björn Påhlsson
* Makefile (CFLAGS): Added "-lrt" to include real time library.
253
  }
668 by Teddy Hogeborn
Do not add a new server to server list if clock_gettime() fails
254
  ret = clock_gettime(CLOCK_MONOTONIC, &(new_server->last_seen));
255
  if(ret == -1){
256
    perror_plus("clock_gettime");
714 by Teddy Hogeborn
mandos-client: Fix mem free bug.
257
#ifdef __GNUC__
258
#pragma GCC diagnostic push
259
#pragma GCC diagnostic ignored "-Wcast-qual"
260
#endif
261
    free((char *)(new_server->ip));
262
#ifdef __GNUC__
263
#pragma GCC diagnostic pop
264
#endif
710 by Teddy Hogeborn
mandos-client: Fix minor memory leak on memory full or clock failure.
265
    free(new_server);
668 by Teddy Hogeborn
Do not add a new server to server list if clock_gettime() fails
266
    return false;
267
  }
491 by teddy at bsnet
* plugins.d/mandos-client.c (avahi_loop_with_timeout): Fix warning.
268
  /* Special case of first server */
602 by Teddy Hogeborn
* plugins.d/mandos-client (mandos_context): Moved to inside "main()".
269
  if(*current_server == NULL){
24.1.174 by Björn Påhlsson
* Makefile (CFLAGS): Added "-lrt" to include real time library.
270
    new_server->next = new_server;
271
    new_server->prev = new_server;
602 by Teddy Hogeborn
* plugins.d/mandos-client (mandos_context): Moved to inside "main()".
272
    *current_server = new_server;
24.1.174 by Björn Påhlsson
* Makefile (CFLAGS): Added "-lrt" to include real time library.
273
  } else {
672 by Teddy Hogeborn
Update GCC warning flags and function attributes to GCC 4.7.
274
    /* Place the new server last in the list */
602 by Teddy Hogeborn
* plugins.d/mandos-client (mandos_context): Moved to inside "main()".
275
    new_server->next = *current_server;
276
    new_server->prev = (*current_server)->prev;
24.1.174 by Björn Påhlsson
* Makefile (CFLAGS): Added "-lrt" to include real time library.
277
    new_server->prev->next = new_server;
602 by Teddy Hogeborn
* plugins.d/mandos-client (mandos_context): Moved to inside "main()".
278
    (*current_server)->prev = new_server;
24.1.174 by Björn Påhlsson
* Makefile (CFLAGS): Added "-lrt" to include real time library.
279
  }
505.1.27 by teddy at bsnet
* plugins.d/mandos-client.c (add_server): Return bool; all callers
280
  return true;
24.1.174 by Björn Påhlsson
* Makefile (CFLAGS): Added "-lrt" to include real time library.
281
}
282
951 by Teddy Hogeborn
mandos-client: Set system clock if necessary
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
39 by Teddy Hogeborn
* plugins.d/mandosclient.c (pgp_packet_decrypt): Renamed variables.
335
/* 
24.1.81 by Björn Påhlsson
removed keyring pre-requirement for starting password-request.
336
 * Initialize GPGME.
39 by Teddy Hogeborn
* plugins.d/mandosclient.c (pgp_packet_decrypt): Renamed variables.
337
 */
672 by Teddy Hogeborn
Update GCC warning flags and function attributes to GCC 4.7.
338
__attribute__((nonnull, warn_unused_result))
673 by Teddy Hogeborn
Make mandos-client prefer /run/tmp over /tmp.
339
static bool init_gpgme(const char * const seckey,
340
		       const char * const pubkey,
341
		       const char * const tempdir,
342
		       mandos_context *mc){
13 by Björn Påhlsson
Added following support:
343
  gpgme_error_t rc;
344
  gpgme_engine_info_t engine_info;
168 by Teddy Hogeborn
* initramfs-tools-hook: Use long options where available. Use only
345
  
24.1.81 by Björn Påhlsson
removed keyring pre-requirement for starting password-request.
346
  /*
288 by Teddy Hogeborn
* plugins.d/mandos-client.c (main): Use separate bool variable instead
347
   * Helper function to insert pub and seckey to the engine keyring.
24.1.81 by Björn Påhlsson
removed keyring pre-requirement for starting password-request.
348
   */
673 by Teddy Hogeborn
Make mandos-client prefer /run/tmp over /tmp.
349
  bool import_key(const char * const filename){
361 by Teddy Hogeborn
* plugins.d/mandos-client.c (init_gpgme): Move variable "ret" into the
350
    int ret;
24.1.81 by Björn Påhlsson
removed keyring pre-requirement for starting password-request.
351
    int fd;
352
    gpgme_data_t pgp_data;
353
    
257.1.2 by Mooie
Fixed warnings in the 64 bit build. Added explicit cast to int for
354
    fd = (int)TEMP_FAILURE_RETRY(open(filename, O_RDONLY));
24.1.81 by Björn Påhlsson
removed keyring pre-requirement for starting password-request.
355
    if(fd == -1){
24.1.174 by Björn Påhlsson
* Makefile (CFLAGS): Added "-lrt" to include real time library.
356
      perror_plus("open");
24.1.81 by Björn Påhlsson
removed keyring pre-requirement for starting password-request.
357
      return false;
358
    }
359
    
951 by Teddy Hogeborn
mandos-client: Set system clock if necessary
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
      time_t keytime = keystat.st_mtim.tv_sec;
400
      if(stime(&keytime) != 0){
401
	perror_plus("stime");
402
      }
403
      ret = lower_privileges();
404
      if(ret != 0){
405
	errno = ret;
406
	perror_plus("Failed to lower privileges");
407
      }
408
    } while(false);
409
24.1.81 by Björn Påhlsson
removed keyring pre-requirement for starting password-request.
410
    rc = gpgme_data_new_from_fd(&pgp_data, fd);
266 by Teddy Hogeborn
* plugin-runner.c: Only space changes.
411
    if(rc != GPG_ERR_NO_ERROR){
505.2.6 by Björn Påhlsson
replace calls to fprintf with fprintf_plus.
412
      fprintf_plus(stderr, "bad gpgme_data_new_from_fd: %s: %s\n",
505.3.9 by Teddy Hogeborn
* plugins.d/mandos-client.c: Merge unified printing system.
413
		   gpgme_strsource(rc), gpgme_strerror(rc));
24.1.81 by Björn Påhlsson
removed keyring pre-requirement for starting password-request.
414
      return false;
415
    }
168 by Teddy Hogeborn
* initramfs-tools-hook: Use long options where available. Use only
416
    
602 by Teddy Hogeborn
* plugins.d/mandos-client (mandos_context): Moved to inside "main()".
417
    rc = gpgme_op_import(mc->ctx, pgp_data);
266 by Teddy Hogeborn
* plugin-runner.c: Only space changes.
418
    if(rc != GPG_ERR_NO_ERROR){
505.2.6 by Björn Påhlsson
replace calls to fprintf with fprintf_plus.
419
      fprintf_plus(stderr, "bad gpgme_op_import: %s: %s\n",
505.3.9 by Teddy Hogeborn
* plugins.d/mandos-client.c: Merge unified printing system.
420
		   gpgme_strsource(rc), gpgme_strerror(rc));
24.1.81 by Björn Påhlsson
removed keyring pre-requirement for starting password-request.
421
      return false;
422
    }
947 by Teddy Hogeborn
Check for and report GPGME key import errors
423
    {
424
      gpgme_import_result_t import_result
425
	= gpgme_op_import_result(mc->ctx);
426
      if((import_result->imported < 1
427
	  or import_result->not_imported > 0)
428
	 and import_result->unchanged == 0){
429
	fprintf_plus(stderr, "bad gpgme_op_import_results:\n");
430
	fprintf_plus(stderr,
431
		     "The total number of considered keys: %d\n",
432
		     import_result->considered);
433
	fprintf_plus(stderr,
434
		     "The number of keys without user ID: %d\n",
435
		     import_result->no_user_id);
436
	fprintf_plus(stderr,
437
		     "The total number of imported keys: %d\n",
438
		     import_result->imported);
439
	fprintf_plus(stderr, "The number of imported RSA keys: %d\n",
440
		     import_result->imported_rsa);
441
	fprintf_plus(stderr, "The number of unchanged keys: %d\n",
442
		     import_result->unchanged);
443
	fprintf_plus(stderr, "The number of new user IDs: %d\n",
444
		     import_result->new_user_ids);
445
	fprintf_plus(stderr, "The number of new sub keys: %d\n",
446
		     import_result->new_sub_keys);
447
	fprintf_plus(stderr, "The number of new signatures: %d\n",
448
		     import_result->new_signatures);
449
	fprintf_plus(stderr, "The number of new revocations: %d\n",
450
		     import_result->new_revocations);
451
	fprintf_plus(stderr,
452
		     "The total number of secret keys read: %d\n",
453
		     import_result->secret_read);
454
	fprintf_plus(stderr,
455
		     "The number of imported secret keys: %d\n",
456
		     import_result->secret_imported);
457
	fprintf_plus(stderr,
458
		     "The number of unchanged secret keys: %d\n",
459
		     import_result->secret_unchanged);
460
	fprintf_plus(stderr, "The number of keys not imported: %d\n",
461
		     import_result->not_imported);
462
	for(gpgme_import_status_t import_status
463
	      = import_result->imports;
464
	    import_status != NULL;
465
	    import_status = import_status->next){
466
	  fprintf_plus(stderr, "Import status for key: %s\n",
467
		       import_status->fpr);
468
	  if(import_status->result != GPG_ERR_NO_ERROR){
469
	    fprintf_plus(stderr, "Import result: %s: %s\n",
470
			 gpgme_strsource(import_status->result),
471
			 gpgme_strerror(import_status->result));
472
	  }
473
	  fprintf_plus(stderr, "Key status:\n");
474
	  fprintf_plus(stderr,
475
		       import_status->status & GPGME_IMPORT_NEW
476
		       ? "The key was new.\n"
477
		       : "The key was not new.\n");
478
	  fprintf_plus(stderr,
479
		       import_status->status & GPGME_IMPORT_UID
480
		       ? "The key contained new user IDs.\n"
481
		       : "The key did not contain new user IDs.\n");
482
	  fprintf_plus(stderr,
483
		       import_status->status & GPGME_IMPORT_SIG
484
		       ? "The key contained new signatures.\n"
485
		       : "The key did not contain new signatures.\n");
486
	  fprintf_plus(stderr,
487
		       import_status->status & GPGME_IMPORT_SUBKEY
488
		       ? "The key contained new sub keys.\n"
489
		       : "The key did not contain new sub keys.\n");
490
	  fprintf_plus(stderr,
491
		       import_status->status & GPGME_IMPORT_SECRET
492
		       ? "The key contained a secret key.\n"
493
		       : "The key did not contain a secret key.\n");
494
	}
495
	return false;
496
      }
497
    }
168 by Teddy Hogeborn
* initramfs-tools-hook: Use long options where available. Use only
498
    
774 by Teddy Hogeborn
Don't use TEMP_FAILURE_RETRY around close().
499
    ret = close(fd);
24.1.81 by Björn Påhlsson
removed keyring pre-requirement for starting password-request.
500
    if(ret == -1){
24.1.174 by Björn Påhlsson
* Makefile (CFLAGS): Added "-lrt" to include real time library.
501
      perror_plus("close");
24.1.81 by Björn Påhlsson
removed keyring pre-requirement for starting password-request.
502
    }
503
    gpgme_data_release(pgp_data);
504
    return true;
505
  }
39 by Teddy Hogeborn
* plugins.d/mandosclient.c (pgp_packet_decrypt): Renamed variables.
506
  
266 by Teddy Hogeborn
* plugin-runner.c: Only space changes.
507
  if(debug){
505.2.6 by Björn Påhlsson
replace calls to fprintf with fprintf_plus.
508
    fprintf_plus(stderr, "Initializing GPGME\n");
15.1.1 by Björn Påhlsson
Added debugg support in form off --debug and --debug=mandosclient
509
  }
168 by Teddy Hogeborn
* initramfs-tools-hook: Use long options where available. Use only
510
  
13 by Björn Påhlsson
Added following support:
511
  /* Init GPGME */
512
  gpgme_check_version(NULL);
24.1.4 by Björn Påhlsson
Added optional parameters certdir, certkey and certfile that can be iven at start in the command line.
513
  rc = gpgme_engine_check_version(GPGME_PROTOCOL_OpenPGP);
266 by Teddy Hogeborn
* plugin-runner.c: Only space changes.
514
  if(rc != GPG_ERR_NO_ERROR){
505.2.6 by Björn Påhlsson
replace calls to fprintf with fprintf_plus.
515
    fprintf_plus(stderr, "bad gpgme_engine_check_version: %s: %s\n",
505.3.9 by Teddy Hogeborn
* plugins.d/mandos-client.c: Merge unified printing system.
516
		 gpgme_strsource(rc), gpgme_strerror(rc));
24.1.81 by Björn Påhlsson
removed keyring pre-requirement for starting password-request.
517
    return false;
24.1.4 by Björn Påhlsson
Added optional parameters certdir, certkey and certfile that can be iven at start in the command line.
518
  }
168 by Teddy Hogeborn
* initramfs-tools-hook: Use long options where available. Use only
519
  
492 by Teddy Hogeborn
* plugins.d/mandos-client.c (main): Do not even try to work around
520
  /* Set GPGME home directory for the OpenPGP engine only */
266 by Teddy Hogeborn
* plugin-runner.c: Only space changes.
521
  rc = gpgme_get_engine_info(&engine_info);
522
  if(rc != GPG_ERR_NO_ERROR){
505.2.6 by Björn Påhlsson
replace calls to fprintf with fprintf_plus.
523
    fprintf_plus(stderr, "bad gpgme_get_engine_info: %s: %s\n",
505.3.9 by Teddy Hogeborn
* plugins.d/mandos-client.c: Merge unified printing system.
524
		 gpgme_strsource(rc), gpgme_strerror(rc));
24.1.81 by Björn Påhlsson
removed keyring pre-requirement for starting password-request.
525
    return false;
13 by Björn Påhlsson
Added following support:
526
  }
527
  while(engine_info != NULL){
528
    if(engine_info->protocol == GPGME_PROTOCOL_OpenPGP){
529
      gpgme_set_engine_info(GPGME_PROTOCOL_OpenPGP,
24.1.81 by Björn Påhlsson
removed keyring pre-requirement for starting password-request.
530
			    engine_info->file_name, tempdir);
13 by Björn Påhlsson
Added following support:
531
      break;
532
    }
533
    engine_info = engine_info->next;
534
  }
535
  if(engine_info == NULL){
505.3.9 by Teddy Hogeborn
* plugins.d/mandos-client.c: Merge unified printing system.
536
    fprintf_plus(stderr, "Could not set GPGME home dir to %s\n",
537
		 tempdir);
24.1.81 by Björn Påhlsson
removed keyring pre-requirement for starting password-request.
538
    return false;
539
  }
168 by Teddy Hogeborn
* initramfs-tools-hook: Use long options where available. Use only
540
  
24.1.81 by Björn Påhlsson
removed keyring pre-requirement for starting password-request.
541
  /* Create new GPGME "context" */
602 by Teddy Hogeborn
* plugins.d/mandos-client (mandos_context): Moved to inside "main()".
542
  rc = gpgme_new(&(mc->ctx));
266 by Teddy Hogeborn
* plugin-runner.c: Only space changes.
543
  if(rc != GPG_ERR_NO_ERROR){
946 by Teddy Hogeborn
Remove duplicate "Mandos plugin mandos-client:" in error output
544
    fprintf_plus(stderr, "bad gpgme_new: %s: %s\n",
545
		 gpgme_strsource(rc), gpgme_strerror(rc));
24.1.81 by Björn Påhlsson
removed keyring pre-requirement for starting password-request.
546
    return false;
547
  }
548
  
266 by Teddy Hogeborn
* plugin-runner.c: Only space changes.
549
  if(not import_key(pubkey) or not import_key(seckey)){
24.1.81 by Björn Påhlsson
removed keyring pre-requirement for starting password-request.
550
    return false;
551
  }
552
  
355 by Teddy Hogeborn
* mandos: White-space fixes only.
553
  return true;
24.1.81 by Björn Påhlsson
removed keyring pre-requirement for starting password-request.
554
}
555
556
/* 
557
 * Decrypt OpenPGP data.
558
 * Returns -1 on error
559
 */
672 by Teddy Hogeborn
Update GCC warning flags and function attributes to GCC 4.7.
560
__attribute__((nonnull, warn_unused_result))
24.1.134 by Björn Påhlsson
plugin-runner: Added support for empty string arguments
561
static ssize_t pgp_packet_decrypt(const char *cryptotext,
266 by Teddy Hogeborn
* plugin-runner.c: Only space changes.
562
				  size_t crypto_size,
602 by Teddy Hogeborn
* plugins.d/mandos-client (mandos_context): Moved to inside "main()".
563
				  char **plaintext,
564
				  mandos_context *mc){
24.1.81 by Björn Påhlsson
removed keyring pre-requirement for starting password-request.
565
  gpgme_data_t dh_crypto, dh_plain;
566
  gpgme_error_t rc;
567
  ssize_t ret;
568
  size_t plaintext_capacity = 0;
569
  ssize_t plaintext_length = 0;
570
  
266 by Teddy Hogeborn
* plugin-runner.c: Only space changes.
571
  if(debug){
505.2.6 by Björn Påhlsson
replace calls to fprintf with fprintf_plus.
572
    fprintf_plus(stderr, "Trying to decrypt OpenPGP data\n");
13 by Björn Påhlsson
Added following support:
573
  }
574
  
39 by Teddy Hogeborn
* plugins.d/mandosclient.c (pgp_packet_decrypt): Renamed variables.
575
  /* Create new GPGME data buffer from memory cryptotext */
576
  rc = gpgme_data_new_from_mem(&dh_crypto, cryptotext, crypto_size,
577
			       0);
266 by Teddy Hogeborn
* plugin-runner.c: Only space changes.
578
  if(rc != GPG_ERR_NO_ERROR){
505.2.6 by Björn Påhlsson
replace calls to fprintf with fprintf_plus.
579
    fprintf_plus(stderr, "bad gpgme_data_new_from_mem: %s: %s\n",
505.3.9 by Teddy Hogeborn
* plugins.d/mandos-client.c: Merge unified printing system.
580
		 gpgme_strsource(rc), gpgme_strerror(rc));
13 by Björn Påhlsson
Added following support:
581
    return -1;
582
  }
583
  
584
  /* Create new empty GPGME data buffer for the plaintext */
585
  rc = gpgme_data_new(&dh_plain);
266 by Teddy Hogeborn
* plugin-runner.c: Only space changes.
586
  if(rc != GPG_ERR_NO_ERROR){
946 by Teddy Hogeborn
Remove duplicate "Mandos plugin mandos-client:" in error output
587
    fprintf_plus(stderr, "bad gpgme_data_new: %s: %s\n",
505.3.9 by Teddy Hogeborn
* plugins.d/mandos-client.c: Merge unified printing system.
588
		 gpgme_strsource(rc), gpgme_strerror(rc));
39 by Teddy Hogeborn
* plugins.d/mandosclient.c (pgp_packet_decrypt): Renamed variables.
589
    gpgme_data_release(dh_crypto);
13 by Björn Påhlsson
Added following support:
590
    return -1;
591
  }
592
  
39 by Teddy Hogeborn
* plugins.d/mandosclient.c (pgp_packet_decrypt): Renamed variables.
593
  /* Decrypt data from the cryptotext data buffer to the plaintext
594
     data buffer */
602 by Teddy Hogeborn
* plugins.d/mandos-client (mandos_context): Moved to inside "main()".
595
  rc = gpgme_op_decrypt(mc->ctx, dh_crypto, dh_plain);
266 by Teddy Hogeborn
* plugin-runner.c: Only space changes.
596
  if(rc != GPG_ERR_NO_ERROR){
505.2.6 by Björn Påhlsson
replace calls to fprintf with fprintf_plus.
597
    fprintf_plus(stderr, "bad gpgme_op_decrypt: %s: %s\n",
505.3.9 by Teddy Hogeborn
* plugins.d/mandos-client.c: Merge unified printing system.
598
		 gpgme_strsource(rc), gpgme_strerror(rc));
39 by Teddy Hogeborn
* plugins.d/mandosclient.c (pgp_packet_decrypt): Renamed variables.
599
    plaintext_length = -1;
266 by Teddy Hogeborn
* plugin-runner.c: Only space changes.
600
    if(debug){
99 by Teddy Hogeborn
* mandos (fingerprint): Bug fix: Check crtverify.value, not crtverify.
601
      gpgme_decrypt_result_t result;
602 by Teddy Hogeborn
* plugins.d/mandos-client (mandos_context): Moved to inside "main()".
602
      result = gpgme_op_decrypt_result(mc->ctx);
266 by Teddy Hogeborn
* plugin-runner.c: Only space changes.
603
      if(result == NULL){
505.2.6 by Björn Påhlsson
replace calls to fprintf with fprintf_plus.
604
	fprintf_plus(stderr, "gpgme_op_decrypt_result failed\n");
99 by Teddy Hogeborn
* mandos (fingerprint): Bug fix: Check crtverify.value, not crtverify.
605
      } else {
944 by Teddy Hogeborn
Don't print NULL string pointers in error message output
606
	if(result->unsupported_algorithm != NULL) {
607
	  fprintf_plus(stderr, "Unsupported algorithm: %s\n",
608
		       result->unsupported_algorithm);
609
	}
945 by Teddy Hogeborn
Print a boolean more readably in error message output
610
	fprintf_plus(stderr, "Wrong key usage: %s\n",
611
		     result->wrong_key_usage ? "Yes" : "No");
99 by Teddy Hogeborn
* mandos (fingerprint): Bug fix: Check crtverify.value, not crtverify.
612
	if(result->file_name != NULL){
505.2.6 by Björn Påhlsson
replace calls to fprintf with fprintf_plus.
613
	  fprintf_plus(stderr, "File name: %s\n", result->file_name);
99 by Teddy Hogeborn
* mandos (fingerprint): Bug fix: Check crtverify.value, not crtverify.
614
	}
948 by Teddy Hogeborn
Minor code cleanup
615
616
	for(gpgme_recipient_t r = result->recipients; r != NULL;
617
	    r = r->next){
505.2.6 by Björn Påhlsson
replace calls to fprintf with fprintf_plus.
618
	  fprintf_plus(stderr, "Public key algorithm: %s\n",
948 by Teddy Hogeborn
Minor code cleanup
619
		       gpgme_pubkey_algo_name(r->pubkey_algo));
620
	  fprintf_plus(stderr, "Key ID: %s\n", r->keyid);
505.2.6 by Björn Påhlsson
replace calls to fprintf with fprintf_plus.
621
	  fprintf_plus(stderr, "Secret key available: %s\n",
948 by Teddy Hogeborn
Minor code cleanup
622
		       r->status == GPG_ERR_NO_SECKEY ? "No" : "Yes");
99 by Teddy Hogeborn
* mandos (fingerprint): Bug fix: Check crtverify.value, not crtverify.
623
	}
624
      }
625
    }
39 by Teddy Hogeborn
* plugins.d/mandosclient.c (pgp_packet_decrypt): Renamed variables.
626
    goto decrypt_end;
13 by Björn Påhlsson
Added following support:
627
  }
39 by Teddy Hogeborn
* plugins.d/mandosclient.c (pgp_packet_decrypt): Renamed variables.
628
  
15.1.1 by Björn Påhlsson
Added debugg support in form off --debug and --debug=mandosclient
629
  if(debug){
505.2.6 by Björn Påhlsson
replace calls to fprintf with fprintf_plus.
630
    fprintf_plus(stderr, "Decryption of OpenPGP data succeeded\n");
15.1.1 by Björn Påhlsson
Added debugg support in form off --debug and --debug=mandosclient
631
  }
39 by Teddy Hogeborn
* plugins.d/mandosclient.c (pgp_packet_decrypt): Renamed variables.
632
  
13 by Björn Påhlsson
Added following support:
633
  /* Seek back to the beginning of the GPGME plaintext data buffer */
266 by Teddy Hogeborn
* plugin-runner.c: Only space changes.
634
  if(gpgme_data_seek(dh_plain, (off_t)0, SEEK_SET) == -1){
24.1.174 by Björn Påhlsson
* Makefile (CFLAGS): Added "-lrt" to include real time library.
635
    perror_plus("gpgme_data_seek");
39 by Teddy Hogeborn
* plugins.d/mandosclient.c (pgp_packet_decrypt): Renamed variables.
636
    plaintext_length = -1;
637
    goto decrypt_end;
24.1.5 by Björn Påhlsson
plugbasedclient:
638
  }
639
  
39 by Teddy Hogeborn
* plugins.d/mandosclient.c (pgp_packet_decrypt): Renamed variables.
640
  *plaintext = NULL;
13 by Björn Påhlsson
Added following support:
641
  while(true){
24.1.132 by Björn Påhlsson
Fixed a bug in fallback handling
642
    plaintext_capacity = incbuffer(plaintext,
505.3.6 by teddy at bsnet
* plugins.d/mandos-client.c: Some white space fixes.
643
				   (size_t)plaintext_length,
644
				   plaintext_capacity);
266 by Teddy Hogeborn
* plugin-runner.c: Only space changes.
645
    if(plaintext_capacity == 0){
505.3.6 by teddy at bsnet
* plugins.d/mandos-client.c: Some white space fixes.
646
      perror_plus("incbuffer");
647
      plaintext_length = -1;
648
      goto decrypt_end;
13 by Björn Påhlsson
Added following support:
649
    }
650
    
39 by Teddy Hogeborn
* plugins.d/mandosclient.c (pgp_packet_decrypt): Renamed variables.
651
    ret = gpgme_data_read(dh_plain, *plaintext + plaintext_length,
21 by Teddy Hogeborn
* Makefile (CFLAGS): Changed to use $(WARN), $(DEBUG), $(COVERAGE) and
652
			  BUFFER_SIZE);
13 by Björn Påhlsson
Added following support:
653
    /* Print the data, if any */
266 by Teddy Hogeborn
* plugin-runner.c: Only space changes.
654
    if(ret == 0){
39 by Teddy Hogeborn
* plugins.d/mandosclient.c (pgp_packet_decrypt): Renamed variables.
655
      /* EOF */
13 by Björn Påhlsson
Added following support:
656
      break;
657
    }
658
    if(ret < 0){
24.1.174 by Björn Påhlsson
* Makefile (CFLAGS): Added "-lrt" to include real time library.
659
      perror_plus("gpgme_data_read");
39 by Teddy Hogeborn
* plugins.d/mandosclient.c (pgp_packet_decrypt): Renamed variables.
660
      plaintext_length = -1;
661
      goto decrypt_end;
13 by Björn Påhlsson
Added following support:
662
    }
39 by Teddy Hogeborn
* plugins.d/mandosclient.c (pgp_packet_decrypt): Renamed variables.
663
    plaintext_length += ret;
13 by Björn Påhlsson
Added following support:
664
  }
143 by Teddy Hogeborn
* Makefile (mandos.8): Add dependency on "overview.xml" and
665
  
39 by Teddy Hogeborn
* plugins.d/mandosclient.c (pgp_packet_decrypt): Renamed variables.
666
  if(debug){
505.2.6 by Björn Påhlsson
replace calls to fprintf with fprintf_plus.
667
    fprintf_plus(stderr, "Decrypted password is: ");
40 by Teddy Hogeborn
* plugins.d/mandosclient.c (initgnutls): Moved "err" variable into its
668
    for(ssize_t i = 0; i < plaintext_length; i++){
39 by Teddy Hogeborn
* plugins.d/mandosclient.c (pgp_packet_decrypt): Renamed variables.
669
      fprintf(stderr, "%02hhX ", (*plaintext)[i]);
670
    }
671
    fprintf(stderr, "\n");
672
  }
673
  
674
 decrypt_end:
675
  
676
  /* Delete the GPGME cryptotext data buffer */
677
  gpgme_data_release(dh_crypto);
15.1.3 by Björn Påhlsson
Added getopt_long support for mandosclient and passprompt
678
  
679
  /* Delete the GPGME plaintext data buffer */
13 by Björn Påhlsson
Added following support:
680
  gpgme_data_release(dh_plain);
39 by Teddy Hogeborn
* plugins.d/mandosclient.c (pgp_packet_decrypt): Renamed variables.
681
  return plaintext_length;
13 by Björn Påhlsson
Added following support:
682
}
683
743 by Teddy Hogeborn
Automatically determine the number of DH bits in the TLS handshake.
684
__attribute__((warn_unused_result, const))
685
static const char *safe_string(const char *str){
686
  if(str == NULL)
687
    return "(unknown)";
688
  return str;
689
}
690
672 by Teddy Hogeborn
Update GCC warning flags and function attributes to GCC 4.7.
691
__attribute__((warn_unused_result))
692
static const char *safer_gnutls_strerror(int value){
597 by Teddy Hogeborn
* plugins.d/mandos-client.c: Don't use assert(). Use in_port_t for
693
  const char *ret = gnutls_strerror(value);
743 by Teddy Hogeborn
Automatically determine the number of DH bits in the TLS handshake.
694
  return safe_string(ret);
13 by Björn Påhlsson
Added following support:
695
}
696
40 by Teddy Hogeborn
* plugins.d/mandosclient.c (initgnutls): Moved "err" variable into its
697
/* GnuTLS log function callback */
672 by Teddy Hogeborn
Update GCC warning flags and function attributes to GCC 4.7.
698
__attribute__((nonnull))
36 by Teddy Hogeborn
* TODO: Converted to org-mode style
699
static void debuggnutls(__attribute__((unused)) int level,
700
			const char* string){
505.2.6 by Björn Påhlsson
replace calls to fprintf with fprintf_plus.
701
  fprintf_plus(stderr, "GnuTLS: %s", string);
13 by Björn Påhlsson
Added following support:
702
}
703
811 by Teddy Hogeborn
Client: Remove an incorrect "nonnull" attribute
704
__attribute__((nonnull(1, 2, 4), warn_unused_result))
24.1.134 by Björn Påhlsson
plugin-runner: Added support for empty string arguments
705
static int init_gnutls_global(const char *pubkeyfilename,
602 by Teddy Hogeborn
* plugins.d/mandos-client (mandos_context): Moved to inside "main()".
706
			      const char *seckeyfilename,
762 by Teddy Hogeborn
mandos-client: Add --dh-params FILE option.
707
			      const char *dhparamsfilename,
602 by Teddy Hogeborn
* plugins.d/mandos-client (mandos_context): Moved to inside "main()".
708
			      mandos_context *mc){
13 by Björn Påhlsson
Added following support:
709
  int ret;
21 by Teddy Hogeborn
* Makefile (CFLAGS): Changed to use $(WARN), $(DEBUG), $(COVERAGE) and
710
  
15.1.1 by Björn Påhlsson
Added debugg support in form off --debug and --debug=mandosclient
711
  if(debug){
505.2.6 by Björn Påhlsson
replace calls to fprintf with fprintf_plus.
712
    fprintf_plus(stderr, "Initializing GnuTLS\n");
15.1.1 by Björn Påhlsson
Added debugg support in form off --debug and --debug=mandosclient
713
  }
24.1.29 by Björn Påhlsson
Added more header file comments
714
  
266 by Teddy Hogeborn
* plugin-runner.c: Only space changes.
715
  if(debug){
40 by Teddy Hogeborn
* plugins.d/mandosclient.c (initgnutls): Moved "err" variable into its
716
    /* "Use a log level over 10 to enable all debugging options."
717
     * - GnuTLS manual
718
     */
15.1.1 by Björn Påhlsson
Added debugg support in form off --debug and --debug=mandosclient
719
    gnutls_global_set_log_level(11);
720
    gnutls_global_set_log_function(debuggnutls);
721
  }
722
  
40 by Teddy Hogeborn
* plugins.d/mandosclient.c (initgnutls): Moved "err" variable into its
723
  /* OpenPGP credentials */
602 by Teddy Hogeborn
* plugins.d/mandos-client (mandos_context): Moved to inside "main()".
724
  ret = gnutls_certificate_allocate_credentials(&mc->cred);
266 by Teddy Hogeborn
* plugin-runner.c: Only space changes.
725
  if(ret != GNUTLS_E_SUCCESS){
505.3.9 by Teddy Hogeborn
* plugins.d/mandos-client.c: Merge unified printing system.
726
    fprintf_plus(stderr, "GnuTLS memory error: %s\n",
727
		 safer_gnutls_strerror(ret));
13 by Björn Påhlsson
Added following support:
728
    return -1;
729
  }
21 by Teddy Hogeborn
* Makefile (CFLAGS): Changed to use $(WARN), $(DEBUG), $(COVERAGE) and
730
  
15.1.1 by Björn Påhlsson
Added debugg support in form off --debug and --debug=mandosclient
731
  if(debug){
962 by Teddy Hogeborn
Add support for using raw public keys in TLS (RFC 7250)
732
    fprintf_plus(stderr, "Attempting to use public key %s and"
733
		 " private key %s as GnuTLS credentials\n",
505.3.9 by Teddy Hogeborn
* plugins.d/mandos-client.c: Merge unified printing system.
734
		 pubkeyfilename,
735
		 seckeyfilename);
15.1.1 by Björn Påhlsson
Added debugg support in form off --debug and --debug=mandosclient
736
  }
21 by Teddy Hogeborn
* Makefile (CFLAGS): Changed to use $(WARN), $(DEBUG), $(COVERAGE) and
737
  
962 by Teddy Hogeborn
Add support for using raw public keys in TLS (RFC 7250)
738
#if GNUTLS_VERSION_NUMBER >= 0x030606
739
  ret = gnutls_certificate_set_rawpk_key_file
740
    (mc->cred, pubkeyfilename, seckeyfilename,
741
     GNUTLS_X509_FMT_PEM,	/* format */
742
     NULL,			/* pass */
743
     /* key_usage */
744
     GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT,
745
     NULL, 			/* names */
746
     0,				/* names_length */
747
     /* privkey_flags */
748
     GNUTLS_PKCS_PLAIN | GNUTLS_PKCS_NULL_PASSWORD,
749
     0);			/* pkcs11_flags */
750
#elif GNUTLS_VERSION_NUMBER < 0x030600
13 by Björn Påhlsson
Added following support:
751
  ret = gnutls_certificate_set_openpgp_key_file
602 by Teddy Hogeborn
* plugins.d/mandos-client (mandos_context): Moved to inside "main()".
752
    (mc->cred, pubkeyfilename, seckeyfilename,
76 by Teddy Hogeborn
* plugins.d/password-request.c (init_gnutls_global): Renamed
753
     GNUTLS_OPENPGP_FMT_BASE64);
962 by Teddy Hogeborn
Add support for using raw public keys in TLS (RFC 7250)
754
#else
755
#error "Needs GnuTLS 3.6.6 or later, or before 3.6.0"
756
#endif
293 by Teddy Hogeborn
* plugin-runner.c: Whitespace changes only.
757
  if(ret != GNUTLS_E_SUCCESS){
505.2.6 by Björn Påhlsson
replace calls to fprintf with fprintf_plus.
758
    fprintf_plus(stderr,
962 by Teddy Hogeborn
Add support for using raw public keys in TLS (RFC 7250)
759
		 "Error[%d] while reading the key pair ('%s',"
505.2.6 by Björn Påhlsson
replace calls to fprintf with fprintf_plus.
760
		 " '%s')\n", ret, pubkeyfilename, seckeyfilename);
505.3.9 by Teddy Hogeborn
* plugins.d/mandos-client.c: Merge unified printing system.
761
    fprintf_plus(stderr, "The GnuTLS error is: %s\n",
762
		 safer_gnutls_strerror(ret));
24.1.20 by Björn Påhlsson
mandosclient
763
    goto globalfail;
13 by Björn Påhlsson
Added following support:
764
  }
21 by Teddy Hogeborn
* Makefile (CFLAGS): Changed to use $(WARN), $(DEBUG), $(COVERAGE) and
765
  
40 by Teddy Hogeborn
* plugins.d/mandosclient.c (initgnutls): Moved "err" variable into its
766
  /* GnuTLS server initialization */
602 by Teddy Hogeborn
* plugins.d/mandos-client (mandos_context): Moved to inside "main()".
767
  ret = gnutls_dh_params_init(&mc->dh_params);
293 by Teddy Hogeborn
* plugin-runner.c: Whitespace changes only.
768
  if(ret != GNUTLS_E_SUCCESS){
505.3.9 by Teddy Hogeborn
* plugins.d/mandos-client.c: Merge unified printing system.
769
    fprintf_plus(stderr, "Error in GnuTLS DH parameter"
770
		 " initialization: %s\n",
771
		 safer_gnutls_strerror(ret));
24.1.20 by Björn Påhlsson
mandosclient
772
    goto globalfail;
13 by Björn Påhlsson
Added following support:
773
  }
762 by Teddy Hogeborn
mandos-client: Add --dh-params FILE option.
774
  /* If a Diffie-Hellman parameters file was given, try to use it */
775
  if(dhparamsfilename != NULL){
776
    gnutls_datum_t params = { .data = NULL, .size = 0 };
777
    do {
778
      int dhpfile = open(dhparamsfilename, O_RDONLY);
779
      if(dhpfile == -1){
780
	perror_plus("open");
781
	dhparamsfilename = NULL;
782
	break;
783
      }
784
      size_t params_capacity = 0;
743 by Teddy Hogeborn
Automatically determine the number of DH bits in the TLS handshake.
785
      while(true){
762 by Teddy Hogeborn
mandos-client: Add --dh-params FILE option.
786
	params_capacity = incbuffer((char **)&params.data,
787
				    (size_t)params.size,
788
				    (size_t)params_capacity);
789
	if(params_capacity == 0){
743 by Teddy Hogeborn
Automatically determine the number of DH bits in the TLS handshake.
790
	  perror_plus("incbuffer");
762 by Teddy Hogeborn
mandos-client: Add --dh-params FILE option.
791
	  free(params.data);
792
	  params.data = NULL;
793
	  dhparamsfilename = NULL;
743 by Teddy Hogeborn
Automatically determine the number of DH bits in the TLS handshake.
794
	  break;
795
	}
762 by Teddy Hogeborn
mandos-client: Add --dh-params FILE option.
796
	ssize_t bytes_read = read(dhpfile,
797
				  params.data + params.size,
743 by Teddy Hogeborn
Automatically determine the number of DH bits in the TLS handshake.
798
				  BUFFER_SIZE);
799
	/* EOF */
800
	if(bytes_read == 0){
801
	  break;
802
	}
803
	/* check bytes_read for failure */
804
	if(bytes_read < 0){
805
	  perror_plus("read");
762 by Teddy Hogeborn
mandos-client: Add --dh-params FILE option.
806
	  free(params.data);
807
	  params.data = NULL;
808
	  dhparamsfilename = NULL;
809
	  break;
810
	}
811
	params.size += (unsigned int)bytes_read;
812
      }
941 by Teddy Hogeborn
Check return values from newly added close() calls
813
      ret = close(dhpfile);
814
      if(ret == -1){
815
	perror_plus("close");
816
      }
762 by Teddy Hogeborn
mandos-client: Add --dh-params FILE option.
817
      if(params.data == NULL){
818
	dhparamsfilename = NULL;
819
      }
820
      if(dhparamsfilename == NULL){
821
	break;
822
      }
823
      ret = gnutls_dh_params_import_pkcs3(mc->dh_params, &params,
824
					  GNUTLS_X509_FMT_PEM);
825
      if(ret != GNUTLS_E_SUCCESS){
826
	fprintf_plus(stderr, "Failed to parse DH parameters in file"
827
		     " \"%s\": %s\n", dhparamsfilename,
828
		     safer_gnutls_strerror(ret));
829
	dhparamsfilename = NULL;
830
      }
877 by Teddy Hogeborn
Fix bug where Mandos client would crash on exit
831
      free(params.data);
762 by Teddy Hogeborn
mandos-client: Add --dh-params FILE option.
832
    } while(false);
833
  }
834
  if(dhparamsfilename == NULL){
835
    if(mc->dh_bits == 0){
962 by Teddy Hogeborn
Add support for using raw public keys in TLS (RFC 7250)
836
#if GNUTLS_VERSION_NUMBER < 0x030600
762 by Teddy Hogeborn
mandos-client: Add --dh-params FILE option.
837
      /* Find out the optimal number of DH bits */
838
      /* Try to read the private key file */
839
      gnutls_datum_t buffer = { .data = NULL, .size = 0 };
840
      do {
841
	int secfile = open(seckeyfilename, O_RDONLY);
842
	if(secfile == -1){
843
	  perror_plus("open");
844
	  break;
845
	}
846
	size_t buffer_capacity = 0;
847
	while(true){
848
	  buffer_capacity = incbuffer((char **)&buffer.data,
849
				      (size_t)buffer.size,
850
				      (size_t)buffer_capacity);
851
	  if(buffer_capacity == 0){
852
	    perror_plus("incbuffer");
853
	    free(buffer.data);
854
	    buffer.data = NULL;
855
	    break;
856
	  }
857
	  ssize_t bytes_read = read(secfile,
858
				    buffer.data + buffer.size,
859
				    BUFFER_SIZE);
860
	  /* EOF */
861
	  if(bytes_read == 0){
862
	    break;
863
	  }
864
	  /* check bytes_read for failure */
865
	  if(bytes_read < 0){
866
	    perror_plus("read");
867
	    free(buffer.data);
868
	    buffer.data = NULL;
869
	    break;
870
	  }
871
	  buffer.size += (unsigned int)bytes_read;
872
	}
873
	close(secfile);
874
      } while(false);
875
      /* If successful, use buffer to parse private key */
876
      gnutls_sec_param_t sec_param = GNUTLS_SEC_PARAM_ULTRA;
877
      if(buffer.data != NULL){
878
	{
879
	  gnutls_openpgp_privkey_t privkey = NULL;
880
	  ret = gnutls_openpgp_privkey_init(&privkey);
743 by Teddy Hogeborn
Automatically determine the number of DH bits in the TLS handshake.
881
	  if(ret != GNUTLS_E_SUCCESS){
762 by Teddy Hogeborn
mandos-client: Add --dh-params FILE option.
882
	    fprintf_plus(stderr, "Error initializing OpenPGP key"
883
			 " structure: %s",
743 by Teddy Hogeborn
Automatically determine the number of DH bits in the TLS handshake.
884
			 safer_gnutls_strerror(ret));
762 by Teddy Hogeborn
mandos-client: Add --dh-params FILE option.
885
	    free(buffer.data);
886
	    buffer.data = NULL;
887
	  } else {
888
	    ret = gnutls_openpgp_privkey_import
889
	      (privkey, &buffer, GNUTLS_OPENPGP_FMT_BASE64, "", 0);
890
	    if(ret != GNUTLS_E_SUCCESS){
891
	      fprintf_plus(stderr, "Error importing OpenPGP key : %s",
892
			   safer_gnutls_strerror(ret));
893
	      privkey = NULL;
894
	    }
895
	    free(buffer.data);
896
	    buffer.data = NULL;
897
	    if(privkey != NULL){
898
	      /* Use private key to suggest an appropriate
899
		 sec_param */
900
	      sec_param = gnutls_openpgp_privkey_sec_param(privkey);
901
	      gnutls_openpgp_privkey_deinit(privkey);
902
	      if(debug){
903
		fprintf_plus(stderr, "This OpenPGP key implies using"
904
			     " a GnuTLS security parameter \"%s\".\n",
905
			     safe_string(gnutls_sec_param_get_name
906
					 (sec_param)));
907
	      }
908
	    }
743 by Teddy Hogeborn
Automatically determine the number of DH bits in the TLS handshake.
909
	  }
762 by Teddy Hogeborn
mandos-client: Add --dh-params FILE option.
910
	}
911
	if(sec_param == GNUTLS_SEC_PARAM_UNKNOWN){
912
	  /* Err on the side of caution */
913
	  sec_param = GNUTLS_SEC_PARAM_ULTRA;
914
	  if(debug){
915
	    fprintf_plus(stderr, "Falling back to security parameter"
916
			 " \"%s\"\n",
917
			 safe_string(gnutls_sec_param_get_name
918
				     (sec_param)));
743 by Teddy Hogeborn
Automatically determine the number of DH bits in the TLS handshake.
919
	  }
920
	}
921
      }
962 by Teddy Hogeborn
Add support for using raw public keys in TLS (RFC 7250)
922
      unsigned int uret = gnutls_sec_param_to_pk_bits(GNUTLS_PK_DH, sec_param);
762 by Teddy Hogeborn
mandos-client: Add --dh-params FILE option.
923
      if(uret != 0){
924
	mc->dh_bits = uret;
743 by Teddy Hogeborn
Automatically determine the number of DH bits in the TLS handshake.
925
	if(debug){
762 by Teddy Hogeborn
mandos-client: Add --dh-params FILE option.
926
	  fprintf_plus(stderr, "A \"%s\" GnuTLS security parameter"
927
		       " implies %u DH bits; using that.\n",
743 by Teddy Hogeborn
Automatically determine the number of DH bits in the TLS handshake.
928
		       safe_string(gnutls_sec_param_get_name
762 by Teddy Hogeborn
mandos-client: Add --dh-params FILE option.
929
				   (sec_param)),
930
		       mc->dh_bits);
743 by Teddy Hogeborn
Automatically determine the number of DH bits in the TLS handshake.
931
	}
762 by Teddy Hogeborn
mandos-client: Add --dh-params FILE option.
932
      } else {
933
	fprintf_plus(stderr, "Failed to get implied number of DH"
934
		     " bits for security parameter \"%s\"): %s\n",
743 by Teddy Hogeborn
Automatically determine the number of DH bits in the TLS handshake.
935
		     safe_string(gnutls_sec_param_get_name
936
				 (sec_param)),
762 by Teddy Hogeborn
mandos-client: Add --dh-params FILE option.
937
		     safer_gnutls_strerror(ret));
938
	goto globalfail;
743 by Teddy Hogeborn
Automatically determine the number of DH bits in the TLS handshake.
939
      }
962 by Teddy Hogeborn
Add support for using raw public keys in TLS (RFC 7250)
940
#endif
941
    } else {			/* dh_bits != 0 */
942
      if(debug){
943
	fprintf_plus(stderr, "DH bits explicitly set to %u\n",
944
		     mc->dh_bits);
945
      }
946
      ret = gnutls_dh_params_generate2(mc->dh_params, mc->dh_bits);
947
      if(ret != GNUTLS_E_SUCCESS){
948
	fprintf_plus(stderr, "Error in GnuTLS prime generation (%u"
949
		     " bits): %s\n", mc->dh_bits,
950
		     safer_gnutls_strerror(ret));
951
	goto globalfail;
952
      }
953
      gnutls_certificate_set_dh_params(mc->cred, mc->dh_params);
743 by Teddy Hogeborn
Automatically determine the number of DH bits in the TLS handshake.
954
    }
762 by Teddy Hogeborn
mandos-client: Add --dh-params FILE option.
955
  }
143 by Teddy Hogeborn
* Makefile (mandos.8): Add dependency on "overview.xml" and
956
  
24.1.13 by Björn Påhlsson
mandosclient
957
  return 0;
143 by Teddy Hogeborn
* Makefile (mandos.8): Add dependency on "overview.xml" and
958
  
24.1.20 by Björn Påhlsson
mandosclient
959
 globalfail:
143 by Teddy Hogeborn
* Makefile (mandos.8): Add dependency on "overview.xml" and
960
  
602 by Teddy Hogeborn
* plugins.d/mandos-client (mandos_context): Moved to inside "main()".
961
  gnutls_certificate_free_credentials(mc->cred);
962
  gnutls_dh_params_deinit(mc->dh_params);
24.1.20 by Björn Påhlsson
mandosclient
963
  return -1;
24.1.13 by Björn Påhlsson
mandosclient
964
}
965
672 by Teddy Hogeborn
Update GCC warning flags and function attributes to GCC 4.7.
966
__attribute__((nonnull, warn_unused_result))
602 by Teddy Hogeborn
* plugins.d/mandos-client (mandos_context): Moved to inside "main()".
967
static int init_gnutls_session(gnutls_session_t *session,
968
			       mandos_context *mc){
24.1.13 by Björn Påhlsson
mandosclient
969
  int ret;
40 by Teddy Hogeborn
* plugins.d/mandosclient.c (initgnutls): Moved "err" variable into its
970
  /* GnuTLS session creation */
368 by Teddy Hogeborn
* plugins.d/mandos-client.c (init_gnutls_session): Retry interrupted
971
  do {
962 by Teddy Hogeborn
Add support for using raw public keys in TLS (RFC 7250)
972
    ret = gnutls_init(session, (GNUTLS_SERVER
973
#if GNUTLS_VERSION_NUMBER >= 0x030506
974
				| GNUTLS_NO_TICKETS
975
#endif
976
#if GNUTLS_VERSION_NUMBER >= 0x030606
977
				| GNUTLS_ENABLE_RAWPK
978
#endif
979
				));
371 by Teddy Hogeborn
* plugins.d/mandos-client.c (init_gnutls_session): Always fail and
980
    if(quit_now){
981
      return -1;
982
    }
368 by Teddy Hogeborn
* plugins.d/mandos-client.c (init_gnutls_session): Retry interrupted
983
  } while(ret == GNUTLS_E_INTERRUPTED or ret == GNUTLS_E_AGAIN);
266 by Teddy Hogeborn
* plugin-runner.c: Only space changes.
984
  if(ret != GNUTLS_E_SUCCESS){
505.3.9 by Teddy Hogeborn
* plugins.d/mandos-client.c: Merge unified printing system.
985
    fprintf_plus(stderr,
986
		 "Error in GnuTLS session initialization: %s\n",
987
		 safer_gnutls_strerror(ret));
13 by Björn Påhlsson
Added following support:
988
  }
21 by Teddy Hogeborn
* Makefile (CFLAGS): Changed to use $(WARN), $(DEBUG), $(COVERAGE) and
989
  
40 by Teddy Hogeborn
* plugins.d/mandosclient.c (initgnutls): Moved "err" variable into its
990
  {
991
    const char *err;
368 by Teddy Hogeborn
* plugins.d/mandos-client.c (init_gnutls_session): Retry interrupted
992
    do {
602 by Teddy Hogeborn
* plugins.d/mandos-client (mandos_context): Moved to inside "main()".
993
      ret = gnutls_priority_set_direct(*session, mc->priority, &err);
371 by Teddy Hogeborn
* plugins.d/mandos-client.c (init_gnutls_session): Always fail and
994
      if(quit_now){
995
	gnutls_deinit(*session);
996
	return -1;
997
      }
368 by Teddy Hogeborn
* plugins.d/mandos-client.c (init_gnutls_session): Retry interrupted
998
    } while(ret == GNUTLS_E_INTERRUPTED or ret == GNUTLS_E_AGAIN);
293 by Teddy Hogeborn
* plugin-runner.c: Whitespace changes only.
999
    if(ret != GNUTLS_E_SUCCESS){
505.2.6 by Björn Påhlsson
replace calls to fprintf with fprintf_plus.
1000
      fprintf_plus(stderr, "Syntax error at: %s\n", err);
505.3.9 by Teddy Hogeborn
* plugins.d/mandos-client.c: Merge unified printing system.
1001
      fprintf_plus(stderr, "GnuTLS error: %s\n",
1002
		   safer_gnutls_strerror(ret));
266 by Teddy Hogeborn
* plugin-runner.c: Only space changes.
1003
      gnutls_deinit(*session);
40 by Teddy Hogeborn
* plugins.d/mandosclient.c (initgnutls): Moved "err" variable into its
1004
      return -1;
1005
    }
13 by Björn Påhlsson
Added following support:
1006
  }
21 by Teddy Hogeborn
* Makefile (CFLAGS): Changed to use $(WARN), $(DEBUG), $(COVERAGE) and
1007
  
368 by Teddy Hogeborn
* plugins.d/mandos-client.c (init_gnutls_session): Retry interrupted
1008
  do {
1009
    ret = gnutls_credentials_set(*session, GNUTLS_CRD_CERTIFICATE,
602 by Teddy Hogeborn
* plugins.d/mandos-client (mandos_context): Moved to inside "main()".
1010
				 mc->cred);
371 by Teddy Hogeborn
* plugins.d/mandos-client.c (init_gnutls_session): Always fail and
1011
    if(quit_now){
1012
      gnutls_deinit(*session);
1013
      return -1;
1014
    }
368 by Teddy Hogeborn
* plugins.d/mandos-client.c (init_gnutls_session): Retry interrupted
1015
  } while(ret == GNUTLS_E_INTERRUPTED or ret == GNUTLS_E_AGAIN);
293 by Teddy Hogeborn
* plugin-runner.c: Whitespace changes only.
1016
  if(ret != GNUTLS_E_SUCCESS){
505.2.6 by Björn Påhlsson
replace calls to fprintf with fprintf_plus.
1017
    fprintf_plus(stderr, "Error setting GnuTLS credentials: %s\n",
505.3.9 by Teddy Hogeborn
* plugins.d/mandos-client.c: Merge unified printing system.
1018
		 safer_gnutls_strerror(ret));
266 by Teddy Hogeborn
* plugin-runner.c: Only space changes.
1019
    gnutls_deinit(*session);
13 by Björn Påhlsson
Added following support:
1020
    return -1;
1021
  }
21 by Teddy Hogeborn
* Makefile (CFLAGS): Changed to use $(WARN), $(DEBUG), $(COVERAGE) and
1022
  
13 by Björn Påhlsson
Added following support:
1023
  /* ignore client certificate if any. */
368 by Teddy Hogeborn
* plugins.d/mandos-client.c (init_gnutls_session): Retry interrupted
1024
  gnutls_certificate_server_set_request(*session, GNUTLS_CERT_IGNORE);
13 by Björn Påhlsson
Added following support:
1025
  
1026
  return 0;
1027
}
1028
40 by Teddy Hogeborn
* plugins.d/mandosclient.c (initgnutls): Moved "err" variable into its
1029
/* Avahi log function callback */
36 by Teddy Hogeborn
* TODO: Converted to org-mode style
1030
static void empty_log(__attribute__((unused)) AvahiLogLevel level,
1031
		      __attribute__((unused)) const char *txt){}
13 by Björn Påhlsson
Added following support:
1032
738.1.6 by Teddy Hogeborn
Fix minor bugs and typos and add some more debug output.
1033
/* Helper function to add_local_route() and delete_local_route() */
738.1.2 by Teddy Hogeborn
mandos-client: Try to start a plugin to add and remove a local route.
1034
__attribute__((nonnull, warn_unused_result))
738.1.6 by Teddy Hogeborn
Fix minor bugs and typos and add some more debug output.
1035
static bool add_delete_local_route(const bool add,
738.1.2 by Teddy Hogeborn
mandos-client: Try to start a plugin to add and remove a local route.
1036
				   const char *address,
1037
				   AvahiIfIndex if_index){
1038
  int ret;
1039
  char helper[] = "mandos-client-iprouteadddel";
1040
  char add_arg[] = "add";
738.1.4 by Teddy Hogeborn
Add plugin for mandos-client to add and delete local routes.
1041
  char delete_arg[] = "delete";
738.1.6 by Teddy Hogeborn
Fix minor bugs and typos and add some more debug output.
1042
  char debug_flag[] = "--debug";
738.1.2 by Teddy Hogeborn
mandos-client: Try to start a plugin to add and remove a local route.
1043
  char *pluginhelperdir = getenv("MANDOSPLUGINHELPERDIR");
1044
  if(pluginhelperdir == NULL){
1045
    if(debug){
1046
      fprintf_plus(stderr, "MANDOSPLUGINHELPERDIR environment"
1047
		   " variable not set; cannot run helper\n");
1048
    }
1049
    return false;
1050
  }
1051
  
1052
  char interface[IF_NAMESIZE];
1053
  if(if_indextoname((unsigned int)if_index, interface) == NULL){
1054
    perror_plus("if_indextoname");
1055
    return false;
1056
  }
1057
  
1058
  int devnull = (int)TEMP_FAILURE_RETRY(open("/dev/null", O_RDONLY));
1059
  if(devnull == -1){
1060
    perror_plus("open(\"/dev/null\", O_RDONLY)");
1061
    return false;
1062
  }
1063
  pid_t pid = fork();
1064
  if(pid == 0){
1065
    /* Child */
1066
    /* Raise privileges */
1067
    errno = raise_privileges_permanently();
1068
    if(errno != 0){
1069
      perror_plus("Failed to raise privileges");
1070
      /* _exit(EX_NOPERM); */
1071
    } else {
1072
      /* Set group */
1073
      errno = 0;
1074
      ret = setgid(0);
1075
      if(ret == -1){
1076
	perror_plus("setgid");
1213 by teddy at recompile
Fix file descriptor leak in mandos-client
1077
	close(devnull);
738.1.2 by Teddy Hogeborn
mandos-client: Try to start a plugin to add and remove a local route.
1078
	_exit(EX_NOPERM);
1079
      }
1080
      /* Reset supplementary groups */
1081
      errno = 0;
1082
      ret = setgroups(0, NULL);
1083
      if(ret == -1){
1084
	perror_plus("setgroups");
1213 by teddy at recompile
Fix file descriptor leak in mandos-client
1085
	close(devnull);
738.1.2 by Teddy Hogeborn
mandos-client: Try to start a plugin to add and remove a local route.
1086
	_exit(EX_NOPERM);
1087
      }
1088
    }
1089
    ret = dup2(devnull, STDIN_FILENO);
1090
    if(ret == -1){
1091
      perror_plus("dup2(devnull, STDIN_FILENO)");
1213 by teddy at recompile
Fix file descriptor leak in mandos-client
1092
      close(devnull);
738.1.2 by Teddy Hogeborn
mandos-client: Try to start a plugin to add and remove a local route.
1093
      _exit(EX_OSERR);
1094
    }
774 by Teddy Hogeborn
Don't use TEMP_FAILURE_RETRY around close().
1095
    ret = close(devnull);
738.1.2 by Teddy Hogeborn
mandos-client: Try to start a plugin to add and remove a local route.
1096
    if(ret == -1){
1097
      perror_plus("close");
1098
    }
1099
    ret = dup2(STDERR_FILENO, STDOUT_FILENO);
1100
    if(ret == -1){
1101
      perror_plus("dup2(STDERR_FILENO, STDOUT_FILENO)");
1102
      _exit(EX_OSERR);
1103
    }
1104
    int helperdir_fd = (int)TEMP_FAILURE_RETRY(open(pluginhelperdir,
1105
						    O_RDONLY
1106
						    | O_DIRECTORY
1107
						    | O_PATH
1108
						    | O_CLOEXEC));
738.1.3 by Teddy Hogeborn
mandos-client: Minor changes to check for more error conditions.
1109
    if(helperdir_fd == -1){
1110
      perror_plus("open");
1111
      _exit(EX_UNAVAILABLE);
1112
    }
738.1.2 by Teddy Hogeborn
mandos-client: Try to start a plugin to add and remove a local route.
1113
    int helper_fd = (int)TEMP_FAILURE_RETRY(openat(helperdir_fd,
1114
						   helper, O_RDONLY));
738.1.3 by Teddy Hogeborn
mandos-client: Minor changes to check for more error conditions.
1115
    if(helper_fd == -1){
1116
      perror_plus("openat");
775 by Teddy Hogeborn
plugin-runner: Minor fix: close helperdir before exiting in fork.
1117
      close(helperdir_fd);
738.1.3 by Teddy Hogeborn
mandos-client: Minor changes to check for more error conditions.
1118
      _exit(EX_UNAVAILABLE);
1119
    }
774 by Teddy Hogeborn
Don't use TEMP_FAILURE_RETRY around close().
1120
    close(helperdir_fd);
738.1.2 by Teddy Hogeborn
mandos-client: Try to start a plugin to add and remove a local route.
1121
#ifdef __GNUC__
1122
#pragma GCC diagnostic push
1123
#pragma GCC diagnostic ignored "-Wcast-qual"
1124
#endif
1125
    if(fexecve(helper_fd, (char *const [])
738.1.4 by Teddy Hogeborn
Add plugin for mandos-client to add and delete local routes.
1126
	       { helper, add ? add_arg : delete_arg, (char *)address,
738.1.6 by Teddy Hogeborn
Fix minor bugs and typos and add some more debug output.
1127
		   interface, debug ? debug_flag : NULL, NULL },
1128
	       environ) == -1){
738.1.2 by Teddy Hogeborn
mandos-client: Try to start a plugin to add and remove a local route.
1129
#ifdef __GNUC__
1130
#pragma GCC diagnostic pop
1131
#endif
1132
      perror_plus("fexecve");
1133
      _exit(EXIT_FAILURE);
1134
    }
1135
  }
1136
  if(pid == -1){
1137
    perror_plus("fork");
1213 by teddy at recompile
Fix file descriptor leak in mandos-client
1138
    close(devnull);
738.1.2 by Teddy Hogeborn
mandos-client: Try to start a plugin to add and remove a local route.
1139
    return false;
1140
  }
1213 by teddy at recompile
Fix file descriptor leak in mandos-client
1141
  ret = close(devnull);
1142
  if(ret == -1){
1143
    perror_plus("close");
1144
  }
738.1.2 by Teddy Hogeborn
mandos-client: Try to start a plugin to add and remove a local route.
1145
  int status;
1146
  pid_t pret = -1;
1147
  errno = 0;
1148
  do {
1149
    pret = waitpid(pid, &status, 0);
1150
    if(pret == -1 and errno == EINTR and quit_now){
1151
      int errno_raising = 0;
1152
      if((errno = raise_privileges()) != 0){
1153
	errno_raising = errno;
1154
	perror_plus("Failed to raise privileges in order to"
1155
		    " kill helper program");
1156
      }
1157
      if(kill(pid, SIGTERM) == -1){
1158
	perror_plus("kill");
1159
      }
1160
      if((errno_raising == 0) and (errno = lower_privileges()) != 0){
1161
	perror_plus("Failed to lower privileges after killing"
1162
		    " helper program");
1163
      }
1164
      return false;
1165
    }
1166
  } while(pret == -1 and errno == EINTR);
1167
  if(pret == -1){
1168
    perror_plus("waitpid");
1169
    return false;
1170
  }
1171
  if(WIFEXITED(status)){
1172
    if(WEXITSTATUS(status) != 0){
1173
      fprintf_plus(stderr, "Error: iprouteadddel exited"
1174
		   " with status %d\n", WEXITSTATUS(status));
1175
      return false;
1176
    }
1177
    return true;
1178
  }
1179
  if(WIFSIGNALED(status)){
1180
    fprintf_plus(stderr, "Error: iprouteadddel died by"
1181
		 " signal %d\n", WTERMSIG(status));
1182
    return false;
1183
  }
1184
  fprintf_plus(stderr, "Error: iprouteadddel crashed\n");
1185
  return false;
1186
}
1187
1188
__attribute__((nonnull, warn_unused_result))
1189
static bool add_local_route(const char *address,
1190
			    AvahiIfIndex if_index){
738.1.6 by Teddy Hogeborn
Fix minor bugs and typos and add some more debug output.
1191
  if(debug){
1192
    fprintf_plus(stderr, "Adding route to %s\n", address);
1193
  }
1194
  return add_delete_local_route(true, address, if_index);
738.1.2 by Teddy Hogeborn
mandos-client: Try to start a plugin to add and remove a local route.
1195
}
1196
1197
__attribute__((nonnull, warn_unused_result))
738.1.6 by Teddy Hogeborn
Fix minor bugs and typos and add some more debug output.
1198
static bool delete_local_route(const char *address,
738.1.2 by Teddy Hogeborn
mandos-client: Try to start a plugin to add and remove a local route.
1199
			       AvahiIfIndex if_index){
738.1.6 by Teddy Hogeborn
Fix minor bugs and typos and add some more debug output.
1200
  if(debug){
1201
    fprintf_plus(stderr, "Removing route to %s\n", address);
1202
  }
1203
  return add_delete_local_route(false, address, if_index);
738.1.2 by Teddy Hogeborn
mandos-client: Try to start a plugin to add and remove a local route.
1204
}
1205
40 by Teddy Hogeborn
* plugins.d/mandosclient.c (initgnutls): Moved "err" variable into its
1206
/* Called when a Mandos server is found */
672 by Teddy Hogeborn
Update GCC warning flags and function attributes to GCC 4.7.
1207
__attribute__((nonnull, warn_unused_result))
597 by Teddy Hogeborn
* plugins.d/mandos-client.c: Don't use assert(). Use in_port_t for
1208
static int start_mandos_communication(const char *ip, in_port_t port,
24.1.9 by Björn Påhlsson
not working midwork...
1209
				      AvahiIfIndex if_index,
602 by Teddy Hogeborn
* plugins.d/mandos-client (mandos_context): Moved to inside "main()".
1210
				      int af, mandos_context *mc){
358 by Teddy Hogeborn
* plugins.d/mandos-client.c (start_mandos_communication): Check
1211
  int ret, tcp_sd = -1;
257.1.2 by Mooie
Fixed warnings in the 64 bit build. Added explicit cast to int for
1212
  ssize_t sret;
669 by Teddy Hogeborn
Use "struct sockaddr_storage" instead of a union in mandos-client.
1213
  struct sockaddr_storage to;
13 by Björn Påhlsson
Added following support:
1214
  char *buffer = NULL;
372 by Teddy Hogeborn
* plugins.d/mandos-client.c (start_mandos_communication): Bug fix:
1215
  char *decrypted_buffer = NULL;
13 by Björn Påhlsson
Added following support:
1216
  size_t buffer_length = 0;
1217
  size_t buffer_capacity = 0;
24.1.10 by Björn Påhlsson
merge commit
1218
  size_t written;
372 by Teddy Hogeborn
* plugins.d/mandos-client.c (start_mandos_communication): Bug fix:
1219
  int retval = -1;
38 by Teddy Hogeborn
* plugbasedclient.c (main): New "--userid" and "--groupid" options.
1220
  gnutls_session_t session;
304 by Teddy Hogeborn
Four new interrelated features:
1221
  int pf;			/* Protocol family */
738.1.2 by Teddy Hogeborn
mandos-client: Try to start a plugin to add and remove a local route.
1222
  bool route_added = false;
304 by Teddy Hogeborn
Four new interrelated features:
1223
  
399 by Teddy Hogeborn
* Makefile (BROKEN_PIE): Add comment.
1224
  errno = 0;
1225
  
358 by Teddy Hogeborn
* plugins.d/mandos-client.c (start_mandos_communication): Check
1226
  if(quit_now){
399 by Teddy Hogeborn
* Makefile (BROKEN_PIE): Add comment.
1227
    errno = EINTR;
358 by Teddy Hogeborn
* plugins.d/mandos-client.c (start_mandos_communication): Check
1228
    return -1;
1229
  }
1230
  
304 by Teddy Hogeborn
Four new interrelated features:
1231
  switch(af){
1232
  case AF_INET6:
1233
    pf = PF_INET6;
1234
    break;
1235
  case AF_INET:
1236
    pf = PF_INET;
1237
    break;
1238
  default:
505.2.6 by Björn Påhlsson
replace calls to fprintf with fprintf_plus.
1239
    fprintf_plus(stderr, "Bad address family: %d\n", af);
399 by Teddy Hogeborn
* Makefile (BROKEN_PIE): Add comment.
1240
    errno = EINVAL;
304 by Teddy Hogeborn
Four new interrelated features:
1241
    return -1;
1242
  }
21 by Teddy Hogeborn
* Makefile (CFLAGS): Changed to use $(WARN), $(DEBUG), $(COVERAGE) and
1243
  
605 by Teddy Hogeborn
* plugins.d/mandos-client.c: Comment changes
1244
  /* If the interface is specified and we have a list of interfaces */
604 by Teddy Hogeborn
* plugins.d/mandos-client (start_mandos_communication): Bug fix; skip
1245
  if(if_index != AVAHI_IF_UNSPEC and mc->interfaces != NULL){
1246
    /* Check if the interface is one of the interfaces we are using */
1247
    bool match = false;
1248
    {
1249
      char *interface = NULL;
890 by Teddy Hogeborn
Add spaces around all '=' signs in all C code.
1250
      while((interface = argz_next(mc->interfaces,
1251
				   mc->interfaces_size,
1252
				   interface))){
604 by Teddy Hogeborn
* plugins.d/mandos-client (start_mandos_communication): Bug fix; skip
1253
	if(if_nametoindex(interface) == (unsigned int)if_index){
1254
	  match = true;
1255
	  break;
1256
	}
1257
      }
1258
    }
1259
    if(not match){
605 by Teddy Hogeborn
* plugins.d/mandos-client.c: Comment changes
1260
      /* This interface does not match any in the list, so we don't
1261
	 connect to the server */
604 by Teddy Hogeborn
* plugins.d/mandos-client (start_mandos_communication): Bug fix; skip
1262
      if(debug){
1263
	char interface[IF_NAMESIZE];
1264
	if(if_indextoname((unsigned int)if_index, interface) == NULL){
1265
	  perror_plus("if_indextoname");
1266
	} else {
1267
	  fprintf_plus(stderr, "Skipping server on non-used interface"
1268
		       " \"%s\"\n",
1269
		       if_indextoname((unsigned int)if_index,
1270
				      interface));
1271
	}
1272
      }
1273
      return -1;
1274
    }
1275
  }
1276
  
602 by Teddy Hogeborn
* plugins.d/mandos-client (mandos_context): Moved to inside "main()".
1277
  ret = init_gnutls_session(&session, mc);
266 by Teddy Hogeborn
* plugin-runner.c: Only space changes.
1278
  if(ret != 0){
40 by Teddy Hogeborn
* plugins.d/mandosclient.c (initgnutls): Moved "err" variable into its
1279
    return -1;
1280
  }
1281
  
15.1.1 by Björn Påhlsson
Added debugg support in form off --debug and --debug=mandosclient
1282
  if(debug){
505.3.9 by Teddy Hogeborn
* plugins.d/mandos-client.c: Merge unified printing system.
1283
    fprintf_plus(stderr, "Setting up a TCP connection to %s, port %"
597 by Teddy Hogeborn
* plugins.d/mandos-client.c: Don't use assert(). Use in_port_t for
1284
		 PRIuMAX "\n", ip, (uintmax_t)port);
15.1.1 by Björn Påhlsson
Added debugg support in form off --debug and --debug=mandosclient
1285
  }
13 by Björn Påhlsson
Added following support:
1286
  
738.1.2 by Teddy Hogeborn
mandos-client: Try to start a plugin to add and remove a local route.
1287
  tcp_sd = socket(pf, SOCK_STREAM | SOCK_CLOEXEC, 0);
293 by Teddy Hogeborn
* plugin-runner.c: Whitespace changes only.
1288
  if(tcp_sd < 0){
399 by Teddy Hogeborn
* Makefile (BROKEN_PIE): Add comment.
1289
    int e = errno;
24.1.174 by Björn Påhlsson
* Makefile (CFLAGS): Added "-lrt" to include real time library.
1290
    perror_plus("socket");
399 by Teddy Hogeborn
* Makefile (BROKEN_PIE): Add comment.
1291
    errno = e;
358 by Teddy Hogeborn
* plugins.d/mandos-client.c (start_mandos_communication): Check
1292
    goto mandos_end;
1293
  }
1294
  
1295
  if(quit_now){
399 by Teddy Hogeborn
* Makefile (BROKEN_PIE): Add comment.
1296
    errno = EINTR;
358 by Teddy Hogeborn
* plugins.d/mandos-client.c (start_mandos_communication): Check
1297
    goto mandos_end;
13 by Björn Påhlsson
Added following support:
1298
  }
143 by Teddy Hogeborn
* Makefile (mandos.8): Add dependency on "overview.xml" and
1299
  
304 by Teddy Hogeborn
Four new interrelated features:
1300
  if(af == AF_INET6){
773 by Teddy Hogeborn
mandos-client: Don't use memset().
1301
    struct sockaddr_in6 *to6 = (struct sockaddr_in6 *)&to;
1302
    *to6 = (struct sockaddr_in6){ .sin6_family = (sa_family_t)af };
1303
    ret = inet_pton(af, ip, &to6->sin6_addr);
304 by Teddy Hogeborn
Four new interrelated features:
1304
  } else {			/* IPv4 */
773 by Teddy Hogeborn
mandos-client: Don't use memset().
1305
    struct sockaddr_in *to4 = (struct sockaddr_in *)&to;
1306
    *to4 = (struct sockaddr_in){ .sin_family = (sa_family_t)af };
1307
    ret = inet_pton(af, ip, &to4->sin_addr);
304 by Teddy Hogeborn
Four new interrelated features:
1308
  }
266 by Teddy Hogeborn
* plugin-runner.c: Only space changes.
1309
  if(ret < 0 ){
399 by Teddy Hogeborn
* Makefile (BROKEN_PIE): Add comment.
1310
    int e = errno;
24.1.174 by Björn Påhlsson
* Makefile (CFLAGS): Added "-lrt" to include real time library.
1311
    perror_plus("inet_pton");
399 by Teddy Hogeborn
* Makefile (BROKEN_PIE): Add comment.
1312
    errno = e;
358 by Teddy Hogeborn
* plugins.d/mandos-client.c (start_mandos_communication): Check
1313
    goto mandos_end;
38 by Teddy Hogeborn
* plugbasedclient.c (main): New "--userid" and "--groupid" options.
1314
  }
13 by Björn Påhlsson
Added following support:
1315
  if(ret == 0){
399 by Teddy Hogeborn
* Makefile (BROKEN_PIE): Add comment.
1316
    int e = errno;
505.2.6 by Björn Påhlsson
replace calls to fprintf with fprintf_plus.
1317
    fprintf_plus(stderr, "Bad address: %s\n", ip);
399 by Teddy Hogeborn
* Makefile (BROKEN_PIE): Add comment.
1318
    errno = e;
358 by Teddy Hogeborn
* plugins.d/mandos-client.c (start_mandos_communication): Check
1319
    goto mandos_end;
13 by Björn Påhlsson
Added following support:
1320
  }
304 by Teddy Hogeborn
Four new interrelated features:
1321
  if(af == AF_INET6){
672 by Teddy Hogeborn
Update GCC warning flags and function attributes to GCC 4.7.
1322
    ((struct sockaddr_in6 *)&to)->sin6_port = htons(port);
669 by Teddy Hogeborn
Use "struct sockaddr_storage" instead of a union in mandos-client.
1323
    if(IN6_IS_ADDR_LINKLOCAL
1324
       (&((struct sockaddr_in6 *)&to)->sin6_addr)){
304 by Teddy Hogeborn
Four new interrelated features:
1325
      if(if_index == AVAHI_IF_UNSPEC){
505.3.9 by Teddy Hogeborn
* plugins.d/mandos-client.c: Merge unified printing system.
1326
	fprintf_plus(stderr, "An IPv6 link-local address is"
1327
		     " incomplete without a network interface\n");
399 by Teddy Hogeborn
* Makefile (BROKEN_PIE): Add comment.
1328
	errno = EINVAL;
358 by Teddy Hogeborn
* plugins.d/mandos-client.c (start_mandos_communication): Check
1329
	goto mandos_end;
304 by Teddy Hogeborn
Four new interrelated features:
1330
      }
1331
      /* Set the network interface number as scope */
669 by Teddy Hogeborn
Use "struct sockaddr_storage" instead of a union in mandos-client.
1332
      ((struct sockaddr_in6 *)&to)->sin6_scope_id = (uint32_t)if_index;
304 by Teddy Hogeborn
Four new interrelated features:
1333
    }
1334
  } else {
669 by Teddy Hogeborn
Use "struct sockaddr_storage" instead of a union in mandos-client.
1335
    ((struct sockaddr_in *)&to)->sin_port = htons(port);
304 by Teddy Hogeborn
Four new interrelated features:
1336
  }
21 by Teddy Hogeborn
* Makefile (CFLAGS): Changed to use $(WARN), $(DEBUG), $(COVERAGE) and
1337
  
358 by Teddy Hogeborn
* plugins.d/mandos-client.c (start_mandos_communication): Check
1338
  if(quit_now){
399 by Teddy Hogeborn
* Makefile (BROKEN_PIE): Add comment.
1339
    errno = EINTR;
358 by Teddy Hogeborn
* plugins.d/mandos-client.c (start_mandos_communication): Check
1340
    goto mandos_end;
1341
  }
1342
  
15.1.1 by Björn Påhlsson
Added debugg support in form off --debug and --debug=mandosclient
1343
  if(debug){
304 by Teddy Hogeborn
Four new interrelated features:
1344
    if(af == AF_INET6 and if_index != AVAHI_IF_UNSPEC){
1345
      char interface[IF_NAMESIZE];
1346
      if(if_indextoname((unsigned int)if_index, interface) == NULL){
24.1.174 by Björn Påhlsson
* Makefile (CFLAGS): Added "-lrt" to include real time library.
1347
	perror_plus("if_indextoname");
304 by Teddy Hogeborn
Four new interrelated features:
1348
      } else {
597 by Teddy Hogeborn
* plugins.d/mandos-client.c: Don't use assert(). Use in_port_t for
1349
	fprintf_plus(stderr, "Connection to: %s%%%s, port %" PRIuMAX
1350
		     "\n", ip, interface, (uintmax_t)port);
304 by Teddy Hogeborn
Four new interrelated features:
1351
      }
1352
    } else {
597 by Teddy Hogeborn
* plugins.d/mandos-client.c: Don't use assert(). Use in_port_t for
1353
      fprintf_plus(stderr, "Connection to: %s, port %" PRIuMAX "\n",
1354
		   ip, (uintmax_t)port);
304 by Teddy Hogeborn
Four new interrelated features:
1355
    }
1356
    char addrstr[(INET_ADDRSTRLEN > INET6_ADDRSTRLEN) ?
1357
		 INET_ADDRSTRLEN : INET6_ADDRSTRLEN] = "";
1358
    if(af == AF_INET6){
669 by Teddy Hogeborn
Use "struct sockaddr_storage" instead of a union in mandos-client.
1359
      ret = getnameinfo((struct sockaddr *)&to,
1360
			sizeof(struct sockaddr_in6),
667 by Teddy Hogeborn
Use getnameinfo() instead of inet_ntop() in mandos-client.
1361
			addrstr, sizeof(addrstr), NULL, 0,
1362
			NI_NUMERICHOST);
304 by Teddy Hogeborn
Four new interrelated features:
1363
    } else {
669 by Teddy Hogeborn
Use "struct sockaddr_storage" instead of a union in mandos-client.
1364
      ret = getnameinfo((struct sockaddr *)&to,
1365
			sizeof(struct sockaddr_in),
667 by Teddy Hogeborn
Use getnameinfo() instead of inet_ntop() in mandos-client.
1366
			addrstr, sizeof(addrstr), NULL, 0,
1367
			NI_NUMERICHOST);
304 by Teddy Hogeborn
Four new interrelated features:
1368
    }
667 by Teddy Hogeborn
Use getnameinfo() instead of inet_ntop() in mandos-client.
1369
    if(ret == EAI_SYSTEM){
1370
      perror_plus("getnameinfo");
1371
    } else if(ret != 0) {
1372
      fprintf_plus(stderr, "getnameinfo: %s", gai_strerror(ret));
1373
    } else if(strcmp(addrstr, ip) != 0){
1374
      fprintf_plus(stderr, "Canonical address form: %s\n", addrstr);
37 by Teddy Hogeborn
Non-tested commit for merge purposes.
1375
    }
15.1.1 by Björn Påhlsson
Added debugg support in form off --debug and --debug=mandosclient
1376
  }
13 by Björn Påhlsson
Added following support:
1377
  
358 by Teddy Hogeborn
* plugins.d/mandos-client.c (start_mandos_communication): Check
1378
  if(quit_now){
399 by Teddy Hogeborn
* Makefile (BROKEN_PIE): Add comment.
1379
    errno = EINTR;
358 by Teddy Hogeborn
* plugins.d/mandos-client.c (start_mandos_communication): Check
1380
    goto mandos_end;
1381
  }
1382
  
738.1.2 by Teddy Hogeborn
mandos-client: Try to start a plugin to add and remove a local route.
1383
  while(true){
1384
    if(af == AF_INET6){
1385
      ret = connect(tcp_sd, (struct sockaddr *)&to,
1386
		    sizeof(struct sockaddr_in6));
1387
    } else {
1388
      ret = connect(tcp_sd, (struct sockaddr *)&to, /* IPv4 */
1389
		    sizeof(struct sockaddr_in));
1390
    }
1391
    if(ret < 0){
790 by Teddy Hogeborn
Bug fix: Add local route also when host is unreachable.
1392
      if(((errno == ENETUNREACH) or (errno == EHOSTUNREACH))
738.1.2 by Teddy Hogeborn
mandos-client: Try to start a plugin to add and remove a local route.
1393
	 and if_index != AVAHI_IF_UNSPEC
1394
	 and connect_to == NULL
1395
	 and not route_added and
1396
	 ((af == AF_INET6 and not
1397
	   IN6_IS_ADDR_LINKLOCAL(&(((struct sockaddr_in6 *)
1398
				    &to)->sin6_addr)))
1399
	  or (af == AF_INET and
1400
	      /* Not a a IPv4LL address */
1401
	      (ntohl(((struct sockaddr_in *)&to)->sin_addr.s_addr)
1402
	       & 0xFFFF0000L) != 0xA9FE0000L))){
1403
	/* Work around Avahi bug - Avahi does not announce link-local
1404
	   addresses if it has a global address, so local hosts with
1405
	   *only* a link-local address (e.g. Mandos clients) cannot
1406
	   connect to a Mandos server announced by Avahi on a server
1407
	   host with a global address.  Work around this by retrying
1408
	   with an explicit route added with the server's address.
1409
	   
1410
	   Avahi bug reference:
868 by Teddy Hogeborn
Change all http:// URLs to https:// wherever possible.
1411
	   https://lists.freedesktop.org/archives/avahi/2010-February/001833.html
738.1.2 by Teddy Hogeborn
mandos-client: Try to start a plugin to add and remove a local route.
1412
	   https://bugs.debian.org/587961
1413
	*/
738.1.6 by Teddy Hogeborn
Fix minor bugs and typos and add some more debug output.
1414
	if(debug){
1415
	  fprintf_plus(stderr, "Mandos server unreachable, trying"
1416
		       " direct route\n");
1417
	}
738.1.2 by Teddy Hogeborn
mandos-client: Try to start a plugin to add and remove a local route.
1418
	int e = errno;
1419
	route_added = add_local_route(ip, if_index);
1420
	if(route_added){
1421
	  continue;
1422
	}
1423
	errno = e;
1424
      }
1425
      if(errno != ECONNREFUSED or debug){
1426
	int e = errno;
1427
	perror_plus("connect");
1428
	errno = e;
1429
      }
1430
      goto mandos_end;
1431
    }
1432
    
1433
    if(quit_now){
1434
      errno = EINTR;
1435
      goto mandos_end;
1436
    }
1437
    break;
13 by Björn Påhlsson
Added following support:
1438
  }
143 by Teddy Hogeborn
* Makefile (mandos.8): Add dependency on "overview.xml" and
1439
  
24.1.12 by Björn Påhlsson
merge +
1440
  const char *out = mandos_protocol_version;
24.1.10 by Björn Påhlsson
merge commit
1441
  written = 0;
266 by Teddy Hogeborn
* plugin-runner.c: Only space changes.
1442
  while(true){
24.1.10 by Björn Påhlsson
merge commit
1443
    size_t out_size = strlen(out);
257.1.2 by Mooie
Fixed warnings in the 64 bit build. Added explicit cast to int for
1444
    ret = (int)TEMP_FAILURE_RETRY(write(tcp_sd, out + written,
505.3.6 by teddy at bsnet
* plugins.d/mandos-client.c: Some white space fixes.
1445
					out_size - written));
266 by Teddy Hogeborn
* plugin-runner.c: Only space changes.
1446
    if(ret == -1){
399 by Teddy Hogeborn
* Makefile (BROKEN_PIE): Add comment.
1447
      int e = errno;
24.1.174 by Björn Påhlsson
* Makefile (CFLAGS): Added "-lrt" to include real time library.
1448
      perror_plus("write");
399 by Teddy Hogeborn
* Makefile (BROKEN_PIE): Add comment.
1449
      errno = e;
24.1.12 by Björn Påhlsson
merge +
1450
      goto mandos_end;
24.1.10 by Björn Påhlsson
merge commit
1451
    }
24.1.12 by Björn Påhlsson
merge +
1452
    written += (size_t)ret;
24.1.10 by Björn Påhlsson
merge commit
1453
    if(written < out_size){
1454
      continue;
1455
    } else {
266 by Teddy Hogeborn
* plugin-runner.c: Only space changes.
1456
      if(out == mandos_protocol_version){
24.1.10 by Björn Påhlsson
merge commit
1457
	written = 0;
1458
	out = "\r\n";
1459
      } else {
1460
	break;
1461
      }
1462
    }
358 by Teddy Hogeborn
* plugins.d/mandos-client.c (start_mandos_communication): Check
1463
  
1464
    if(quit_now){
399 by Teddy Hogeborn
* Makefile (BROKEN_PIE): Add comment.
1465
      errno = EINTR;
358 by Teddy Hogeborn
* plugins.d/mandos-client.c (start_mandos_communication): Check
1466
      goto mandos_end;
1467
    }
24.1.10 by Björn Påhlsson
merge commit
1468
  }
143 by Teddy Hogeborn
* Makefile (mandos.8): Add dependency on "overview.xml" and
1469
  
40 by Teddy Hogeborn
* plugins.d/mandosclient.c (initgnutls): Moved "err" variable into its
1470
  if(debug){
505.2.6 by Björn Påhlsson
replace calls to fprintf with fprintf_plus.
1471
    fprintf_plus(stderr, "Establishing TLS session with %s\n", ip);
15.1.1 by Björn Påhlsson
Added debugg support in form off --debug and --debug=mandosclient
1472
  }
21 by Teddy Hogeborn
* Makefile (CFLAGS): Changed to use $(WARN), $(DEBUG), $(COVERAGE) and
1473
  
358 by Teddy Hogeborn
* plugins.d/mandos-client.c (start_mandos_communication): Check
1474
  if(quit_now){
399 by Teddy Hogeborn
* Makefile (BROKEN_PIE): Add comment.
1475
    errno = EINTR;
358 by Teddy Hogeborn
* plugins.d/mandos-client.c (start_mandos_communication): Check
1476
    goto mandos_end;
1477
  }
1478
  
588 by Teddy Hogeborn
* plugins.d/mandos-client.c (start_mandos_communication): Eliminate
1479
  /* This casting via intptr_t is to eliminate warning about casting
1480
     an int to a pointer type.  This is exactly how the GnuTLS Guile
1481
     function "set-session-transport-fd!" does it. */
1482
  gnutls_transport_set_ptr(session,
1483
			   (gnutls_transport_ptr_t)(intptr_t)tcp_sd);
143 by Teddy Hogeborn
* Makefile (mandos.8): Add dependency on "overview.xml" and
1484
  
358 by Teddy Hogeborn
* plugins.d/mandos-client.c (start_mandos_communication): Check
1485
  if(quit_now){
399 by Teddy Hogeborn
* Makefile (BROKEN_PIE): Add comment.
1486
    errno = EINTR;
358 by Teddy Hogeborn
* plugins.d/mandos-client.c (start_mandos_communication): Check
1487
    goto mandos_end;
1488
  }
1489
  
363 by Teddy Hogeborn
* plugin-runner.c: Minor stylistic changes.
1490
  do {
266 by Teddy Hogeborn
* plugin-runner.c: Only space changes.
1491
    ret = gnutls_handshake(session);
358 by Teddy Hogeborn
* plugins.d/mandos-client.c (start_mandos_communication): Check
1492
    if(quit_now){
399 by Teddy Hogeborn
* Makefile (BROKEN_PIE): Add comment.
1493
      errno = EINTR;
358 by Teddy Hogeborn
* plugins.d/mandos-client.c (start_mandos_communication): Check
1494
      goto mandos_end;
1495
    }
24.1.29 by Björn Påhlsson
Added more header file comments
1496
  } while(ret == GNUTLS_E_AGAIN or ret == GNUTLS_E_INTERRUPTED);
13 by Björn Påhlsson
Added following support:
1497
  
266 by Teddy Hogeborn
* plugin-runner.c: Only space changes.
1498
  if(ret != GNUTLS_E_SUCCESS){
25 by Teddy Hogeborn
* mandos-clients.conf ([DEFAULT]): New section.
1499
    if(debug){
505.2.6 by Björn Påhlsson
replace calls to fprintf with fprintf_plus.
1500
      fprintf_plus(stderr, "*** GnuTLS Handshake failed ***\n");
266 by Teddy Hogeborn
* plugin-runner.c: Only space changes.
1501
      gnutls_perror(ret);
25 by Teddy Hogeborn
* mandos-clients.conf ([DEFAULT]): New section.
1502
    }
399 by Teddy Hogeborn
* Makefile (BROKEN_PIE): Add comment.
1503
    errno = EPROTO;
40 by Teddy Hogeborn
* plugins.d/mandosclient.c (initgnutls): Moved "err" variable into its
1504
    goto mandos_end;
13 by Björn Påhlsson
Added following support:
1505
  }
21 by Teddy Hogeborn
* Makefile (CFLAGS): Changed to use $(WARN), $(DEBUG), $(COVERAGE) and
1506
  
40 by Teddy Hogeborn
* plugins.d/mandosclient.c (initgnutls): Moved "err" variable into its
1507
  /* Read OpenPGP packet that contains the wanted password */
21 by Teddy Hogeborn
* Makefile (CFLAGS): Changed to use $(WARN), $(DEBUG), $(COVERAGE) and
1508
  
15.1.1 by Björn Påhlsson
Added debugg support in form off --debug and --debug=mandosclient
1509
  if(debug){
505.3.9 by Teddy Hogeborn
* plugins.d/mandos-client.c: Merge unified printing system.
1510
    fprintf_plus(stderr, "Retrieving OpenPGP encrypted password from"
1511
		 " %s\n", ip);
15.1.1 by Björn Påhlsson
Added debugg support in form off --debug and --debug=mandosclient
1512
  }
143 by Teddy Hogeborn
* Makefile (mandos.8): Add dependency on "overview.xml" and
1513
  
13 by Björn Påhlsson
Added following support:
1514
  while(true){
358 by Teddy Hogeborn
* plugins.d/mandos-client.c (start_mandos_communication): Check
1515
    
1516
    if(quit_now){
399 by Teddy Hogeborn
* Makefile (BROKEN_PIE): Add comment.
1517
      errno = EINTR;
358 by Teddy Hogeborn
* plugins.d/mandos-client.c (start_mandos_communication): Check
1518
      goto mandos_end;
1519
    }
1520
    
24.1.132 by Björn Påhlsson
Fixed a bug in fallback handling
1521
    buffer_capacity = incbuffer(&buffer, buffer_length,
505.3.6 by teddy at bsnet
* plugins.d/mandos-client.c: Some white space fixes.
1522
				buffer_capacity);
266 by Teddy Hogeborn
* plugin-runner.c: Only space changes.
1523
    if(buffer_capacity == 0){
399 by Teddy Hogeborn
* Makefile (BROKEN_PIE): Add comment.
1524
      int e = errno;
24.1.174 by Björn Påhlsson
* Makefile (CFLAGS): Added "-lrt" to include real time library.
1525
      perror_plus("incbuffer");
399 by Teddy Hogeborn
* Makefile (BROKEN_PIE): Add comment.
1526
      errno = e;
24.1.12 by Björn Påhlsson
merge +
1527
      goto mandos_end;
13 by Björn Påhlsson
Added following support:
1528
    }
1529
    
358 by Teddy Hogeborn
* plugins.d/mandos-client.c (start_mandos_communication): Check
1530
    if(quit_now){
399 by Teddy Hogeborn
* Makefile (BROKEN_PIE): Add comment.
1531
      errno = EINTR;
358 by Teddy Hogeborn
* plugins.d/mandos-client.c (start_mandos_communication): Check
1532
      goto mandos_end;
1533
    }
1534
    
257.1.2 by Mooie
Fixed warnings in the 64 bit build. Added explicit cast to int for
1535
    sret = gnutls_record_recv(session, buffer+buffer_length,
1536
			      BUFFER_SIZE);
266 by Teddy Hogeborn
* plugin-runner.c: Only space changes.
1537
    if(sret == 0){
13 by Björn Påhlsson
Added following support:
1538
      break;
1539
    }
266 by Teddy Hogeborn
* plugin-runner.c: Only space changes.
1540
    if(sret < 0){
257.1.2 by Mooie
Fixed warnings in the 64 bit build. Added explicit cast to int for
1541
      switch(sret){
13 by Björn Påhlsson
Added following support:
1542
      case GNUTLS_E_INTERRUPTED:
1543
      case GNUTLS_E_AGAIN:
1544
	break;
1545
      case GNUTLS_E_REHANDSHAKE:
363 by Teddy Hogeborn
* plugin-runner.c: Minor stylistic changes.
1546
	do {
266 by Teddy Hogeborn
* plugin-runner.c: Only space changes.
1547
	  ret = gnutls_handshake(session);
358 by Teddy Hogeborn
* plugins.d/mandos-client.c (start_mandos_communication): Check
1548
	  
1549
	  if(quit_now){
399 by Teddy Hogeborn
* Makefile (BROKEN_PIE): Add comment.
1550
	    errno = EINTR;
358 by Teddy Hogeborn
* plugins.d/mandos-client.c (start_mandos_communication): Check
1551
	    goto mandos_end;
1552
	  }
24.1.29 by Björn Påhlsson
Added more header file comments
1553
	} while(ret == GNUTLS_E_AGAIN or ret == GNUTLS_E_INTERRUPTED);
266 by Teddy Hogeborn
* plugin-runner.c: Only space changes.
1554
	if(ret < 0){
505.3.9 by Teddy Hogeborn
* plugins.d/mandos-client.c: Merge unified printing system.
1555
	  fprintf_plus(stderr, "*** GnuTLS Re-handshake failed "
1556
		       "***\n");
266 by Teddy Hogeborn
* plugin-runner.c: Only space changes.
1557
	  gnutls_perror(ret);
399 by Teddy Hogeborn
* Makefile (BROKEN_PIE): Add comment.
1558
	  errno = EPROTO;
40 by Teddy Hogeborn
* plugins.d/mandosclient.c (initgnutls): Moved "err" variable into its
1559
	  goto mandos_end;
13 by Björn Påhlsson
Added following support:
1560
	}
1561
	break;
1562
      default:
505.2.6 by Björn Påhlsson
replace calls to fprintf with fprintf_plus.
1563
	fprintf_plus(stderr, "Unknown error while reading data from"
505.3.9 by Teddy Hogeborn
* plugins.d/mandos-client.c: Merge unified printing system.
1564
		     " encrypted session with Mandos server\n");
266 by Teddy Hogeborn
* plugin-runner.c: Only space changes.
1565
	gnutls_bye(session, GNUTLS_SHUT_RDWR);
399 by Teddy Hogeborn
* Makefile (BROKEN_PIE): Add comment.
1566
	errno = EIO;
40 by Teddy Hogeborn
* plugins.d/mandosclient.c (initgnutls): Moved "err" variable into its
1567
	goto mandos_end;
13 by Björn Påhlsson
Added following support:
1568
      }
1569
    } else {
257.1.2 by Mooie
Fixed warnings in the 64 bit build. Added explicit cast to int for
1570
      buffer_length += (size_t) sret;
13 by Björn Påhlsson
Added following support:
1571
    }
1572
  }
15.1.1 by Björn Påhlsson
Added debugg support in form off --debug and --debug=mandosclient
1573
  
40 by Teddy Hogeborn
* plugins.d/mandosclient.c (initgnutls): Moved "err" variable into its
1574
  if(debug){
505.2.6 by Björn Påhlsson
replace calls to fprintf with fprintf_plus.
1575
    fprintf_plus(stderr, "Closing TLS session\n");
40 by Teddy Hogeborn
* plugins.d/mandosclient.c (initgnutls): Moved "err" variable into its
1576
  }
1577
  
358 by Teddy Hogeborn
* plugins.d/mandos-client.c (start_mandos_communication): Check
1578
  if(quit_now){
399 by Teddy Hogeborn
* Makefile (BROKEN_PIE): Add comment.
1579
    errno = EINTR;
371 by Teddy Hogeborn
* plugins.d/mandos-client.c (init_gnutls_session): Always fail and
1580
    goto mandos_end;
1581
  }
1582
  
1583
  do {
1584
    ret = gnutls_bye(session, GNUTLS_SHUT_RDWR);
1585
    if(quit_now){
399 by Teddy Hogeborn
* Makefile (BROKEN_PIE): Add comment.
1586
      errno = EINTR;
371 by Teddy Hogeborn
* plugins.d/mandos-client.c (init_gnutls_session): Always fail and
1587
      goto mandos_end;
1588
    }
1589
  } while(ret == GNUTLS_E_AGAIN or ret == GNUTLS_E_INTERRUPTED);
358 by Teddy Hogeborn
* plugins.d/mandos-client.c (start_mandos_communication): Check
1590
  
266 by Teddy Hogeborn
* plugin-runner.c: Only space changes.
1591
  if(buffer_length > 0){
362 by Teddy Hogeborn
* plugin-runner.c (getplugin, add_environment, main): Handle EINTR
1592
    ssize_t decrypted_buffer_size;
505.3.6 by teddy at bsnet
* plugins.d/mandos-client.c: Some white space fixes.
1593
    decrypted_buffer_size = pgp_packet_decrypt(buffer, buffer_length,
602 by Teddy Hogeborn
* plugins.d/mandos-client (mandos_context): Moved to inside "main()".
1594
					       &decrypted_buffer, mc);
266 by Teddy Hogeborn
* plugin-runner.c: Only space changes.
1595
    if(decrypted_buffer_size >= 0){
361 by Teddy Hogeborn
* plugins.d/mandos-client.c (init_gpgme): Move variable "ret" into the
1596
      
866 by Teddy Hogeborn
mandos-client: Bug fix: flush stdout to detect write errors.
1597
      clearerr(stdout);
24.1.10 by Björn Påhlsson
merge commit
1598
      written = 0;
28 by Teddy Hogeborn
* server.conf: New file.
1599
      while(written < (size_t) decrypted_buffer_size){
358 by Teddy Hogeborn
* plugins.d/mandos-client.c (start_mandos_communication): Check
1600
	if(quit_now){
399 by Teddy Hogeborn
* Makefile (BROKEN_PIE): Add comment.
1601
	  errno = EINTR;
358 by Teddy Hogeborn
* plugins.d/mandos-client.c (start_mandos_communication): Check
1602
	  goto mandos_end;
1603
	}
1604
	
266 by Teddy Hogeborn
* plugin-runner.c: Only space changes.
1605
	ret = (int)fwrite(decrypted_buffer + written, 1,
1606
			  (size_t)decrypted_buffer_size - written,
1607
			  stdout);
21 by Teddy Hogeborn
* Makefile (CFLAGS): Changed to use $(WARN), $(DEBUG), $(COVERAGE) and
1608
	if(ret == 0 and ferror(stdout)){
399 by Teddy Hogeborn
* Makefile (BROKEN_PIE): Add comment.
1609
	  int e = errno;
21 by Teddy Hogeborn
* Makefile (CFLAGS): Changed to use $(WARN), $(DEBUG), $(COVERAGE) and
1610
	  if(debug){
505.2.6 by Björn Påhlsson
replace calls to fprintf with fprintf_plus.
1611
	    fprintf_plus(stderr, "Error writing encrypted data: %s\n",
505.3.9 by Teddy Hogeborn
* plugins.d/mandos-client.c: Merge unified printing system.
1612
			 strerror(errno));
21 by Teddy Hogeborn
* Makefile (CFLAGS): Changed to use $(WARN), $(DEBUG), $(COVERAGE) and
1613
	  }
399 by Teddy Hogeborn
* Makefile (BROKEN_PIE): Add comment.
1614
	  errno = e;
372 by Teddy Hogeborn
* plugins.d/mandos-client.c (start_mandos_communication): Bug fix:
1615
	  goto mandos_end;
21 by Teddy Hogeborn
* Makefile (CFLAGS): Changed to use $(WARN), $(DEBUG), $(COVERAGE) and
1616
	}
22 by Teddy Hogeborn
* plugins.d/mandosclient.c (pgp_packet_decrypt): Cast "0" argument to
1617
	written += (size_t)ret;
21 by Teddy Hogeborn
* Makefile (CFLAGS): Changed to use $(WARN), $(DEBUG), $(COVERAGE) and
1618
      }
866 by Teddy Hogeborn
mandos-client: Bug fix: flush stdout to detect write errors.
1619
      ret = fflush(stdout);
1620
      if(ret != 0){
1621
	int e = errno;
1622
	if(debug){
1623
	  fprintf_plus(stderr, "Error writing encrypted data: %s\n",
1624
		       strerror(errno));
1625
	}
1626
	errno = e;
1627
	goto mandos_end;
1628
      }
372 by Teddy Hogeborn
* plugins.d/mandos-client.c (start_mandos_communication): Bug fix:
1629
      retval = 0;
13 by Björn Påhlsson
Added following support:
1630
    }
1631
  }
40 by Teddy Hogeborn
* plugins.d/mandosclient.c (initgnutls): Moved "err" variable into its
1632
  
1633
  /* Shutdown procedure */
1634
  
1635
 mandos_end:
399 by Teddy Hogeborn
* Makefile (BROKEN_PIE): Add comment.
1636
  {
738.1.2 by Teddy Hogeborn
mandos-client: Try to start a plugin to add and remove a local route.
1637
    if(route_added){
738.1.6 by Teddy Hogeborn
Fix minor bugs and typos and add some more debug output.
1638
      if(not delete_local_route(ip, if_index)){
1639
	fprintf_plus(stderr, "Failed to delete local route to %s on"
738.1.2 by Teddy Hogeborn
mandos-client: Try to start a plugin to add and remove a local route.
1640
		     " interface %d", ip, if_index);
1641
      }
1642
    }
399 by Teddy Hogeborn
* Makefile (BROKEN_PIE): Add comment.
1643
    int e = errno;
1644
    free(decrypted_buffer);
1645
    free(buffer);
1646
    if(tcp_sd >= 0){
774 by Teddy Hogeborn
Don't use TEMP_FAILURE_RETRY around close().
1647
      ret = close(tcp_sd);
399 by Teddy Hogeborn
* Makefile (BROKEN_PIE): Add comment.
1648
    }
1649
    if(ret == -1){
1650
      if(e == 0){
1651
	e = errno;
1652
      }
24.1.174 by Björn Påhlsson
* Makefile (CFLAGS): Added "-lrt" to include real time library.
1653
      perror_plus("close");
399 by Teddy Hogeborn
* Makefile (BROKEN_PIE): Add comment.
1654
    }
1655
    gnutls_deinit(session);
24.1.174 by Björn Påhlsson
* Makefile (CFLAGS): Added "-lrt" to include real time library.
1656
    errno = e;
399 by Teddy Hogeborn
* Makefile (BROKEN_PIE): Add comment.
1657
    if(quit_now){
24.1.174 by Björn Påhlsson
* Makefile (CFLAGS): Added "-lrt" to include real time library.
1658
      errno = EINTR;
399 by Teddy Hogeborn
* Makefile (BROKEN_PIE): Add comment.
1659
      retval = -1;
1660
    }
358 by Teddy Hogeborn
* plugins.d/mandos-client.c (start_mandos_communication): Check
1661
  }
13 by Björn Påhlsson
Added following support:
1662
  return retval;
1663
}
1664
39 by Teddy Hogeborn
* plugins.d/mandosclient.c (pgp_packet_decrypt): Renamed variables.
1665
static void resolve_callback(AvahiSServiceResolver *r,
1666
			     AvahiIfIndex interface,
304 by Teddy Hogeborn
Four new interrelated features:
1667
			     AvahiProtocol proto,
39 by Teddy Hogeborn
* plugins.d/mandosclient.c (pgp_packet_decrypt): Renamed variables.
1668
			     AvahiResolverEvent event,
1669
			     const char *name,
1670
			     const char *type,
1671
			     const char *domain,
1672
			     const char *host_name,
1673
			     const AvahiAddress *address,
1674
			     uint16_t port,
1675
			     AVAHI_GCC_UNUSED AvahiStringList *txt,
1676
			     AVAHI_GCC_UNUSED AvahiLookupResultFlags
1677
			     flags,
672 by Teddy Hogeborn
Update GCC warning flags and function attributes to GCC 4.7.
1678
			     void *mc){
597 by Teddy Hogeborn
* plugins.d/mandos-client.c: Don't use assert(). Use in_port_t for
1679
  if(r == NULL){
1680
    return;
1681
  }
22 by Teddy Hogeborn
* plugins.d/mandosclient.c (pgp_packet_decrypt): Cast "0" argument to
1682
  
21 by Teddy Hogeborn
* Makefile (CFLAGS): Changed to use $(WARN), $(DEBUG), $(COVERAGE) and
1683
  /* Called whenever a service has been resolved successfully or
1684
     timed out */
22 by Teddy Hogeborn
* plugins.d/mandosclient.c (pgp_packet_decrypt): Cast "0" argument to
1685
  
353 by Teddy Hogeborn
* plugins.d/mandos-client.c (quit_now): Move up declaration before
1686
  if(quit_now){
715 by Teddy Hogeborn
mandos-client: Bug Fix: Fix some memory leaks.
1687
    avahi_s_service_resolver_free(r);
353 by Teddy Hogeborn
* plugins.d/mandos-client.c (quit_now): Move up declaration before
1688
    return;
1689
  }
1690
  
293 by Teddy Hogeborn
* plugin-runner.c: Whitespace changes only.
1691
  switch(event){
21 by Teddy Hogeborn
* Makefile (CFLAGS): Changed to use $(WARN), $(DEBUG), $(COVERAGE) and
1692
  default:
1693
  case AVAHI_RESOLVER_FAILURE:
505.3.9 by Teddy Hogeborn
* plugins.d/mandos-client.c: Merge unified printing system.
1694
    fprintf_plus(stderr, "(Avahi Resolver) Failed to resolve service "
1695
		 "'%s' of type '%s' in domain '%s': %s\n", name, type,
1696
		 domain,
602 by Teddy Hogeborn
* plugins.d/mandos-client (mandos_context): Moved to inside "main()".
1697
		 avahi_strerror(avahi_server_errno
1698
				(((mandos_context*)mc)->server)));
21 by Teddy Hogeborn
* Makefile (CFLAGS): Changed to use $(WARN), $(DEBUG), $(COVERAGE) and
1699
    break;
22 by Teddy Hogeborn
* plugins.d/mandosclient.c (pgp_packet_decrypt): Cast "0" argument to
1700
    
21 by Teddy Hogeborn
* Makefile (CFLAGS): Changed to use $(WARN), $(DEBUG), $(COVERAGE) and
1701
  case AVAHI_RESOLVER_FOUND:
1702
    {
1703
      char ip[AVAHI_ADDRESS_STR_MAX];
1704
      avahi_address_snprint(ip, sizeof(ip), address);
1705
      if(debug){
505.2.6 by Björn Påhlsson
replace calls to fprintf with fprintf_plus.
1706
	fprintf_plus(stderr, "Mandos server \"%s\" found on %s (%s, %"
505.3.9 by Teddy Hogeborn
* plugins.d/mandos-client.c: Merge unified printing system.
1707
		     PRIdMAX ") on port %" PRIu16 "\n", name,
1708
		     host_name, ip, (intmax_t)interface, port);
21 by Teddy Hogeborn
* Makefile (CFLAGS): Changed to use $(WARN), $(DEBUG), $(COVERAGE) and
1709
      }
597 by Teddy Hogeborn
* plugins.d/mandos-client.c: Don't use assert(). Use in_port_t for
1710
      int ret = start_mandos_communication(ip, (in_port_t)port,
1711
					   interface,
602 by Teddy Hogeborn
* plugins.d/mandos-client (mandos_context): Moved to inside "main()".
1712
					   avahi_proto_to_af(proto),
1713
					   mc);
266 by Teddy Hogeborn
* plugin-runner.c: Only space changes.
1714
      if(ret == 0){
601 by Teddy Hogeborn
* plugins.d/mandos-client (mandos_context): Removed "simple_poll"
1715
	avahi_simple_poll_quit(simple_poll);
24.1.174 by Björn Påhlsson
* Makefile (CFLAGS): Added "-lrt" to include real time library.
1716
      } else {
597 by Teddy Hogeborn
* plugins.d/mandos-client.c: Don't use assert(). Use in_port_t for
1717
	if(not add_server(ip, (in_port_t)port, interface,
602 by Teddy Hogeborn
* plugins.d/mandos-client (mandos_context): Moved to inside "main()".
1718
			  avahi_proto_to_af(proto),
1719
			  &((mandos_context*)mc)->current_server)){
505.1.27 by teddy at bsnet
* plugins.d/mandos-client.c (add_server): Return bool; all callers
1720
	  fprintf_plus(stderr, "Failed to add server \"%s\" to server"
1721
		       " list\n", name);
1722
	}
21 by Teddy Hogeborn
* Makefile (CFLAGS): Changed to use $(WARN), $(DEBUG), $(COVERAGE) and
1723
      }
13 by Björn Påhlsson
Added following support:
1724
    }
21 by Teddy Hogeborn
* Makefile (CFLAGS): Changed to use $(WARN), $(DEBUG), $(COVERAGE) and
1725
  }
1726
  avahi_s_service_resolver_free(r);
13 by Björn Påhlsson
Added following support:
1727
}
1728
293 by Teddy Hogeborn
* plugin-runner.c: Whitespace changes only.
1729
static void browse_callback(AvahiSServiceBrowser *b,
1730
			    AvahiIfIndex interface,
1731
			    AvahiProtocol protocol,
1732
			    AvahiBrowserEvent event,
1733
			    const char *name,
1734
			    const char *type,
1735
			    const char *domain,
1736
			    AVAHI_GCC_UNUSED AvahiLookupResultFlags
1737
			    flags,
672 by Teddy Hogeborn
Update GCC warning flags and function attributes to GCC 4.7.
1738
			    void *mc){
597 by Teddy Hogeborn
* plugins.d/mandos-client.c: Don't use assert(). Use in_port_t for
1739
  if(b == NULL){
1740
    return;
1741
  }
24.1.9 by Björn Påhlsson
not working midwork...
1742
  
1743
  /* Called whenever a new services becomes available on the LAN or
1744
     is removed from the LAN */
1745
  
358 by Teddy Hogeborn
* plugins.d/mandos-client.c (start_mandos_communication): Check
1746
  if(quit_now){
1747
    return;
1748
  }
1749
  
293 by Teddy Hogeborn
* plugin-runner.c: Whitespace changes only.
1750
  switch(event){
24.1.9 by Björn Påhlsson
not working midwork...
1751
  default:
1752
  case AVAHI_BROWSER_FAILURE:
38 by Teddy Hogeborn
* plugbasedclient.c (main): New "--userid" and "--groupid" options.
1753
    
505.2.6 by Björn Påhlsson
replace calls to fprintf with fprintf_plus.
1754
    fprintf_plus(stderr, "(Avahi browser) %s\n",
602 by Teddy Hogeborn
* plugins.d/mandos-client (mandos_context): Moved to inside "main()".
1755
		 avahi_strerror(avahi_server_errno
1756
				(((mandos_context*)mc)->server)));
601 by Teddy Hogeborn
* plugins.d/mandos-client (mandos_context): Removed "simple_poll"
1757
    avahi_simple_poll_quit(simple_poll);
24.1.9 by Björn Påhlsson
not working midwork...
1758
    return;
38 by Teddy Hogeborn
* plugbasedclient.c (main): New "--userid" and "--groupid" options.
1759
    
24.1.9 by Björn Påhlsson
not working midwork...
1760
  case AVAHI_BROWSER_NEW:
40 by Teddy Hogeborn
* plugins.d/mandosclient.c (initgnutls): Moved "err" variable into its
1761
    /* We ignore the returned Avahi resolver object. In the callback
1762
       function we free it. If the Avahi server is terminated before
1763
       the callback function is called the Avahi server will free the
1764
       resolver for us. */
38 by Teddy Hogeborn
* plugbasedclient.c (main): New "--userid" and "--groupid" options.
1765
    
602 by Teddy Hogeborn
* plugins.d/mandos-client (mandos_context): Moved to inside "main()".
1766
    if(avahi_s_service_resolver_new(((mandos_context*)mc)->server,
1767
				    interface, protocol, name, type,
1768
				    domain, protocol, 0,
1769
				    resolve_callback, mc) == NULL)
505.3.9 by Teddy Hogeborn
* plugins.d/mandos-client.c: Merge unified printing system.
1770
      fprintf_plus(stderr, "Avahi: Failed to resolve service '%s':"
1771
		   " %s\n", name,
602 by Teddy Hogeborn
* plugins.d/mandos-client (mandos_context): Moved to inside "main()".
1772
		   avahi_strerror(avahi_server_errno
1773
				  (((mandos_context*)mc)->server)));
24.1.9 by Björn Påhlsson
not working midwork...
1774
    break;
38 by Teddy Hogeborn
* plugbasedclient.c (main): New "--userid" and "--groupid" options.
1775
    
24.1.9 by Björn Påhlsson
not working midwork...
1776
  case AVAHI_BROWSER_REMOVE:
1777
    break;
38 by Teddy Hogeborn
* plugbasedclient.c (main): New "--userid" and "--groupid" options.
1778
    
24.1.9 by Björn Påhlsson
not working midwork...
1779
  case AVAHI_BROWSER_ALL_FOR_NOW:
1780
  case AVAHI_BROWSER_CACHE_EXHAUSTED:
40 by Teddy Hogeborn
* plugins.d/mandosclient.c (initgnutls): Moved "err" variable into its
1781
    if(debug){
505.3.9 by Teddy Hogeborn
* plugins.d/mandos-client.c: Merge unified printing system.
1782
      fprintf_plus(stderr, "No Mandos server found, still"
1783
		   " searching...\n");
40 by Teddy Hogeborn
* plugins.d/mandosclient.c (initgnutls): Moved "err" variable into its
1784
    }
24.1.9 by Björn Påhlsson
not working midwork...
1785
    break;
1786
  }
13 by Björn Påhlsson
Added following support:
1787
}
1788
485 by Teddy Hogeborn
Merge from Björn.
1789
/* Signal handler that stops main loop after SIGTERM */
354 by Teddy Hogeborn
* plugins.d/mandos-client.c (signal_received): New.
1790
static void handle_sigterm(int sig){
308 by Teddy Hogeborn
* plugin-runner.c: Comment change.
1791
  if(quit_now){
1792
    return;
1793
  }
1794
  quit_now = 1;
354 by Teddy Hogeborn
* plugins.d/mandos-client.c (signal_received): New.
1795
  signal_received = sig;
24.1.134 by Björn Påhlsson
plugin-runner: Added support for empty string arguments
1796
  int old_errno = errno;
24.1.174 by Björn Påhlsson
* Makefile (CFLAGS): Added "-lrt" to include real time library.
1797
  /* set main loop to exit */
601 by Teddy Hogeborn
* plugins.d/mandos-client (mandos_context): Removed "simple_poll"
1798
  if(simple_poll != NULL){
1799
    avahi_simple_poll_quit(simple_poll);
308 by Teddy Hogeborn
* plugin-runner.c: Comment change.
1800
  }
24.1.134 by Björn Påhlsson
plugin-runner: Added support for empty string arguments
1801
  errno = old_errno;
1802
}
1803
672 by Teddy Hogeborn
Update GCC warning flags and function attributes to GCC 4.7.
1804
__attribute__((nonnull, warn_unused_result))
505.2.2 by teddy at bsnet
* plugins.d/mandos-client.c (good_interface): Use SIOCGIFFLAGS instead
1805
bool get_flags(const char *ifname, struct ifreq *ifr){
505.2.1 by teddy at bsnet
* plugins.d/mandos-client.c (good_interface): Use SIOCGIFFLAGS instead
1806
  int ret;
819 by Teddy Hogeborn
errno is of type int, not error_t
1807
  int old_errno;
505.2.2 by teddy at bsnet
* plugins.d/mandos-client.c (good_interface): Use SIOCGIFFLAGS instead
1808
  
505.2.1 by teddy at bsnet
* plugins.d/mandos-client.c (good_interface): Use SIOCGIFFLAGS instead
1809
  int s = socket(PF_INET6, SOCK_DGRAM, IPPROTO_IP);
1810
  if(s < 0){
819 by Teddy Hogeborn
errno is of type int, not error_t
1811
    old_errno = errno;
505.2.1 by teddy at bsnet
* plugins.d/mandos-client.c (good_interface): Use SIOCGIFFLAGS instead
1812
    perror_plus("socket");
819 by Teddy Hogeborn
errno is of type int, not error_t
1813
    errno = old_errno;
505.2.2 by teddy at bsnet
* plugins.d/mandos-client.c (good_interface): Use SIOCGIFFLAGS instead
1814
    return false;
505.2.1 by teddy at bsnet
* plugins.d/mandos-client.c (good_interface): Use SIOCGIFFLAGS instead
1815
  }
798 by Teddy Hogeborn
plugins.d/mandos-client.c (get_flags): Use strncpy(), not strcpy().
1816
  strncpy(ifr->ifr_name, ifname, IF_NAMESIZE);
1817
  ifr->ifr_name[IF_NAMESIZE-1] = '\0'; /* NUL terminate */
505.2.2 by teddy at bsnet
* plugins.d/mandos-client.c (good_interface): Use SIOCGIFFLAGS instead
1818
  ret = ioctl(s, SIOCGIFFLAGS, ifr);
505.2.1 by teddy at bsnet
* plugins.d/mandos-client.c (good_interface): Use SIOCGIFFLAGS instead
1819
  if(ret == -1){
237.2.34 by teddy at bsnet
* plugins.d/mandos-client.c: Added debug output.
1820
    if(debug){
819 by Teddy Hogeborn
errno is of type int, not error_t
1821
      old_errno = errno;
505.2.1 by teddy at bsnet
* plugins.d/mandos-client.c (good_interface): Use SIOCGIFFLAGS instead
1822
      perror_plus("ioctl SIOCGIFFLAGS");
819 by Teddy Hogeborn
errno is of type int, not error_t
1823
      errno = old_errno;
237.2.34 by teddy at bsnet
* plugins.d/mandos-client.c: Added debug output.
1824
    }
941 by Teddy Hogeborn
Check return values from newly added close() calls
1825
    if((close(s) == -1) and debug){
1826
      old_errno = errno;
1827
      perror_plus("close");
1828
      errno = old_errno;
1829
    }
505.2.2 by teddy at bsnet
* plugins.d/mandos-client.c (good_interface): Use SIOCGIFFLAGS instead
1830
    return false;
237.2.33 by teddy at bsnet
* plugins.d/mandos-client.c: An empty interface name now means to
1831
  }
941 by Teddy Hogeborn
Check return values from newly added close() calls
1832
  if((close(s) == -1) and debug){
1833
    old_errno = errno;
1834
    perror_plus("close");
1835
    errno = old_errno;
1836
  }
505.2.2 by teddy at bsnet
* plugins.d/mandos-client.c (good_interface): Use SIOCGIFFLAGS instead
1837
  return true;
1838
}
1839
672 by Teddy Hogeborn
Update GCC warning flags and function attributes to GCC 4.7.
1840
__attribute__((nonnull, warn_unused_result))
505.2.2 by teddy at bsnet
* plugins.d/mandos-client.c (good_interface): Use SIOCGIFFLAGS instead
1841
bool good_flags(const char *ifname, const struct ifreq *ifr){
1842
  
237.2.33 by teddy at bsnet
* plugins.d/mandos-client.c: An empty interface name now means to
1843
  /* Reject the loopback device */
505.2.2 by teddy at bsnet
* plugins.d/mandos-client.c (good_interface): Use SIOCGIFFLAGS instead
1844
  if(ifr->ifr_flags & IFF_LOOPBACK){
237.2.34 by teddy at bsnet
* plugins.d/mandos-client.c: Added debug output.
1845
    if(debug){
505.3.9 by Teddy Hogeborn
* plugins.d/mandos-client.c: Merge unified printing system.
1846
      fprintf_plus(stderr, "Rejecting loopback interface \"%s\"\n",
1847
		   ifname);
237.2.34 by teddy at bsnet
* plugins.d/mandos-client.c: Added debug output.
1848
    }
505.2.2 by teddy at bsnet
* plugins.d/mandos-client.c (good_interface): Use SIOCGIFFLAGS instead
1849
    return false;
237.2.33 by teddy at bsnet
* plugins.d/mandos-client.c: An empty interface name now means to
1850
  }
1851
  /* Accept point-to-point devices only if connect_to is specified */
505.2.2 by teddy at bsnet
* plugins.d/mandos-client.c (good_interface): Use SIOCGIFFLAGS instead
1852
  if(connect_to != NULL and (ifr->ifr_flags & IFF_POINTOPOINT)){
237.2.34 by teddy at bsnet
* plugins.d/mandos-client.c: Added debug output.
1853
    if(debug){
505.3.9 by Teddy Hogeborn
* plugins.d/mandos-client.c: Merge unified printing system.
1854
      fprintf_plus(stderr, "Accepting point-to-point interface"
1855
		   " \"%s\"\n", ifname);
237.2.34 by teddy at bsnet
* plugins.d/mandos-client.c: Added debug output.
1856
    }
505.2.2 by teddy at bsnet
* plugins.d/mandos-client.c (good_interface): Use SIOCGIFFLAGS instead
1857
    return true;
237.2.33 by teddy at bsnet
* plugins.d/mandos-client.c: An empty interface name now means to
1858
  }
1859
  /* Otherwise, reject non-broadcast-capable devices */
505.2.2 by teddy at bsnet
* plugins.d/mandos-client.c (good_interface): Use SIOCGIFFLAGS instead
1860
  if(not (ifr->ifr_flags & IFF_BROADCAST)){
237.2.34 by teddy at bsnet
* plugins.d/mandos-client.c: Added debug output.
1861
    if(debug){
505.3.9 by Teddy Hogeborn
* plugins.d/mandos-client.c: Merge unified printing system.
1862
      fprintf_plus(stderr, "Rejecting non-broadcast interface"
1863
		   " \"%s\"\n", ifname);
237.2.34 by teddy at bsnet
* plugins.d/mandos-client.c: Added debug output.
1864
    }
505.2.2 by teddy at bsnet
* plugins.d/mandos-client.c (good_interface): Use SIOCGIFFLAGS instead
1865
    return false;
237.2.33 by teddy at bsnet
* plugins.d/mandos-client.c: An empty interface name now means to
1866
  }
481 by teddy at bsnet
* plugins.d/mandos-client.c (good_interface): Reject non-ARP
1867
  /* Reject non-ARP interfaces (including dummy interfaces) */
505.2.2 by teddy at bsnet
* plugins.d/mandos-client.c (good_interface): Use SIOCGIFFLAGS instead
1868
  if(ifr->ifr_flags & IFF_NOARP){
481 by teddy at bsnet
* plugins.d/mandos-client.c (good_interface): Reject non-ARP
1869
    if(debug){
505.3.9 by Teddy Hogeborn
* plugins.d/mandos-client.c: Merge unified printing system.
1870
      fprintf_plus(stderr, "Rejecting non-ARP interface \"%s\"\n",
1871
		   ifname);
481 by teddy at bsnet
* plugins.d/mandos-client.c (good_interface): Reject non-ARP
1872
    }
505.2.2 by teddy at bsnet
* plugins.d/mandos-client.c (good_interface): Use SIOCGIFFLAGS instead
1873
    return false;
481 by teddy at bsnet
* plugins.d/mandos-client.c (good_interface): Reject non-ARP
1874
  }
505.2.2 by teddy at bsnet
* plugins.d/mandos-client.c (good_interface): Use SIOCGIFFLAGS instead
1875
  
237.2.33 by teddy at bsnet
* plugins.d/mandos-client.c: An empty interface name now means to
1876
  /* Accept this device */
237.2.34 by teddy at bsnet
* plugins.d/mandos-client.c: Added debug output.
1877
  if(debug){
505.2.6 by Björn Påhlsson
replace calls to fprintf with fprintf_plus.
1878
    fprintf_plus(stderr, "Interface \"%s\" is good\n", ifname);
505.2.2 by teddy at bsnet
* plugins.d/mandos-client.c (good_interface): Use SIOCGIFFLAGS instead
1879
  }
1880
  return true;
1881
}
1882
1883
/* 
1884
 * This function determines if a directory entry in /sys/class/net
1885
 * corresponds to an acceptable network device.
1886
 * (This function is passed to scandir(3) as a filter function.)
1887
 */
672 by Teddy Hogeborn
Update GCC warning flags and function attributes to GCC 4.7.
1888
__attribute__((nonnull, warn_unused_result))
505.2.2 by teddy at bsnet
* plugins.d/mandos-client.c (good_interface): Use SIOCGIFFLAGS instead
1889
int good_interface(const struct dirent *if_entry){
1890
  if(if_entry->d_name[0] == '.'){
1891
    return 0;
1892
  }
505.3.1 by teddy at bsnet
* plugins.d/mandos-client.c (good_interface): Add error message.
1893
  
505.2.2 by teddy at bsnet
* plugins.d/mandos-client.c (good_interface): Use SIOCGIFFLAGS instead
1894
  struct ifreq ifr;
1895
  if(not get_flags(if_entry->d_name, &ifr)){
505.3.1 by teddy at bsnet
* plugins.d/mandos-client.c (good_interface): Add error message.
1896
    if(debug){
505.3.9 by Teddy Hogeborn
* plugins.d/mandos-client.c: Merge unified printing system.
1897
      fprintf_plus(stderr, "Failed to get flags for interface "
1898
		   "\"%s\"\n", if_entry->d_name);
505.3.1 by teddy at bsnet
* plugins.d/mandos-client.c (good_interface): Add error message.
1899
    }
505.2.2 by teddy at bsnet
* plugins.d/mandos-client.c (good_interface): Use SIOCGIFFLAGS instead
1900
    return 0;
1901
  }
1902
  
1903
  if(not good_flags(if_entry->d_name, &ifr)){
1904
    return 0;
237.2.34 by teddy at bsnet
* plugins.d/mandos-client.c: Added debug output.
1905
  }
237.2.33 by teddy at bsnet
* plugins.d/mandos-client.c: An empty interface name now means to
1906
  return 1;
1907
}
1908
505.2.3 by Teddy Hogeborn
Intermediate commit - this does *not* work yet.
1909
/* 
594.1.4 by Teddy Hogeborn
* plugins.d/mandos-client.c (get_flags): Don't clobber errno.
1910
 * This function determines if a network interface is up.
1911
 */
672 by Teddy Hogeborn
Update GCC warning flags and function attributes to GCC 4.7.
1912
__attribute__((nonnull, warn_unused_result))
594.1.4 by Teddy Hogeborn
* plugins.d/mandos-client.c (get_flags): Don't clobber errno.
1913
bool interface_is_up(const char *interface){
1914
  struct ifreq ifr;
1915
  if(not get_flags(interface, &ifr)){
1916
    if(debug){
1917
      fprintf_plus(stderr, "Failed to get flags for interface "
1918
		   "\"%s\"\n", interface);
1919
    }
1920
    return false;
1921
  }
1922
  
1923
  return (bool)(ifr.ifr_flags & IFF_UP);
1924
}
1925
1926
/* 
1927
 * This function determines if a network interface is running
1928
 */
672 by Teddy Hogeborn
Update GCC warning flags and function attributes to GCC 4.7.
1929
__attribute__((nonnull, warn_unused_result))
594.1.4 by Teddy Hogeborn
* plugins.d/mandos-client.c (get_flags): Don't clobber errno.
1930
bool interface_is_running(const char *interface){
1931
  struct ifreq ifr;
1932
  if(not get_flags(interface, &ifr)){
1933
    if(debug){
1934
      fprintf_plus(stderr, "Failed to get flags for interface "
1935
		   "\"%s\"\n", interface);
1936
    }
1937
    return false;
1938
  }
1939
  
1940
  return (bool)(ifr.ifr_flags & IFF_RUNNING);
505.2.3 by Teddy Hogeborn
Intermediate commit - this does *not* work yet.
1941
}
1942
672 by Teddy Hogeborn
Update GCC warning flags and function attributes to GCC 4.7.
1943
__attribute__((nonnull, pure, warn_unused_result))
24.1.172 by Björn Påhlsson
using scandir instead of readdir
1944
int notdotentries(const struct dirent *direntry){
1945
  /* Skip "." and ".." */
1946
  if(direntry->d_name[0] == '.'
1947
     and (direntry->d_name[1] == '\0'
1948
	  or (direntry->d_name[1] == '.'
1949
	      and direntry->d_name[2] == '\0'))){
1950
    return 0;
1951
  }
1952
  return 1;
1953
}
1954
505.2.3 by Teddy Hogeborn
Intermediate commit - this does *not* work yet.
1955
/* Is this directory entry a runnable program? */
672 by Teddy Hogeborn
Update GCC warning flags and function attributes to GCC 4.7.
1956
__attribute__((nonnull, warn_unused_result))
505.2.3 by Teddy Hogeborn
Intermediate commit - this does *not* work yet.
1957
int runnable_hook(const struct dirent *direntry){
1958
  int ret;
505.3.6 by teddy at bsnet
* plugins.d/mandos-client.c: Some white space fixes.
1959
  size_t sret;
505.2.3 by Teddy Hogeborn
Intermediate commit - this does *not* work yet.
1960
  struct stat st;
1961
  
1962
  if((direntry->d_name)[0] == '\0'){
1963
    /* Empty name? */
1964
    return 0;
1965
  }
1966
  
505.3.6 by teddy at bsnet
* plugins.d/mandos-client.c: Some white space fixes.
1967
  sret = strspn(direntry->d_name, "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
1968
		"abcdefghijklmnopqrstuvwxyz"
1969
		"0123456789"
688 by Teddy Hogeborn
Minor bug fix in mandos-client: Allow periods in network hook names.
1970
		"_.-");
505.3.6 by teddy at bsnet
* plugins.d/mandos-client.c: Some white space fixes.
1971
  if((direntry->d_name)[sret] != '\0'){
1972
    /* Contains non-allowed characters */
1973
    if(debug){
505.2.6 by Björn Påhlsson
replace calls to fprintf with fprintf_plus.
1974
      fprintf_plus(stderr, "Ignoring hook \"%s\" with bad name\n",
505.3.9 by Teddy Hogeborn
* plugins.d/mandos-client.c: Merge unified printing system.
1975
		   direntry->d_name);
505.3.6 by teddy at bsnet
* plugins.d/mandos-client.c: Some white space fixes.
1976
    }
1977
    return 0;
1978
  }
505.2.3 by Teddy Hogeborn
Intermediate commit - this does *not* work yet.
1979
  
693 by Teddy Hogeborn
Make mandos-client use fstatat().
1980
  ret = fstatat(hookdir_fd, direntry->d_name, &st, 0);
505.2.3 by Teddy Hogeborn
Intermediate commit - this does *not* work yet.
1981
  if(ret == -1){
1982
    if(debug){
505.3.6 by teddy at bsnet
* plugins.d/mandos-client.c: Some white space fixes.
1983
      perror_plus("Could not stat hook");
505.2.3 by Teddy Hogeborn
Intermediate commit - this does *not* work yet.
1984
    }
1985
    return 0;
1986
  }
505.3.1 by teddy at bsnet
* plugins.d/mandos-client.c (good_interface): Add error message.
1987
  if(not (S_ISREG(st.st_mode))){
505.2.3 by Teddy Hogeborn
Intermediate commit - this does *not* work yet.
1988
    /* Not a regular file */
505.3.6 by teddy at bsnet
* plugins.d/mandos-client.c: Some white space fixes.
1989
    if(debug){
505.2.6 by Björn Påhlsson
replace calls to fprintf with fprintf_plus.
1990
      fprintf_plus(stderr, "Ignoring hook \"%s\" - not a file\n",
505.3.9 by Teddy Hogeborn
* plugins.d/mandos-client.c: Merge unified printing system.
1991
		   direntry->d_name);
505.3.6 by teddy at bsnet
* plugins.d/mandos-client.c: Some white space fixes.
1992
    }
505.2.3 by Teddy Hogeborn
Intermediate commit - this does *not* work yet.
1993
    return 0;
1994
  }
1995
  if(not (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))){
1996
    /* Not executable */
505.3.6 by teddy at bsnet
* plugins.d/mandos-client.c: Some white space fixes.
1997
    if(debug){
505.2.6 by Björn Påhlsson
replace calls to fprintf with fprintf_plus.
1998
      fprintf_plus(stderr, "Ignoring hook \"%s\" - not executable\n",
505.3.9 by Teddy Hogeborn
* plugins.d/mandos-client.c: Merge unified printing system.
1999
		   direntry->d_name);
505.3.6 by teddy at bsnet
* plugins.d/mandos-client.c: Some white space fixes.
2000
    }
505.2.3 by Teddy Hogeborn
Intermediate commit - this does *not* work yet.
2001
    return 0;
2002
  }
505.3.12 by Teddy Hogeborn
* plugins.d/mandos-client.c (runnable_hook): Add debug output.
2003
  if(debug){
2004
    fprintf_plus(stderr, "Hook \"%s\" is acceptable\n",
2005
		 direntry->d_name);
2006
  }
505.2.3 by Teddy Hogeborn
Intermediate commit - this does *not* work yet.
2007
  return 1;
2008
}
2009
672 by Teddy Hogeborn
Update GCC warning flags and function attributes to GCC 4.7.
2010
__attribute__((nonnull, warn_unused_result))
602 by Teddy Hogeborn
* plugins.d/mandos-client (mandos_context): Moved to inside "main()".
2011
int avahi_loop_with_timeout(AvahiSimplePoll *s, int retry_interval,
2012
			    mandos_context *mc){
24.1.174 by Björn Påhlsson
* Makefile (CFLAGS): Added "-lrt" to include real time library.
2013
  int ret;
2014
  struct timespec now;
2015
  struct timespec waited_time;
2016
  intmax_t block_time;
491 by teddy at bsnet
* plugins.d/mandos-client.c (avahi_loop_with_timeout): Fix warning.
2017
  
24.1.174 by Björn Påhlsson
* Makefile (CFLAGS): Added "-lrt" to include real time library.
2018
  while(true){
602 by Teddy Hogeborn
* plugins.d/mandos-client (mandos_context): Moved to inside "main()".
2019
    if(mc->current_server == NULL){
671 by Teddy Hogeborn
White space fix: change "if (" to "if(" in C code.
2020
      if(debug){
505.3.9 by Teddy Hogeborn
* plugins.d/mandos-client.c: Merge unified printing system.
2021
	fprintf_plus(stderr, "Wait until first server is found."
2022
		     " No timeout!\n");
24.1.174 by Björn Påhlsson
* Makefile (CFLAGS): Added "-lrt" to include real time library.
2023
      }
2024
      ret = avahi_simple_poll_iterate(s, -1);
2025
    } else {
671 by Teddy Hogeborn
White space fix: change "if (" to "if(" in C code.
2026
      if(debug){
505.3.9 by Teddy Hogeborn
* plugins.d/mandos-client.c: Merge unified printing system.
2027
	fprintf_plus(stderr, "Check current_server if we should run"
2028
		     " it, or wait\n");
24.1.174 by Björn Påhlsson
* Makefile (CFLAGS): Added "-lrt" to include real time library.
2029
      }
2030
      /* the current time */
2031
      ret = clock_gettime(CLOCK_MONOTONIC, &now);
2032
      if(ret == -1){
2033
	perror_plus("clock_gettime");
2034
	return -1;
2035
      }
2036
      /* Calculating in ms how long time between now and server
2037
	 who we visted longest time ago. Now - last seen.  */
485 by Teddy Hogeborn
Merge from Björn.
2038
      waited_time.tv_sec = (now.tv_sec
602 by Teddy Hogeborn
* plugins.d/mandos-client (mandos_context): Moved to inside "main()".
2039
			    - mc->current_server->last_seen.tv_sec);
485 by Teddy Hogeborn
Merge from Björn.
2040
      waited_time.tv_nsec = (now.tv_nsec
602 by Teddy Hogeborn
* plugins.d/mandos-client (mandos_context): Moved to inside "main()".
2041
			     - mc->current_server->last_seen.tv_nsec);
485 by Teddy Hogeborn
Merge from Björn.
2042
      /* total time is 10s/10,000ms.
2043
	 Converting to s from ms by dividing by 1,000,
2044
	 and ns to ms by dividing by 1,000,000. */
2045
      block_time = ((retry_interval
2046
		     - ((intmax_t)waited_time.tv_sec * 1000))
2047
		    - ((intmax_t)waited_time.tv_nsec / 1000000));
491 by teddy at bsnet
* plugins.d/mandos-client.c (avahi_loop_with_timeout): Fix warning.
2048
      
671 by Teddy Hogeborn
White space fix: change "if (" to "if(" in C code.
2049
      if(debug){
505.3.9 by Teddy Hogeborn
* plugins.d/mandos-client.c: Merge unified printing system.
2050
	fprintf_plus(stderr, "Blocking for %" PRIdMAX " ms\n",
2051
		     block_time);
24.1.174 by Björn Påhlsson
* Makefile (CFLAGS): Added "-lrt" to include real time library.
2052
      }
491 by teddy at bsnet
* plugins.d/mandos-client.c (avahi_loop_with_timeout): Fix warning.
2053
      
24.1.174 by Björn Påhlsson
* Makefile (CFLAGS): Added "-lrt" to include real time library.
2054
      if(block_time <= 0){
602 by Teddy Hogeborn
* plugins.d/mandos-client (mandos_context): Moved to inside "main()".
2055
	ret = start_mandos_communication(mc->current_server->ip,
2056
					 mc->current_server->port,
2057
					 mc->current_server->if_index,
2058
					 mc->current_server->af, mc);
24.1.174 by Björn Påhlsson
* Makefile (CFLAGS): Added "-lrt" to include real time library.
2059
	if(ret == 0){
602 by Teddy Hogeborn
* plugins.d/mandos-client (mandos_context): Moved to inside "main()".
2060
	  avahi_simple_poll_quit(s);
24.1.174 by Björn Påhlsson
* Makefile (CFLAGS): Added "-lrt" to include real time library.
2061
	  return 0;
2062
	}
485 by Teddy Hogeborn
Merge from Björn.
2063
	ret = clock_gettime(CLOCK_MONOTONIC,
602 by Teddy Hogeborn
* plugins.d/mandos-client (mandos_context): Moved to inside "main()".
2064
			    &mc->current_server->last_seen);
24.1.174 by Björn Påhlsson
* Makefile (CFLAGS): Added "-lrt" to include real time library.
2065
	if(ret == -1){
2066
	  perror_plus("clock_gettime");
2067
	  return -1;
2068
	}
602 by Teddy Hogeborn
* plugins.d/mandos-client (mandos_context): Moved to inside "main()".
2069
	mc->current_server = mc->current_server->next;
485 by Teddy Hogeborn
Merge from Björn.
2070
	block_time = 0; 	/* Call avahi to find new Mandos
2071
				   servers, but don't block */
24.1.174 by Björn Påhlsson
* Makefile (CFLAGS): Added "-lrt" to include real time library.
2072
      }
2073
      
2074
      ret = avahi_simple_poll_iterate(s, (int)block_time);
2075
    }
2076
    if(ret != 0){
671 by Teddy Hogeborn
White space fix: change "if (" to "if(" in C code.
2077
      if(ret > 0 or errno != EINTR){
24.1.174 by Björn Påhlsson
* Makefile (CFLAGS): Added "-lrt" to include real time library.
2078
	return (ret != 1) ? ret : 0;
2079
      }
2080
    }
2081
  }
2082
}
2083
672 by Teddy Hogeborn
Update GCC warning flags and function attributes to GCC 4.7.
2084
__attribute__((nonnull))
2085
void run_network_hooks(const char *mode, const char *interface,
505.3.8 by Teddy Hogeborn
* plugins.d/mandos-client.c (run_network_hooks): New.
2086
		       const float delay){
704 by Teddy Hogeborn
mandos-client: Fix some bugs on error conditions.
2087
  struct dirent **direntries = NULL;
691 by Teddy Hogeborn
Make mandos-client use scandirat() if it exists.
2088
  if(hookdir_fd == -1){
738.1.2 by Teddy Hogeborn
mandos-client: Try to start a plugin to add and remove a local route.
2089
    hookdir_fd = open(hookdir, O_RDONLY | O_DIRECTORY | O_PATH
2090
		      | O_CLOEXEC);
691 by Teddy Hogeborn
Make mandos-client use scandirat() if it exists.
2091
    if(hookdir_fd == -1){
2092
      if(errno == ENOENT){
2093
	if(debug){
2094
	  fprintf_plus(stderr, "Network hook directory \"%s\" not"
2095
		       " found\n", hookdir);
2096
	}
2097
      } else {
2098
	perror_plus("open");
2099
      }
2100
      return;
2101
    }
2102
  }
935 by Teddy Hogeborn
Client: Bug fix: Possible memory leak if failing to open /dev/null
2103
  int devnull = (int)TEMP_FAILURE_RETRY(open("/dev/null", O_RDONLY));
2104
  if(devnull == -1){
2105
    perror_plus("open(\"/dev/null\", O_RDONLY)");
2106
    return;
2107
  }
691 by Teddy Hogeborn
Make mandos-client use scandirat() if it exists.
2108
  int numhooks = scandirat(hookdir_fd, ".", &direntries,
2109
			   runnable_hook, alphasort);
505.3.8 by Teddy Hogeborn
* plugins.d/mandos-client.c (run_network_hooks): New.
2110
  if(numhooks == -1){
691 by Teddy Hogeborn
Make mandos-client use scandirat() if it exists.
2111
    perror_plus("scandir");
935 by Teddy Hogeborn
Client: Bug fix: Possible memory leak if failing to open /dev/null
2112
    close(devnull);
691 by Teddy Hogeborn
Make mandos-client use scandirat() if it exists.
2113
    return;
2114
  }
2115
  struct dirent *direntry;
2116
  int ret;
2117
  for(int i = 0; i < numhooks; i++){
2118
    direntry = direntries[i];
2119
    if(debug){
2120
      fprintf_plus(stderr, "Running network hook \"%s\"\n",
2121
		   direntry->d_name);
2122
    }
2123
    pid_t hook_pid = fork();
2124
    if(hook_pid == 0){
2125
      /* Child */
2126
      /* Raise privileges */
706 by Teddy Hogeborn
mandos-client: Better error messages.
2127
      errno = raise_privileges_permanently();
2128
      if(errno != 0){
691 by Teddy Hogeborn
Make mandos-client use scandirat() if it exists.
2129
	perror_plus("Failed to raise privileges");
2130
	_exit(EX_NOPERM);
2131
      }
2132
      /* Set group */
2133
      errno = 0;
2134
      ret = setgid(0);
2135
      if(ret == -1){
2136
	perror_plus("setgid");
2137
	_exit(EX_NOPERM);
2138
      }
2139
      /* Reset supplementary groups */
2140
      errno = 0;
2141
      ret = setgroups(0, NULL);
2142
      if(ret == -1){
2143
	perror_plus("setgroups");
2144
	_exit(EX_NOPERM);
2145
      }
2146
      ret = setenv("MANDOSNETHOOKDIR", hookdir, 1);
2147
      if(ret == -1){
2148
	perror_plus("setenv");
2149
	_exit(EX_OSERR);
2150
      }
2151
      ret = setenv("DEVICE", interface, 1);
2152
      if(ret == -1){
2153
	perror_plus("setenv");
2154
	_exit(EX_OSERR);
2155
      }
2156
      ret = setenv("VERBOSITY", debug ? "1" : "0", 1);
2157
      if(ret == -1){
2158
	perror_plus("setenv");
2159
	_exit(EX_OSERR);
2160
      }
2161
      ret = setenv("MODE", mode, 1);
2162
      if(ret == -1){
2163
	perror_plus("setenv");
2164
	_exit(EX_OSERR);
2165
      }
2166
      char *delaystring;
2167
      ret = asprintf(&delaystring, "%f", (double)delay);
2168
      if(ret == -1){
505.3.8 by Teddy Hogeborn
* plugins.d/mandos-client.c (run_network_hooks): New.
2169
	perror_plus("asprintf");
691 by Teddy Hogeborn
Make mandos-client use scandirat() if it exists.
2170
	_exit(EX_OSERR);
2171
      }
2172
      ret = setenv("DELAY", delaystring, 1);
2173
      if(ret == -1){
505.3.8 by Teddy Hogeborn
* plugins.d/mandos-client.c (run_network_hooks): New.
2174
	free(delaystring);
691 by Teddy Hogeborn
Make mandos-client use scandirat() if it exists.
2175
	perror_plus("setenv");
2176
	_exit(EX_OSERR);
2177
      }
2178
      free(delaystring);
2179
      if(connect_to != NULL){
2180
	ret = setenv("CONNECT", connect_to, 1);
2181
	if(ret == -1){
2182
	  perror_plus("setenv");
2183
	  _exit(EX_OSERR);
2184
	}
2185
      }
738.1.3 by Teddy Hogeborn
mandos-client: Minor changes to check for more error conditions.
2186
      int hook_fd = (int)TEMP_FAILURE_RETRY(openat(hookdir_fd,
2187
						   direntry->d_name,
2188
						   O_RDONLY));
696 by Teddy Hogeborn
Bug fix for mandos-client: Run the network hook, not the directory.
2189
      if(hook_fd == -1){
2190
	perror_plus("openat");
2191
	_exit(EXIT_FAILURE);
2192
      }
774 by Teddy Hogeborn
Don't use TEMP_FAILURE_RETRY around close().
2193
      if(close(hookdir_fd) == -1){
696 by Teddy Hogeborn
Bug fix for mandos-client: Run the network hook, not the directory.
2194
	perror_plus("close");
2195
	_exit(EXIT_FAILURE);
2196
      }
738.1.2 by Teddy Hogeborn
mandos-client: Try to start a plugin to add and remove a local route.
2197
      ret = dup2(devnull, STDIN_FILENO);
2198
      if(ret == -1){
2199
	perror_plus("dup2(devnull, STDIN_FILENO)");
2200
	_exit(EX_OSERR);
2201
      }
774 by Teddy Hogeborn
Don't use TEMP_FAILURE_RETRY around close().
2202
      ret = close(devnull);
738.1.2 by Teddy Hogeborn
mandos-client: Try to start a plugin to add and remove a local route.
2203
      if(ret == -1){
2204
	perror_plus("close");
2205
	_exit(EX_OSERR);
2206
      }
2207
      ret = dup2(STDERR_FILENO, STDOUT_FILENO);
2208
      if(ret == -1){
2209
	perror_plus("dup2(STDERR_FILENO, STDOUT_FILENO)");
2210
	_exit(EX_OSERR);
2211
      }
696 by Teddy Hogeborn
Bug fix for mandos-client: Run the network hook, not the directory.
2212
      if(fexecve(hook_fd, (char *const []){ direntry->d_name, NULL },
2213
		 environ) == -1){
692 by Teddy Hogeborn
Make mandos-client use fexecve().
2214
	perror_plus("fexecve");
691 by Teddy Hogeborn
Make mandos-client use scandirat() if it exists.
2215
	_exit(EXIT_FAILURE);
2216
      }
2217
    } else {
733 by Teddy Hogeborn
mandos-client: Bug fix: Check fork() return value.
2218
      if(hook_pid == -1){
2219
	perror_plus("fork");
2220
	free(direntry);
2221
	continue;
2222
      }
691 by Teddy Hogeborn
Make mandos-client use scandirat() if it exists.
2223
      int status;
2224
      if(TEMP_FAILURE_RETRY(waitpid(hook_pid, &status, 0)) == -1){
2225
	perror_plus("waitpid");
715 by Teddy Hogeborn
mandos-client: Bug Fix: Fix some memory leaks.
2226
	free(direntry);
691 by Teddy Hogeborn
Make mandos-client use scandirat() if it exists.
2227
	continue;
2228
      }
2229
      if(WIFEXITED(status)){
2230
	if(WEXITSTATUS(status) != 0){
2231
	  fprintf_plus(stderr, "Warning: network hook \"%s\" exited"
2232
		       " with status %d\n", direntry->d_name,
2233
		       WEXITSTATUS(status));
715 by Teddy Hogeborn
mandos-client: Bug Fix: Fix some memory leaks.
2234
	  free(direntry);
691 by Teddy Hogeborn
Make mandos-client use scandirat() if it exists.
2235
	  continue;
2236
	}
2237
      } else if(WIFSIGNALED(status)){
2238
	fprintf_plus(stderr, "Warning: network hook \"%s\" died by"
2239
		     " signal %d\n", direntry->d_name,
2240
		     WTERMSIG(status));
715 by Teddy Hogeborn
mandos-client: Bug Fix: Fix some memory leaks.
2241
	free(direntry);
691 by Teddy Hogeborn
Make mandos-client use scandirat() if it exists.
2242
	continue;
505.3.8 by Teddy Hogeborn
* plugins.d/mandos-client.c (run_network_hooks): New.
2243
      } else {
691 by Teddy Hogeborn
Make mandos-client use scandirat() if it exists.
2244
	fprintf_plus(stderr, "Warning: network hook \"%s\""
2245
		     " crashed\n", direntry->d_name);
715 by Teddy Hogeborn
mandos-client: Bug Fix: Fix some memory leaks.
2246
	free(direntry);
691 by Teddy Hogeborn
Make mandos-client use scandirat() if it exists.
2247
	continue;
2248
      }
2249
    }
2250
    if(debug){
2251
      fprintf_plus(stderr, "Network hook \"%s\" ran successfully\n",
2252
		   direntry->d_name);
2253
    }
715 by Teddy Hogeborn
mandos-client: Bug Fix: Fix some memory leaks.
2254
    free(direntry);
691 by Teddy Hogeborn
Make mandos-client use scandirat() if it exists.
2255
  }
704 by Teddy Hogeborn
mandos-client: Fix some bugs on error conditions.
2256
  free(direntries);
774 by Teddy Hogeborn
Don't use TEMP_FAILURE_RETRY around close().
2257
  if(close(hookdir_fd) == -1){
691 by Teddy Hogeborn
Make mandos-client use scandirat() if it exists.
2258
    perror_plus("close");
2259
  } else {
2260
    hookdir_fd = -1;
2261
  }
2262
  close(devnull);
505.3.8 by Teddy Hogeborn
* plugins.d/mandos-client.c (run_network_hooks): New.
2263
}
2264
672 by Teddy Hogeborn
Update GCC warning flags and function attributes to GCC 4.7.
2265
__attribute__((nonnull, warn_unused_result))
819 by Teddy Hogeborn
errno is of type int, not error_t
2266
int bring_up_interface(const char *const interface,
2267
		       const float delay){
2268
  int old_errno = errno;
672 by Teddy Hogeborn
Update GCC warning flags and function attributes to GCC 4.7.
2269
  int ret;
594.1.1 by Teddy Hogeborn
* plugins.d/mandos-client.c: Refactoring.
2270
  struct ifreq network;
594.1.4 by Teddy Hogeborn
* plugins.d/mandos-client.c (get_flags): Don't clobber errno.
2271
  unsigned int if_index = if_nametoindex(interface);
594.1.1 by Teddy Hogeborn
* plugins.d/mandos-client.c: Refactoring.
2272
  if(if_index == 0){
2273
    fprintf_plus(stderr, "No such interface: \"%s\"\n", interface);
594.1.2 by Teddy Hogeborn
* plugins.d/mandos-client.c (bring_up_interface): Bug fix: Return
2274
    errno = old_errno;
2275
    return ENXIO;
594.1.1 by Teddy Hogeborn
* plugins.d/mandos-client.c: Refactoring.
2276
  }
2277
  
2278
  if(quit_now){
594.1.2 by Teddy Hogeborn
* plugins.d/mandos-client.c (bring_up_interface): Bug fix: Return
2279
    errno = old_errno;
594.1.1 by Teddy Hogeborn
* plugins.d/mandos-client.c: Refactoring.
2280
    return EINTR;
2281
  }
2282
  
594.1.4 by Teddy Hogeborn
* plugins.d/mandos-client.c (get_flags): Don't clobber errno.
2283
  if(not interface_is_up(interface)){
819 by Teddy Hogeborn
errno is of type int, not error_t
2284
    int ret_errno = 0;
2285
    int ioctl_errno = 0;
672 by Teddy Hogeborn
Update GCC warning flags and function attributes to GCC 4.7.
2286
    if(not get_flags(interface, &network)){
594.1.4 by Teddy Hogeborn
* plugins.d/mandos-client.c (get_flags): Don't clobber errno.
2287
      ret_errno = errno;
2288
      fprintf_plus(stderr, "Failed to get flags for interface "
2289
		   "\"%s\"\n", interface);
672 by Teddy Hogeborn
Update GCC warning flags and function attributes to GCC 4.7.
2290
      errno = old_errno;
594.1.4 by Teddy Hogeborn
* plugins.d/mandos-client.c (get_flags): Don't clobber errno.
2291
      return ret_errno;
2292
    }
672 by Teddy Hogeborn
Update GCC warning flags and function attributes to GCC 4.7.
2293
    network.ifr_flags |= IFF_UP; /* set flag */
594.1.4 by Teddy Hogeborn
* plugins.d/mandos-client.c (get_flags): Don't clobber errno.
2294
    
672 by Teddy Hogeborn
Update GCC warning flags and function attributes to GCC 4.7.
2295
    int sd = socket(PF_INET6, SOCK_DGRAM, IPPROTO_IP);
2296
    if(sd == -1){
594.1.4 by Teddy Hogeborn
* plugins.d/mandos-client.c (get_flags): Don't clobber errno.
2297
      ret_errno = errno;
2298
      perror_plus("socket");
2299
      errno = old_errno;
2300
      return ret_errno;
2301
    }
672 by Teddy Hogeborn
Update GCC warning flags and function attributes to GCC 4.7.
2302
    
594.1.4 by Teddy Hogeborn
* plugins.d/mandos-client.c (get_flags): Don't clobber errno.
2303
    if(quit_now){
774 by Teddy Hogeborn
Don't use TEMP_FAILURE_RETRY around close().
2304
      ret = close(sd);
672 by Teddy Hogeborn
Update GCC warning flags and function attributes to GCC 4.7.
2305
      if(ret == -1){
2306
	perror_plus("close");
2307
      }
594.1.4 by Teddy Hogeborn
* plugins.d/mandos-client.c (get_flags): Don't clobber errno.
2308
      errno = old_errno;
2309
      return EINTR;
2310
    }
2311
    
2312
    if(debug){
2313
      fprintf_plus(stderr, "Bringing up interface \"%s\"\n",
2314
		   interface);
2315
    }
2316
    
672 by Teddy Hogeborn
Update GCC warning flags and function attributes to GCC 4.7.
2317
    /* Raise privileges */
2318
    ret_errno = raise_privileges();
680 by Teddy Hogeborn
Minor changes to minimize diff from last release.
2319
    if(ret_errno != 0){
706 by Teddy Hogeborn
mandos-client: Better error messages.
2320
      errno = ret_errno;
680 by Teddy Hogeborn
Minor changes to minimize diff from last release.
2321
      perror_plus("Failed to raise privileges");
2322
    }
2323
    
2324
#ifdef __linux__
2325
    int ret_linux;
672 by Teddy Hogeborn
Update GCC warning flags and function attributes to GCC 4.7.
2326
    bool restore_loglevel = false;
2327
    if(ret_errno == 0){
2328
      /* Lower kernel loglevel to KERN_NOTICE to avoid KERN_INFO
2329
	 messages about the network interface to mess up the prompt */
2330
      ret_linux = klogctl(8, NULL, 5);
2331
      if(ret_linux == -1){
2332
	perror_plus("klogctl");
2333
      } else {
2334
	restore_loglevel = true;
2335
      }
594.1.4 by Teddy Hogeborn
* plugins.d/mandos-client.c (get_flags): Don't clobber errno.
2336
    }
2337
#endif	/* __linux__ */
672 by Teddy Hogeborn
Update GCC warning flags and function attributes to GCC 4.7.
2338
    int ret_setflags = ioctl(sd, SIOCSIFFLAGS, &network);
2339
    ioctl_errno = errno;
594.1.4 by Teddy Hogeborn
* plugins.d/mandos-client.c (get_flags): Don't clobber errno.
2340
#ifdef __linux__
2341
    if(restore_loglevel){
2342
      ret_linux = klogctl(7, NULL, 0);
2343
      if(ret_linux == -1){
2344
	perror_plus("klogctl");
2345
      }
2346
    }
2347
#endif	/* __linux__ */
2348
    
672 by Teddy Hogeborn
Update GCC warning flags and function attributes to GCC 4.7.
2349
    /* If raise_privileges() succeeded above */
2350
    if(ret_errno == 0){
2351
      /* Lower privileges */
2352
      ret_errno = lower_privileges();
2353
      if(ret_errno != 0){
2354
	errno = ret_errno;
2355
	perror_plus("Failed to lower privileges");
2356
      }
2357
    }
594.1.4 by Teddy Hogeborn
* plugins.d/mandos-client.c (get_flags): Don't clobber errno.
2358
    
2359
    /* Close the socket */
774 by Teddy Hogeborn
Don't use TEMP_FAILURE_RETRY around close().
2360
    ret = close(sd);
594.1.1 by Teddy Hogeborn
* plugins.d/mandos-client.c: Refactoring.
2361
    if(ret == -1){
594.1.4 by Teddy Hogeborn
* plugins.d/mandos-client.c (get_flags): Don't clobber errno.
2362
      perror_plus("close");
2363
    }
2364
    
2365
    if(ret_setflags == -1){
672 by Teddy Hogeborn
Update GCC warning flags and function attributes to GCC 4.7.
2366
      errno = ioctl_errno;
594.1.1 by Teddy Hogeborn
* plugins.d/mandos-client.c: Refactoring.
2367
      perror_plus("ioctl SIOCSIFFLAGS +IFF_UP");
594.1.2 by Teddy Hogeborn
* plugins.d/mandos-client.c (bring_up_interface): Bug fix: Return
2368
      errno = old_errno;
672 by Teddy Hogeborn
Update GCC warning flags and function attributes to GCC 4.7.
2369
      return ioctl_errno;
594.1.1 by Teddy Hogeborn
* plugins.d/mandos-client.c: Refactoring.
2370
    }
594.1.4 by Teddy Hogeborn
* plugins.d/mandos-client.c (get_flags): Don't clobber errno.
2371
  } else if(debug){
2372
    fprintf_plus(stderr, "Interface \"%s\" is already up; good\n",
2373
		 interface);
594.1.1 by Teddy Hogeborn
* plugins.d/mandos-client.c: Refactoring.
2374
  }
594.1.4 by Teddy Hogeborn
* plugins.d/mandos-client.c (get_flags): Don't clobber errno.
2375
  
594.1.1 by Teddy Hogeborn
* plugins.d/mandos-client.c: Refactoring.
2376
  /* Sleep checking until interface is running.
2377
     Check every 0.25s, up to total time of delay */
890 by Teddy Hogeborn
Add spaces around all '=' signs in all C code.
2378
  for(int i = 0; i < delay * 4; i++){
594.1.4 by Teddy Hogeborn
* plugins.d/mandos-client.c (get_flags): Don't clobber errno.
2379
    if(interface_is_running(interface)){
594.1.1 by Teddy Hogeborn
* plugins.d/mandos-client.c: Refactoring.
2380
      break;
2381
    }
2382
    struct timespec sleeptime = { .tv_nsec = 250000000 };
2383
    ret = nanosleep(&sleeptime, NULL);
2384
    if(ret == -1 and errno != EINTR){
2385
      perror_plus("nanosleep");
2386
    }
2387
  }
594.1.4 by Teddy Hogeborn
* plugins.d/mandos-client.c (get_flags): Don't clobber errno.
2388
  
2389
  errno = old_errno;
2390
  return 0;
2391
}
2392
672 by Teddy Hogeborn
Update GCC warning flags and function attributes to GCC 4.7.
2393
__attribute__((nonnull, warn_unused_result))
819 by Teddy Hogeborn
errno is of type int, not error_t
2394
int take_down_interface(const char *const interface){
2395
  int old_errno = errno;
594.1.4 by Teddy Hogeborn
* plugins.d/mandos-client.c (get_flags): Don't clobber errno.
2396
  struct ifreq network;
2397
  unsigned int if_index = if_nametoindex(interface);
2398
  if(if_index == 0){
2399
    fprintf_plus(stderr, "No such interface: \"%s\"\n", interface);
2400
    errno = old_errno;
2401
    return ENXIO;
594.1.1 by Teddy Hogeborn
* plugins.d/mandos-client.c: Refactoring.
2402
  }
594.1.4 by Teddy Hogeborn
* plugins.d/mandos-client.c (get_flags): Don't clobber errno.
2403
  if(interface_is_up(interface)){
819 by Teddy Hogeborn
errno is of type int, not error_t
2404
    int ret_errno = 0;
2405
    int ioctl_errno = 0;
594.1.4 by Teddy Hogeborn
* plugins.d/mandos-client.c (get_flags): Don't clobber errno.
2406
    if(not get_flags(interface, &network) and debug){
2407
      ret_errno = errno;
2408
      fprintf_plus(stderr, "Failed to get flags for interface "
2409
		   "\"%s\"\n", interface);
672 by Teddy Hogeborn
Update GCC warning flags and function attributes to GCC 4.7.
2410
      errno = old_errno;
594.1.4 by Teddy Hogeborn
* plugins.d/mandos-client.c (get_flags): Don't clobber errno.
2411
      return ret_errno;
2412
    }
2413
    network.ifr_flags &= ~(short)IFF_UP; /* clear flag */
2414
    
666 by Teddy Hogeborn
Bug fix: Free all memory and give better messages when memory is full.
2415
    int sd = socket(PF_INET6, SOCK_DGRAM, IPPROTO_IP);
672 by Teddy Hogeborn
Update GCC warning flags and function attributes to GCC 4.7.
2416
    if(sd == -1){
594.1.4 by Teddy Hogeborn
* plugins.d/mandos-client.c (get_flags): Don't clobber errno.
2417
      ret_errno = errno;
2418
      perror_plus("socket");
2419
      errno = old_errno;
2420
      return ret_errno;
2421
    }
2422
    
2423
    if(debug){
2424
      fprintf_plus(stderr, "Taking down interface \"%s\"\n",
2425
		   interface);
2426
    }
2427
    
672 by Teddy Hogeborn
Update GCC warning flags and function attributes to GCC 4.7.
2428
    /* Raise privileges */
2429
    ret_errno = raise_privileges();
2430
    if(ret_errno != 0){
706 by Teddy Hogeborn
mandos-client: Better error messages.
2431
      errno = ret_errno;
672 by Teddy Hogeborn
Update GCC warning flags and function attributes to GCC 4.7.
2432
      perror_plus("Failed to raise privileges");
2433
    }
680 by Teddy Hogeborn
Minor changes to minimize diff from last release.
2434
    
666 by Teddy Hogeborn
Bug fix: Free all memory and give better messages when memory is full.
2435
    int ret_setflags = ioctl(sd, SIOCSIFFLAGS, &network);
672 by Teddy Hogeborn
Update GCC warning flags and function attributes to GCC 4.7.
2436
    ioctl_errno = errno;
594.1.4 by Teddy Hogeborn
* plugins.d/mandos-client.c (get_flags): Don't clobber errno.
2437
    
672 by Teddy Hogeborn
Update GCC warning flags and function attributes to GCC 4.7.
2438
    /* If raise_privileges() succeeded above */
2439
    if(ret_errno == 0){
2440
      /* Lower privileges */
2441
      ret_errno = lower_privileges();
2442
      if(ret_errno != 0){
2443
	errno = ret_errno;
2444
	perror_plus("Failed to lower privileges");
2445
      }
2446
    }
594.1.4 by Teddy Hogeborn
* plugins.d/mandos-client.c (get_flags): Don't clobber errno.
2447
    
2448
    /* Close the socket */
774 by Teddy Hogeborn
Don't use TEMP_FAILURE_RETRY around close().
2449
    int ret = close(sd);
594.1.1 by Teddy Hogeborn
* plugins.d/mandos-client.c: Refactoring.
2450
    if(ret == -1){
594.1.4 by Teddy Hogeborn
* plugins.d/mandos-client.c (get_flags): Don't clobber errno.
2451
      perror_plus("close");
2452
    }
2453
    
2454
    if(ret_setflags == -1){
672 by Teddy Hogeborn
Update GCC warning flags and function attributes to GCC 4.7.
2455
      errno = ioctl_errno;
594.1.4 by Teddy Hogeborn
* plugins.d/mandos-client.c (get_flags): Don't clobber errno.
2456
      perror_plus("ioctl SIOCSIFFLAGS -IFF_UP");
2457
      errno = old_errno;
672 by Teddy Hogeborn
Update GCC warning flags and function attributes to GCC 4.7.
2458
      return ioctl_errno;
594.1.4 by Teddy Hogeborn
* plugins.d/mandos-client.c (get_flags): Don't clobber errno.
2459
    }
2460
  } else if(debug){
2461
    fprintf_plus(stderr, "Interface \"%s\" is already down; odd\n",
2462
		 interface);
594.1.1 by Teddy Hogeborn
* plugins.d/mandos-client.c: Refactoring.
2463
  }
594.1.4 by Teddy Hogeborn
* plugins.d/mandos-client.c (get_flags): Don't clobber errno.
2464
  
594.1.2 by Teddy Hogeborn
* plugins.d/mandos-client.c (bring_up_interface): Bug fix: Return
2465
  errno = old_errno;
2466
  return 0;
594.1.1 by Teddy Hogeborn
* plugins.d/mandos-client.c: Refactoring.
2467
}
2468
40 by Teddy Hogeborn
* plugins.d/mandosclient.c (initgnutls): Moved "err" variable into its
2469
int main(int argc, char *argv[]){
743 by Teddy Hogeborn
Automatically determine the number of DH bits in the TLS handshake.
2470
  mandos_context mc = { .server = NULL, .dh_bits = 0,
962 by Teddy Hogeborn
Add support for using raw public keys in TLS (RFC 7250)
2471
#if GNUTLS_VERSION_NUMBER >= 0x030606
2472
			.priority = "SECURE128:!CTYPE-X.509"
2473
			":+CTYPE-RAWPK:!RSA:!VERS-ALL:+VERS-TLS1.3"
2474
			":%PROFILE_ULTRA",
2475
#elif GNUTLS_VERSION_NUMBER < 0x030600
777 by Teddy Hogeborn
Bug fix for GnuTLS 3: be compatible with old 2048-bit DSA keys.
2476
			.priority = "SECURE256:!CTYPE-X.509"
2477
			":+CTYPE-OPENPGP:!RSA:+SIGN-DSA-SHA256",
962 by Teddy Hogeborn
Add support for using raw public keys in TLS (RFC 7250)
2478
#else
2479
#error "Needs GnuTLS 3.6.6 or later, or before 3.6.0"
2480
#endif
777 by Teddy Hogeborn
Bug fix for GnuTLS 3: be compatible with old 2048-bit DSA keys.
2481
			.current_server = NULL, .interfaces = NULL,
2482
			.interfaces_size = 0 };
293 by Teddy Hogeborn
* plugin-runner.c: Whitespace changes only.
2483
  AvahiSServiceBrowser *sb = NULL;
594.1.4 by Teddy Hogeborn
* plugins.d/mandos-client.c (get_flags): Don't clobber errno.
2484
  error_t ret_errno;
293 by Teddy Hogeborn
* plugin-runner.c: Whitespace changes only.
2485
  int ret;
2486
  intmax_t tmpmax;
311 by Teddy Hogeborn
Overflows are not detected by sscanf(), so stop using it:
2487
  char *tmp;
293 by Teddy Hogeborn
* plugin-runner.c: Whitespace changes only.
2488
  int exitcode = EXIT_SUCCESS;
594.1.4 by Teddy Hogeborn
* plugins.d/mandos-client.c (get_flags): Don't clobber errno.
2489
  char *interfaces_to_take_down = NULL;
2490
  size_t interfaces_to_take_down_size = 0;
673 by Teddy Hogeborn
Make mandos-client prefer /run/tmp over /tmp.
2491
  char run_tempdir[] = "/run/tmp/mandosXXXXXX";
2492
  char old_tempdir[] = "/tmp/mandosXXXXXX";
2493
  char *tempdir = NULL;
293 by Teddy Hogeborn
* plugin-runner.c: Whitespace changes only.
2494
  AvahiIfIndex if_index = AVAHI_IF_UNSPEC;
2495
  const char *seckey = PATHDIR "/" SECKEY;
2496
  const char *pubkey = PATHDIR "/" PUBKEY;
962 by Teddy Hogeborn
Add support for using raw public keys in TLS (RFC 7250)
2497
#if GNUTLS_VERSION_NUMBER >= 0x030606
2498
  const char *tls_privkey = PATHDIR "/" TLS_PRIVKEY;
2499
  const char *tls_pubkey = PATHDIR "/" TLS_PUBKEY;
2500
#endif
762 by Teddy Hogeborn
mandos-client: Add --dh-params FILE option.
2501
  const char *dh_params_file = NULL;
594.1.4 by Teddy Hogeborn
* plugins.d/mandos-client.c (get_flags): Don't clobber errno.
2502
  char *interfaces_hooks = NULL;
293 by Teddy Hogeborn
* plugin-runner.c: Whitespace changes only.
2503
  
2504
  bool gnutls_initialized = false;
2505
  bool gpgme_initialized = false;
311 by Teddy Hogeborn
Overflows are not detected by sscanf(), so stop using it:
2506
  float delay = 2.5f;
485 by Teddy Hogeborn
Merge from Björn.
2507
  double retry_interval = 10; /* 10s between trying a server and
2508
				 retrying the same server again */
311 by Teddy Hogeborn
Overflows are not detected by sscanf(), so stop using it:
2509
  
369 by Teddy Hogeborn
* init.d-mandos (Required-Start, Required-Stop): Bug fix: Added
2510
  struct sigaction old_sigterm_action = { .sa_handler = SIG_DFL };
24.1.134 by Björn Påhlsson
plugin-runner: Added support for empty string arguments
2511
  struct sigaction sigterm_action = { .sa_handler = handle_sigterm };
293 by Teddy Hogeborn
* plugin-runner.c: Whitespace changes only.
2512
  
368 by Teddy Hogeborn
* plugins.d/mandos-client.c (init_gnutls_session): Retry interrupted
2513
  uid = getuid();
2514
  gid = getgid();
2515
  
2516
  /* Lower any group privileges we might have, just to be safe */
2517
  errno = 0;
2518
  ret = setgid(gid);
2519
  if(ret == -1){
24.1.174 by Björn Påhlsson
* Makefile (CFLAGS): Added "-lrt" to include real time library.
2520
    perror_plus("setgid");
368 by Teddy Hogeborn
* plugins.d/mandos-client.c (init_gnutls_session): Retry interrupted
2521
  }
2522
  
2523
  /* Lower user privileges (temporarily) */
2524
  errno = 0;
2525
  ret = seteuid(uid);
2526
  if(ret == -1){
24.1.174 by Björn Påhlsson
* Makefile (CFLAGS): Added "-lrt" to include real time library.
2527
    perror_plus("seteuid");
368 by Teddy Hogeborn
* plugins.d/mandos-client.c (init_gnutls_session): Retry interrupted
2528
  }
2529
  
2530
  if(quit_now){
2531
    goto end;
2532
  }
2533
  
293 by Teddy Hogeborn
* plugin-runner.c: Whitespace changes only.
2534
  {
2535
    struct argp_option options[] = {
2536
      { .name = "debug", .key = 128,
2537
	.doc = "Debug mode", .group = 3 },
2538
      { .name = "connect", .key = 'c',
2539
	.arg = "ADDRESS:PORT",
2540
	.doc = "Connect directly to a specific Mandos server",
2541
	.group = 1 },
2542
      { .name = "interface", .key = 'i',
2543
	.arg = "NAME",
304 by Teddy Hogeborn
Four new interrelated features:
2544
	.doc = "Network interface that will be used to search for"
2545
	" Mandos servers",
293 by Teddy Hogeborn
* plugin-runner.c: Whitespace changes only.
2546
	.group = 1 },
2547
      { .name = "seckey", .key = 's',
2548
	.arg = "FILE",
2549
	.doc = "OpenPGP secret key file base name",
2550
	.group = 1 },
2551
      { .name = "pubkey", .key = 'p',
2552
	.arg = "FILE",
2553
	.doc = "OpenPGP public key file base name",
962 by Teddy Hogeborn
Add support for using raw public keys in TLS (RFC 7250)
2554
	.group = 1 },
2555
      { .name = "tls-privkey", .key = 't',
2556
	.arg = "FILE",
2557
#if GNUTLS_VERSION_NUMBER >= 0x030606
2558
	.doc = "TLS private key file base name",
2559
#else
2560
	.doc = "Dummy; ignored (requires GnuTLS 3.6.6)",
2561
#endif
2562
	.group = 1 },
2563
      { .name = "tls-pubkey", .key = 'T',
2564
	.arg = "FILE",
2565
#if GNUTLS_VERSION_NUMBER >= 0x030606
2566
	.doc = "TLS public key file base name",
2567
#else
2568
	.doc = "Dummy; ignored (requires GnuTLS 3.6.6)",
2569
#endif
2570
	.group = 1 },
293 by Teddy Hogeborn
* plugin-runner.c: Whitespace changes only.
2571
      { .name = "dh-bits", .key = 129,
2572
	.arg = "BITS",
2573
	.doc = "Bit length of the prime number used in the"
2574
	" Diffie-Hellman key exchange",
2575
	.group = 2 },
762 by Teddy Hogeborn
mandos-client: Add --dh-params FILE option.
2576
      { .name = "dh-params", .key = 134,
2577
	.arg = "FILE",
2578
	.doc = "PEM-encoded PKCS#3 file with pre-generated parameters"
2579
	" for the Diffie-Hellman key exchange",
2580
	.group = 2 },
293 by Teddy Hogeborn
* plugin-runner.c: Whitespace changes only.
2581
      { .name = "priority", .key = 130,
2582
	.arg = "STRING",
2583
	.doc = "GnuTLS priority string for the TLS handshake",
2584
	.group = 1 },
2585
      { .name = "delay", .key = 131,
2586
	.arg = "SECONDS",
2587
	.doc = "Maximum delay to wait for interface startup",
2588
	.group = 2 },
24.1.174 by Björn Påhlsson
* Makefile (CFLAGS): Added "-lrt" to include real time library.
2589
      { .name = "retry", .key = 132,
2590
	.arg = "SECONDS",
535.1.1 by teddy at recompile
Add wireless network hook
2591
	.doc = "Retry interval used when denied by the Mandos server",
24.1.174 by Björn Påhlsson
* Makefile (CFLAGS): Added "-lrt" to include real time library.
2592
	.group = 2 },
505.3.4 by teddy at bsnet
* plugins.d/mandos-client.c (runnable_hook): Bug fix: stat using the
2593
      { .name = "network-hook-dir", .key = 133,
2594
	.arg = "DIR",
2595
	.doc = "Directory where network hooks are located",
2596
	.group = 2 },
394 by Teddy Hogeborn
Convert some programs to use the exit codes from <sysexits.h>. Change
2597
      /*
2598
       * These reproduce what we would get without ARGP_NO_HELP
2599
       */
2600
      { .name = "help", .key = '?',
2601
	.doc = "Give this help list", .group = -1 },
2602
      { .name = "usage", .key = -3,
2603
	.doc = "Give a short usage message", .group = -1 },
2604
      { .name = "version", .key = 'V',
2605
	.doc = "Print program version", .group = -1 },
293 by Teddy Hogeborn
* plugin-runner.c: Whitespace changes only.
2606
      { .name = NULL }
2607
    };
2608
    
2609
    error_t parse_opt(int key, char *arg,
2610
		      struct argp_state *state){
394 by Teddy Hogeborn
Convert some programs to use the exit codes from <sysexits.h>. Change
2611
      errno = 0;
293 by Teddy Hogeborn
* plugin-runner.c: Whitespace changes only.
2612
      switch(key){
2613
      case 128:			/* --debug */
2614
	debug = true;
2615
	break;
2616
      case 'c':			/* --connect */
2617
	connect_to = arg;
2618
	break;
2619
      case 'i':			/* --interface */
603 by Teddy Hogeborn
* plugins.d/mandos-client (mandos_context): New "interfaces" and
2620
	ret_errno = argz_add_sep(&mc.interfaces, &mc.interfaces_size,
2621
				 arg, (int)',');
594.1.4 by Teddy Hogeborn
* plugins.d/mandos-client.c (get_flags): Don't clobber errno.
2622
	if(ret_errno != 0){
2623
	  argp_error(state, "%s", strerror(ret_errno));
2624
	}
293 by Teddy Hogeborn
* plugin-runner.c: Whitespace changes only.
2625
	break;
2626
      case 's':			/* --seckey */
2627
	seckey = arg;
2628
	break;
2629
      case 'p':			/* --pubkey */
2630
	pubkey = arg;
2631
	break;
962 by Teddy Hogeborn
Add support for using raw public keys in TLS (RFC 7250)
2632
      case 't':			/* --tls-privkey */
2633
#if GNUTLS_VERSION_NUMBER >= 0x030606
2634
	tls_privkey = arg;
2635
#endif
2636
	break;
2637
      case 'T':			/* --tls-pubkey */
2638
#if GNUTLS_VERSION_NUMBER >= 0x030606
2639
	tls_pubkey = arg;
2640
#endif
2641
	break;
293 by Teddy Hogeborn
* plugin-runner.c: Whitespace changes only.
2642
      case 129:			/* --dh-bits */
311 by Teddy Hogeborn
Overflows are not detected by sscanf(), so stop using it:
2643
	errno = 0;
2644
	tmpmax = strtoimax(arg, &tmp, 10);
2645
	if(errno != 0 or tmp == arg or *tmp != '\0'
2646
	   or tmpmax != (typeof(mc.dh_bits))tmpmax){
394 by Teddy Hogeborn
Convert some programs to use the exit codes from <sysexits.h>. Change
2647
	  argp_error(state, "Bad number of DH bits");
293 by Teddy Hogeborn
* plugin-runner.c: Whitespace changes only.
2648
	}
2649
	mc.dh_bits = (typeof(mc.dh_bits))tmpmax;
2650
	break;
762 by Teddy Hogeborn
mandos-client: Add --dh-params FILE option.
2651
      case 134:			/* --dh-params */
2652
	dh_params_file = arg;
2653
	break;
293 by Teddy Hogeborn
* plugin-runner.c: Whitespace changes only.
2654
      case 130:			/* --priority */
2655
	mc.priority = arg;
2656
	break;
2657
      case 131:			/* --delay */
311 by Teddy Hogeborn
Overflows are not detected by sscanf(), so stop using it:
2658
	errno = 0;
2659
	delay = strtof(arg, &tmp);
2660
	if(errno != 0 or tmp == arg or *tmp != '\0'){
394 by Teddy Hogeborn
Convert some programs to use the exit codes from <sysexits.h>. Change
2661
	  argp_error(state, "Bad delay");
293 by Teddy Hogeborn
* plugin-runner.c: Whitespace changes only.
2662
	}
24.1.174 by Björn Påhlsson
* Makefile (CFLAGS): Added "-lrt" to include real time library.
2663
      case 132:			/* --retry */
2664
	errno = 0;
2665
	retry_interval = strtod(arg, &tmp);
2666
	if(errno != 0 or tmp == arg or *tmp != '\0'
491 by teddy at bsnet
* plugins.d/mandos-client.c (avahi_loop_with_timeout): Fix warning.
2667
	   or (retry_interval * 1000) > INT_MAX
2668
	   or retry_interval < 0){
24.1.174 by Björn Påhlsson
* Makefile (CFLAGS): Added "-lrt" to include real time library.
2669
	  argp_error(state, "Bad retry interval");
2670
	}
293 by Teddy Hogeborn
* plugin-runner.c: Whitespace changes only.
2671
	break;
505.3.4 by teddy at bsnet
* plugins.d/mandos-client.c (runnable_hook): Bug fix: stat using the
2672
      case 133:			/* --network-hook-dir */
2673
	hookdir = arg;
2674
	break;
394 by Teddy Hogeborn
Convert some programs to use the exit codes from <sysexits.h>. Change
2675
	/*
2676
	 * These reproduce what we would get without ARGP_NO_HELP
2677
	 */
2678
      case '?':			/* --help */
2679
	argp_state_help(state, state->out_stream,
2680
			(ARGP_HELP_STD_HELP | ARGP_HELP_EXIT_ERR)
2681
			& ~(unsigned int)ARGP_HELP_EXIT_OK);
975 by Teddy Hogeborn
Fix warnings from -Wimplicit-fallthrough
2682
	__builtin_unreachable();
394 by Teddy Hogeborn
Convert some programs to use the exit codes from <sysexits.h>. Change
2683
      case -3:			/* --usage */
2684
	argp_state_help(state, state->out_stream,
2685
			ARGP_HELP_USAGE | ARGP_HELP_EXIT_ERR);
975 by Teddy Hogeborn
Fix warnings from -Wimplicit-fallthrough
2686
	__builtin_unreachable();
394 by Teddy Hogeborn
Convert some programs to use the exit codes from <sysexits.h>. Change
2687
      case 'V':			/* --version */
505.2.6 by Björn Påhlsson
replace calls to fprintf with fprintf_plus.
2688
	fprintf_plus(state->out_stream, "%s\n", argp_program_version);
394 by Teddy Hogeborn
Convert some programs to use the exit codes from <sysexits.h>. Change
2689
	exit(argp_err_exit_status);
293 by Teddy Hogeborn
* plugin-runner.c: Whitespace changes only.
2690
	break;
2691
      default:
2692
	return ARGP_ERR_UNKNOWN;
2693
      }
394 by Teddy Hogeborn
Convert some programs to use the exit codes from <sysexits.h>. Change
2694
      return errno;
293 by Teddy Hogeborn
* plugin-runner.c: Whitespace changes only.
2695
    }
2696
    
2697
    struct argp argp = { .options = options, .parser = parse_opt,
2698
			 .args_doc = "",
2699
			 .doc = "Mandos client -- Get and decrypt"
2700
			 " passwords from a Mandos server" };
819 by Teddy Hogeborn
errno is of type int, not error_t
2701
    ret_errno = argp_parse(&argp, argc, argv,
2702
			   ARGP_IN_ORDER | ARGP_NO_HELP, 0, NULL);
2703
    switch(ret_errno){
394 by Teddy Hogeborn
Convert some programs to use the exit codes from <sysexits.h>. Change
2704
    case 0:
2705
      break;
2706
    case ENOMEM:
2707
    default:
819 by Teddy Hogeborn
errno is of type int, not error_t
2708
      errno = ret_errno;
24.1.174 by Björn Påhlsson
* Makefile (CFLAGS): Added "-lrt" to include real time library.
2709
      perror_plus("argp_parse");
394 by Teddy Hogeborn
Convert some programs to use the exit codes from <sysexits.h>. Change
2710
      exitcode = EX_OSERR;
2711
      goto end;
2712
    case EINVAL:
2713
      exitcode = EX_USAGE;
293 by Teddy Hogeborn
* plugin-runner.c: Whitespace changes only.
2714
      goto end;
2715
    }
2716
  }
738.1.2 by Teddy Hogeborn
mandos-client: Try to start a plugin to add and remove a local route.
2717
  
505.3.16 by teddy at bsnet
* network-hooks.d/bridge: Use "/usr/sbin/brctl" explicitly.
2718
  {
487 by Teddy Hogeborn
* initramfs-tools-script: Abort if plugin-runner is missing. Removed
2719
    /* Work around Debian bug #633582:
868 by Teddy Hogeborn
Change all http:// URLs to https:// wherever possible.
2720
       <https://bugs.debian.org/633582> */
487 by Teddy Hogeborn
* initramfs-tools-script: Abort if plugin-runner is missing. Removed
2721
    
672 by Teddy Hogeborn
Update GCC warning flags and function attributes to GCC 4.7.
2722
    /* Re-raise privileges */
819 by Teddy Hogeborn
errno is of type int, not error_t
2723
    ret = raise_privileges();
2724
    if(ret != 0){
2725
      errno = ret;
672 by Teddy Hogeborn
Update GCC warning flags and function attributes to GCC 4.7.
2726
      perror_plus("Failed to raise privileges");
2727
    } else {
505.3.16 by teddy at bsnet
* network-hooks.d/bridge: Use "/usr/sbin/brctl" explicitly.
2728
      struct stat st;
2729
      
2730
      if(strcmp(seckey, PATHDIR "/" SECKEY) == 0){
2731
	int seckey_fd = open(seckey, O_RDONLY);
2732
	if(seckey_fd == -1){
2733
	  perror_plus("open");
2734
	} else {
2735
	  ret = (int)TEMP_FAILURE_RETRY(fstat(seckey_fd, &st));
2736
	  if(ret == -1){
2737
	    perror_plus("fstat");
2738
	  } else {
2739
	    if(S_ISREG(st.st_mode)
2740
	       and st.st_uid == 0 and st.st_gid == 0){
2741
	      ret = fchown(seckey_fd, uid, gid);
2742
	      if(ret == -1){
2743
		perror_plus("fchown");
2744
	      }
2745
	    }
2746
	  }
774 by Teddy Hogeborn
Don't use TEMP_FAILURE_RETRY around close().
2747
	  close(seckey_fd);
505.3.16 by teddy at bsnet
* network-hooks.d/bridge: Use "/usr/sbin/brctl" explicitly.
2748
	}
2749
      }
738.1.2 by Teddy Hogeborn
mandos-client: Try to start a plugin to add and remove a local route.
2750
      
505.3.16 by teddy at bsnet
* network-hooks.d/bridge: Use "/usr/sbin/brctl" explicitly.
2751
      if(strcmp(pubkey, PATHDIR "/" PUBKEY) == 0){
2752
	int pubkey_fd = open(pubkey, O_RDONLY);
2753
	if(pubkey_fd == -1){
2754
	  perror_plus("open");
2755
	} else {
2756
	  ret = (int)TEMP_FAILURE_RETRY(fstat(pubkey_fd, &st));
2757
	  if(ret == -1){
2758
	    perror_plus("fstat");
2759
	  } else {
2760
	    if(S_ISREG(st.st_mode)
2761
	       and st.st_uid == 0 and st.st_gid == 0){
2762
	      ret = fchown(pubkey_fd, uid, gid);
2763
	      if(ret == -1){
2764
		perror_plus("fchown");
2765
	      }
2766
	    }
2767
	  }
774 by Teddy Hogeborn
Don't use TEMP_FAILURE_RETRY around close().
2768
	  close(pubkey_fd);
505.3.16 by teddy at bsnet
* network-hooks.d/bridge: Use "/usr/sbin/brctl" explicitly.
2769
	}
2770
      }
738.1.2 by Teddy Hogeborn
mandos-client: Try to start a plugin to add and remove a local route.
2771
      
776 by Teddy Hogeborn
mandos-client: Bug fix: don't crash if --dh-params was not used.
2772
      if(dh_params_file != NULL
2773
	 and strcmp(dh_params_file, PATHDIR "/dhparams.pem" ) == 0){
765 by Teddy Hogeborn
Install client Diffie-Hellman parameters into initramfs.
2774
	int dhparams_fd = open(dh_params_file, O_RDONLY);
2775
	if(dhparams_fd == -1){
2776
	  perror_plus("open");
2777
	} else {
2778
	  ret = (int)TEMP_FAILURE_RETRY(fstat(dhparams_fd, &st));
2779
	  if(ret == -1){
2780
	    perror_plus("fstat");
2781
	  } else {
2782
	    if(S_ISREG(st.st_mode)
2783
	       and st.st_uid == 0 and st.st_gid == 0){
2784
	      ret = fchown(dhparams_fd, uid, gid);
2785
	      if(ret == -1){
2786
		perror_plus("fchown");
2787
	      }
2788
	    }
2789
	  }
774 by Teddy Hogeborn
Don't use TEMP_FAILURE_RETRY around close().
2790
	  close(dhparams_fd);
765 by Teddy Hogeborn
Install client Diffie-Hellman parameters into initramfs.
2791
	}
2792
      }
2793
      
505.3.11 by Teddy Hogeborn
* Makefile (run-client): Add "--network-hook-dir" option.
2794
      /* Lower privileges */
819 by Teddy Hogeborn
errno is of type int, not error_t
2795
      ret = lower_privileges();
2796
      if(ret != 0){
2797
	errno = ret;
672 by Teddy Hogeborn
Update GCC warning flags and function attributes to GCC 4.7.
2798
	perror_plus("Failed to lower privileges");
2799
      }
505.2.3 by Teddy Hogeborn
Intermediate commit - this does *not* work yet.
2800
    }
2801
  }
2802
  
604 by Teddy Hogeborn
* plugins.d/mandos-client (start_mandos_communication): Bug fix; skip
2803
  /* Remove invalid interface names (except "none") */
594.1.4 by Teddy Hogeborn
* plugins.d/mandos-client.c (get_flags): Don't clobber errno.
2804
  {
2805
    char *interface = NULL;
603 by Teddy Hogeborn
* plugins.d/mandos-client (mandos_context): New "interfaces" and
2806
    while((interface = argz_next(mc.interfaces, mc.interfaces_size,
594.1.4 by Teddy Hogeborn
* plugins.d/mandos-client.c (get_flags): Don't clobber errno.
2807
				 interface))){
604 by Teddy Hogeborn
* plugins.d/mandos-client (start_mandos_communication): Bug fix; skip
2808
      if(strcmp(interface, "none") != 0
2809
	 and if_nametoindex(interface) == 0){
2810
	if(interface[0] != '\0'){
594.1.4 by Teddy Hogeborn
* plugins.d/mandos-client.c (get_flags): Don't clobber errno.
2811
	  fprintf_plus(stderr, "Not using nonexisting interface"
2812
		       " \"%s\"\n", interface);
2813
	}
603 by Teddy Hogeborn
* plugins.d/mandos-client (mandos_context): New "interfaces" and
2814
	argz_delete(&mc.interfaces, &mc.interfaces_size, interface);
594.1.4 by Teddy Hogeborn
* plugins.d/mandos-client.c (get_flags): Don't clobber errno.
2815
	interface = NULL;
2816
      }
2817
    }
2818
  }
2819
  
505.3.16 by teddy at bsnet
* network-hooks.d/bridge: Use "/usr/sbin/brctl" explicitly.
2820
  /* Run network hooks */
594.1.4 by Teddy Hogeborn
* plugins.d/mandos-client.c (get_flags): Don't clobber errno.
2821
  {
603 by Teddy Hogeborn
* plugins.d/mandos-client (mandos_context): New "interfaces" and
2822
    if(mc.interfaces != NULL){
2823
      interfaces_hooks = malloc(mc.interfaces_size);
599 by Teddy Hogeborn
* plugins.d/mandos-client.c (main): Bug fix: Set DEVICE environment
2824
      if(interfaces_hooks == NULL){
2825
	perror_plus("malloc");
2826
	goto end;
2827
      }
603 by Teddy Hogeborn
* plugins.d/mandos-client (mandos_context): New "interfaces" and
2828
      memcpy(interfaces_hooks, mc.interfaces, mc.interfaces_size);
666 by Teddy Hogeborn
Bug fix: Free all memory and give better messages when memory is full.
2829
      argz_stringify(interfaces_hooks, mc.interfaces_size, (int)',');
594.1.4 by Teddy Hogeborn
* plugins.d/mandos-client.c (get_flags): Don't clobber errno.
2830
    }
672 by Teddy Hogeborn
Update GCC warning flags and function attributes to GCC 4.7.
2831
    run_network_hooks("start", interfaces_hooks != NULL ?
2832
		      interfaces_hooks : "", delay);
505.3.16 by teddy at bsnet
* network-hooks.d/bridge: Use "/usr/sbin/brctl" explicitly.
2833
  }
2834
  
24.1.135 by Björn Påhlsson
Earlier signal handling
2835
  if(not debug){
2836
    avahi_set_log_function(empty_log);
2837
  }
505.2.3 by Teddy Hogeborn
Intermediate commit - this does *not* work yet.
2838
  
24.1.135 by Björn Påhlsson
Earlier signal handling
2839
  /* Initialize Avahi early so avahi_simple_poll_quit() can be called
2840
     from the signal handler */
2841
  /* Initialize the pseudo-RNG for Avahi */
2842
  srand((unsigned int) time(NULL));
601 by Teddy Hogeborn
* plugins.d/mandos-client (mandos_context): Removed "simple_poll"
2843
  simple_poll = avahi_simple_poll_new();
2844
  if(simple_poll == NULL){
505.3.9 by Teddy Hogeborn
* plugins.d/mandos-client.c: Merge unified printing system.
2845
    fprintf_plus(stderr,
2846
		 "Avahi: Failed to create simple poll object.\n");
399 by Teddy Hogeborn
* Makefile (BROKEN_PIE): Add comment.
2847
    exitcode = EX_UNAVAILABLE;
24.1.135 by Björn Påhlsson
Earlier signal handling
2848
    goto end;
2849
  }
309 by Teddy Hogeborn
Merge from Björn:
2850
  
24.1.135 by Björn Påhlsson
Earlier signal handling
2851
  sigemptyset(&sigterm_action.sa_mask);
309 by Teddy Hogeborn
Merge from Björn:
2852
  ret = sigaddset(&sigterm_action.sa_mask, SIGINT);
2853
  if(ret == -1){
24.1.174 by Björn Påhlsson
* Makefile (CFLAGS): Added "-lrt" to include real time library.
2854
    perror_plus("sigaddset");
399 by Teddy Hogeborn
* Makefile (BROKEN_PIE): Add comment.
2855
    exitcode = EX_OSERR;
309 by Teddy Hogeborn
Merge from Björn:
2856
    goto end;
2857
  }
2858
  ret = sigaddset(&sigterm_action.sa_mask, SIGHUP);
2859
  if(ret == -1){
24.1.174 by Björn Påhlsson
* Makefile (CFLAGS): Added "-lrt" to include real time library.
2860
    perror_plus("sigaddset");
399 by Teddy Hogeborn
* Makefile (BROKEN_PIE): Add comment.
2861
    exitcode = EX_OSERR;
309 by Teddy Hogeborn
Merge from Björn:
2862
    goto end;
2863
  }
24.1.135 by Björn Påhlsson
Earlier signal handling
2864
  ret = sigaddset(&sigterm_action.sa_mask, SIGTERM);
2865
  if(ret == -1){
24.1.174 by Björn Påhlsson
* Makefile (CFLAGS): Added "-lrt" to include real time library.
2866
    perror_plus("sigaddset");
399 by Teddy Hogeborn
* Makefile (BROKEN_PIE): Add comment.
2867
    exitcode = EX_OSERR;
24.1.135 by Björn Påhlsson
Earlier signal handling
2868
    goto end;
2869
  }
357 by Teddy Hogeborn
* plugins.d/mandos-client.c (main): Do not handle ignored signals.
2870
  /* Need to check if the handler is SIG_IGN before handling:
2871
     | [[info:libc:Initial Signal Actions]] |
2872
     | [[info:libc:Basic Signal Handling]]  |
2873
  */
2874
  ret = sigaction(SIGINT, NULL, &old_sigterm_action);
2875
  if(ret == -1){
24.1.174 by Björn Påhlsson
* Makefile (CFLAGS): Added "-lrt" to include real time library.
2876
    perror_plus("sigaction");
399 by Teddy Hogeborn
* Makefile (BROKEN_PIE): Add comment.
2877
    return EX_OSERR;
357 by Teddy Hogeborn
* plugins.d/mandos-client.c (main): Do not handle ignored signals.
2878
  }
2879
  if(old_sigterm_action.sa_handler != SIG_IGN){
2880
    ret = sigaction(SIGINT, &sigterm_action, NULL);
2881
    if(ret == -1){
24.1.174 by Björn Påhlsson
* Makefile (CFLAGS): Added "-lrt" to include real time library.
2882
      perror_plus("sigaction");
399 by Teddy Hogeborn
* Makefile (BROKEN_PIE): Add comment.
2883
      exitcode = EX_OSERR;
357 by Teddy Hogeborn
* plugins.d/mandos-client.c (main): Do not handle ignored signals.
2884
      goto end;
2885
    }
2886
  }
2887
  ret = sigaction(SIGHUP, NULL, &old_sigterm_action);
2888
  if(ret == -1){
24.1.174 by Björn Påhlsson
* Makefile (CFLAGS): Added "-lrt" to include real time library.
2889
    perror_plus("sigaction");
399 by Teddy Hogeborn
* Makefile (BROKEN_PIE): Add comment.
2890
    return EX_OSERR;
357 by Teddy Hogeborn
* plugins.d/mandos-client.c (main): Do not handle ignored signals.
2891
  }
2892
  if(old_sigterm_action.sa_handler != SIG_IGN){
2893
    ret = sigaction(SIGHUP, &sigterm_action, NULL);
2894
    if(ret == -1){
24.1.174 by Björn Påhlsson
* Makefile (CFLAGS): Added "-lrt" to include real time library.
2895
      perror_plus("sigaction");
399 by Teddy Hogeborn
* Makefile (BROKEN_PIE): Add comment.
2896
      exitcode = EX_OSERR;
357 by Teddy Hogeborn
* plugins.d/mandos-client.c (main): Do not handle ignored signals.
2897
      goto end;
2898
    }
2899
  }
2900
  ret = sigaction(SIGTERM, NULL, &old_sigterm_action);
2901
  if(ret == -1){
24.1.174 by Björn Påhlsson
* Makefile (CFLAGS): Added "-lrt" to include real time library.
2902
    perror_plus("sigaction");
399 by Teddy Hogeborn
* Makefile (BROKEN_PIE): Add comment.
2903
    return EX_OSERR;
357 by Teddy Hogeborn
* plugins.d/mandos-client.c (main): Do not handle ignored signals.
2904
  }
2905
  if(old_sigterm_action.sa_handler != SIG_IGN){
2906
    ret = sigaction(SIGTERM, &sigterm_action, NULL);
2907
    if(ret == -1){
24.1.174 by Björn Påhlsson
* Makefile (CFLAGS): Added "-lrt" to include real time library.
2908
      perror_plus("sigaction");
399 by Teddy Hogeborn
* Makefile (BROKEN_PIE): Add comment.
2909
      exitcode = EX_OSERR;
357 by Teddy Hogeborn
* plugins.d/mandos-client.c (main): Do not handle ignored signals.
2910
      goto end;
2911
    }
354 by Teddy Hogeborn
* plugins.d/mandos-client.c (signal_received): New.
2912
  }
293 by Teddy Hogeborn
* plugin-runner.c: Whitespace changes only.
2913
  
594.1.4 by Teddy Hogeborn
* plugins.d/mandos-client.c (get_flags): Don't clobber errno.
2914
  /* If no interfaces were specified, make a list */
603 by Teddy Hogeborn
* plugins.d/mandos-client (mandos_context): New "interfaces" and
2915
  if(mc.interfaces == NULL){
699 by Teddy Hogeborn
Fix free() of possibly uninitialized pointer in mandos-client.
2916
    struct dirent **direntries = NULL;
594.1.4 by Teddy Hogeborn
* plugins.d/mandos-client.c (get_flags): Don't clobber errno.
2917
    /* Look for any good interfaces */
2918
    ret = scandir(sys_class_net, &direntries, good_interface,
2919
		  alphasort);
2920
    if(ret >= 1){
2921
      /* Add all found interfaces to interfaces list */
2922
      for(int i = 0; i < ret; ++i){
603 by Teddy Hogeborn
* plugins.d/mandos-client (mandos_context): New "interfaces" and
2923
	ret_errno = argz_add(&mc.interfaces, &mc.interfaces_size,
594.1.4 by Teddy Hogeborn
* plugins.d/mandos-client.c (get_flags): Don't clobber errno.
2924
			     direntries[i]->d_name);
2925
	if(ret_errno != 0){
666 by Teddy Hogeborn
Bug fix: Free all memory and give better messages when memory is full.
2926
	  errno = ret_errno;
594.1.4 by Teddy Hogeborn
* plugins.d/mandos-client.c (get_flags): Don't clobber errno.
2927
	  perror_plus("argz_add");
715 by Teddy Hogeborn
mandos-client: Bug Fix: Fix some memory leaks.
2928
	  free(direntries[i]);
594.1.4 by Teddy Hogeborn
* plugins.d/mandos-client.c (get_flags): Don't clobber errno.
2929
	  continue;
2930
	}
2931
	if(debug){
2932
	  fprintf_plus(stderr, "Will use interface \"%s\"\n",
2933
		       direntries[i]->d_name);
2934
	}
715 by Teddy Hogeborn
mandos-client: Bug Fix: Fix some memory leaks.
2935
	free(direntries[i]);
594.1.4 by Teddy Hogeborn
* plugins.d/mandos-client.c (get_flags): Don't clobber errno.
2936
      }
2937
      free(direntries);
2938
    } else {
704 by Teddy Hogeborn
mandos-client: Fix some bugs on error conditions.
2939
      if(ret == 0){
2940
	free(direntries);
2941
      }
594.1.4 by Teddy Hogeborn
* plugins.d/mandos-client.c (get_flags): Don't clobber errno.
2942
      fprintf_plus(stderr, "Could not find a network interface\n");
2943
      exitcode = EXIT_FAILURE;
2944
      goto end;
2945
    }
2946
  }
2947
  
605 by Teddy Hogeborn
* plugins.d/mandos-client.c: Comment changes
2948
  /* Bring up interfaces which are down, and remove any "none"s */
604 by Teddy Hogeborn
* plugins.d/mandos-client (start_mandos_communication): Bug fix; skip
2949
  {
594.1.4 by Teddy Hogeborn
* plugins.d/mandos-client.c (get_flags): Don't clobber errno.
2950
    char *interface = NULL;
603 by Teddy Hogeborn
* plugins.d/mandos-client (mandos_context): New "interfaces" and
2951
    while((interface = argz_next(mc.interfaces, mc.interfaces_size,
594.1.4 by Teddy Hogeborn
* plugins.d/mandos-client.c (get_flags): Don't clobber errno.
2952
				 interface))){
604 by Teddy Hogeborn
* plugins.d/mandos-client (start_mandos_communication): Bug fix; skip
2953
      /* If interface name is "none", stop bringing up interfaces.
2954
	 Also remove all instances of "none" from the list */
2955
      if(strcmp(interface, "none") == 0){
2956
	argz_delete(&mc.interfaces, &mc.interfaces_size,
2957
		    interface);
2958
	interface = NULL;
2959
	while((interface = argz_next(mc.interfaces,
2960
				     mc.interfaces_size, interface))){
2961
	  if(strcmp(interface, "none") == 0){
2962
	    argz_delete(&mc.interfaces, &mc.interfaces_size,
2963
			interface);
2964
	    interface = NULL;
2965
	  }
2966
	}
2967
	break;
2968
      }
594.1.4 by Teddy Hogeborn
* plugins.d/mandos-client.c (get_flags): Don't clobber errno.
2969
      bool interface_was_up = interface_is_up(interface);
672 by Teddy Hogeborn
Update GCC warning flags and function attributes to GCC 4.7.
2970
      errno = bring_up_interface(interface, delay);
594.1.4 by Teddy Hogeborn
* plugins.d/mandos-client.c (get_flags): Don't clobber errno.
2971
      if(not interface_was_up){
672 by Teddy Hogeborn
Update GCC warning flags and function attributes to GCC 4.7.
2972
	if(errno != 0){
767 by Teddy Hogeborn
plugins.d/mandos-client.c (main): See why it failed to bring up interface.
2973
	  fprintf_plus(stderr, "Failed to bring up interface \"%s\":"
2974
		       " %s\n", interface, strerror(errno));
594.1.4 by Teddy Hogeborn
* plugins.d/mandos-client.c (get_flags): Don't clobber errno.
2975
	} else {
672 by Teddy Hogeborn
Update GCC warning flags and function attributes to GCC 4.7.
2976
	  errno = argz_add(&interfaces_to_take_down,
2977
			   &interfaces_to_take_down_size,
2978
			   interface);
2979
	  if(errno != 0){
666 by Teddy Hogeborn
Bug fix: Free all memory and give better messages when memory is full.
2980
	    perror_plus("argz_add");
2981
	  }
594.1.4 by Teddy Hogeborn
* plugins.d/mandos-client.c (get_flags): Don't clobber errno.
2982
	}
2983
      }
2984
    }
2985
    if(debug and (interfaces_to_take_down == NULL)){
2986
      fprintf_plus(stderr, "No interfaces were brought up\n");
365 by Teddy Hogeborn
* plugins.d/mandos-client.c (main): Bug fix: Check result of setgid().
2987
    }
293 by Teddy Hogeborn
* plugin-runner.c: Whitespace changes only.
2988
  }
2989
  
604 by Teddy Hogeborn
* plugins.d/mandos-client (start_mandos_communication): Bug fix; skip
2990
  /* If we only got one interface, explicitly use only that one */
2991
  if(argz_count(mc.interfaces, mc.interfaces_size) == 1){
2992
    if(debug){
2993
      fprintf_plus(stderr, "Using only interface \"%s\"\n",
2994
		   mc.interfaces);
2995
    }
2996
    if_index = (AvahiIfIndex)if_nametoindex(mc.interfaces);
2997
  }
2998
  
353 by Teddy Hogeborn
* plugins.d/mandos-client.c (quit_now): Move up declaration before
2999
  if(quit_now){
3000
    goto end;
3001
  }
3002
  
962 by Teddy Hogeborn
Add support for using raw public keys in TLS (RFC 7250)
3003
#if GNUTLS_VERSION_NUMBER >= 0x030606
3004
  ret = init_gnutls_global(tls_pubkey, tls_privkey, dh_params_file, &mc);
3005
#elif GNUTLS_VERSION_NUMBER < 0x030600
762 by Teddy Hogeborn
mandos-client: Add --dh-params FILE option.
3006
  ret = init_gnutls_global(pubkey, seckey, dh_params_file, &mc);
962 by Teddy Hogeborn
Add support for using raw public keys in TLS (RFC 7250)
3007
#else
3008
#error "Needs GnuTLS 3.6.6 or later, or before 3.6.0"
3009
#endif
293 by Teddy Hogeborn
* plugin-runner.c: Whitespace changes only.
3010
  if(ret == -1){
505.2.6 by Björn Påhlsson
replace calls to fprintf with fprintf_plus.
3011
    fprintf_plus(stderr, "init_gnutls_global failed\n");
399 by Teddy Hogeborn
* Makefile (BROKEN_PIE): Add comment.
3012
    exitcode = EX_UNAVAILABLE;
293 by Teddy Hogeborn
* plugin-runner.c: Whitespace changes only.
3013
    goto end;
3014
  } else {
3015
    gnutls_initialized = true;
3016
  }
3017
  
353 by Teddy Hogeborn
* plugins.d/mandos-client.c (quit_now): Move up declaration before
3018
  if(quit_now){
3019
    goto end;
3020
  }
3021
  
673 by Teddy Hogeborn
Make mandos-client prefer /run/tmp over /tmp.
3022
  /* Try /run/tmp before /tmp */
3023
  tempdir = mkdtemp(run_tempdir);
3024
  if(tempdir == NULL and errno == ENOENT){
3025
      if(debug){
3026
	fprintf_plus(stderr, "Tempdir %s did not work, trying %s\n",
3027
		     run_tempdir, old_tempdir);
3028
      }
3029
      tempdir = mkdtemp(old_tempdir);
3030
  }
3031
  if(tempdir == NULL){
24.1.174 by Björn Påhlsson
* Makefile (CFLAGS): Added "-lrt" to include real time library.
3032
    perror_plus("mkdtemp");
293 by Teddy Hogeborn
* plugin-runner.c: Whitespace changes only.
3033
    goto end;
3034
  }
353 by Teddy Hogeborn
* plugins.d/mandos-client.c (quit_now): Move up declaration before
3035
  
3036
  if(quit_now){
3037
    goto end;
3038
  }
293 by Teddy Hogeborn
* plugin-runner.c: Whitespace changes only.
3039
  
602 by Teddy Hogeborn
* plugins.d/mandos-client (mandos_context): Moved to inside "main()".
3040
  if(not init_gpgme(pubkey, seckey, tempdir, &mc)){
505.2.6 by Björn Påhlsson
replace calls to fprintf with fprintf_plus.
3041
    fprintf_plus(stderr, "init_gpgme failed\n");
399 by Teddy Hogeborn
* Makefile (BROKEN_PIE): Add comment.
3042
    exitcode = EX_UNAVAILABLE;
293 by Teddy Hogeborn
* plugin-runner.c: Whitespace changes only.
3043
    goto end;
3044
  } else {
3045
    gpgme_initialized = true;
3046
  }
3047
  
353 by Teddy Hogeborn
* plugins.d/mandos-client.c (quit_now): Move up declaration before
3048
  if(quit_now){
3049
    goto end;
293 by Teddy Hogeborn
* plugin-runner.c: Whitespace changes only.
3050
  }
3051
  
3052
  if(connect_to != NULL){
3053
    /* Connect directly, do not use Zeroconf */
3054
    /* (Mainly meant for debugging) */
3055
    char *address = strrchr(connect_to, ':');
594.1.1 by Teddy Hogeborn
* plugins.d/mandos-client.c: Refactoring.
3056
    
293 by Teddy Hogeborn
* plugin-runner.c: Whitespace changes only.
3057
    if(address == NULL){
505.2.6 by Björn Påhlsson
replace calls to fprintf with fprintf_plus.
3058
      fprintf_plus(stderr, "No colon in address\n");
399 by Teddy Hogeborn
* Makefile (BROKEN_PIE): Add comment.
3059
      exitcode = EX_USAGE;
293 by Teddy Hogeborn
* plugin-runner.c: Whitespace changes only.
3060
      goto end;
3061
    }
353 by Teddy Hogeborn
* plugins.d/mandos-client.c (quit_now): Move up declaration before
3062
    
3063
    if(quit_now){
3064
      goto end;
3065
    }
3066
    
597 by Teddy Hogeborn
* plugins.d/mandos-client.c: Don't use assert(). Use in_port_t for
3067
    in_port_t port;
311 by Teddy Hogeborn
Overflows are not detected by sscanf(), so stop using it:
3068
    errno = 0;
3069
    tmpmax = strtoimax(address+1, &tmp, 10);
3070
    if(errno != 0 or tmp == address+1 or *tmp != '\0'
597 by Teddy Hogeborn
* plugins.d/mandos-client.c: Don't use assert(). Use in_port_t for
3071
       or tmpmax != (in_port_t)tmpmax){
505.2.6 by Björn Påhlsson
replace calls to fprintf with fprintf_plus.
3072
      fprintf_plus(stderr, "Bad port number\n");
399 by Teddy Hogeborn
* Makefile (BROKEN_PIE): Add comment.
3073
      exitcode = EX_USAGE;
293 by Teddy Hogeborn
* plugin-runner.c: Whitespace changes only.
3074
      goto end;
3075
    }
604 by Teddy Hogeborn
* plugins.d/mandos-client (start_mandos_communication): Bug fix; skip
3076
    
353 by Teddy Hogeborn
* plugins.d/mandos-client.c (quit_now): Move up declaration before
3077
    if(quit_now){
3078
      goto end;
3079
    }
3080
    
597 by Teddy Hogeborn
* plugins.d/mandos-client.c: Don't use assert(). Use in_port_t for
3081
    port = (in_port_t)tmpmax;
293 by Teddy Hogeborn
* plugin-runner.c: Whitespace changes only.
3082
    *address = '\0';
304 by Teddy Hogeborn
Four new interrelated features:
3083
    /* Colon in address indicates IPv6 */
3084
    int af;
491 by teddy at bsnet
* plugins.d/mandos-client.c (avahi_loop_with_timeout): Fix warning.
3085
    if(strchr(connect_to, ':') != NULL){
304 by Teddy Hogeborn
Four new interrelated features:
3086
      af = AF_INET6;
491 by teddy at bsnet
* plugins.d/mandos-client.c (avahi_loop_with_timeout): Fix warning.
3087
      /* Accept [] around IPv6 address - see RFC 5952 */
3088
      if(connect_to[0] == '[' and address[-1] == ']')
3089
	{
3090
	  connect_to++;
3091
	  address[-1] = '\0';
3092
	}
304 by Teddy Hogeborn
Four new interrelated features:
3093
    } else {
3094
      af = AF_INET;
3095
    }
491 by teddy at bsnet
* plugins.d/mandos-client.c (avahi_loop_with_timeout): Fix warning.
3096
    address = connect_to;
353 by Teddy Hogeborn
* plugins.d/mandos-client.c (quit_now): Move up declaration before
3097
    
3098
    if(quit_now){
3099
      goto end;
3100
    }
491 by teddy at bsnet
* plugins.d/mandos-client.c (avahi_loop_with_timeout): Fix warning.
3101
    
24.1.163 by Björn Påhlsson
mandos-client: Added never ending loop for --connect
3102
    while(not quit_now){
602 by Teddy Hogeborn
* plugins.d/mandos-client (mandos_context): Moved to inside "main()".
3103
      ret = start_mandos_communication(address, port, if_index, af,
3104
				       &mc);
24.1.163 by Björn Påhlsson
mandos-client: Added never ending loop for --connect
3105
      if(quit_now or ret == 0){
399 by Teddy Hogeborn
* Makefile (BROKEN_PIE): Add comment.
3106
	break;
3107
      }
491 by teddy at bsnet
* plugins.d/mandos-client.c (avahi_loop_with_timeout): Fix warning.
3108
      if(debug){
505.3.9 by Teddy Hogeborn
* plugins.d/mandos-client.c: Merge unified printing system.
3109
	fprintf_plus(stderr, "Retrying in %d seconds\n",
3110
		     (int)retry_interval);
491 by teddy at bsnet
* plugins.d/mandos-client.c (avahi_loop_with_timeout): Fix warning.
3111
      }
620 by Teddy Hogeborn
* plugin-runner.c (main): Bug fix; do not ignore return value of
3112
      sleep((unsigned int)retry_interval);
492 by Teddy Hogeborn
* plugins.d/mandos-client.c (main): Do not even try to work around
3113
    }
3114
    
671 by Teddy Hogeborn
White space fix: change "if (" to "if(" in C code.
3115
    if(not quit_now){
293 by Teddy Hogeborn
* plugin-runner.c: Whitespace changes only.
3116
      exitcode = EXIT_SUCCESS;
3117
    }
505.2.3 by Teddy Hogeborn
Intermediate commit - this does *not* work yet.
3118
    
293 by Teddy Hogeborn
* plugin-runner.c: Whitespace changes only.
3119
    goto end;
3120
  }
353 by Teddy Hogeborn
* plugins.d/mandos-client.c (quit_now): Move up declaration before
3121
  
3122
  if(quit_now){
3123
    goto end;
3124
  }
3125
  
293 by Teddy Hogeborn
* plugin-runner.c: Whitespace changes only.
3126
  {
3127
    AvahiServerConfig config;
3128
    /* Do not publish any local Zeroconf records */
3129
    avahi_server_config_init(&config);
3130
    config.publish_hinfo = 0;
3131
    config.publish_addresses = 0;
3132
    config.publish_workstation = 0;
3133
    config.publish_domain = 0;
3134
    
3135
    /* Allocate a new server */
601 by Teddy Hogeborn
* plugins.d/mandos-client (mandos_context): Removed "simple_poll"
3136
    mc.server = avahi_server_new(avahi_simple_poll_get(simple_poll),
819 by Teddy Hogeborn
errno is of type int, not error_t
3137
				 &config, NULL, NULL, &ret);
293 by Teddy Hogeborn
* plugin-runner.c: Whitespace changes only.
3138
    
3139
    /* Free the Avahi configuration data */
3140
    avahi_server_config_free(&config);
3141
  }
3142
  
3143
  /* Check if creating the Avahi server object succeeded */
3144
  if(mc.server == NULL){
505.2.6 by Björn Påhlsson
replace calls to fprintf with fprintf_plus.
3145
    fprintf_plus(stderr, "Failed to create Avahi server: %s\n",
819 by Teddy Hogeborn
errno is of type int, not error_t
3146
		 avahi_strerror(ret));
399 by Teddy Hogeborn
* Makefile (BROKEN_PIE): Add comment.
3147
    exitcode = EX_UNAVAILABLE;
293 by Teddy Hogeborn
* plugin-runner.c: Whitespace changes only.
3148
    goto end;
3149
  }
3150
  
353 by Teddy Hogeborn
* plugins.d/mandos-client.c (quit_now): Move up declaration before
3151
  if(quit_now){
3152
    goto end;
3153
  }
3154
  
293 by Teddy Hogeborn
* plugin-runner.c: Whitespace changes only.
3155
  /* Create the Avahi service browser */
3156
  sb = avahi_s_service_browser_new(mc.server, if_index,
313 by Teddy Hogeborn
* plugins.d/mandos-client.c (browse_callback, main): Do not require
3157
				   AVAHI_PROTO_UNSPEC, "_mandos._tcp",
602 by Teddy Hogeborn
* plugins.d/mandos-client (mandos_context): Moved to inside "main()".
3158
				   NULL, 0, browse_callback,
3159
				   (void *)&mc);
293 by Teddy Hogeborn
* plugin-runner.c: Whitespace changes only.
3160
  if(sb == NULL){
505.2.6 by Björn Påhlsson
replace calls to fprintf with fprintf_plus.
3161
    fprintf_plus(stderr, "Failed to create service browser: %s\n",
505.3.9 by Teddy Hogeborn
* plugins.d/mandos-client.c: Merge unified printing system.
3162
		 avahi_strerror(avahi_server_errno(mc.server)));
399 by Teddy Hogeborn
* Makefile (BROKEN_PIE): Add comment.
3163
    exitcode = EX_UNAVAILABLE;
293 by Teddy Hogeborn
* plugin-runner.c: Whitespace changes only.
3164
    goto end;
3165
  }
307 by Teddy Hogeborn
Merge from Björn:
3166
  
353 by Teddy Hogeborn
* plugins.d/mandos-client.c (quit_now): Move up declaration before
3167
  if(quit_now){
3168
    goto end;
3169
  }
3170
  
293 by Teddy Hogeborn
* plugin-runner.c: Whitespace changes only.
3171
  /* Run the main loop */
3172
  
3173
  if(debug){
505.2.6 by Björn Påhlsson
replace calls to fprintf with fprintf_plus.
3174
    fprintf_plus(stderr, "Starting Avahi loop search\n");
293 by Teddy Hogeborn
* plugin-runner.c: Whitespace changes only.
3175
  }
687 by Teddy Hogeborn
White space fix only.
3176
  
601 by Teddy Hogeborn
* plugins.d/mandos-client (mandos_context): Removed "simple_poll"
3177
  ret = avahi_loop_with_timeout(simple_poll,
602 by Teddy Hogeborn
* plugins.d/mandos-client (mandos_context): Moved to inside "main()".
3178
				(int)(retry_interval * 1000), &mc);
24.1.174 by Björn Påhlsson
* Makefile (CFLAGS): Added "-lrt" to include real time library.
3179
  if(debug){
505.2.6 by Björn Påhlsson
replace calls to fprintf with fprintf_plus.
3180
    fprintf_plus(stderr, "avahi_loop_with_timeout exited %s\n",
505.3.9 by Teddy Hogeborn
* plugins.d/mandos-client.c: Merge unified printing system.
3181
		 (ret == 0) ? "successfully" : "with error");
24.1.174 by Björn Påhlsson
* Makefile (CFLAGS): Added "-lrt" to include real time library.
3182
  }
293 by Teddy Hogeborn
* plugin-runner.c: Whitespace changes only.
3183
  
40 by Teddy Hogeborn
* plugins.d/mandosclient.c (initgnutls): Moved "err" variable into its
3184
 end:
293 by Teddy Hogeborn
* plugin-runner.c: Whitespace changes only.
3185
  
3186
  if(debug){
870 by Teddy Hogeborn
Show what signal, if any, made mandos-client exit.
3187
    if(signal_received){
3188
      fprintf_plus(stderr, "%s exiting due to signal %d: %s\n",
3189
		   argv[0], signal_received,
3190
		   strsignal(signal_received));
3191
    } else {
3192
      fprintf_plus(stderr, "%s exiting\n", argv[0]);
3193
    }
293 by Teddy Hogeborn
* plugin-runner.c: Whitespace changes only.
3194
  }
3195
  
3196
  /* Cleanup things */
604 by Teddy Hogeborn
* plugins.d/mandos-client (start_mandos_communication): Bug fix; skip
3197
  free(mc.interfaces);
3198
  
293 by Teddy Hogeborn
* plugin-runner.c: Whitespace changes only.
3199
  if(sb != NULL)
3200
    avahi_s_service_browser_free(sb);
3201
  
3202
  if(mc.server != NULL)
3203
    avahi_server_free(mc.server);
3204
  
601 by Teddy Hogeborn
* plugins.d/mandos-client (mandos_context): Removed "simple_poll"
3205
  if(simple_poll != NULL)
3206
    avahi_simple_poll_free(simple_poll);
293 by Teddy Hogeborn
* plugin-runner.c: Whitespace changes only.
3207
  
3208
  if(gnutls_initialized){
3209
    gnutls_certificate_free_credentials(mc.cred);
3210
    gnutls_dh_params_deinit(mc.dh_params);
3211
  }
3212
  
3213
  if(gpgme_initialized){
3214
    gpgme_release(mc.ctx);
3215
  }
505.3.12 by Teddy Hogeborn
* plugins.d/mandos-client.c (runnable_hook): Add debug output.
3216
  
485 by Teddy Hogeborn
Merge from Björn.
3217
  /* Cleans up the circular linked list of Mandos servers the client
3218
     has seen */
24.1.174 by Björn Påhlsson
* Makefile (CFLAGS): Added "-lrt" to include real time library.
3219
  if(mc.current_server != NULL){
3220
    mc.current_server->prev->next = NULL;
3221
    while(mc.current_server != NULL){
3222
      server *next = mc.current_server->next;
714 by Teddy Hogeborn
mandos-client: Fix mem free bug.
3223
#ifdef __GNUC__
3224
#pragma GCC diagnostic push
3225
#pragma GCC diagnostic ignored "-Wcast-qual"
3226
#endif
3227
      free((char *)(mc.current_server->ip));
3228
#ifdef __GNUC__
3229
#pragma GCC diagnostic pop
3230
#endif
24.1.174 by Björn Påhlsson
* Makefile (CFLAGS): Added "-lrt" to include real time library.
3231
      free(mc.current_server);
3232
      mc.current_server = next;
3233
    }
3234
  }
293 by Teddy Hogeborn
* plugin-runner.c: Whitespace changes only.
3235
  
672 by Teddy Hogeborn
Update GCC warning flags and function attributes to GCC 4.7.
3236
  /* Re-raise privileges */
505.3.8 by Teddy Hogeborn
* plugins.d/mandos-client.c (run_network_hooks): New.
3237
  {
819 by Teddy Hogeborn
errno is of type int, not error_t
3238
    ret = raise_privileges();
3239
    if(ret != 0){
3240
      errno = ret;
672 by Teddy Hogeborn
Update GCC warning flags and function attributes to GCC 4.7.
3241
      perror_plus("Failed to raise privileges");
3242
    } else {
3243
      
3244
      /* Run network hooks */
3245
      run_network_hooks("stop", interfaces_hooks != NULL ?
3246
			interfaces_hooks : "", delay);
3247
      
3248
      /* Take down the network interfaces which were brought up */
3249
      {
3250
	char *interface = NULL;
890 by Teddy Hogeborn
Add spaces around all '=' signs in all C code.
3251
	while((interface = argz_next(interfaces_to_take_down,
3252
				     interfaces_to_take_down_size,
3253
				     interface))){
819 by Teddy Hogeborn
errno is of type int, not error_t
3254
	  ret = take_down_interface(interface);
3255
	  if(ret != 0){
3256
	    errno = ret;
672 by Teddy Hogeborn
Update GCC warning flags and function attributes to GCC 4.7.
3257
	    perror_plus("Failed to take down interface");
3258
	  }
3259
	}
3260
	if(debug and (interfaces_to_take_down == NULL)){
3261
	  fprintf_plus(stderr, "No interfaces needed to be taken"
3262
		       " down\n");
3263
	}
3264
      }
3265
    }
680 by Teddy Hogeborn
Minor changes to minimize diff from last release.
3266
    
819 by Teddy Hogeborn
errno is of type int, not error_t
3267
    ret = lower_privileges_permanently();
3268
    if(ret != 0){
3269
      errno = ret;
672 by Teddy Hogeborn
Update GCC warning flags and function attributes to GCC 4.7.
3270
      perror_plus("Failed to lower privileges permanently");
3271
    }
594.1.4 by Teddy Hogeborn
* plugins.d/mandos-client.c (get_flags): Don't clobber errno.
3272
  }
3273
  
3274
  free(interfaces_to_take_down);
3275
  free(interfaces_hooks);
350 by Teddy Hogeborn
* plugins.d/mandos-client.c (main): Take down network interface on
3276
  
813 by Teddy Hogeborn
Client: Remove new key directory introduced in GnuPG 2.1
3277
  void clean_dir_at(int base, const char * const dirname,
3278
		    uintmax_t level){
3279
    struct dirent **direntries = NULL;
3280
    int dret;
3281
    int dir_fd = (int)TEMP_FAILURE_RETRY(openat(base, dirname,
3282
						O_RDONLY
3283
						| O_NOFOLLOW
3284
						| O_DIRECTORY
3285
						| O_PATH));
3286
    if(dir_fd == -1){
3287
      perror_plus("open");
936 by Teddy Hogeborn
Client: Bug fix: Don't try to clean directory which fails to open
3288
      return;
813 by Teddy Hogeborn
Client: Remove new key directory introduced in GnuPG 2.1
3289
    }
3290
    int numentries = scandirat(dir_fd, ".", &direntries,
3291
			       notdotentries, alphasort);
3292
    if(numentries >= 0){
3293
      for(int i = 0; i < numentries; i++){
3294
	if(debug){
3295
	  fprintf_plus(stderr, "Unlinking \"%s/%s\"\n",
3296
		       dirname, direntries[i]->d_name);
3297
	}
3298
	dret = unlinkat(dir_fd, direntries[i]->d_name, 0);
3299
	if(dret == -1){
3300
	  if(errno == EISDIR){
3301
	      dret = unlinkat(dir_fd, direntries[i]->d_name,
3302
			      AT_REMOVEDIR);
3303
	  }	    
3304
	  if((dret == -1) and (errno == ENOTEMPTY)
3305
	     and (strcmp(direntries[i]->d_name, "private-keys-v1.d")
3306
		  == 0) and (level == 0)){
3307
	    /* Recurse only in this special case */
3308
	    clean_dir_at(dir_fd, direntries[i]->d_name, level+1);
3309
	    dret = 0;
3310
	  }
934 by Teddy Hogeborn
Client: Don't print failures to remove nonexisting files.
3311
	  if((dret == -1) and (errno != ENOENT)){
813 by Teddy Hogeborn
Client: Remove new key directory introduced in GnuPG 2.1
3312
	    fprintf_plus(stderr, "unlink(\"%s/%s\"): %s\n", dirname,
3313
			 direntries[i]->d_name, strerror(errno));
3314
	  }
3315
	}
3316
	free(direntries[i]);
3317
      }
3318
      
3319
      /* need to clean even if 0 because man page doesn't specify */
3320
      free(direntries);
3321
      dret = unlinkat(base, dirname, AT_REMOVEDIR);
3322
      if(dret == -1 and errno != ENOENT){
3323
	perror_plus("rmdir");
3324
      }
3325
    } else {
3326
      perror_plus("scandirat");
3327
    }
3328
    close(dir_fd);
3329
  }
3330
  
24.1.172 by Björn Påhlsson
using scandir instead of readdir
3331
  /* Removes the GPGME temp directory and all files inside */
673 by Teddy Hogeborn
Make mandos-client prefer /run/tmp over /tmp.
3332
  if(tempdir != NULL){
813 by Teddy Hogeborn
Client: Remove new key directory introduced in GnuPG 2.1
3333
    clean_dir_at(-1, tempdir, 0);
293 by Teddy Hogeborn
* plugin-runner.c: Whitespace changes only.
3334
  }
3335
  
354 by Teddy Hogeborn
* plugins.d/mandos-client.c (signal_received): New.
3336
  if(quit_now){
357 by Teddy Hogeborn
* plugins.d/mandos-client.c (main): Do not handle ignored signals.
3337
    sigemptyset(&old_sigterm_action.sa_mask);
3338
    old_sigterm_action.sa_handler = SIG_DFL;
374 by Teddy Hogeborn
* plugins.d/mandos-client.c (main): Try harder to raise signal on
3339
    ret = (int)TEMP_FAILURE_RETRY(sigaction(signal_received,
3340
					    &old_sigterm_action,
3341
					    NULL));
354 by Teddy Hogeborn
* plugins.d/mandos-client.c (signal_received): New.
3342
    if(ret == -1){
24.1.174 by Björn Påhlsson
* Makefile (CFLAGS): Added "-lrt" to include real time library.
3343
      perror_plus("sigaction");
354 by Teddy Hogeborn
* plugins.d/mandos-client.c (signal_received): New.
3344
    }
374 by Teddy Hogeborn
* plugins.d/mandos-client.c (main): Try harder to raise signal on
3345
    do {
3346
      ret = raise(signal_received);
3347
    } while(ret != 0 and errno == EINTR);
3348
    if(ret != 0){
24.1.174 by Björn Påhlsson
* Makefile (CFLAGS): Added "-lrt" to include real time library.
3349
      perror_plus("raise");
374 by Teddy Hogeborn
* plugins.d/mandos-client.c (main): Try harder to raise signal on
3350
      abort();
3351
    }
3352
    TEMP_FAILURE_RETRY(pause());
354 by Teddy Hogeborn
* plugins.d/mandos-client.c (signal_received): New.
3353
  }
3354
  
293 by Teddy Hogeborn
* plugin-runner.c: Whitespace changes only.
3355
  return exitcode;
13 by Björn Påhlsson
Added following support:
3356
}