added credentials support to the tuntap router

This commit is contained in:
Unbit
2013-12-15 07:49:44 +01:00
parent 33a6195e44
commit b9170b2c85
3 changed files with 88 additions and 15 deletions
+34 -12
View File
@@ -3,7 +3,7 @@
extern struct uwsgi_tuntap utt;
// create a new peer
struct uwsgi_tuntap_peer *uwsgi_tuntap_peer_create(struct uwsgi_tuntap_router *uttr, int fd) {
struct uwsgi_tuntap_peer *uwsgi_tuntap_peer_create(struct uwsgi_tuntap_router *uttr, int fd, int is_router) {
struct uwsgi_tuntap_peer *uttp = uwsgi_calloc(sizeof(struct uwsgi_tuntap_peer));
uttp->fd = fd;
@@ -21,6 +21,19 @@ struct uwsgi_tuntap_peer *uwsgi_tuntap_peer_create(struct uwsgi_tuntap_router *u
uttr->peers_tail = uttp;
}
if (!is_router && utt.use_credentials) {
uwsgi_log_verbose("[uwsgi-tuntap] waiting for privileges drop...\n");
for(;;) {
if (getuid() > 0) break;
sleep(1);
}
uwsgi_log_verbose("[uwsgi-tuntap] privileges dropped\n");
if (uwsgi_pass_cred(fd, "uwsgi-tuntap", 12)) {
// better to exit
exit(1);
}
}
return uttp;
}
@@ -159,6 +172,24 @@ retry:
}
}
int uwsgi_tuntap_register_addr(struct uwsgi_tuntap_router *uttr, struct uwsgi_tuntap_peer *uttp) {
struct uwsgi_tuntap_peer *tmp_uttp = uwsgi_tuntap_peer_get_by_addr(uttr, uttp->addr);
char ip[INET_ADDRSTRLEN + 1];
memset(ip, 0, INET_ADDRSTRLEN + 1);
if (!inet_ntop(AF_INET, &uttp->addr, ip, INET_ADDRSTRLEN)) {
uwsgi_error("uwsgi_tuntap_register_addr()/inet_ntop()");
return -1;
}
if (uttp != tmp_uttp) {
uwsgi_log("[tuntap-router] detected ip collision for %s\n", ip);
uwsgi_tuntap_peer_destroy(uttr, tmp_uttp);
}
uwsgi_log("[tuntap-router] registered new peer %s (fd: %d)\n", ip, uttp->fd);
memcpy(uttp->ip, ip, INET_ADDRSTRLEN + 1);
return 0;
}
// receive a packet from the client
int uwsgi_tuntap_peer_dequeue(struct uwsgi_tuntap_router *uttr, struct uwsgi_tuntap_peer *uttp, int is_router) {
// get body
@@ -192,19 +223,10 @@ int uwsgi_tuntap_peer_dequeue(struct uwsgi_tuntap_router *uttr, struct uwsgi_tun
if (!uttp->addr)
return -1;
struct uwsgi_tuntap_peer *tmp_uttp = uwsgi_tuntap_peer_get_by_addr(uttr, uttp->addr);
char ip[INET_ADDRSTRLEN + 1];
memset(ip, 0, INET_ADDRSTRLEN + 1);
if (!inet_ntop(AF_INET, &uttp->addr, ip, INET_ADDRSTRLEN)) {
uwsgi_error("inet_ntop()");
if (uwsgi_tuntap_register_addr(uttr, uttp)) {
return -1;
}
if (uttp != tmp_uttp) {
uwsgi_log("[tuntap-router] detected ip collision for %s\n", ip);
uwsgi_tuntap_peer_destroy(uttr, tmp_uttp);
}
uwsgi_log("[tuntap-router] registered new peer %s (fd: %d)\n", ip, uttp->fd);
memcpy(uttp->ip, ip, INET_ADDRSTRLEN + 1);
}
enqueue:
+8 -1
View File
@@ -33,6 +33,10 @@ struct uwsgi_tuntap_peer {
uint64_t tx;
uint64_t rx;
uint64_t dropped;
uint8_t sent_credentials;
pid_t pid;
uid_t uid;
gid_t gid;
};
struct uwsgi_tuntap_firewall_rule {
@@ -65,6 +69,8 @@ struct uwsgi_tuntap {
struct uwsgi_tuntap_firewall_rule *fw_in;
struct uwsgi_tuntap_firewall_rule *fw_out;
char *stats_server;
char *use_credentials;
uint32_t (*addr_by_credentials)(pid_t, uid_t, gid_t);
};
int uwsgi_tuntap_peer_dequeue(struct uwsgi_tuntap_router *, struct uwsgi_tuntap_peer *, int);
@@ -73,10 +79,11 @@ void uwsgi_tuntap_enqueue(struct uwsgi_tuntap_router *);
int uwsgi_tuntap_firewall_check(struct uwsgi_tuntap_firewall_rule *, char *, uint16_t);
struct uwsgi_tuntap_peer *uwsgi_tuntap_peer_create(struct uwsgi_tuntap_router *, int);
struct uwsgi_tuntap_peer *uwsgi_tuntap_peer_create(struct uwsgi_tuntap_router *, int, int);
struct uwsgi_tuntap_peer *uwsgi_tuntap_peer_get_by_addr(struct uwsgi_tuntap_router *,uint32_t);
void uwsgi_tuntap_peer_destroy(struct uwsgi_tuntap_router *, struct uwsgi_tuntap_peer *);
int uwsgi_tuntap_device(char *);
void uwsgi_tuntap_opt_firewall(char *, char *, void *);
int uwsgi_tuntap_register_addr(struct uwsgi_tuntap_router *, struct uwsgi_tuntap_peer *);
+46 -2
View File
@@ -59,6 +59,7 @@ struct uwsgi_tuntap utt;
static struct uwsgi_option uwsgi_tuntap_options[] = {
{"tuntap-router", required_argument, 0, "run the tuntap router (syntax: <device> <socket> [stats])", uwsgi_opt_add_string_list, &utt.routers, 0},
{"tuntap-device", required_argument, 0, "add a tuntap device to the instance (syntax: <device>[ <socket>])", uwsgi_opt_add_string_list, &utt.devices, 0},
{"tuntap-use-credentials", optional_argument, 0, "enable check of SCM_CREDENTIALS for tuntap client/server", uwsgi_opt_set_str, &utt.use_credentials, 0},
{"tuntap-router-firewall-in", required_argument, 0, "add a firewall rule to the tuntap router (syntax: <action> <src/mask> <dst/mask>)", uwsgi_tuntap_opt_firewall, &utt.fw_in, 0},
{"tuntap-router-firewall-out", required_argument, 0, "add a firewall rule to the tuntap router (syntax: <action> <src/mask> <dst/mask>)", uwsgi_tuntap_opt_firewall, &utt.fw_out, 0},
{"tuntap-router-stats", required_argument, 0, "run the tuntap router stats server", uwsgi_opt_set_str, &utt.stats_server, 0},
@@ -95,7 +96,7 @@ static void *uwsgi_tuntap_loop(void *arg) {
uwsgi_socket_nb(uttr->server_fd);
struct uwsgi_tuntap_peer *uttp = uwsgi_tuntap_peer_create(uttr, uttr->server_fd);
struct uwsgi_tuntap_peer *uttp = uwsgi_tuntap_peer_create(uttr, uttr->server_fd, 0);
for (;;) {
int interesting_fd = -1;
@@ -270,7 +271,13 @@ void uwsgi_tuntap_router_loop(int id, void *arg) {
uwsgi_error("uwsgi_tuntap_server_loop()/accept()");
continue;
}
struct uwsgi_tuntap_peer *uttp = uwsgi_tuntap_peer_create(uttr, client_fd);
if (utt.use_credentials) {
if (uwsgi_socket_passcred(client_fd)) {
close(client_fd);
continue;
}
}
struct uwsgi_tuntap_peer *uttp = uwsgi_tuntap_peer_create(uttr, client_fd, 1);
if (event_queue_add_fd_read(uttr->queue, uttp->fd)) {
uwsgi_tuntap_peer_destroy(uttr, uttp);
}
@@ -287,6 +294,33 @@ void uwsgi_tuntap_router_loop(int id, void *arg) {
if (interesting_fd == uttp->fd) {
// read from the client
if (event_queue_interesting_fd_is_read(events, i)) {
if (utt.use_credentials) {
if (uttp->addr == 0) {
if (!uttp->sent_credentials) {
if (uwsgi_recv_cred(uttp->fd, "uwsgi-tuntap", 12, &uttp->pid, &uttp->uid, &uttp->gid)) {
uwsgi_tuntap_peer_destroy(uttr, uttp);
break;
}
if (utt.addr_by_credentials) {
uttp->addr = utt.addr_by_credentials(uttp->pid, uttp->uid, uttp->gid);
if (!uttp->addr) {
uwsgi_tuntap_peer_destroy(uttr, uttp);
break;
}
if (uwsgi_tuntap_register_addr(uttr, uttp)) {
uwsgi_tuntap_peer_destroy(uttr, uttp);
break;
}
}
break;
}
else {
uwsgi_tuntap_peer_destroy(uttr, uttp);
break;
}
}
}
if (uwsgi_tuntap_peer_dequeue(uttr, uttp, 1)) {
uwsgi_tuntap_peer_destroy(uttr, uttp);
break;
@@ -319,6 +353,16 @@ static void uwsgi_tuntap_router() {
if (!utt.buffer_size)
utt.buffer_size = 8192;
if (utt.use_credentials) {
if (utt.use_credentials[0] != 0) {
utt.addr_by_credentials = (uint32_t (*)(pid_t, uid_t, gid_t)) dlsym(RTLD_DEFAULT, utt.use_credentials);
if (!utt.addr_by_credentials) {
uwsgi_log("[uwsgi-tuntap] unable to find symbol %s\n", utt.use_credentials);
exit(1);
}
}
}
struct uwsgi_string_list *usl;
uwsgi_foreach(usl, utt.routers) {
char *space = strchr(usl->value, ' ');