/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: 2009-01-29 22:22:32 UTC
  • Revision ID: teddy@fukt.bsnet.se-20090129222232-p9hqnq338nsvxayp
* mandos (main): Bug fix: Do setgid before setuid.  Add verbose GnuTLS
                 debugging messages.
* plugins.d/mandos-client.c (main): Bug fix: Do setgid before setuid.

Show diffs side-by-side

added added

removed removed

Lines of Context:
36
36
#define _GNU_SOURCE             /* TEMP_FAILURE_RETRY(), asprintf() */
37
37
 
38
38
#include <stdio.h>              /* fprintf(), stderr, fwrite(),
39
 
                                   stdout, ferror(), sscanf */
 
39
                                   stdout, ferror(), sscanf(),
 
40
                                   remove() */
40
41
#include <stdint.h>             /* uint16_t, uint32_t */
41
42
#include <stddef.h>             /* NULL, size_t, ssize_t */
42
43
#include <stdlib.h>             /* free(), EXIT_SUCCESS, EXIT_FAILURE,
57
58
#include <fcntl.h>              /* open() */
58
59
#include <dirent.h>             /* opendir(), struct dirent, readdir()
59
60
                                 */
60
 
#include <inttypes.h>           /* PRIu16, SCNu16 */
 
61
#include <inttypes.h>           /* PRIu16, intmax_t, SCNdMAX */
61
62
#include <assert.h>             /* assert() */
62
63
#include <errno.h>              /* perror(), errno */
63
64
#include <time.h>               /* time() */
153
154
  
154
155
  
155
156
  /*
156
 
   * Helper function to insert pub and seckey to the enigne keyring.
 
157
   * Helper function to insert pub and seckey to the engine keyring.
157
158
   */
158
159
  bool import_key(const char *filename){
159
160
    int fd;
365
366
}
366
367
 
367
368
static const char * safer_gnutls_strerror(int value) {
368
 
  const char *ret = gnutls_strerror(value); /* Spurious warning */
 
369
  const char *ret = gnutls_strerror(value); /* Spurious warning from
 
370
                                               -Wunreachable-code */
369
371
  if(ret == NULL)
370
372
    ret = "(unknown)";
371
373
  return ret;
404
406
  /* OpenPGP credentials */
405
407
  gnutls_certificate_allocate_credentials(&mc->cred);
406
408
  if(ret != GNUTLS_E_SUCCESS){
407
 
    fprintf(stderr, "GnuTLS memory error: %s\n", /* Spurious
408
 
                                                    warning */
 
409
    fprintf(stderr, "GnuTLS memory error: %s\n", /* Spurious warning
 
410
                                                  * from
 
411
                                                  * -Wunreachable-code
 
412
                                                  */
409
413
            safer_gnutls_strerror(ret));
410
414
    gnutls_global_deinit();
411
415
    return -1;
553
557
    fprintf(stderr, "Bad address: %s\n", ip);
554
558
    return -1;
555
559
  }
556
 
  to.in6.sin6_port = htons(port); /* Spurious warning */
 
560
  to.in6.sin6_port = htons(port); /* Spurious warnings from
 
561
                                     -Wconversion and
 
562
                                     -Wunreachable-code */
557
563
  
558
564
  to.in6.sin6_scope_id = (uint32_t)if_index;
559
565
  
749
755
      avahi_address_snprint(ip, sizeof(ip), address);
750
756
      if(debug){
751
757
        fprintf(stderr, "Mandos server \"%s\" found on %s (%s, %"
752
 
                PRIu16 ") on port %d\n", name, host_name, ip,
753
 
                interface, port);
 
758
                PRIdMAX ") on port %" PRIu16 "\n", name, host_name,
 
759
                ip, (intmax_t)interface, port);
754
760
      }
755
761
      int ret = start_mandos_communication(ip, port, interface, mc);
756
762
      if(ret == 0){
816
822
    AvahiSServiceBrowser *sb = NULL;
817
823
    int error;
818
824
    int ret;
 
825
    intmax_t tmpmax;
 
826
    int numchars;
819
827
    int exitcode = EXIT_SUCCESS;
820
828
    const char *interface = "eth0";
821
829
    struct ifreq network;
824
832
    gid_t gid;
825
833
    char *connect_to = NULL;
826
834
    char tempdir[] = "/tmp/mandosXXXXXX";
 
835
    bool tempdir_created = false;
827
836
    AvahiIfIndex if_index = AVAHI_IF_UNSPEC;
828
837
    const char *seckey = PATHDIR "/" SECKEY;
829
838
    const char *pubkey = PATHDIR "/" PUBKEY;
831
840
    mandos_context mc = { .simple_poll = NULL, .server = NULL,
832
841
                          .dh_bits = 1024, .priority = "SECURE256"
833
842
                          ":!CTYPE-X.509:+CTYPE-OPENPGP" };
834
 
    bool gnutls_initalized = false;
835
 
    bool gpgme_initalized = false;
 
843
    bool gnutls_initialized = false;
 
844
    bool gpgme_initialized = false;
836
845
    
837
846
    {
838
847
      struct argp_option options[] = {
886
895
          pubkey = arg;
887
896
          break;
888
897
        case 129:               /* --dh-bits */
889
 
          ret = sscanf(arg, "%u", &mc.dh_bits);
890
 
          if(ret != 1){
 
898
          ret = sscanf(arg, "%" SCNdMAX "%n", &tmpmax, &numchars);
 
899
          if(ret < 1 or tmpmax != (typeof(mc.dh_bits))tmpmax
 
900
             or arg[numchars] != '\0'){
891
901
            fprintf(stderr, "Bad number of DH bits\n");
892
902
            exit(EXIT_FAILURE);
893
903
          }
 
904
          mc.dh_bits = (typeof(mc.dh_bits))tmpmax;
894
905
          break;
895
906
        case 130:               /* --priority */
896
907
          mc.priority = arg;
950
961
    uid = getuid();
951
962
    gid = getgid();
952
963
    
 
964
    setgid(gid);
 
965
    if(ret == -1){
 
966
      perror("setgid");
 
967
    }
 
968
    
953
969
    ret = setuid(uid);
954
970
    if(ret == -1){
955
971
      perror("setuid");
956
972
    }
957
973
    
958
 
    setgid(gid);
959
 
    if(ret == -1){
960
 
      perror("setgid");
961
 
    }
962
 
    
963
974
    ret = init_gnutls_global(&mc, pubkey, seckey);
964
975
    if(ret == -1){
965
976
      fprintf(stderr, "init_gnutls_global failed\n");
966
977
      exitcode = EXIT_FAILURE;
967
978
      goto end;
968
979
    } else {
969
 
      gnutls_initalized = true;
 
980
      gnutls_initialized = true;
970
981
    }
971
982
    
972
983
    if(mkdtemp(tempdir) == NULL){
973
984
      perror("mkdtemp");
974
 
      tempdir[0] = '\0';
975
985
      goto end;
976
986
    }
 
987
    tempdir_created = true;
977
988
    
978
989
    if(not init_gpgme(&mc, pubkey, seckey, tempdir)){
979
 
      fprintf(stderr, "gpgme_initalized failed\n");
 
990
      fprintf(stderr, "init_gpgme failed\n");
980
991
      exitcode = EXIT_FAILURE;
981
992
      goto end;
982
993
    } else {
983
 
      gpgme_initalized = true;
 
994
      gpgme_initialized = true;
984
995
    }
985
996
    
986
997
    if_index = (AvahiIfIndex) if_nametoindex(interface);
987
998
    if(if_index == 0){
988
999
      fprintf(stderr, "No such interface: \"%s\"\n", interface);
989
 
      exit(EXIT_FAILURE);
 
1000
      exitcode = EXIT_FAILURE;
 
1001
      goto end;
990
1002
    }
991
1003
    
992
1004
    if(connect_to != NULL){
999
1011
        goto end;
1000
1012
      }
1001
1013
      uint16_t port;
1002
 
      ret = sscanf(address+1, "%" SCNu16, &port);
1003
 
      if(ret != 1){
 
1014
      ret = sscanf(address+1, "%" SCNdMAX "%n", &tmpmax, &numchars);
 
1015
      if(ret < 1 or tmpmax != (uint16_t)tmpmax
 
1016
         or address[numchars+1] != '\0'){
1004
1017
        fprintf(stderr, "Bad port number\n");
1005
1018
        exitcode = EXIT_FAILURE;
1006
1019
        goto end;
1007
1020
      }
 
1021
      port = (uint16_t)tmpmax;
1008
1022
      *address = '\0';
1009
1023
      address = connect_to;
1010
1024
      ret = start_mandos_communication(address, port, if_index, &mc);
1094
1108
    if(mc.simple_poll != NULL)
1095
1109
        avahi_simple_poll_free(mc.simple_poll);
1096
1110
    
1097
 
    if(gnutls_initalized){
 
1111
    if(gnutls_initialized){
1098
1112
      gnutls_certificate_free_credentials(mc.cred);
1099
1113
      gnutls_global_deinit();
1100
1114
      gnutls_dh_params_deinit(mc.dh_params);
1101
1115
    }
1102
1116
    
1103
 
    if(gpgme_initalized){
 
1117
    if(gpgme_initialized){
1104
1118
      gpgme_release(mc.ctx);
1105
1119
    }
1106
1120
    
1107
1121
    /* Removes the temp directory used by GPGME */
1108
 
    if(tempdir[0] != '\0'){
 
1122
    if(tempdir_created){
1109
1123
      DIR *d;
1110
1124
      struct dirent *direntry;
1111
1125
      d = opendir(tempdir);
1119
1133
          if(direntry == NULL){
1120
1134
            break;
1121
1135
          }
1122
 
          if(direntry->d_type == DT_REG){
1123
 
            char *fullname = NULL;
1124
 
            ret = asprintf(&fullname, "%s/%s", tempdir,
1125
 
                           direntry->d_name);
1126
 
            if(ret < 0){
1127
 
              perror("asprintf");
1128
 
              continue;
1129
 
            }
1130
 
            ret = unlink(fullname);
1131
 
            if(ret == -1){
1132
 
              fprintf(stderr, "unlink(\"%s\"): %s",
1133
 
                      fullname, strerror(errno));
1134
 
            }
1135
 
            free(fullname);
1136
 
          }
 
1136
          /* Skip "." and ".." */
 
1137
          if(direntry->d_name[0] == '.'
 
1138
             and (direntry->d_name[1] == '\0'
 
1139
                  or (direntry->d_name[1] == '.'
 
1140
                      and direntry->d_name[2] == '\0'))){
 
1141
            continue;
 
1142
          }
 
1143
          char *fullname = NULL;
 
1144
          ret = asprintf(&fullname, "%s/%s", tempdir,
 
1145
                         direntry->d_name);
 
1146
          if(ret < 0){
 
1147
            perror("asprintf");
 
1148
            continue;
 
1149
          }
 
1150
          ret = remove(fullname);
 
1151
          if(ret == -1){
 
1152
            fprintf(stderr, "remove(\"%s\"): %s\n", fullname,
 
1153
                    strerror(errno));
 
1154
          }
 
1155
          free(fullname);
1137
1156
        }
1138
1157
        closedir(d);
1139
1158
      }
1142
1161
        perror("rmdir");
1143
1162
      }
1144
1163
    }
1145
 
          
 
1164
    
1146
1165
    return exitcode;
1147
1166
}