198
/* Delete the GPGME FILE pointer cryptotext data buffer */
199
gpgme_data_release(dh_crypto);
201
210
/* Seek back to the beginning of the GPGME plaintext data buffer */
202
211
if (gpgme_data_seek(dh_plain, (off_t) 0, SEEK_SET) == -1){
203
212
perror("pgpme_data_seek");
213
plaintext_length = -1;
208
if (new_packet_length + BUFFER_SIZE > new_packet_capacity){
209
*new_packet = realloc(*new_packet,
210
(unsigned int)new_packet_capacity
219
if (plaintext_length + BUFFER_SIZE
220
> (ssize_t) plaintext_capacity){
221
*plaintext = realloc(*plaintext, plaintext_capacity
212
if (*new_packet == NULL){
223
if (*plaintext == NULL){
213
224
perror("realloc");
225
plaintext_length = -1;
216
new_packet_capacity += BUFFER_SIZE;
228
plaintext_capacity += BUFFER_SIZE;
219
ret = gpgme_data_read(dh_plain, *new_packet + new_packet_length,
231
ret = gpgme_data_read(dh_plain, *plaintext + plaintext_length,
221
233
/* Print the data, if any */
226
239
perror("gpgme_data_read");
240
plaintext_length = -1;
229
new_packet_length += ret;
243
plaintext_length += ret;
232
/* FIXME: check characters before printing to screen so to not print
233
terminal control characters */
235
/* fprintf(stderr, "decrypted password is: "); */
236
/* fwrite(*new_packet, 1, new_packet_length, stderr); */
237
/* fprintf(stderr, "\n"); */
247
fprintf(stderr, "Decrypted password is: ");
248
for(ssize_t i = 0; i < plaintext_length; i++){
249
fprintf(stderr, "%02hhX ", (*plaintext)[i]);
251
fprintf(stderr, "\n");
256
/* Delete the GPGME cryptotext data buffer */
257
gpgme_data_release(dh_crypto);
240
259
/* Delete the GPGME plaintext data buffer */
241
260
gpgme_data_release(dh_plain);
242
return new_packet_length;
261
return plaintext_length;
245
264
static const char * safer_gnutls_strerror (int value) {
265
285
if ((ret = gnutls_global_init ())
266
286
!= GNUTLS_E_SUCCESS) {
267
fprintf (stderr, "global_init: %s\n", safer_gnutls_strerror(ret));
287
fprintf (stderr, "GnuTLS global_init: %s\n",
288
safer_gnutls_strerror(ret));
293
/* "Use a log level over 10 to enable all debugging options."
272
296
gnutls_global_set_log_level(11);
273
297
gnutls_global_set_log_function(debuggnutls);
276
/* openpgp credentials */
277
if ((ret = gnutls_certificate_allocate_credentials (&es->cred))
300
/* OpenPGP credentials */
301
if ((ret = gnutls_certificate_allocate_credentials (&mc->cred))
278
302
!= GNUTLS_E_SUCCESS) {
279
fprintf (stderr, "memory error: %s\n",
303
fprintf (stderr, "GnuTLS memory error: %s\n",
280
304
safer_gnutls_strerror(ret));
285
309
fprintf(stderr, "Attempting to use OpenPGP certificate %s"
286
" and keyfile %s as GnuTLS credentials\n", certfile,
310
" and keyfile %s as GnuTLS credentials\n", pubkeyfile,
290
314
ret = gnutls_certificate_set_openpgp_key_file
291
(es->cred, certfile, certkey, GNUTLS_OPENPGP_FMT_BASE64);
315
(mc->cred, pubkeyfile, seckeyfile, GNUTLS_OPENPGP_FMT_BASE64);
292
316
if (ret != GNUTLS_E_SUCCESS) {
294
(stderr, "Error[%d] while reading the OpenPGP key pair ('%s',"
296
ret, certfile, certkey);
297
fprintf(stdout, "The Error is: %s\n",
318
"Error[%d] while reading the OpenPGP key pair ('%s',"
319
" '%s')\n", ret, pubkeyfile, seckeyfile);
320
fprintf(stdout, "The GnuTLS error is: %s\n",
298
321
safer_gnutls_strerror(ret));
302
//GnuTLS server initialization
303
if ((ret = gnutls_dh_params_init (&es->dh_params))
304
!= GNUTLS_E_SUCCESS) {
305
fprintf (stderr, "Error in dh parameter initialization: %s\n",
306
safer_gnutls_strerror(ret));
310
if ((ret = gnutls_dh_params_generate2 (es->dh_params, DH_BITS))
311
!= GNUTLS_E_SUCCESS) {
312
fprintf (stderr, "Error in prime generation: %s\n",
313
safer_gnutls_strerror(ret));
317
gnutls_certificate_set_dh_params (es->cred, es->dh_params);
319
// GnuTLS session creation
320
if ((ret = gnutls_init (&es->session, GNUTLS_SERVER))
321
!= GNUTLS_E_SUCCESS){
325
/* GnuTLS server initialization */
326
ret = gnutls_dh_params_init(dh_params);
327
if (ret != GNUTLS_E_SUCCESS) {
328
fprintf (stderr, "Error in GnuTLS DH parameter initialization:"
329
" %s\n", safer_gnutls_strerror(ret));
332
ret = gnutls_dh_params_generate2(*dh_params, mc->dh_bits);
333
if (ret != GNUTLS_E_SUCCESS) {
334
fprintf (stderr, "Error in GnuTLS prime generation: %s\n",
335
safer_gnutls_strerror(ret));
339
gnutls_certificate_set_dh_params(mc->cred, *dh_params);
341
/* GnuTLS session creation */
342
ret = gnutls_init(session, GNUTLS_SERVER);
343
if (ret != GNUTLS_E_SUCCESS){
322
344
fprintf(stderr, "Error in GnuTLS session initialization: %s\n",
323
345
safer_gnutls_strerror(ret));
326
if ((ret = gnutls_priority_set_direct (es->session, mc->priority, &err))
327
!= GNUTLS_E_SUCCESS) {
328
fprintf(stderr, "Syntax error at: %s\n", err);
329
fprintf(stderr, "GnuTLS error: %s\n",
330
safer_gnutls_strerror(ret));
350
ret = gnutls_priority_set_direct(*session, mc->priority, &err);
351
if (ret != GNUTLS_E_SUCCESS) {
352
fprintf(stderr, "Syntax error at: %s\n", err);
353
fprintf(stderr, "GnuTLS error: %s\n",
354
safer_gnutls_strerror(ret));
334
if ((ret = gnutls_credentials_set
335
(es->session, GNUTLS_CRD_CERTIFICATE, es->cred))
336
!= GNUTLS_E_SUCCESS) {
337
fprintf(stderr, "Error setting a credentials set: %s\n",
359
ret = gnutls_credentials_set(*session, GNUTLS_CRD_CERTIFICATE,
361
if (ret != GNUTLS_E_SUCCESS) {
362
fprintf(stderr, "Error setting GnuTLS credentials: %s\n",
338
363
safer_gnutls_strerror(ret));
342
367
/* ignore client certificate if any. */
343
gnutls_certificate_server_set_request (es->session,
368
gnutls_certificate_server_set_request (*session,
344
369
GNUTLS_CERT_IGNORE);
346
gnutls_dh_set_prime_bits (es->session, DH_BITS);
371
gnutls_dh_set_prime_bits (*session, mc->dh_bits);
376
/* Avahi log function callback */
351
377
static void empty_log(__attribute__((unused)) AvahiLogLevel level,
352
378
__attribute__((unused)) const char *txt){}
380
/* Called when a Mandos server is found */
354
381
static int start_mandos_communication(const char *ip, uint16_t port,
355
382
AvahiIfIndex if_index,
356
383
mandos_context *mc){
358
385
struct sockaddr_in6 to;
359
encrypted_session es;
360
386
char *buffer = NULL;
361
387
char *decrypted_buffer;
362
388
size_t buffer_length = 0;
407
439
fprintf(stderr, "Connection to: %s, port %d\n", ip, port);
408
/* char addrstr[INET6_ADDRSTRLEN]; */
409
/* if(inet_ntop(to.sin6_family, &(to.sin6_addr), addrstr, */
410
/* sizeof(addrstr)) == NULL){ */
411
/* perror("inet_ntop"); */
413
/* fprintf(stderr, "Really connecting to: %s, port %d\n", */
414
/* addrstr, ntohs(to.sin6_port)); */
440
char addrstr[INET6_ADDRSTRLEN] = "";
441
if(inet_ntop(to.sin6_family, &(to.sin6_addr), addrstr,
442
sizeof(addrstr)) == NULL){
445
if(strcmp(addrstr, ip) != 0){
446
fprintf(stderr, "Canonical address form: %s\n", addrstr);
418
451
ret = connect(tcp_sd, (struct sockaddr *) &to, sizeof(to));
473
500
case GNUTLS_E_AGAIN:
475
502
case GNUTLS_E_REHANDSHAKE:
476
ret = gnutls_handshake (es.session);
503
ret = gnutls_handshake (session);
478
fprintf(stderr, "\n*** Handshake failed ***\n");
505
fprintf(stderr, "*** GnuTLS Re-handshake failed ***\n");
479
506
gnutls_perror (ret);
485
512
fprintf(stderr, "Unknown error while reading data from"
486
" encrypted session with mandos server\n");
513
" encrypted session with Mandos server\n");
488
gnutls_bye (es.session, GNUTLS_SHUT_RDWR);
515
gnutls_bye (session, GNUTLS_SHUT_RDWR);
492
519
buffer_length += (size_t) ret;
524
fprintf(stderr, "Closing TLS session\n");
527
gnutls_bye (session, GNUTLS_SHUT_RDWR);
496
529
if (buffer_length > 0){
497
530
decrypted_buffer_size = pgp_packet_decrypt(buffer,
499
532
&decrypted_buffer,
501
534
if (decrypted_buffer_size >= 0){
502
535
while(written < (size_t) decrypted_buffer_size){
503
536
ret = (int)fwrite (decrypted_buffer + written, 1,
525
fprintf(stderr, "Closing TLS session\n");
555
/* Shutdown procedure */
529
gnutls_bye (es.session, GNUTLS_SHUT_RDWR);
532
gnutls_deinit (es.session);
533
gnutls_certificate_free_credentials (es.cred);
560
gnutls_deinit (session);
561
gnutls_certificate_free_credentials (mc->cred);
534
562
gnutls_global_deinit ();
538
static void resolve_callback( AvahiSServiceResolver *r,
539
AvahiIfIndex interface,
540
AVAHI_GCC_UNUSED AvahiProtocol protocol,
541
AvahiResolverEvent event,
545
const char *host_name,
546
const AvahiAddress *address,
548
AVAHI_GCC_UNUSED AvahiStringList *txt,
549
AVAHI_GCC_UNUSED AvahiLookupResultFlags flags,
550
AVAHI_GCC_UNUSED void* userdata) {
566
static void resolve_callback(AvahiSServiceResolver *r,
567
AvahiIfIndex interface,
568
AVAHI_GCC_UNUSED AvahiProtocol protocol,
569
AvahiResolverEvent event,
573
const char *host_name,
574
const AvahiAddress *address,
576
AVAHI_GCC_UNUSED AvahiStringList *txt,
577
AVAHI_GCC_UNUSED AvahiLookupResultFlags
551
580
mandos_context *mc = userdata;
552
581
assert(r); /* Spurious warning */
599
629
case AVAHI_BROWSER_FAILURE:
601
fprintf(stderr, "(Browser) %s\n",
631
fprintf(stderr, "(Avahi browser) %s\n",
602
632
avahi_strerror(avahi_server_errno(mc->server)));
603
633
avahi_simple_poll_quit(mc->simple_poll);
606
636
case AVAHI_BROWSER_NEW:
607
/* We ignore the returned resolver object. In the callback
608
function we free it. If the server is terminated before
609
the callback function is called the server will free
610
the resolver for us. */
612
if (!(avahi_s_service_resolver_new(mc->server, interface, protocol, name,
637
/* We ignore the returned Avahi resolver object. In the callback
638
function we free it. If the Avahi server is terminated before
639
the callback function is called the Avahi server will free the
642
if (!(avahi_s_service_resolver_new(mc->server, interface,
643
protocol, name, type, domain,
614
644
AVAHI_PROTO_INET6, 0,
615
645
resolve_callback, mc)))
616
fprintf(stderr, "Failed to resolve service '%s': %s\n", name,
617
avahi_strerror(avahi_server_errno(s)));
646
fprintf(stderr, "Avahi: Failed to resolve service '%s': %s\n",
647
name, avahi_strerror(avahi_server_errno(mc->server)));
620
650
case AVAHI_BROWSER_REMOVE:
623
653
case AVAHI_BROWSER_ALL_FOR_NOW:
624
654
case AVAHI_BROWSER_CACHE_EXHAUSTED:
656
fprintf(stderr, "No Mandos server found, still searching...\n");
639
memcpy(tmp, first, f_len);
672
memcpy(tmp, first, f_len); /* Spurious warning */
641
674
tmp[f_len] = '/';
643
memcpy(tmp + f_len + 1, second, s_len);
676
memcpy(tmp + f_len + 1, second, s_len); /* Spurious warning */
645
678
tmp[f_len + 1 + s_len] = '\0';
650
int main(AVAHI_GCC_UNUSED int argc, AVAHI_GCC_UNUSED char*argv[]) {
651
AvahiServerConfig config;
683
int main(int argc, char *argv[]){
652
684
AvahiSServiceBrowser *sb = NULL;
655
int returncode = EXIT_SUCCESS;
687
int exitcode = EXIT_SUCCESS;
656
688
const char *interface = "eth0";
657
689
struct ifreq network;
659
691
char *connect_to = NULL;
660
692
AvahiIfIndex if_index = AVAHI_IF_UNSPEC;
661
693
mandos_context mc = { .simple_poll = NULL, .server = NULL,
662
.dh_bits = 2048, .priority = "SECURE256"};
694
.dh_bits = 1024, .priority = "SECURE256"};
665
static struct option long_options[] = {
666
{"debug", no_argument, (int *)&debug, 1},
667
{"connect", required_argument, 0, 'C'},
668
{"interface", required_argument, 0, 'i'},
669
{"certdir", required_argument, 0, 'd'},
670
{"certkey", required_argument, 0, 'c'},
671
{"certfile", required_argument, 0, 'k'},
672
{"dh_bits", required_argument, 0, 'D'},
673
{"priority", required_argument, 0, 'p'},
676
int option_index = 0;
677
ret = getopt_long (argc, argv, "i:", long_options,
697
/* Temporary int to get the address of for getopt_long */
698
int debug_int = debug ? 1 : 0;
700
struct option long_options[] = {
701
{"debug", no_argument, &debug_int, 1},
702
{"connect", required_argument, NULL, 'c'},
703
{"interface", required_argument, NULL, 'i'},
704
{"keydir", required_argument, NULL, 'd'},
705
{"seckey", required_argument, NULL, 's'},
706
{"pubkey", required_argument, NULL, 'p'},
707
{"dh-bits", required_argument, NULL, 'D'},
708
{"priority", required_argument, NULL, 'P'},
711
int option_index = 0;
712
ret = getopt_long (argc, argv, "i:", long_options,
706
tmp = strtol(optarg, NULL, 10);
707
if (errno == ERANGE){
739
mc.dh_bits = (unsigned int) strtol(optarg, NULL, 10);
708
741
perror("strtol");
709
742
exit(EXIT_FAILURE);
746
mc.priority = optarg;
750
/* getopt_long() has already printed a message about the
751
unrcognized option, so just exit. */
715
mc.priority = optarg;
722
certfile = combinepath(certdir, certfile);
723
if (certfile == NULL){
724
perror("combinepath");
725
returncode = EXIT_FAILURE;
729
certkey = combinepath(certdir, certkey);
730
if (certkey == NULL){
731
perror("combinepath");
732
returncode = EXIT_FAILURE;
755
/* Set the global debug flag from the temporary int */
756
debug = debug_int ? true : false;
759
pubkeyfile = combinepath(keydir, pubkeyfile);
760
if (pubkeyfile == NULL){
761
perror("combinepath");
762
exitcode = EXIT_FAILURE;
766
seckeyfile = combinepath(keydir, seckeyfile);
767
if (seckeyfile == NULL){
768
perror("combinepath");
736
772
if_index = (AvahiIfIndex) if_nametoindex(interface);
766
sd = socket(PF_INET6, SOCK_DGRAM, IPPROTO_IP);
769
returncode = EXIT_FAILURE;
772
strcpy(network.ifr_name, interface);
773
ret = ioctl(sd, SIOCGIFFLAGS, &network);
776
perror("ioctl SIOCGIFFLAGS");
777
returncode = EXIT_FAILURE;
780
if((network.ifr_flags & IFF_UP) == 0){
781
network.ifr_flags |= IFF_UP;
782
ret = ioctl(sd, SIOCSIFFLAGS, &network);
802
/* If the interface is down, bring it up */
804
sd = socket(PF_INET6, SOCK_DGRAM, IPPROTO_IP);
807
exitcode = EXIT_FAILURE;
810
strcpy(network.ifr_name, interface); /* Spurious warning */
811
ret = ioctl(sd, SIOCGIFFLAGS, &network);
784
perror("ioctl SIOCSIFFLAGS");
785
returncode = EXIT_FAILURE;
813
perror("ioctl SIOCGIFFLAGS");
814
exitcode = EXIT_FAILURE;
817
if((network.ifr_flags & IFF_UP) == 0){
818
network.ifr_flags |= IFF_UP;
819
ret = ioctl(sd, SIOCSIFFLAGS, &network);
821
perror("ioctl SIOCSIFFLAGS");
822
exitcode = EXIT_FAILURE;
792
830
avahi_set_log_function(empty_log);
795
/* Initialize the psuedo-RNG */
833
/* Initialize the pseudo-RNG for Avahi */
796
834
srand((unsigned int) time(NULL));
798
/* Allocate main loop object */
799
if (!(mc.simple_poll = avahi_simple_poll_new())) {
800
fprintf(stderr, "Failed to create simple poll object.\n");
801
returncode = EXIT_FAILURE;
805
/* Do not publish any local records */
806
avahi_server_config_init(&config);
807
config.publish_hinfo = 0;
808
config.publish_addresses = 0;
809
config.publish_workstation = 0;
810
config.publish_domain = 0;
812
/* Allocate a new server */
813
mc.server = avahi_server_new(avahi_simple_poll_get(simple_poll),
814
&config, NULL, NULL, &error);
816
/* Free the configuration data */
817
avahi_server_config_free(&config);
819
/* Check if creating the server object succeeded */
821
fprintf(stderr, "Failed to create server: %s\n",
836
/* Allocate main Avahi loop object */
837
mc.simple_poll = avahi_simple_poll_new();
838
if (mc.simple_poll == NULL) {
839
fprintf(stderr, "Avahi: Failed to create simple poll"
841
exitcode = EXIT_FAILURE;
846
AvahiServerConfig config;
847
/* Do not publish any local Zeroconf records */
848
avahi_server_config_init(&config);
849
config.publish_hinfo = 0;
850
config.publish_addresses = 0;
851
config.publish_workstation = 0;
852
config.publish_domain = 0;
854
/* Allocate a new server */
855
mc.server = avahi_server_new(avahi_simple_poll_get
856
(mc.simple_poll), &config, NULL,
859
/* Free the Avahi configuration data */
860
avahi_server_config_free(&config);
863
/* Check if creating the Avahi server object succeeded */
864
if (mc.server == NULL) {
865
fprintf(stderr, "Failed to create Avahi server: %s\n",
822
866
avahi_strerror(error));
823
returncode = EXIT_FAILURE;
867
exitcode = EXIT_FAILURE;
827
/* Create the service browser */
871
/* Create the Avahi service browser */
828
872
sb = avahi_s_service_browser_new(mc.server, if_index,
829
873
AVAHI_PROTO_INET6,
830
874
"_mandos._tcp", NULL, 0,
831
875
browse_callback, &mc);
833
877
fprintf(stderr, "Failed to create service browser: %s\n",
834
878
avahi_strerror(avahi_server_errno(mc.server)));
835
returncode = EXIT_FAILURE;
879
exitcode = EXIT_FAILURE;
839
883
/* Run the main loop */
842
fprintf(stderr, "Starting avahi loop search\n");
886
fprintf(stderr, "Starting Avahi loop search\n");
845
avahi_simple_poll_loop(simple_poll);
889
avahi_simple_poll_loop(mc.simple_poll);
850
894
fprintf(stderr, "%s exiting\n", argv[0]);
853
897
/* Cleanup things */
855
899
avahi_s_service_browser_free(sb);
901
if (mc.server != NULL)
858
902
avahi_server_free(mc.server);
861
avahi_simple_poll_free(simple_poll);
904
if (mc.simple_poll != NULL)
905
avahi_simple_poll_free(mc.simple_poll);