/mandos/release

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

« back to all changes in this revision

Viewing changes to plugins.d/mandosclient.c

  • Committer: Teddy Hogeborn
  • Date: 2008-08-02 21:06:12 UTC
  • Revision ID: teddy@fukt.bsnet.se-20080802210612-4c1waup4z0f66ya7
Non-tested commit for merge purposes.

* plugbasedclient.c (getplugin, addargument, set_cloexec): Made static.

* plugins.d/passprompt.c (termination_handler): Made static.

Show diffs side-by-side

added added

removed removed

Lines of Context:
8
8
 * includes the following functions: "resolve_callback",
9
9
 * "browse_callback", and parts of "main".
10
10
 * 
11
 
 * Everything else is Copyright © 2007-2008 Teddy Hogeborn and Björn
12
 
 * Påhlsson.
 
11
 * Everything else is
 
12
 * Copyright © 2007-2008 Teddy Hogeborn & Björn Påhlsson
13
13
 * 
14
14
 * This program is free software: you can redistribute it and/or
15
15
 * modify it under the terms of the GNU General Public License as
25
25
 * along with this program.  If not, see
26
26
 * <http://www.gnu.org/licenses/>.
27
27
 * 
28
 
 * Contact the authors at <https://www.fukt.bsnet.se/~belorn/> and
29
 
 * <https://www.fukt.bsnet.se/~teddy/>.
 
28
 * Contact the authors at <mandos@fukt.bsnet.se>.
30
29
 */
31
30
 
32
 
#define _FORTIFY_SOURCE 2
33
 
 
 
31
/* Needed by GPGME, specifically gpgme_data_seek() */
34
32
#define _LARGEFILE_SOURCE
35
33
#define _FILE_OFFSET_BITS 64
36
34
 
65
63
#include <errno.h>              /* perror() */
66
64
#include <gpgme.h>
67
65
 
68
 
// getopt long
 
66
// getopt_long
69
67
#include <getopt.h>
70
68
 
71
 
#ifndef CERT_ROOT
72
 
#define CERT_ROOT "/conf/conf.d/cryptkeyreq/"
73
 
#endif
74
 
#define CERTFILE CERT_ROOT "openpgp-client.txt"
75
 
#define KEYFILE CERT_ROOT "openpgp-client-key.txt"
76
69
#define BUFFER_SIZE 256
77
 
#define DH_BITS 1024
 
70
 
 
71
static int dh_bits = 1024;
 
72
 
 
73
static const char *keydir = "/conf/conf.d/mandos";
 
74
static const char *pubkeyfile = "pubkey.txt";
 
75
static const char *seckeyfile = "seckey.txt";
78
76
 
79
77
bool debug = false;
80
78
 
 
79
/* Used for  */
81
80
typedef struct {
82
81
  gnutls_session_t session;
83
82
  gnutls_certificate_credentials_t cred;
85
84
} encrypted_session;
86
85
 
87
86
 
88
 
ssize_t pgp_packet_decrypt (char *packet, size_t packet_size,
89
 
                            char **new_packet, const char *homedir){
 
87
static ssize_t pgp_packet_decrypt (char *packet, size_t packet_size,
 
88
                                   char **new_packet,
 
89
                                   const char *homedir){
90
90
  gpgme_data_t dh_crypto, dh_plain;
91
91
  gpgme_ctx_t ctx;
92
92
  gpgme_error_t rc;
101
101
  
102
102
  /* Init GPGME */
103
103
  gpgme_check_version(NULL);
104
 
  gpgme_engine_check_version(GPGME_PROTOCOL_OpenPGP);
 
104
  rc = gpgme_engine_check_version(GPGME_PROTOCOL_OpenPGP);
 
105
  if (rc != GPG_ERR_NO_ERROR){
 
106
    fprintf(stderr, "bad gpgme_engine_check_version: %s: %s\n",
 
107
            gpgme_strsource(rc), gpgme_strerror(rc));
 
108
    return -1;
 
109
  }
105
110
  
106
111
  /* Set GPGME home directory */
107
112
  rc = gpgme_get_engine_info (&engine_info);
193
198
  gpgme_data_release(dh_crypto);
194
199
  
195
200
  /* Seek back to the beginning of the GPGME plaintext data buffer */
196
 
  gpgme_data_seek(dh_plain, (off_t) 0, SEEK_SET);
197
 
 
 
201
  if (gpgme_data_seek(dh_plain, (off_t) 0, SEEK_SET) == -1){
 
202
    perror("pgpme_data_seek");
 
203
  }
 
204
  
198
205
  *new_packet = 0;
199
206
  while(true){
200
207
    if (new_packet_length + BUFFER_SIZE > new_packet_capacity){
241
248
  return ret;
242
249
}
243
250
 
244
 
void debuggnutls(__attribute__((unused)) int level,
245
 
                 const char* string){
 
251
static void debuggnutls(__attribute__((unused)) int level,
 
252
                        const char* string){
246
253
  fprintf(stderr, "%s", string);
247
254
}
248
255
 
249
 
int initgnutls(encrypted_session *es){
 
256
static int initgnutls(encrypted_session *es){
250
257
  const char *err;
251
258
  int ret;
252
259
  
253
260
  if(debug){
254
261
    fprintf(stderr, "Initializing GnuTLS\n");
255
262
  }
256
 
  
 
263
 
257
264
  if ((ret = gnutls_global_init ())
258
265
      != GNUTLS_E_SUCCESS) {
259
266
    fprintf (stderr, "global_init: %s\n", safer_gnutls_strerror(ret));
275
282
  
276
283
  if(debug){
277
284
    fprintf(stderr, "Attempting to use OpenPGP certificate %s"
278
 
            " and keyfile %s as GnuTLS credentials\n", CERTFILE,
279
 
            KEYFILE);
 
285
            " and keyfile %s as GnuTLS credentials\n", pubkeyfile,
 
286
            seckeyfile);
280
287
  }
281
288
  
282
289
  ret = gnutls_certificate_set_openpgp_key_file
283
 
    (es->cred, CERTFILE, KEYFILE, GNUTLS_OPENPGP_FMT_BASE64);
 
290
    (es->cred, pubkeyfile, seckeyfile, GNUTLS_OPENPGP_FMT_BASE64);
284
291
  if (ret != GNUTLS_E_SUCCESS) {
285
292
    fprintf
286
293
      (stderr, "Error[%d] while reading the OpenPGP key pair ('%s',"
287
294
       " '%s')\n",
288
 
       ret, CERTFILE, KEYFILE);
 
295
       ret, pubkeyfile, seckeyfile);
289
296
    fprintf(stdout, "The Error is: %s\n",
290
297
            safer_gnutls_strerror(ret));
291
298
    return -1;
299
306
    return -1;
300
307
  }
301
308
  
302
 
  if ((ret = gnutls_dh_params_generate2 (es->dh_params, DH_BITS))
 
309
  if ((ret = gnutls_dh_params_generate2 (es->dh_params, dh_bits))
303
310
      != GNUTLS_E_SUCCESS) {
304
311
    fprintf (stderr, "Error in prime generation: %s\n",
305
312
             safer_gnutls_strerror(ret));
335
342
  gnutls_certificate_server_set_request (es->session,
336
343
                                         GNUTLS_CERT_IGNORE);
337
344
  
338
 
  gnutls_dh_set_prime_bits (es->session, DH_BITS);
 
345
  gnutls_dh_set_prime_bits (es->session, dh_bits);
339
346
  
340
347
  return 0;
341
348
}
342
349
 
343
 
void empty_log(__attribute__((unused)) AvahiLogLevel level,
344
 
               __attribute__((unused)) const char *txt){}
 
350
static void empty_log(__attribute__((unused)) AvahiLogLevel level,
 
351
                      __attribute__((unused)) const char *txt){}
345
352
 
346
 
int start_mandos_communication(const char *ip, uint16_t port,
347
 
                               unsigned int if_index){
 
353
static int start_mandos_communication(const char *ip, uint16_t port,
 
354
                                      AvahiIfIndex if_index){
348
355
  int ret, tcp_sd;
349
356
  struct sockaddr_in6 to;
350
357
  encrypted_session es;
358
365
  char interface[IF_NAMESIZE];
359
366
  
360
367
  if(debug){
361
 
    fprintf(stderr, "Setting up a tcp connection to %s\n", ip);
 
368
    fprintf(stderr, "Setting up a tcp connection to %s, port %d\n",
 
369
            ip, port);
362
370
  }
363
371
  
364
372
  tcp_sd = socket(PF_INET6, SOCK_STREAM, 0);
367
375
    return -1;
368
376
  }
369
377
  
370
 
  if(if_indextoname(if_index, interface) == NULL){
 
378
  if(if_indextoname((unsigned int)if_index, interface) == NULL){
371
379
    if(debug){
372
380
      perror("if_indextoname");
373
381
    }
394
402
  to.sin6_scope_id = (uint32_t)if_index;
395
403
  
396
404
  if(debug){
397
 
    fprintf(stderr, "Connection to: %s\n", ip);
 
405
    fprintf(stderr, "Connection to: %s, port %d\n", ip, port);
 
406
    char addrstr[INET6_ADDRSTRLEN] = "";
 
407
    if(inet_ntop(to.sin6_family, &(to.sin6_addr), addrstr,
 
408
                 sizeof(addrstr)) == NULL){
 
409
      perror("inet_ntop");
 
410
    } else {
 
411
      if(strcmp(addrstr, ip) != 0){
 
412
        fprintf(stderr, "Canonical address form: %s\n",
 
413
                addrstr, ntohs(to.sin6_port));
 
414
      }
 
415
    }
398
416
  }
399
417
  
400
418
  ret = connect(tcp_sd, (struct sockaddr *) &to, sizeof(to));
479
497
    decrypted_buffer_size = pgp_packet_decrypt(buffer,
480
498
                                               buffer_length,
481
499
                                               &decrypted_buffer,
482
 
                                               CERT_ROOT);
 
500
                                               keydir);
483
501
    if (decrypted_buffer_size >= 0){
484
 
      while(written < decrypted_buffer_size){
 
502
      while(written < (size_t) decrypted_buffer_size){
485
503
        ret = (int)fwrite (decrypted_buffer + written, 1,
486
504
                           (size_t)decrypted_buffer_size - written,
487
505
                           stdout);
556
574
        fprintf(stderr, "Mandos server \"%s\" found on %s (%s) on"
557
575
                " port %d\n", name, host_name, ip, port);
558
576
      }
559
 
      int ret = start_mandos_communication(ip, port,
560
 
                                           (unsigned int) interface);
 
577
      int ret = start_mandos_communication(ip, port, interface);
561
578
      if (ret == 0){
562
579
        exit(EXIT_SUCCESS);
563
580
      }
615
632
    }
616
633
}
617
634
 
 
635
/* Combines file name and path and returns the malloced new
 
636
   string. some sane checks could/should be added */
 
637
static const char *combinepath(const char *first, const char *second){
 
638
  size_t f_len = strlen(first);
 
639
  size_t s_len = strlen(second);
 
640
  char *tmp = malloc(f_len + s_len + 2);
 
641
  if (tmp == NULL){
 
642
    return NULL;
 
643
  }
 
644
  if(f_len > 0){
 
645
    memcpy(tmp, first, f_len);
 
646
  }
 
647
  tmp[f_len] = '/';
 
648
  if(s_len > 0){
 
649
    memcpy(tmp + f_len + 1, second, s_len);
 
650
  }
 
651
  tmp[f_len + 1 + s_len] = '\0';
 
652
  return tmp;
 
653
}
 
654
 
 
655
 
618
656
int main(AVAHI_GCC_UNUSED int argc, AVAHI_GCC_UNUSED char*argv[]) {
619
657
    AvahiServerConfig config;
620
658
    AvahiSServiceBrowser *sb = NULL;
621
659
    int error;
622
660
    int ret;
 
661
    int debug_int = 0;
623
662
    int returncode = EXIT_SUCCESS;
624
 
    const char *interface = "eth0";
 
663
    const char *interface = NULL;
 
664
    AvahiIfIndex if_index = AVAHI_IF_UNSPEC;
 
665
    char *connect_to = NULL;
625
666
    
 
667
    debug_int = debug ? 1 : 0;
626
668
    while (true){
627
669
      static struct option long_options[] = {
628
 
        {"debug", no_argument, (int *)&debug, 1},
629
 
        {"interface", required_argument, 0, 'i'},
 
670
        {"debug", no_argument, &debug_int, 1},
 
671
        {"connect", required_argument, NULL, 'C'},
 
672
        {"interface", required_argument, NULL, 'i'},
 
673
        {"keydir", required_argument, NULL, 'd'},
 
674
        {"seckey", required_argument, NULL, 'c'},
 
675
        {"pubkey", required_argument, NULL, 'k'},
 
676
        {"dh-bits", required_argument, NULL, 'D'},
630
677
        {0, 0, 0, 0} };
631
678
      
632
679
      int option_index = 0;
643
690
      case 'i':
644
691
        interface = optarg;
645
692
        break;
 
693
      case 'C':
 
694
        connect_to = optarg;
 
695
        break;
 
696
      case 'd':
 
697
        keydir = optarg;
 
698
        break;
 
699
      case 'c':
 
700
        pubkeyfile = optarg;
 
701
        break;
 
702
      case 'k':
 
703
        seckeyfile = optarg;
 
704
        break;
 
705
      case 'D':
 
706
        dh_bits = atoi(optarg);
 
707
        break;
 
708
      case '?':
 
709
        break
646
710
      default:
647
711
        exit(EXIT_FAILURE);
648
712
      }
649
713
    }
 
714
    debug = debug_int ? true : false;
 
715
    
 
716
    pubkeyfile = combinepath(keydir, pubkeyfile);
 
717
    if (pubkeyfile == NULL){
 
718
      perror("combinepath");
 
719
      goto exit;
 
720
    }
 
721
    
 
722
    if(interface != NULL){
 
723
      if_index = (AvahiIfIndex) if_nametoindex(interface);
 
724
      if(if_index == 0){
 
725
        fprintf(stderr, "No such interface: \"%s\"\n", interface);
 
726
        exit(EXIT_FAILURE);
 
727
      }
 
728
    }
 
729
    
 
730
    if(connect_to != NULL){
 
731
      /* Connect directly, do not use Zeroconf */
 
732
      /* (Mainly meant for debugging) */
 
733
      char *address = strrchr(connect_to, ':');
 
734
      if(address == NULL){
 
735
        fprintf(stderr, "No colon in address\n");
 
736
        exit(EXIT_FAILURE);
 
737
      }
 
738
      errno = 0;
 
739
      uint16_t port = (uint16_t) strtol(address+1, NULL, 10);
 
740
      if(errno){
 
741
        perror("Bad port number");
 
742
        exit(EXIT_FAILURE);
 
743
      }
 
744
      *address = '\0';
 
745
      address = connect_to;
 
746
      ret = start_mandos_communication(address, port, if_index);
 
747
      if(ret < 0){
 
748
        exit(EXIT_FAILURE);
 
749
      } else {
 
750
        exit(EXIT_SUCCESS);
 
751
      }
 
752
    }
 
753
    
 
754
    seckeyfile = combinepath(keydir, seckeyfile);
 
755
    if (seckeyfile == NULL){
 
756
      perror("combinepath");
 
757
      goto exit;
 
758
    }
650
759
    
651
760
    if (not debug){
652
761
      avahi_set_log_function(empty_log);
685
794
    }
686
795
    
687
796
    /* Create the service browser */
688
 
    sb = avahi_s_service_browser_new(server,
689
 
                                     (AvahiIfIndex)
690
 
                                     if_nametoindex(interface),
 
797
    sb = avahi_s_service_browser_new(server, if_index,
691
798
                                     AVAHI_PROTO_INET6,
692
799
                                     "_mandos._tcp", NULL, 0,
693
800
                                     browse_callback, server);
721
828
 
722
829
    if (simple_poll)
723
830
        avahi_simple_poll_free(simple_poll);
724
 
 
 
831
    free(pubkeyfile);
 
832
    free(seckeyfile);
 
833
    
725
834
    return returncode;
726
835
}