65
65
#include <errno.h> /* perror() */
69
69
#include <getopt.h>
72
#define CERT_ROOT "/conf/conf.d/cryptkeyreq/"
74
#define CERTFILE CERT_ROOT "openpgp-client.txt"
75
#define KEYFILE CERT_ROOT "openpgp-client-key.txt"
71
76
#define BUFFER_SIZE 256
73
static const char *keydir = "/conf/conf.d/mandos";
74
static const char *pubkeyfile = "pubkey.txt";
75
static const char *seckeyfile = "seckey.txt";
77
79
bool debug = false;
79
/* Used for passing in values through all the callback functions */
81
AvahiSimplePoll *simple_poll;
82
gnutls_session_t session;
83
83
gnutls_certificate_credentials_t cred;
88
static ssize_t pgp_packet_decrypt (char *packet, size_t packet_size,
84
gnutls_dh_params_t dh_params;
88
ssize_t pgp_packet_decrypt (char *packet, size_t packet_size,
89
char **new_packet, const char *homedir){
91
90
gpgme_data_t dh_crypto, dh_plain;
252
static void debuggnutls(__attribute__((unused)) int level,
244
void debuggnutls(__attribute__((unused)) int level,
254
246
fprintf(stderr, "%s", string);
257
static int initgnutls(mandos_context *mc, gnutls_session_t *session,
258
gnutls_dh_params_t *dh_params){
249
int initgnutls(encrypted_session *es){
263
254
fprintf(stderr, "Initializing GnuTLS\n");
266
257
if ((ret = gnutls_global_init ())
267
258
!= GNUTLS_E_SUCCESS) {
268
259
fprintf (stderr, "global_init: %s\n", safer_gnutls_strerror(ret));
273
264
gnutls_global_set_log_level(11);
274
265
gnutls_global_set_log_function(debuggnutls);
277
268
/* openpgp credentials */
278
if ((ret = gnutls_certificate_allocate_credentials (&mc->cred))
269
if ((ret = gnutls_certificate_allocate_credentials (&es->cred))
279
270
!= GNUTLS_E_SUCCESS) {
280
271
fprintf (stderr, "memory error: %s\n",
281
272
safer_gnutls_strerror(ret));
286
277
fprintf(stderr, "Attempting to use OpenPGP certificate %s"
287
" and keyfile %s as GnuTLS credentials\n", pubkeyfile,
278
" and keyfile %s as GnuTLS credentials\n", CERTFILE,
291
282
ret = gnutls_certificate_set_openpgp_key_file
292
(mc->cred, pubkeyfile, seckeyfile, GNUTLS_OPENPGP_FMT_BASE64);
283
(es->cred, CERTFILE, KEYFILE, GNUTLS_OPENPGP_FMT_BASE64);
293
284
if (ret != GNUTLS_E_SUCCESS) {
295
286
(stderr, "Error[%d] while reading the OpenPGP key pair ('%s',"
297
ret, pubkeyfile, seckeyfile);
288
ret, CERTFILE, KEYFILE);
298
289
fprintf(stdout, "The Error is: %s\n",
299
290
safer_gnutls_strerror(ret));
303
294
//GnuTLS server initialization
304
if ((ret = gnutls_dh_params_init(dh_params))
295
if ((ret = gnutls_dh_params_init (&es->dh_params))
305
296
!= GNUTLS_E_SUCCESS) {
306
297
fprintf (stderr, "Error in dh parameter initialization: %s\n",
307
298
safer_gnutls_strerror(ret));
311
if ((ret = gnutls_dh_params_generate2(*dh_params, mc->dh_bits))
302
if ((ret = gnutls_dh_params_generate2 (es->dh_params, DH_BITS))
312
303
!= GNUTLS_E_SUCCESS) {
313
304
fprintf (stderr, "Error in prime generation: %s\n",
314
305
safer_gnutls_strerror(ret));
318
gnutls_certificate_set_dh_params(mc->cred, *dh_params);
309
gnutls_certificate_set_dh_params (es->cred, es->dh_params);
320
311
// GnuTLS session creation
321
if ((ret = gnutls_init(session, GNUTLS_SERVER))
312
if ((ret = gnutls_init (&es->session, GNUTLS_SERVER))
322
313
!= GNUTLS_E_SUCCESS){
323
314
fprintf(stderr, "Error in GnuTLS session initialization: %s\n",
324
315
safer_gnutls_strerror(ret));
327
if ((ret = gnutls_priority_set_direct(*session, mc->priority, &err))
318
if ((ret = gnutls_priority_set_direct (es->session, "NORMAL", &err))
328
319
!= GNUTLS_E_SUCCESS) {
329
320
fprintf(stderr, "Syntax error at: %s\n", err);
330
321
fprintf(stderr, "GnuTLS error: %s\n",
343
334
/* ignore client certificate if any. */
344
gnutls_certificate_server_set_request (*session,
335
gnutls_certificate_server_set_request (es->session,
345
336
GNUTLS_CERT_IGNORE);
347
gnutls_dh_set_prime_bits (*session, mc->dh_bits);
338
gnutls_dh_set_prime_bits (es->session, DH_BITS);
352
static void empty_log(__attribute__((unused)) AvahiLogLevel level,
353
__attribute__((unused)) const char *txt){}
343
void empty_log(__attribute__((unused)) AvahiLogLevel level,
344
__attribute__((unused)) const char *txt){}
355
static int start_mandos_communication(const char *ip, uint16_t port,
356
AvahiIfIndex if_index,
346
int start_mandos_communication(const char *ip, uint16_t port,
347
unsigned int if_index){
359
349
struct sockaddr_in6 to;
350
encrypted_session es;
360
351
char *buffer = NULL;
361
352
char *decrypted_buffer;
362
353
size_t buffer_length = 0;
528
gnutls_bye (session, GNUTLS_SHUT_RDWR);
511
gnutls_bye (es.session, GNUTLS_SHUT_RDWR);
531
gnutls_deinit (session);
532
gnutls_certificate_free_credentials (mc->cred);
514
gnutls_deinit (es.session);
515
gnutls_certificate_free_credentials (es.cred);
533
516
gnutls_global_deinit ();
537
static void resolve_callback( AvahiSServiceResolver *r,
538
AvahiIfIndex interface,
539
AVAHI_GCC_UNUSED AvahiProtocol protocol,
540
AvahiResolverEvent event,
544
const char *host_name,
545
const AvahiAddress *address,
547
AVAHI_GCC_UNUSED AvahiStringList *txt,
548
AVAHI_GCC_UNUSED AvahiLookupResultFlags flags,
550
mandos_context *mc = userdata;
520
static AvahiSimplePoll *simple_poll = NULL;
521
static AvahiServer *server = NULL;
523
static void resolve_callback(
524
AvahiSServiceResolver *r,
525
AvahiIfIndex interface,
526
AVAHI_GCC_UNUSED AvahiProtocol protocol,
527
AvahiResolverEvent event,
531
const char *host_name,
532
const AvahiAddress *address,
534
AVAHI_GCC_UNUSED AvahiStringList *txt,
535
AVAHI_GCC_UNUSED AvahiLookupResultFlags flags,
536
AVAHI_GCC_UNUSED void* userdata) {
551
538
assert(r); /* Spurious warning */
553
540
/* Called whenever a service has been resolved successfully or
578
566
avahi_s_service_resolver_free(r);
581
static void browse_callback( AvahiSServiceBrowser *b,
582
AvahiIfIndex interface,
583
AvahiProtocol protocol,
584
AvahiBrowserEvent event,
588
AVAHI_GCC_UNUSED AvahiLookupResultFlags flags,
590
mandos_context *mc = userdata;
591
assert(b); /* Spurious warning */
593
/* Called whenever a new services becomes available on the LAN or
594
is removed from the LAN */
598
case AVAHI_BROWSER_FAILURE:
600
fprintf(stderr, "(Browser) %s\n",
601
avahi_strerror(avahi_server_errno(mc->server)));
602
avahi_simple_poll_quit(mc->simple_poll);
605
case AVAHI_BROWSER_NEW:
606
/* We ignore the returned resolver object. In the callback
607
function we free it. If the server is terminated before
608
the callback function is called the server will free
609
the resolver for us. */
611
if (!(avahi_s_service_resolver_new(mc->server, interface, protocol, name,
613
AVAHI_PROTO_INET6, 0,
614
resolve_callback, mc)))
615
fprintf(stderr, "Failed to resolve service '%s': %s\n", name,
616
avahi_strerror(avahi_server_errno(mc->server)));
619
case AVAHI_BROWSER_REMOVE:
622
case AVAHI_BROWSER_ALL_FOR_NOW:
623
case AVAHI_BROWSER_CACHE_EXHAUSTED:
628
/* Combines file name and path and returns the malloced new
629
string. some sane checks could/should be added */
630
static const char *combinepath(const char *first, const char *second){
631
size_t f_len = strlen(first);
632
size_t s_len = strlen(second);
633
char *tmp = malloc(f_len + s_len + 2);
638
memcpy(tmp, first, f_len); /* Spurious warning */
642
memcpy(tmp + f_len + 1, second, s_len); /* Spurious warning */
644
tmp[f_len + 1 + s_len] = '\0';
569
static void browse_callback(
570
AvahiSServiceBrowser *b,
571
AvahiIfIndex interface,
572
AvahiProtocol protocol,
573
AvahiBrowserEvent event,
577
AVAHI_GCC_UNUSED AvahiLookupResultFlags flags,
580
AvahiServer *s = userdata;
581
assert(b); /* Spurious warning */
583
/* Called whenever a new services becomes available on the LAN or
584
is removed from the LAN */
588
case AVAHI_BROWSER_FAILURE:
590
fprintf(stderr, "(Browser) %s\n",
591
avahi_strerror(avahi_server_errno(server)));
592
avahi_simple_poll_quit(simple_poll);
595
case AVAHI_BROWSER_NEW:
596
/* We ignore the returned resolver object. In the callback
597
function we free it. If the server is terminated before
598
the callback function is called the server will free
599
the resolver for us. */
601
if (!(avahi_s_service_resolver_new(s, interface, protocol, name,
603
AVAHI_PROTO_INET6, 0,
604
resolve_callback, s)))
605
fprintf(stderr, "Failed to resolve service '%s': %s\n", name,
606
avahi_strerror(avahi_server_errno(s)));
609
case AVAHI_BROWSER_REMOVE:
612
case AVAHI_BROWSER_ALL_FOR_NOW:
613
case AVAHI_BROWSER_CACHE_EXHAUSTED:
649
618
int main(AVAHI_GCC_UNUSED int argc, AVAHI_GCC_UNUSED char*argv[]) {
650
619
AvahiServerConfig config;
651
620
AvahiSServiceBrowser *sb = NULL;
655
623
int returncode = EXIT_SUCCESS;
656
624
const char *interface = "eth0";
657
struct ifreq network;
659
char *connect_to = NULL;
660
AvahiIfIndex if_index = AVAHI_IF_UNSPEC;
661
mandos_context mc = { .simple_poll = NULL, .server = NULL,
662
.dh_bits = 1024, .priority = "SECURE256"};
664
debug_int = debug ? 1 : 0;
666
struct option long_options[] = {
667
{"debug", no_argument, &debug_int, 1},
668
{"connect", required_argument, NULL, 'c'},
669
{"interface", required_argument, NULL, 'i'},
670
{"keydir", required_argument, NULL, 'd'},
671
{"seckey", required_argument, NULL, 's'},
672
{"pubkey", required_argument, NULL, 'p'},
673
{"dh-bits", required_argument, NULL, 'D'},
674
{"priority", required_argument, NULL, 'P'},
627
static struct option long_options[] = {
628
{"debug", no_argument, (int *)&debug, 1},
629
{"interface", required_argument, 0, 'i'},
677
632
int option_index = 0;
689
644
interface = optarg;
705
mc.dh_bits = (unsigned int) strtol(optarg, NULL, 10);
712
mc.priority = optarg;
716
647
exit(EXIT_FAILURE);
719
debug = debug_int ? true : false;
721
pubkeyfile = combinepath(keydir, pubkeyfile);
722
if (pubkeyfile == NULL){
723
perror("combinepath");
724
returncode = EXIT_FAILURE;
728
seckeyfile = combinepath(keydir, seckeyfile);
729
if (seckeyfile == NULL){
730
perror("combinepath");
734
if_index = (AvahiIfIndex) if_nametoindex(interface);
736
fprintf(stderr, "No such interface: \"%s\"\n", interface);
740
if(connect_to != NULL){
741
/* Connect directly, do not use Zeroconf */
742
/* (Mainly meant for debugging) */
743
char *address = strrchr(connect_to, ':');
745
fprintf(stderr, "No colon in address\n");
749
uint16_t port = (uint16_t) strtol(address+1, NULL, 10);
751
perror("Bad port number");
755
address = connect_to;
756
ret = start_mandos_communication(address, port, if_index, &mc);
764
sd = socket(PF_INET6, SOCK_DGRAM, IPPROTO_IP);
767
returncode = EXIT_FAILURE;
770
strcpy(network.ifr_name, interface); /* Spurious warning */
771
ret = ioctl(sd, SIOCGIFFLAGS, &network);
774
perror("ioctl SIOCGIFFLAGS");
775
returncode = EXIT_FAILURE;
778
if((network.ifr_flags & IFF_UP) == 0){
779
network.ifr_flags |= IFF_UP;
780
ret = ioctl(sd, SIOCSIFFLAGS, &network);
782
perror("ioctl SIOCSIFFLAGS");
783
returncode = EXIT_FAILURE;
790
652
avahi_set_log_function(empty_log);