/mandos/trunk

To get this branch, use:
bzr branch http://bzr.recompile.se/loggerhead/mandos/trunk

« back to all changes in this revision

Viewing changes to plugins.d/mandos-client.c

  • Committer: Teddy Hogeborn
  • Date: 2008-12-10 01:26:02 UTC
  • mfrom: (237.1.2 mandos)
  • Revision ID: teddy@fukt.bsnet.se-20081210012602-vhz3h75xkj24t340
First version of a somewhat complete D-Bus server interface.  Also
change user/group name to "_mandos".

* debian/mandos.postinst: Rename old "mandos" user and group to
                          "_mandos"; create "_mandos" user and group
                          if none exist.
* debian/mandos-client.postinst: - '' -

* initramfs-tools-hook: Try "_mandos" before "mandos" as user and
                        group name.

* mandos (_datetime_to_dbus_struct): New; was previously local.
  (Client.started): Renamed to "last_started".  All users changed.
  (Client.started): New; boolean.
  (Client.dbus_object_path): New.
  (Client.check_command): Renamed to "checker_command".  All users
                          changed.
  (Client.__init__): Set and use "self.dbus_object_path".  Set
                     "self.started".
  (Client.start): Update "self.started".  Emit "self.PropertyChanged"
                  signals for both "started" and "last_started".
  (Client.stop): Update "self.started".  Emit "self.PropertyChanged"
                 signal for "started".
  (Client.checker_callback): Take additional "command" argument.  All
                             callers changed. Emit
                             "self.PropertyChanged" signal.
  (Client.bump_timeout): Emit "self.PropertyChanged" signal for
                         "last_checked_ok".
  (Client.start_checker): Emit "self.PropertyChanged" signal for
                          "checker_running".
  (Client.stop_checker): Emit "self.PropertyChanged" signal for
                         "checker_running".
  (Client.still_valid): Bug fix: use "getattr(self, started, False)"
                        instead of "self.started" in case this client
                        object is so new that the "started" attribute
                        has not been created yet.
  (Client.IntervalChanged, Client.CheckerIsRunning, Client.GetChecker,
  Client.GetCreated, Client.GetFingerprint, Client.GetHost,
  Client.GetInterval, Client.GetName, Client.GetStarted,
  Client.GetTimeout, Client.StateChanged, Client.TimeoutChanged):
  Removed; all callers changed.
  (Client.CheckerCompleted): Add "condition" and "command" arguments.
                             All callers changed.
  (Client.GetAllProperties, Client.PropertyChanged): New.
  (Client.StillValid): Renamed to "IsStillValid".
  (Client.StartChecker): Changed to its own function to avoid the
                         return value from "Client.start_checker()".
  (Client.Stop): Changed to its own function to avoid the return value
                 from "Client.stop()".
  (main): Try "_mandos" before "mandos" as user and group name.
          Removed inner function "remove_from_clients".  New inner
          class "MandosServer".

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*  -*- coding: utf-8 -*- */
2
2
/*
3
 
 * Mandos-client - get and decrypt data from a Mandos server
 
3
 * Mandos client - get and decrypt data from a Mandos server
4
4
 *
5
5
 * This program is partly derived from an example program for an Avahi
6
6
 * service browser, downloaded from
9
9
 * "browse_callback", and parts of "main".
10
10
 * 
11
11
 * Everything else is
12
 
 * Copyright © 2008,2009 Teddy Hogeborn
13
 
 * Copyright © 2008,2009 Björn Påhlsson
 
12
 * Copyright © 2008 Teddy Hogeborn
 
13
 * Copyright © 2008 Björn Påhlsson
14
14
 * 
15
15
 * This program is free software: you can redistribute it and/or
16
16
 * modify it under the terms of the GNU General Public License as
36
36
#define _GNU_SOURCE             /* TEMP_FAILURE_RETRY(), asprintf() */
37
37
 
38
38
#include <stdio.h>              /* fprintf(), stderr, fwrite(),
39
 
                                   stdout, ferror(), sscanf */
 
39
                                   stdout, ferror() */
40
40
#include <stdint.h>             /* uint16_t, uint32_t */
41
41
#include <stddef.h>             /* NULL, size_t, ssize_t */
42
42
#include <stdlib.h>             /* free(), EXIT_SUCCESS, EXIT_FAILURE,
48
48
#include <sys/types.h>          /* socket(), inet_pton(), sockaddr,
49
49
                                   sockaddr_in6, PF_INET6,
50
50
                                   SOCK_STREAM, INET6_ADDRSTRLEN,
51
 
                                   uid_t, gid_t, open(), opendir(),
52
 
                                   DIR */
 
51
                                   uid_t, gid_t, open(), opendir(), DIR */
53
52
#include <sys/stat.h>           /* open() */
54
53
#include <sys/socket.h>         /* socket(), struct sockaddr_in6,
55
54
                                   struct in6_addr, inet_pton(),
56
55
                                   connect() */
57
56
#include <fcntl.h>              /* open() */
58
 
#include <dirent.h>             /* opendir(), struct dirent, readdir()
59
 
                                 */
60
 
#include <inttypes.h>           /* PRIu16, intmax_t, SCNdMAX */
 
57
#include <dirent.h>             /* opendir(), struct dirent, readdir() */
 
58
#include <inttypes.h>           /* PRIu16 */
61
59
#include <assert.h>             /* assert() */
62
60
#include <errno.h>              /* perror(), errno */
63
61
#include <time.h>               /* time() */
69
67
                                   getuid(), getgid(), setuid(),
70
68
                                   setgid() */
71
69
#include <arpa/inet.h>          /* inet_pton(), htons */
72
 
#include <iso646.h>             /* not, and, or */
 
70
#include <iso646.h>             /* not, and */
73
71
#include <argp.h>               /* struct argp_option, error_t, struct
74
72
                                   argp_state, struct argp,
75
73
                                   argp_parse(), ARGP_KEY_ARG,
92
90
                                   gnutls_*
93
91
                                   init_gnutls_session(),
94
92
                                   GNUTLS_* */
95
 
#include <gnutls/openpgp.h>
96
 
                          /* gnutls_certificate_set_openpgp_key_file(),
 
93
#include <gnutls/openpgp.h>     /* gnutls_certificate_set_openpgp_key_file(),
97
94
                                   GNUTLS_OPENPGP_FMT_BASE64 */
98
95
 
99
96
/* GPGME */
132
129
 */
133
130
size_t adjustbuffer(char **buffer, size_t buffer_length,
134
131
                  size_t buffer_capacity){
135
 
  if(buffer_length + BUFFER_SIZE > buffer_capacity){
 
132
  if (buffer_length + BUFFER_SIZE > buffer_capacity){
136
133
    *buffer = realloc(*buffer, buffer_capacity + BUFFER_SIZE);
137
 
    if(buffer == NULL){
 
134
    if (buffer == NULL){
138
135
      return 0;
139
136
    }
140
137
    buffer_capacity += BUFFER_SIZE;
159
156
    int fd;
160
157
    gpgme_data_t pgp_data;
161
158
    
162
 
    fd = (int)TEMP_FAILURE_RETRY(open(filename, O_RDONLY));
 
159
    fd = TEMP_FAILURE_RETRY(open(filename, O_RDONLY));
163
160
    if(fd == -1){
164
161
      perror("open");
165
162
      return false;
166
163
    }
167
164
    
168
165
    rc = gpgme_data_new_from_fd(&pgp_data, fd);
169
 
    if(rc != GPG_ERR_NO_ERROR){
 
166
    if (rc != GPG_ERR_NO_ERROR){
170
167
      fprintf(stderr, "bad gpgme_data_new_from_fd: %s: %s\n",
171
168
              gpgme_strsource(rc), gpgme_strerror(rc));
172
169
      return false;
173
170
    }
174
171
    
175
172
    rc = gpgme_op_import(mc->ctx, pgp_data);
176
 
    if(rc != GPG_ERR_NO_ERROR){
 
173
    if (rc != GPG_ERR_NO_ERROR){
177
174
      fprintf(stderr, "bad gpgme_op_import: %s: %s\n",
178
175
              gpgme_strsource(rc), gpgme_strerror(rc));
179
176
      return false;
180
177
    }
181
178
    
182
 
    ret = (int)TEMP_FAILURE_RETRY(close(fd));
 
179
    ret = TEMP_FAILURE_RETRY(close(fd));
183
180
    if(ret == -1){
184
181
      perror("close");
185
182
    }
187
184
    return true;
188
185
  }
189
186
  
190
 
  if(debug){
 
187
  if (debug){
191
188
    fprintf(stderr, "Initialize gpgme\n");
192
189
  }
193
190
  
194
191
  /* Init GPGME */
195
192
  gpgme_check_version(NULL);
196
193
  rc = gpgme_engine_check_version(GPGME_PROTOCOL_OpenPGP);
197
 
  if(rc != GPG_ERR_NO_ERROR){
 
194
  if (rc != GPG_ERR_NO_ERROR){
198
195
    fprintf(stderr, "bad gpgme_engine_check_version: %s: %s\n",
199
196
            gpgme_strsource(rc), gpgme_strerror(rc));
200
197
    return false;
201
198
  }
202
199
  
203
200
    /* Set GPGME home directory for the OpenPGP engine only */
204
 
  rc = gpgme_get_engine_info(&engine_info);
205
 
  if(rc != GPG_ERR_NO_ERROR){
 
201
  rc = gpgme_get_engine_info (&engine_info);
 
202
  if (rc != GPG_ERR_NO_ERROR){
206
203
    fprintf(stderr, "bad gpgme_get_engine_info: %s: %s\n",
207
204
            gpgme_strsource(rc), gpgme_strerror(rc));
208
205
    return false;
222
219
  
223
220
  /* Create new GPGME "context" */
224
221
  rc = gpgme_new(&(mc->ctx));
225
 
  if(rc != GPG_ERR_NO_ERROR){
 
222
  if (rc != GPG_ERR_NO_ERROR){
226
223
    fprintf(stderr, "bad gpgme_new: %s: %s\n",
227
224
            gpgme_strsource(rc), gpgme_strerror(rc));
228
225
    return false;
229
226
  }
230
227
  
231
 
  if(not import_key(pubkey) or not import_key(seckey)){
 
228
  if (not import_key(pubkey) or not import_key(seckey)){
232
229
    return false;
233
230
  }
234
231
  
239
236
 * Decrypt OpenPGP data.
240
237
 * Returns -1 on error
241
238
 */
242
 
static ssize_t pgp_packet_decrypt(const mandos_context *mc,
243
 
                                  const char *cryptotext,
244
 
                                  size_t crypto_size,
245
 
                                  char **plaintext){
 
239
static ssize_t pgp_packet_decrypt (const mandos_context *mc,
 
240
                                   const char *cryptotext,
 
241
                                   size_t crypto_size,
 
242
                                   char **plaintext){
246
243
  gpgme_data_t dh_crypto, dh_plain;
247
244
  gpgme_error_t rc;
248
245
  ssize_t ret;
249
246
  size_t plaintext_capacity = 0;
250
247
  ssize_t plaintext_length = 0;
251
248
  
252
 
  if(debug){
 
249
  if (debug){
253
250
    fprintf(stderr, "Trying to decrypt OpenPGP data\n");
254
251
  }
255
252
  
256
253
  /* Create new GPGME data buffer from memory cryptotext */
257
254
  rc = gpgme_data_new_from_mem(&dh_crypto, cryptotext, crypto_size,
258
255
                               0);
259
 
  if(rc != GPG_ERR_NO_ERROR){
 
256
  if (rc != GPG_ERR_NO_ERROR){
260
257
    fprintf(stderr, "bad gpgme_data_new_from_mem: %s: %s\n",
261
258
            gpgme_strsource(rc), gpgme_strerror(rc));
262
259
    return -1;
264
261
  
265
262
  /* Create new empty GPGME data buffer for the plaintext */
266
263
  rc = gpgme_data_new(&dh_plain);
267
 
  if(rc != GPG_ERR_NO_ERROR){
 
264
  if (rc != GPG_ERR_NO_ERROR){
268
265
    fprintf(stderr, "bad gpgme_data_new: %s: %s\n",
269
266
            gpgme_strsource(rc), gpgme_strerror(rc));
270
267
    gpgme_data_release(dh_crypto);
274
271
  /* Decrypt data from the cryptotext data buffer to the plaintext
275
272
     data buffer */
276
273
  rc = gpgme_op_decrypt(mc->ctx, dh_crypto, dh_plain);
277
 
  if(rc != GPG_ERR_NO_ERROR){
 
274
  if (rc != GPG_ERR_NO_ERROR){
278
275
    fprintf(stderr, "bad gpgme_op_decrypt: %s: %s\n",
279
276
            gpgme_strsource(rc), gpgme_strerror(rc));
280
277
    plaintext_length = -1;
281
 
    if(debug){
 
278
    if (debug){
282
279
      gpgme_decrypt_result_t result;
283
280
      result = gpgme_op_decrypt_result(mc->ctx);
284
 
      if(result == NULL){
 
281
      if (result == NULL){
285
282
        fprintf(stderr, "gpgme_op_decrypt_result failed\n");
286
283
      } else {
287
284
        fprintf(stderr, "Unsupported algorithm: %s\n",
314
311
  }
315
312
  
316
313
  /* Seek back to the beginning of the GPGME plaintext data buffer */
317
 
  if(gpgme_data_seek(dh_plain, (off_t)0, SEEK_SET) == -1){
 
314
  if (gpgme_data_seek(dh_plain, (off_t) 0, SEEK_SET) == -1){
318
315
    perror("gpgme_data_seek");
319
316
    plaintext_length = -1;
320
317
    goto decrypt_end;
325
322
    plaintext_capacity = adjustbuffer(plaintext,
326
323
                                      (size_t)plaintext_length,
327
324
                                      plaintext_capacity);
328
 
    if(plaintext_capacity == 0){
 
325
    if (plaintext_capacity == 0){
329
326
        perror("adjustbuffer");
330
327
        plaintext_length = -1;
331
328
        goto decrypt_end;
334
331
    ret = gpgme_data_read(dh_plain, *plaintext + plaintext_length,
335
332
                          BUFFER_SIZE);
336
333
    /* Print the data, if any */
337
 
    if(ret == 0){
 
334
    if (ret == 0){
338
335
      /* EOF */
339
336
      break;
340
337
    }
364
361
  return plaintext_length;
365
362
}
366
363
 
367
 
static const char * safer_gnutls_strerror(int value) {
368
 
  const char *ret = gnutls_strerror(value); /* Spurious warning from
369
 
                                               -Wunreachable-code */
370
 
  if(ret == NULL)
 
364
static const char * safer_gnutls_strerror (int value) {
 
365
  const char *ret = gnutls_strerror (value); /* Spurious warning */
 
366
  if (ret == NULL)
371
367
    ret = "(unknown)";
372
368
  return ret;
373
369
}
388
384
  }
389
385
  
390
386
  ret = gnutls_global_init();
391
 
  if(ret != GNUTLS_E_SUCCESS) {
392
 
    fprintf(stderr, "GnuTLS global_init: %s\n",
393
 
            safer_gnutls_strerror(ret));
 
387
  if (ret != GNUTLS_E_SUCCESS) {
 
388
    fprintf (stderr, "GnuTLS global_init: %s\n",
 
389
             safer_gnutls_strerror(ret));
394
390
    return -1;
395
391
  }
396
392
  
397
 
  if(debug){
 
393
  if (debug){
398
394
    /* "Use a log level over 10 to enable all debugging options."
399
395
     * - GnuTLS manual
400
396
     */
404
400
  
405
401
  /* OpenPGP credentials */
406
402
  gnutls_certificate_allocate_credentials(&mc->cred);
407
 
  if(ret != GNUTLS_E_SUCCESS){
408
 
    fprintf(stderr, "GnuTLS memory error: %s\n", /* Spurious warning
409
 
                                                  * from
410
 
                                                  * -Wunreachable-code
411
 
                                                  */
412
 
            safer_gnutls_strerror(ret));
413
 
    gnutls_global_deinit();
 
403
  if (ret != GNUTLS_E_SUCCESS){
 
404
    fprintf (stderr, "GnuTLS memory error: %s\n", /* Spurious
 
405
                                                     warning */
 
406
             safer_gnutls_strerror(ret));
 
407
    gnutls_global_deinit ();
414
408
    return -1;
415
409
  }
416
410
  
423
417
  ret = gnutls_certificate_set_openpgp_key_file
424
418
    (mc->cred, pubkeyfilename, seckeyfilename,
425
419
     GNUTLS_OPENPGP_FMT_BASE64);
426
 
  if(ret != GNUTLS_E_SUCCESS) {
 
420
  if (ret != GNUTLS_E_SUCCESS) {
427
421
    fprintf(stderr,
428
422
            "Error[%d] while reading the OpenPGP key pair ('%s',"
429
423
            " '%s')\n", ret, pubkeyfilename, seckeyfilename);
434
428
  
435
429
  /* GnuTLS server initialization */
436
430
  ret = gnutls_dh_params_init(&mc->dh_params);
437
 
  if(ret != GNUTLS_E_SUCCESS) {
438
 
    fprintf(stderr, "Error in GnuTLS DH parameter initialization:"
439
 
            " %s\n", safer_gnutls_strerror(ret));
 
431
  if (ret != GNUTLS_E_SUCCESS) {
 
432
    fprintf (stderr, "Error in GnuTLS DH parameter initialization:"
 
433
             " %s\n", safer_gnutls_strerror(ret));
440
434
    goto globalfail;
441
435
  }
442
436
  ret = gnutls_dh_params_generate2(mc->dh_params, mc->dh_bits);
443
 
  if(ret != GNUTLS_E_SUCCESS) {
444
 
    fprintf(stderr, "Error in GnuTLS prime generation: %s\n",
445
 
            safer_gnutls_strerror(ret));
 
437
  if (ret != GNUTLS_E_SUCCESS) {
 
438
    fprintf (stderr, "Error in GnuTLS prime generation: %s\n",
 
439
             safer_gnutls_strerror(ret));
446
440
    goto globalfail;
447
441
  }
448
442
  
463
457
  int ret;
464
458
  /* GnuTLS session creation */
465
459
  ret = gnutls_init(session, GNUTLS_SERVER);
466
 
  if(ret != GNUTLS_E_SUCCESS){
 
460
  if (ret != GNUTLS_E_SUCCESS){
467
461
    fprintf(stderr, "Error in GnuTLS session initialization: %s\n",
468
462
            safer_gnutls_strerror(ret));
469
463
  }
471
465
  {
472
466
    const char *err;
473
467
    ret = gnutls_priority_set_direct(*session, mc->priority, &err);
474
 
    if(ret != GNUTLS_E_SUCCESS) {
 
468
    if (ret != GNUTLS_E_SUCCESS) {
475
469
      fprintf(stderr, "Syntax error at: %s\n", err);
476
470
      fprintf(stderr, "GnuTLS error: %s\n",
477
471
              safer_gnutls_strerror(ret));
478
 
      gnutls_deinit(*session);
 
472
      gnutls_deinit (*session);
479
473
      return -1;
480
474
    }
481
475
  }
482
476
  
483
477
  ret = gnutls_credentials_set(*session, GNUTLS_CRD_CERTIFICATE,
484
478
                               mc->cred);
485
 
  if(ret != GNUTLS_E_SUCCESS) {
 
479
  if (ret != GNUTLS_E_SUCCESS) {
486
480
    fprintf(stderr, "Error setting GnuTLS credentials: %s\n",
487
481
            safer_gnutls_strerror(ret));
488
 
    gnutls_deinit(*session);
 
482
    gnutls_deinit (*session);
489
483
    return -1;
490
484
  }
491
485
  
492
486
  /* ignore client certificate if any. */
493
 
  gnutls_certificate_server_set_request(*session,
494
 
                                        GNUTLS_CERT_IGNORE);
 
487
  gnutls_certificate_server_set_request (*session,
 
488
                                         GNUTLS_CERT_IGNORE);
495
489
  
496
 
  gnutls_dh_set_prime_bits(*session, mc->dh_bits);
 
490
  gnutls_dh_set_prime_bits (*session, mc->dh_bits);
497
491
  
498
492
  return 0;
499
493
}
507
501
                                      AvahiIfIndex if_index,
508
502
                                      mandos_context *mc){
509
503
  int ret, tcp_sd;
510
 
  ssize_t sret;
511
504
  union { struct sockaddr in; struct sockaddr_in6 in6; } to;
512
505
  char *buffer = NULL;
513
506
  char *decrypted_buffer;
519
512
  char interface[IF_NAMESIZE];
520
513
  gnutls_session_t session;
521
514
  
522
 
  ret = init_gnutls_session(mc, &session);
523
 
  if(ret != 0){
 
515
  ret = init_gnutls_session (mc, &session);
 
516
  if (ret != 0){
524
517
    return -1;
525
518
  }
526
519
  
548
541
  /* It would be nice to have a way to detect if we were passed an
549
542
     IPv4 address here.   Now we assume an IPv6 address. */
550
543
  ret = inet_pton(AF_INET6, ip, &to.in6.sin6_addr);
551
 
  if(ret < 0 ){
 
544
  if (ret < 0 ){
552
545
    perror("inet_pton");
553
546
    return -1;
554
547
  }
556
549
    fprintf(stderr, "Bad address: %s\n", ip);
557
550
    return -1;
558
551
  }
559
 
  to.in6.sin6_port = htons(port); /* Spurious warnings from
560
 
                                     -Wconversion and
561
 
                                     -Wunreachable-code */
 
552
  to.in6.sin6_port = htons(port); /* Spurious warning */
562
553
  
563
554
  to.in6.sin6_scope_id = (uint32_t)if_index;
564
555
  
577
568
  }
578
569
  
579
570
  ret = connect(tcp_sd, &to.in, sizeof(to));
580
 
  if(ret < 0){
 
571
  if (ret < 0){
581
572
    perror("connect");
582
573
    return -1;
583
574
  }
584
575
  
585
576
  const char *out = mandos_protocol_version;
586
577
  written = 0;
587
 
  while(true){
 
578
  while (true){
588
579
    size_t out_size = strlen(out);
589
 
    ret = (int)TEMP_FAILURE_RETRY(write(tcp_sd, out + written,
 
580
    ret = TEMP_FAILURE_RETRY(write(tcp_sd, out + written,
590
581
                                   out_size - written));
591
 
    if(ret == -1){
 
582
    if (ret == -1){
592
583
      perror("write");
593
584
      retval = -1;
594
585
      goto mandos_end;
597
588
    if(written < out_size){
598
589
      continue;
599
590
    } else {
600
 
      if(out == mandos_protocol_version){
 
591
      if (out == mandos_protocol_version){
601
592
        written = 0;
602
593
        out = "\r\n";
603
594
      } else {
610
601
    fprintf(stderr, "Establishing TLS session with %s\n", ip);
611
602
  }
612
603
  
613
 
  gnutls_transport_set_ptr(session, (gnutls_transport_ptr_t) tcp_sd);
 
604
  gnutls_transport_set_ptr (session, (gnutls_transport_ptr_t) tcp_sd);
614
605
  
615
606
  do{
616
 
    ret = gnutls_handshake(session);
 
607
    ret = gnutls_handshake (session);
617
608
  } while(ret == GNUTLS_E_AGAIN or ret == GNUTLS_E_INTERRUPTED);
618
609
  
619
 
  if(ret != GNUTLS_E_SUCCESS){
 
610
  if (ret != GNUTLS_E_SUCCESS){
620
611
    if(debug){
621
612
      fprintf(stderr, "*** GnuTLS Handshake failed ***\n");
622
 
      gnutls_perror(ret);
 
613
      gnutls_perror (ret);
623
614
    }
624
615
    retval = -1;
625
616
    goto mandos_end;
635
626
  while(true){
636
627
    buffer_capacity = adjustbuffer(&buffer, buffer_length,
637
628
                                   buffer_capacity);
638
 
    if(buffer_capacity == 0){
 
629
    if (buffer_capacity == 0){
639
630
      perror("adjustbuffer");
640
631
      retval = -1;
641
632
      goto mandos_end;
642
633
    }
643
634
    
644
 
    sret = gnutls_record_recv(session, buffer+buffer_length,
645
 
                              BUFFER_SIZE);
646
 
    if(sret == 0){
 
635
    ret = gnutls_record_recv(session, buffer+buffer_length,
 
636
                             BUFFER_SIZE);
 
637
    if (ret == 0){
647
638
      break;
648
639
    }
649
 
    if(sret < 0){
650
 
      switch(sret){
 
640
    if (ret < 0){
 
641
      switch(ret){
651
642
      case GNUTLS_E_INTERRUPTED:
652
643
      case GNUTLS_E_AGAIN:
653
644
        break;
654
645
      case GNUTLS_E_REHANDSHAKE:
655
646
        do{
656
 
          ret = gnutls_handshake(session);
 
647
          ret = gnutls_handshake (session);
657
648
        } while(ret == GNUTLS_E_AGAIN or ret == GNUTLS_E_INTERRUPTED);
658
 
        if(ret < 0){
 
649
        if (ret < 0){
659
650
          fprintf(stderr, "*** GnuTLS Re-handshake failed ***\n");
660
 
          gnutls_perror(ret);
 
651
          gnutls_perror (ret);
661
652
          retval = -1;
662
653
          goto mandos_end;
663
654
        }
666
657
        fprintf(stderr, "Unknown error while reading data from"
667
658
                " encrypted session with Mandos server\n");
668
659
        retval = -1;
669
 
        gnutls_bye(session, GNUTLS_SHUT_RDWR);
 
660
        gnutls_bye (session, GNUTLS_SHUT_RDWR);
670
661
        goto mandos_end;
671
662
      }
672
663
    } else {
673
 
      buffer_length += (size_t) sret;
 
664
      buffer_length += (size_t) ret;
674
665
    }
675
666
  }
676
667
  
678
669
    fprintf(stderr, "Closing TLS session\n");
679
670
  }
680
671
  
681
 
  gnutls_bye(session, GNUTLS_SHUT_RDWR);
 
672
  gnutls_bye (session, GNUTLS_SHUT_RDWR);
682
673
  
683
 
  if(buffer_length > 0){
 
674
  if (buffer_length > 0){
684
675
    decrypted_buffer_size = pgp_packet_decrypt(mc, buffer,
685
676
                                               buffer_length,
686
677
                                               &decrypted_buffer);
687
 
    if(decrypted_buffer_size >= 0){
 
678
    if (decrypted_buffer_size >= 0){
688
679
      written = 0;
689
680
      while(written < (size_t) decrypted_buffer_size){
690
 
        ret = (int)fwrite(decrypted_buffer + written, 1,
691
 
                          (size_t)decrypted_buffer_size - written,
692
 
                          stdout);
 
681
        ret = (int)fwrite (decrypted_buffer + written, 1,
 
682
                           (size_t)decrypted_buffer_size - written,
 
683
                           stdout);
693
684
        if(ret == 0 and ferror(stdout)){
694
685
          if(debug){
695
686
            fprintf(stderr, "Error writing encrypted data: %s\n",
712
703
  
713
704
 mandos_end:
714
705
  free(buffer);
715
 
  ret = (int)TEMP_FAILURE_RETRY(close(tcp_sd));
 
706
  ret = TEMP_FAILURE_RETRY(close(tcp_sd));
716
707
  if(ret == -1){
717
708
    perror("close");
718
709
  }
719
 
  gnutls_deinit(session);
 
710
  gnutls_deinit (session);
720
711
  return retval;
721
712
}
722
713
 
740
731
  /* Called whenever a service has been resolved successfully or
741
732
     timed out */
742
733
  
743
 
  switch(event) {
 
734
  switch (event) {
744
735
  default:
745
736
  case AVAHI_RESOLVER_FAILURE:
746
737
    fprintf(stderr, "(Avahi Resolver) Failed to resolve service '%s'"
754
745
      avahi_address_snprint(ip, sizeof(ip), address);
755
746
      if(debug){
756
747
        fprintf(stderr, "Mandos server \"%s\" found on %s (%s, %"
757
 
                PRIdMAX ") on port %" PRIu16 "\n", name, host_name,
758
 
                ip, (intmax_t)interface, port);
 
748
                PRIu16 ") on port %d\n", name, host_name, ip,
 
749
                interface, port);
759
750
      }
760
751
      int ret = start_mandos_communication(ip, port, interface, mc);
761
 
      if(ret == 0){
 
752
      if (ret == 0){
762
753
        avahi_simple_poll_quit(mc->simple_poll);
763
754
      }
764
755
    }
782
773
  /* Called whenever a new services becomes available on the LAN or
783
774
     is removed from the LAN */
784
775
  
785
 
  switch(event) {
 
776
  switch (event) {
786
777
  default:
787
778
  case AVAHI_BROWSER_FAILURE:
788
779
    
797
788
       the callback function is called the Avahi server will free the
798
789
       resolver for us. */
799
790
    
800
 
    if(!(avahi_s_service_resolver_new(mc->server, interface,
 
791
    if (!(avahi_s_service_resolver_new(mc->server, interface,
801
792
                                       protocol, name, type, domain,
802
793
                                       AVAHI_PROTO_INET6, 0,
803
794
                                       resolve_callback, mc)))
821
812
    AvahiSServiceBrowser *sb = NULL;
822
813
    int error;
823
814
    int ret;
824
 
    intmax_t tmpmax;
825
 
    int numchars;
826
815
    int exitcode = EXIT_SUCCESS;
827
816
    const char *interface = "eth0";
828
817
    struct ifreq network;
838
827
    mandos_context mc = { .simple_poll = NULL, .server = NULL,
839
828
                          .dh_bits = 1024, .priority = "SECURE256"
840
829
                          ":!CTYPE-X.509:+CTYPE-OPENPGP" };
841
 
    bool gnutls_initialized = false;
842
 
    bool gpgme_initialized = false;
 
830
    bool gnutls_initalized = false;
 
831
    bool gpgme_initalized = false;
843
832
    
844
833
    {
845
834
      struct argp_option options[] = {
874
863
        { .name = NULL }
875
864
      };
876
865
      
877
 
      error_t parse_opt(int key, char *arg,
878
 
                        struct argp_state *state) {
879
 
        switch(key) {
 
866
      error_t parse_opt (int key, char *arg,
 
867
                         struct argp_state *state) {
 
868
        /* Get the INPUT argument from `argp_parse', which we know is
 
869
           a pointer to our plugin list pointer. */
 
870
        switch (key) {
880
871
        case 128:               /* --debug */
881
872
          debug = true;
882
873
          break;
893
884
          pubkey = arg;
894
885
          break;
895
886
        case 129:               /* --dh-bits */
896
 
          ret = sscanf(arg, "%" SCNdMAX "%n", &tmpmax, &numchars);
897
 
          if(ret < 1 or tmpmax != (typeof(mc.dh_bits))tmpmax
898
 
             or arg[numchars] != '\0'){
899
 
            fprintf(stderr, "Bad number of DH bits\n");
 
887
          errno = 0;
 
888
          mc.dh_bits = (unsigned int) strtol(arg, NULL, 10);
 
889
          if (errno){
 
890
            perror("strtol");
900
891
            exit(EXIT_FAILURE);
901
892
          }
902
 
          mc.dh_bits = (typeof(mc.dh_bits))tmpmax;
903
893
          break;
904
894
        case 130:               /* --priority */
905
895
          mc.priority = arg;
906
896
          break;
907
897
        case ARGP_KEY_ARG:
908
 
          argp_usage(state);
 
898
          argp_usage (state);
909
899
        case ARGP_KEY_END:
910
900
          break;
911
901
        default:
918
908
                           .args_doc = "",
919
909
                           .doc = "Mandos client -- Get and decrypt"
920
910
                           " passwords from a Mandos server" };
921
 
      ret = argp_parse(&argp, argc, argv, 0, 0, NULL);
922
 
      if(ret == ARGP_ERR_UNKNOWN){
 
911
      ret = argp_parse (&argp, argc, argv, 0, 0, NULL);
 
912
      if (ret == ARGP_ERR_UNKNOWN){
923
913
        fprintf(stderr, "Unknown error while parsing arguments\n");
924
914
        exitcode = EXIT_FAILURE;
925
915
        goto end;
950
940
          goto end;
951
941
        }
952
942
      }
953
 
      ret = (int)TEMP_FAILURE_RETRY(close(sd));
 
943
      ret = TEMP_FAILURE_RETRY(close(sd));
954
944
      if(ret == -1){
955
945
        perror("close");
956
946
      }
960
950
    gid = getgid();
961
951
    
962
952
    ret = setuid(uid);
963
 
    if(ret == -1){
 
953
    if (ret == -1){
964
954
      perror("setuid");
965
955
    }
966
956
    
967
957
    setgid(gid);
968
 
    if(ret == -1){
 
958
    if (ret == -1){
969
959
      perror("setgid");
970
960
    }
971
961
    
972
962
    ret = init_gnutls_global(&mc, pubkey, seckey);
973
 
    if(ret == -1){
 
963
    if (ret == -1){
974
964
      fprintf(stderr, "init_gnutls_global failed\n");
975
965
      exitcode = EXIT_FAILURE;
976
966
      goto end;
977
967
    } else {
978
 
      gnutls_initialized = true;
 
968
      gnutls_initalized = true;
979
969
    }
980
970
    
981
971
    if(mkdtemp(tempdir) == NULL){
985
975
    }
986
976
    
987
977
    if(not init_gpgme(&mc, pubkey, seckey, tempdir)){
988
 
      fprintf(stderr, "init_gpgme failed\n");
 
978
      fprintf(stderr, "gpgme_initalized failed\n");
989
979
      exitcode = EXIT_FAILURE;
990
980
      goto end;
991
981
    } else {
992
 
      gpgme_initialized = true;
 
982
      gpgme_initalized = true;
993
983
    }
994
984
    
995
985
    if_index = (AvahiIfIndex) if_nametoindex(interface);
1007
997
        exitcode = EXIT_FAILURE;
1008
998
        goto end;
1009
999
      }
1010
 
      uint16_t port;
1011
 
      ret = sscanf(address+1, "%" SCNdMAX "%n", &tmpmax, &numchars);
1012
 
      if(ret < 1 or tmpmax != (uint16_t)tmpmax
1013
 
         or address[numchars+1] != '\0'){
1014
 
        fprintf(stderr, "Bad port number\n");
 
1000
      errno = 0;
 
1001
      uint16_t port = (uint16_t) strtol(address+1, NULL, 10);
 
1002
      if(errno){
 
1003
        perror("Bad port number");
1015
1004
        exitcode = EXIT_FAILURE;
1016
1005
        goto end;
1017
1006
      }
1018
 
      port = (uint16_t)tmpmax;
1019
1007
      *address = '\0';
1020
1008
      address = connect_to;
1021
1009
      ret = start_mandos_communication(address, port, if_index, &mc);
1027
1015
      goto end;
1028
1016
    }
1029
1017
    
1030
 
    if(not debug){
 
1018
    if (not debug){
1031
1019
      avahi_set_log_function(empty_log);
1032
1020
    }
1033
1021
    
1036
1024
    
1037
1025
    /* Allocate main Avahi loop object */
1038
1026
    mc.simple_poll = avahi_simple_poll_new();
1039
 
    if(mc.simple_poll == NULL) {
 
1027
    if (mc.simple_poll == NULL) {
1040
1028
        fprintf(stderr, "Avahi: Failed to create simple poll"
1041
1029
                " object.\n");
1042
1030
        exitcode = EXIT_FAILURE;
1062
1050
    }
1063
1051
    
1064
1052
    /* Check if creating the Avahi server object succeeded */
1065
 
    if(mc.server == NULL) {
 
1053
    if (mc.server == NULL) {
1066
1054
        fprintf(stderr, "Failed to create Avahi server: %s\n",
1067
1055
                avahi_strerror(error));
1068
1056
        exitcode = EXIT_FAILURE;
1074
1062
                                     AVAHI_PROTO_INET6,
1075
1063
                                     "_mandos._tcp", NULL, 0,
1076
1064
                                     browse_callback, &mc);
1077
 
    if(sb == NULL) {
 
1065
    if (sb == NULL) {
1078
1066
        fprintf(stderr, "Failed to create service browser: %s\n",
1079
1067
                avahi_strerror(avahi_server_errno(mc.server)));
1080
1068
        exitcode = EXIT_FAILURE;
1083
1071
    
1084
1072
    /* Run the main loop */
1085
1073
    
1086
 
    if(debug){
 
1074
    if (debug){
1087
1075
      fprintf(stderr, "Starting Avahi loop search\n");
1088
1076
    }
1089
1077
    
1091
1079
    
1092
1080
 end:
1093
1081
    
1094
 
    if(debug){
 
1082
    if (debug){
1095
1083
      fprintf(stderr, "%s exiting\n", argv[0]);
1096
1084
    }
1097
1085
    
1098
1086
    /* Cleanup things */
1099
 
    if(sb != NULL)
 
1087
    if (sb != NULL)
1100
1088
        avahi_s_service_browser_free(sb);
1101
1089
    
1102
 
    if(mc.server != NULL)
 
1090
    if (mc.server != NULL)
1103
1091
        avahi_server_free(mc.server);
1104
1092
    
1105
 
    if(mc.simple_poll != NULL)
 
1093
    if (mc.simple_poll != NULL)
1106
1094
        avahi_simple_poll_free(mc.simple_poll);
1107
1095
    
1108
 
    if(gnutls_initialized){
 
1096
    if (gnutls_initalized){
1109
1097
      gnutls_certificate_free_credentials(mc.cred);
1110
 
      gnutls_global_deinit();
 
1098
      gnutls_global_deinit ();
1111
1099
      gnutls_dh_params_deinit(mc.dh_params);
1112
1100
    }
1113
1101
    
1114
 
    if(gpgme_initialized){
 
1102
    if(gpgme_initalized){
1115
1103
      gpgme_release(mc.ctx);
1116
1104
    }
1117
1105
    
1121
1109
      struct dirent *direntry;
1122
1110
      d = opendir(tempdir);
1123
1111
      if(d == NULL){
1124
 
        if(errno != ENOENT){
1125
 
          perror("opendir");
1126
 
        }
 
1112
        perror("opendir");
1127
1113
      } else {
1128
1114
        while(true){
1129
1115
          direntry = readdir(d);
1130
1116
          if(direntry == NULL){
1131
1117
            break;
1132
1118
          }
1133
 
          if(direntry->d_type == DT_REG){
 
1119
          if (direntry->d_type == DT_REG){
1134
1120
            char *fullname = NULL;
1135
1121
            ret = asprintf(&fullname, "%s/%s", tempdir,
1136
1122
                           direntry->d_name);
1149
1135
        closedir(d);
1150
1136
      }
1151
1137
      ret = rmdir(tempdir);
1152
 
      if(ret == -1 and errno != ENOENT){
 
1138
      if(ret == -1){
1153
1139
        perror("rmdir");
1154
1140
      }
1155
1141
    }