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