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