From d5acb508bcf8f6d177cc6b5a3411490337f45545 Mon Sep 17 00:00:00 2001 From: Sebastien Raveau Date: Wed, 24 Jun 2009 17:28:13 +0000 Subject: [PATCH] Add support for applying SELinux context --- CHANGELOG | 2 ++ doc/iodine.te | 25 +++++++++++++++++++++++++ man/iodine.8 | 9 ++++++++- src/common.c | 15 +++++++++++++++ src/common.h | 1 + src/iodine.c | 13 +++++++++++-- src/iodined.c | 15 ++++++++++++--- src/osflags | 6 ++++++ 8 files changed, 80 insertions(+), 6 deletions(-) create mode 100644 doc/iodine.te diff --git a/CHANGELOG b/CHANGELOG index c8899e1..69bf8b3 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -10,6 +10,8 @@ CHANGES: - Any device name is now supported on Windows, fixes #47. - Multiple installed TAP32 interfaces are now supported, fixes #46. - Return nonzero if tunnel fails to open, fixes #62. + - Support for setting a SELinux context, based on patch by + Sebastien Raveau. Sample context file in doc/iodine.te 2009-06-01: 0.5.2 "WifiFree" - Fixed client segfault on OS X, #57 diff --git a/doc/iodine.te b/doc/iodine.te new file mode 100644 index 0000000..9749f03 --- /dev/null +++ b/doc/iodine.te @@ -0,0 +1,25 @@ +# Sample post-initialization SELinux policy for Iodine +policy_module(iodine, 1.1) + +require { + type init_t; + type initrc_t; + type unconfined_t; + type unlabeled_t; + class udp_socket { read write }; + class rawip_socket { write read }; + class association recvfrom; + class unix_dgram_socket { create connect }; +} + +type iodine_t; +domain_type(iodine_t) +domain_dyntrans_type(initrc_t) +allow initrc_t iodine_t:process dyntransition; + +allow iodine_t unconfined_t:udp_socket { read write }; +allow iodine_t unconfined_t:rawip_socket { write read }; +allow iodine_t unlabeled_t:association recvfrom; +allow iodine_t self:unix_dgram_socket { create connect }; +corenet_raw_receive_generic_node(iodine_t) +corenet_rw_tun_tap_dev(iodine_t) diff --git a/man/iodine.8 b/man/iodine.8 index 1eeac2b..d83edac 100644 --- a/man/iodine.8 +++ b/man/iodine.8 @@ -19,6 +19,8 @@ iodine, iodined \- tunnel IPv4 over DNS .I device .B ] [-m .I fragsize +.B ] [-z +.I context .B ] .B [ .I nameserver @@ -47,7 +49,9 @@ iodine, iodined \- tunnel IPv4 over DNS .I dnsport .B ] [-P .I password -.B ] +.B ] [-z +.I context +.B ] .I tunnel_ip .B [ .I /netmask @@ -89,6 +93,9 @@ and otherwise tunX. Use 'password' to authenticate. If not used, .B stdin will be used as input. Only the first 32 characters will be used. +.TP +.B -z context +Apply SELinux 'context' after initialization. .SS Client Options: .TP .B -m fragsize diff --git a/src/common.c b/src/common.c index 2a8380b..ba87a89 100644 --- a/src/common.c +++ b/src/common.c @@ -41,6 +41,10 @@ #include #endif +#ifdef HAVE_SETCON +# include +#endif + #include "common.h" /* The raw header used when not using DNS protocol */ @@ -167,6 +171,17 @@ do_chroot(char *newroot) #endif } +void +do_setcon(char *context) +{ +#ifdef HAVE_SETCON + if (-1 == setcon(context)) + err(1, "%s", context); +#else + warnx("No SELinux support built in"); +#endif +} + void do_detach() { diff --git a/src/common.h b/src/common.h index eb1b39b..28fc2bb 100644 --- a/src/common.h +++ b/src/common.h @@ -90,6 +90,7 @@ int open_dns(int, in_addr_t); void close_dns(int); void do_chroot(char *); +void do_setcon(char *); void do_detach(); void read_password(char*, size_t); diff --git a/src/iodine.c b/src/iodine.c index 0776704..71dbbcb 100644 --- a/src/iodine.c +++ b/src/iodine.c @@ -1104,7 +1104,7 @@ usage() { extern char *__progname; fprintf(stderr, "Usage: %s [-v] [-h] [-f] [-u user] [-t chrootdir] [-d device] " - "[-P password] [-m maxfragsize] [nameserver] topdomain\n", __progname); + "[-P password] [-m maxfragsize] [-z context] [nameserver] topdomain\n", __progname); exit(2); } @@ -1114,7 +1114,7 @@ help() { fprintf(stderr, "iodine IP over DNS tunneling client\n"); fprintf(stderr, "Usage: %s [-v] [-h] [-f] [-u user] [-t chrootdir] [-d device] " - "[-P password] [-m maxfragsize] [nameserver] topdomain\n", __progname); + "[-P password] [-m maxfragsize] [-z context] [nameserver] topdomain\n", __progname); fprintf(stderr, " -v to print version info and exit\n"); fprintf(stderr, " -h to print this help and exit\n"); fprintf(stderr, " -f to keep running in foreground\n"); @@ -1123,6 +1123,7 @@ help() { fprintf(stderr, " -d device to set tunnel device name\n"); fprintf(stderr, " -P password used for authentication (max 32 chars will be used)\n"); fprintf(stderr, " -m maxfragsize, to limit size of downstream packets\n"); + fprintf(stderr, " -z context, to apply specified SELinux context after initialization\n"); fprintf(stderr, "nameserver is the IP number of the relaying nameserver, if absent /etc/resolv.conf is used\n"); fprintf(stderr, "topdomain is the FQDN that is delegated to the tunnel endpoint.\n"); @@ -1151,6 +1152,7 @@ main(int argc, char **argv) char *username; int foreground; char *newroot; + char *context; char *device; int choice; int tun_fd; @@ -1163,6 +1165,7 @@ main(int argc, char **argv) username = NULL; foreground = 0; newroot = NULL; + context = NULL; device = NULL; chunkid = 0; @@ -1222,6 +1225,9 @@ main(int argc, char **argv) autodetect_frag_size = 0; max_downstream_frag_size = atoi(optarg); break; + case 'z': + context = optarg; + break; default: usage(); /* NOTREACHED */ @@ -1321,6 +1327,9 @@ main(int argc, char **argv) } #endif } + + if (context != NULL) + do_setcon(context); downstream_seqno = 0; downstream_fragment = 0; diff --git a/src/iodined.c b/src/iodined.c index b885a6a..96d7188 100644 --- a/src/iodined.c +++ b/src/iodined.c @@ -981,7 +981,7 @@ usage() { extern char *__progname; fprintf(stderr, "Usage: %s [-v] [-h] [-c] [-s] [-f] [-D] [-u user] " - "[-t chrootdir] [-d device] [-m mtu] " + "[-t chrootdir] [-d device] [-m mtu] [-z context] " "[-l ip address to listen on] [-p port] [-n external ip] [-b dnsport] [-P password]" " tunnel_ip[/netmask] topdomain\n", __progname); exit(2); @@ -993,7 +993,7 @@ help() { fprintf(stderr, "iodine IP over DNS tunneling server\n"); fprintf(stderr, "Usage: %s [-v] [-h] [-c] [-s] [-f] [-D] [-u user] " - "[-t chrootdir] [-d device] [-m mtu] " + "[-t chrootdir] [-d device] [-m mtu] [-z context] " "[-l ip address to listen on] [-p port] [-n external ip] [-b dnsport] [-P password]" " tunnel_ip[/netmask] topdomain\n", __progname); fprintf(stderr, " -v to print version info and exit\n"); @@ -1007,6 +1007,7 @@ help() { fprintf(stderr, " -t dir to chroot to directory dir\n"); fprintf(stderr, " -d device to set tunnel device name\n"); fprintf(stderr, " -m mtu to set tunnel device mtu\n"); + fprintf(stderr, " -z context to apply SELinux context after initialization\n"); fprintf(stderr, " -l ip address to listen on for incoming dns traffic " "(default 0.0.0.0)\n"); fprintf(stderr, " -p port to listen on for incoming dns traffic (default 53)\n"); @@ -1039,6 +1040,7 @@ main(int argc, char **argv) int foreground; char *username; char *newroot; + char *context; char *device; int dnsd_fd; int tun_fd; @@ -1057,6 +1059,7 @@ main(int argc, char **argv) username = NULL; newroot = NULL; + context = NULL; device = NULL; foreground = 0; bind_enable = 0; @@ -1090,7 +1093,7 @@ main(int argc, char **argv) srand(time(NULL)); fw_query_init(); - while ((choice = getopt(argc, argv, "vcsfhDu:t:d:m:l:p:n:b:P:")) != -1) { + while ((choice = getopt(argc, argv, "vcsfhDu:t:d:m:l:p:n:b:P:z:")) != -1) { switch(choice) { case 'v': version(); @@ -1142,6 +1145,9 @@ main(int argc, char **argv) /* XXX: find better way of cleaning up ps(1) */ memset(optarg, 0, strlen(optarg)); break; + case 'z': + context = optarg; + break; default: usage(); break; @@ -1287,6 +1293,9 @@ main(int argc, char **argv) #endif } + if (context != NULL) + do_setcon(context); + #ifndef WINDOWS32 openlog(__progname, LOG_NOWAIT, LOG_DAEMON); #endif diff --git a/src/osflags b/src/osflags index fc6da1c..787ffaa 100755 --- a/src/osflags +++ b/src/osflags @@ -16,6 +16,9 @@ link) windows32) echo '-lws2_32 -liphlpapi'; ;; + Linux) + [ -e /usr/include/selinux/selinux.h ] && echo '-lselinux'; + ;; esac ;; cflags) @@ -23,6 +26,9 @@ cflags) BeOS) echo '-Dsocklen_t=int'; ;; + Linux) + [ -e /usr/include/selinux/selinux.h ] && echo '-DHAVE_SETCON'; + ;; esac ;; *)