/mandos/trunk

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