/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: Björn Påhlsson
  • Date: 2008-07-20 03:51:41 UTC
  • Revision ID: belorn@braxen-20080720035141-ta0y0be7fotdm4ks
Fixed a overbufferflow bug, thanks to a forgotten \0

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
}