/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, SCNu16 */
 
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 */
369
 
  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)
370
367
    ret = "(unknown)";
371
368
  return ret;
372
369
}
387
384
  }
388
385
  
389
386
  ret = gnutls_global_init();
390
 
  if(ret != GNUTLS_E_SUCCESS) {
391
 
    fprintf(stderr, "GnuTLS global_init: %s\n",
392
 
            safer_gnutls_strerror(ret));
 
387
  if (ret != GNUTLS_E_SUCCESS) {
 
388
    fprintf (stderr, "GnuTLS global_init: %s\n",
 
389
             safer_gnutls_strerror(ret));
393
390
    return -1;
394
391
  }
395
392
  
396
 
  if(debug){
 
393
  if (debug){
397
394
    /* "Use a log level over 10 to enable all debugging options."
398
395
     * - GnuTLS manual
399
396
     */
403
400
  
404
401
  /* OpenPGP credentials */
405
402
  gnutls_certificate_allocate_credentials(&mc->cred);
406
 
  if(ret != GNUTLS_E_SUCCESS){
407
 
    fprintf(stderr, "GnuTLS memory error: %s\n", /* Spurious
408
 
                                                    warning */
409
 
            safer_gnutls_strerror(ret));
410
 
    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 ();
411
408
    return -1;
412
409
  }
413
410
  
420
417
  ret = gnutls_certificate_set_openpgp_key_file
421
418
    (mc->cred, pubkeyfilename, seckeyfilename,
422
419
     GNUTLS_OPENPGP_FMT_BASE64);
423
 
  if(ret != GNUTLS_E_SUCCESS) {
 
420
  if (ret != GNUTLS_E_SUCCESS) {
424
421
    fprintf(stderr,
425
422
            "Error[%d] while reading the OpenPGP key pair ('%s',"
426
423
            " '%s')\n", ret, pubkeyfilename, seckeyfilename);
431
428
  
432
429
  /* GnuTLS server initialization */
433
430
  ret = gnutls_dh_params_init(&mc->dh_params);
434
 
  if(ret != GNUTLS_E_SUCCESS) {
435
 
    fprintf(stderr, "Error in GnuTLS DH parameter initialization:"
436
 
            " %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));
437
434
    goto globalfail;
438
435
  }
439
436
  ret = gnutls_dh_params_generate2(mc->dh_params, mc->dh_bits);
440
 
  if(ret != GNUTLS_E_SUCCESS) {
441
 
    fprintf(stderr, "Error in GnuTLS prime generation: %s\n",
442
 
            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));
443
440
    goto globalfail;
444
441
  }
445
442
  
460
457
  int ret;
461
458
  /* GnuTLS session creation */
462
459
  ret = gnutls_init(session, GNUTLS_SERVER);
463
 
  if(ret != GNUTLS_E_SUCCESS){
 
460
  if (ret != GNUTLS_E_SUCCESS){
464
461
    fprintf(stderr, "Error in GnuTLS session initialization: %s\n",
465
462
            safer_gnutls_strerror(ret));
466
463
  }
468
465
  {
469
466
    const char *err;
470
467
    ret = gnutls_priority_set_direct(*session, mc->priority, &err);
471
 
    if(ret != GNUTLS_E_SUCCESS) {
 
468
    if (ret != GNUTLS_E_SUCCESS) {
472
469
      fprintf(stderr, "Syntax error at: %s\n", err);
473
470
      fprintf(stderr, "GnuTLS error: %s\n",
474
471
              safer_gnutls_strerror(ret));
475
 
      gnutls_deinit(*session);
 
472
      gnutls_deinit (*session);
476
473
      return -1;
477
474
    }
478
475
  }
479
476
  
480
477
  ret = gnutls_credentials_set(*session, GNUTLS_CRD_CERTIFICATE,
481
478
                               mc->cred);
482
 
  if(ret != GNUTLS_E_SUCCESS) {
 
479
  if (ret != GNUTLS_E_SUCCESS) {
483
480
    fprintf(stderr, "Error setting GnuTLS credentials: %s\n",
484
481
            safer_gnutls_strerror(ret));
485
 
    gnutls_deinit(*session);
 
482
    gnutls_deinit (*session);
486
483
    return -1;
487
484
  }
488
485
  
489
486
  /* ignore client certificate if any. */
490
 
  gnutls_certificate_server_set_request(*session,
491
 
                                        GNUTLS_CERT_IGNORE);
 
487
  gnutls_certificate_server_set_request (*session,
 
488
                                         GNUTLS_CERT_IGNORE);
492
489
  
493
 
  gnutls_dh_set_prime_bits(*session, mc->dh_bits);
 
490
  gnutls_dh_set_prime_bits (*session, mc->dh_bits);
494
491
  
495
492
  return 0;
496
493
}
504
501
                                      AvahiIfIndex if_index,
505
502
                                      mandos_context *mc){
506
503
  int ret, tcp_sd;
507
 
  ssize_t sret;
508
504
  union { struct sockaddr in; struct sockaddr_in6 in6; } to;
509
505
  char *buffer = NULL;
510
506
  char *decrypted_buffer;
516
512
  char interface[IF_NAMESIZE];
517
513
  gnutls_session_t session;
518
514
  
519
 
  ret = init_gnutls_session(mc, &session);
520
 
  if(ret != 0){
 
515
  ret = init_gnutls_session (mc, &session);
 
516
  if (ret != 0){
521
517
    return -1;
522
518
  }
523
519
  
545
541
  /* It would be nice to have a way to detect if we were passed an
546
542
     IPv4 address here.   Now we assume an IPv6 address. */
547
543
  ret = inet_pton(AF_INET6, ip, &to.in6.sin6_addr);
548
 
  if(ret < 0 ){
 
544
  if (ret < 0 ){
549
545
    perror("inet_pton");
550
546
    return -1;
551
547
  }
572
568
  }
573
569
  
574
570
  ret = connect(tcp_sd, &to.in, sizeof(to));
575
 
  if(ret < 0){
 
571
  if (ret < 0){
576
572
    perror("connect");
577
573
    return -1;
578
574
  }
579
575
  
580
576
  const char *out = mandos_protocol_version;
581
577
  written = 0;
582
 
  while(true){
 
578
  while (true){
583
579
    size_t out_size = strlen(out);
584
 
    ret = (int)TEMP_FAILURE_RETRY(write(tcp_sd, out + written,
 
580
    ret = TEMP_FAILURE_RETRY(write(tcp_sd, out + written,
585
581
                                   out_size - written));
586
 
    if(ret == -1){
 
582
    if (ret == -1){
587
583
      perror("write");
588
584
      retval = -1;
589
585
      goto mandos_end;
592
588
    if(written < out_size){
593
589
      continue;
594
590
    } else {
595
 
      if(out == mandos_protocol_version){
 
591
      if (out == mandos_protocol_version){
596
592
        written = 0;
597
593
        out = "\r\n";
598
594
      } else {
605
601
    fprintf(stderr, "Establishing TLS session with %s\n", ip);
606
602
  }
607
603
  
608
 
  gnutls_transport_set_ptr(session, (gnutls_transport_ptr_t) tcp_sd);
 
604
  gnutls_transport_set_ptr (session, (gnutls_transport_ptr_t) tcp_sd);
609
605
  
610
606
  do{
611
 
    ret = gnutls_handshake(session);
 
607
    ret = gnutls_handshake (session);
612
608
  } while(ret == GNUTLS_E_AGAIN or ret == GNUTLS_E_INTERRUPTED);
613
609
  
614
 
  if(ret != GNUTLS_E_SUCCESS){
 
610
  if (ret != GNUTLS_E_SUCCESS){
615
611
    if(debug){
616
612
      fprintf(stderr, "*** GnuTLS Handshake failed ***\n");
617
 
      gnutls_perror(ret);
 
613
      gnutls_perror (ret);
618
614
    }
619
615
    retval = -1;
620
616
    goto mandos_end;
630
626
  while(true){
631
627
    buffer_capacity = adjustbuffer(&buffer, buffer_length,
632
628
                                   buffer_capacity);
633
 
    if(buffer_capacity == 0){
 
629
    if (buffer_capacity == 0){
634
630
      perror("adjustbuffer");
635
631
      retval = -1;
636
632
      goto mandos_end;
637
633
    }
638
634
    
639
 
    sret = gnutls_record_recv(session, buffer+buffer_length,
640
 
                              BUFFER_SIZE);
641
 
    if(sret == 0){
 
635
    ret = gnutls_record_recv(session, buffer+buffer_length,
 
636
                             BUFFER_SIZE);
 
637
    if (ret == 0){
642
638
      break;
643
639
    }
644
 
    if(sret < 0){
645
 
      switch(sret){
 
640
    if (ret < 0){
 
641
      switch(ret){
646
642
      case GNUTLS_E_INTERRUPTED:
647
643
      case GNUTLS_E_AGAIN:
648
644
        break;
649
645
      case GNUTLS_E_REHANDSHAKE:
650
646
        do{
651
 
          ret = gnutls_handshake(session);
 
647
          ret = gnutls_handshake (session);
652
648
        } while(ret == GNUTLS_E_AGAIN or ret == GNUTLS_E_INTERRUPTED);
653
 
        if(ret < 0){
 
649
        if (ret < 0){
654
650
          fprintf(stderr, "*** GnuTLS Re-handshake failed ***\n");
655
 
          gnutls_perror(ret);
 
651
          gnutls_perror (ret);
656
652
          retval = -1;
657
653
          goto mandos_end;
658
654
        }
661
657
        fprintf(stderr, "Unknown error while reading data from"
662
658
                " encrypted session with Mandos server\n");
663
659
        retval = -1;
664
 
        gnutls_bye(session, GNUTLS_SHUT_RDWR);
 
660
        gnutls_bye (session, GNUTLS_SHUT_RDWR);
665
661
        goto mandos_end;
666
662
      }
667
663
    } else {
668
 
      buffer_length += (size_t) sret;
 
664
      buffer_length += (size_t) ret;
669
665
    }
670
666
  }
671
667
  
673
669
    fprintf(stderr, "Closing TLS session\n");
674
670
  }
675
671
  
676
 
  gnutls_bye(session, GNUTLS_SHUT_RDWR);
 
672
  gnutls_bye (session, GNUTLS_SHUT_RDWR);
677
673
  
678
 
  if(buffer_length > 0){
 
674
  if (buffer_length > 0){
679
675
    decrypted_buffer_size = pgp_packet_decrypt(mc, buffer,
680
676
                                               buffer_length,
681
677
                                               &decrypted_buffer);
682
 
    if(decrypted_buffer_size >= 0){
 
678
    if (decrypted_buffer_size >= 0){
683
679
      written = 0;
684
680
      while(written < (size_t) decrypted_buffer_size){
685
 
        ret = (int)fwrite(decrypted_buffer + written, 1,
686
 
                          (size_t)decrypted_buffer_size - written,
687
 
                          stdout);
 
681
        ret = (int)fwrite (decrypted_buffer + written, 1,
 
682
                           (size_t)decrypted_buffer_size - written,
 
683
                           stdout);
688
684
        if(ret == 0 and ferror(stdout)){
689
685
          if(debug){
690
686
            fprintf(stderr, "Error writing encrypted data: %s\n",
707
703
  
708
704
 mandos_end:
709
705
  free(buffer);
710
 
  ret = (int)TEMP_FAILURE_RETRY(close(tcp_sd));
 
706
  ret = TEMP_FAILURE_RETRY(close(tcp_sd));
711
707
  if(ret == -1){
712
708
    perror("close");
713
709
  }
714
 
  gnutls_deinit(session);
 
710
  gnutls_deinit (session);
715
711
  return retval;
716
712
}
717
713
 
735
731
  /* Called whenever a service has been resolved successfully or
736
732
     timed out */
737
733
  
738
 
  switch(event) {
 
734
  switch (event) {
739
735
  default:
740
736
  case AVAHI_RESOLVER_FAILURE:
741
737
    fprintf(stderr, "(Avahi Resolver) Failed to resolve service '%s'"
753
749
                interface, port);
754
750
      }
755
751
      int ret = start_mandos_communication(ip, port, interface, mc);
756
 
      if(ret == 0){
 
752
      if (ret == 0){
757
753
        avahi_simple_poll_quit(mc->simple_poll);
758
754
      }
759
755
    }
777
773
  /* Called whenever a new services becomes available on the LAN or
778
774
     is removed from the LAN */
779
775
  
780
 
  switch(event) {
 
776
  switch (event) {
781
777
  default:
782
778
  case AVAHI_BROWSER_FAILURE:
783
779
    
792
788
       the callback function is called the Avahi server will free the
793
789
       resolver for us. */
794
790
    
795
 
    if(!(avahi_s_service_resolver_new(mc->server, interface,
 
791
    if (!(avahi_s_service_resolver_new(mc->server, interface,
796
792
                                       protocol, name, type, domain,
797
793
                                       AVAHI_PROTO_INET6, 0,
798
794
                                       resolve_callback, mc)))
867
863
        { .name = NULL }
868
864
      };
869
865
      
870
 
      error_t parse_opt(int key, char *arg,
871
 
                        struct argp_state *state) {
872
 
        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) {
873
871
        case 128:               /* --debug */
874
872
          debug = true;
875
873
          break;
886
884
          pubkey = arg;
887
885
          break;
888
886
        case 129:               /* --dh-bits */
889
 
          ret = sscanf(arg, "%u", &mc.dh_bits);
890
 
          if(ret != 1){
891
 
            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");
892
891
            exit(EXIT_FAILURE);
893
892
          }
894
893
          break;
896
895
          mc.priority = arg;
897
896
          break;
898
897
        case ARGP_KEY_ARG:
899
 
          argp_usage(state);
 
898
          argp_usage (state);
900
899
        case ARGP_KEY_END:
901
900
          break;
902
901
        default:
909
908
                           .args_doc = "",
910
909
                           .doc = "Mandos client -- Get and decrypt"
911
910
                           " passwords from a Mandos server" };
912
 
      ret = argp_parse(&argp, argc, argv, 0, 0, NULL);
913
 
      if(ret == ARGP_ERR_UNKNOWN){
 
911
      ret = argp_parse (&argp, argc, argv, 0, 0, NULL);
 
912
      if (ret == ARGP_ERR_UNKNOWN){
914
913
        fprintf(stderr, "Unknown error while parsing arguments\n");
915
914
        exitcode = EXIT_FAILURE;
916
915
        goto end;
941
940
          goto end;
942
941
        }
943
942
      }
944
 
      ret = (int)TEMP_FAILURE_RETRY(close(sd));
 
943
      ret = TEMP_FAILURE_RETRY(close(sd));
945
944
      if(ret == -1){
946
945
        perror("close");
947
946
      }
951
950
    gid = getgid();
952
951
    
953
952
    ret = setuid(uid);
954
 
    if(ret == -1){
 
953
    if (ret == -1){
955
954
      perror("setuid");
956
955
    }
957
956
    
958
957
    setgid(gid);
959
 
    if(ret == -1){
 
958
    if (ret == -1){
960
959
      perror("setgid");
961
960
    }
962
961
    
963
962
    ret = init_gnutls_global(&mc, pubkey, seckey);
964
 
    if(ret == -1){
 
963
    if (ret == -1){
965
964
      fprintf(stderr, "init_gnutls_global failed\n");
966
965
      exitcode = EXIT_FAILURE;
967
966
      goto end;
998
997
        exitcode = EXIT_FAILURE;
999
998
        goto end;
1000
999
      }
1001
 
      uint16_t port;
1002
 
      ret = sscanf(address+1, "%" SCNu16, &port);
1003
 
      if(ret != 1){
1004
 
        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");
1005
1004
        exitcode = EXIT_FAILURE;
1006
1005
        goto end;
1007
1006
      }
1016
1015
      goto end;
1017
1016
    }
1018
1017
    
1019
 
    if(not debug){
 
1018
    if (not debug){
1020
1019
      avahi_set_log_function(empty_log);
1021
1020
    }
1022
1021
    
1025
1024
    
1026
1025
    /* Allocate main Avahi loop object */
1027
1026
    mc.simple_poll = avahi_simple_poll_new();
1028
 
    if(mc.simple_poll == NULL) {
 
1027
    if (mc.simple_poll == NULL) {
1029
1028
        fprintf(stderr, "Avahi: Failed to create simple poll"
1030
1029
                " object.\n");
1031
1030
        exitcode = EXIT_FAILURE;
1051
1050
    }
1052
1051
    
1053
1052
    /* Check if creating the Avahi server object succeeded */
1054
 
    if(mc.server == NULL) {
 
1053
    if (mc.server == NULL) {
1055
1054
        fprintf(stderr, "Failed to create Avahi server: %s\n",
1056
1055
                avahi_strerror(error));
1057
1056
        exitcode = EXIT_FAILURE;
1063
1062
                                     AVAHI_PROTO_INET6,
1064
1063
                                     "_mandos._tcp", NULL, 0,
1065
1064
                                     browse_callback, &mc);
1066
 
    if(sb == NULL) {
 
1065
    if (sb == NULL) {
1067
1066
        fprintf(stderr, "Failed to create service browser: %s\n",
1068
1067
                avahi_strerror(avahi_server_errno(mc.server)));
1069
1068
        exitcode = EXIT_FAILURE;
1072
1071
    
1073
1072
    /* Run the main loop */
1074
1073
    
1075
 
    if(debug){
 
1074
    if (debug){
1076
1075
      fprintf(stderr, "Starting Avahi loop search\n");
1077
1076
    }
1078
1077
    
1080
1079
    
1081
1080
 end:
1082
1081
    
1083
 
    if(debug){
 
1082
    if (debug){
1084
1083
      fprintf(stderr, "%s exiting\n", argv[0]);
1085
1084
    }
1086
1085
    
1087
1086
    /* Cleanup things */
1088
 
    if(sb != NULL)
 
1087
    if (sb != NULL)
1089
1088
        avahi_s_service_browser_free(sb);
1090
1089
    
1091
 
    if(mc.server != NULL)
 
1090
    if (mc.server != NULL)
1092
1091
        avahi_server_free(mc.server);
1093
1092
    
1094
 
    if(mc.simple_poll != NULL)
 
1093
    if (mc.simple_poll != NULL)
1095
1094
        avahi_simple_poll_free(mc.simple_poll);
1096
1095
    
1097
 
    if(gnutls_initalized){
 
1096
    if (gnutls_initalized){
1098
1097
      gnutls_certificate_free_credentials(mc.cred);
1099
 
      gnutls_global_deinit();
 
1098
      gnutls_global_deinit ();
1100
1099
      gnutls_dh_params_deinit(mc.dh_params);
1101
1100
    }
1102
1101
    
1110
1109
      struct dirent *direntry;
1111
1110
      d = opendir(tempdir);
1112
1111
      if(d == NULL){
1113
 
        if(errno != ENOENT){
1114
 
          perror("opendir");
1115
 
        }
 
1112
        perror("opendir");
1116
1113
      } else {
1117
1114
        while(true){
1118
1115
          direntry = readdir(d);
1119
1116
          if(direntry == NULL){
1120
1117
            break;
1121
1118
          }
1122
 
          if(direntry->d_type == DT_REG){
 
1119
          if (direntry->d_type == DT_REG){
1123
1120
            char *fullname = NULL;
1124
1121
            ret = asprintf(&fullname, "%s/%s", tempdir,
1125
1122
                           direntry->d_name);
1138
1135
        closedir(d);
1139
1136
      }
1140
1137
      ret = rmdir(tempdir);
1141
 
      if(ret == -1 and errno != ENOENT){
 
1138
      if(ret == -1){
1142
1139
        perror("rmdir");
1143
1140
      }
1144
1141
    }