/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
/*
3
 * Mandos client - get and decrypt data from a Mandos server
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
 * 
11
 * Everything else is Copyright © 2007-2008 Teddy Hogeborn and Björn
12
 * Påhlsson.
13
 * 
14
 * This program is free software: you can redistribute it and/or
15
 * modify it under the terms of the GNU General Public License as
16
 * published by the Free Software Foundation, either version 3 of the
17
 * License, or (at your option) any later version.
18
 * 
19
 * This program is distributed in the hope that it will be useful, but
20
 * WITHOUT ANY WARRANTY; without even the implied warranty of
21
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22
 * General Public License for more details.
23
 * 
24
 * You should have received a copy of the GNU General Public License
25
 * along with this program.  If not, see
26
 * <http://www.gnu.org/licenses/>.
27
 * 
28
 * Contact the authors at <https://www.fukt.bsnet.se/~belorn/> and
29
 * <https://www.fukt.bsnet.se/~teddy/>.
30
 */
31
32
#define _FORTIFY_SOURCE 2
13 by Björn Påhlsson
Added following support:
33
34
#define _LARGEFILE_SOURCE
35
#define _FILE_OFFSET_BITS 64
36
37
#include <stdio.h>
38
#include <assert.h>
39
#include <stdlib.h>
40
#include <time.h>
41
#include <net/if.h>		/* if_nametoindex */
42
43
#include <avahi-core/core.h>
44
#include <avahi-core/lookup.h>
45
#include <avahi-core/log.h>
46
#include <avahi-common/simple-watch.h>
47
#include <avahi-common/malloc.h>
48
#include <avahi-common/error.h>
49
50
//mandos client part
22 by Teddy Hogeborn
* plugins.d/mandosclient.c (pgp_packet_decrypt): Cast "0" argument to
51
#include <sys/types.h>		/* socket(), inet_pton() */
52
#include <sys/socket.h>		/* socket(), struct sockaddr_in6,
21 by Teddy Hogeborn
* Makefile (CFLAGS): Changed to use $(WARN), $(DEBUG), $(COVERAGE) and
53
				   struct in6_addr, inet_pton() */
54
#include <gnutls/gnutls.h>	/* All GnuTLS stuff */
55
#include <gnutls/openpgp.h>	/* GnuTLS with openpgp stuff */
13 by Björn Påhlsson
Added following support:
56
57
#include <unistd.h>		/* close() */
58
#include <netinet/in.h>
59
#include <stdbool.h>		/* true */
60
#include <string.h>		/* memset */
61
#include <arpa/inet.h>		/* inet_pton() */
62
#include <iso646.h>		/* not */
63
64
// gpgme
65
#include <errno.h>		/* perror() */
66
#include <gpgme.h>
67
15.1.3 by Björn Påhlsson
Added getopt_long support for mandosclient and passprompt
68
// getopt long
69
#include <getopt.h>
13 by Björn Påhlsson
Added following support:
70
71
#define BUFFER_SIZE 256
72
#define DH_BITS 1024
73
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.
74
const char *certdir = "/conf/conf.d/cryptkeyreq/";
75
const char *certfile = "openpgp-client.txt";
76
const char *certkey = "openpgp-client-key.txt";
77
15.1.2 by Björn Påhlsson
Added debug options from passprompt as --debug and --debug=passprompt
78
bool debug = false;
15.1.1 by Björn Påhlsson
Added debugg support in form off --debug and --debug=mandosclient
79
13 by Björn Påhlsson
Added following support:
80
typedef struct {
81
  gnutls_session_t session;
82
  gnutls_certificate_credentials_t cred;
83
  gnutls_dh_params_t dh_params;
84
} encrypted_session;
85
86
21 by Teddy Hogeborn
* Makefile (CFLAGS): Changed to use $(WARN), $(DEBUG), $(COVERAGE) and
87
ssize_t pgp_packet_decrypt (char *packet, size_t packet_size,
88
			    char **new_packet, const char *homedir){
13 by Björn Påhlsson
Added following support:
89
  gpgme_data_t dh_crypto, dh_plain;
90
  gpgme_ctx_t ctx;
91
  gpgme_error_t rc;
92
  ssize_t ret;
21 by Teddy Hogeborn
* Makefile (CFLAGS): Changed to use $(WARN), $(DEBUG), $(COVERAGE) and
93
  ssize_t new_packet_capacity = 0;
94
  ssize_t new_packet_length = 0;
13 by Björn Påhlsson
Added following support:
95
  gpgme_engine_info_t engine_info;
96
15.1.1 by Björn Påhlsson
Added debugg support in form off --debug and --debug=mandosclient
97
  if (debug){
21 by Teddy Hogeborn
* Makefile (CFLAGS): Changed to use $(WARN), $(DEBUG), $(COVERAGE) and
98
    fprintf(stderr, "Trying to decrypt OpenPGP packet\n");
15.1.1 by Björn Påhlsson
Added debugg support in form off --debug and --debug=mandosclient
99
  }
100
  
13 by Björn Påhlsson
Added following support:
101
  /* Init GPGME */
102
  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.
103
  rc = gpgme_engine_check_version(GPGME_PROTOCOL_OpenPGP);
104
  if (rc != GPG_ERR_NO_ERROR){
105
    fprintf(stderr, "bad gpgme_engine_check_version: %s: %s\n",
106
	    gpgme_strsource(rc), gpgme_strerror(rc));
107
    return -1;
108
  }
13 by Björn Påhlsson
Added following support:
109
  
110
  /* Set GPGME home directory */
111
  rc = gpgme_get_engine_info (&engine_info);
112
  if (rc != GPG_ERR_NO_ERROR){
113
    fprintf(stderr, "bad gpgme_get_engine_info: %s: %s\n",
114
	    gpgme_strsource(rc), gpgme_strerror(rc));
115
    return -1;
116
  }
117
  while(engine_info != NULL){
118
    if(engine_info->protocol == GPGME_PROTOCOL_OpenPGP){
119
      gpgme_set_engine_info(GPGME_PROTOCOL_OpenPGP,
120
			    engine_info->file_name, homedir);
121
      break;
122
    }
123
    engine_info = engine_info->next;
124
  }
125
  if(engine_info == NULL){
126
    fprintf(stderr, "Could not set home dir to %s\n", homedir);
127
    return -1;
128
  }
129
  
130
  /* Create new GPGME data buffer from packet buffer */
131
  rc = gpgme_data_new_from_mem(&dh_crypto, packet, packet_size, 0);
132
  if (rc != GPG_ERR_NO_ERROR){
133
    fprintf(stderr, "bad gpgme_data_new_from_mem: %s: %s\n",
134
	    gpgme_strsource(rc), gpgme_strerror(rc));
135
    return -1;
136
  }
137
  
138
  /* Create new empty GPGME data buffer for the plaintext */
139
  rc = gpgme_data_new(&dh_plain);
140
  if (rc != GPG_ERR_NO_ERROR){
141
    fprintf(stderr, "bad gpgme_data_new: %s: %s\n",
142
	    gpgme_strsource(rc), gpgme_strerror(rc));
143
    return -1;
144
  }
145
  
146
  /* Create new GPGME "context" */
147
  rc = gpgme_new(&ctx);
148
  if (rc != GPG_ERR_NO_ERROR){
149
    fprintf(stderr, "bad gpgme_new: %s: %s\n",
150
	    gpgme_strsource(rc), gpgme_strerror(rc));
151
    return -1;
152
  }
153
  
21 by Teddy Hogeborn
* Makefile (CFLAGS): Changed to use $(WARN), $(DEBUG), $(COVERAGE) and
154
  /* Decrypt data from the FILE pointer to the plaintext data
155
     buffer */
13 by Björn Påhlsson
Added following support:
156
  rc = gpgme_op_decrypt(ctx, dh_crypto, dh_plain);
157
  if (rc != GPG_ERR_NO_ERROR){
158
    fprintf(stderr, "bad gpgme_op_decrypt: %s: %s\n",
159
	    gpgme_strsource(rc), gpgme_strerror(rc));
160
    return -1;
161
  }
15.1.1 by Björn Påhlsson
Added debugg support in form off --debug and --debug=mandosclient
162
163
  if(debug){
21 by Teddy Hogeborn
* Makefile (CFLAGS): Changed to use $(WARN), $(DEBUG), $(COVERAGE) and
164
    fprintf(stderr, "Decryption of OpenPGP packet succeeded\n");
15.1.1 by Björn Påhlsson
Added debugg support in form off --debug and --debug=mandosclient
165
  }
166
167
  if (debug){
168
    gpgme_decrypt_result_t result;
169
    result = gpgme_op_decrypt_result(ctx);
170
    if (result == NULL){
171
      fprintf(stderr, "gpgme_op_decrypt_result failed\n");
172
    } else {
21 by Teddy Hogeborn
* Makefile (CFLAGS): Changed to use $(WARN), $(DEBUG), $(COVERAGE) and
173
      fprintf(stderr, "Unsupported algorithm: %s\n",
174
	      result->unsupported_algorithm);
175
      fprintf(stderr, "Wrong key usage: %d\n",
176
	      result->wrong_key_usage);
15.1.1 by Björn Påhlsson
Added debugg support in form off --debug and --debug=mandosclient
177
      if(result->file_name != NULL){
178
	fprintf(stderr, "File name: %s\n", result->file_name);
179
      }
180
      gpgme_recipient_t recipient;
181
      recipient = result->recipients;
182
      if(recipient){
183
	while(recipient != NULL){
184
	  fprintf(stderr, "Public key algorithm: %s\n",
185
		  gpgme_pubkey_algo_name(recipient->pubkey_algo));
186
	  fprintf(stderr, "Key ID: %s\n", recipient->keyid);
187
	  fprintf(stderr, "Secret key available: %s\n",
21 by Teddy Hogeborn
* Makefile (CFLAGS): Changed to use $(WARN), $(DEBUG), $(COVERAGE) and
188
		  recipient->status == GPG_ERR_NO_SECKEY
189
		  ? "No" : "Yes");
15.1.1 by Björn Påhlsson
Added debugg support in form off --debug and --debug=mandosclient
190
	  recipient = recipient->next;
191
	}
192
      }
193
    }
194
  }
13 by Björn Påhlsson
Added following support:
195
  
196
  /* Delete the GPGME FILE pointer cryptotext data buffer */
197
  gpgme_data_release(dh_crypto);
198
  
199
  /* Seek back to the beginning of the GPGME plaintext data buffer */
22 by Teddy Hogeborn
* plugins.d/mandosclient.c (pgp_packet_decrypt): Cast "0" argument to
200
  gpgme_data_seek(dh_plain, (off_t) 0, SEEK_SET);
13 by Björn Påhlsson
Added following support:
201
202
  *new_packet = 0;
203
  while(true){
204
    if (new_packet_length + BUFFER_SIZE > new_packet_capacity){
21 by Teddy Hogeborn
* Makefile (CFLAGS): Changed to use $(WARN), $(DEBUG), $(COVERAGE) and
205
      *new_packet = realloc(*new_packet,
206
			    (unsigned int)new_packet_capacity
207
			    + BUFFER_SIZE);
13 by Björn Påhlsson
Added following support:
208
      if (*new_packet == NULL){
209
	perror("realloc");
210
	return -1;
211
      }
212
      new_packet_capacity += BUFFER_SIZE;
213
    }
214
    
21 by Teddy Hogeborn
* Makefile (CFLAGS): Changed to use $(WARN), $(DEBUG), $(COVERAGE) and
215
    ret = gpgme_data_read(dh_plain, *new_packet + new_packet_length,
216
			  BUFFER_SIZE);
13 by Björn Påhlsson
Added following support:
217
    /* Print the data, if any */
218
    if (ret == 0){
219
      break;
220
    }
221
    if(ret < 0){
222
      perror("gpgme_data_read");
223
      return -1;
224
    }
225
    new_packet_length += ret;
226
  }
227
15.1.3 by Björn Påhlsson
Added getopt_long support for mandosclient and passprompt
228
  /* FIXME: check characters before printing to screen so to not print
229
     terminal control characters */
230
  /*   if(debug){ */
231
  /*     fprintf(stderr, "decrypted password is: "); */
232
  /*     fwrite(*new_packet, 1, new_packet_length, stderr); */
233
  /*     fprintf(stderr, "\n"); */
234
  /*   } */
235
  
236
  /* Delete the GPGME plaintext data buffer */
13 by Björn Påhlsson
Added following support:
237
  gpgme_data_release(dh_plain);
238
  return new_packet_length;
239
}
240
241
static const char * safer_gnutls_strerror (int value) {
242
  const char *ret = gnutls_strerror (value);
243
  if (ret == NULL)
244
    ret = "(unknown)";
245
  return ret;
246
}
247
21 by Teddy Hogeborn
* Makefile (CFLAGS): Changed to use $(WARN), $(DEBUG), $(COVERAGE) and
248
void debuggnutls(__attribute__((unused)) int level,
249
		 const char* string){
13 by Björn Påhlsson
Added following support:
250
  fprintf(stderr, "%s", string);
251
}
252
253
int initgnutls(encrypted_session *es){
254
  const char *err;
255
  int ret;
21 by Teddy Hogeborn
* Makefile (CFLAGS): Changed to use $(WARN), $(DEBUG), $(COVERAGE) and
256
  
15.1.1 by Björn Påhlsson
Added debugg support in form off --debug and --debug=mandosclient
257
  if(debug){
21 by Teddy Hogeborn
* Makefile (CFLAGS): Changed to use $(WARN), $(DEBUG), $(COVERAGE) and
258
    fprintf(stderr, "Initializing GnuTLS\n");
15.1.1 by Björn Påhlsson
Added debugg support in form off --debug and --debug=mandosclient
259
  }
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.
260
13 by Björn Påhlsson
Added following support:
261
  if ((ret = gnutls_global_init ())
262
      != GNUTLS_E_SUCCESS) {
263
    fprintf (stderr, "global_init: %s\n", safer_gnutls_strerror(ret));
264
    return -1;
265
  }
266
15.1.1 by Björn Påhlsson
Added debugg support in form off --debug and --debug=mandosclient
267
  if (debug){
268
    gnutls_global_set_log_level(11);
269
    gnutls_global_set_log_function(debuggnutls);
270
  }
271
  
13 by Björn Påhlsson
Added following support:
272
  /* openpgp credentials */
273
  if ((ret = gnutls_certificate_allocate_credentials (&es->cred))
274
      != GNUTLS_E_SUCCESS) {
21 by Teddy Hogeborn
* Makefile (CFLAGS): Changed to use $(WARN), $(DEBUG), $(COVERAGE) and
275
    fprintf (stderr, "memory error: %s\n",
276
	     safer_gnutls_strerror(ret));
13 by Björn Påhlsson
Added following support:
277
    return -1;
278
  }
21 by Teddy Hogeborn
* Makefile (CFLAGS): Changed to use $(WARN), $(DEBUG), $(COVERAGE) and
279
  
15.1.1 by Björn Påhlsson
Added debugg support in form off --debug and --debug=mandosclient
280
  if(debug){
21 by Teddy Hogeborn
* Makefile (CFLAGS): Changed to use $(WARN), $(DEBUG), $(COVERAGE) and
281
    fprintf(stderr, "Attempting to use OpenPGP certificate %s"
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.
282
	    " and keyfile %s as GnuTLS credentials\n", certfile,
283
	    certkey);
15.1.1 by Björn Påhlsson
Added debugg support in form off --debug and --debug=mandosclient
284
  }
21 by Teddy Hogeborn
* Makefile (CFLAGS): Changed to use $(WARN), $(DEBUG), $(COVERAGE) and
285
  
13 by Björn Påhlsson
Added following support:
286
  ret = gnutls_certificate_set_openpgp_key_file
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.
287
    (es->cred, certfile, certkey, GNUTLS_OPENPGP_FMT_BASE64);
13 by Björn Påhlsson
Added following support:
288
  if (ret != GNUTLS_E_SUCCESS) {
289
    fprintf
21 by Teddy Hogeborn
* Makefile (CFLAGS): Changed to use $(WARN), $(DEBUG), $(COVERAGE) and
290
      (stderr, "Error[%d] while reading the OpenPGP key pair ('%s',"
291
       " '%s')\n",
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.
292
       ret, certfile, certkey);
13 by Björn Påhlsson
Added following support:
293
    fprintf(stdout, "The Error is: %s\n",
294
	    safer_gnutls_strerror(ret));
295
    return -1;
296
  }
21 by Teddy Hogeborn
* Makefile (CFLAGS): Changed to use $(WARN), $(DEBUG), $(COVERAGE) and
297
  
298
  //GnuTLS server initialization
13 by Björn Påhlsson
Added following support:
299
  if ((ret = gnutls_dh_params_init (&es->dh_params))
300
      != GNUTLS_E_SUCCESS) {
301
    fprintf (stderr, "Error in dh parameter initialization: %s\n",
302
	     safer_gnutls_strerror(ret));
303
    return -1;
304
  }
21 by Teddy Hogeborn
* Makefile (CFLAGS): Changed to use $(WARN), $(DEBUG), $(COVERAGE) and
305
  
13 by Björn Påhlsson
Added following support:
306
  if ((ret = gnutls_dh_params_generate2 (es->dh_params, DH_BITS))
307
      != GNUTLS_E_SUCCESS) {
308
    fprintf (stderr, "Error in prime generation: %s\n",
309
	     safer_gnutls_strerror(ret));
310
    return -1;
311
  }
21 by Teddy Hogeborn
* Makefile (CFLAGS): Changed to use $(WARN), $(DEBUG), $(COVERAGE) and
312
  
13 by Björn Påhlsson
Added following support:
313
  gnutls_certificate_set_dh_params (es->cred, es->dh_params);
21 by Teddy Hogeborn
* Makefile (CFLAGS): Changed to use $(WARN), $(DEBUG), $(COVERAGE) and
314
  
315
  // GnuTLS session creation
13 by Björn Påhlsson
Added following support:
316
  if ((ret = gnutls_init (&es->session, GNUTLS_SERVER))
317
      != GNUTLS_E_SUCCESS){
21 by Teddy Hogeborn
* Makefile (CFLAGS): Changed to use $(WARN), $(DEBUG), $(COVERAGE) and
318
    fprintf(stderr, "Error in GnuTLS session initialization: %s\n",
13 by Björn Påhlsson
Added following support:
319
	    safer_gnutls_strerror(ret));
320
  }
21 by Teddy Hogeborn
* Makefile (CFLAGS): Changed to use $(WARN), $(DEBUG), $(COVERAGE) and
321
  
13 by Björn Påhlsson
Added following support:
322
  if ((ret = gnutls_priority_set_direct (es->session, "NORMAL", &err))
323
      != GNUTLS_E_SUCCESS) {
324
    fprintf(stderr, "Syntax error at: %s\n", err);
21 by Teddy Hogeborn
* Makefile (CFLAGS): Changed to use $(WARN), $(DEBUG), $(COVERAGE) and
325
    fprintf(stderr, "GnuTLS error: %s\n",
13 by Björn Påhlsson
Added following support:
326
	    safer_gnutls_strerror(ret));
327
    return -1;
328
  }
21 by Teddy Hogeborn
* Makefile (CFLAGS): Changed to use $(WARN), $(DEBUG), $(COVERAGE) and
329
  
13 by Björn Påhlsson
Added following support:
330
  if ((ret = gnutls_credentials_set
331
       (es->session, GNUTLS_CRD_CERTIFICATE, es->cred))
332
      != GNUTLS_E_SUCCESS) {
333
    fprintf(stderr, "Error setting a credentials set: %s\n",
334
	    safer_gnutls_strerror(ret));
335
    return -1;
336
  }
21 by Teddy Hogeborn
* Makefile (CFLAGS): Changed to use $(WARN), $(DEBUG), $(COVERAGE) and
337
  
13 by Björn Påhlsson
Added following support:
338
  /* ignore client certificate if any. */
21 by Teddy Hogeborn
* Makefile (CFLAGS): Changed to use $(WARN), $(DEBUG), $(COVERAGE) and
339
  gnutls_certificate_server_set_request (es->session,
340
					 GNUTLS_CERT_IGNORE);
13 by Björn Påhlsson
Added following support:
341
  
342
  gnutls_dh_set_prime_bits (es->session, DH_BITS);
343
  
344
  return 0;
345
}
346
21 by Teddy Hogeborn
* Makefile (CFLAGS): Changed to use $(WARN), $(DEBUG), $(COVERAGE) and
347
void empty_log(__attribute__((unused)) AvahiLogLevel level,
348
	       __attribute__((unused)) const char *txt){}
13 by Björn Påhlsson
Added following support:
349
22 by Teddy Hogeborn
* plugins.d/mandosclient.c (pgp_packet_decrypt): Cast "0" argument to
350
int start_mandos_communication(const char *ip, uint16_t port,
21 by Teddy Hogeborn
* Makefile (CFLAGS): Changed to use $(WARN), $(DEBUG), $(COVERAGE) and
351
			       unsigned int if_index){
13 by Björn Påhlsson
Added following support:
352
  int ret, tcp_sd;
353
  struct sockaddr_in6 to;
354
  encrypted_session es;
355
  char *buffer = NULL;
356
  char *decrypted_buffer;
357
  size_t buffer_length = 0;
358
  size_t buffer_capacity = 0;
359
  ssize_t decrypted_buffer_size;
22 by Teddy Hogeborn
* plugins.d/mandosclient.c (pgp_packet_decrypt): Cast "0" argument to
360
  size_t written = 0;
13 by Björn Påhlsson
Added following support:
361
  int retval = 0;
21 by Teddy Hogeborn
* Makefile (CFLAGS): Changed to use $(WARN), $(DEBUG), $(COVERAGE) and
362
  char interface[IF_NAMESIZE];
363
  
15.1.1 by Björn Påhlsson
Added debugg support in form off --debug and --debug=mandosclient
364
  if(debug){
365
    fprintf(stderr, "Setting up a tcp connection to %s\n", ip);
366
  }
13 by Björn Påhlsson
Added following support:
367
  
368
  tcp_sd = socket(PF_INET6, SOCK_STREAM, 0);
369
  if(tcp_sd < 0) {
370
    perror("socket");
371
    return -1;
372
  }
21 by Teddy Hogeborn
* Makefile (CFLAGS): Changed to use $(WARN), $(DEBUG), $(COVERAGE) and
373
  
374
  if(if_indextoname(if_index, interface) == NULL){
375
    if(debug){
376
      perror("if_indextoname");
377
    }
378
    return -1;
379
  }
380
  
15.1.1 by Björn Påhlsson
Added debugg support in form off --debug and --debug=mandosclient
381
  if(debug){
382
    fprintf(stderr, "Binding to interface %s\n", interface);
383
  }
21 by Teddy Hogeborn
* Makefile (CFLAGS): Changed to use $(WARN), $(DEBUG), $(COVERAGE) and
384
  
22 by Teddy Hogeborn
* plugins.d/mandosclient.c (pgp_packet_decrypt): Cast "0" argument to
385
  memset(&to,0,sizeof(to));	/* Spurious warning */
13 by Björn Påhlsson
Added following support:
386
  to.sin6_family = AF_INET6;
18 by Teddy Hogeborn
* plugins.d/Makefile: Removed
387
  ret = inet_pton(AF_INET6, ip, &to.sin6_addr);
13 by Björn Påhlsson
Added following support:
388
  if (ret < 0 ){
389
    perror("inet_pton");
390
    return -1;
391
  }  
392
  if(ret == 0){
393
    fprintf(stderr, "Bad address: %s\n", ip);
394
    return -1;
395
  }
22 by Teddy Hogeborn
* plugins.d/mandosclient.c (pgp_packet_decrypt): Cast "0" argument to
396
  to.sin6_port = htons(port);	/* Spurious warning */
21 by Teddy Hogeborn
* Makefile (CFLAGS): Changed to use $(WARN), $(DEBUG), $(COVERAGE) and
397
  
398
  to.sin6_scope_id = (uint32_t)if_index;
399
  
15.1.1 by Björn Påhlsson
Added debugg support in form off --debug and --debug=mandosclient
400
  if(debug){
401
    fprintf(stderr, "Connection to: %s\n", ip);
402
  }
13 by Björn Påhlsson
Added following support:
403
  
404
  ret = connect(tcp_sd, (struct sockaddr *) &to, sizeof(to));
405
  if (ret < 0){
406
    perror("connect");
407
    return -1;
408
  }
409
  
410
  ret = initgnutls (&es);
411
  if (ret != 0){
412
    retval = -1;
413
    return -1;
414
  }
21 by Teddy Hogeborn
* Makefile (CFLAGS): Changed to use $(WARN), $(DEBUG), $(COVERAGE) and
415
  
416
  gnutls_transport_set_ptr (es.session,
417
			    (gnutls_transport_ptr_t) tcp_sd);
418
  
15.1.1 by Björn Påhlsson
Added debugg support in form off --debug and --debug=mandosclient
419
  if(debug){
21 by Teddy Hogeborn
* Makefile (CFLAGS): Changed to use $(WARN), $(DEBUG), $(COVERAGE) and
420
    fprintf(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
421
  }
422
  
13 by Björn Påhlsson
Added following support:
423
  ret = gnutls_handshake (es.session);
424
  
425
  if (ret != GNUTLS_E_SUCCESS){
25 by Teddy Hogeborn
* mandos-clients.conf ([DEFAULT]): New section.
426
    if(debug){
427
      fprintf(stderr, "\n*** Handshake failed ***\n");
428
      gnutls_perror (ret);
429
    }
13 by Björn Påhlsson
Added following support:
430
    retval = -1;
431
    goto exit;
432
  }
21 by Teddy Hogeborn
* Makefile (CFLAGS): Changed to use $(WARN), $(DEBUG), $(COVERAGE) and
433
  
434
  //Retrieve OpenPGP packet that contains the wanted password
435
  
15.1.1 by Björn Påhlsson
Added debugg support in form off --debug and --debug=mandosclient
436
  if(debug){
21 by Teddy Hogeborn
* Makefile (CFLAGS): Changed to use $(WARN), $(DEBUG), $(COVERAGE) and
437
    fprintf(stderr, "Retrieving pgp encrypted password from %s\n",
438
	    ip);
15.1.1 by Björn Påhlsson
Added debugg support in form off --debug and --debug=mandosclient
439
  }
440
13 by Björn Påhlsson
Added following support:
441
  while(true){
442
    if (buffer_length + BUFFER_SIZE > buffer_capacity){
443
      buffer = realloc(buffer, buffer_capacity + BUFFER_SIZE);
444
      if (buffer == NULL){
445
	perror("realloc");
446
	goto exit;
447
      }
448
      buffer_capacity += BUFFER_SIZE;
449
    }
450
    
451
    ret = gnutls_record_recv
452
      (es.session, buffer+buffer_length, BUFFER_SIZE);
453
    if (ret == 0){
454
      break;
455
    }
456
    if (ret < 0){
457
      switch(ret){
458
      case GNUTLS_E_INTERRUPTED:
459
      case GNUTLS_E_AGAIN:
460
	break;
461
      case GNUTLS_E_REHANDSHAKE:
462
	ret = gnutls_handshake (es.session);
463
	if (ret < 0){
464
	  fprintf(stderr, "\n*** Handshake failed ***\n");
465
	  gnutls_perror (ret);
466
	  retval = -1;
467
	  goto exit;
468
	}
469
	break;
470
      default:
21 by Teddy Hogeborn
* Makefile (CFLAGS): Changed to use $(WARN), $(DEBUG), $(COVERAGE) and
471
	fprintf(stderr, "Unknown error while reading data from"
472
		" encrypted session with mandos server\n");
13 by Björn Påhlsson
Added following support:
473
	retval = -1;
474
	gnutls_bye (es.session, GNUTLS_SHUT_RDWR);
475
	goto exit;
476
      }
477
    } else {
21 by Teddy Hogeborn
* Makefile (CFLAGS): Changed to use $(WARN), $(DEBUG), $(COVERAGE) and
478
      buffer_length += (size_t) ret;
13 by Björn Påhlsson
Added following support:
479
    }
480
  }
15.1.1 by Björn Påhlsson
Added debugg support in form off --debug and --debug=mandosclient
481
  
13 by Björn Påhlsson
Added following support:
482
  if (buffer_length > 0){
21 by Teddy Hogeborn
* Makefile (CFLAGS): Changed to use $(WARN), $(DEBUG), $(COVERAGE) and
483
    decrypted_buffer_size = pgp_packet_decrypt(buffer,
484
					       buffer_length,
485
					       &decrypted_buffer,
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.
486
					       certdir);
21 by Teddy Hogeborn
* Makefile (CFLAGS): Changed to use $(WARN), $(DEBUG), $(COVERAGE) and
487
    if (decrypted_buffer_size >= 0){
22 by Teddy Hogeborn
* plugins.d/mandosclient.c (pgp_packet_decrypt): Cast "0" argument to
488
      while(written < decrypted_buffer_size){
489
	ret = (int)fwrite (decrypted_buffer + written, 1,
490
			   (size_t)decrypted_buffer_size - written,
491
			   stdout);
21 by Teddy Hogeborn
* Makefile (CFLAGS): Changed to use $(WARN), $(DEBUG), $(COVERAGE) and
492
	if(ret == 0 and ferror(stdout)){
493
	  if(debug){
494
	    fprintf(stderr, "Error writing encrypted data: %s\n",
495
		    strerror(errno));
496
	  }
497
	  retval = -1;
498
	  break;
499
	}
22 by Teddy Hogeborn
* plugins.d/mandosclient.c (pgp_packet_decrypt): Cast "0" argument to
500
	written += (size_t)ret;
21 by Teddy Hogeborn
* Makefile (CFLAGS): Changed to use $(WARN), $(DEBUG), $(COVERAGE) and
501
      }
13 by Björn Påhlsson
Added following support:
502
      free(decrypted_buffer);
15.1.1 by Björn Påhlsson
Added debugg support in form off --debug and --debug=mandosclient
503
    } else {
504
      retval = -1;
13 by Björn Påhlsson
Added following support:
505
    }
506
  }
507
15.1.1 by Björn Påhlsson
Added debugg support in form off --debug and --debug=mandosclient
508
  //shutdown procedure
509
510
  if(debug){
21 by Teddy Hogeborn
* Makefile (CFLAGS): Changed to use $(WARN), $(DEBUG), $(COVERAGE) and
511
    fprintf(stderr, "Closing TLS session\n");
15.1.1 by Björn Påhlsson
Added debugg support in form off --debug and --debug=mandosclient
512
  }
513
13 by Björn Påhlsson
Added following support:
514
  free(buffer);
515
  gnutls_bye (es.session, GNUTLS_SHUT_RDWR);
516
 exit:
517
  close(tcp_sd);
518
  gnutls_deinit (es.session);
519
  gnutls_certificate_free_credentials (es.cred);
520
  gnutls_global_deinit ();
521
  return retval;
522
}
523
524
static AvahiSimplePoll *simple_poll = NULL;
525
static AvahiServer *server = NULL;
526
527
static void resolve_callback(
528
    AvahiSServiceResolver *r,
22 by Teddy Hogeborn
* plugins.d/mandosclient.c (pgp_packet_decrypt): Cast "0" argument to
529
    AvahiIfIndex interface,
13 by Björn Påhlsson
Added following support:
530
    AVAHI_GCC_UNUSED AvahiProtocol protocol,
531
    AvahiResolverEvent event,
532
    const char *name,
533
    const char *type,
534
    const char *domain,
535
    const char *host_name,
536
    const AvahiAddress *address,
537
    uint16_t port,
21 by Teddy Hogeborn
* Makefile (CFLAGS): Changed to use $(WARN), $(DEBUG), $(COVERAGE) and
538
    AVAHI_GCC_UNUSED AvahiStringList *txt,
539
    AVAHI_GCC_UNUSED AvahiLookupResultFlags flags,
13 by Björn Påhlsson
Added following support:
540
    AVAHI_GCC_UNUSED void* userdata) {
541
    
22 by Teddy Hogeborn
* plugins.d/mandosclient.c (pgp_packet_decrypt): Cast "0" argument to
542
  assert(r);			/* Spurious warning */
543
  
21 by Teddy Hogeborn
* Makefile (CFLAGS): Changed to use $(WARN), $(DEBUG), $(COVERAGE) and
544
  /* Called whenever a service has been resolved successfully or
545
     timed out */
22 by Teddy Hogeborn
* plugins.d/mandosclient.c (pgp_packet_decrypt): Cast "0" argument to
546
  
21 by Teddy Hogeborn
* Makefile (CFLAGS): Changed to use $(WARN), $(DEBUG), $(COVERAGE) and
547
  switch (event) {
548
  default:
549
  case AVAHI_RESOLVER_FAILURE:
550
    fprintf(stderr, "(Resolver) Failed to resolve service '%s' of"
551
	    " type '%s' in domain '%s': %s\n", name, type, domain,
552
	    avahi_strerror(avahi_server_errno(server)));
553
    break;
22 by Teddy Hogeborn
* plugins.d/mandosclient.c (pgp_packet_decrypt): Cast "0" argument to
554
    
21 by Teddy Hogeborn
* Makefile (CFLAGS): Changed to use $(WARN), $(DEBUG), $(COVERAGE) and
555
  case AVAHI_RESOLVER_FOUND:
556
    {
557
      char ip[AVAHI_ADDRESS_STR_MAX];
558
      avahi_address_snprint(ip, sizeof(ip), address);
559
      if(debug){
25 by Teddy Hogeborn
* mandos-clients.conf ([DEFAULT]): New section.
560
	fprintf(stderr, "Mandos server \"%s\" found on %s (%s) on"
561
		" port %d\n", name, host_name, ip, port);
21 by Teddy Hogeborn
* Makefile (CFLAGS): Changed to use $(WARN), $(DEBUG), $(COVERAGE) and
562
      }
563
      int ret = start_mandos_communication(ip, port,
22 by Teddy Hogeborn
* plugins.d/mandosclient.c (pgp_packet_decrypt): Cast "0" argument to
564
					   (unsigned int) interface);
21 by Teddy Hogeborn
* Makefile (CFLAGS): Changed to use $(WARN), $(DEBUG), $(COVERAGE) and
565
      if (ret == 0){
566
	exit(EXIT_SUCCESS);
567
      }
13 by Björn Påhlsson
Added following support:
568
    }
21 by Teddy Hogeborn
* Makefile (CFLAGS): Changed to use $(WARN), $(DEBUG), $(COVERAGE) and
569
  }
570
  avahi_s_service_resolver_free(r);
13 by Björn Påhlsson
Added following support:
571
}
572
573
static void browse_callback(
574
    AvahiSServiceBrowser *b,
575
    AvahiIfIndex interface,
576
    AvahiProtocol protocol,
577
    AvahiBrowserEvent event,
578
    const char *name,
579
    const char *type,
580
    const char *domain,
581
    AVAHI_GCC_UNUSED AvahiLookupResultFlags flags,
582
    void* userdata) {
583
    
584
    AvahiServer *s = userdata;
22 by Teddy Hogeborn
* plugins.d/mandosclient.c (pgp_packet_decrypt): Cast "0" argument to
585
    assert(b);			/* Spurious warning */
586
    
21 by Teddy Hogeborn
* Makefile (CFLAGS): Changed to use $(WARN), $(DEBUG), $(COVERAGE) and
587
    /* Called whenever a new services becomes available on the LAN or
588
       is removed from the LAN */
22 by Teddy Hogeborn
* plugins.d/mandosclient.c (pgp_packet_decrypt): Cast "0" argument to
589
    
13 by Björn Påhlsson
Added following support:
590
    switch (event) {
21 by Teddy Hogeborn
* Makefile (CFLAGS): Changed to use $(WARN), $(DEBUG), $(COVERAGE) and
591
    default:
592
    case AVAHI_BROWSER_FAILURE:
593
      
594
      fprintf(stderr, "(Browser) %s\n",
595
	      avahi_strerror(avahi_server_errno(server)));
596
      avahi_simple_poll_quit(simple_poll);
597
      return;
598
      
599
    case AVAHI_BROWSER_NEW:
600
      /* We ignore the returned resolver object. In the callback
601
	 function we free it. If the server is terminated before
602
	 the callback function is called the server will free
603
	 the resolver for us. */
604
      
605
      if (!(avahi_s_service_resolver_new(s, interface, protocol, name,
606
					 type, domain,
607
					 AVAHI_PROTO_INET6, 0,
608
					 resolve_callback, s)))
609
	fprintf(stderr, "Failed to resolve service '%s': %s\n", name,
610
		avahi_strerror(avahi_server_errno(s)));
611
      break;
612
      
613
    case AVAHI_BROWSER_REMOVE:
614
      break;
615
      
616
    case AVAHI_BROWSER_ALL_FOR_NOW:
617
    case AVAHI_BROWSER_CACHE_EXHAUSTED:
618
      break;
13 by Björn Påhlsson
Added following support:
619
    }
620
}
621
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.
622
/* combinds two strings and returns the malloced new string. som sane checks could/should be added */
623
const char *combinestrings(const char *first, const char *second){
624
  char *tmp;
625
  tmp = malloc(strlen(first) + strlen(second));
626
  if (tmp == NULL){
627
    perror("malloc");
628
    return NULL;
629
  }
630
  strcpy(tmp, first);
631
  strcat(tmp, second);
632
  return tmp;
633
}
634
635
13 by Björn Påhlsson
Added following support:
636
int main(AVAHI_GCC_UNUSED int argc, AVAHI_GCC_UNUSED char*argv[]) {
637
    AvahiServerConfig config;
638
    AvahiSServiceBrowser *sb = NULL;
639
    int error;
15.1.3 by Björn Påhlsson
Added getopt_long support for mandosclient and passprompt
640
    int ret;
15.1.1 by Björn Påhlsson
Added debugg support in form off --debug and --debug=mandosclient
641
    int returncode = EXIT_SUCCESS;
21 by Teddy Hogeborn
* Makefile (CFLAGS): Changed to use $(WARN), $(DEBUG), $(COVERAGE) and
642
    const char *interface = "eth0";
643
    
15.1.3 by Björn Påhlsson
Added getopt_long support for mandosclient and passprompt
644
    while (true){
645
      static struct option long_options[] = {
646
	{"debug", no_argument, (int *)&debug, 1},
647
	{"interface", required_argument, 0, 'i'},
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.
648
	{"certdir", required_argument, 0, 'd'},
649
	{"certkey", required_argument, 0, 'c'},
650
	{"certfile", required_argument, 0, 'k'},
15.1.3 by Björn Påhlsson
Added getopt_long support for mandosclient and passprompt
651
	{0, 0, 0, 0} };
22 by Teddy Hogeborn
* plugins.d/mandosclient.c (pgp_packet_decrypt): Cast "0" argument to
652
      
15.1.3 by Björn Påhlsson
Added getopt_long support for mandosclient and passprompt
653
      int option_index = 0;
21 by Teddy Hogeborn
* Makefile (CFLAGS): Changed to use $(WARN), $(DEBUG), $(COVERAGE) and
654
      ret = getopt_long (argc, argv, "i:", long_options,
655
			 &option_index);
22 by Teddy Hogeborn
* plugins.d/mandosclient.c (pgp_packet_decrypt): Cast "0" argument to
656
      
15.1.3 by Björn Påhlsson
Added getopt_long support for mandosclient and passprompt
657
      if (ret == -1){
658
	break;
659
      }
660
      
661
      switch(ret){
662
      case 0:
663
	break;
664
      case 'i':
665
	interface = optarg;
666
	break;
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.
667
      case 'd':
668
	certdir = optarg;
669
	break;
670
      case 'c':
671
	certfile = optarg;
672
	break;
673
      case 'k':
674
	certkey = optarg;
675
	break;
15.1.3 by Björn Påhlsson
Added getopt_long support for mandosclient and passprompt
676
      default:
677
	exit(EXIT_FAILURE);
678
      }
679
    }
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.
680
681
    certfile = combinestrings(certdir, certfile);
682
    if (certfile == NULL){
683
      goto exit;
684
    }
15.1.3 by Björn Påhlsson
Added getopt_long support for mandosclient and passprompt
685
    
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.
686
    certkey = combinestrings(certdir, certkey);
687
    if (certkey == NULL){
688
      goto exit;
689
    }
690
	
15.1.1 by Björn Påhlsson
Added debugg support in form off --debug and --debug=mandosclient
691
    if (not debug){
692
      avahi_set_log_function(empty_log);
693
    }
13 by Björn Påhlsson
Added following support:
694
    
695
    /* Initialize the psuedo-RNG */
21 by Teddy Hogeborn
* Makefile (CFLAGS): Changed to use $(WARN), $(DEBUG), $(COVERAGE) and
696
    srand((unsigned int) time(NULL));
13 by Björn Påhlsson
Added following support:
697
698
    /* Allocate main loop object */
699
    if (!(simple_poll = avahi_simple_poll_new())) {
700
        fprintf(stderr, "Failed to create simple poll object.\n");
15.1.1 by Björn Påhlsson
Added debugg support in form off --debug and --debug=mandosclient
701
	
702
        goto exit;
13 by Björn Påhlsson
Added following support:
703
    }
704
705
    /* Do not publish any local records */
706
    avahi_server_config_init(&config);
707
    config.publish_hinfo = 0;
708
    config.publish_addresses = 0;
709
    config.publish_workstation = 0;
710
    config.publish_domain = 0;
711
712
    /* Allocate a new server */
21 by Teddy Hogeborn
* Makefile (CFLAGS): Changed to use $(WARN), $(DEBUG), $(COVERAGE) and
713
    server = avahi_server_new(avahi_simple_poll_get(simple_poll),
714
			      &config, NULL, NULL, &error);
13 by Björn Påhlsson
Added following support:
715
716
    /* Free the configuration data */
717
    avahi_server_config_free(&config);
718
15.1.1 by Björn Påhlsson
Added debugg support in form off --debug and --debug=mandosclient
719
    /* Check if creating the server object succeeded */
13 by Björn Påhlsson
Added following support:
720
    if (!server) {
21 by Teddy Hogeborn
* Makefile (CFLAGS): Changed to use $(WARN), $(DEBUG), $(COVERAGE) and
721
        fprintf(stderr, "Failed to create server: %s\n",
722
		avahi_strerror(error));
15.1.1 by Björn Påhlsson
Added debugg support in form off --debug and --debug=mandosclient
723
	returncode = EXIT_FAILURE;
724
        goto exit;
13 by Björn Påhlsson
Added following support:
725
    }
726
    
727
    /* Create the service browser */
21 by Teddy Hogeborn
* Makefile (CFLAGS): Changed to use $(WARN), $(DEBUG), $(COVERAGE) and
728
    sb = avahi_s_service_browser_new(server,
729
				     (AvahiIfIndex)
730
				     if_nametoindex(interface),
731
				     AVAHI_PROTO_INET6,
732
				     "_mandos._tcp", NULL, 0,
733
				     browse_callback, server);
734
    if (!sb) {
735
        fprintf(stderr, "Failed to create service browser: %s\n",
736
		avahi_strerror(avahi_server_errno(server)));
15.1.1 by Björn Påhlsson
Added debugg support in form off --debug and --debug=mandosclient
737
	returncode = EXIT_FAILURE;
738
        goto exit;
13 by Björn Påhlsson
Added following support:
739
    }
740
    
741
    /* Run the main loop */
15.1.1 by Björn Påhlsson
Added debugg support in form off --debug and --debug=mandosclient
742
743
    if (debug){
744
      fprintf(stderr, "Starting avahi loop search\n");
745
    }
746
    
13 by Björn Påhlsson
Added following support:
747
    avahi_simple_poll_loop(simple_poll);
748
    
21 by Teddy Hogeborn
* Makefile (CFLAGS): Changed to use $(WARN), $(DEBUG), $(COVERAGE) and
749
 exit:
15.1.1 by Björn Påhlsson
Added debugg support in form off --debug and --debug=mandosclient
750
751
    if (debug){
752
      fprintf(stderr, "%s exiting\n", argv[0]);
753
    }
13 by Björn Påhlsson
Added following support:
754
    
755
    /* Cleanup things */
756
    if (sb)
757
        avahi_s_service_browser_free(sb);
758
    
759
    if (server)
760
        avahi_server_free(server);
761
762
    if (simple_poll)
763
        avahi_simple_poll_free(simple_poll);
764
15.1.3 by Björn Påhlsson
Added getopt_long support for mandosclient and passprompt
765
    return returncode;
13 by Björn Påhlsson
Added following support:
766
}