/mandos/release

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

« back to all changes in this revision

Viewing changes to plugins.d/mandosclient.c

  • Committer: Teddy Hogeborn
  • Date: 2008-07-21 15:34:44 UTC
  • Revision ID: teddy@fukt.bsnet.se-20080721153444-lugbjkj1oq65ugq3
* Makefile (CFLAGS): Changed to use $(WARN), $(DEBUG), $(COVERAGE) and
                     $(LANGUAGE).
  (WARN, DEBUG, COVERAGE, LANGUAGE): New.
  (LDFLAGS): New; use $(COVERAGE)

* plugbasedclient.c: Added copyright header.
  (process.buffer_size, process.buffer_length): Changed to "size_t".
  (main): Cast arguments to malloc and realloc.  Detect read errors
          from processes.

* mandosclient.c: Added copyright header.
  (interface): Moved to inside "main".
  (gpg_packet_decrypt): Renamed to "pgp_packet_decrypt"; all callers
                        changed.  Changed "new_packet_capacity" and
                        "new_packet_length" to be ssize_t.  Cast
                        arguments to realloc.
  (debuggnutls): Attribute "level" argument as unused.
  (empty_log): Attribute "level" and "txt" arguments as unused.
  (start_mandos_communication): New argument "if_index".  Bug fix:
                                check ret, no tcp_sd, for errors from
                                setsockopt.  Use "if_index" directly
                                instead of looking up the index.  Loop
                                around fwrite until all data is written.
  (resolve_callback): Attribute "txt", and "flags" as usused.  Added
                      default case to switch.  Also show server host
                      name.  Call start_mandos_communication with
                      "interface".
  (browse_callback): Added default case to switch.
  (main): Variable "interface" moved here.  Cast "srand" argument.
          Bug fix: Call avahi_s_service_browser_new with index of
          "interface", not "eth0".

* passprompt.c: Added copyright header.
  (termination_handler): Attribute "signum" argument as unused.

Show diffs side-by-side

added added

removed removed

Lines of Context:
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
 
***/
 
1
/*  -*- coding: utf-8 -*- */
 
2
/*
 
3
 * Mandos client - get and decrypt data from a Mandos server
 
4
 *
 
5
 * This program is partly derived from an example program for an Avahi
 
6
 * service browser, downloaded from
 
7
 * <http://avahi.org/browser/examples/core-browse-services.c>.  This
 
8
 * includes the following functions: "resolve_callback",
 
9
 * "browse_callback", and parts of "main".
 
10
 * 
 
11
 * Everything else is Copyright © 2007-2008 Teddy Hogeborn and Björn
 
12
 * Påhlsson.
 
13
 * 
 
14
 * This program is free software: you can redistribute it and/or
 
15
 * modify it under the terms of the GNU General Public License as
 
16
 * published by the Free Software Foundation, either version 3 of the
 
17
 * License, or (at your option) any later version.
 
18
 * 
 
19
 * This program is distributed in the hope that it will be useful, but
 
20
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 
21
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
22
 * General Public License for more details.
 
23
 * 
 
24
 * You should have received a copy of the GNU General Public License
 
25
 * along with this program.  If not, see
 
26
 * <http://www.gnu.org/licenses/>.
 
27
 * 
 
28
 * Contact the authors at <https://www.fukt.bsnet.se/~belorn/> and
 
29
 * <https://www.fukt.bsnet.se/~teddy/>.
 
30
 */
 
31
 
 
32
#define _FORTIFY_SOURCE 2
19
33
 
20
34
#define _LARGEFILE_SOURCE
21
35
#define _FILE_OFFSET_BITS 64
34
48
#include <avahi-common/error.h>
35
49
 
36
50
//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 */
 
51
#include <sys/types.h>          /* socket(), setsockopt(),
 
52
                                   inet_pton() */
 
53
#include <sys/socket.h>         /* socket(), setsockopt(),
 
54
                                   struct sockaddr_in6,
 
55
                                   struct in6_addr, inet_pton() */
 
56
#include <gnutls/gnutls.h>      /* All GnuTLS stuff */
 
57
#include <gnutls/openpgp.h>     /* GnuTLS with openpgp stuff */
41
58
 
42
59
#include <unistd.h>             /* close() */
43
60
#include <netinet/in.h>
62
79
#define DH_BITS 1024
63
80
 
64
81
bool debug = false;
65
 
char *interface = "eth0";
66
82
 
67
83
typedef struct {
68
84
  gnutls_session_t session;
71
87
} encrypted_session;
72
88
 
73
89
 
74
 
ssize_t gpg_packet_decrypt (char *packet, size_t packet_size, char **new_packet, char *homedir){
 
90
ssize_t pgp_packet_decrypt (char *packet, size_t packet_size,
 
91
                            char **new_packet, const char *homedir){
75
92
  gpgme_data_t dh_crypto, dh_plain;
76
93
  gpgme_ctx_t ctx;
77
94
  gpgme_error_t rc;
78
95
  ssize_t ret;
79
 
  size_t new_packet_capacity = 0;
80
 
  size_t new_packet_length = 0;
 
96
  ssize_t new_packet_capacity = 0;
 
97
  ssize_t new_packet_length = 0;
81
98
  gpgme_engine_info_t engine_info;
82
99
 
83
100
  if (debug){
84
 
    fprintf(stderr, "Attempting to decrypt password from gpg packet\n");
 
101
    fprintf(stderr, "Trying to decrypt OpenPGP packet\n");
85
102
  }
86
103
  
87
104
  /* Init GPGME */
132
149
    return -1;
133
150
  }
134
151
  
135
 
  /* Decrypt data from the FILE pointer to the plaintext data buffer */
 
152
  /* Decrypt data from the FILE pointer to the plaintext data
 
153
     buffer */
136
154
  rc = gpgme_op_decrypt(ctx, dh_crypto, dh_plain);
137
155
  if (rc != GPG_ERR_NO_ERROR){
138
156
    fprintf(stderr, "bad gpgme_op_decrypt: %s: %s\n",
141
159
  }
142
160
 
143
161
  if(debug){
144
 
    fprintf(stderr, "decryption of gpg packet succeeded\n");
 
162
    fprintf(stderr, "Decryption of OpenPGP packet succeeded\n");
145
163
  }
146
164
 
147
165
  if (debug){
150
168
    if (result == NULL){
151
169
      fprintf(stderr, "gpgme_op_decrypt_result failed\n");
152
170
    } else {
153
 
      fprintf(stderr, "Unsupported algorithm: %s\n", result->unsupported_algorithm);
154
 
      fprintf(stderr, "Wrong key usage: %d\n", result->wrong_key_usage);
 
171
      fprintf(stderr, "Unsupported algorithm: %s\n",
 
172
              result->unsupported_algorithm);
 
173
      fprintf(stderr, "Wrong key usage: %d\n",
 
174
              result->wrong_key_usage);
155
175
      if(result->file_name != NULL){
156
176
        fprintf(stderr, "File name: %s\n", result->file_name);
157
177
      }
163
183
                  gpgme_pubkey_algo_name(recipient->pubkey_algo));
164
184
          fprintf(stderr, "Key ID: %s\n", recipient->keyid);
165
185
          fprintf(stderr, "Secret key available: %s\n",
166
 
                  recipient->status == GPG_ERR_NO_SECKEY ? "No" : "Yes");
 
186
                  recipient->status == GPG_ERR_NO_SECKEY
 
187
                  ? "No" : "Yes");
167
188
          recipient = recipient->next;
168
189
        }
169
190
      }
179
200
  *new_packet = 0;
180
201
  while(true){
181
202
    if (new_packet_length + BUFFER_SIZE > new_packet_capacity){
182
 
      *new_packet = realloc(*new_packet, new_packet_capacity + BUFFER_SIZE);
 
203
      *new_packet = realloc(*new_packet,
 
204
                            (unsigned int)new_packet_capacity
 
205
                            + BUFFER_SIZE);
183
206
      if (*new_packet == NULL){
184
207
        perror("realloc");
185
208
        return -1;
187
210
      new_packet_capacity += BUFFER_SIZE;
188
211
    }
189
212
    
190
 
    ret = gpgme_data_read(dh_plain, *new_packet + new_packet_length, BUFFER_SIZE);
 
213
    ret = gpgme_data_read(dh_plain, *new_packet + new_packet_length,
 
214
                          BUFFER_SIZE);
191
215
    /* Print the data, if any */
192
216
    if (ret == 0){
193
 
      /* If password is empty, then a incorrect error will be printed */
194
217
      break;
195
218
    }
196
219
    if(ret < 0){
220
243
  return ret;
221
244
}
222
245
 
223
 
void debuggnutls(int level, const char* string){
 
246
void debuggnutls(__attribute__((unused)) int level,
 
247
                 const char* string){
224
248
  fprintf(stderr, "%s", string);
225
249
}
226
250
 
227
251
int initgnutls(encrypted_session *es){
228
252
  const char *err;
229
253
  int ret;
230
 
 
 
254
  
231
255
  if(debug){
232
 
    fprintf(stderr, "Initializing gnutls\n");
 
256
    fprintf(stderr, "Initializing GnuTLS\n");
233
257
  }
234
 
 
235
258
  
236
259
  if ((ret = gnutls_global_init ())
237
260
      != GNUTLS_E_SUCCESS) {
244
267
    gnutls_global_set_log_function(debuggnutls);
245
268
  }
246
269
  
247
 
 
248
270
  /* openpgp credentials */
249
271
  if ((ret = gnutls_certificate_allocate_credentials (&es->cred))
250
272
      != GNUTLS_E_SUCCESS) {
251
 
    fprintf (stderr, "memory error: %s\n", safer_gnutls_strerror(ret));
 
273
    fprintf (stderr, "memory error: %s\n",
 
274
             safer_gnutls_strerror(ret));
252
275
    return -1;
253
276
  }
254
 
 
 
277
  
255
278
  if(debug){
256
 
    fprintf(stderr, "Attempting to use openpgp certificate %s"
257
 
            " and keyfile %s as gnutls credentials\n", CERTFILE, KEYFILE);
 
279
    fprintf(stderr, "Attempting to use OpenPGP certificate %s"
 
280
            " and keyfile %s as GnuTLS credentials\n", CERTFILE,
 
281
            KEYFILE);
258
282
  }
259
 
 
 
283
  
260
284
  ret = gnutls_certificate_set_openpgp_key_file
261
285
    (es->cred, CERTFILE, KEYFILE, GNUTLS_OPENPGP_FMT_BASE64);
262
286
  if (ret != GNUTLS_E_SUCCESS) {
263
287
    fprintf
264
 
      (stderr, "Error[%d] while reading the OpenPGP key pair ('%s', '%s')\n",
 
288
      (stderr, "Error[%d] while reading the OpenPGP key pair ('%s',"
 
289
       " '%s')\n",
265
290
       ret, CERTFILE, KEYFILE);
266
291
    fprintf(stdout, "The Error is: %s\n",
267
292
            safer_gnutls_strerror(ret));
268
293
    return -1;
269
294
  }
270
 
 
271
 
  //Gnutls server initialization
 
295
  
 
296
  //GnuTLS server initialization
272
297
  if ((ret = gnutls_dh_params_init (&es->dh_params))
273
298
      != GNUTLS_E_SUCCESS) {
274
299
    fprintf (stderr, "Error in dh parameter initialization: %s\n",
275
300
             safer_gnutls_strerror(ret));
276
301
    return -1;
277
302
  }
278
 
 
 
303
  
279
304
  if ((ret = gnutls_dh_params_generate2 (es->dh_params, DH_BITS))
280
305
      != GNUTLS_E_SUCCESS) {
281
306
    fprintf (stderr, "Error in prime generation: %s\n",
282
307
             safer_gnutls_strerror(ret));
283
308
    return -1;
284
309
  }
285
 
 
 
310
  
286
311
  gnutls_certificate_set_dh_params (es->cred, es->dh_params);
287
 
 
288
 
  // Gnutls session creation
 
312
  
 
313
  // GnuTLS session creation
289
314
  if ((ret = gnutls_init (&es->session, GNUTLS_SERVER))
290
315
      != GNUTLS_E_SUCCESS){
291
 
    fprintf(stderr, "Error in gnutls session initialization: %s\n",
 
316
    fprintf(stderr, "Error in GnuTLS session initialization: %s\n",
292
317
            safer_gnutls_strerror(ret));
293
318
  }
294
 
 
 
319
  
295
320
  if ((ret = gnutls_priority_set_direct (es->session, "NORMAL", &err))
296
321
      != GNUTLS_E_SUCCESS) {
297
322
    fprintf(stderr, "Syntax error at: %s\n", err);
298
 
    fprintf(stderr, "Gnutls error: %s\n",
 
323
    fprintf(stderr, "GnuTLS error: %s\n",
299
324
            safer_gnutls_strerror(ret));
300
325
    return -1;
301
326
  }
302
 
 
 
327
  
303
328
  if ((ret = gnutls_credentials_set
304
329
       (es->session, GNUTLS_CRD_CERTIFICATE, es->cred))
305
330
      != GNUTLS_E_SUCCESS) {
307
332
            safer_gnutls_strerror(ret));
308
333
    return -1;
309
334
  }
310
 
 
 
335
  
311
336
  /* ignore client certificate if any. */
312
 
  gnutls_certificate_server_set_request (es->session, GNUTLS_CERT_IGNORE);
 
337
  gnutls_certificate_server_set_request (es->session,
 
338
                                         GNUTLS_CERT_IGNORE);
313
339
  
314
340
  gnutls_dh_set_prime_bits (es->session, DH_BITS);
315
341
  
316
342
  return 0;
317
343
}
318
344
 
319
 
void empty_log(AvahiLogLevel level, const char *txt){}
 
345
void empty_log(__attribute__((unused)) AvahiLogLevel level,
 
346
               __attribute__((unused)) const char *txt){}
320
347
 
321
 
int start_mandos_communication(char *ip, uint16_t port){
 
348
int start_mandos_communication(char *ip, uint16_t port,
 
349
                               unsigned int if_index){
322
350
  int ret, tcp_sd;
323
351
  struct sockaddr_in6 to;
324
352
  encrypted_session es;
328
356
  size_t buffer_capacity = 0;
329
357
  ssize_t decrypted_buffer_size;
330
358
  int retval = 0;
331
 
 
 
359
  char interface[IF_NAMESIZE];
 
360
  
332
361
  if(debug){
333
362
    fprintf(stderr, "Setting up a tcp connection to %s\n", ip);
334
363
  }
338
367
    perror("socket");
339
368
    return -1;
340
369
  }
341
 
 
 
370
  
 
371
  if(if_indextoname(if_index, interface) == NULL){
 
372
    if(debug){
 
373
      perror("if_indextoname");
 
374
    }
 
375
    return -1;
 
376
  }
 
377
  
342
378
  if(debug){
343
379
    fprintf(stderr, "Binding to interface %s\n", interface);
344
380
  }
345
 
 
 
381
  
346
382
  ret = setsockopt(tcp_sd, SOL_SOCKET, SO_BINDTODEVICE, interface, 5);
347
 
  if(tcp_sd < 0) {
 
383
  if(ret < 0) {
348
384
    perror("setsockopt bindtodevice");
349
385
    return -1;
350
386
  }
360
396
    fprintf(stderr, "Bad address: %s\n", ip);
361
397
    return -1;
362
398
  }
 
399
  /* Spurious warnings for the next line, see for instance
 
400
     <http://bugs.debian.org/488884> */
363
401
  to.sin6_port = htons(port);
364
 
  to.sin6_scope_id = if_nametoindex(interface);
365
 
 
 
402
  
 
403
  to.sin6_scope_id = (uint32_t)if_index;
 
404
  
366
405
  if(debug){
367
406
    fprintf(stderr, "Connection to: %s\n", ip);
368
407
  }
378
417
    retval = -1;
379
418
    return -1;
380
419
  }
381
 
    
382
 
  
383
 
  gnutls_transport_set_ptr (es.session, (gnutls_transport_ptr_t) tcp_sd);
384
 
 
 
420
  
 
421
  gnutls_transport_set_ptr (es.session,
 
422
                            (gnutls_transport_ptr_t) tcp_sd);
 
423
  
385
424
  if(debug){
386
 
    fprintf(stderr, "Establishing tls session with %s\n", ip);
 
425
    fprintf(stderr, "Establishing TLS session with %s\n", ip);
387
426
  }
388
 
 
389
427
  
390
428
  ret = gnutls_handshake (es.session);
391
429
  
395
433
    retval = -1;
396
434
    goto exit;
397
435
  }
398
 
 
399
 
  //Retrieve gpg packet that contains the wanted password
400
 
 
 
436
  
 
437
  //Retrieve OpenPGP packet that contains the wanted password
 
438
  
401
439
  if(debug){
402
 
    fprintf(stderr, "Retrieving pgp encrypted password from %s\n", ip);
 
440
    fprintf(stderr, "Retrieving pgp encrypted password from %s\n",
 
441
            ip);
403
442
  }
404
443
 
405
444
  while(true){
432
471
        }
433
472
        break;
434
473
      default:
435
 
        fprintf(stderr, "Unknown error while reading data from encrypted session with mandos server\n");
 
474
        fprintf(stderr, "Unknown error while reading data from"
 
475
                " encrypted session with mandos server\n");
436
476
        retval = -1;
437
477
        gnutls_bye (es.session, GNUTLS_SHUT_RDWR);
438
478
        goto exit;
439
479
      }
440
480
    } else {
441
 
      buffer_length += ret;
 
481
      buffer_length += (size_t) ret;
442
482
    }
443
483
  }
444
484
  
445
485
  if (buffer_length > 0){
446
 
    if ((decrypted_buffer_size = gpg_packet_decrypt(buffer, buffer_length, &decrypted_buffer, CERT_ROOT)) >= 0){
447
 
      fwrite (decrypted_buffer, 1, decrypted_buffer_size, stdout);
 
486
    decrypted_buffer_size = pgp_packet_decrypt(buffer,
 
487
                                               buffer_length,
 
488
                                               &decrypted_buffer,
 
489
                                               CERT_ROOT);
 
490
    if (decrypted_buffer_size >= 0){
 
491
      while(decrypted_buffer_size > 0){
 
492
        ret = fwrite (decrypted_buffer, 1, (size_t)decrypted_buffer_size,
 
493
                      stdout);
 
494
        if(ret == 0 and ferror(stdout)){
 
495
          if(debug){
 
496
            fprintf(stderr, "Error writing encrypted data: %s\n",
 
497
                    strerror(errno));
 
498
          }
 
499
          retval = -1;
 
500
          break;
 
501
        }
 
502
        decrypted_buffer += ret;
 
503
        decrypted_buffer_size -= ret;
 
504
      }
448
505
      free(decrypted_buffer);
449
506
    } else {
450
507
      retval = -1;
454
511
  //shutdown procedure
455
512
 
456
513
  if(debug){
457
 
    fprintf(stderr, "Closing tls session\n");
 
514
    fprintf(stderr, "Closing TLS session\n");
458
515
  }
459
516
 
460
517
  free(buffer);
481
538
    const char *host_name,
482
539
    const AvahiAddress *address,
483
540
    uint16_t port,
484
 
    AvahiStringList *txt,
485
 
    AvahiLookupResultFlags flags,
 
541
    AVAHI_GCC_UNUSED AvahiStringList *txt,
 
542
    AVAHI_GCC_UNUSED AvahiLookupResultFlags flags,
486
543
    AVAHI_GCC_UNUSED void* userdata) {
487
544
    
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);
500
 
            if(debug){
501
 
              fprintf(stderr, "Mandos server found at %s on port %d\n", ip, port);
502
 
            }
503
 
            int ret = start_mandos_communication(ip, port);
504
 
            if (ret == 0){
505
 
              exit(EXIT_SUCCESS);
506
 
            } else {
507
 
              exit(EXIT_FAILURE);
508
 
            }
509
 
        }
 
545
  assert(r);
 
546
 
 
547
  /* Called whenever a service has been resolved successfully or
 
548
     timed out */
 
549
 
 
550
  switch (event) {
 
551
  default:
 
552
  case AVAHI_RESOLVER_FAILURE:
 
553
    fprintf(stderr, "(Resolver) Failed to resolve service '%s' of"
 
554
            " type '%s' in domain '%s': %s\n", name, type, domain,
 
555
            avahi_strerror(avahi_server_errno(server)));
 
556
    break;
 
557
      
 
558
  case AVAHI_RESOLVER_FOUND:
 
559
    {
 
560
      char ip[AVAHI_ADDRESS_STR_MAX];
 
561
      avahi_address_snprint(ip, sizeof(ip), address);
 
562
      if(debug){
 
563
        fprintf(stderr, "Mandos server found on %s (%s) on port %d\n",
 
564
                host_name, ip, port);
 
565
      }
 
566
      int ret = start_mandos_communication(ip, port,
 
567
                                           (unsigned int)
 
568
                                           interface);
 
569
      if (ret == 0){
 
570
        exit(EXIT_SUCCESS);
 
571
      } else {
 
572
        exit(EXIT_FAILURE);
 
573
      }
510
574
    }
511
 
    avahi_s_service_resolver_free(r);
 
575
  }
 
576
  avahi_s_service_resolver_free(r);
512
577
}
513
578
 
514
579
static void browse_callback(
525
590
    AvahiServer *s = userdata;
526
591
    assert(b);
527
592
 
528
 
    /* Called whenever a new services becomes available on the LAN or is removed from the LAN */
 
593
    /* Called whenever a new services becomes available on the LAN or
 
594
       is removed from the LAN */
529
595
 
530
596
    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;
 
597
    default:
 
598
    case AVAHI_BROWSER_FAILURE:
 
599
      
 
600
      fprintf(stderr, "(Browser) %s\n",
 
601
              avahi_strerror(avahi_server_errno(server)));
 
602
      avahi_simple_poll_quit(simple_poll);
 
603
      return;
 
604
      
 
605
    case AVAHI_BROWSER_NEW:
 
606
      /* We ignore the returned resolver object. In the callback
 
607
         function we free it. If the server is terminated before
 
608
         the callback function is called the server will free
 
609
         the resolver for us. */
 
610
      
 
611
      if (!(avahi_s_service_resolver_new(s, interface, protocol, name,
 
612
                                         type, domain,
 
613
                                         AVAHI_PROTO_INET6, 0,
 
614
                                         resolve_callback, s)))
 
615
        fprintf(stderr, "Failed to resolve service '%s': %s\n", name,
 
616
                avahi_strerror(avahi_server_errno(s)));
 
617
      break;
 
618
      
 
619
    case AVAHI_BROWSER_REMOVE:
 
620
      break;
 
621
      
 
622
    case AVAHI_BROWSER_ALL_FOR_NOW:
 
623
    case AVAHI_BROWSER_CACHE_EXHAUSTED:
 
624
      break;
555
625
    }
556
626
}
557
627
 
561
631
    int error;
562
632
    int ret;
563
633
    int returncode = EXIT_SUCCESS;
564
 
 
 
634
    const char *interface = "eth0";
 
635
    
565
636
    while (true){
566
637
      static struct option long_options[] = {
567
638
        {"debug", no_argument, (int *)&debug, 1},
569
640
        {0, 0, 0, 0} };
570
641
 
571
642
      int option_index = 0;
572
 
      ret = getopt_long (argc, argv, "i:", long_options, &option_index);
 
643
      ret = getopt_long (argc, argv, "i:", long_options,
 
644
                         &option_index);
573
645
 
574
646
      if (ret == -1){
575
647
        break;
591
663
    }
592
664
    
593
665
    /* Initialize the psuedo-RNG */
594
 
    srand(time(NULL));
 
666
    srand((unsigned int) time(NULL));
595
667
 
596
668
    /* Allocate main loop object */
597
669
    if (!(simple_poll = avahi_simple_poll_new())) {
608
680
    config.publish_domain = 0;
609
681
 
610
682
    /* Allocate a new server */
611
 
    server = avahi_server_new(avahi_simple_poll_get(simple_poll), &config, NULL, NULL, &error);
 
683
    server = avahi_server_new(avahi_simple_poll_get(simple_poll),
 
684
                              &config, NULL, NULL, &error);
612
685
 
613
686
    /* Free the configuration data */
614
687
    avahi_server_config_free(&config);
615
688
 
616
689
    /* Check if creating the server object succeeded */
617
690
    if (!server) {
618
 
        fprintf(stderr, "Failed to create server: %s\n", avahi_strerror(error));
 
691
        fprintf(stderr, "Failed to create server: %s\n",
 
692
                avahi_strerror(error));
619
693
        returncode = EXIT_FAILURE;
620
694
        goto exit;
621
695
    }
622
696
    
623
697
    /* 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)));
 
698
    sb = avahi_s_service_browser_new(server,
 
699
                                     (AvahiIfIndex)
 
700
                                     if_nametoindex(interface),
 
701
                                     AVAHI_PROTO_INET6,
 
702
                                     "_mandos._tcp", NULL, 0,
 
703
                                     browse_callback, server);
 
704
    if (!sb) {
 
705
        fprintf(stderr, "Failed to create service browser: %s\n",
 
706
                avahi_strerror(avahi_server_errno(server)));
626
707
        returncode = EXIT_FAILURE;
627
708
        goto exit;
628
709
    }
635
716
    
636
717
    avahi_simple_poll_loop(simple_poll);
637
718
    
638
 
exit:
 
719
 exit:
639
720
 
640
721
    if (debug){
641
722
      fprintf(stderr, "%s exiting\n", argv[0]);