/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
314
int start_mandos_communcation(char *ip, uint16_t port){
315
  int ret, tcp_sd;
316
  struct sockaddr_in6 to;
317
  struct in6_addr ip_addr;
318
  encrypted_session es;
319
  char *buffer = NULL;
320
  char *decrypted_buffer;
321
  size_t buffer_length = 0;
322
  size_t buffer_capacity = 0;
323
  ssize_t decrypted_buffer_size;
324
  int retval = 0;
15.1.1 by Björn Påhlsson
Added debugg support in form off --debug and --debug=mandosclient
325
  const char interface[] = "eth0";
13 by Björn Påhlsson
Added following support:
326
15.1.1 by Björn Påhlsson
Added debugg support in form off --debug and --debug=mandosclient
327
  if(debug){
328
    fprintf(stderr, "Setting up a tcp connection to %s\n", ip);
329
  }
13 by Björn Påhlsson
Added following support:
330
  
331
  tcp_sd = socket(PF_INET6, SOCK_STREAM, 0);
332
  if(tcp_sd < 0) {
333
    perror("socket");
334
    return -1;
335
  }
15.1.1 by Björn Påhlsson
Added debugg support in form off --debug and --debug=mandosclient
336
337
  if(debug){
338
    fprintf(stderr, "Binding to interface %s\n", interface);
339
  }
340
341
  ret = setsockopt(tcp_sd, SOL_SOCKET, SO_BINDTODEVICE, interface, 5);
13 by Björn Påhlsson
Added following support:
342
  if(tcp_sd < 0) {
343
    perror("setsockopt bindtodevice");
344
    return -1;
345
  }
346
  
347
  memset(&to,0,sizeof(to));
348
  to.sin6_family = AF_INET6;
349
  ret = inet_pton(AF_INET6, ip, &ip_addr);
350
  if (ret < 0 ){
351
    perror("inet_pton");
352
    return -1;
353
  }  
354
  if(ret == 0){
355
    fprintf(stderr, "Bad address: %s\n", ip);
356
    return -1;
357
  }
358
  to.sin6_port = htons(port);
15.1.1 by Björn Påhlsson
Added debugg support in form off --debug and --debug=mandosclient
359
  to.sin6_scope_id = if_nametoindex(interface);
360
361
  if(debug){
362
    fprintf(stderr, "Connection to: %s\n", ip);
363
  }
13 by Björn Påhlsson
Added following support:
364
  
365
  ret = connect(tcp_sd, (struct sockaddr *) &to, sizeof(to));
366
  if (ret < 0){
367
    perror("connect");
368
    return -1;
369
  }
370
  
371
  ret = initgnutls (&es);
372
  if (ret != 0){
373
    retval = -1;
374
    return -1;
375
  }
376
    
377
  
378
  gnutls_transport_set_ptr (es.session, (gnutls_transport_ptr_t) tcp_sd);
379
15.1.1 by Björn Påhlsson
Added debugg support in form off --debug and --debug=mandosclient
380
  if(debug){
381
    fprintf(stderr, "Establishing tls session with %s\n", ip);
382
  }
383
384
  
13 by Björn Påhlsson
Added following support:
385
  ret = gnutls_handshake (es.session);
386
  
387
  if (ret != GNUTLS_E_SUCCESS){
388
    fprintf(stderr, "\n*** Handshake failed ***\n");
389
    gnutls_perror (ret);
390
    retval = -1;
391
    goto exit;
392
  }
393
15.1.1 by Björn Påhlsson
Added debugg support in form off --debug and --debug=mandosclient
394
  //Retrieve gpg packet that contains the wanted password
395
396
  if(debug){
397
    fprintf(stderr, "Retrieving pgp encrypted password from %s\n", ip);
398
  }
399
13 by Björn Påhlsson
Added following support:
400
  while(true){
401
    if (buffer_length + BUFFER_SIZE > buffer_capacity){
402
      buffer = realloc(buffer, buffer_capacity + BUFFER_SIZE);
403
      if (buffer == NULL){
404
	perror("realloc");
405
	goto exit;
406
      }
407
      buffer_capacity += BUFFER_SIZE;
408
    }
409
    
410
    ret = gnutls_record_recv
411
      (es.session, buffer+buffer_length, BUFFER_SIZE);
412
    if (ret == 0){
413
      break;
414
    }
415
    if (ret < 0){
416
      switch(ret){
417
      case GNUTLS_E_INTERRUPTED:
418
      case GNUTLS_E_AGAIN:
419
	break;
420
      case GNUTLS_E_REHANDSHAKE:
421
	ret = gnutls_handshake (es.session);
422
	if (ret < 0){
423
	  fprintf(stderr, "\n*** Handshake failed ***\n");
424
	  gnutls_perror (ret);
425
	  retval = -1;
426
	  goto exit;
427
	}
428
	break;
429
      default:
430
	fprintf(stderr, "Unknown error while reading data from encrypted session with mandos server\n");
431
	retval = -1;
432
	gnutls_bye (es.session, GNUTLS_SHUT_RDWR);
433
	goto exit;
434
      }
435
    } else {
436
      buffer_length += ret;
437
    }
438
  }
15.1.1 by Björn Påhlsson
Added debugg support in form off --debug and --debug=mandosclient
439
  
13 by Björn Påhlsson
Added following support:
440
  if (buffer_length > 0){
15.1.1 by Björn Påhlsson
Added debugg support in form off --debug and --debug=mandosclient
441
    if ((decrypted_buffer_size = gpg_packet_decrypt(buffer, buffer_length, &decrypted_buffer, CERT_ROOT)) >= 0){
13 by Björn Påhlsson
Added following support:
442
      fwrite (decrypted_buffer, 1, decrypted_buffer_size, stdout);
443
      free(decrypted_buffer);
15.1.1 by Björn Påhlsson
Added debugg support in form off --debug and --debug=mandosclient
444
    } else {
445
      retval = -1;
13 by Björn Påhlsson
Added following support:
446
    }
447
  }
448
15.1.1 by Björn Påhlsson
Added debugg support in form off --debug and --debug=mandosclient
449
  //shutdown procedure
450
451
  if(debug){
452
    fprintf(stderr, "Closing tls session\n");
453
  }
454
13 by Björn Påhlsson
Added following support:
455
  free(buffer);
456
  gnutls_bye (es.session, GNUTLS_SHUT_RDWR);
457
 exit:
458
  close(tcp_sd);
459
  gnutls_deinit (es.session);
460
  gnutls_certificate_free_credentials (es.cred);
461
  gnutls_global_deinit ();
462
  return retval;
463
}
464
465
static AvahiSimplePoll *simple_poll = NULL;
466
static AvahiServer *server = NULL;
467
468
static void resolve_callback(
469
    AvahiSServiceResolver *r,
470
    AVAHI_GCC_UNUSED AvahiIfIndex interface,
471
    AVAHI_GCC_UNUSED AvahiProtocol protocol,
472
    AvahiResolverEvent event,
473
    const char *name,
474
    const char *type,
475
    const char *domain,
476
    const char *host_name,
477
    const AvahiAddress *address,
478
    uint16_t port,
479
    AvahiStringList *txt,
480
    AvahiLookupResultFlags flags,
481
    AVAHI_GCC_UNUSED void* userdata) {
482
    
483
    assert(r);
484
485
    /* Called whenever a service has been resolved successfully or timed out */
486
487
    switch (event) {
488
        case AVAHI_RESOLVER_FAILURE:
489
            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)));
490
            break;
491
492
        case AVAHI_RESOLVER_FOUND: {
493
	  char ip[AVAHI_ADDRESS_STR_MAX];
494
            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
495
	    if(debug){
496
	      fprintf(stderr, "Mandos server found at %s on port %d\n", ip, port);
497
	    }
13 by Björn Påhlsson
Added following support:
498
	    int ret = start_mandos_communcation(ip, port);
499
	    if (ret == 0){
500
	      exit(EXIT_SUCCESS);
501
	    } else {
502
	      exit(EXIT_FAILURE);
503
	    }
504
        }
505
    }
506
    avahi_s_service_resolver_free(r);
507
}
508
509
static void browse_callback(
510
    AvahiSServiceBrowser *b,
511
    AvahiIfIndex interface,
512
    AvahiProtocol protocol,
513
    AvahiBrowserEvent event,
514
    const char *name,
515
    const char *type,
516
    const char *domain,
517
    AVAHI_GCC_UNUSED AvahiLookupResultFlags flags,
518
    void* userdata) {
519
    
520
    AvahiServer *s = userdata;
521
    assert(b);
522
523
    /* Called whenever a new services becomes available on the LAN or is removed from the LAN */
524
525
    switch (event) {
526
527
        case AVAHI_BROWSER_FAILURE:
528
            
529
            fprintf(stderr, "(Browser) %s\n", avahi_strerror(avahi_server_errno(server)));
530
            avahi_simple_poll_quit(simple_poll);
531
            return;
532
533
        case AVAHI_BROWSER_NEW:
534
            /* We ignore the returned resolver object. In the callback
535
               function we free it. If the server is terminated before
536
               the callback function is called the server will free
537
               the resolver for us. */
538
            
539
            if (!(avahi_s_service_resolver_new(s, interface, protocol, name, type, domain, AVAHI_PROTO_INET6, 0, resolve_callback, s)))
540
                fprintf(stderr, "Failed to resolve service '%s': %s\n", name, avahi_strerror(avahi_server_errno(s)));
541
            
542
            break;
543
544
        case AVAHI_BROWSER_REMOVE:
545
            break;
546
547
        case AVAHI_BROWSER_ALL_FOR_NOW:
548
        case AVAHI_BROWSER_CACHE_EXHAUSTED:
549
            break;
550
    }
551
}
552
553
int main(AVAHI_GCC_UNUSED int argc, AVAHI_GCC_UNUSED char*argv[]) {
554
    AvahiServerConfig config;
555
    AvahiSServiceBrowser *sb = NULL;
15.1.1 by Björn Påhlsson
Added debugg support in form off --debug and --debug=mandosclient
556
    const char db[] = "--debug";
13 by Björn Påhlsson
Added following support:
557
    int error;
558
    int ret = 1;
15.1.1 by Björn Påhlsson
Added debugg support in form off --debug and --debug=mandosclient
559
    int returncode = EXIT_SUCCESS;
560
    char *basename = rindex(argv[0], '/');
561
    if(basename == NULL){
562
      basename = argv[0];
563
    } else {
564
      basename++;
565
    }
566
    
567
    char *program_name = malloc(strlen(basename) + sizeof(db));
568
569
    if (program_name == NULL){
570
      perror("argv[0]");
571
      return EXIT_FAILURE;
572
    }
573
    
574
    program_name[0] = '\0';
575
    
576
    for (int i = 1; i < argc; i++){
577
      if (not strncmp(argv[i], db, 5)){
578
	  strcat(strcat(strcat(program_name, db ), "="), basename);
579
	  if(not strcmp(argv[i], db) or not strcmp(argv[i], program_name)){
580
	    debug = true;
581
	  }
582
	}
583
    }
584
    free(program_name);
585
586
    if (not debug){
587
      avahi_set_log_function(empty_log);
588
    }
13 by Björn Påhlsson
Added following support:
589
    
590
    /* Initialize the psuedo-RNG */
591
    srand(time(NULL));
592
593
    /* Allocate main loop object */
594
    if (!(simple_poll = avahi_simple_poll_new())) {
595
        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
596
	
597
        goto exit;
13 by Björn Påhlsson
Added following support:
598
    }
599
600
    /* Do not publish any local records */
601
    avahi_server_config_init(&config);
602
    config.publish_hinfo = 0;
603
    config.publish_addresses = 0;
604
    config.publish_workstation = 0;
605
    config.publish_domain = 0;
606
607
    /* Allocate a new server */
608
    server = avahi_server_new(avahi_simple_poll_get(simple_poll), &config, NULL, NULL, &error);
609
610
    /* Free the configuration data */
611
    avahi_server_config_free(&config);
612
15.1.1 by Björn Påhlsson
Added debugg support in form off --debug and --debug=mandosclient
613
    /* Check if creating the server object succeeded */
13 by Björn Påhlsson
Added following support:
614
    if (!server) {
615
        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
616
	returncode = EXIT_FAILURE;
617
        goto exit;
13 by Björn Påhlsson
Added following support:
618
    }
619
    
620
    /* Create the service browser */
621
    if (!(sb = avahi_s_service_browser_new(server, if_nametoindex("eth0"), AVAHI_PROTO_INET6, "_mandos._tcp", NULL, 0, browse_callback, server))) {
622
        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
623
	returncode = EXIT_FAILURE;
624
        goto exit;
13 by Björn Påhlsson
Added following support:
625
    }
626
    
627
    /* Run the main loop */
15.1.1 by Björn Påhlsson
Added debugg support in form off --debug and --debug=mandosclient
628
629
    if (debug){
630
      fprintf(stderr, "Starting avahi loop search\n");
631
    }
632
    
13 by Björn Påhlsson
Added following support:
633
    avahi_simple_poll_loop(simple_poll);
634
    
15.1.1 by Björn Påhlsson
Added debugg support in form off --debug and --debug=mandosclient
635
exit:
636
637
    if (debug){
638
      fprintf(stderr, "%s exiting\n", argv[0]);
639
    }
13 by Björn Påhlsson
Added following support:
640
    
641
    /* Cleanup things */
642
    if (sb)
643
        avahi_s_service_browser_free(sb);
644
    
645
    if (server)
646
        avahi_server_free(server);
647
648
    if (simple_poll)
649
        avahi_simple_poll_free(simple_poll);
650
651
    return ret;
652
}