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

* mandos-clients.conf.xml (OPTIONS): Moved up "extended_timeout" to
                                     order options alphabetically.
* clients.conf: Language change in comment.

Show diffs side-by-side

added added

removed removed

Lines of Context:
26
26
 * along with this program.  If not, see
27
27
 * <http://www.gnu.org/licenses/>.
28
28
 * 
29
 
 * Contact the authors at <mandos@recompile.se>.
 
29
 * Contact the authors at <mandos@fukt.bsnet.se>.
30
30
 */
31
31
 
32
32
/* Needed by GPGME, specifically gpgme_data_seek() */
123
123
#define PATHDIR "/conf/conf.d/mandos"
124
124
#define SECKEY "seckey.txt"
125
125
#define PUBKEY "pubkey.txt"
126
 
#define HOOKDIR "/lib/mandos/network-hooks.d"
127
126
 
128
127
bool debug = false;
129
128
static const char mandos_protocol_version[] = "1";
130
129
const char *argp_program_version = "mandos-client " VERSION;
131
 
const char *argp_program_bug_address = "<mandos@recompile.se>";
 
130
const char *argp_program_bug_address = "<mandos@fukt.bsnet.se>";
132
131
static const char sys_class_net[] = "/sys/class/net";
133
132
char *connect_to = NULL;
134
133
 
171
170
  perror(print_text);
172
171
}
173
172
 
174
 
int fprintf_plus(FILE *stream, const char *format, ...){
175
 
  va_list ap;
176
 
  va_start (ap, format);
177
 
  
178
 
  TEMP_FAILURE_RETRY(fprintf(stream, "Mandos plugin %s: ", program_invocation_short_name));
179
 
  return TEMP_FAILURE_RETRY(vfprintf(stream, format, ap));
180
 
}
181
 
 
182
173
/*
183
174
 * Make additional room in "buffer" for at least BUFFER_SIZE more
184
175
 * bytes. "buffer_capacity" is how much is currently allocated,
1094
1085
  errno = old_errno;
1095
1086
}
1096
1087
 
1097
 
bool get_flags(const char *ifname, struct ifreq *ifr){
1098
 
  int ret;
1099
 
  
1100
 
  int s = socket(PF_INET6, SOCK_DGRAM, IPPROTO_IP);
1101
 
  if(s < 0){
1102
 
    perror_plus("socket");
1103
 
    return false;
1104
 
  }
1105
 
  strcpy(ifr->ifr_name, ifname);
1106
 
  ret = ioctl(s, SIOCGIFFLAGS, ifr);
1107
 
  if(ret == -1){
1108
 
    if(debug){
1109
 
      perror_plus("ioctl SIOCGIFFLAGS");
1110
 
    }
1111
 
    return false;
1112
 
  }
1113
 
  return true;
1114
 
}
1115
 
 
1116
 
bool good_flags(const char *ifname, const struct ifreq *ifr){
1117
 
  
1118
 
  /* Reject the loopback device */
1119
 
  if(ifr->ifr_flags & IFF_LOOPBACK){
1120
 
    if(debug){
1121
 
      fprintf(stderr, "Rejecting loopback interface \"%s\"\n",
1122
 
              ifname);
1123
 
    }
1124
 
    return false;
1125
 
  }
1126
 
  /* Accept point-to-point devices only if connect_to is specified */
1127
 
  if(connect_to != NULL and (ifr->ifr_flags & IFF_POINTOPOINT)){
1128
 
    if(debug){
1129
 
      fprintf(stderr, "Accepting point-to-point interface \"%s\"\n",
1130
 
              ifname);
1131
 
    }
1132
 
    return true;
1133
 
  }
1134
 
  /* Otherwise, reject non-broadcast-capable devices */
1135
 
  if(not (ifr->ifr_flags & IFF_BROADCAST)){
1136
 
    if(debug){
1137
 
      fprintf(stderr, "Rejecting non-broadcast interface \"%s\"\n",
1138
 
              ifname);
1139
 
    }
1140
 
    return false;
1141
 
  }
1142
 
  /* Reject non-ARP interfaces (including dummy interfaces) */
1143
 
  if(ifr->ifr_flags & IFF_NOARP){
1144
 
    if(debug){
1145
 
      fprintf(stderr, "Rejecting non-ARP interface \"%s\"\n", ifname);
1146
 
    }
1147
 
    return false;
1148
 
  }
1149
 
  
1150
 
  /* Accept this device */
1151
 
  if(debug){
1152
 
    fprintf(stderr, "Interface \"%s\" is good\n", ifname);
1153
 
  }
1154
 
  return true;
1155
 
}
1156
 
 
1157
1088
/* 
1158
1089
 * This function determines if a directory entry in /sys/class/net
1159
1090
 * corresponds to an acceptable network device.
1160
1091
 * (This function is passed to scandir(3) as a filter function.)
1161
1092
 */
1162
1093
int good_interface(const struct dirent *if_entry){
1163
 
  int ret;
1164
 
  if(if_entry->d_name[0] == '.'){
1165
 
    return 0;
1166
 
  }
1167
 
  struct ifreq ifr;
1168
 
 
1169
 
  if(not get_flags(if_entry->d_name, &ifr)){
1170
 
    return 0;
1171
 
  }
1172
 
  
1173
 
  if(not good_flags(if_entry->d_name, &ifr)){
1174
 
    return 0;
1175
 
  }
1176
 
  return 1;
1177
 
}
1178
 
 
1179
 
/* 
1180
 
 * This function determines if a directory entry in /sys/class/net
1181
 
 * corresponds to an acceptable network device which is up.
1182
 
 * (This function is passed to scandir(3) as a filter function.)
1183
 
 */
1184
 
int up_interface(const struct dirent *if_entry){
1185
1094
  ssize_t ssret;
1186
1095
  char *flagname = NULL;
1187
1096
  if(if_entry->d_name[0] == '.'){
1249
1158
    }
1250
1159
    return 0;
1251
1160
  }
1252
 
 
1253
 
  /* Reject down interfaces */
1254
 
  if(not (flags & IFF_UP)){
1255
 
    return 0;
1256
 
  }
1257
 
  
1258
1161
  /* Accept point-to-point devices only if connect_to is specified */
1259
1162
  if(connect_to != NULL and (flags & IFF_POINTOPOINT)){
1260
1163
    if(debug){
1298
1201
  return 1;
1299
1202
}
1300
1203
 
1301
 
/* Is this directory entry a runnable program? */
1302
 
int runnable_hook(const struct dirent *direntry){
1303
 
  int ret;
1304
 
  struct stat st;
1305
 
  
1306
 
  if((direntry->d_name)[0] == '\0'){
1307
 
    /* Empty name? */
1308
 
    return 0;
1309
 
  }
1310
 
  
1311
 
  /* Save pointer to last character */
1312
 
  char *end = strchr(direntry->d_name, '\0')-1;
1313
 
  
1314
 
  if(*end == '~'){
1315
 
    /* Backup name~ */
1316
 
    return 0;
1317
 
  }
1318
 
  
1319
 
  if(((direntry->d_name)[0] == '#')
1320
 
     and (*end == '#')){
1321
 
    /* Temporary #name# */
1322
 
    return 0;
1323
 
  }
1324
 
  
1325
 
  /* XXX more rules here */
1326
 
  
1327
 
  ret = stat(direntry->d_name, &st);
1328
 
  if(ret == -1){
1329
 
    if(debug){
1330
 
      perror_plus("Could not stat plugin");
1331
 
    }
1332
 
    return 0;
1333
 
  }
1334
 
  if(not (st.st_mode & S_ISREG)){
1335
 
    /* Not a regular file */
1336
 
    return 0;
1337
 
  }
1338
 
  if(not (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))){
1339
 
    /* Not executable */
1340
 
    return 0;
1341
 
  }
1342
 
  return 1;
1343
 
}
1344
 
 
1345
1204
int avahi_loop_with_timeout(AvahiSimplePoll *s, int retry_interval){
1346
1205
  int ret;
1347
1206
  struct timespec now;
1659
1518
    }
1660
1519
  }
1661
1520
  
1662
 
  /* Find network hooks and run them */
1663
 
  {
1664
 
    struct dirent **direntries;
1665
 
    struct dirent *direntry;
1666
 
    int numhooks = scandir(HOOKDIR, &direntries, runnable_hook,
1667
 
                           alphasort);
1668
 
    int devnull = open("/dev/null", O_RDONLY);
1669
 
    for(int i = 0; i < numhooks; i++){
1670
 
      direntry = direntries[0];
1671
 
      char *fullname = NULL;
1672
 
      ret = asprintf(&fullname, "%s/%s", tempdir,
1673
 
                     direntry->d_name);
1674
 
      if(ret < 0){
1675
 
        perror_plus("asprintf");
1676
 
        continue;
1677
 
      }
1678
 
      pid_t hook_pid = fork();
1679
 
      if(hook_pid == 0){
1680
 
        /* Child */
1681
 
        dup2(devnull, STDIN_FILENO);
1682
 
        close(devnull);
1683
 
        dup2(STDERR_FILENO, STDOUT_FILENO);
1684
 
        setenv("DEVICE", interface, 1);
1685
 
        setenv("VERBOSE", debug ? "1" : "0", 1);
1686
 
        setenv("MODE", "start", 1);
1687
 
        /* setenv( XXX more here */
1688
 
        ret = execl(fullname, direntry->d_name, "start");
1689
 
        perror_plus("execl");
1690
 
      }
1691
 
      free(fullname);
1692
 
      if(quit_now){
1693
 
        goto end;
1694
 
      }
1695
 
    }
1696
 
    close(devnull);
1697
 
  }
1698
 
  
1699
1521
  if(not debug){
1700
1522
    avahi_set_log_function(empty_log);
1701
1523
  }
1702
 
  
 
1524
 
1703
1525
  if(interface[0] == '\0'){
1704
1526
    struct dirent **direntries;
1705
1527
    ret = scandir(sys_class_net, &direntries, good_interface,
2047
1869
    if (not quit_now){
2048
1870
      exitcode = EXIT_SUCCESS;
2049
1871
    }
2050
 
    
 
1872
 
2051
1873
    goto end;
2052
1874
  }
2053
1875
  
2150
1972
    }
2151
1973
  }
2152
1974
  
2153
 
  /* XXX run network hooks "stop" here  */
2154
 
  
2155
1975
  /* Take down the network interface */
2156
1976
  if(take_down_interface){
2157
1977
    /* Re-raise priviliges */