/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:
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
 
/*
105
 
  #define PATHDIR "/conf/conf.d/mandos"
106
 
*/
107
 
 
108
 
#define PATHDIR "/conf/conf.d/mandos"
109
 
#define SECKEY "seckey.txt"
110
 
#define PUBKEY "pubkey.txt"
111
 
 
112
101
bool debug = false;
 
102
static const char *keydir = "/conf/conf.d/mandos";
113
103
static const char mandos_protocol_version[] = "1";
114
 
const char *argp_program_version = "mandos-client 1.0";
 
104
const char *argp_program_version = "password-request 1.0";
115
105
const char *argp_program_bug_address = "<mandos@fukt.bsnet.se>";
116
106
 
117
107
/* Used for passing in values through the Avahi callback functions */
122
112
  unsigned int dh_bits;
123
113
  gnutls_dh_params_t dh_params;
124
114
  const char *priority;
125
 
  gpgme_ctx_t ctx;
126
115
} mandos_context;
127
116
 
128
117
/*
143
132
}
144
133
 
145
134
/* 
146
 
 * Initialize GPGME.
 
135
 * Decrypt OpenPGP data using keyrings in HOMEDIR.
 
136
 * Returns -1 on error
147
137
 */
148
 
static bool init_gpgme(mandos_context *mc, const char *seckey,
149
 
                       const char *pubkey, const char *tempdir){
150
 
  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;
151
144
  gpgme_error_t rc;
 
145
  ssize_t ret;
 
146
  size_t plaintext_capacity = 0;
 
147
  ssize_t plaintext_length = 0;
152
148
  gpgme_engine_info_t engine_info;
153
149
  
154
 
  
155
 
  /*
156
 
   * Helper function to insert pub and seckey to the enigne keyring.
157
 
   */
158
 
  bool import_key(const char *filename){
159
 
    int fd;
160
 
    gpgme_data_t pgp_data;
161
 
    
162
 
    fd = TEMP_FAILURE_RETRY(open(filename, O_RDONLY));
163
 
    if(fd == -1){
164
 
      perror("open");
165
 
      return false;
166
 
    }
167
 
    
168
 
    rc = gpgme_data_new_from_fd(&pgp_data, fd);
169
 
    if (rc != GPG_ERR_NO_ERROR){
170
 
      fprintf(stderr, "bad gpgme_data_new_from_fd: %s: %s\n",
171
 
              gpgme_strsource(rc), gpgme_strerror(rc));
172
 
      return false;
173
 
    }
174
 
    
175
 
    rc = gpgme_op_import(mc->ctx, pgp_data);
176
 
    if (rc != GPG_ERR_NO_ERROR){
177
 
      fprintf(stderr, "bad gpgme_op_import: %s: %s\n",
178
 
              gpgme_strsource(rc), gpgme_strerror(rc));
179
 
      return false;
180
 
    }
181
 
    
182
 
    ret = TEMP_FAILURE_RETRY(close(fd));
183
 
    if(ret == -1){
184
 
      perror("close");
185
 
    }
186
 
    gpgme_data_release(pgp_data);
187
 
    return true;
188
 
  }
189
 
  
190
150
  if (debug){
191
 
    fprintf(stderr, "Initialize gpgme\n");
 
151
    fprintf(stderr, "Trying to decrypt OpenPGP data\n");
192
152
  }
193
153
  
194
154
  /* Init GPGME */
197
157
  if (rc != GPG_ERR_NO_ERROR){
198
158
    fprintf(stderr, "bad gpgme_engine_check_version: %s: %s\n",
199
159
            gpgme_strsource(rc), gpgme_strerror(rc));
200
 
    return false;
 
160
    return -1;
201
161
  }
202
162
  
203
 
    /* Set GPGME home directory for the OpenPGP engine only */
 
163
  /* Set GPGME home directory for the OpenPGP engine only */
204
164
  rc = gpgme_get_engine_info (&engine_info);
205
165
  if (rc != GPG_ERR_NO_ERROR){
206
166
    fprintf(stderr, "bad gpgme_get_engine_info: %s: %s\n",
207
167
            gpgme_strsource(rc), gpgme_strerror(rc));
208
 
    return false;
 
168
    return -1;
209
169
  }
210
170
  while(engine_info != NULL){
211
171
    if(engine_info->protocol == GPGME_PROTOCOL_OpenPGP){
212
172
      gpgme_set_engine_info(GPGME_PROTOCOL_OpenPGP,
213
 
                            engine_info->file_name, tempdir);
 
173
                            engine_info->file_name, homedir);
214
174
      break;
215
175
    }
216
176
    engine_info = engine_info->next;
217
177
  }
218
178
  if(engine_info == NULL){
219
 
    fprintf(stderr, "Could not set GPGME home dir to %s\n", tempdir);
220
 
    return false;
221
 
  }
222
 
  
223
 
  /* Create new GPGME "context" */
224
 
  rc = gpgme_new(&(mc->ctx));
225
 
  if (rc != GPG_ERR_NO_ERROR){
226
 
    fprintf(stderr, "bad gpgme_new: %s: %s\n",
227
 
            gpgme_strsource(rc), gpgme_strerror(rc));
228
 
    return false;
229
 
  }
230
 
  
231
 
  if (not import_key(pubkey) or not import_key(seckey)){
232
 
    return false;
233
 
  }
234
 
  
235
 
  return true; 
236
 
}
237
 
 
238
 
/* 
239
 
 * Decrypt OpenPGP data.
240
 
 * Returns -1 on error
241
 
 */
242
 
static ssize_t pgp_packet_decrypt (const mandos_context *mc,
243
 
                                   const char *cryptotext,
244
 
                                   size_t crypto_size,
245
 
                                   char **plaintext){
246
 
  gpgme_data_t dh_crypto, dh_plain;
247
 
  gpgme_error_t rc;
248
 
  ssize_t ret;
249
 
  size_t plaintext_capacity = 0;
250
 
  ssize_t plaintext_length = 0;
251
 
  
252
 
  if (debug){
253
 
    fprintf(stderr, "Trying to decrypt OpenPGP data\n");
 
179
    fprintf(stderr, "Could not set GPGME home dir to %s\n", homedir);
 
180
    return -1;
254
181
  }
255
182
  
256
183
  /* Create new GPGME data buffer from memory cryptotext */
271
198
    return -1;
272
199
  }
273
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
  
274
210
  /* Decrypt data from the cryptotext data buffer to the plaintext
275
211
     data buffer */
276
 
  rc = gpgme_op_decrypt(mc->ctx, dh_crypto, dh_plain);
 
212
  rc = gpgme_op_decrypt(ctx, dh_crypto, dh_plain);
277
213
  if (rc != GPG_ERR_NO_ERROR){
278
214
    fprintf(stderr, "bad gpgme_op_decrypt: %s: %s\n",
279
215
            gpgme_strsource(rc), gpgme_strerror(rc));
280
216
    plaintext_length = -1;
281
217
    if (debug){
282
218
      gpgme_decrypt_result_t result;
283
 
      result = gpgme_op_decrypt_result(mc->ctx);
 
219
      result = gpgme_op_decrypt_result(ctx);
284
220
      if (result == NULL){
285
221
        fprintf(stderr, "gpgme_op_decrypt_result failed\n");
286
222
      } else {
315
251
  
316
252
  /* Seek back to the beginning of the GPGME plaintext data buffer */
317
253
  if (gpgme_data_seek(dh_plain, (off_t) 0, SEEK_SET) == -1){
318
 
    perror("gpgme_data_seek");
 
254
    perror("pgpme_data_seek");
319
255
    plaintext_length = -1;
320
256
    goto decrypt_end;
321
257
  }
345
281
    }
346
282
    plaintext_length += ret;
347
283
  }
348
 
  
 
284
 
349
285
  if(debug){
350
286
    fprintf(stderr, "Decrypted password is: ");
351
287
    for(ssize_t i = 0; i < plaintext_length; i++){
412
348
  }
413
349
  
414
350
  if(debug){
415
 
    fprintf(stderr, "Attempting to use OpenPGP public key %s and"
416
 
            " 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,
417
353
            seckeyfilename);
418
354
  }
419
355
  
424
360
    fprintf(stderr,
425
361
            "Error[%d] while reading the OpenPGP key pair ('%s',"
426
362
            " '%s')\n", ret, pubkeyfilename, seckeyfilename);
427
 
    fprintf(stderr, "The GnuTLS error is: %s\n",
 
363
    fprintf(stdout, "The GnuTLS error is: %s\n",
428
364
            safer_gnutls_strerror(ret));
429
365
    goto globalfail;
430
366
  }
444
380
  }
445
381
  
446
382
  gnutls_certificate_set_dh_params(mc->cred, mc->dh_params);
447
 
  
 
383
 
448
384
  return 0;
449
 
  
 
385
 
450
386
 globalfail:
451
 
  
 
387
 
452
388
  gnutls_certificate_free_credentials(mc->cred);
453
389
  gnutls_global_deinit();
454
 
  gnutls_dh_params_deinit(mc->dh_params);
455
390
  return -1;
 
391
 
456
392
}
457
393
 
458
394
static int init_gnutls_session(mandos_context *mc,
530
466
    perror("socket");
531
467
    return -1;
532
468
  }
533
 
  
 
469
 
534
470
  if(debug){
535
471
    if(if_indextoname((unsigned int)if_index, interface) == NULL){
536
472
      perror("if_indextoname");
575
511
    perror("connect");
576
512
    return -1;
577
513
  }
578
 
  
 
514
 
579
515
  const char *out = mandos_protocol_version;
580
516
  written = 0;
581
517
  while (true){
599
535
      }
600
536
    }
601
537
  }
602
 
  
 
538
 
603
539
  if(debug){
604
540
    fprintf(stderr, "Establishing TLS session with %s\n", ip);
605
541
  }
606
542
  
607
543
  gnutls_transport_set_ptr (session, (gnutls_transport_ptr_t) tcp_sd);
608
 
  
 
544
 
609
545
  do{
610
546
    ret = gnutls_handshake (session);
611
547
  } while(ret == GNUTLS_E_AGAIN or ret == GNUTLS_E_INTERRUPTED);
625
561
    fprintf(stderr, "Retrieving pgp encrypted password from %s\n",
626
562
            ip);
627
563
  }
628
 
  
 
564
 
629
565
  while(true){
630
566
    buffer_capacity = adjustbuffer(&buffer, buffer_length,
631
567
                                   buffer_capacity);
675
611
  gnutls_bye (session, GNUTLS_SHUT_RDWR);
676
612
  
677
613
  if (buffer_length > 0){
678
 
    decrypted_buffer_size = pgp_packet_decrypt(mc, buffer,
 
614
    decrypted_buffer_size = pgp_packet_decrypt(buffer,
679
615
                                               buffer_length,
680
 
                                               &decrypted_buffer);
 
616
                                               &decrypted_buffer,
 
617
                                               keydir);
681
618
    if (decrypted_buffer_size >= 0){
682
619
      written = 0;
683
620
      while(written < (size_t) decrypted_buffer_size){
706
643
  
707
644
 mandos_end:
708
645
  free(buffer);
709
 
  ret = TEMP_FAILURE_RETRY(close(tcp_sd));
710
 
  if(ret == -1){
711
 
    perror("close");
712
 
  }
 
646
  close(tcp_sd);
713
647
  gnutls_deinit (session);
714
648
  return retval;
715
649
}
811
745
  }
812
746
}
813
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
 
814
760
int main(int argc, char *argv[]){
815
761
    AvahiSServiceBrowser *sb = NULL;
816
762
    int error;
822
768
    uid_t uid;
823
769
    gid_t gid;
824
770
    char *connect_to = NULL;
825
 
    char tempdir[] = "/tmp/mandosXXXXXX";
826
771
    AvahiIfIndex if_index = AVAHI_IF_UNSPEC;
827
 
    const char *seckey = PATHDIR "/" SECKEY;
828
 
    const char *pubkey = PATHDIR "/" PUBKEY;
829
 
    
 
772
    char *pubkeyfilename = NULL;
 
773
    char *seckeyfilename = NULL;
 
774
    const char *pubkeyname = "pubkey.txt";
 
775
    const char *seckeyname = "seckey.txt";
830
776
    mandos_context mc = { .simple_poll = NULL, .server = NULL,
831
 
                          .dh_bits = 1024, .priority = "SECURE256"
832
 
                          ":!CTYPE-X.509:+CTYPE-OPENPGP" };
 
777
                          .dh_bits = 1024, .priority = "SECURE256"};
833
778
    bool gnutls_initalized = false;
834
 
    bool gpgme_initalized = false;
835
779
    
836
780
    {
837
781
      struct argp_option options[] = {
838
782
        { .name = "debug", .key = 128,
839
783
          .doc = "Debug mode", .group = 3 },
840
784
        { .name = "connect", .key = 'c',
841
 
          .arg = "ADDRESS:PORT",
842
 
          .doc = "Connect directly to a specific Mandos server",
 
785
          .arg = "IP",
 
786
          .doc = "Connect directly to a sepcified mandos server",
843
787
          .group = 1 },
844
788
        { .name = "interface", .key = 'i',
845
 
          .arg = "NAME",
846
 
          .doc = "Interface that will be used to search for Mandos"
847
 
          " 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",
848
795
          .group = 1 },
849
796
        { .name = "seckey", .key = 's',
850
 
          .arg = "FILE",
851
 
          .doc = "OpenPGP secret key file base name",
 
797
          .arg = "SECKEY",
 
798
          .doc = "Secret openpgp key for gnutls authentication",
852
799
          .group = 1 },
853
800
        { .name = "pubkey", .key = 'p',
854
 
          .arg = "FILE",
855
 
          .doc = "OpenPGP public key file base name",
 
801
          .arg = "PUBKEY",
 
802
          .doc = "Public openpgp key for gnutls authentication",
856
803
          .group = 2 },
857
804
        { .name = "dh-bits", .key = 129,
858
805
          .arg = "BITS",
859
 
          .doc = "Bit length of the prime number used in the"
860
 
          " Diffie-Hellman key exchange",
 
806
          .doc = "dh-bits to use in gnutls communication",
861
807
          .group = 2 },
862
808
        { .name = "priority", .key = 130,
863
 
          .arg = "STRING",
864
 
          .doc = "GnuTLS priority string for the TLS handshake",
865
 
          .group = 1 },
 
809
          .arg = "PRIORITY",
 
810
          .doc = "GNUTLS priority", .group = 1 },
866
811
        { .name = NULL }
867
812
      };
 
813
 
868
814
      
869
815
      error_t parse_opt (int key, char *arg,
870
816
                         struct argp_state *state) {
871
817
        /* Get the INPUT argument from `argp_parse', which we know is
872
818
           a pointer to our plugin list pointer. */
873
819
        switch (key) {
874
 
        case 128:               /* --debug */
 
820
        case 128:
875
821
          debug = true;
876
822
          break;
877
 
        case 'c':               /* --connect */
 
823
        case 'c':
878
824
          connect_to = arg;
879
825
          break;
880
 
        case 'i':               /* --interface */
 
826
        case 'i':
881
827
          interface = arg;
882
828
          break;
883
 
        case 's':               /* --seckey */
884
 
          seckey = arg;
885
 
          break;
886
 
        case 'p':               /* --pubkey */
887
 
          pubkey = arg;
888
 
          break;
889
 
        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:
890
839
          errno = 0;
891
840
          mc.dh_bits = (unsigned int) strtol(arg, NULL, 10);
892
841
          if (errno){
894
843
            exit(EXIT_FAILURE);
895
844
          }
896
845
          break;
897
 
        case 130:               /* --priority */
 
846
        case 130:
898
847
          mc.priority = arg;
899
848
          break;
900
849
        case ARGP_KEY_ARG:
906
855
        }
907
856
        return 0;
908
857
      }
909
 
      
 
858
 
910
859
      struct argp argp = { .options = options, .parser = parse_opt,
911
860
                           .args_doc = "",
912
861
                           .doc = "Mandos client -- Get and decrypt"
913
 
                           " passwords from a Mandos server" };
 
862
                           " passwords from mandos server" };
914
863
      ret = argp_parse (&argp, argc, argv, 0, 0, NULL);
915
864
      if (ret == ARGP_ERR_UNKNOWN){
916
865
        fprintf(stderr, "Unknown error while parsing arguments\n");
918
867
        goto end;
919
868
      }
920
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
    }
921
893
    
922
894
    /* If the interface is down, bring it up */
923
895
    {
943
915
          goto end;
944
916
        }
945
917
      }
946
 
      ret = TEMP_FAILURE_RETRY(close(sd));
947
 
      if(ret == -1){
948
 
        perror("close");
949
 
      }
 
918
      close(sd);
950
919
    }
951
920
    
952
921
    uid = getuid();
962
931
      perror("setgid");
963
932
    }
964
933
    
965
 
    ret = init_gnutls_global(&mc, pubkey, seckey);
966
 
    if (ret == -1){
967
 
      fprintf(stderr, "init_gnutls_global failed\n");
968
 
      exitcode = EXIT_FAILURE;
969
 
      goto end;
970
 
    } else {
971
 
      gnutls_initalized = true;
972
 
    }
973
 
    
974
 
    if(mkdtemp(tempdir) == NULL){
975
 
      perror("mkdtemp");
976
 
      tempdir[0] = '\0';
977
 
      goto end;
978
 
    }
979
 
    
980
 
    if(not init_gpgme(&mc, pubkey, seckey, tempdir)){
981
 
      fprintf(stderr, "gpgme_initalized failed\n");
982
 
      exitcode = EXIT_FAILURE;
983
 
      goto end;
984
 
    } else {
985
 
      gpgme_initalized = true;
986
 
    }
987
 
    
988
934
    if_index = (AvahiIfIndex) if_nametoindex(interface);
989
935
    if(if_index == 0){
990
936
      fprintf(stderr, "No such interface: \"%s\"\n", interface);
1033
979
        exitcode = EXIT_FAILURE;
1034
980
        goto end;
1035
981
    }
1036
 
    
 
982
 
1037
983
    {
1038
984
      AvahiServerConfig config;
1039
985
      /* Do not publish any local Zeroconf records */
1042
988
      config.publish_addresses = 0;
1043
989
      config.publish_workstation = 0;
1044
990
      config.publish_domain = 0;
1045
 
      
 
991
 
1046
992
      /* Allocate a new server */
1047
993
      mc.server = avahi_server_new(avahi_simple_poll_get
1048
994
                                   (mc.simple_poll), &config, NULL,
1049
995
                                   NULL, &error);
1050
 
      
 
996
    
1051
997
      /* Free the Avahi configuration data */
1052
998
      avahi_server_config_free(&config);
1053
999
    }
1073
1019
    }
1074
1020
    
1075
1021
    /* Run the main loop */
1076
 
    
 
1022
 
1077
1023
    if (debug){
1078
1024
      fprintf(stderr, "Starting Avahi loop search\n");
1079
1025
    }
1081
1027
    avahi_simple_poll_loop(mc.simple_poll);
1082
1028
    
1083
1029
 end:
1084
 
    
 
1030
 
1085
1031
    if (debug){
1086
1032
      fprintf(stderr, "%s exiting\n", argv[0]);
1087
1033
    }
1092
1038
    
1093
1039
    if (mc.server != NULL)
1094
1040
        avahi_server_free(mc.server);
1095
 
    
 
1041
 
1096
1042
    if (mc.simple_poll != NULL)
1097
1043
        avahi_simple_poll_free(mc.simple_poll);
1098
 
    
 
1044
    free(pubkeyfilename);
 
1045
    free(seckeyfilename);
 
1046
 
1099
1047
    if (gnutls_initalized){
1100
1048
      gnutls_certificate_free_credentials(mc.cred);
1101
1049
      gnutls_global_deinit ();
1102
 
      gnutls_dh_params_deinit(mc.dh_params);
1103
 
    }
1104
 
    
1105
 
    if(gpgme_initalized){
1106
 
      gpgme_release(mc.ctx);
1107
 
    }
1108
 
    
1109
 
    /* Removes the temp directory used by GPGME */
1110
 
    if(tempdir[0] != '\0'){
1111
 
      DIR *d;
1112
 
      struct dirent *direntry;
1113
 
      d = opendir(tempdir);
1114
 
      if(d == NULL){
1115
 
        perror("opendir");
1116
 
      } else {
1117
 
        while(true){
1118
 
          direntry = readdir(d);
1119
 
          if(direntry == NULL){
1120
 
            break;
1121
 
          }
1122
 
          if (direntry->d_type == DT_REG){
1123
 
            char *fullname = NULL;
1124
 
            ret = asprintf(&fullname, "%s/%s", tempdir,
1125
 
                           direntry->d_name);
1126
 
            if(ret < 0){
1127
 
              perror("asprintf");
1128
 
              continue;
1129
 
            }
1130
 
            ret = unlink(fullname);
1131
 
            if(ret == -1){
1132
 
              fprintf(stderr, "unlink(\"%s\"): %s",
1133
 
                      fullname, strerror(errno));
1134
 
            }
1135
 
            free(fullname);
1136
 
          }
1137
 
        }
1138
 
        closedir(d);
1139
 
      }
1140
 
      ret = rmdir(tempdir);
1141
 
      if(ret == -1){
1142
 
        perror("rmdir");
1143
 
      }
1144
 
    }
1145
 
          
 
1050
    }
 
1051
    
1146
1052
    return exitcode;
1147
1053
}