/mandos/release

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