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