/mandos/trunk

To get this branch, use:
bzr branch http://bzr.recompile.se/loggerhead/mandos/trunk

« 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:
9
9
 * "browse_callback", and parts of "main".
10
10
 * 
11
11
 * Everything else is
12
 
 * Copyright © 2008 Teddy Hogeborn & Björn Påhlsson
 
12
 * Copyright © 2007-2008 Teddy Hogeborn & Björn Påhlsson
13
13
 * 
14
14
 * This program is free software: you can redistribute it and/or
15
15
 * modify it under the terms of the GNU General Public License as
47
47
#include <sys/types.h>          /* socket(), inet_pton(), sockaddr,
48
48
                                   sockaddr_in6, PF_INET6,
49
49
                                   SOCK_STREAM, INET6_ADDRSTRLEN,
50
 
                                   uid_t, gid_t, open(), opendir(), DIR */
51
 
#include <sys/stat.h>           /* open() */
 
50
                                   uid_t, gid_t */
 
51
#include <inttypes.h>           /* PRIu16 */
52
52
#include <sys/socket.h>         /* socket(), struct sockaddr_in6,
53
53
                                   struct in6_addr, inet_pton(),
54
54
                                   connect() */
55
 
#include <fcntl.h>              /* open() */
56
 
#include <dirent.h>             /* opendir(), struct dirent, readdir() */
57
 
#include <inttypes.h>           /* PRIu16 */
58
55
#include <assert.h>             /* assert() */
59
56
#include <errno.h>              /* perror(), errno */
60
57
#include <time.h>               /* time() */
61
58
#include <net/if.h>             /* ioctl, ifreq, SIOCGIFFLAGS, IFF_UP,
62
59
                                   SIOCSIFFLAGS, if_indextoname(),
63
60
                                   if_nametoindex(), IF_NAMESIZE */
64
 
#include <netinet/in.h>
65
61
#include <unistd.h>             /* close(), SEEK_SET, off_t, write(),
66
62
                                   getuid(), getgid(), setuid(),
67
63
                                   setgid() */
 
64
#include <netinet/in.h>
68
65
#include <arpa/inet.h>          /* inet_pton(), htons */
69
66
#include <iso646.h>             /* not, and */
70
67
#include <argp.h>               /* struct argp_option, error_t, struct
101
98
 
102
99
#define BUFFER_SIZE 256
103
100
 
104
 
#define PATHDIR "/conf/conf.d/mandos"
105
 
#define SECKEY "seckey.txt"
106
 
#define PUBKEY "pubkey.txt"
107
 
 
108
101
bool debug = false;
 
102
static const char *keydir = "/conf/conf.d/mandos";
109
103
static const char mandos_protocol_version[] = "1";
110
 
const char *argp_program_version = "mandos-client " VERSION;
 
104
const char *argp_program_version = "password-request 1.0";
111
105
const char *argp_program_bug_address = "<mandos@fukt.bsnet.se>";
112
106
 
113
107
/* Used for passing in values through the Avahi callback functions */
118
112
  unsigned int dh_bits;
119
113
  gnutls_dh_params_t dh_params;
120
114
  const char *priority;
121
 
  gpgme_ctx_t ctx;
122
115
} mandos_context;
123
116
 
124
117
/*
139
132
}
140
133
 
141
134
/* 
142
 
 * Initialize GPGME.
 
135
 * Decrypt OpenPGP data using keyrings in HOMEDIR.
 
136
 * Returns -1 on error
143
137
 */
144
 
static bool init_gpgme(mandos_context *mc, const char *seckey,
145
 
                       const char *pubkey, const char *tempdir){
146
 
  int ret;
 
138
static ssize_t pgp_packet_decrypt (const char *cryptotext,
 
139
                                   size_t crypto_size,
 
140
                                   char **plaintext,
 
141
                                   const char *homedir){
 
142
  gpgme_data_t dh_crypto, dh_plain;
 
143
  gpgme_ctx_t ctx;
147
144
  gpgme_error_t rc;
 
145
  ssize_t ret;
 
146
  size_t plaintext_capacity = 0;
 
147
  ssize_t plaintext_length = 0;
148
148
  gpgme_engine_info_t engine_info;
149
149
  
150
 
  
151
 
  /*
152
 
   * Helper function to insert pub and seckey to the enigne keyring.
153
 
   */
154
 
  bool import_key(const char *filename){
155
 
    int fd;
156
 
    gpgme_data_t pgp_data;
157
 
    
158
 
    fd = TEMP_FAILURE_RETRY(open(filename, O_RDONLY));
159
 
    if(fd == -1){
160
 
      perror("open");
161
 
      return false;
162
 
    }
163
 
    
164
 
    rc = gpgme_data_new_from_fd(&pgp_data, fd);
165
 
    if (rc != GPG_ERR_NO_ERROR){
166
 
      fprintf(stderr, "bad gpgme_data_new_from_fd: %s: %s\n",
167
 
              gpgme_strsource(rc), gpgme_strerror(rc));
168
 
      return false;
169
 
    }
170
 
    
171
 
    rc = gpgme_op_import(mc->ctx, pgp_data);
172
 
    if (rc != GPG_ERR_NO_ERROR){
173
 
      fprintf(stderr, "bad gpgme_op_import: %s: %s\n",
174
 
              gpgme_strsource(rc), gpgme_strerror(rc));
175
 
      return false;
176
 
    }
177
 
    
178
 
    ret = TEMP_FAILURE_RETRY(close(fd));
179
 
    if(ret == -1){
180
 
      perror("close");
181
 
    }
182
 
    gpgme_data_release(pgp_data);
183
 
    return true;
184
 
  }
185
 
  
186
150
  if (debug){
187
 
    fprintf(stderr, "Initialize gpgme\n");
 
151
    fprintf(stderr, "Trying to decrypt OpenPGP data\n");
188
152
  }
189
153
  
190
154
  /* Init GPGME */
193
157
  if (rc != GPG_ERR_NO_ERROR){
194
158
    fprintf(stderr, "bad gpgme_engine_check_version: %s: %s\n",
195
159
            gpgme_strsource(rc), gpgme_strerror(rc));
196
 
    return false;
 
160
    return -1;
197
161
  }
198
162
  
199
 
    /* Set GPGME home directory for the OpenPGP engine only */
 
163
  /* Set GPGME home directory for the OpenPGP engine only */
200
164
  rc = gpgme_get_engine_info (&engine_info);
201
165
  if (rc != GPG_ERR_NO_ERROR){
202
166
    fprintf(stderr, "bad gpgme_get_engine_info: %s: %s\n",
203
167
            gpgme_strsource(rc), gpgme_strerror(rc));
204
 
    return false;
 
168
    return -1;
205
169
  }
206
170
  while(engine_info != NULL){
207
171
    if(engine_info->protocol == GPGME_PROTOCOL_OpenPGP){
208
172
      gpgme_set_engine_info(GPGME_PROTOCOL_OpenPGP,
209
 
                            engine_info->file_name, tempdir);
 
173
                            engine_info->file_name, homedir);
210
174
      break;
211
175
    }
212
176
    engine_info = engine_info->next;
213
177
  }
214
178
  if(engine_info == NULL){
215
 
    fprintf(stderr, "Could not set GPGME home dir to %s\n", tempdir);
216
 
    return false;
217
 
  }
218
 
  
219
 
  /* Create new GPGME "context" */
220
 
  rc = gpgme_new(&(mc->ctx));
221
 
  if (rc != GPG_ERR_NO_ERROR){
222
 
    fprintf(stderr, "bad gpgme_new: %s: %s\n",
223
 
            gpgme_strsource(rc), gpgme_strerror(rc));
224
 
    return false;
225
 
  }
226
 
  
227
 
  if (not import_key(pubkey) or not import_key(seckey)){
228
 
    return false;
229
 
  }
230
 
  
231
 
  return true; 
232
 
}
233
 
 
234
 
/* 
235
 
 * Decrypt OpenPGP data.
236
 
 * Returns -1 on error
237
 
 */
238
 
static ssize_t pgp_packet_decrypt (const mandos_context *mc,
239
 
                                   const char *cryptotext,
240
 
                                   size_t crypto_size,
241
 
                                   char **plaintext){
242
 
  gpgme_data_t dh_crypto, dh_plain;
243
 
  gpgme_error_t rc;
244
 
  ssize_t ret;
245
 
  size_t plaintext_capacity = 0;
246
 
  ssize_t plaintext_length = 0;
247
 
  
248
 
  if (debug){
249
 
    fprintf(stderr, "Trying to decrypt OpenPGP data\n");
 
179
    fprintf(stderr, "Could not set GPGME home dir to %s\n", homedir);
 
180
    return -1;
250
181
  }
251
182
  
252
183
  /* Create new GPGME data buffer from memory cryptotext */
267
198
    return -1;
268
199
  }
269
200
  
 
201
  /* Create new GPGME "context" */
 
202
  rc = gpgme_new(&ctx);
 
203
  if (rc != GPG_ERR_NO_ERROR){
 
204
    fprintf(stderr, "bad gpgme_new: %s: %s\n",
 
205
            gpgme_strsource(rc), gpgme_strerror(rc));
 
206
    plaintext_length = -1;
 
207
    goto decrypt_end;
 
208
  }
 
209
  
270
210
  /* Decrypt data from the cryptotext data buffer to the plaintext
271
211
     data buffer */
272
 
  rc = gpgme_op_decrypt(mc->ctx, dh_crypto, dh_plain);
 
212
  rc = gpgme_op_decrypt(ctx, dh_crypto, dh_plain);
273
213
  if (rc != GPG_ERR_NO_ERROR){
274
214
    fprintf(stderr, "bad gpgme_op_decrypt: %s: %s\n",
275
215
            gpgme_strsource(rc), gpgme_strerror(rc));
276
216
    plaintext_length = -1;
277
217
    if (debug){
278
218
      gpgme_decrypt_result_t result;
279
 
      result = gpgme_op_decrypt_result(mc->ctx);
 
219
      result = gpgme_op_decrypt_result(ctx);
280
220
      if (result == NULL){
281
221
        fprintf(stderr, "gpgme_op_decrypt_result failed\n");
282
222
      } else {
311
251
  
312
252
  /* Seek back to the beginning of the GPGME plaintext data buffer */
313
253
  if (gpgme_data_seek(dh_plain, (off_t) 0, SEEK_SET) == -1){
314
 
    perror("gpgme_data_seek");
 
254
    perror("pgpme_data_seek");
315
255
    plaintext_length = -1;
316
256
    goto decrypt_end;
317
257
  }
341
281
    }
342
282
    plaintext_length += ret;
343
283
  }
344
 
  
 
284
 
345
285
  if(debug){
346
286
    fprintf(stderr, "Decrypted password is: ");
347
287
    for(ssize_t i = 0; i < plaintext_length; i++){
408
348
  }
409
349
  
410
350
  if(debug){
411
 
    fprintf(stderr, "Attempting to use OpenPGP public key %s and"
412
 
            " secret key %s as GnuTLS credentials\n", pubkeyfilename,
 
351
    fprintf(stderr, "Attempting to use OpenPGP certificate %s"
 
352
            " and keyfile %s as GnuTLS credentials\n", pubkeyfilename,
413
353
            seckeyfilename);
414
354
  }
415
355
  
420
360
    fprintf(stderr,
421
361
            "Error[%d] while reading the OpenPGP key pair ('%s',"
422
362
            " '%s')\n", ret, pubkeyfilename, seckeyfilename);
423
 
    fprintf(stderr, "The GnuTLS error is: %s\n",
 
363
    fprintf(stdout, "The GnuTLS error is: %s\n",
424
364
            safer_gnutls_strerror(ret));
425
365
    goto globalfail;
426
366
  }
440
380
  }
441
381
  
442
382
  gnutls_certificate_set_dh_params(mc->cred, mc->dh_params);
443
 
  
 
383
 
444
384
  return 0;
445
 
  
 
385
 
446
386
 globalfail:
447
 
  
 
387
 
448
388
  gnutls_certificate_free_credentials(mc->cred);
449
389
  gnutls_global_deinit();
450
 
  gnutls_dh_params_deinit(mc->dh_params);
451
390
  return -1;
 
391
 
452
392
}
453
393
 
454
394
static int init_gnutls_session(mandos_context *mc,
526
466
    perror("socket");
527
467
    return -1;
528
468
  }
529
 
  
 
469
 
530
470
  if(debug){
531
471
    if(if_indextoname((unsigned int)if_index, interface) == NULL){
532
472
      perror("if_indextoname");
571
511
    perror("connect");
572
512
    return -1;
573
513
  }
574
 
  
 
514
 
575
515
  const char *out = mandos_protocol_version;
576
516
  written = 0;
577
517
  while (true){
595
535
      }
596
536
    }
597
537
  }
598
 
  
 
538
 
599
539
  if(debug){
600
540
    fprintf(stderr, "Establishing TLS session with %s\n", ip);
601
541
  }
602
542
  
603
543
  gnutls_transport_set_ptr (session, (gnutls_transport_ptr_t) tcp_sd);
604
 
  
 
544
 
605
545
  do{
606
546
    ret = gnutls_handshake (session);
607
547
  } while(ret == GNUTLS_E_AGAIN or ret == GNUTLS_E_INTERRUPTED);
621
561
    fprintf(stderr, "Retrieving pgp encrypted password from %s\n",
622
562
            ip);
623
563
  }
624
 
  
 
564
 
625
565
  while(true){
626
566
    buffer_capacity = adjustbuffer(&buffer, buffer_length,
627
567
                                   buffer_capacity);
671
611
  gnutls_bye (session, GNUTLS_SHUT_RDWR);
672
612
  
673
613
  if (buffer_length > 0){
674
 
    decrypted_buffer_size = pgp_packet_decrypt(mc, buffer,
 
614
    decrypted_buffer_size = pgp_packet_decrypt(buffer,
675
615
                                               buffer_length,
676
 
                                               &decrypted_buffer);
 
616
                                               &decrypted_buffer,
 
617
                                               keydir);
677
618
    if (decrypted_buffer_size >= 0){
678
619
      written = 0;
679
620
      while(written < (size_t) decrypted_buffer_size){
702
643
  
703
644
 mandos_end:
704
645
  free(buffer);
705
 
  ret = TEMP_FAILURE_RETRY(close(tcp_sd));
706
 
  if(ret == -1){
707
 
    perror("close");
708
 
  }
 
646
  close(tcp_sd);
709
647
  gnutls_deinit (session);
710
648
  return retval;
711
649
}
807
745
  }
808
746
}
809
747
 
 
748
/* Combines file name and path and returns the malloced new
 
749
   string. some sane checks could/should be added */
 
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){
 
754
    return NULL;
 
755
  }
 
756
  return tmp;
 
757
}
 
758
 
 
759
 
810
760
int main(int argc, char *argv[]){
811
761
    AvahiSServiceBrowser *sb = NULL;
812
762
    int error;
818
768
    uid_t uid;
819
769
    gid_t gid;
820
770
    char *connect_to = NULL;
821
 
    char tempdir[] = "/tmp/mandosXXXXXX";
822
771
    AvahiIfIndex if_index = AVAHI_IF_UNSPEC;
823
 
    const char *seckey = PATHDIR "/" SECKEY;
824
 
    const char *pubkey = PATHDIR "/" PUBKEY;
825
 
    
 
772
    char *pubkeyfilename = NULL;
 
773
    char *seckeyfilename = NULL;
 
774
    const char *pubkeyname = "pubkey.txt";
 
775
    const char *seckeyname = "seckey.txt";
826
776
    mandos_context mc = { .simple_poll = NULL, .server = NULL,
827
 
                          .dh_bits = 1024, .priority = "SECURE256"
828
 
                          ":!CTYPE-X.509:+CTYPE-OPENPGP" };
 
777
                          .dh_bits = 1024, .priority = "SECURE256"};
829
778
    bool gnutls_initalized = false;
830
 
    bool gpgme_initalized = false;
831
779
    
832
780
    {
833
781
      struct argp_option options[] = {
834
782
        { .name = "debug", .key = 128,
835
783
          .doc = "Debug mode", .group = 3 },
836
784
        { .name = "connect", .key = 'c',
837
 
          .arg = "ADDRESS:PORT",
838
 
          .doc = "Connect directly to a specific Mandos server",
 
785
          .arg = "IP",
 
786
          .doc = "Connect directly to a sepcified mandos server",
839
787
          .group = 1 },
840
788
        { .name = "interface", .key = 'i',
841
 
          .arg = "NAME",
842
 
          .doc = "Interface that will be used to search for Mandos"
843
 
          " servers",
 
789
          .arg = "INTERFACE",
 
790
          .doc = "Interface that Avahi will conntect through",
 
791
          .group = 1 },
 
792
        { .name = "keydir", .key = 'd',
 
793
          .arg = "KEYDIR",
 
794
          .doc = "Directory where the openpgp keyring is",
844
795
          .group = 1 },
845
796
        { .name = "seckey", .key = 's',
846
 
          .arg = "FILE",
847
 
          .doc = "OpenPGP secret key file base name",
 
797
          .arg = "SECKEY",
 
798
          .doc = "Secret openpgp key for gnutls authentication",
848
799
          .group = 1 },
849
800
        { .name = "pubkey", .key = 'p',
850
 
          .arg = "FILE",
851
 
          .doc = "OpenPGP public key file base name",
 
801
          .arg = "PUBKEY",
 
802
          .doc = "Public openpgp key for gnutls authentication",
852
803
          .group = 2 },
853
804
        { .name = "dh-bits", .key = 129,
854
805
          .arg = "BITS",
855
 
          .doc = "Bit length of the prime number used in the"
856
 
          " Diffie-Hellman key exchange",
 
806
          .doc = "dh-bits to use in gnutls communication",
857
807
          .group = 2 },
858
808
        { .name = "priority", .key = 130,
859
 
          .arg = "STRING",
860
 
          .doc = "GnuTLS priority string for the TLS handshake",
861
 
          .group = 1 },
 
809
          .arg = "PRIORITY",
 
810
          .doc = "GNUTLS priority", .group = 1 },
862
811
        { .name = NULL }
863
812
      };
 
813
 
864
814
      
865
815
      error_t parse_opt (int key, char *arg,
866
816
                         struct argp_state *state) {
867
817
        /* Get the INPUT argument from `argp_parse', which we know is
868
818
           a pointer to our plugin list pointer. */
869
819
        switch (key) {
870
 
        case 128:               /* --debug */
 
820
        case 128:
871
821
          debug = true;
872
822
          break;
873
 
        case 'c':               /* --connect */
 
823
        case 'c':
874
824
          connect_to = arg;
875
825
          break;
876
 
        case 'i':               /* --interface */
 
826
        case 'i':
877
827
          interface = arg;
878
828
          break;
879
 
        case 's':               /* --seckey */
880
 
          seckey = arg;
881
 
          break;
882
 
        case 'p':               /* --pubkey */
883
 
          pubkey = arg;
884
 
          break;
885
 
        case 129:               /* --dh-bits */
 
829
        case 'd':
 
830
          keydir = arg;
 
831
          break;
 
832
        case 's':
 
833
          seckeyname = arg;
 
834
          break;
 
835
        case 'p':
 
836
          pubkeyname = arg;
 
837
          break;
 
838
        case 129:
886
839
          errno = 0;
887
840
          mc.dh_bits = (unsigned int) strtol(arg, NULL, 10);
888
841
          if (errno){
890
843
            exit(EXIT_FAILURE);
891
844
          }
892
845
          break;
893
 
        case 130:               /* --priority */
 
846
        case 130:
894
847
          mc.priority = arg;
895
848
          break;
896
849
        case ARGP_KEY_ARG:
902
855
        }
903
856
        return 0;
904
857
      }
905
 
      
 
858
 
906
859
      struct argp argp = { .options = options, .parser = parse_opt,
907
860
                           .args_doc = "",
908
861
                           .doc = "Mandos client -- Get and decrypt"
909
 
                           " passwords from a Mandos server" };
 
862
                           " passwords from mandos server" };
910
863
      ret = argp_parse (&argp, argc, argv, 0, 0, NULL);
911
864
      if (ret == ARGP_ERR_UNKNOWN){
912
865
        fprintf(stderr, "Unknown error while parsing arguments\n");
914
867
        goto end;
915
868
      }
916
869
    }
 
870
      
 
871
    pubkeyfilename = combinepath(keydir, pubkeyname);
 
872
    if (pubkeyfilename == NULL){
 
873
      perror("combinepath");
 
874
      exitcode = EXIT_FAILURE;
 
875
      goto end;
 
876
    }
 
877
    
 
878
    seckeyfilename = combinepath(keydir, seckeyname);
 
879
    if (seckeyfilename == NULL){
 
880
      perror("combinepath");
 
881
      exitcode = EXIT_FAILURE;
 
882
      goto end;
 
883
    }
 
884
 
 
885
    ret = init_gnutls_global(&mc, pubkeyfilename, seckeyfilename);
 
886
    if (ret == -1){
 
887
      fprintf(stderr, "init_gnutls_global failed\n");
 
888
      exitcode = EXIT_FAILURE;
 
889
      goto end;
 
890
    } else {
 
891
      gnutls_initalized = true;
 
892
    }
917
893
    
918
894
    /* If the interface is down, bring it up */
919
895
    {
939
915
          goto end;
940
916
        }
941
917
      }
942
 
      ret = TEMP_FAILURE_RETRY(close(sd));
943
 
      if(ret == -1){
944
 
        perror("close");
945
 
      }
 
918
      close(sd);
946
919
    }
947
920
    
948
921
    uid = getuid();
958
931
      perror("setgid");
959
932
    }
960
933
    
961
 
    ret = init_gnutls_global(&mc, pubkey, seckey);
962
 
    if (ret == -1){
963
 
      fprintf(stderr, "init_gnutls_global failed\n");
964
 
      exitcode = EXIT_FAILURE;
965
 
      goto end;
966
 
    } else {
967
 
      gnutls_initalized = true;
968
 
    }
969
 
    
970
 
    if(mkdtemp(tempdir) == NULL){
971
 
      perror("mkdtemp");
972
 
      tempdir[0] = '\0';
973
 
      goto end;
974
 
    }
975
 
    
976
 
    if(not init_gpgme(&mc, pubkey, seckey, tempdir)){
977
 
      fprintf(stderr, "gpgme_initalized failed\n");
978
 
      exitcode = EXIT_FAILURE;
979
 
      goto end;
980
 
    } else {
981
 
      gpgme_initalized = true;
982
 
    }
983
 
    
984
934
    if_index = (AvahiIfIndex) if_nametoindex(interface);
985
935
    if(if_index == 0){
986
936
      fprintf(stderr, "No such interface: \"%s\"\n", interface);
1029
979
        exitcode = EXIT_FAILURE;
1030
980
        goto end;
1031
981
    }
1032
 
    
 
982
 
1033
983
    {
1034
984
      AvahiServerConfig config;
1035
985
      /* Do not publish any local Zeroconf records */
1038
988
      config.publish_addresses = 0;
1039
989
      config.publish_workstation = 0;
1040
990
      config.publish_domain = 0;
1041
 
      
 
991
 
1042
992
      /* Allocate a new server */
1043
993
      mc.server = avahi_server_new(avahi_simple_poll_get
1044
994
                                   (mc.simple_poll), &config, NULL,
1045
995
                                   NULL, &error);
1046
 
      
 
996
    
1047
997
      /* Free the Avahi configuration data */
1048
998
      avahi_server_config_free(&config);
1049
999
    }
1069
1019
    }
1070
1020
    
1071
1021
    /* Run the main loop */
1072
 
    
 
1022
 
1073
1023
    if (debug){
1074
1024
      fprintf(stderr, "Starting Avahi loop search\n");
1075
1025
    }
1077
1027
    avahi_simple_poll_loop(mc.simple_poll);
1078
1028
    
1079
1029
 end:
1080
 
    
 
1030
 
1081
1031
    if (debug){
1082
1032
      fprintf(stderr, "%s exiting\n", argv[0]);
1083
1033
    }
1088
1038
    
1089
1039
    if (mc.server != NULL)
1090
1040
        avahi_server_free(mc.server);
1091
 
    
 
1041
 
1092
1042
    if (mc.simple_poll != NULL)
1093
1043
        avahi_simple_poll_free(mc.simple_poll);
1094
 
    
 
1044
    free(pubkeyfilename);
 
1045
    free(seckeyfilename);
 
1046
 
1095
1047
    if (gnutls_initalized){
1096
1048
      gnutls_certificate_free_credentials(mc.cred);
1097
1049
      gnutls_global_deinit ();
1098
 
      gnutls_dh_params_deinit(mc.dh_params);
1099
 
    }
1100
 
    
1101
 
    if(gpgme_initalized){
1102
 
      gpgme_release(mc.ctx);
1103
 
    }
1104
 
    
1105
 
    /* Removes the temp directory used by GPGME */
1106
 
    if(tempdir[0] != '\0'){
1107
 
      DIR *d;
1108
 
      struct dirent *direntry;
1109
 
      d = opendir(tempdir);
1110
 
      if(d == NULL){
1111
 
        perror("opendir");
1112
 
      } else {
1113
 
        while(true){
1114
 
          direntry = readdir(d);
1115
 
          if(direntry == NULL){
1116
 
            break;
1117
 
          }
1118
 
          if (direntry->d_type == DT_REG){
1119
 
            char *fullname = NULL;
1120
 
            ret = asprintf(&fullname, "%s/%s", tempdir,
1121
 
                           direntry->d_name);
1122
 
            if(ret < 0){
1123
 
              perror("asprintf");
1124
 
              continue;
1125
 
            }
1126
 
            ret = unlink(fullname);
1127
 
            if(ret == -1){
1128
 
              fprintf(stderr, "unlink(\"%s\"): %s",
1129
 
                      fullname, strerror(errno));
1130
 
            }
1131
 
            free(fullname);
1132
 
          }
1133
 
        }
1134
 
        closedir(d);
1135
 
      }
1136
 
      ret = rmdir(tempdir);
1137
 
      if(ret == -1){
1138
 
        perror("rmdir");
1139
 
      }
1140
 
    }
1141
 
          
 
1050
    }
 
1051
    
1142
1052
    return exitcode;
1143
1053
}