/mandos/trunk

To get this branch, use:
bzr branch http://bzr.recompile.se/loggerhead/mandos/trunk
13 by Björn Påhlsson
Added following support:
1
/***
2
  This file is part of avahi.
3
 
4
  avahi is free software; you can redistribute it and/or modify it
5
  under the terms of the GNU Lesser General Public License as
6
  published by the Free Software Foundation; either version 2.1 of the
7
  License, or (at your option) any later version.
8
 
9
  avahi is distributed in the hope that it will be useful, but WITHOUT
10
  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11
  or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
12
  Public License for more details.
13
 
14
  You should have received a copy of the GNU Lesser General Public
15
  License along with avahi; if not, write to the Free Software
16
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
17
  USA.
18
***/
19
20
#define _LARGEFILE_SOURCE
21
#define _FILE_OFFSET_BITS 64
22
23
#include <stdio.h>
24
#include <assert.h>
25
#include <stdlib.h>
26
#include <time.h>
27
#include <net/if.h>		/* if_nametoindex */
28
29
#include <avahi-core/core.h>
30
#include <avahi-core/lookup.h>
31
#include <avahi-core/log.h>
32
#include <avahi-common/simple-watch.h>
33
#include <avahi-common/malloc.h>
34
#include <avahi-common/error.h>
35
36
//mandos client part
37
#include <sys/types.h>		/* socket(), setsockopt(), inet_pton() */
38
#include <sys/socket.h>		/* socket(), setsockopt(), struct sockaddr_in6, struct in6_addr, inet_pton() */
39
#include <gnutls/gnutls.h>	/* ALL GNUTLS STUFF */
40
#include <gnutls/openpgp.h>	/* gnutls with openpgp stuff */
41
42
#include <unistd.h>		/* close() */
43
#include <netinet/in.h>
44
#include <stdbool.h>		/* true */
45
#include <string.h>		/* memset */
46
#include <arpa/inet.h>		/* inet_pton() */
47
#include <iso646.h>		/* not */
48
49
// gpgme
50
#include <errno.h>		/* perror() */
51
#include <gpgme.h>
52
15.1.3 by Björn Påhlsson
Added getopt_long support for mandosclient and passprompt
53
// getopt long
54
#include <getopt.h>
13 by Björn Påhlsson
Added following support:
55
56
#ifndef CERT_ROOT
57
#define CERT_ROOT "/conf/conf.d/cryptkeyreq/"
58
#endif
59
#define CERTFILE CERT_ROOT "openpgp-client.txt"
60
#define KEYFILE CERT_ROOT "openpgp-client-key.txt"
61
#define BUFFER_SIZE 256
62
#define DH_BITS 1024
63
15.1.2 by Björn Påhlsson
Added debug options from passprompt as --debug and --debug=passprompt
64
bool debug = false;
15.1.3 by Björn Påhlsson
Added getopt_long support for mandosclient and passprompt
65
char *interface = "eth0";
15.1.1 by Björn Påhlsson
Added debugg support in form off --debug and --debug=mandosclient
66
13 by Björn Påhlsson
Added following support:
67
typedef struct {
68
  gnutls_session_t session;
69
  gnutls_certificate_credentials_t cred;
70
  gnutls_dh_params_t dh_params;
71
} encrypted_session;
72
73
74
ssize_t gpg_packet_decrypt (char *packet, size_t packet_size, char **new_packet, char *homedir){
75
  gpgme_data_t dh_crypto, dh_plain;
76
  gpgme_ctx_t ctx;
77
  gpgme_error_t rc;
78
  ssize_t ret;
79
  size_t new_packet_capacity = 0;
80
  size_t new_packet_length = 0;
81
  gpgme_engine_info_t engine_info;
82
15.1.1 by Björn Påhlsson
Added debugg support in form off --debug and --debug=mandosclient
83
  if (debug){
84
    fprintf(stderr, "Attempting to decrypt password from gpg packet\n");
85
  }
86
  
13 by Björn Påhlsson
Added following support:
87
  /* Init GPGME */
88
  gpgme_check_version(NULL);
89
  gpgme_engine_check_version(GPGME_PROTOCOL_OpenPGP);
90
  
91
  /* Set GPGME home directory */
92
  rc = gpgme_get_engine_info (&engine_info);
93
  if (rc != GPG_ERR_NO_ERROR){
94
    fprintf(stderr, "bad gpgme_get_engine_info: %s: %s\n",
95
	    gpgme_strsource(rc), gpgme_strerror(rc));
96
    return -1;
97
  }
98
  while(engine_info != NULL){
99
    if(engine_info->protocol == GPGME_PROTOCOL_OpenPGP){
100
      gpgme_set_engine_info(GPGME_PROTOCOL_OpenPGP,
101
			    engine_info->file_name, homedir);
102
      break;
103
    }
104
    engine_info = engine_info->next;
105
  }
106
  if(engine_info == NULL){
107
    fprintf(stderr, "Could not set home dir to %s\n", homedir);
108
    return -1;
109
  }
110
  
111
  /* Create new GPGME data buffer from packet buffer */
112
  rc = gpgme_data_new_from_mem(&dh_crypto, packet, packet_size, 0);
113
  if (rc != GPG_ERR_NO_ERROR){
114
    fprintf(stderr, "bad gpgme_data_new_from_mem: %s: %s\n",
115
	    gpgme_strsource(rc), gpgme_strerror(rc));
116
    return -1;
117
  }
118
  
119
  /* Create new empty GPGME data buffer for the plaintext */
120
  rc = gpgme_data_new(&dh_plain);
121
  if (rc != GPG_ERR_NO_ERROR){
122
    fprintf(stderr, "bad gpgme_data_new: %s: %s\n",
123
	    gpgme_strsource(rc), gpgme_strerror(rc));
124
    return -1;
125
  }
126
  
127
  /* Create new GPGME "context" */
128
  rc = gpgme_new(&ctx);
129
  if (rc != GPG_ERR_NO_ERROR){
130
    fprintf(stderr, "bad gpgme_new: %s: %s\n",
131
	    gpgme_strsource(rc), gpgme_strerror(rc));
132
    return -1;
133
  }
134
  
135
  /* Decrypt data from the FILE pointer to the plaintext data buffer */
136
  rc = gpgme_op_decrypt(ctx, dh_crypto, dh_plain);
137
  if (rc != GPG_ERR_NO_ERROR){
138
    fprintf(stderr, "bad gpgme_op_decrypt: %s: %s\n",
139
	    gpgme_strsource(rc), gpgme_strerror(rc));
140
    return -1;
141
  }
15.1.1 by Björn Påhlsson
Added debugg support in form off --debug and --debug=mandosclient
142
143
  if(debug){
144
    fprintf(stderr, "decryption of gpg packet succeeded\n");
145
  }
146
147
  if (debug){
148
    gpgme_decrypt_result_t result;
149
    result = gpgme_op_decrypt_result(ctx);
150
    if (result == NULL){
151
      fprintf(stderr, "gpgme_op_decrypt_result failed\n");
152
    } else {
153
      fprintf(stderr, "Unsupported algorithm: %s\n", result->unsupported_algorithm);
154
      fprintf(stderr, "Wrong key usage: %d\n", result->wrong_key_usage);
155
      if(result->file_name != NULL){
156
	fprintf(stderr, "File name: %s\n", result->file_name);
157
      }
158
      gpgme_recipient_t recipient;
159
      recipient = result->recipients;
160
      if(recipient){
161
	while(recipient != NULL){
162
	  fprintf(stderr, "Public key algorithm: %s\n",
163
		  gpgme_pubkey_algo_name(recipient->pubkey_algo));
164
	  fprintf(stderr, "Key ID: %s\n", recipient->keyid);
165
	  fprintf(stderr, "Secret key available: %s\n",
166
		  recipient->status == GPG_ERR_NO_SECKEY ? "No" : "Yes");
167
	  recipient = recipient->next;
168
	}
169
      }
170
    }
171
  }
13 by Björn Påhlsson
Added following support:
172
  
173
  /* Delete the GPGME FILE pointer cryptotext data buffer */
174
  gpgme_data_release(dh_crypto);
175
  
176
  /* Seek back to the beginning of the GPGME plaintext data buffer */
177
  gpgme_data_seek(dh_plain, 0, SEEK_SET);
178
179
  *new_packet = 0;
180
  while(true){
181
    if (new_packet_length + BUFFER_SIZE > new_packet_capacity){
182
      *new_packet = realloc(*new_packet, new_packet_capacity + BUFFER_SIZE);
183
      if (*new_packet == NULL){
184
	perror("realloc");
185
	return -1;
186
      }
187
      new_packet_capacity += BUFFER_SIZE;
188
    }
189
    
190
    ret = gpgme_data_read(dh_plain, *new_packet + new_packet_length, BUFFER_SIZE);
191
    /* Print the data, if any */
192
    if (ret == 0){
193
      /* If password is empty, then a incorrect error will be printed */
194
      break;
195
    }
196
    if(ret < 0){
197
      perror("gpgme_data_read");
198
      return -1;
199
    }
200
    new_packet_length += ret;
201
  }
202
15.1.3 by Björn Påhlsson
Added getopt_long support for mandosclient and passprompt
203
  /* FIXME: check characters before printing to screen so to not print
204
     terminal control characters */
205
  /*   if(debug){ */
206
  /*     fprintf(stderr, "decrypted password is: "); */
207
  /*     fwrite(*new_packet, 1, new_packet_length, stderr); */
208
  /*     fprintf(stderr, "\n"); */
209
  /*   } */
210
  
211
  /* Delete the GPGME plaintext data buffer */
13 by Björn Påhlsson
Added following support:
212
  gpgme_data_release(dh_plain);
213
  return new_packet_length;
214
}
215
216
static const char * safer_gnutls_strerror (int value) {
217
  const char *ret = gnutls_strerror (value);
218
  if (ret == NULL)
219
    ret = "(unknown)";
220
  return ret;
221
}
222
223
void debuggnutls(int level, const char* string){
224
  fprintf(stderr, "%s", string);
225
}
226
227
int initgnutls(encrypted_session *es){
228
  const char *err;
229
  int ret;
15.1.1 by Björn Påhlsson
Added debugg support in form off --debug and --debug=mandosclient
230
231
  if(debug){
232
    fprintf(stderr, "Initializing gnutls\n");
233
  }
234
13 by Björn Påhlsson
Added following support:
235
  
236
  if ((ret = gnutls_global_init ())
237
      != GNUTLS_E_SUCCESS) {
238
    fprintf (stderr, "global_init: %s\n", safer_gnutls_strerror(ret));
239
    return -1;
240
  }
241
15.1.1 by Björn Påhlsson
Added debugg support in form off --debug and --debug=mandosclient
242
  if (debug){
243
    gnutls_global_set_log_level(11);
244
    gnutls_global_set_log_function(debuggnutls);
245
  }
246
  
13 by Björn Påhlsson
Added following support:
247
248
  /* openpgp credentials */
249
  if ((ret = gnutls_certificate_allocate_credentials (&es->cred))
250
      != GNUTLS_E_SUCCESS) {
251
    fprintf (stderr, "memory error: %s\n", safer_gnutls_strerror(ret));
252
    return -1;
253
  }
254
15.1.1 by Björn Påhlsson
Added debugg support in form off --debug and --debug=mandosclient
255
  if(debug){
256
    fprintf(stderr, "Attempting to use openpgp certificate %s"
257
	    " and keyfile %s as gnutls credentials\n", CERTFILE, KEYFILE);
258
  }
259
13 by Björn Påhlsson
Added following support:
260
  ret = gnutls_certificate_set_openpgp_key_file
261
    (es->cred, CERTFILE, KEYFILE, GNUTLS_OPENPGP_FMT_BASE64);
262
  if (ret != GNUTLS_E_SUCCESS) {
263
    fprintf
264
      (stderr, "Error[%d] while reading the OpenPGP key pair ('%s', '%s')\n",
265
       ret, CERTFILE, KEYFILE);
266
    fprintf(stdout, "The Error is: %s\n",
267
	    safer_gnutls_strerror(ret));
268
    return -1;
269
  }
270
271
  //Gnutls server initialization
272
  if ((ret = gnutls_dh_params_init (&es->dh_params))
273
      != GNUTLS_E_SUCCESS) {
274
    fprintf (stderr, "Error in dh parameter initialization: %s\n",
275
	     safer_gnutls_strerror(ret));
276
    return -1;
277
  }
278
279
  if ((ret = gnutls_dh_params_generate2 (es->dh_params, DH_BITS))
280
      != GNUTLS_E_SUCCESS) {
281
    fprintf (stderr, "Error in prime generation: %s\n",
282
	     safer_gnutls_strerror(ret));
283
    return -1;
284
  }
285
286
  gnutls_certificate_set_dh_params (es->cred, es->dh_params);
287
288
  // Gnutls session creation
289
  if ((ret = gnutls_init (&es->session, GNUTLS_SERVER))
290
      != GNUTLS_E_SUCCESS){
291
    fprintf(stderr, "Error in gnutls session initialization: %s\n",
292
	    safer_gnutls_strerror(ret));
293
  }
294
295
  if ((ret = gnutls_priority_set_direct (es->session, "NORMAL", &err))
296
      != GNUTLS_E_SUCCESS) {
297
    fprintf(stderr, "Syntax error at: %s\n", err);
298
    fprintf(stderr, "Gnutls error: %s\n",
299
	    safer_gnutls_strerror(ret));
300
    return -1;
301
  }
302
303
  if ((ret = gnutls_credentials_set
304
       (es->session, GNUTLS_CRD_CERTIFICATE, es->cred))
305
      != GNUTLS_E_SUCCESS) {
306
    fprintf(stderr, "Error setting a credentials set: %s\n",
307
	    safer_gnutls_strerror(ret));
308
    return -1;
309
  }
310
311
  /* ignore client certificate if any. */
312
  gnutls_certificate_server_set_request (es->session, GNUTLS_CERT_IGNORE);
313
  
314
  gnutls_dh_set_prime_bits (es->session, DH_BITS);
315
  
316
  return 0;
317
}
318
319
void empty_log(AvahiLogLevel level, const char *txt){}
320
19 by Teddy Hogeborn
* plugins.d/mandosclient.c (start_mandos_communcation): Renamed to
321
int start_mandos_communication(char *ip, uint16_t port){
13 by Björn Påhlsson
Added following support:
322
  int ret, tcp_sd;
323
  struct sockaddr_in6 to;
324
  encrypted_session es;
325
  char *buffer = NULL;
326
  char *decrypted_buffer;
327
  size_t buffer_length = 0;
328
  size_t buffer_capacity = 0;
329
  ssize_t decrypted_buffer_size;
330
  int retval = 0;
331
15.1.1 by Björn Påhlsson
Added debugg support in form off --debug and --debug=mandosclient
332
  if(debug){
333
    fprintf(stderr, "Setting up a tcp connection to %s\n", ip);
334
  }
13 by Björn Påhlsson
Added following support:
335
  
336
  tcp_sd = socket(PF_INET6, SOCK_STREAM, 0);
337
  if(tcp_sd < 0) {
338
    perror("socket");
339
    return -1;
340
  }
15.1.1 by Björn Påhlsson
Added debugg support in form off --debug and --debug=mandosclient
341
342
  if(debug){
343
    fprintf(stderr, "Binding to interface %s\n", interface);
344
  }
345
346
  ret = setsockopt(tcp_sd, SOL_SOCKET, SO_BINDTODEVICE, interface, 5);
13 by Björn Påhlsson
Added following support:
347
  if(tcp_sd < 0) {
348
    perror("setsockopt bindtodevice");
349
    return -1;
350
  }
351
  
352
  memset(&to,0,sizeof(to));
353
  to.sin6_family = AF_INET6;
18 by Teddy Hogeborn
* plugins.d/Makefile: Removed
354
  ret = inet_pton(AF_INET6, ip, &to.sin6_addr);
13 by Björn Påhlsson
Added following support:
355
  if (ret < 0 ){
356
    perror("inet_pton");
357
    return -1;
358
  }  
359
  if(ret == 0){
360
    fprintf(stderr, "Bad address: %s\n", ip);
361
    return -1;
362
  }
363
  to.sin6_port = htons(port);
15.1.1 by Björn Påhlsson
Added debugg support in form off --debug and --debug=mandosclient
364
  to.sin6_scope_id = if_nametoindex(interface);
365
366
  if(debug){
367
    fprintf(stderr, "Connection to: %s\n", ip);
368
  }
13 by Björn Påhlsson
Added following support:
369
  
370
  ret = connect(tcp_sd, (struct sockaddr *) &to, sizeof(to));
371
  if (ret < 0){
372
    perror("connect");
373
    return -1;
374
  }
375
  
376
  ret = initgnutls (&es);
377
  if (ret != 0){
378
    retval = -1;
379
    return -1;
380
  }
381
    
382
  
383
  gnutls_transport_set_ptr (es.session, (gnutls_transport_ptr_t) tcp_sd);
384
15.1.1 by Björn Påhlsson
Added debugg support in form off --debug and --debug=mandosclient
385
  if(debug){
386
    fprintf(stderr, "Establishing tls session with %s\n", ip);
387
  }
388
389
  
13 by Björn Påhlsson
Added following support:
390
  ret = gnutls_handshake (es.session);
391
  
392
  if (ret != GNUTLS_E_SUCCESS){
393
    fprintf(stderr, "\n*** Handshake failed ***\n");
394
    gnutls_perror (ret);
395
    retval = -1;
396
    goto exit;
397
  }
398
15.1.1 by Björn Påhlsson
Added debugg support in form off --debug and --debug=mandosclient
399
  //Retrieve gpg packet that contains the wanted password
400
401
  if(debug){
402
    fprintf(stderr, "Retrieving pgp encrypted password from %s\n", ip);
403
  }
404
13 by Björn Påhlsson
Added following support:
405
  while(true){
406
    if (buffer_length + BUFFER_SIZE > buffer_capacity){
407
      buffer = realloc(buffer, buffer_capacity + BUFFER_SIZE);
408
      if (buffer == NULL){
409
	perror("realloc");
410
	goto exit;
411
      }
412
      buffer_capacity += BUFFER_SIZE;
413
    }
414
    
415
    ret = gnutls_record_recv
416
      (es.session, buffer+buffer_length, BUFFER_SIZE);
417
    if (ret == 0){
418
      break;
419
    }
420
    if (ret < 0){
421
      switch(ret){
422
      case GNUTLS_E_INTERRUPTED:
423
      case GNUTLS_E_AGAIN:
424
	break;
425
      case GNUTLS_E_REHANDSHAKE:
426
	ret = gnutls_handshake (es.session);
427
	if (ret < 0){
428
	  fprintf(stderr, "\n*** Handshake failed ***\n");
429
	  gnutls_perror (ret);
430
	  retval = -1;
431
	  goto exit;
432
	}
433
	break;
434
      default:
435
	fprintf(stderr, "Unknown error while reading data from encrypted session with mandos server\n");
436
	retval = -1;
437
	gnutls_bye (es.session, GNUTLS_SHUT_RDWR);
438
	goto exit;
439
      }
440
    } else {
441
      buffer_length += ret;
442
    }
443
  }
15.1.1 by Björn Påhlsson
Added debugg support in form off --debug and --debug=mandosclient
444
  
13 by Björn Påhlsson
Added following support:
445
  if (buffer_length > 0){
15.1.1 by Björn Påhlsson
Added debugg support in form off --debug and --debug=mandosclient
446
    if ((decrypted_buffer_size = gpg_packet_decrypt(buffer, buffer_length, &decrypted_buffer, CERT_ROOT)) >= 0){
13 by Björn Påhlsson
Added following support:
447
      fwrite (decrypted_buffer, 1, decrypted_buffer_size, stdout);
448
      free(decrypted_buffer);
15.1.1 by Björn Påhlsson
Added debugg support in form off --debug and --debug=mandosclient
449
    } else {
450
      retval = -1;
13 by Björn Påhlsson
Added following support:
451
    }
452
  }
453
15.1.1 by Björn Påhlsson
Added debugg support in form off --debug and --debug=mandosclient
454
  //shutdown procedure
455
456
  if(debug){
457
    fprintf(stderr, "Closing tls session\n");
458
  }
459
13 by Björn Påhlsson
Added following support:
460
  free(buffer);
461
  gnutls_bye (es.session, GNUTLS_SHUT_RDWR);
462
 exit:
463
  close(tcp_sd);
464
  gnutls_deinit (es.session);
465
  gnutls_certificate_free_credentials (es.cred);
466
  gnutls_global_deinit ();
467
  return retval;
468
}
469
470
static AvahiSimplePoll *simple_poll = NULL;
471
static AvahiServer *server = NULL;
472
473
static void resolve_callback(
474
    AvahiSServiceResolver *r,
475
    AVAHI_GCC_UNUSED AvahiIfIndex interface,
476
    AVAHI_GCC_UNUSED AvahiProtocol protocol,
477
    AvahiResolverEvent event,
478
    const char *name,
479
    const char *type,
480
    const char *domain,
481
    const char *host_name,
482
    const AvahiAddress *address,
483
    uint16_t port,
484
    AvahiStringList *txt,
485
    AvahiLookupResultFlags flags,
486
    AVAHI_GCC_UNUSED void* userdata) {
487
    
488
    assert(r);
489
490
    /* Called whenever a service has been resolved successfully or timed out */
491
492
    switch (event) {
493
        case AVAHI_RESOLVER_FAILURE:
494
            fprintf(stderr, "(Resolver) Failed to resolve service '%s' of type '%s' in domain '%s': %s\n", name, type, domain, avahi_strerror(avahi_server_errno(server)));
495
            break;
496
497
        case AVAHI_RESOLVER_FOUND: {
498
	  char ip[AVAHI_ADDRESS_STR_MAX];
499
            avahi_address_snprint(ip, sizeof(ip), address);
15.1.1 by Björn Påhlsson
Added debugg support in form off --debug and --debug=mandosclient
500
	    if(debug){
501
	      fprintf(stderr, "Mandos server found at %s on port %d\n", ip, port);
502
	    }
19 by Teddy Hogeborn
* plugins.d/mandosclient.c (start_mandos_communcation): Renamed to
503
	    int ret = start_mandos_communication(ip, port);
13 by Björn Påhlsson
Added following support:
504
	    if (ret == 0){
505
	      exit(EXIT_SUCCESS);
506
	    } else {
507
	      exit(EXIT_FAILURE);
508
	    }
509
        }
510
    }
511
    avahi_s_service_resolver_free(r);
512
}
513
514
static void browse_callback(
515
    AvahiSServiceBrowser *b,
516
    AvahiIfIndex interface,
517
    AvahiProtocol protocol,
518
    AvahiBrowserEvent event,
519
    const char *name,
520
    const char *type,
521
    const char *domain,
522
    AVAHI_GCC_UNUSED AvahiLookupResultFlags flags,
523
    void* userdata) {
524
    
525
    AvahiServer *s = userdata;
526
    assert(b);
527
528
    /* Called whenever a new services becomes available on the LAN or is removed from the LAN */
529
530
    switch (event) {
531
532
        case AVAHI_BROWSER_FAILURE:
533
            
534
            fprintf(stderr, "(Browser) %s\n", avahi_strerror(avahi_server_errno(server)));
535
            avahi_simple_poll_quit(simple_poll);
536
            return;
537
538
        case AVAHI_BROWSER_NEW:
539
            /* We ignore the returned resolver object. In the callback
540
               function we free it. If the server is terminated before
541
               the callback function is called the server will free
542
               the resolver for us. */
543
            
544
            if (!(avahi_s_service_resolver_new(s, interface, protocol, name, type, domain, AVAHI_PROTO_INET6, 0, resolve_callback, s)))
545
                fprintf(stderr, "Failed to resolve service '%s': %s\n", name, avahi_strerror(avahi_server_errno(s)));
546
            
547
            break;
548
549
        case AVAHI_BROWSER_REMOVE:
550
            break;
551
552
        case AVAHI_BROWSER_ALL_FOR_NOW:
553
        case AVAHI_BROWSER_CACHE_EXHAUSTED:
554
            break;
555
    }
556
}
557
558
int main(AVAHI_GCC_UNUSED int argc, AVAHI_GCC_UNUSED char*argv[]) {
559
    AvahiServerConfig config;
560
    AvahiSServiceBrowser *sb = NULL;
561
    int error;
15.1.3 by Björn Påhlsson
Added getopt_long support for mandosclient and passprompt
562
    int ret;
15.1.1 by Björn Påhlsson
Added debugg support in form off --debug and --debug=mandosclient
563
    int returncode = EXIT_SUCCESS;
15.1.3 by Björn Påhlsson
Added getopt_long support for mandosclient and passprompt
564
565
    while (true){
566
      static struct option long_options[] = {
567
	{"debug", no_argument, (int *)&debug, 1},
568
	{"interface", required_argument, 0, 'i'},
569
	{0, 0, 0, 0} };
570
571
      int option_index = 0;
572
      ret = getopt_long (argc, argv, "i:", long_options, &option_index);
573
574
      if (ret == -1){
575
	break;
576
      }
577
      
578
      switch(ret){
579
      case 0:
580
	break;
581
      case 'i':
582
	interface = optarg;
583
	break;
584
      default:
585
	exit(EXIT_FAILURE);
586
      }
587
    }
588
    
15.1.1 by Björn Påhlsson
Added debugg support in form off --debug and --debug=mandosclient
589
    if (not debug){
590
      avahi_set_log_function(empty_log);
591
    }
13 by Björn Påhlsson
Added following support:
592
    
593
    /* Initialize the psuedo-RNG */
594
    srand(time(NULL));
595
596
    /* Allocate main loop object */
597
    if (!(simple_poll = avahi_simple_poll_new())) {
598
        fprintf(stderr, "Failed to create simple poll object.\n");
15.1.1 by Björn Påhlsson
Added debugg support in form off --debug and --debug=mandosclient
599
	
600
        goto exit;
13 by Björn Påhlsson
Added following support:
601
    }
602
603
    /* Do not publish any local records */
604
    avahi_server_config_init(&config);
605
    config.publish_hinfo = 0;
606
    config.publish_addresses = 0;
607
    config.publish_workstation = 0;
608
    config.publish_domain = 0;
609
610
    /* Allocate a new server */
611
    server = avahi_server_new(avahi_simple_poll_get(simple_poll), &config, NULL, NULL, &error);
612
613
    /* Free the configuration data */
614
    avahi_server_config_free(&config);
615
15.1.1 by Björn Påhlsson
Added debugg support in form off --debug and --debug=mandosclient
616
    /* Check if creating the server object succeeded */
13 by Björn Påhlsson
Added following support:
617
    if (!server) {
618
        fprintf(stderr, "Failed to create server: %s\n", avahi_strerror(error));
15.1.1 by Björn Påhlsson
Added debugg support in form off --debug and --debug=mandosclient
619
	returncode = EXIT_FAILURE;
620
        goto exit;
13 by Björn Påhlsson
Added following support:
621
    }
622
    
623
    /* Create the service browser */
624
    if (!(sb = avahi_s_service_browser_new(server, if_nametoindex("eth0"), AVAHI_PROTO_INET6, "_mandos._tcp", NULL, 0, browse_callback, server))) {
625
        fprintf(stderr, "Failed to create service browser: %s\n", avahi_strerror(avahi_server_errno(server)));
15.1.1 by Björn Påhlsson
Added debugg support in form off --debug and --debug=mandosclient
626
	returncode = EXIT_FAILURE;
627
        goto exit;
13 by Björn Påhlsson
Added following support:
628
    }
629
    
630
    /* Run the main loop */
15.1.1 by Björn Påhlsson
Added debugg support in form off --debug and --debug=mandosclient
631
632
    if (debug){
633
      fprintf(stderr, "Starting avahi loop search\n");
634
    }
635
    
13 by Björn Påhlsson
Added following support:
636
    avahi_simple_poll_loop(simple_poll);
637
    
15.1.1 by Björn Påhlsson
Added debugg support in form off --debug and --debug=mandosclient
638
exit:
639
640
    if (debug){
641
      fprintf(stderr, "%s exiting\n", argv[0]);
642
    }
13 by Björn Påhlsson
Added following support:
643
    
644
    /* Cleanup things */
645
    if (sb)
646
        avahi_s_service_browser_free(sb);
647
    
648
    if (server)
649
        avahi_server_free(server);
650
651
    if (simple_poll)
652
        avahi_simple_poll_free(simple_poll);
653
15.1.3 by Björn Påhlsson
Added getopt_long support for mandosclient and passprompt
654
    return returncode;
13 by Björn Påhlsson
Added following support:
655
}