/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

* plugins.d/mandos-client.c (run_network_hooks): New.
  (main): Run run_network_hooks() with "stop" and "start" at
          appropriate places.  Don't lower privileges permanently
          prematurely.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1410
1410
  }
1411
1411
}
1412
1412
 
 
1413
bool run_network_hooks(const char *mode, const char *interface,
 
1414
                       const float delay){
 
1415
  struct dirent **direntries;
 
1416
  struct dirent *direntry;
 
1417
  int ret;
 
1418
  int numhooks = scandir(hookdir, &direntries, runnable_hook,
 
1419
                         alphasort);
 
1420
  if(numhooks == -1){
 
1421
    perror_plus("scandir");
 
1422
  } else {
 
1423
    int devnull = open("/dev/null", O_RDONLY);
 
1424
    for(int i = 0; i < numhooks; i++){
 
1425
      direntry = direntries[0];
 
1426
      char *fullname = NULL;
 
1427
      ret = asprintf(&fullname, "%s/%s", hookdir, direntry->d_name);
 
1428
      if(ret < 0){
 
1429
        perror_plus("asprintf");
 
1430
        continue;
 
1431
      }
 
1432
      pid_t hook_pid = fork();
 
1433
      if(hook_pid == 0){
 
1434
        /* Child */
 
1435
        dup2(devnull, STDIN_FILENO);
 
1436
        close(devnull);
 
1437
        dup2(STDERR_FILENO, STDOUT_FILENO);
 
1438
        ret = setenv("MANDOSNETHOOKDIR", hookdir, 1);
 
1439
        if(ret == -1){
 
1440
          perror_plus("setenv");
 
1441
          return false;
 
1442
        }
 
1443
        ret = setenv("DEVICE", interface, 1);
 
1444
        if(ret == -1){
 
1445
          perror_plus("setenv");
 
1446
          return false;
 
1447
        }
 
1448
        ret = setenv("VERBOSE", debug ? "1" : "0", 1);
 
1449
        if(ret == -1){
 
1450
          perror_plus("setenv");
 
1451
          return false;
 
1452
        }
 
1453
        ret = setenv("MODE", mode, 1);
 
1454
        if(ret == -1){
 
1455
          perror_plus("setenv");
 
1456
          return false;
 
1457
        }
 
1458
        char *delaystring;
 
1459
        ret = asprintf(&delaystring, "%f", delay);
 
1460
        if(ret == -1){
 
1461
          perror_plus("asprintf");
 
1462
          return false;
 
1463
        }
 
1464
        ret = setenv("DELAY", delaystring, 1);
 
1465
        if(ret == -1){
 
1466
          free(delaystring);
 
1467
          perror_plus("setenv");
 
1468
          return false;
 
1469
        }
 
1470
        free(delaystring);
 
1471
        ret = execl(fullname, direntry->d_name, mode, NULL);
 
1472
        perror_plus("execl");
 
1473
      } else {
 
1474
        int status;
 
1475
        if(TEMP_FAILURE_RETRY(waitpid(hook_pid, &status, 0)) == -1){
 
1476
          perror_plus("waitpid");
 
1477
          free(fullname);
 
1478
          continue;
 
1479
        }
 
1480
        if(WIFEXITED(status)){
 
1481
          if(WEXITSTATUS(status) != 0){
 
1482
            fprintf(stderr, "Mandos plugin mandos-client: "
 
1483
                    "Warning: network hook \"%s\" exited"
 
1484
                    " with status %d\n", direntry->d_name,
 
1485
                    WEXITSTATUS(status));
 
1486
            free(fullname);
 
1487
            continue;
 
1488
          }
 
1489
        } else if(WIFSIGNALED(status)){
 
1490
          fprintf(stderr, "Mandos plugin mandos-client: "
 
1491
                  "Warning: network hook \"%s\" died by"
 
1492
                  " signal %d\n", direntry->d_name,
 
1493
                  WTERMSIG(status));
 
1494
          free(fullname);
 
1495
          continue;
 
1496
        } else {
 
1497
          fprintf(stderr, "Mandos plugin mandos-client: "
 
1498
                  "Warning: network hook \"%s\" crashed\n",
 
1499
                  direntry->d_name);
 
1500
          free(fullname);
 
1501
          continue;
 
1502
        }
 
1503
      }
 
1504
      free(fullname);
 
1505
      if(quit_now){
 
1506
        break;
 
1507
      }
 
1508
    }
 
1509
    close(devnull);
 
1510
  }
 
1511
  return true;
 
1512
}
 
1513
 
1413
1514
int main(int argc, char *argv[]){
1414
1515
  AvahiSServiceBrowser *sb = NULL;
1415
1516
  int error;
1664
1765
    }
1665
1766
  }
1666
1767
  
1667
 
  /* Find network hooks and run them */
 
1768
  /* Run network hooks */
1668
1769
  {
1669
 
    struct dirent **direntries;
1670
 
    struct dirent *direntry;
1671
 
    int numhooks = scandir(hookdir, &direntries, runnable_hook,
1672
 
                           alphasort);
1673
 
    if(numhooks == -1){
1674
 
      perror_plus("scandir");
1675
 
    } else {
1676
 
      int devnull = open("/dev/null", O_RDONLY);
1677
 
      for(int i = 0; i < numhooks; i++){
1678
 
        direntry = direntries[0];
1679
 
        char *fullname = NULL;
1680
 
        ret = asprintf(&fullname, "%s/%s", hookdir, direntry->d_name);
1681
 
        if(ret < 0){
1682
 
          perror_plus("asprintf");
1683
 
          continue;
1684
 
        }
1685
 
        pid_t hook_pid = fork();
1686
 
        if(hook_pid == 0){
1687
 
          /* Child */
1688
 
          dup2(devnull, STDIN_FILENO);
1689
 
          close(devnull);
1690
 
          dup2(STDERR_FILENO, STDOUT_FILENO);
1691
 
          ret = setenv("MANDOSNETHOOKDIR", hookdir, 1);
1692
 
          if(ret == -1){
1693
 
            perror_plus("setenv");
1694
 
            exit(1);
1695
 
          }
1696
 
          ret = setenv("DEVICE", interface, 1);
1697
 
          if(ret == -1){
1698
 
            perror_plus("setenv");
1699
 
            exit(1);
1700
 
          }
1701
 
          ret = setenv("VERBOSE", debug ? "1" : "0", 1);
1702
 
          if(ret == -1){
1703
 
            perror_plus("setenv");
1704
 
            exit(1);
1705
 
          }
1706
 
          ret = setenv("MODE", "start", 1);
1707
 
          if(ret == -1){
1708
 
            perror_plus("setenv");
1709
 
            exit(1);
1710
 
          }
1711
 
          char *delaystring;
1712
 
          ret = asprintf(&delaystring, "%f", delay);
1713
 
          if(ret == -1){
1714
 
            perror_plus("asprintf");
1715
 
            exit(1);
1716
 
          }
1717
 
          ret = setenv("DELAY", delaystring, 1);
1718
 
          if(ret == -1){
1719
 
            free(delaystring);
1720
 
            perror_plus("setenv");
1721
 
            exit(1);
1722
 
          }
1723
 
          free(delaystring);
1724
 
          ret = execl(fullname, direntry->d_name, "start", NULL);
1725
 
          perror_plus("execl");
1726
 
        } else {
1727
 
          int status;
1728
 
          if(TEMP_FAILURE_RETRY(waitpid(hook_pid, &status, 0)) == -1){
1729
 
            perror_plus("waitpid");
1730
 
            free(fullname);
1731
 
            continue;
1732
 
          }
1733
 
          if(WIFEXITED(status)){
1734
 
            if(WEXITSTATUS(status) != 0){
1735
 
              fprintf(stderr, "Mandos plugin mandos-client: "
1736
 
                      "Warning: network hook \"%s\" exited"
1737
 
                      " with status %d\n", direntry->d_name,
1738
 
                      WEXITSTATUS(status));
1739
 
              free(fullname);
1740
 
              continue;
1741
 
            }
1742
 
          } else if(WIFSIGNALED(status)){
1743
 
            fprintf(stderr, "Mandos plugin mandos-client: "
1744
 
                    "Warning: network hook \"%s\" died by"
1745
 
                    " signal %d\n", direntry->d_name,
1746
 
                    WTERMSIG(status));
1747
 
            free(fullname);
1748
 
            continue;
1749
 
          } else {
1750
 
            fprintf(stderr, "Mandos plugin mandos-client: "
1751
 
                    "Warning: network hook \"%s\" crashed\n",
1752
 
                    direntry->d_name);
1753
 
            free(fullname);
1754
 
            continue;
1755
 
          }
1756
 
        }
1757
 
        free(fullname);
1758
 
        if(quit_now){
1759
 
          goto end;
1760
 
        }
1761
 
      }
1762
 
      close(devnull);
 
1770
    /* Re-raise priviliges */
 
1771
    errno = 0;
 
1772
    ret = seteuid(0);
 
1773
    if(ret == -1){
 
1774
      perror_plus("seteuid");
 
1775
    }
 
1776
    if(not run_network_hooks("start", interface, delay)){
 
1777
      goto end;
 
1778
    }
 
1779
    /* Lower privileges */
 
1780
    errno = 0;
 
1781
    ret = seteuid(uid);
 
1782
    if(ret == -1){
 
1783
      perror_plus("seteuid");
1763
1784
    }
1764
1785
  }
1765
1786
  
2007
2028
#endif  /* __linux__ */
2008
2029
    /* Lower privileges */
2009
2030
    errno = 0;
2010
 
    if(take_down_interface){
2011
 
      /* Lower privileges */
2012
 
      ret = seteuid(uid);
2013
 
      if(ret == -1){
2014
 
        perror_plus("seteuid");
2015
 
      }
2016
 
    } else {
2017
 
      /* Lower privileges permanently */
2018
 
      ret = setuid(uid);
2019
 
      if(ret == -1){
2020
 
        perror_plus("setuid");
2021
 
      }
 
2031
    /* Lower privileges */
 
2032
    ret = seteuid(uid);
 
2033
    if(ret == -1){
 
2034
      perror_plus("seteuid");
2022
2035
    }
2023
2036
  }
2024
2037
  
2237
2250
    }
2238
2251
  }
2239
2252
  
2240
 
  /* XXX run network hooks "stop" here  */
2241
 
  
2242
 
  /* Take down the network interface */
2243
 
  if(take_down_interface){
2244
 
    /* Re-raise priviliges */
 
2253
  /* Re-raise priviliges */
 
2254
  {
2245
2255
    errno = 0;
2246
2256
    ret = seteuid(0);
2247
2257
    if(ret == -1){
2248
2258
      perror_plus("seteuid");
2249
2259
    }
2250
 
    if(geteuid() == 0){
 
2260
    /* Run network hooks */
 
2261
    if(not run_network_hooks("stop", interface, delay)){
 
2262
      goto end;
 
2263
    }
 
2264
    
 
2265
    /* Take down the network interface */
 
2266
    if(take_down_interface and geteuid() == 0){
2251
2267
      ret = ioctl(sd, SIOCGIFFLAGS, &network);
2252
2268
      if(ret == -1){
2253
2269
        perror_plus("ioctl SIOCGIFFLAGS");
2262
2278
      if(ret == -1){
2263
2279
        perror_plus("close");
2264
2280
      }
2265
 
      /* Lower privileges permanently */
2266
 
      errno = 0;
2267
 
      ret = setuid(uid);
2268
 
      if(ret == -1){
2269
 
        perror_plus("setuid");
2270
 
      }
2271
2281
    }
2272
2282
  }
 
2283
  /* Lower privileges permanently */
 
2284
  errno = 0;
 
2285
  ret = setuid(uid);
 
2286
  if(ret == -1){
 
2287
    perror_plus("setuid");
 
2288
  }
2273
2289
  
2274
2290
  /* Removes the GPGME temp directory and all files inside */
2275
2291
  if(tempdir_created){