/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/password-request.c

  • Committer: Teddy Hogeborn
  • Date: 2008-08-29 05:53:59 UTC
  • Revision ID: teddy@fukt.bsnet.se-20080829055359-wkdasnyxtylmnxus
* mandos.xml (EXAMPLE): Replaced all occurences of command name with
                        "&COMMANDNAME;".

* plugins.d/password-prompt.c (main): Improved some documentation
                                      strings.  Do perror() of
                                      tcgetattr() fails.  Add debug
                                      output if interrupted by signal.
                                      Loop over write() instead of
                                      using fwrite() when outputting
                                      password.  Add debug output if
                                      getline() returns 0, unless it
                                      was caused by a signal.  Add
                                      exit status code to debug
                                      output.

* plugins.d/password-prompt.xml: Changed all single quotes to double
                                 quotes for consistency.  Removed
                                 <?xml-stylesheet>.
  (ENTITY TIMESTAMP): New.  Automatically updated by Emacs time-stamp
                      by using Emacs local variables.
  (/refentry/refentryinfo/title): Changed to "Mandos Manual".
  (/refentry/refentryinfo/productname): Changed to "Mandos".
  (/refentry/refentryinfo/date): New; set to "&TIMESTAMP;".
  (/refentry/refentryinfo/copyright): Split copyright holders.
  (/refentry/refnamediv/refpurpose): Improved wording.
  (SYNOPSIS): Fix to use correct markup.  Add short options.
  (DESCRIPTION, OPTIONS): Improved wording.
  (OPTIONS): Improved wording.  Use more correct markup.  Document
             short options.
  (EXIT STATUS): Add text.
  (ENVIRONMENT): Document use of "cryptsource" and "crypttarget".
  (FILES): REMOVED.
  (BUGS): Add text.
  (EXAMPLE): Added some examples.
  (SECURITY): Added text.
  (SEE ALSO): Remove reference to mandos(8).  Add reference to
              crypttab(5).

Show diffs side-by-side

added added

removed removed

Lines of Context:
32
32
#define _LARGEFILE_SOURCE
33
33
#define _FILE_OFFSET_BITS 64
34
34
 
35
 
#define _GNU_SOURCE             /* TEMP_FAILURE_RETRY() */
 
35
#define _GNU_SOURCE             /* TEMP_FAILURE_RETRY(), asprintf() */
36
36
 
37
 
#include <stdio.h>
38
 
#include <assert.h>
39
 
#include <stdlib.h>
40
 
#include <time.h>
41
 
#include <net/if.h>             /* if_nametoindex */
42
 
#include <sys/ioctl.h>          /* ioctl, ifreq, SIOCGIFFLAGS, IFF_UP,
43
 
                                   SIOCSIFFLAGS */
 
37
#include <stdio.h>              /* fprintf(), stderr, fwrite(),
 
38
                                   stdout, ferror() */
 
39
#include <stdint.h>             /* uint16_t, uint32_t */
 
40
#include <stddef.h>             /* NULL, size_t, ssize_t */
 
41
#include <stdlib.h>             /* free(), EXIT_SUCCESS, EXIT_FAILURE,
 
42
                                   srand() */
 
43
#include <stdbool.h>            /* bool, true */
 
44
#include <string.h>             /* memset(), strcmp(), strlen(),
 
45
                                   strerror(), asprintf(), strcpy() */
 
46
#include <sys/ioctl.h>          /* ioctl */
 
47
#include <sys/types.h>          /* socket(), inet_pton(), sockaddr,
 
48
                                   sockaddr_in6, PF_INET6,
 
49
                                   SOCK_STREAM, INET6_ADDRSTRLEN,
 
50
                                   uid_t, gid_t */
 
51
#include <inttypes.h>           /* PRIu16 */
 
52
#include <sys/socket.h>         /* socket(), struct sockaddr_in6,
 
53
                                   struct in6_addr, inet_pton(),
 
54
                                   connect() */
 
55
#include <assert.h>             /* assert() */
 
56
#include <errno.h>              /* perror(), errno */
 
57
#include <time.h>               /* time() */
44
58
#include <net/if.h>             /* ioctl, ifreq, SIOCGIFFLAGS, IFF_UP,
45
 
                                   SIOCSIFFLAGS */
 
59
                                   SIOCSIFFLAGS, if_indextoname(),
 
60
                                   if_nametoindex(), IF_NAMESIZE */
 
61
#include <unistd.h>             /* close(), SEEK_SET, off_t, write(),
 
62
                                   getuid(), getgid(), setuid(),
 
63
                                   setgid() */
 
64
#include <netinet/in.h>
 
65
#include <arpa/inet.h>          /* inet_pton(), htons */
 
66
#include <iso646.h>             /* not, and */
 
67
#include <argp.h>               /* struct argp_option, error_t, struct
 
68
                                   argp_state, struct argp,
 
69
                                   argp_parse(), ARGP_KEY_ARG,
 
70
                                   ARGP_KEY_END, ARGP_ERR_UNKNOWN */
46
71
 
 
72
/* Avahi */
 
73
/* All Avahi types, constants and functions
 
74
 Avahi*, avahi_*,
 
75
 AVAHI_* */
47
76
#include <avahi-core/core.h>
48
77
#include <avahi-core/lookup.h>
49
78
#include <avahi-core/log.h>
51
80
#include <avahi-common/malloc.h>
52
81
#include <avahi-common/error.h>
53
82
 
54
 
/* Mandos client part */
55
 
#include <sys/types.h>          /* socket(), inet_pton() */
56
 
#include <sys/socket.h>         /* socket(), struct sockaddr_in6,
57
 
                                   struct in6_addr, inet_pton() */
58
 
#include <gnutls/gnutls.h>      /* All GnuTLS stuff */
59
 
#include <gnutls/openpgp.h>     /* GnuTLS with openpgp stuff */
 
83
/* GnuTLS */
 
84
#include <gnutls/gnutls.h>      /* All GnuTLS types, constants and
 
85
                                   functions:
 
86
                                   gnutls_*
 
87
                                   init_gnutls_session(),
 
88
                                   GNUTLS_* */
 
89
#include <gnutls/openpgp.h>     /* gnutls_certificate_set_openpgp_key_file(),
 
90
                                   GNUTLS_OPENPGP_FMT_BASE64 */
60
91
 
61
 
#include <unistd.h>             /* close() */
62
 
#include <netinet/in.h>
63
 
#include <stdbool.h>            /* true */
64
 
#include <string.h>             /* memset */
65
 
#include <arpa/inet.h>          /* inet_pton() */
66
 
#include <iso646.h>             /* not */
67
 
#include <net/if.h>             /* IF_NAMESIZE */
68
 
#include <argp.h>               /* struct argp_option,
69
 
                                   struct argp_state, struct argp,
70
 
                                   argp_parse() */
71
92
/* GPGME */
72
 
#include <errno.h>              /* perror() */
73
 
#include <gpgme.h>
 
93
#include <gpgme.h>              /* All GPGME types, constants and
 
94
                                   functions:
 
95
                                   gpgme_*
 
96
                                   GPGME_PROTOCOL_OpenPGP,
 
97
                                   GPG_ERR_NO_* */
74
98
 
75
99
#define BUFFER_SIZE 256
76
100
 
77
101
bool debug = false;
78
102
static const char *keydir = "/conf/conf.d/mandos";
79
103
static const char mandos_protocol_version[] = "1";
80
 
const char *argp_program_version = "mandosclient 0.9";
 
104
const char *argp_program_version = "password-request 1.0";
81
105
const char *argp_program_bug_address = "<mandos@fukt.bsnet.se>";
82
106
 
83
107
/* Used for passing in values through the Avahi callback functions */
190
214
    fprintf(stderr, "bad gpgme_op_decrypt: %s: %s\n",
191
215
            gpgme_strsource(rc), gpgme_strerror(rc));
192
216
    plaintext_length = -1;
 
217
    if (debug){
 
218
      gpgme_decrypt_result_t result;
 
219
      result = gpgme_op_decrypt_result(ctx);
 
220
      if (result == NULL){
 
221
        fprintf(stderr, "gpgme_op_decrypt_result failed\n");
 
222
      } else {
 
223
        fprintf(stderr, "Unsupported algorithm: %s\n",
 
224
                result->unsupported_algorithm);
 
225
        fprintf(stderr, "Wrong key usage: %u\n",
 
226
                result->wrong_key_usage);
 
227
        if(result->file_name != NULL){
 
228
          fprintf(stderr, "File name: %s\n", result->file_name);
 
229
        }
 
230
        gpgme_recipient_t recipient;
 
231
        recipient = result->recipients;
 
232
        if(recipient){
 
233
          while(recipient != NULL){
 
234
            fprintf(stderr, "Public key algorithm: %s\n",
 
235
                    gpgme_pubkey_algo_name(recipient->pubkey_algo));
 
236
            fprintf(stderr, "Key ID: %s\n", recipient->keyid);
 
237
            fprintf(stderr, "Secret key available: %s\n",
 
238
                    recipient->status == GPG_ERR_NO_SECKEY
 
239
                    ? "No" : "Yes");
 
240
            recipient = recipient->next;
 
241
          }
 
242
        }
 
243
      }
 
244
    }
193
245
    goto decrypt_end;
194
246
  }
195
247
  
197
249
    fprintf(stderr, "Decryption of OpenPGP data succeeded\n");
198
250
  }
199
251
  
200
 
  if (debug){
201
 
    gpgme_decrypt_result_t result;
202
 
    result = gpgme_op_decrypt_result(ctx);
203
 
    if (result == NULL){
204
 
      fprintf(stderr, "gpgme_op_decrypt_result failed\n");
205
 
    } else {
206
 
      fprintf(stderr, "Unsupported algorithm: %s\n",
207
 
              result->unsupported_algorithm);
208
 
      fprintf(stderr, "Wrong key usage: %d\n",
209
 
              result->wrong_key_usage);
210
 
      if(result->file_name != NULL){
211
 
        fprintf(stderr, "File name: %s\n", result->file_name);
212
 
      }
213
 
      gpgme_recipient_t recipient;
214
 
      recipient = result->recipients;
215
 
      if(recipient){
216
 
        while(recipient != NULL){
217
 
          fprintf(stderr, "Public key algorithm: %s\n",
218
 
                  gpgme_pubkey_algo_name(recipient->pubkey_algo));
219
 
          fprintf(stderr, "Key ID: %s\n", recipient->keyid);
220
 
          fprintf(stderr, "Secret key available: %s\n",
221
 
                  recipient->status == GPG_ERR_NO_SECKEY
222
 
                  ? "No" : "Yes");
223
 
          recipient = recipient->next;
224
 
        }
225
 
      }
226
 
    }
227
 
  }
228
 
  
229
252
  /* Seek back to the beginning of the GPGME plaintext data buffer */
230
253
  if (gpgme_data_seek(dh_plain, (off_t) 0, SEEK_SET) == -1){
231
254
    perror("pgpme_data_seek");
278
301
}
279
302
 
280
303
static const char * safer_gnutls_strerror (int value) {
281
 
  const char *ret = gnutls_strerror (value);
 
304
  const char *ret = gnutls_strerror (value); /* Spurious warning */
282
305
  if (ret == NULL)
283
306
    ret = "(unknown)";
284
307
  return ret;
291
314
}
292
315
 
293
316
static int init_gnutls_global(mandos_context *mc,
294
 
                              const char *pubkeyfile,
295
 
                              const char *seckeyfile){
 
317
                              const char *pubkeyfilename,
 
318
                              const char *seckeyfilename){
296
319
  int ret;
297
320
  
298
321
  if(debug){
299
322
    fprintf(stderr, "Initializing GnuTLS\n");
300
323
  }
301
 
 
302
 
  if ((ret = gnutls_global_init ())
303
 
      != GNUTLS_E_SUCCESS) {
 
324
  
 
325
  ret = gnutls_global_init();
 
326
  if (ret != GNUTLS_E_SUCCESS) {
304
327
    fprintf (stderr, "GnuTLS global_init: %s\n",
305
328
             safer_gnutls_strerror(ret));
306
329
    return -1;
315
338
  }
316
339
  
317
340
  /* OpenPGP credentials */
318
 
  if ((ret = gnutls_certificate_allocate_credentials (&mc->cred))
319
 
      != GNUTLS_E_SUCCESS) {
320
 
    fprintf (stderr, "GnuTLS memory error: %s\n",
 
341
  gnutls_certificate_allocate_credentials(&mc->cred);
 
342
  if (ret != GNUTLS_E_SUCCESS){
 
343
    fprintf (stderr, "GnuTLS memory error: %s\n", /* Spurious
 
344
                                                     warning */
321
345
             safer_gnutls_strerror(ret));
 
346
    gnutls_global_deinit ();
322
347
    return -1;
323
348
  }
324
349
  
325
350
  if(debug){
326
351
    fprintf(stderr, "Attempting to use OpenPGP certificate %s"
327
 
            " and keyfile %s as GnuTLS credentials\n", pubkeyfile,
328
 
            seckeyfile);
 
352
            " and keyfile %s as GnuTLS credentials\n", pubkeyfilename,
 
353
            seckeyfilename);
329
354
  }
330
355
  
331
356
  ret = gnutls_certificate_set_openpgp_key_file
332
 
    (mc->cred, pubkeyfile, seckeyfile, GNUTLS_OPENPGP_FMT_BASE64);
 
357
    (mc->cred, pubkeyfilename, seckeyfilename,
 
358
     GNUTLS_OPENPGP_FMT_BASE64);
333
359
  if (ret != GNUTLS_E_SUCCESS) {
334
360
    fprintf(stderr,
335
361
            "Error[%d] while reading the OpenPGP key pair ('%s',"
336
 
            " '%s')\n", ret, pubkeyfile, seckeyfile);
 
362
            " '%s')\n", ret, pubkeyfilename, seckeyfilename);
337
363
    fprintf(stdout, "The GnuTLS error is: %s\n",
338
364
            safer_gnutls_strerror(ret));
339
 
    return -1;
 
365
    goto globalfail;
340
366
  }
341
367
  
342
368
  /* GnuTLS server initialization */
344
370
  if (ret != GNUTLS_E_SUCCESS) {
345
371
    fprintf (stderr, "Error in GnuTLS DH parameter initialization:"
346
372
             " %s\n", safer_gnutls_strerror(ret));
347
 
    return -1;
 
373
    goto globalfail;
348
374
  }
349
375
  ret = gnutls_dh_params_generate2(mc->dh_params, mc->dh_bits);
350
376
  if (ret != GNUTLS_E_SUCCESS) {
351
377
    fprintf (stderr, "Error in GnuTLS prime generation: %s\n",
352
378
             safer_gnutls_strerror(ret));
353
 
    return -1;
 
379
    goto globalfail;
354
380
  }
355
381
  
356
382
  gnutls_certificate_set_dh_params(mc->cred, mc->dh_params);
357
383
 
358
384
  return 0;
 
385
 
 
386
 globalfail:
 
387
 
 
388
  gnutls_certificate_free_credentials(mc->cred);
 
389
  gnutls_global_deinit();
 
390
  return -1;
 
391
 
359
392
}
360
393
 
361
394
static int init_gnutls_session(mandos_context *mc,
375
408
      fprintf(stderr, "Syntax error at: %s\n", err);
376
409
      fprintf(stderr, "GnuTLS error: %s\n",
377
410
              safer_gnutls_strerror(ret));
 
411
      gnutls_deinit (*session);
378
412
      return -1;
379
413
    }
380
414
  }
384
418
  if (ret != GNUTLS_E_SUCCESS) {
385
419
    fprintf(stderr, "Error setting GnuTLS credentials: %s\n",
386
420
            safer_gnutls_strerror(ret));
 
421
    gnutls_deinit (*session);
387
422
    return -1;
388
423
  }
389
424
  
422
457
  }
423
458
  
424
459
  if(debug){
425
 
    fprintf(stderr, "Setting up a tcp connection to %s, port %d\n",
426
 
            ip, port);
 
460
    fprintf(stderr, "Setting up a tcp connection to %s, port %" PRIu16
 
461
            "\n", ip, port);
427
462
  }
428
463
  
429
464
  tcp_sd = socket(PF_INET6, SOCK_STREAM, 0);
440
475
    fprintf(stderr, "Binding to interface %s\n", interface);
441
476
  }
442
477
  
443
 
  memset(&to,0,sizeof(to));     /* Spurious warning */
 
478
  memset(&to, 0, sizeof(to));
444
479
  to.in6.sin6_family = AF_INET6;
445
480
  /* It would be nice to have a way to detect if we were passed an
446
481
     IPv4 address here.   Now we assume an IPv6 address. */
453
488
    fprintf(stderr, "Bad address: %s\n", ip);
454
489
    return -1;
455
490
  }
456
 
  to.in6.sin6_port = htons(port);       /* Spurious warning */
 
491
  to.in6.sin6_port = htons(port); /* Spurious warning */
457
492
  
458
493
  to.in6.sin6_scope_id = (uint32_t)if_index;
459
494
  
460
495
  if(debug){
461
 
    fprintf(stderr, "Connection to: %s, port %d\n", ip, port);
 
496
    fprintf(stderr, "Connection to: %s, port %" PRIu16 "\n", ip,
 
497
            port);
462
498
    char addrstr[INET6_ADDRSTRLEN] = "";
463
499
    if(inet_ntop(to.in6.sin6_family, &(to.in6.sin6_addr), addrstr,
464
500
                 sizeof(addrstr)) == NULL){
505
541
  }
506
542
  
507
543
  gnutls_transport_set_ptr (session, (gnutls_transport_ptr_t) tcp_sd);
508
 
  
509
 
  ret = gnutls_handshake (session);
 
544
 
 
545
  do{
 
546
    ret = gnutls_handshake (session);
 
547
  } while(ret == GNUTLS_E_AGAIN or ret == GNUTLS_E_INTERRUPTED);
510
548
  
511
549
  if (ret != GNUTLS_E_SUCCESS){
512
550
    if(debug){
544
582
      case GNUTLS_E_AGAIN:
545
583
        break;
546
584
      case GNUTLS_E_REHANDSHAKE:
547
 
        ret = gnutls_handshake (session);
 
585
        do{
 
586
          ret = gnutls_handshake (session);
 
587
        } while(ret == GNUTLS_E_AGAIN or ret == GNUTLS_E_INTERRUPTED);
548
588
        if (ret < 0){
549
589
          fprintf(stderr, "*** GnuTLS Re-handshake failed ***\n");
550
590
          gnutls_perror (ret);
595
635
    } else {
596
636
      retval = -1;
597
637
    }
 
638
  } else {
 
639
    retval = -1;
598
640
  }
599
641
  
600
642
  /* Shutdown procedure */
603
645
  free(buffer);
604
646
  close(tcp_sd);
605
647
  gnutls_deinit (session);
606
 
  gnutls_certificate_free_credentials (mc->cred);
607
 
  gnutls_global_deinit ();
608
648
  return retval;
609
649
}
610
650
 
623
663
                             flags,
624
664
                             void* userdata) {
625
665
  mandos_context *mc = userdata;
626
 
  assert(r);                    /* Spurious warning */
 
666
  assert(r);
627
667
  
628
668
  /* Called whenever a service has been resolved successfully or
629
669
     timed out */
641
681
      char ip[AVAHI_ADDRESS_STR_MAX];
642
682
      avahi_address_snprint(ip, sizeof(ip), address);
643
683
      if(debug){
644
 
        fprintf(stderr, "Mandos server \"%s\" found on %s (%s, %d) on"
645
 
                " port %d\n", name, host_name, ip, interface, port);
 
684
        fprintf(stderr, "Mandos server \"%s\" found on %s (%s, %"
 
685
                PRIu16 ") on port %d\n", name, host_name, ip,
 
686
                interface, port);
646
687
      }
647
688
      int ret = start_mandos_communication(ip, port, interface, mc);
648
689
      if (ret == 0){
649
 
        exit(EXIT_SUCCESS);
 
690
        avahi_simple_poll_quit(mc->simple_poll);
650
691
      }
651
692
    }
652
693
  }
664
705
                             flags,
665
706
                             void* userdata) {
666
707
  mandos_context *mc = userdata;
667
 
  assert(b);                    /* Spurious warning */
 
708
  assert(b);
668
709
  
669
710
  /* Called whenever a new services becomes available on the LAN or
670
711
     is removed from the LAN */
706
747
 
707
748
/* Combines file name and path and returns the malloced new
708
749
   string. some sane checks could/should be added */
709
 
static const char *combinepath(const char *first, const char *second){
710
 
  size_t f_len = strlen(first);
711
 
  size_t s_len = strlen(second);
712
 
  char *tmp = malloc(f_len + s_len + 2);
713
 
  if (tmp == NULL){
 
750
static char *combinepath(const char *first, const char *second){
 
751
  char *tmp;
 
752
  int ret = asprintf(&tmp, "%s/%s", first, second);
 
753
  if(ret < 0){
714
754
    return NULL;
715
755
  }
716
 
  if(f_len > 0){
717
 
    memcpy(tmp, first, f_len);  /* Spurious warning */
718
 
  }
719
 
  tmp[f_len] = '/';
720
 
  if(s_len > 0){
721
 
    memcpy(tmp + f_len + 1, second, s_len); /* Spurious warning */
722
 
  }
723
 
  tmp[f_len + 1 + s_len] = '\0';
724
756
  return tmp;
725
757
}
726
758
 
737
769
    gid_t gid;
738
770
    char *connect_to = NULL;
739
771
    AvahiIfIndex if_index = AVAHI_IF_UNSPEC;
740
 
    const char *pubkeyfile = "pubkey.txt";
741
 
    const char *seckeyfile = "seckey.txt";
 
772
    char *pubkeyfilename = NULL;
 
773
    char *seckeyfilename = NULL;
 
774
    const char *pubkeyname = "pubkey.txt";
 
775
    const char *seckeyname = "seckey.txt";
742
776
    mandos_context mc = { .simple_poll = NULL, .server = NULL,
743
777
                          .dh_bits = 1024, .priority = "SECURE256"};
 
778
    bool gnutls_initalized = false;
744
779
    
745
780
    {
746
781
      struct argp_option options[] = {
795
830
          keydir = arg;
796
831
          break;
797
832
        case 's':
798
 
          seckeyfile = arg;
 
833
          seckeyname = arg;
799
834
          break;
800
835
        case 'p':
801
 
          pubkeyfile = arg;
 
836
          pubkeyname = arg;
802
837
          break;
803
838
        case 129:
804
839
          errno = 0;
813
848
          break;
814
849
        case ARGP_KEY_ARG:
815
850
          argp_usage (state);
 
851
        case ARGP_KEY_END:
816
852
          break;
817
 
          case ARGP_KEY_END:
818
 
            break;
819
853
        default:
820
854
          return ARGP_ERR_UNKNOWN;
821
855
        }
826
860
                           .args_doc = "",
827
861
                           .doc = "Mandos client -- Get and decrypt"
828
862
                           " passwords from mandos server" };
829
 
      argp_parse (&argp, argc, argv, 0, 0, NULL);
 
863
      ret = argp_parse (&argp, argc, argv, 0, 0, NULL);
 
864
      if (ret == ARGP_ERR_UNKNOWN){
 
865
        fprintf(stderr, "Unknown error while parsing arguments\n");
 
866
        exitcode = EXIT_FAILURE;
 
867
        goto end;
 
868
      }
830
869
    }
831
870
      
832
 
    pubkeyfile = combinepath(keydir, pubkeyfile);
833
 
    if (pubkeyfile == NULL){
 
871
    pubkeyfilename = combinepath(keydir, pubkeyname);
 
872
    if (pubkeyfilename == NULL){
834
873
      perror("combinepath");
835
874
      exitcode = EXIT_FAILURE;
836
875
      goto end;
837
876
    }
838
877
    
839
 
    seckeyfile = combinepath(keydir, seckeyfile);
840
 
    if (seckeyfile == NULL){
 
878
    seckeyfilename = combinepath(keydir, seckeyname);
 
879
    if (seckeyfilename == NULL){
841
880
      perror("combinepath");
 
881
      exitcode = EXIT_FAILURE;
842
882
      goto end;
843
883
    }
844
884
 
845
 
    ret = init_gnutls_global(&mc, pubkeyfile, seckeyfile);
 
885
    ret = init_gnutls_global(&mc, pubkeyfilename, seckeyfilename);
846
886
    if (ret == -1){
847
 
      fprintf(stderr, "init_gnutls_global\n");
 
887
      fprintf(stderr, "init_gnutls_global failed\n");
 
888
      exitcode = EXIT_FAILURE;
848
889
      goto end;
849
 
    }
850
 
 
 
890
    } else {
 
891
      gnutls_initalized = true;
 
892
    }
 
893
    
 
894
    /* If the interface is down, bring it up */
 
895
    {
 
896
      sd = socket(PF_INET6, SOCK_DGRAM, IPPROTO_IP);
 
897
      if(sd < 0) {
 
898
        perror("socket");
 
899
        exitcode = EXIT_FAILURE;
 
900
        goto end;
 
901
      }
 
902
      strcpy(network.ifr_name, interface);
 
903
      ret = ioctl(sd, SIOCGIFFLAGS, &network);
 
904
      if(ret == -1){
 
905
        perror("ioctl SIOCGIFFLAGS");
 
906
        exitcode = EXIT_FAILURE;
 
907
        goto end;
 
908
      }
 
909
      if((network.ifr_flags & IFF_UP) == 0){
 
910
        network.ifr_flags |= IFF_UP;
 
911
        ret = ioctl(sd, SIOCSIFFLAGS, &network);
 
912
        if(ret == -1){
 
913
          perror("ioctl SIOCSIFFLAGS");
 
914
          exitcode = EXIT_FAILURE;
 
915
          goto end;
 
916
        }
 
917
      }
 
918
      close(sd);
 
919
    }
 
920
    
851
921
    uid = getuid();
852
922
    gid = getgid();
853
 
 
 
923
    
854
924
    ret = setuid(uid);
855
925
    if (ret == -1){
856
926
      perror("setuid");
894
964
      goto end;
895
965
    }
896
966
    
897
 
    /* If the interface is down, bring it up */
898
 
    {
899
 
      sd = socket(PF_INET6, SOCK_DGRAM, IPPROTO_IP);
900
 
      if(sd < 0) {
901
 
        perror("socket");
902
 
        exitcode = EXIT_FAILURE;
903
 
        goto end;
904
 
      }
905
 
      strcpy(network.ifr_name, interface); /* Spurious warning */
906
 
      ret = ioctl(sd, SIOCGIFFLAGS, &network);
907
 
      if(ret == -1){
908
 
        perror("ioctl SIOCGIFFLAGS");
909
 
        exitcode = EXIT_FAILURE;
910
 
        goto end;
911
 
      }
912
 
      if((network.ifr_flags & IFF_UP) == 0){
913
 
        network.ifr_flags |= IFF_UP;
914
 
        ret = ioctl(sd, SIOCSIFFLAGS, &network);
915
 
        if(ret == -1){
916
 
          perror("ioctl SIOCSIFFLAGS");
917
 
          exitcode = EXIT_FAILURE;
918
 
          goto end;
919
 
        }
920
 
      }
921
 
      close(sd);
922
 
    }
923
 
    
924
967
    if (not debug){
925
968
      avahi_set_log_function(empty_log);
926
969
    }
998
1041
 
999
1042
    if (mc.simple_poll != NULL)
1000
1043
        avahi_simple_poll_free(mc.simple_poll);
1001
 
    free(pubkeyfile);
1002
 
    free(seckeyfile);
 
1044
    free(pubkeyfilename);
 
1045
    free(seckeyfilename);
 
1046
 
 
1047
    if (gnutls_initalized){
 
1048
      gnutls_certificate_free_credentials(mc.cred);
 
1049
      gnutls_global_deinit ();
 
1050
    }
1003
1051
    
1004
1052
    return exitcode;
1005
1053
}