/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 02:33:00 UTC
  • Revision ID: teddy@fukt.bsnet.se-20080721023300-c4t0cq7sxit973py
* plugins.d/Makefile: Removed

* plugins.d/mandosclient.c (start_mandos_communcation): Bug fix: write
                                                        server IP
                                                        address to
                                                        "to" struct.

Show diffs side-by-side

added added

removed removed

Lines of Context:
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
 
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
***/
33
19
 
34
20
#define _LARGEFILE_SOURCE
35
21
#define _FILE_OFFSET_BITS 64
48
34
#include <avahi-common/error.h>
49
35
 
50
36
//mandos client part
51
 
#include <sys/types.h>          /* socket(), inet_pton() */
52
 
#include <sys/socket.h>         /* socket(), struct sockaddr_in6,
53
 
                                   struct in6_addr, inet_pton() */
54
 
#include <gnutls/gnutls.h>      /* All GnuTLS stuff */
55
 
#include <gnutls/openpgp.h>     /* GnuTLS with openpgp stuff */
 
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 */
56
41
 
57
42
#include <unistd.h>             /* close() */
58
43
#include <netinet/in.h>
65
50
#include <errno.h>              /* perror() */
66
51
#include <gpgme.h>
67
52
 
68
 
// getopt long
69
 
#include <getopt.h>
70
53
 
71
54
#ifndef CERT_ROOT
72
55
#define CERT_ROOT "/conf/conf.d/cryptkeyreq/"
85
68
} encrypted_session;
86
69
 
87
70
 
88
 
ssize_t pgp_packet_decrypt (char *packet, size_t packet_size,
89
 
                            char **new_packet, const char *homedir){
 
71
ssize_t gpg_packet_decrypt (char *packet, size_t packet_size, char **new_packet, char *homedir){
90
72
  gpgme_data_t dh_crypto, dh_plain;
91
73
  gpgme_ctx_t ctx;
92
74
  gpgme_error_t rc;
93
75
  ssize_t ret;
94
 
  ssize_t new_packet_capacity = 0;
95
 
  ssize_t new_packet_length = 0;
 
76
  size_t new_packet_capacity = 0;
 
77
  size_t new_packet_length = 0;
96
78
  gpgme_engine_info_t engine_info;
97
79
 
98
80
  if (debug){
99
 
    fprintf(stderr, "Trying to decrypt OpenPGP packet\n");
 
81
    fprintf(stderr, "Attempting to decrypt password from gpg packet\n");
100
82
  }
101
83
  
102
84
  /* Init GPGME */
147
129
    return -1;
148
130
  }
149
131
  
150
 
  /* Decrypt data from the FILE pointer to the plaintext data
151
 
     buffer */
 
132
  /* Decrypt data from the FILE pointer to the plaintext data buffer */
152
133
  rc = gpgme_op_decrypt(ctx, dh_crypto, dh_plain);
153
134
  if (rc != GPG_ERR_NO_ERROR){
154
135
    fprintf(stderr, "bad gpgme_op_decrypt: %s: %s\n",
157
138
  }
158
139
 
159
140
  if(debug){
160
 
    fprintf(stderr, "Decryption of OpenPGP packet succeeded\n");
 
141
    fprintf(stderr, "decryption of gpg packet succeeded\n");
161
142
  }
162
143
 
163
144
  if (debug){
166
147
    if (result == NULL){
167
148
      fprintf(stderr, "gpgme_op_decrypt_result failed\n");
168
149
    } else {
169
 
      fprintf(stderr, "Unsupported algorithm: %s\n",
170
 
              result->unsupported_algorithm);
171
 
      fprintf(stderr, "Wrong key usage: %d\n",
172
 
              result->wrong_key_usage);
 
150
      fprintf(stderr, "Unsupported algorithm: %s\n", result->unsupported_algorithm);
 
151
      fprintf(stderr, "Wrong key usage: %d\n", result->wrong_key_usage);
173
152
      if(result->file_name != NULL){
174
153
        fprintf(stderr, "File name: %s\n", result->file_name);
175
154
      }
181
160
                  gpgme_pubkey_algo_name(recipient->pubkey_algo));
182
161
          fprintf(stderr, "Key ID: %s\n", recipient->keyid);
183
162
          fprintf(stderr, "Secret key available: %s\n",
184
 
                  recipient->status == GPG_ERR_NO_SECKEY
185
 
                  ? "No" : "Yes");
 
163
                  recipient->status == GPG_ERR_NO_SECKEY ? "No" : "Yes");
186
164
          recipient = recipient->next;
187
165
        }
188
166
      }
193
171
  gpgme_data_release(dh_crypto);
194
172
  
195
173
  /* Seek back to the beginning of the GPGME plaintext data buffer */
196
 
  gpgme_data_seek(dh_plain, (off_t) 0, SEEK_SET);
 
174
  gpgme_data_seek(dh_plain, 0, SEEK_SET);
197
175
 
198
176
  *new_packet = 0;
199
177
  while(true){
200
178
    if (new_packet_length + BUFFER_SIZE > new_packet_capacity){
201
 
      *new_packet = realloc(*new_packet,
202
 
                            (unsigned int)new_packet_capacity
203
 
                            + BUFFER_SIZE);
 
179
      *new_packet = realloc(*new_packet, new_packet_capacity + BUFFER_SIZE);
204
180
      if (*new_packet == NULL){
205
181
        perror("realloc");
206
182
        return -1;
208
184
      new_packet_capacity += BUFFER_SIZE;
209
185
    }
210
186
    
211
 
    ret = gpgme_data_read(dh_plain, *new_packet + new_packet_length,
212
 
                          BUFFER_SIZE);
 
187
    ret = gpgme_data_read(dh_plain, *new_packet + new_packet_length, BUFFER_SIZE);
213
188
    /* Print the data, if any */
214
189
    if (ret == 0){
 
190
      /* If password is empty, then a incorrect error will be printed */
215
191
      break;
216
192
    }
217
193
    if(ret < 0){
221
197
    new_packet_length += ret;
222
198
  }
223
199
 
224
 
  /* FIXME: check characters before printing to screen so to not print
225
 
     terminal control characters */
226
 
  /*   if(debug){ */
227
 
  /*     fprintf(stderr, "decrypted password is: "); */
228
 
  /*     fwrite(*new_packet, 1, new_packet_length, stderr); */
229
 
  /*     fprintf(stderr, "\n"); */
230
 
  /*   } */
231
 
  
232
 
  /* Delete the GPGME plaintext data buffer */
 
200
  if(debug){
 
201
    fprintf(stderr, "decrypted password is: %s\n", *new_packet);
 
202
  }
 
203
 
 
204
   /* Delete the GPGME plaintext data buffer */
233
205
  gpgme_data_release(dh_plain);
234
206
  return new_packet_length;
235
207
}
241
213
  return ret;
242
214
}
243
215
 
244
 
void debuggnutls(__attribute__((unused)) int level,
245
 
                 const char* string){
 
216
void debuggnutls(int level, const char* string){
246
217
  fprintf(stderr, "%s", string);
247
218
}
248
219
 
249
220
int initgnutls(encrypted_session *es){
250
221
  const char *err;
251
222
  int ret;
252
 
  
 
223
 
253
224
  if(debug){
254
 
    fprintf(stderr, "Initializing GnuTLS\n");
 
225
    fprintf(stderr, "Initializing gnutls\n");
255
226
  }
 
227
 
256
228
  
257
229
  if ((ret = gnutls_global_init ())
258
230
      != GNUTLS_E_SUCCESS) {
265
237
    gnutls_global_set_log_function(debuggnutls);
266
238
  }
267
239
  
 
240
 
268
241
  /* openpgp credentials */
269
242
  if ((ret = gnutls_certificate_allocate_credentials (&es->cred))
270
243
      != GNUTLS_E_SUCCESS) {
271
 
    fprintf (stderr, "memory error: %s\n",
272
 
             safer_gnutls_strerror(ret));
 
244
    fprintf (stderr, "memory error: %s\n", safer_gnutls_strerror(ret));
273
245
    return -1;
274
246
  }
275
 
  
 
247
 
276
248
  if(debug){
277
 
    fprintf(stderr, "Attempting to use OpenPGP certificate %s"
278
 
            " and keyfile %s as GnuTLS credentials\n", CERTFILE,
279
 
            KEYFILE);
 
249
    fprintf(stderr, "Attempting to use openpgp certificate %s"
 
250
            " and keyfile %s as gnutls credentials\n", CERTFILE, KEYFILE);
280
251
  }
281
 
  
 
252
 
282
253
  ret = gnutls_certificate_set_openpgp_key_file
283
254
    (es->cred, CERTFILE, KEYFILE, GNUTLS_OPENPGP_FMT_BASE64);
284
255
  if (ret != GNUTLS_E_SUCCESS) {
285
256
    fprintf
286
 
      (stderr, "Error[%d] while reading the OpenPGP key pair ('%s',"
287
 
       " '%s')\n",
 
257
      (stderr, "Error[%d] while reading the OpenPGP key pair ('%s', '%s')\n",
288
258
       ret, CERTFILE, KEYFILE);
289
259
    fprintf(stdout, "The Error is: %s\n",
290
260
            safer_gnutls_strerror(ret));
291
261
    return -1;
292
262
  }
293
 
  
294
 
  //GnuTLS server initialization
 
263
 
 
264
  //Gnutls server initialization
295
265
  if ((ret = gnutls_dh_params_init (&es->dh_params))
296
266
      != GNUTLS_E_SUCCESS) {
297
267
    fprintf (stderr, "Error in dh parameter initialization: %s\n",
298
268
             safer_gnutls_strerror(ret));
299
269
    return -1;
300
270
  }
301
 
  
 
271
 
302
272
  if ((ret = gnutls_dh_params_generate2 (es->dh_params, DH_BITS))
303
273
      != GNUTLS_E_SUCCESS) {
304
274
    fprintf (stderr, "Error in prime generation: %s\n",
305
275
             safer_gnutls_strerror(ret));
306
276
    return -1;
307
277
  }
308
 
  
 
278
 
309
279
  gnutls_certificate_set_dh_params (es->cred, es->dh_params);
310
 
  
311
 
  // GnuTLS session creation
 
280
 
 
281
  // Gnutls session creation
312
282
  if ((ret = gnutls_init (&es->session, GNUTLS_SERVER))
313
283
      != GNUTLS_E_SUCCESS){
314
 
    fprintf(stderr, "Error in GnuTLS session initialization: %s\n",
 
284
    fprintf(stderr, "Error in gnutls session initialization: %s\n",
315
285
            safer_gnutls_strerror(ret));
316
286
  }
317
 
  
 
287
 
318
288
  if ((ret = gnutls_priority_set_direct (es->session, "NORMAL", &err))
319
289
      != GNUTLS_E_SUCCESS) {
320
290
    fprintf(stderr, "Syntax error at: %s\n", err);
321
 
    fprintf(stderr, "GnuTLS error: %s\n",
 
291
    fprintf(stderr, "Gnutls error: %s\n",
322
292
            safer_gnutls_strerror(ret));
323
293
    return -1;
324
294
  }
325
 
  
 
295
 
326
296
  if ((ret = gnutls_credentials_set
327
297
       (es->session, GNUTLS_CRD_CERTIFICATE, es->cred))
328
298
      != GNUTLS_E_SUCCESS) {
330
300
            safer_gnutls_strerror(ret));
331
301
    return -1;
332
302
  }
333
 
  
 
303
 
334
304
  /* ignore client certificate if any. */
335
 
  gnutls_certificate_server_set_request (es->session,
336
 
                                         GNUTLS_CERT_IGNORE);
 
305
  gnutls_certificate_server_set_request (es->session, GNUTLS_CERT_IGNORE);
337
306
  
338
307
  gnutls_dh_set_prime_bits (es->session, DH_BITS);
339
308
  
340
309
  return 0;
341
310
}
342
311
 
343
 
void empty_log(__attribute__((unused)) AvahiLogLevel level,
344
 
               __attribute__((unused)) const char *txt){}
 
312
void empty_log(AvahiLogLevel level, const char *txt){}
345
313
 
346
 
int start_mandos_communication(const char *ip, uint16_t port,
347
 
                               unsigned int if_index){
 
314
int start_mandos_communcation(char *ip, uint16_t port){
348
315
  int ret, tcp_sd;
349
316
  struct sockaddr_in6 to;
350
317
  encrypted_session es;
353
320
  size_t buffer_length = 0;
354
321
  size_t buffer_capacity = 0;
355
322
  ssize_t decrypted_buffer_size;
356
 
  size_t written = 0;
357
323
  int retval = 0;
358
 
  char interface[IF_NAMESIZE];
359
 
  
 
324
  const char interface[] = "eth0";
 
325
 
360
326
  if(debug){
361
327
    fprintf(stderr, "Setting up a tcp connection to %s\n", ip);
362
328
  }
366
332
    perror("socket");
367
333
    return -1;
368
334
  }
369
 
  
370
 
  if(if_indextoname(if_index, interface) == NULL){
371
 
    if(debug){
372
 
      perror("if_indextoname");
373
 
    }
374
 
    return -1;
375
 
  }
376
 
  
 
335
 
377
336
  if(debug){
378
337
    fprintf(stderr, "Binding to interface %s\n", interface);
379
338
  }
 
339
 
 
340
  ret = setsockopt(tcp_sd, SOL_SOCKET, SO_BINDTODEVICE, interface, 5);
 
341
  if(tcp_sd < 0) {
 
342
    perror("setsockopt bindtodevice");
 
343
    return -1;
 
344
  }
380
345
  
381
 
  memset(&to,0,sizeof(to));     /* Spurious warning */
 
346
  memset(&to,0,sizeof(to));
382
347
  to.sin6_family = AF_INET6;
383
348
  ret = inet_pton(AF_INET6, ip, &to.sin6_addr);
384
349
  if (ret < 0 ){
389
354
    fprintf(stderr, "Bad address: %s\n", ip);
390
355
    return -1;
391
356
  }
392
 
  to.sin6_port = htons(port);   /* Spurious warning */
393
 
  
394
 
  to.sin6_scope_id = (uint32_t)if_index;
395
 
  
 
357
  to.sin6_port = htons(port);
 
358
  to.sin6_scope_id = if_nametoindex(interface);
 
359
 
396
360
  if(debug){
397
361
    fprintf(stderr, "Connection to: %s\n", ip);
398
362
  }
408
372
    retval = -1;
409
373
    return -1;
410
374
  }
411
 
  
412
 
  gnutls_transport_set_ptr (es.session,
413
 
                            (gnutls_transport_ptr_t) tcp_sd);
414
 
  
 
375
    
 
376
  
 
377
  gnutls_transport_set_ptr (es.session, (gnutls_transport_ptr_t) tcp_sd);
 
378
 
415
379
  if(debug){
416
 
    fprintf(stderr, "Establishing TLS session with %s\n", ip);
 
380
    fprintf(stderr, "Establishing tls session with %s\n", ip);
417
381
  }
 
382
 
418
383
  
419
384
  ret = gnutls_handshake (es.session);
420
385
  
424
389
    retval = -1;
425
390
    goto exit;
426
391
  }
427
 
  
428
 
  //Retrieve OpenPGP packet that contains the wanted password
429
 
  
 
392
 
 
393
  //Retrieve gpg packet that contains the wanted password
 
394
 
430
395
  if(debug){
431
 
    fprintf(stderr, "Retrieving pgp encrypted password from %s\n",
432
 
            ip);
 
396
    fprintf(stderr, "Retrieving pgp encrypted password from %s\n", ip);
433
397
  }
434
398
 
435
399
  while(true){
462
426
        }
463
427
        break;
464
428
      default:
465
 
        fprintf(stderr, "Unknown error while reading data from"
466
 
                " encrypted session with mandos server\n");
 
429
        fprintf(stderr, "Unknown error while reading data from encrypted session with mandos server\n");
467
430
        retval = -1;
468
431
        gnutls_bye (es.session, GNUTLS_SHUT_RDWR);
469
432
        goto exit;
470
433
      }
471
434
    } else {
472
 
      buffer_length += (size_t) ret;
 
435
      buffer_length += ret;
473
436
    }
474
437
  }
475
438
  
476
439
  if (buffer_length > 0){
477
 
    decrypted_buffer_size = pgp_packet_decrypt(buffer,
478
 
                                               buffer_length,
479
 
                                               &decrypted_buffer,
480
 
                                               CERT_ROOT);
481
 
    if (decrypted_buffer_size >= 0){
482
 
      while(written < decrypted_buffer_size){
483
 
        ret = (int)fwrite (decrypted_buffer + written, 1,
484
 
                           (size_t)decrypted_buffer_size - written,
485
 
                           stdout);
486
 
        if(ret == 0 and ferror(stdout)){
487
 
          if(debug){
488
 
            fprintf(stderr, "Error writing encrypted data: %s\n",
489
 
                    strerror(errno));
490
 
          }
491
 
          retval = -1;
492
 
          break;
493
 
        }
494
 
        written += (size_t)ret;
495
 
      }
 
440
    if ((decrypted_buffer_size = gpg_packet_decrypt(buffer, buffer_length, &decrypted_buffer, CERT_ROOT)) >= 0){
 
441
      fwrite (decrypted_buffer, 1, decrypted_buffer_size, stdout);
496
442
      free(decrypted_buffer);
497
443
    } else {
498
444
      retval = -1;
502
448
  //shutdown procedure
503
449
 
504
450
  if(debug){
505
 
    fprintf(stderr, "Closing TLS session\n");
 
451
    fprintf(stderr, "Closing tls session\n");
506
452
  }
507
453
 
508
454
  free(buffer);
520
466
 
521
467
static void resolve_callback(
522
468
    AvahiSServiceResolver *r,
523
 
    AvahiIfIndex interface,
 
469
    AVAHI_GCC_UNUSED AvahiIfIndex interface,
524
470
    AVAHI_GCC_UNUSED AvahiProtocol protocol,
525
471
    AvahiResolverEvent event,
526
472
    const char *name,
529
475
    const char *host_name,
530
476
    const AvahiAddress *address,
531
477
    uint16_t port,
532
 
    AVAHI_GCC_UNUSED AvahiStringList *txt,
533
 
    AVAHI_GCC_UNUSED AvahiLookupResultFlags flags,
 
478
    AvahiStringList *txt,
 
479
    AvahiLookupResultFlags flags,
534
480
    AVAHI_GCC_UNUSED void* userdata) {
535
481
    
536
 
  assert(r);                    /* Spurious warning */
537
 
  
538
 
  /* Called whenever a service has been resolved successfully or
539
 
     timed out */
540
 
  
541
 
  switch (event) {
542
 
  default:
543
 
  case AVAHI_RESOLVER_FAILURE:
544
 
    fprintf(stderr, "(Resolver) Failed to resolve service '%s' of"
545
 
            " type '%s' in domain '%s': %s\n", name, type, domain,
546
 
            avahi_strerror(avahi_server_errno(server)));
547
 
    break;
548
 
    
549
 
  case AVAHI_RESOLVER_FOUND:
550
 
    {
551
 
      char ip[AVAHI_ADDRESS_STR_MAX];
552
 
      avahi_address_snprint(ip, sizeof(ip), address);
553
 
      if(debug){
554
 
        fprintf(stderr, "Mandos server found on %s (%s) on port %d\n",
555
 
                host_name, ip, port);
556
 
      }
557
 
      int ret = start_mandos_communication(ip, port,
558
 
                                           (unsigned int) interface);
559
 
      if (ret == 0){
560
 
        exit(EXIT_SUCCESS);
561
 
      } else {
562
 
        exit(EXIT_FAILURE);
563
 
      }
 
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);
 
494
            if(debug){
 
495
              fprintf(stderr, "Mandos server found at %s on port %d\n", ip, port);
 
496
            }
 
497
            int ret = start_mandos_communcation(ip, port);
 
498
            if (ret == 0){
 
499
              exit(EXIT_SUCCESS);
 
500
            } else {
 
501
              exit(EXIT_FAILURE);
 
502
            }
 
503
        }
564
504
    }
565
 
  }
566
 
  avahi_s_service_resolver_free(r);
 
505
    avahi_s_service_resolver_free(r);
567
506
}
568
507
 
569
508
static void browse_callback(
578
517
    void* userdata) {
579
518
    
580
519
    AvahiServer *s = userdata;
581
 
    assert(b);                  /* Spurious warning */
582
 
    
583
 
    /* Called whenever a new services becomes available on the LAN or
584
 
       is removed from the LAN */
585
 
    
 
520
    assert(b);
 
521
 
 
522
    /* Called whenever a new services becomes available on the LAN or is removed from the LAN */
 
523
 
586
524
    switch (event) {
587
 
    default:
588
 
    case AVAHI_BROWSER_FAILURE:
589
 
      
590
 
      fprintf(stderr, "(Browser) %s\n",
591
 
              avahi_strerror(avahi_server_errno(server)));
592
 
      avahi_simple_poll_quit(simple_poll);
593
 
      return;
594
 
      
595
 
    case AVAHI_BROWSER_NEW:
596
 
      /* We ignore the returned resolver object. In the callback
597
 
         function we free it. If the server is terminated before
598
 
         the callback function is called the server will free
599
 
         the resolver for us. */
600
 
      
601
 
      if (!(avahi_s_service_resolver_new(s, interface, protocol, name,
602
 
                                         type, domain,
603
 
                                         AVAHI_PROTO_INET6, 0,
604
 
                                         resolve_callback, s)))
605
 
        fprintf(stderr, "Failed to resolve service '%s': %s\n", name,
606
 
                avahi_strerror(avahi_server_errno(s)));
607
 
      break;
608
 
      
609
 
    case AVAHI_BROWSER_REMOVE:
610
 
      break;
611
 
      
612
 
    case AVAHI_BROWSER_ALL_FOR_NOW:
613
 
    case AVAHI_BROWSER_CACHE_EXHAUSTED:
614
 
      break;
 
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;
615
549
    }
616
550
}
617
551
 
618
552
int main(AVAHI_GCC_UNUSED int argc, AVAHI_GCC_UNUSED char*argv[]) {
619
553
    AvahiServerConfig config;
620
554
    AvahiSServiceBrowser *sb = NULL;
 
555
    const char db[] = "--debug";
621
556
    int error;
622
 
    int ret;
 
557
    int ret = 1;
623
558
    int returncode = EXIT_SUCCESS;
624
 
    const char *interface = "eth0";
625
 
    
626
 
    while (true){
627
 
      static struct option long_options[] = {
628
 
        {"debug", no_argument, (int *)&debug, 1},
629
 
        {"interface", required_argument, 0, 'i'},
630
 
        {0, 0, 0, 0} };
631
 
      
632
 
      int option_index = 0;
633
 
      ret = getopt_long (argc, argv, "i:", long_options,
634
 
                         &option_index);
635
 
      
636
 
      if (ret == -1){
637
 
        break;
638
 
      }
639
 
      
640
 
      switch(ret){
641
 
      case 0:
642
 
        break;
643
 
      case 'i':
644
 
        interface = optarg;
645
 
        break;
646
 
      default:
647
 
        exit(EXIT_FAILURE);
648
 
      }
649
 
    }
650
 
    
 
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
 
651
585
    if (not debug){
652
586
      avahi_set_log_function(empty_log);
653
587
    }
654
588
    
655
589
    /* Initialize the psuedo-RNG */
656
 
    srand((unsigned int) time(NULL));
 
590
    srand(time(NULL));
657
591
 
658
592
    /* Allocate main loop object */
659
593
    if (!(simple_poll = avahi_simple_poll_new())) {
670
604
    config.publish_domain = 0;
671
605
 
672
606
    /* Allocate a new server */
673
 
    server = avahi_server_new(avahi_simple_poll_get(simple_poll),
674
 
                              &config, NULL, NULL, &error);
 
607
    server = avahi_server_new(avahi_simple_poll_get(simple_poll), &config, NULL, NULL, &error);
675
608
 
676
609
    /* Free the configuration data */
677
610
    avahi_server_config_free(&config);
678
611
 
679
612
    /* Check if creating the server object succeeded */
680
613
    if (!server) {
681
 
        fprintf(stderr, "Failed to create server: %s\n",
682
 
                avahi_strerror(error));
 
614
        fprintf(stderr, "Failed to create server: %s\n", avahi_strerror(error));
683
615
        returncode = EXIT_FAILURE;
684
616
        goto exit;
685
617
    }
686
618
    
687
619
    /* Create the service browser */
688
 
    sb = avahi_s_service_browser_new(server,
689
 
                                     (AvahiIfIndex)
690
 
                                     if_nametoindex(interface),
691
 
                                     AVAHI_PROTO_INET6,
692
 
                                     "_mandos._tcp", NULL, 0,
693
 
                                     browse_callback, server);
694
 
    if (!sb) {
695
 
        fprintf(stderr, "Failed to create service browser: %s\n",
696
 
                avahi_strerror(avahi_server_errno(server)));
 
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)));
697
622
        returncode = EXIT_FAILURE;
698
623
        goto exit;
699
624
    }
706
631
    
707
632
    avahi_simple_poll_loop(simple_poll);
708
633
    
709
 
 exit:
 
634
exit:
710
635
 
711
636
    if (debug){
712
637
      fprintf(stderr, "%s exiting\n", argv[0]);
722
647
    if (simple_poll)
723
648
        avahi_simple_poll_free(simple_poll);
724
649
 
725
 
    return returncode;
 
650
    return ret;
726
651
}