/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 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
 
59
72
#define BUFFER_SIZE 256
60
73
#define DH_BITS 1024
61
74
 
62
 
bool debug = false;
63
 
 
64
75
typedef struct {
65
76
  gnutls_session_t session;
66
77
  gnutls_certificate_credentials_t cred;
77
88
  size_t new_packet_length = 0;
78
89
  gpgme_engine_info_t engine_info;
79
90
 
80
 
  if (debug){
81
 
    fprintf(stderr, "Attempting to decrypt password from gpg packet\n");
82
 
  }
83
 
  
84
91
  /* Init GPGME */
85
92
  gpgme_check_version(NULL);
86
93
  gpgme_engine_check_version(GPGME_PROTOCOL_OpenPGP);
136
143
            gpgme_strsource(rc), gpgme_strerror(rc));
137
144
    return -1;
138
145
  }
139
 
 
140
 
  if(debug){
141
 
    fprintf(stderr, "decryption of gpg packet succeeded\n");
142
 
  }
143
 
 
144
 
  if (debug){
145
 
    gpgme_decrypt_result_t result;
146
 
    result = gpgme_op_decrypt_result(ctx);
147
 
    if (result == NULL){
148
 
      fprintf(stderr, "gpgme_op_decrypt_result failed\n");
149
 
    } else {
150
 
      fprintf(stderr, "Unsupported algorithm: %s\n", result->unsupported_algorithm);
151
 
      fprintf(stderr, "Wrong key usage: %d\n", result->wrong_key_usage);
152
 
      if(result->file_name != NULL){
153
 
        fprintf(stderr, "File name: %s\n", result->file_name);
154
 
      }
155
 
      gpgme_recipient_t recipient;
156
 
      recipient = result->recipients;
157
 
      if(recipient){
158
 
        while(recipient != NULL){
159
 
          fprintf(stderr, "Public key algorithm: %s\n",
160
 
                  gpgme_pubkey_algo_name(recipient->pubkey_algo));
161
 
          fprintf(stderr, "Key ID: %s\n", recipient->keyid);
162
 
          fprintf(stderr, "Secret key available: %s\n",
163
 
                  recipient->status == GPG_ERR_NO_SECKEY ? "No" : "Yes");
164
 
          recipient = recipient->next;
165
 
        }
166
 
      }
167
 
    }
168
 
  }
169
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
 
170
167
  /* Delete the GPGME FILE pointer cryptotext data buffer */
171
168
  gpgme_data_release(dh_crypto);
172
169
  
197
194
    new_packet_length += ret;
198
195
  }
199
196
 
200
 
  if(debug){
201
 
    fprintf(stderr, "decrypted password is: %s\n", *new_packet);
202
 
  }
203
 
 
204
197
   /* Delete the GPGME plaintext data buffer */
205
198
  gpgme_data_release(dh_plain);
206
199
  return new_packet_length;
220
213
int initgnutls(encrypted_session *es){
221
214
  const char *err;
222
215
  int ret;
223
 
 
224
 
  if(debug){
225
 
    fprintf(stderr, "Initializing gnutls\n");
226
 
  }
227
 
 
228
216
  
229
217
  if ((ret = gnutls_global_init ())
230
218
      != GNUTLS_E_SUCCESS) {
232
220
    return -1;
233
221
  }
234
222
 
235
 
  if (debug){
236
 
    gnutls_global_set_log_level(11);
237
 
    gnutls_global_set_log_function(debuggnutls);
238
 
  }
239
 
  
 
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
 
240
227
 
241
228
  /* openpgp credentials */
242
229
  if ((ret = gnutls_certificate_allocate_credentials (&es->cred))
245
232
    return -1;
246
233
  }
247
234
 
248
 
  if(debug){
249
 
    fprintf(stderr, "Attempting to use openpgp certificate %s"
250
 
            " and keyfile %s as gnutls credentials\n", CERTFILE, KEYFILE);
251
 
  }
252
 
 
253
235
  ret = gnutls_certificate_set_openpgp_key_file
254
236
    (es->cred, CERTFILE, KEYFILE, GNUTLS_OPENPGP_FMT_BASE64);
255
237
  if (ret != GNUTLS_E_SUCCESS) {
314
296
int start_mandos_communcation(char *ip, uint16_t port){
315
297
  int ret, tcp_sd;
316
298
  struct sockaddr_in6 to;
 
299
  struct in6_addr ip_addr;
317
300
  encrypted_session es;
318
301
  char *buffer = NULL;
319
302
  char *decrypted_buffer;
321
304
  size_t buffer_capacity = 0;
322
305
  ssize_t decrypted_buffer_size;
323
306
  int retval = 0;
324
 
  const char interface[] = "eth0";
325
307
 
326
 
  if(debug){
327
 
    fprintf(stderr, "Setting up a tcp connection to %s\n", ip);
328
 
  }
329
308
  
330
309
  tcp_sd = socket(PF_INET6, SOCK_STREAM, 0);
331
310
  if(tcp_sd < 0) {
332
311
    perror("socket");
333
312
    return -1;
334
313
  }
335
 
 
336
 
  if(debug){
337
 
    fprintf(stderr, "Binding to interface %s\n", interface);
338
 
  }
339
 
 
340
 
  ret = setsockopt(tcp_sd, SOL_SOCKET, SO_BINDTODEVICE, interface, 5);
 
314
  
 
315
  ret = setsockopt(tcp_sd, SOL_SOCKET, SO_BINDTODEVICE, "eth0", 5);
341
316
  if(tcp_sd < 0) {
342
317
    perror("setsockopt bindtodevice");
343
318
    return -1;
345
320
  
346
321
  memset(&to,0,sizeof(to));
347
322
  to.sin6_family = AF_INET6;
348
 
  ret = inet_pton(AF_INET6, ip, &to.sin6_addr);
 
323
  ret = inet_pton(AF_INET6, ip, &ip_addr);
349
324
  if (ret < 0 ){
350
325
    perror("inet_pton");
351
326
    return -1;
355
330
    return -1;
356
331
  }
357
332
  to.sin6_port = htons(port);
358
 
  to.sin6_scope_id = if_nametoindex(interface);
359
 
 
360
 
  if(debug){
361
 
    fprintf(stderr, "Connection to: %s\n", ip);
362
 
  }
 
333
  to.sin6_scope_id = if_nametoindex("eth0");
363
334
  
364
335
  ret = connect(tcp_sd, (struct sockaddr *) &to, sizeof(to));
365
336
  if (ret < 0){
376
347
  
377
348
  gnutls_transport_set_ptr (es.session, (gnutls_transport_ptr_t) tcp_sd);
378
349
 
379
 
  if(debug){
380
 
    fprintf(stderr, "Establishing tls session with %s\n", ip);
381
 
  }
382
 
 
383
 
  
384
350
  ret = gnutls_handshake (es.session);
385
351
  
386
352
  if (ret != GNUTLS_E_SUCCESS){
390
356
    goto exit;
391
357
  }
392
358
 
393
 
  //Retrieve gpg packet that contains the wanted password
394
 
 
395
 
  if(debug){
396
 
    fprintf(stderr, "Retrieving pgp encrypted password from %s\n", ip);
397
 
  }
398
 
 
 
359
  //retrive password
399
360
  while(true){
400
361
    if (buffer_length + BUFFER_SIZE > buffer_capacity){
401
362
      buffer = realloc(buffer, buffer_capacity + BUFFER_SIZE);
435
396
      buffer_length += ret;
436
397
    }
437
398
  }
438
 
  
 
399
 
439
400
  if (buffer_length > 0){
440
 
    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 {
441
404
      fwrite (decrypted_buffer, 1, decrypted_buffer_size, stdout);
442
405
      free(decrypted_buffer);
443
 
    } else {
444
 
      retval = -1;
445
406
    }
446
407
  }
447
408
 
 
409
  free(buffer);
 
410
 
448
411
  //shutdown procedure
449
 
 
450
 
  if(debug){
451
 
    fprintf(stderr, "Closing tls session\n");
452
 
  }
453
 
 
454
 
  free(buffer);
455
412
  gnutls_bye (es.session, GNUTLS_SHUT_RDWR);
456
413
 exit:
457
414
  close(tcp_sd);
491
448
        case AVAHI_RESOLVER_FOUND: {
492
449
          char ip[AVAHI_ADDRESS_STR_MAX];
493
450
            avahi_address_snprint(ip, sizeof(ip), address);
494
 
            if(debug){
495
 
              fprintf(stderr, "Mandos server found at %s on port %d\n", ip, port);
496
 
            }
497
451
            int ret = start_mandos_communcation(ip, port);
498
452
            if (ret == 0){
499
453
              exit(EXIT_SUCCESS);
552
506
int main(AVAHI_GCC_UNUSED int argc, AVAHI_GCC_UNUSED char*argv[]) {
553
507
    AvahiServerConfig config;
554
508
    AvahiSServiceBrowser *sb = NULL;
555
 
    const char db[] = "--debug";
556
509
    int error;
557
510
    int ret = 1;
558
 
    int returncode = EXIT_SUCCESS;
559
 
    char *basename = rindex(argv[0], '/');
560
 
    if(basename == NULL){
561
 
      basename = argv[0];
562
 
    } else {
563
 
      basename++;
564
 
    }
565
 
    
566
 
    char *program_name = malloc(strlen(basename) + sizeof(db));
567
 
 
568
 
    if (program_name == NULL){
569
 
      perror("argv[0]");
570
 
      return EXIT_FAILURE;
571
 
    }
572
 
    
573
 
    program_name[0] = '\0';
574
 
    
575
 
    for (int i = 1; i < argc; i++){
576
 
      if (not strncmp(argv[i], db, 5)){
577
 
          strcat(strcat(strcat(program_name, db ), "="), basename);
578
 
          if(not strcmp(argv[i], db) or not strcmp(argv[i], program_name)){
579
 
            debug = true;
580
 
          }
581
 
        }
582
 
    }
583
 
    free(program_name);
584
 
 
585
 
    if (not debug){
586
 
      avahi_set_log_function(empty_log);
587
 
    }
 
511
 
 
512
    avahi_set_log_function(empty_log);
588
513
    
589
514
    /* Initialize the psuedo-RNG */
590
515
    srand(time(NULL));
592
517
    /* Allocate main loop object */
593
518
    if (!(simple_poll = avahi_simple_poll_new())) {
594
519
        fprintf(stderr, "Failed to create simple poll object.\n");
595
 
        
596
 
        goto exit;
 
520
        goto fail;
597
521
    }
598
522
 
599
523
    /* Do not publish any local records */
603
527
    config.publish_workstation = 0;
604
528
    config.publish_domain = 0;
605
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
    
606
535
    /* Allocate a new server */
607
536
    server = avahi_server_new(avahi_simple_poll_get(simple_poll), &config, NULL, NULL, &error);
608
537
 
609
538
    /* Free the configuration data */
610
539
    avahi_server_config_free(&config);
611
540
 
612
 
    /* Check if creating the server object succeeded */
 
541
    /* Check wether creating the server object succeeded */
613
542
    if (!server) {
614
543
        fprintf(stderr, "Failed to create server: %s\n", avahi_strerror(error));
615
 
        returncode = EXIT_FAILURE;
616
 
        goto exit;
 
544
        goto fail;
617
545
    }
618
546
    
619
547
    /* Create the service browser */
620
548
    if (!(sb = avahi_s_service_browser_new(server, if_nametoindex("eth0"), AVAHI_PROTO_INET6, "_mandos._tcp", NULL, 0, browse_callback, server))) {
621
549
        fprintf(stderr, "Failed to create service browser: %s\n", avahi_strerror(avahi_server_errno(server)));
622
 
        returncode = EXIT_FAILURE;
623
 
        goto exit;
 
550
        goto fail;
624
551
    }
625
552
    
626
553
    /* Run the main loop */
627
 
 
628
 
    if (debug){
629
 
      fprintf(stderr, "Starting avahi loop search\n");
630
 
    }
631
 
    
632
554
    avahi_simple_poll_loop(simple_poll);
633
555
    
634
 
exit:
635
 
 
636
 
    if (debug){
637
 
      fprintf(stderr, "%s exiting\n", argv[0]);
638
 
    }
 
556
    ret = 0;
 
557
    
 
558
fail:
639
559
    
640
560
    /* Cleanup things */
641
561
    if (sb)