/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
 * 
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,
29 by Teddy Hogeborn
* plugins.d/mandosclient.c (start_mandos_communication): Changed
346
			       AvahiIfIndex 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
  
29 by Teddy Hogeborn
* plugins.d/mandosclient.c (start_mandos_communication): Changed
370
  if(if_indextoname((unsigned int)if_index, interface) == NULL){
21 by Teddy Hogeborn
* Makefile (CFLAGS): Changed to use $(WARN), $(DEBUG), $(COVERAGE) and
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
      }
29 by Teddy Hogeborn
* plugins.d/mandosclient.c (start_mandos_communication): Changed
567
      int ret = start_mandos_communication(ip, port, interface);
21 by Teddy Hogeborn
* Makefile (CFLAGS): Changed to use $(WARN), $(DEBUG), $(COVERAGE) and
568
      if (ret == 0){
569
	exit(EXIT_SUCCESS);
570
      }
13 by Björn Påhlsson
Added following support:
571
    }
21 by Teddy Hogeborn
* Makefile (CFLAGS): Changed to use $(WARN), $(DEBUG), $(COVERAGE) and
572
  }
573
  avahi_s_service_resolver_free(r);
13 by Björn Påhlsson
Added following support:
574
}
575
576
static void browse_callback(
577
    AvahiSServiceBrowser *b,
578
    AvahiIfIndex interface,
579
    AvahiProtocol protocol,
580
    AvahiBrowserEvent event,
581
    const char *name,
582
    const char *type,
583
    const char *domain,
584
    AVAHI_GCC_UNUSED AvahiLookupResultFlags flags,
585
    void* userdata) {
586
    
587
    AvahiServer *s = userdata;
22 by Teddy Hogeborn
* plugins.d/mandosclient.c (pgp_packet_decrypt): Cast "0" argument to
588
    assert(b);			/* Spurious warning */
589
    
21 by Teddy Hogeborn
* Makefile (CFLAGS): Changed to use $(WARN), $(DEBUG), $(COVERAGE) and
590
    /* Called whenever a new services becomes available on the LAN or
591
       is removed from the LAN */
22 by Teddy Hogeborn
* plugins.d/mandosclient.c (pgp_packet_decrypt): Cast "0" argument to
592
    
13 by Björn Påhlsson
Added following support:
593
    switch (event) {
21 by Teddy Hogeborn
* Makefile (CFLAGS): Changed to use $(WARN), $(DEBUG), $(COVERAGE) and
594
    default:
595
    case AVAHI_BROWSER_FAILURE:
596
      
597
      fprintf(stderr, "(Browser) %s\n",
598
	      avahi_strerror(avahi_server_errno(server)));
599
      avahi_simple_poll_quit(simple_poll);
600
      return;
601
      
602
    case AVAHI_BROWSER_NEW:
603
      /* We ignore the returned resolver object. In the callback
604
	 function we free it. If the server is terminated before
605
	 the callback function is called the server will free
606
	 the resolver for us. */
607
      
608
      if (!(avahi_s_service_resolver_new(s, interface, protocol, name,
609
					 type, domain,
610
					 AVAHI_PROTO_INET6, 0,
611
					 resolve_callback, s)))
612
	fprintf(stderr, "Failed to resolve service '%s': %s\n", name,
613
		avahi_strerror(avahi_server_errno(s)));
614
      break;
615
      
616
    case AVAHI_BROWSER_REMOVE:
617
      break;
618
      
619
    case AVAHI_BROWSER_ALL_FOR_NOW:
620
    case AVAHI_BROWSER_CACHE_EXHAUSTED:
621
      break;
13 by Björn Påhlsson
Added following support:
622
    }
623
}
624
625
int main(AVAHI_GCC_UNUSED int argc, AVAHI_GCC_UNUSED char*argv[]) {
626
    AvahiServerConfig config;
627
    AvahiSServiceBrowser *sb = NULL;
628
    int error;
15.1.3 by Björn Påhlsson
Added getopt_long support for mandosclient and passprompt
629
    int ret;
15.1.1 by Björn Påhlsson
Added debugg support in form off --debug and --debug=mandosclient
630
    int returncode = EXIT_SUCCESS;
29 by Teddy Hogeborn
* plugins.d/mandosclient.c (start_mandos_communication): Changed
631
    const char *interface = NULL;
632
    AvahiIfIndex if_index = AVAHI_IF_UNSPEC;
28 by Teddy Hogeborn
* server.conf: New file.
633
    char *connect_to = NULL;
21 by Teddy Hogeborn
* Makefile (CFLAGS): Changed to use $(WARN), $(DEBUG), $(COVERAGE) and
634
    
15.1.3 by Björn Påhlsson
Added getopt_long support for mandosclient and passprompt
635
    while (true){
636
      static struct option long_options[] = {
637
	{"debug", no_argument, (int *)&debug, 1},
28 by Teddy Hogeborn
* server.conf: New file.
638
	{"connect", required_argument, 0, 'c'},
15.1.3 by Björn Påhlsson
Added getopt_long support for mandosclient and passprompt
639
	{"interface", required_argument, 0, 'i'},
640
	{0, 0, 0, 0} };
22 by Teddy Hogeborn
* plugins.d/mandosclient.c (pgp_packet_decrypt): Cast "0" argument to
641
      
15.1.3 by Björn Påhlsson
Added getopt_long support for mandosclient and passprompt
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);
22 by Teddy Hogeborn
* plugins.d/mandosclient.c (pgp_packet_decrypt): Cast "0" argument to
645
      
15.1.3 by Björn Påhlsson
Added getopt_long support for mandosclient and passprompt
646
      if (ret == -1){
647
	break;
648
      }
649
      
650
      switch(ret){
651
      case 0:
652
	break;
653
      case 'i':
654
	interface = optarg;
655
	break;
28 by Teddy Hogeborn
* server.conf: New file.
656
      case 'c':
657
	connect_to = optarg;
658
	break;
15.1.3 by Björn Påhlsson
Added getopt_long support for mandosclient and passprompt
659
      default:
660
	exit(EXIT_FAILURE);
661
      }
662
    }
663
    
29 by Teddy Hogeborn
* plugins.d/mandosclient.c (start_mandos_communication): Changed
664
    if(interface != NULL){
665
      if_index = (AvahiIfIndex) if_nametoindex(interface);
666
      if(if_index == 0){
667
	fprintf(stderr, "No such interface: \"%s\"\n", interface);
668
	exit(EXIT_FAILURE);
669
      }
28 by Teddy Hogeborn
* server.conf: New file.
670
    }
671
    
672
    if(connect_to != NULL){
673
      /* Connect directly, do not use Zeroconf */
674
      /* (Mainly meant for debugging) */
675
      char *address = strrchr(connect_to, ':');
676
      if(address == NULL){
677
        fprintf(stderr, "No colon in address\n");
678
	exit(EXIT_FAILURE);
679
      }
680
      errno = 0;
681
      uint16_t port = (uint16_t) strtol(address+1, NULL, 10);
682
      if(errno){
683
	perror("Bad port number");
684
	exit(EXIT_FAILURE);
685
      }
686
      *address = '\0';
687
      address = connect_to;
688
      ret = start_mandos_communication(address, port, if_index);
689
      if(ret < 0){
690
	exit(EXIT_FAILURE);
691
      } else {
692
	exit(EXIT_SUCCESS);
693
      }
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 */
29 by Teddy Hogeborn
* plugins.d/mandosclient.c (start_mandos_communication): Changed
733
    sb = avahi_s_service_browser_new(server, if_index,
21 by Teddy Hogeborn
* Makefile (CFLAGS): Changed to use $(WARN), $(DEBUG), $(COVERAGE) and
734
				     AVAHI_PROTO_INET6,
735
				     "_mandos._tcp", NULL, 0,
736
				     browse_callback, server);
737
    if (!sb) {
738
        fprintf(stderr, "Failed to create service browser: %s\n",
739
		avahi_strerror(avahi_server_errno(server)));
15.1.1 by Björn Påhlsson
Added debugg support in form off --debug and --debug=mandosclient
740
	returncode = EXIT_FAILURE;
741
        goto exit;
13 by Björn Påhlsson
Added following support:
742
    }
743
    
744
    /* Run the main loop */
15.1.1 by Björn Påhlsson
Added debugg support in form off --debug and --debug=mandosclient
745
746
    if (debug){
747
      fprintf(stderr, "Starting avahi loop search\n");
748
    }
749
    
13 by Björn Påhlsson
Added following support:
750
    avahi_simple_poll_loop(simple_poll);
751
    
21 by Teddy Hogeborn
* Makefile (CFLAGS): Changed to use $(WARN), $(DEBUG), $(COVERAGE) and
752
 exit:
15.1.1 by Björn Påhlsson
Added debugg support in form off --debug and --debug=mandosclient
753
754
    if (debug){
755
      fprintf(stderr, "%s exiting\n", argv[0]);
756
    }
13 by Björn Påhlsson
Added following support:
757
    
758
    /* Cleanup things */
759
    if (sb)
760
        avahi_s_service_browser_free(sb);
761
    
762
    if (server)
763
        avahi_server_free(server);
764
765
    if (simple_poll)
766
        avahi_simple_poll_free(simple_poll);
767
15.1.3 by Björn Påhlsson
Added getopt_long support for mandosclient and passprompt
768
    return returncode;
13 by Björn Påhlsson
Added following support:
769
}