/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/mandos-client.c

  • Committer: Teddy Hogeborn
  • Date: 2015-07-20 03:03:33 UTC
  • Revision ID: teddy@recompile.se-20150720030333-203m2aeblypcsfte
Bug fix for GnuTLS 3: be compatible with old 2048-bit DSA keys.

The mandos-keygen program in Mandos version 1.6.0 and older generated
2048-bit DSA keys, and when GnuTLS uses these it has trouble
connecting using the Mandos default priority string.  This was
previously fixed in Mandos 1.6.2, but the bug reappeared when using
GnuTLS 3, so the default priority string has to change again; this
time also the Mandos client has to change its default, so now the
server and the client should use the same default priority string:

SECURE256:!CTYPE-X.509:+CTYPE-OPENPGP:!RSA:+SIGN-DSA-SHA256

* mandos (main/server_defaults): Changed default priority string.
* mandos-options.xml (/section/para[id="priority_compat"]): Removed.
  (/section/para[id="priority"]): Changed default priority string.
* mandos.conf ([DEFAULT]/priority): - '' -
* mandos.conf.xml (OPTIONS/priority): Refer to the id "priority"
                                      instead of "priority_compat".
* mandos.xml (OPTIONS/--priority): - '' -
* plugins.d/mandos-client.c (main): Changed default priority string.

Show diffs side-by-side

added added

removed removed

Lines of Context:
9
9
 * "browse_callback", and parts of "main".
10
10
 * 
11
11
 * Everything else is
12
 
 * Copyright © 2008-2016 Teddy Hogeborn
13
 
 * Copyright © 2008-2016 Björn Påhlsson
 
12
 * Copyright © 2008-2015 Teddy Hogeborn
 
13
 * Copyright © 2008-2015 Björn Påhlsson
14
14
 * 
15
15
 * This program is free software: you can redistribute it and/or
16
16
 * modify it under the terms of the GNU General Public License as
47
47
                                   strtof(), abort() */
48
48
#include <stdbool.h>            /* bool, false, true */
49
49
#include <string.h>             /* strcmp(), strlen(), strerror(),
50
 
                                   asprintf(), strncpy() */
 
50
                                   asprintf(), strcpy() */
51
51
#include <sys/ioctl.h>          /* ioctl */
52
52
#include <sys/types.h>          /* socket(), inet_pton(), sockaddr,
53
53
                                   sockaddr_in6, PF_INET6,
57
57
#include <sys/socket.h>         /* socket(), struct sockaddr_in6,
58
58
                                   inet_pton(), connect(),
59
59
                                   getnameinfo() */
60
 
#include <fcntl.h>              /* open(), unlinkat(), AT_REMOVEDIR */
 
60
#include <fcntl.h>              /* open(), unlinkat() */
61
61
#include <dirent.h>             /* opendir(), struct dirent, readdir()
62
62
                                 */
63
63
#include <inttypes.h>           /* PRIu16, PRIdMAX, intmax_t,
64
64
                                   strtoimax() */
65
 
#include <errno.h>              /* perror(), errno, EINTR, EINVAL,
66
 
                                   EAI_SYSTEM, ENETUNREACH,
67
 
                                   EHOSTUNREACH, ECONNREFUSED, EPROTO,
68
 
                                   EIO, ENOENT, ENXIO, ENOMEM, EISDIR,
69
 
                                   ENOTEMPTY,
 
65
#include <errno.h>              /* perror(), errno,
70
66
                                   program_invocation_short_name */
71
67
#include <time.h>               /* nanosleep(), time(), sleep() */
72
68
#include <net/if.h>             /* ioctl, ifreq, SIOCGIFFLAGS, IFF_UP,
517
513
  fprintf_plus(stderr, "GnuTLS: %s", string);
518
514
}
519
515
 
520
 
__attribute__((nonnull(1, 2, 4), warn_unused_result))
 
516
__attribute__((nonnull, warn_unused_result))
521
517
static int init_gnutls_global(const char *pubkeyfilename,
522
518
                              const char *seckeyfilename,
523
519
                              const char *dhparamsfilename,
529
525
    fprintf_plus(stderr, "Initializing GnuTLS\n");
530
526
  }
531
527
  
 
528
  ret = gnutls_global_init();
 
529
  if(ret != GNUTLS_E_SUCCESS){
 
530
    fprintf_plus(stderr, "GnuTLS global_init: %s\n",
 
531
                 safer_gnutls_strerror(ret));
 
532
    return -1;
 
533
  }
 
534
  
532
535
  if(debug){
533
536
    /* "Use a log level over 10 to enable all debugging options."
534
537
     * - GnuTLS manual
542
545
  if(ret != GNUTLS_E_SUCCESS){
543
546
    fprintf_plus(stderr, "GnuTLS memory error: %s\n",
544
547
                 safer_gnutls_strerror(ret));
 
548
    gnutls_global_deinit();
545
549
    return -1;
546
550
  }
547
551
  
751
755
 globalfail:
752
756
  
753
757
  gnutls_certificate_free_credentials(mc->cred);
 
758
  gnutls_global_deinit();
754
759
  gnutls_dh_params_deinit(mc->dh_params);
755
760
  return -1;
756
761
}
1218
1223
                    sizeof(struct sockaddr_in));
1219
1224
    }
1220
1225
    if(ret < 0){
1221
 
      if(((errno == ENETUNREACH) or (errno == EHOSTUNREACH))
 
1226
      if(errno == ENETUNREACH
1222
1227
         and if_index != AVAHI_IF_UNSPEC
1223
1228
         and connect_to == NULL
1224
1229
         and not route_added and
1632
1637
    errno = ret_errno;
1633
1638
    return false;
1634
1639
  }
1635
 
  strncpy(ifr->ifr_name, ifname, IF_NAMESIZE);
1636
 
  ifr->ifr_name[IF_NAMESIZE-1] = '\0'; /* NUL terminate */
 
1640
  strcpy(ifr->ifr_name, ifname);
1637
1641
  ret = ioctl(s, SIOCGIFFLAGS, ifr);
1638
1642
  if(ret == -1){
1639
1643
    if(debug){
1909
1913
      return;
1910
1914
    }
1911
1915
  }
 
1916
#ifdef __GLIBC__
 
1917
#if __GLIBC_PREREQ(2, 15)
1912
1918
  int numhooks = scandirat(hookdir_fd, ".", &direntries,
1913
1919
                           runnable_hook, alphasort);
 
1920
#else  /* not __GLIBC_PREREQ(2, 15) */
 
1921
  int numhooks = scandir(hookdir, &direntries, runnable_hook,
 
1922
                         alphasort);
 
1923
#endif  /* not __GLIBC_PREREQ(2, 15) */
 
1924
#else   /* not __GLIBC__ */
 
1925
  int numhooks = scandir(hookdir, &direntries, runnable_hook,
 
1926
                         alphasort);
 
1927
#endif  /* not __GLIBC__ */
1914
1928
  if(numhooks == -1){
1915
1929
    perror_plus("scandir");
1916
1930
    return;
2961
2975
  
2962
2976
  if(gnutls_initialized){
2963
2977
    gnutls_certificate_free_credentials(mc.cred);
 
2978
    gnutls_global_deinit();
2964
2979
    gnutls_dh_params_deinit(mc.dh_params);
2965
2980
  }
2966
2981
  
3028
3043
  free(interfaces_to_take_down);
3029
3044
  free(interfaces_hooks);
3030
3045
  
3031
 
  void clean_dir_at(int base, const char * const dirname,
3032
 
                    uintmax_t level){
3033
 
    struct dirent **direntries = NULL;
3034
 
    int dret;
3035
 
    int dir_fd = (int)TEMP_FAILURE_RETRY(openat(base, dirname,
3036
 
                                                O_RDONLY
3037
 
                                                | O_NOFOLLOW
3038
 
                                                | O_DIRECTORY
3039
 
                                                | O_PATH));
3040
 
    if(dir_fd == -1){
3041
 
      perror_plus("open");
3042
 
    }
3043
 
    int numentries = scandirat(dir_fd, ".", &direntries,
3044
 
                               notdotentries, alphasort);
3045
 
    if(numentries >= 0){
3046
 
      for(int i = 0; i < numentries; i++){
3047
 
        if(debug){
3048
 
          fprintf_plus(stderr, "Unlinking \"%s/%s\"\n",
3049
 
                       dirname, direntries[i]->d_name);
3050
 
        }
3051
 
        dret = unlinkat(dir_fd, direntries[i]->d_name, 0);
3052
 
        if(dret == -1){
3053
 
          if(errno == EISDIR){
3054
 
              dret = unlinkat(dir_fd, direntries[i]->d_name,
3055
 
                              AT_REMOVEDIR);
3056
 
          }         
3057
 
          if((dret == -1) and (errno == ENOTEMPTY)
3058
 
             and (strcmp(direntries[i]->d_name, "private-keys-v1.d")
3059
 
                  == 0) and (level == 0)){
3060
 
            /* Recurse only in this special case */
3061
 
            clean_dir_at(dir_fd, direntries[i]->d_name, level+1);
3062
 
            dret = 0;
3063
 
          }
3064
 
          if(dret == -1){
3065
 
            fprintf_plus(stderr, "unlink(\"%s/%s\"): %s\n", dirname,
3066
 
                         direntries[i]->d_name, strerror(errno));
3067
 
          }
3068
 
        }
3069
 
        free(direntries[i]);
3070
 
      }
3071
 
      
3072
 
      /* need to clean even if 0 because man page doesn't specify */
3073
 
      free(direntries);
3074
 
      if(numentries == -1){
3075
 
        perror_plus("scandirat");
3076
 
      }
3077
 
      dret = unlinkat(base, dirname, AT_REMOVEDIR);
3078
 
      if(dret == -1 and errno != ENOENT){
3079
 
        perror_plus("rmdir");
3080
 
      }
3081
 
    } else {
3082
 
      perror_plus("scandirat");
3083
 
    }
3084
 
    close(dir_fd);
3085
 
  }
3086
 
  
3087
3046
  /* Removes the GPGME temp directory and all files inside */
3088
3047
  if(tempdir != NULL){
3089
 
    clean_dir_at(-1, tempdir, 0);
 
3048
    struct dirent **direntries = NULL;
 
3049
    int tempdir_fd = (int)TEMP_FAILURE_RETRY(open(tempdir, O_RDONLY
 
3050
                                                  | O_NOFOLLOW
 
3051
                                                  | O_DIRECTORY
 
3052
                                                  | O_PATH));
 
3053
    if(tempdir_fd == -1){
 
3054
      perror_plus("open");
 
3055
    } else {
 
3056
#ifdef __GLIBC__
 
3057
#if __GLIBC_PREREQ(2, 15)
 
3058
      int numentries = scandirat(tempdir_fd, ".", &direntries,
 
3059
                                 notdotentries, alphasort);
 
3060
#else  /* not __GLIBC_PREREQ(2, 15) */
 
3061
      int numentries = scandir(tempdir, &direntries, notdotentries,
 
3062
                               alphasort);
 
3063
#endif  /* not __GLIBC_PREREQ(2, 15) */
 
3064
#else   /* not __GLIBC__ */
 
3065
      int numentries = scandir(tempdir, &direntries, notdotentries,
 
3066
                               alphasort);
 
3067
#endif  /* not __GLIBC__ */
 
3068
      if(numentries >= 0){
 
3069
        for(int i = 0; i < numentries; i++){
 
3070
          ret = unlinkat(tempdir_fd, direntries[i]->d_name, 0);
 
3071
          if(ret == -1){
 
3072
            fprintf_plus(stderr, "unlinkat(open(\"%s\", O_RDONLY),"
 
3073
                         " \"%s\", 0): %s\n", tempdir,
 
3074
                         direntries[i]->d_name, strerror(errno));
 
3075
          }
 
3076
          free(direntries[i]);
 
3077
        }
 
3078
        
 
3079
        /* need to clean even if 0 because man page doesn't specify */
 
3080
        free(direntries);
 
3081
        if(numentries == -1){
 
3082
          perror_plus("scandir");
 
3083
        }
 
3084
        ret = rmdir(tempdir);
 
3085
        if(ret == -1 and errno != ENOENT){
 
3086
          perror_plus("rmdir");
 
3087
        }
 
3088
      }
 
3089
      close(tempdir_fd);
 
3090
    }
3090
3091
  }
3091
3092
  
3092
3093
  if(quit_now){