/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/mandosclient.c

  • Committer: Björn Påhlsson
  • Date: 2008-07-20 02:52:20 UTC
  • Revision ID: belorn@braxen-20080720025220-r5u0388uy9iu23h6
Added following support:
Pluginbased client handler
rewritten Mandos client
       Avahi instead of udp server discovery
       openpgp encrypted key support
Passprompt stand alone application for direct console input
Added logging for Mandos server

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* $Id$ */
 
2
 
 
3
/* PLEASE NOTE *
 
4
 * This file demonstrates how to use Avahi's core API, this is
 
5
 * the embeddable mDNS stack for embedded applications.
 
6
 *
 
7
 * End user applications should *not* use this API and should use
 
8
 * the D-Bus or C APIs, please see
 
9
 * client-browse-services.c and glib-integration.c
 
10
 * 
 
11
 * I repeat, you probably do *not* want to use this example.
 
12
 */
 
13
 
1
14
/***
2
15
  This file is part of avahi.
3
16
 
50
63
#include <errno.h>              /* perror() */
51
64
#include <gpgme.h>
52
65
 
53
 
// getopt long
54
 
#include <getopt.h>
55
66
 
56
67
#ifndef CERT_ROOT
57
68
#define CERT_ROOT "/conf/conf.d/cryptkeyreq/"
61
72
#define BUFFER_SIZE 256
62
73
#define DH_BITS 1024
63
74
 
64
 
bool debug = false;
65
 
char *interface = "eth0";
66
 
 
67
75
typedef struct {
68
76
  gnutls_session_t session;
69
77
  gnutls_certificate_credentials_t cred;
80
88
  size_t new_packet_length = 0;
81
89
  gpgme_engine_info_t engine_info;
82
90
 
83
 
  if (debug){
84
 
    fprintf(stderr, "Attempting to decrypt password from gpg packet\n");
85
 
  }
86
 
  
87
91
  /* Init GPGME */
88
92
  gpgme_check_version(NULL);
89
93
  gpgme_engine_check_version(GPGME_PROTOCOL_OpenPGP);
139
143
            gpgme_strsource(rc), gpgme_strerror(rc));
140
144
    return -1;
141
145
  }
142
 
 
143
 
  if(debug){
144
 
    fprintf(stderr, "decryption of gpg packet succeeded\n");
145
 
  }
146
 
 
147
 
  if (debug){
148
 
    gpgme_decrypt_result_t result;
149
 
    result = gpgme_op_decrypt_result(ctx);
150
 
    if (result == NULL){
151
 
      fprintf(stderr, "gpgme_op_decrypt_result failed\n");
152
 
    } else {
153
 
      fprintf(stderr, "Unsupported algorithm: %s\n", result->unsupported_algorithm);
154
 
      fprintf(stderr, "Wrong key usage: %d\n", result->wrong_key_usage);
155
 
      if(result->file_name != NULL){
156
 
        fprintf(stderr, "File name: %s\n", result->file_name);
157
 
      }
158
 
      gpgme_recipient_t recipient;
159
 
      recipient = result->recipients;
160
 
      if(recipient){
161
 
        while(recipient != NULL){
162
 
          fprintf(stderr, "Public key algorithm: %s\n",
163
 
                  gpgme_pubkey_algo_name(recipient->pubkey_algo));
164
 
          fprintf(stderr, "Key ID: %s\n", recipient->keyid);
165
 
          fprintf(stderr, "Secret key available: %s\n",
166
 
                  recipient->status == GPG_ERR_NO_SECKEY ? "No" : "Yes");
167
 
          recipient = recipient->next;
168
 
        }
169
 
      }
170
 
    }
171
 
  }
172
146
  
 
147
/*   gpgme_decrypt_result_t result; */
 
148
/*   result = gpgme_op_decrypt_result(ctx); */
 
149
/*   fprintf(stderr, "Unsupported algorithm: %s\n", result->unsupported_algorithm); */
 
150
/*   fprintf(stderr, "Wrong key usage: %d\n", result->wrong_key_usage); */
 
151
/*   if(result->file_name != NULL){ */
 
152
/*     fprintf(stderr, "File name: %s\n", result->file_name); */
 
153
/*   } */
 
154
/*   gpgme_recipient_t recipient; */
 
155
/*   recipient = result->recipients; */
 
156
/*   if(recipient){ */
 
157
/*     while(recipient != NULL){ */
 
158
/*       fprintf(stderr, "Public key algorithm: %s\n", */
 
159
/*            gpgme_pubkey_algo_name(recipient->pubkey_algo)); */
 
160
/*       fprintf(stderr, "Key ID: %s\n", recipient->keyid); */
 
161
/*       fprintf(stderr, "Secret key available: %s\n", */
 
162
/*            recipient->status == GPG_ERR_NO_SECKEY ? "No" : "Yes"); */
 
163
/*       recipient = recipient->next; */
 
164
/*     } */
 
165
/*   } */
 
166
 
173
167
  /* Delete the GPGME FILE pointer cryptotext data buffer */
174
168
  gpgme_data_release(dh_crypto);
175
169
  
200
194
    new_packet_length += ret;
201
195
  }
202
196
 
203
 
  /* FIXME: check characters before printing to screen so to not print
204
 
     terminal control characters */
205
 
  /*   if(debug){ */
206
 
  /*     fprintf(stderr, "decrypted password is: "); */
207
 
  /*     fwrite(*new_packet, 1, new_packet_length, stderr); */
208
 
  /*     fprintf(stderr, "\n"); */
209
 
  /*   } */
210
 
  
211
 
  /* Delete the GPGME plaintext data buffer */
 
197
   /* Delete the GPGME plaintext data buffer */
212
198
  gpgme_data_release(dh_plain);
213
199
  return new_packet_length;
214
200
}
227
213
int initgnutls(encrypted_session *es){
228
214
  const char *err;
229
215
  int ret;
230
 
 
231
 
  if(debug){
232
 
    fprintf(stderr, "Initializing gnutls\n");
233
 
  }
234
 
 
235
216
  
236
217
  if ((ret = gnutls_global_init ())
237
218
      != GNUTLS_E_SUCCESS) {
239
220
    return -1;
240
221
  }
241
222
 
242
 
  if (debug){
243
 
    gnutls_global_set_log_level(11);
244
 
    gnutls_global_set_log_function(debuggnutls);
245
 
  }
246
 
  
 
223
  /* Uncomment to enable full debuggin on the gnutls library */
 
224
  /*   gnutls_global_set_log_level(11); */
 
225
  /*   gnutls_global_set_log_function(debuggnutls); */
 
226
 
247
227
 
248
228
  /* openpgp credentials */
249
229
  if ((ret = gnutls_certificate_allocate_credentials (&es->cred))
252
232
    return -1;
253
233
  }
254
234
 
255
 
  if(debug){
256
 
    fprintf(stderr, "Attempting to use openpgp certificate %s"
257
 
            " and keyfile %s as gnutls credentials\n", CERTFILE, KEYFILE);
258
 
  }
259
 
 
260
235
  ret = gnutls_certificate_set_openpgp_key_file
261
236
    (es->cred, CERTFILE, KEYFILE, GNUTLS_OPENPGP_FMT_BASE64);
262
237
  if (ret != GNUTLS_E_SUCCESS) {
318
293
 
319
294
void empty_log(AvahiLogLevel level, const char *txt){}
320
295
 
321
 
int start_mandos_communication(char *ip, uint16_t port){
 
296
int start_mandos_communcation(char *ip, uint16_t port){
322
297
  int ret, tcp_sd;
323
298
  struct sockaddr_in6 to;
 
299
  struct in6_addr ip_addr;
324
300
  encrypted_session es;
325
301
  char *buffer = NULL;
326
302
  char *decrypted_buffer;
329
305
  ssize_t decrypted_buffer_size;
330
306
  int retval = 0;
331
307
 
332
 
  if(debug){
333
 
    fprintf(stderr, "Setting up a tcp connection to %s\n", ip);
334
 
  }
335
308
  
336
309
  tcp_sd = socket(PF_INET6, SOCK_STREAM, 0);
337
310
  if(tcp_sd < 0) {
338
311
    perror("socket");
339
312
    return -1;
340
313
  }
341
 
 
342
 
  if(debug){
343
 
    fprintf(stderr, "Binding to interface %s\n", interface);
344
 
  }
345
 
 
346
 
  ret = setsockopt(tcp_sd, SOL_SOCKET, SO_BINDTODEVICE, interface, 5);
 
314
  
 
315
  ret = setsockopt(tcp_sd, SOL_SOCKET, SO_BINDTODEVICE, "eth0", 5);
347
316
  if(tcp_sd < 0) {
348
317
    perror("setsockopt bindtodevice");
349
318
    return -1;
351
320
  
352
321
  memset(&to,0,sizeof(to));
353
322
  to.sin6_family = AF_INET6;
354
 
  ret = inet_pton(AF_INET6, ip, &to.sin6_addr);
 
323
  ret = inet_pton(AF_INET6, ip, &ip_addr);
355
324
  if (ret < 0 ){
356
325
    perror("inet_pton");
357
326
    return -1;
361
330
    return -1;
362
331
  }
363
332
  to.sin6_port = htons(port);
364
 
  to.sin6_scope_id = if_nametoindex(interface);
365
 
 
366
 
  if(debug){
367
 
    fprintf(stderr, "Connection to: %s\n", ip);
368
 
  }
 
333
  to.sin6_scope_id = if_nametoindex("eth0");
369
334
  
370
335
  ret = connect(tcp_sd, (struct sockaddr *) &to, sizeof(to));
371
336
  if (ret < 0){
382
347
  
383
348
  gnutls_transport_set_ptr (es.session, (gnutls_transport_ptr_t) tcp_sd);
384
349
 
385
 
  if(debug){
386
 
    fprintf(stderr, "Establishing tls session with %s\n", ip);
387
 
  }
388
 
 
389
 
  
390
350
  ret = gnutls_handshake (es.session);
391
351
  
392
352
  if (ret != GNUTLS_E_SUCCESS){
396
356
    goto exit;
397
357
  }
398
358
 
399
 
  //Retrieve gpg packet that contains the wanted password
400
 
 
401
 
  if(debug){
402
 
    fprintf(stderr, "Retrieving pgp encrypted password from %s\n", ip);
403
 
  }
404
 
 
 
359
  //retrive password
405
360
  while(true){
406
361
    if (buffer_length + BUFFER_SIZE > buffer_capacity){
407
362
      buffer = realloc(buffer, buffer_capacity + BUFFER_SIZE);
441
396
      buffer_length += ret;
442
397
    }
443
398
  }
444
 
  
 
399
 
445
400
  if (buffer_length > 0){
446
 
    if ((decrypted_buffer_size = gpg_packet_decrypt(buffer, buffer_length, &decrypted_buffer, CERT_ROOT)) >= 0){
 
401
    if ((decrypted_buffer_size = gpg_packet_decrypt(buffer, buffer_length, &decrypted_buffer, CERT_ROOT)) == 0){
 
402
      retval = -1;
 
403
    } else {
447
404
      fwrite (decrypted_buffer, 1, decrypted_buffer_size, stdout);
448
405
      free(decrypted_buffer);
449
 
    } else {
450
 
      retval = -1;
451
406
    }
452
407
  }
453
408
 
 
409
  free(buffer);
 
410
 
454
411
  //shutdown procedure
455
 
 
456
 
  if(debug){
457
 
    fprintf(stderr, "Closing tls session\n");
458
 
  }
459
 
 
460
 
  free(buffer);
461
412
  gnutls_bye (es.session, GNUTLS_SHUT_RDWR);
462
413
 exit:
463
414
  close(tcp_sd);
497
448
        case AVAHI_RESOLVER_FOUND: {
498
449
          char ip[AVAHI_ADDRESS_STR_MAX];
499
450
            avahi_address_snprint(ip, sizeof(ip), address);
500
 
            if(debug){
501
 
              fprintf(stderr, "Mandos server found at %s on port %d\n", ip, port);
502
 
            }
503
 
            int ret = start_mandos_communication(ip, port);
 
451
            int ret = start_mandos_communcation(ip, port);
504
452
            if (ret == 0){
505
453
              exit(EXIT_SUCCESS);
506
454
            } else {
559
507
    AvahiServerConfig config;
560
508
    AvahiSServiceBrowser *sb = NULL;
561
509
    int error;
562
 
    int ret;
563
 
    int returncode = EXIT_SUCCESS;
564
 
 
565
 
    while (true){
566
 
      static struct option long_options[] = {
567
 
        {"debug", no_argument, (int *)&debug, 1},
568
 
        {"interface", required_argument, 0, 'i'},
569
 
        {0, 0, 0, 0} };
570
 
 
571
 
      int option_index = 0;
572
 
      ret = getopt_long (argc, argv, "i:", long_options, &option_index);
573
 
 
574
 
      if (ret == -1){
575
 
        break;
576
 
      }
577
 
      
578
 
      switch(ret){
579
 
      case 0:
580
 
        break;
581
 
      case 'i':
582
 
        interface = optarg;
583
 
        break;
584
 
      default:
585
 
        exit(EXIT_FAILURE);
586
 
      }
587
 
    }
588
 
    
589
 
    if (not debug){
590
 
      avahi_set_log_function(empty_log);
591
 
    }
 
510
    int ret = 1;
 
511
 
 
512
    avahi_set_log_function(empty_log);
592
513
    
593
514
    /* Initialize the psuedo-RNG */
594
515
    srand(time(NULL));
596
517
    /* Allocate main loop object */
597
518
    if (!(simple_poll = avahi_simple_poll_new())) {
598
519
        fprintf(stderr, "Failed to create simple poll object.\n");
599
 
        
600
 
        goto exit;
 
520
        goto fail;
601
521
    }
602
522
 
603
523
    /* Do not publish any local records */
607
527
    config.publish_workstation = 0;
608
528
    config.publish_domain = 0;
609
529
 
 
530
/*     /\* Set a unicast DNS server for wide area DNS-SD *\/ */
 
531
/*     avahi_address_parse("193.11.177.11", AVAHI_PROTO_UNSPEC, &config.wide_area_servers[0]); */
 
532
/*     config.n_wide_area_servers = 1; */
 
533
/*     config.enable_wide_area = 1; */
 
534
    
610
535
    /* Allocate a new server */
611
536
    server = avahi_server_new(avahi_simple_poll_get(simple_poll), &config, NULL, NULL, &error);
612
537
 
613
538
    /* Free the configuration data */
614
539
    avahi_server_config_free(&config);
615
540
 
616
 
    /* Check if creating the server object succeeded */
 
541
    /* Check wether creating the server object succeeded */
617
542
    if (!server) {
618
543
        fprintf(stderr, "Failed to create server: %s\n", avahi_strerror(error));
619
 
        returncode = EXIT_FAILURE;
620
 
        goto exit;
 
544
        goto fail;
621
545
    }
622
546
    
623
547
    /* Create the service browser */
624
548
    if (!(sb = avahi_s_service_browser_new(server, if_nametoindex("eth0"), AVAHI_PROTO_INET6, "_mandos._tcp", NULL, 0, browse_callback, server))) {
625
549
        fprintf(stderr, "Failed to create service browser: %s\n", avahi_strerror(avahi_server_errno(server)));
626
 
        returncode = EXIT_FAILURE;
627
 
        goto exit;
 
550
        goto fail;
628
551
    }
629
552
    
630
553
    /* Run the main loop */
631
 
 
632
 
    if (debug){
633
 
      fprintf(stderr, "Starting avahi loop search\n");
634
 
    }
635
 
    
636
554
    avahi_simple_poll_loop(simple_poll);
637
555
    
638
 
exit:
639
 
 
640
 
    if (debug){
641
 
      fprintf(stderr, "%s exiting\n", argv[0]);
642
 
    }
 
556
    ret = 0;
 
557
    
 
558
fail:
643
559
    
644
560
    /* Cleanup things */
645
561
    if (sb)
651
567
    if (simple_poll)
652
568
        avahi_simple_poll_free(simple_poll);
653
569
 
654
 
    return returncode;
 
570
    return ret;
655
571
}