/mandos/trunk

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

« back to all changes in this revision

Viewing changes to plugins.d/mandosclient.c

  • Committer: Teddy Hogeborn
  • Date: 2008-08-02 21:06:12 UTC
  • Revision ID: teddy@fukt.bsnet.se-20080802210612-4c1waup4z0f66ya7
Non-tested commit for merge purposes.

* plugbasedclient.c (getplugin, addargument, set_cloexec): Made static.

* plugins.d/passprompt.c (termination_handler): Made static.

Show diffs side-by-side

added added

removed removed

Lines of Context:
37
37
#include <stdlib.h>
38
38
#include <time.h>
39
39
#include <net/if.h>             /* if_nametoindex */
40
 
#include <sys/ioctl.h>          /* ioctl, ifreq, SIOCGIFFLAGS, IFF_UP,
41
 
                                   SIOCSIFFLAGS */
42
 
#include <net/if.h>             /* ioctl, ifreq, SIOCGIFFLAGS, IFF_UP,
43
 
                                   SIOCSIFFLAGS */
44
40
 
45
41
#include <avahi-core/core.h>
46
42
#include <avahi-core/lookup.h>
72
68
 
73
69
#define BUFFER_SIZE 256
74
70
 
 
71
static int dh_bits = 1024;
 
72
 
75
73
static const char *keydir = "/conf/conf.d/mandos";
76
74
static const char *pubkeyfile = "pubkey.txt";
77
75
static const char *seckeyfile = "seckey.txt";
78
76
 
79
77
bool debug = false;
80
78
 
81
 
/* Used for passing in values through all the callback functions */
 
79
/* Used for  */
82
80
typedef struct {
83
 
  AvahiSimplePoll *simple_poll;
84
 
  AvahiServer *server;
 
81
  gnutls_session_t session;
85
82
  gnutls_certificate_credentials_t cred;
86
 
  unsigned int dh_bits;
87
 
  const char *priority;
88
 
} mandos_context;
89
 
 
90
 
/* 
91
 
 * Decrypt OpenPGP data using keyrings in HOMEDIR.
92
 
 * Returns -1 on error
93
 
 */
94
 
static ssize_t pgp_packet_decrypt (const char *cryptotext,
95
 
                                   size_t crypto_size,
96
 
                                   char **plaintext,
 
83
  gnutls_dh_params_t dh_params;
 
84
} encrypted_session;
 
85
 
 
86
 
 
87
static ssize_t pgp_packet_decrypt (char *packet, size_t packet_size,
 
88
                                   char **new_packet,
97
89
                                   const char *homedir){
98
90
  gpgme_data_t dh_crypto, dh_plain;
99
91
  gpgme_ctx_t ctx;
100
92
  gpgme_error_t rc;
101
93
  ssize_t ret;
102
 
  ssize_t plaintext_capacity = 0;
103
 
  ssize_t plaintext_length = 0;
 
94
  ssize_t new_packet_capacity = 0;
 
95
  ssize_t new_packet_length = 0;
104
96
  gpgme_engine_info_t engine_info;
105
 
  
 
97
 
106
98
  if (debug){
107
 
    fprintf(stderr, "Trying to decrypt OpenPGP data\n");
 
99
    fprintf(stderr, "Trying to decrypt OpenPGP packet\n");
108
100
  }
109
101
  
110
102
  /* Init GPGME */
116
108
    return -1;
117
109
  }
118
110
  
119
 
  /* Set GPGME home directory for the OpenPGP engine only */
 
111
  /* Set GPGME home directory */
120
112
  rc = gpgme_get_engine_info (&engine_info);
121
113
  if (rc != GPG_ERR_NO_ERROR){
122
114
    fprintf(stderr, "bad gpgme_get_engine_info: %s: %s\n",
132
124
    engine_info = engine_info->next;
133
125
  }
134
126
  if(engine_info == NULL){
135
 
    fprintf(stderr, "Could not set GPGME home dir to %s\n", homedir);
 
127
    fprintf(stderr, "Could not set home dir to %s\n", homedir);
136
128
    return -1;
137
129
  }
138
130
  
139
 
  /* Create new GPGME data buffer from memory cryptotext */
140
 
  rc = gpgme_data_new_from_mem(&dh_crypto, cryptotext, crypto_size,
141
 
                               0);
 
131
  /* Create new GPGME data buffer from packet buffer */
 
132
  rc = gpgme_data_new_from_mem(&dh_crypto, packet, packet_size, 0);
142
133
  if (rc != GPG_ERR_NO_ERROR){
143
134
    fprintf(stderr, "bad gpgme_data_new_from_mem: %s: %s\n",
144
135
            gpgme_strsource(rc), gpgme_strerror(rc));
150
141
  if (rc != GPG_ERR_NO_ERROR){
151
142
    fprintf(stderr, "bad gpgme_data_new: %s: %s\n",
152
143
            gpgme_strsource(rc), gpgme_strerror(rc));
153
 
    gpgme_data_release(dh_crypto);
154
144
    return -1;
155
145
  }
156
146
  
159
149
  if (rc != GPG_ERR_NO_ERROR){
160
150
    fprintf(stderr, "bad gpgme_new: %s: %s\n",
161
151
            gpgme_strsource(rc), gpgme_strerror(rc));
162
 
    plaintext_length = -1;
163
 
    goto decrypt_end;
 
152
    return -1;
164
153
  }
165
154
  
166
 
  /* Decrypt data from the cryptotext data buffer to the plaintext
167
 
     data buffer */
 
155
  /* Decrypt data from the FILE pointer to the plaintext data
 
156
     buffer */
168
157
  rc = gpgme_op_decrypt(ctx, dh_crypto, dh_plain);
169
158
  if (rc != GPG_ERR_NO_ERROR){
170
159
    fprintf(stderr, "bad gpgme_op_decrypt: %s: %s\n",
171
160
            gpgme_strsource(rc), gpgme_strerror(rc));
172
 
    plaintext_length = -1;
173
 
    goto decrypt_end;
 
161
    return -1;
174
162
  }
175
 
  
 
163
 
176
164
  if(debug){
177
 
    fprintf(stderr, "Decryption of OpenPGP data succeeded\n");
 
165
    fprintf(stderr, "Decryption of OpenPGP packet succeeded\n");
178
166
  }
179
 
  
 
167
 
180
168
  if (debug){
181
169
    gpgme_decrypt_result_t result;
182
170
    result = gpgme_op_decrypt_result(ctx);
206
194
    }
207
195
  }
208
196
  
 
197
  /* Delete the GPGME FILE pointer cryptotext data buffer */
 
198
  gpgme_data_release(dh_crypto);
 
199
  
209
200
  /* Seek back to the beginning of the GPGME plaintext data buffer */
210
201
  if (gpgme_data_seek(dh_plain, (off_t) 0, SEEK_SET) == -1){
211
202
    perror("pgpme_data_seek");
212
 
    plaintext_length = -1;
213
 
    goto decrypt_end;
214
203
  }
215
204
  
216
 
  *plaintext = NULL;
 
205
  *new_packet = 0;
217
206
  while(true){
218
 
    if (plaintext_length + BUFFER_SIZE > plaintext_capacity){
219
 
      *plaintext = realloc(*plaintext,
220
 
                            (unsigned int)plaintext_capacity
 
207
    if (new_packet_length + BUFFER_SIZE > new_packet_capacity){
 
208
      *new_packet = realloc(*new_packet,
 
209
                            (unsigned int)new_packet_capacity
221
210
                            + BUFFER_SIZE);
222
 
      if (*plaintext == NULL){
 
211
      if (*new_packet == NULL){
223
212
        perror("realloc");
224
 
        plaintext_length = -1;
225
 
        goto decrypt_end;
 
213
        return -1;
226
214
      }
227
 
      plaintext_capacity += BUFFER_SIZE;
 
215
      new_packet_capacity += BUFFER_SIZE;
228
216
    }
229
217
    
230
 
    ret = gpgme_data_read(dh_plain, *plaintext + plaintext_length,
 
218
    ret = gpgme_data_read(dh_plain, *new_packet + new_packet_length,
231
219
                          BUFFER_SIZE);
232
220
    /* Print the data, if any */
233
221
    if (ret == 0){
234
 
      /* EOF */
235
222
      break;
236
223
    }
237
224
    if(ret < 0){
238
225
      perror("gpgme_data_read");
239
 
      plaintext_length = -1;
240
 
      goto decrypt_end;
 
226
      return -1;
241
227
    }
242
 
    plaintext_length += ret;
 
228
    new_packet_length += ret;
243
229
  }
244
230
 
245
 
  if(debug){
246
 
    fprintf(stderr, "Decrypted password is: ");
247
 
    for(size_t i = 0; i < plaintext_length; i++){
248
 
      fprintf(stderr, "%02hhX ", (*plaintext)[i]);
249
 
    }
250
 
    fprintf(stderr, "\n");
251
 
  }
252
 
  
253
 
 decrypt_end:
254
 
  
255
 
  /* Delete the GPGME cryptotext data buffer */
256
 
  gpgme_data_release(dh_crypto);
 
231
  /* FIXME: check characters before printing to screen so to not print
 
232
     terminal control characters */
 
233
  /*   if(debug){ */
 
234
  /*     fprintf(stderr, "decrypted password is: "); */
 
235
  /*     fwrite(*new_packet, 1, new_packet_length, stderr); */
 
236
  /*     fprintf(stderr, "\n"); */
 
237
  /*   } */
257
238
  
258
239
  /* Delete the GPGME plaintext data buffer */
259
240
  gpgme_data_release(dh_plain);
260
 
  return plaintext_length;
 
241
  return new_packet_length;
261
242
}
262
243
 
263
244
static const char * safer_gnutls_strerror (int value) {
272
253
  fprintf(stderr, "%s", string);
273
254
}
274
255
 
275
 
static int initgnutls(mandos_context *mc, gnutls_session_t *session,
276
 
                      gnutls_dh_params_t *dh_params){
 
256
static int initgnutls(encrypted_session *es){
277
257
  const char *err;
278
258
  int ret;
279
259
  
286
266
    fprintf (stderr, "global_init: %s\n", safer_gnutls_strerror(ret));
287
267
    return -1;
288
268
  }
289
 
  
 
269
 
290
270
  if (debug){
291
271
    gnutls_global_set_log_level(11);
292
272
    gnutls_global_set_log_function(debuggnutls);
293
273
  }
294
274
  
295
275
  /* openpgp credentials */
296
 
  if ((ret = gnutls_certificate_allocate_credentials (&mc->cred))
 
276
  if ((ret = gnutls_certificate_allocate_credentials (&es->cred))
297
277
      != GNUTLS_E_SUCCESS) {
298
278
    fprintf (stderr, "memory error: %s\n",
299
279
             safer_gnutls_strerror(ret));
307
287
  }
308
288
  
309
289
  ret = gnutls_certificate_set_openpgp_key_file
310
 
    (mc->cred, pubkeyfile, seckeyfile, GNUTLS_OPENPGP_FMT_BASE64);
 
290
    (es->cred, pubkeyfile, seckeyfile, GNUTLS_OPENPGP_FMT_BASE64);
311
291
  if (ret != GNUTLS_E_SUCCESS) {
312
292
    fprintf
313
293
      (stderr, "Error[%d] while reading the OpenPGP key pair ('%s',"
319
299
  }
320
300
  
321
301
  //GnuTLS server initialization
322
 
  if ((ret = gnutls_dh_params_init(dh_params))
 
302
  if ((ret = gnutls_dh_params_init (&es->dh_params))
323
303
      != GNUTLS_E_SUCCESS) {
324
304
    fprintf (stderr, "Error in dh parameter initialization: %s\n",
325
305
             safer_gnutls_strerror(ret));
326
306
    return -1;
327
307
  }
328
308
  
329
 
  if ((ret = gnutls_dh_params_generate2(*dh_params, mc->dh_bits))
 
309
  if ((ret = gnutls_dh_params_generate2 (es->dh_params, dh_bits))
330
310
      != GNUTLS_E_SUCCESS) {
331
311
    fprintf (stderr, "Error in prime generation: %s\n",
332
312
             safer_gnutls_strerror(ret));
333
313
    return -1;
334
314
  }
335
315
  
336
 
  gnutls_certificate_set_dh_params(mc->cred, *dh_params);
 
316
  gnutls_certificate_set_dh_params (es->cred, es->dh_params);
337
317
  
338
318
  // GnuTLS session creation
339
 
  if ((ret = gnutls_init(session, GNUTLS_SERVER))
 
319
  if ((ret = gnutls_init (&es->session, GNUTLS_SERVER))
340
320
      != GNUTLS_E_SUCCESS){
341
321
    fprintf(stderr, "Error in GnuTLS session initialization: %s\n",
342
322
            safer_gnutls_strerror(ret));
343
323
  }
344
324
  
345
 
  if ((ret = gnutls_priority_set_direct(*session, mc->priority, &err))
 
325
  if ((ret = gnutls_priority_set_direct (es->session, "NORMAL", &err))
346
326
      != GNUTLS_E_SUCCESS) {
347
327
    fprintf(stderr, "Syntax error at: %s\n", err);
348
328
    fprintf(stderr, "GnuTLS error: %s\n",
350
330
    return -1;
351
331
  }
352
332
  
353
 
  if ((ret = gnutls_credentials_set(*session, GNUTLS_CRD_CERTIFICATE,
354
 
                                    mc->cred))
 
333
  if ((ret = gnutls_credentials_set
 
334
       (es->session, GNUTLS_CRD_CERTIFICATE, es->cred))
355
335
      != GNUTLS_E_SUCCESS) {
356
336
    fprintf(stderr, "Error setting a credentials set: %s\n",
357
337
            safer_gnutls_strerror(ret));
359
339
  }
360
340
  
361
341
  /* ignore client certificate if any. */
362
 
  gnutls_certificate_server_set_request (*session,
 
342
  gnutls_certificate_server_set_request (es->session,
363
343
                                         GNUTLS_CERT_IGNORE);
364
344
  
365
 
  gnutls_dh_set_prime_bits (*session, mc->dh_bits);
 
345
  gnutls_dh_set_prime_bits (es->session, dh_bits);
366
346
  
367
347
  return 0;
368
348
}
371
351
                      __attribute__((unused)) const char *txt){}
372
352
 
373
353
static int start_mandos_communication(const char *ip, uint16_t port,
374
 
                                      AvahiIfIndex if_index,
375
 
                                      mandos_context *mc){
 
354
                                      AvahiIfIndex if_index){
376
355
  int ret, tcp_sd;
377
356
  struct sockaddr_in6 to;
 
357
  encrypted_session es;
378
358
  char *buffer = NULL;
379
359
  char *decrypted_buffer;
380
360
  size_t buffer_length = 0;
383
363
  size_t written = 0;
384
364
  int retval = 0;
385
365
  char interface[IF_NAMESIZE];
386
 
  gnutls_session_t session;
387
 
  gnutls_dh_params_t dh_params;
388
366
  
389
367
  if(debug){
390
368
    fprintf(stderr, "Setting up a tcp connection to %s, port %d\n",
396
374
    perror("socket");
397
375
    return -1;
398
376
  }
399
 
 
400
 
  if(debug){
401
 
    if(if_indextoname((unsigned int)if_index, interface) == NULL){
 
377
  
 
378
  if(if_indextoname((unsigned int)if_index, interface) == NULL){
 
379
    if(debug){
402
380
      perror("if_indextoname");
403
 
      return -1;
404
381
    }
 
382
    return -1;
 
383
  }
 
384
  
 
385
  if(debug){
405
386
    fprintf(stderr, "Binding to interface %s\n", interface);
406
387
  }
407
388
  
411
392
  if (ret < 0 ){
412
393
    perror("inet_pton");
413
394
    return -1;
414
 
  }
 
395
  }  
415
396
  if(ret == 0){
416
397
    fprintf(stderr, "Bad address: %s\n", ip);
417
398
    return -1;
428
409
      perror("inet_ntop");
429
410
    } else {
430
411
      if(strcmp(addrstr, ip) != 0){
431
 
        fprintf(stderr, "Canonical address form: %s\n", addrstr);
 
412
        fprintf(stderr, "Canonical address form: %s\n",
 
413
                addrstr, ntohs(to.sin6_port));
432
414
      }
433
415
    }
434
416
  }
439
421
    return -1;
440
422
  }
441
423
  
442
 
  ret = initgnutls (mc, &session, &dh_params);
 
424
  ret = initgnutls (&es);
443
425
  if (ret != 0){
444
426
    retval = -1;
445
427
    return -1;
446
428
  }
447
429
  
448
 
  gnutls_transport_set_ptr (session, (gnutls_transport_ptr_t) tcp_sd);
 
430
  gnutls_transport_set_ptr (es.session,
 
431
                            (gnutls_transport_ptr_t) tcp_sd);
449
432
  
450
433
  if(debug){
451
434
    fprintf(stderr, "Establishing TLS session with %s\n", ip);
452
435
  }
453
436
  
454
 
  ret = gnutls_handshake (session);
 
437
  ret = gnutls_handshake (es.session);
455
438
  
456
439
  if (ret != GNUTLS_E_SUCCESS){
457
440
    if(debug){
479
462
      buffer_capacity += BUFFER_SIZE;
480
463
    }
481
464
    
482
 
    ret = gnutls_record_recv(session, buffer+buffer_length,
483
 
                             BUFFER_SIZE);
 
465
    ret = gnutls_record_recv
 
466
      (es.session, buffer+buffer_length, BUFFER_SIZE);
484
467
    if (ret == 0){
485
468
      break;
486
469
    }
490
473
      case GNUTLS_E_AGAIN:
491
474
        break;
492
475
      case GNUTLS_E_REHANDSHAKE:
493
 
        ret = gnutls_handshake (session);
 
476
        ret = gnutls_handshake (es.session);
494
477
        if (ret < 0){
495
478
          fprintf(stderr, "\n*** Handshake failed ***\n");
496
479
          gnutls_perror (ret);
502
485
        fprintf(stderr, "Unknown error while reading data from"
503
486
                " encrypted session with mandos server\n");
504
487
        retval = -1;
505
 
        gnutls_bye (session, GNUTLS_SHUT_RDWR);
 
488
        gnutls_bye (es.session, GNUTLS_SHUT_RDWR);
506
489
        goto exit;
507
490
      }
508
491
    } else {
543
526
  }
544
527
 
545
528
  free(buffer);
546
 
  gnutls_bye (session, GNUTLS_SHUT_RDWR);
 
529
  gnutls_bye (es.session, GNUTLS_SHUT_RDWR);
547
530
 exit:
548
531
  close(tcp_sd);
549
 
  gnutls_deinit (session);
550
 
  gnutls_certificate_free_credentials (mc->cred);
 
532
  gnutls_deinit (es.session);
 
533
  gnutls_certificate_free_credentials (es.cred);
551
534
  gnutls_global_deinit ();
552
535
  return retval;
553
536
}
554
537
 
555
 
static void resolve_callback(AvahiSServiceResolver *r,
556
 
                             AvahiIfIndex interface,
557
 
                             AVAHI_GCC_UNUSED AvahiProtocol protocol,
558
 
                             AvahiResolverEvent event,
559
 
                             const char *name,
560
 
                             const char *type,
561
 
                             const char *domain,
562
 
                             const char *host_name,
563
 
                             const AvahiAddress *address,
564
 
                             uint16_t port,
565
 
                             AVAHI_GCC_UNUSED AvahiStringList *txt,
566
 
                             AVAHI_GCC_UNUSED AvahiLookupResultFlags
567
 
                             flags,
568
 
                             void* userdata) {
569
 
  mandos_context *mc = userdata;
 
538
static AvahiSimplePoll *simple_poll = NULL;
 
539
static AvahiServer *server = NULL;
 
540
 
 
541
static void resolve_callback(
 
542
    AvahiSServiceResolver *r,
 
543
    AvahiIfIndex interface,
 
544
    AVAHI_GCC_UNUSED AvahiProtocol protocol,
 
545
    AvahiResolverEvent event,
 
546
    const char *name,
 
547
    const char *type,
 
548
    const char *domain,
 
549
    const char *host_name,
 
550
    const AvahiAddress *address,
 
551
    uint16_t port,
 
552
    AVAHI_GCC_UNUSED AvahiStringList *txt,
 
553
    AVAHI_GCC_UNUSED AvahiLookupResultFlags flags,
 
554
    AVAHI_GCC_UNUSED void* userdata) {
 
555
    
570
556
  assert(r);                    /* Spurious warning */
571
557
  
572
558
  /* Called whenever a service has been resolved successfully or
577
563
  case AVAHI_RESOLVER_FAILURE:
578
564
    fprintf(stderr, "(Resolver) Failed to resolve service '%s' of"
579
565
            " type '%s' in domain '%s': %s\n", name, type, domain,
580
 
            avahi_strerror(avahi_server_errno(mc->server)));
 
566
            avahi_strerror(avahi_server_errno(server)));
581
567
    break;
582
568
    
583
569
  case AVAHI_RESOLVER_FOUND:
588
574
        fprintf(stderr, "Mandos server \"%s\" found on %s (%s) on"
589
575
                " port %d\n", name, host_name, ip, port);
590
576
      }
591
 
      int ret = start_mandos_communication(ip, port, interface, mc);
 
577
      int ret = start_mandos_communication(ip, port, interface);
592
578
      if (ret == 0){
593
579
        exit(EXIT_SUCCESS);
594
580
      }
597
583
  avahi_s_service_resolver_free(r);
598
584
}
599
585
 
600
 
static void browse_callback( AvahiSServiceBrowser *b,
601
 
                             AvahiIfIndex interface,
602
 
                             AvahiProtocol protocol,
603
 
                             AvahiBrowserEvent event,
604
 
                             const char *name,
605
 
                             const char *type,
606
 
                             const char *domain,
607
 
                             AVAHI_GCC_UNUSED AvahiLookupResultFlags
608
 
                             flags,
609
 
                             void* userdata) {
610
 
  mandos_context *mc = userdata;
611
 
  assert(b);                    /* Spurious warning */
612
 
  
613
 
  /* Called whenever a new services becomes available on the LAN or
614
 
     is removed from the LAN */
615
 
  
616
 
  switch (event) {
617
 
  default:
618
 
  case AVAHI_BROWSER_FAILURE:
619
 
    
620
 
    fprintf(stderr, "(Browser) %s\n",
621
 
            avahi_strerror(avahi_server_errno(mc->server)));
622
 
    avahi_simple_poll_quit(mc->simple_poll);
623
 
    return;
624
 
    
625
 
  case AVAHI_BROWSER_NEW:
626
 
    /* We ignore the returned resolver object. In the callback
627
 
       function we free it. If the server is terminated before
628
 
       the callback function is called the server will free
629
 
       the resolver for us. */
630
 
    
631
 
    if (!(avahi_s_service_resolver_new(mc->server, interface,
632
 
                                       protocol, name, type, domain,
633
 
                                       AVAHI_PROTO_INET6, 0,
634
 
                                       resolve_callback, mc)))
635
 
      fprintf(stderr, "Failed to resolve service '%s': %s\n", name,
636
 
              avahi_strerror(avahi_server_errno(mc->server)));
637
 
    break;
638
 
    
639
 
  case AVAHI_BROWSER_REMOVE:
640
 
    break;
641
 
    
642
 
  case AVAHI_BROWSER_ALL_FOR_NOW:
643
 
  case AVAHI_BROWSER_CACHE_EXHAUSTED:
644
 
    break;
645
 
  }
 
586
static void browse_callback(
 
587
    AvahiSServiceBrowser *b,
 
588
    AvahiIfIndex interface,
 
589
    AvahiProtocol protocol,
 
590
    AvahiBrowserEvent event,
 
591
    const char *name,
 
592
    const char *type,
 
593
    const char *domain,
 
594
    AVAHI_GCC_UNUSED AvahiLookupResultFlags flags,
 
595
    void* userdata) {
 
596
    
 
597
    AvahiServer *s = userdata;
 
598
    assert(b);                  /* Spurious warning */
 
599
    
 
600
    /* Called whenever a new services becomes available on the LAN or
 
601
       is removed from the LAN */
 
602
    
 
603
    switch (event) {
 
604
    default:
 
605
    case AVAHI_BROWSER_FAILURE:
 
606
      
 
607
      fprintf(stderr, "(Browser) %s\n",
 
608
              avahi_strerror(avahi_server_errno(server)));
 
609
      avahi_simple_poll_quit(simple_poll);
 
610
      return;
 
611
      
 
612
    case AVAHI_BROWSER_NEW:
 
613
      /* We ignore the returned resolver object. In the callback
 
614
         function we free it. If the server is terminated before
 
615
         the callback function is called the server will free
 
616
         the resolver for us. */
 
617
      
 
618
      if (!(avahi_s_service_resolver_new(s, interface, protocol, name,
 
619
                                         type, domain,
 
620
                                         AVAHI_PROTO_INET6, 0,
 
621
                                         resolve_callback, s)))
 
622
        fprintf(stderr, "Failed to resolve service '%s': %s\n", name,
 
623
                avahi_strerror(avahi_server_errno(s)));
 
624
      break;
 
625
      
 
626
    case AVAHI_BROWSER_REMOVE:
 
627
      break;
 
628
      
 
629
    case AVAHI_BROWSER_ALL_FOR_NOW:
 
630
    case AVAHI_BROWSER_CACHE_EXHAUSTED:
 
631
      break;
 
632
    }
646
633
}
647
634
 
648
635
/* Combines file name and path and returns the malloced new
655
642
    return NULL;
656
643
  }
657
644
  if(f_len > 0){
658
 
    memcpy(tmp, first, f_len);  /* Spurious warning */
 
645
    memcpy(tmp, first, f_len);
659
646
  }
660
647
  tmp[f_len] = '/';
661
648
  if(s_len > 0){
662
 
    memcpy(tmp + f_len + 1, second, s_len); /* Spurious warning */
 
649
    memcpy(tmp + f_len + 1, second, s_len);
663
650
  }
664
651
  tmp[f_len + 1 + s_len] = '\0';
665
652
  return tmp;
671
658
    AvahiSServiceBrowser *sb = NULL;
672
659
    int error;
673
660
    int ret;
674
 
    int debug_int;
 
661
    int debug_int = 0;
675
662
    int returncode = EXIT_SUCCESS;
676
 
    const char *interface = "eth0";
677
 
    struct ifreq network;
678
 
    int sd;
 
663
    const char *interface = NULL;
 
664
    AvahiIfIndex if_index = AVAHI_IF_UNSPEC;
679
665
    char *connect_to = NULL;
680
 
    AvahiIfIndex if_index = AVAHI_IF_UNSPEC;
681
 
    mandos_context mc = { .simple_poll = NULL, .server = NULL,
682
 
                          .dh_bits = 1024, .priority = "SECURE256"};
683
666
    
684
667
    debug_int = debug ? 1 : 0;
685
668
    while (true){
686
 
      struct option long_options[] = {
 
669
      static struct option long_options[] = {
687
670
        {"debug", no_argument, &debug_int, 1},
688
 
        {"connect", required_argument, NULL, 'c'},
 
671
        {"connect", required_argument, NULL, 'C'},
689
672
        {"interface", required_argument, NULL, 'i'},
690
673
        {"keydir", required_argument, NULL, 'd'},
691
 
        {"seckey", required_argument, NULL, 's'},
692
 
        {"pubkey", required_argument, NULL, 'p'},
 
674
        {"seckey", required_argument, NULL, 'c'},
 
675
        {"pubkey", required_argument, NULL, 'k'},
693
676
        {"dh-bits", required_argument, NULL, 'D'},
694
 
        {"priority", required_argument, NULL, 'P'},
695
677
        {0, 0, 0, 0} };
696
678
      
697
679
      int option_index = 0;
708
690
      case 'i':
709
691
        interface = optarg;
710
692
        break;
711
 
      case 'c':
 
693
      case 'C':
712
694
        connect_to = optarg;
713
695
        break;
714
696
      case 'd':
715
697
        keydir = optarg;
716
698
        break;
717
 
      case 'p':
 
699
      case 'c':
718
700
        pubkeyfile = optarg;
719
701
        break;
720
 
      case 's':
 
702
      case 'k':
721
703
        seckeyfile = optarg;
722
704
        break;
723
705
      case 'D':
724
 
        errno = 0;
725
 
        mc.dh_bits = (unsigned int) strtol(optarg, NULL, 10);
726
 
        if (errno){
727
 
          perror("strtol");
728
 
          exit(EXIT_FAILURE);
729
 
        }
730
 
        break;
731
 
      case 'P':
732
 
        mc.priority = optarg;
 
706
        dh_bits = atoi(optarg);
733
707
        break;
734
708
      case '?':
 
709
        break
735
710
      default:
736
711
        exit(EXIT_FAILURE);
737
712
      }
741
716
    pubkeyfile = combinepath(keydir, pubkeyfile);
742
717
    if (pubkeyfile == NULL){
743
718
      perror("combinepath");
744
 
      returncode = EXIT_FAILURE;
745
 
      goto exit;
746
 
    }
747
 
    
748
 
    seckeyfile = combinepath(keydir, seckeyfile);
749
 
    if (seckeyfile == NULL){
750
 
      perror("combinepath");
751
 
      goto exit;
752
 
    }
753
 
    
754
 
    if_index = (AvahiIfIndex) if_nametoindex(interface);
755
 
    if(if_index == 0){
756
 
      fprintf(stderr, "No such interface: \"%s\"\n", interface);
757
 
      exit(EXIT_FAILURE);
 
719
      goto exit;
 
720
    }
 
721
    
 
722
    if(interface != NULL){
 
723
      if_index = (AvahiIfIndex) if_nametoindex(interface);
 
724
      if(if_index == 0){
 
725
        fprintf(stderr, "No such interface: \"%s\"\n", interface);
 
726
        exit(EXIT_FAILURE);
 
727
      }
758
728
    }
759
729
    
760
730
    if(connect_to != NULL){
773
743
      }
774
744
      *address = '\0';
775
745
      address = connect_to;
776
 
      ret = start_mandos_communication(address, port, if_index, &mc);
 
746
      ret = start_mandos_communication(address, port, if_index);
777
747
      if(ret < 0){
778
748
        exit(EXIT_FAILURE);
779
749
      } else {
781
751
      }
782
752
    }
783
753
    
784
 
    sd = socket(PF_INET6, SOCK_DGRAM, IPPROTO_IP);
785
 
    if(sd < 0) {
786
 
      perror("socket");
787
 
      returncode = EXIT_FAILURE;
788
 
      goto exit;
789
 
    }
790
 
    strcpy(network.ifr_name, interface); /* Spurious warning */
791
 
    ret = ioctl(sd, SIOCGIFFLAGS, &network);
792
 
    if(ret == -1){
793
 
      
794
 
      perror("ioctl SIOCGIFFLAGS");
795
 
      returncode = EXIT_FAILURE;
796
 
      goto exit;
797
 
    }
798
 
    if((network.ifr_flags & IFF_UP) == 0){
799
 
      network.ifr_flags |= IFF_UP;
800
 
      ret = ioctl(sd, SIOCSIFFLAGS, &network);
801
 
      if(ret == -1){
802
 
        perror("ioctl SIOCSIFFLAGS");
803
 
        returncode = EXIT_FAILURE;
804
 
        goto exit;
805
 
      }
806
 
    }
807
 
    close(sd);
 
754
    seckeyfile = combinepath(keydir, seckeyfile);
 
755
    if (seckeyfile == NULL){
 
756
      perror("combinepath");
 
757
      goto exit;
 
758
    }
808
759
    
809
760
    if (not debug){
810
761
      avahi_set_log_function(empty_log);
814
765
    srand((unsigned int) time(NULL));
815
766
 
816
767
    /* Allocate main loop object */
817
 
    if (!(mc.simple_poll = avahi_simple_poll_new())) {
 
768
    if (!(simple_poll = avahi_simple_poll_new())) {
818
769
        fprintf(stderr, "Failed to create simple poll object.\n");
819
 
        returncode = EXIT_FAILURE;
 
770
        
820
771
        goto exit;
821
772
    }
822
773
 
828
779
    config.publish_domain = 0;
829
780
 
830
781
    /* Allocate a new server */
831
 
    mc.server=avahi_server_new(avahi_simple_poll_get(mc.simple_poll),
832
 
                               &config, NULL, NULL, &error);
833
 
    
 
782
    server = avahi_server_new(avahi_simple_poll_get(simple_poll),
 
783
                              &config, NULL, NULL, &error);
 
784
 
834
785
    /* Free the configuration data */
835
786
    avahi_server_config_free(&config);
836
 
    
 
787
 
837
788
    /* Check if creating the server object succeeded */
838
 
    if (!mc.server) {
 
789
    if (!server) {
839
790
        fprintf(stderr, "Failed to create server: %s\n",
840
791
                avahi_strerror(error));
841
792
        returncode = EXIT_FAILURE;
843
794
    }
844
795
    
845
796
    /* Create the service browser */
846
 
    sb = avahi_s_service_browser_new(mc.server, if_index,
 
797
    sb = avahi_s_service_browser_new(server, if_index,
847
798
                                     AVAHI_PROTO_INET6,
848
799
                                     "_mandos._tcp", NULL, 0,
849
 
                                     browse_callback, &mc);
 
800
                                     browse_callback, server);
850
801
    if (!sb) {
851
802
        fprintf(stderr, "Failed to create service browser: %s\n",
852
 
                avahi_strerror(avahi_server_errno(mc.server)));
 
803
                avahi_strerror(avahi_server_errno(server)));
853
804
        returncode = EXIT_FAILURE;
854
805
        goto exit;
855
806
    }
860
811
      fprintf(stderr, "Starting avahi loop search\n");
861
812
    }
862
813
    
863
 
    avahi_simple_poll_loop(mc.simple_poll);
 
814
    avahi_simple_poll_loop(simple_poll);
864
815
    
865
816
 exit:
866
817
 
872
823
    if (sb)
873
824
        avahi_s_service_browser_free(sb);
874
825
    
875
 
    if (mc.server)
876
 
        avahi_server_free(mc.server);
 
826
    if (server)
 
827
        avahi_server_free(server);
877
828
 
878
 
    if (mc.simple_poll)
879
 
        avahi_simple_poll_free(mc.simple_poll);
 
829
    if (simple_poll)
 
830
        avahi_simple_poll_free(simple_poll);
880
831
    free(pubkeyfile);
881
832
    free(seckeyfile);
882
833