diff --git a/src/Makefile.am b/src/Makefile.am index ad455c9e..be2c14e7 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -5,9 +5,9 @@ EXTRA_DIST = ocserv.1 bin_PROGRAMS = ocserv -ocserv_SOURCES = main.c vpn.c http_auth.c tlslib.c cookies.c http-parser/http_parser.c \ - vpn.h auth.h cookies.h tlslib.h http-parser/http_parser.h log.c tun.c tun.h \ - config.c +ocserv_SOURCES = main.c worker-vpn.c worker-auth.c tlslib.c cookies.c http-parser/http_parser.c \ + vpn.h cookies.h tlslib.h http-parser/http_parser.h log.c tun.c tun.h \ + config.c worker-auth.h ocserv_SOURCES += ocserv-args.def ocserv-args.c ocserv-args.h diff --git a/src/config.c b/src/config.c index beb58abe..59e62b63 100644 --- a/src/config.c +++ b/src/config.c @@ -81,7 +81,6 @@ fprintf(stderr, "Configuration option %s is mandatory.\n", name); \ } - static void parse_cfg_file(const char* file, struct cfg_st *config) { tOptionValue const * pov; @@ -161,7 +160,25 @@ unsigned j; READ_STRING("ipv6-dns", config->network.ipv6_dns, 0); READ_MULTI_LINE("route", config->network.routes, config->network.routes_size, 0); +} +/* sanity checks on config */ +static void check_cfg( struct cfg_st *config) +{ + if (config->network.ipv4 == NULL && config->network.ipv6 == NULL) { + fprintf(stderr, "No ipv4-network or ipv6-network options set.\n"); + exit(1); + } + + if (config->network.ipv4 != NULL && config->network.ipv4_netmask == NULL) { + fprintf(stderr, "No mask found for IPv4 network.\n"); + exit(1); + } + + if (config->network.ipv6 != NULL && config->network.ipv6_netmask == NULL) { + fprintf(stderr, "No mask found for IPv6 network.\n"); + exit(1); + } } int cmd_parser (int argc, char **argv, struct cfg_st* config) @@ -184,6 +201,8 @@ int cmd_parser (int argc, char **argv, struct cfg_st* config) parse_cfg_file(cfg_file, config); + check_cfg(config); + return 0; } diff --git a/src/cookies.h b/src/cookies.h index 1b728633..1a30cad4 100644 --- a/src/cookies.h +++ b/src/cookies.h @@ -5,6 +5,7 @@ struct __attribute__ ((__packed__)) stored_cookie_st { char username[MAX_USERNAME_SIZE]; + char tun_name[IFNAMSIZ]; time_t expiration; }; diff --git a/src/http_auth.h b/src/http_auth.h deleted file mode 100644 index 57fb339c..00000000 --- a/src/http_auth.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef AUTH_H -#define AUTH_H - -int get_auth_handler(worker_st *server); -int post_old_auth_handler(worker_st *server); -int post_new_auth_handler(worker_st *server); - -#endif diff --git a/src/main.c b/src/main.c index 23c0d4f2..7b8dcfcc 100644 --- a/src/main.c +++ b/src/main.c @@ -34,6 +34,7 @@ #include #include +#include #include #include diff --git a/src/tun.c b/src/tun.c index f2ab8894..c2699e34 100644 --- a/src/tun.c +++ b/src/tun.c @@ -56,10 +56,6 @@ static int bignum_add1 (uint8_t * num, unsigned size) return 0; } -#define SA_IN_P(p) (&((struct sockaddr_in *)(p))->sin_addr) -#define SA_IN_U8_P(p) ((uint8_t*)(&((struct sockaddr_in *)(p))->sin_addr)) -#define SA_IN6_P(p) (&((struct sockaddr_in6 *)(p))->sin6_addr) -#define SA_IN6_U8_P(p) ((uint8_t*)(&((struct sockaddr_in6 *)(p))->sin6_addr)) static int get_avail_network_addresses(const struct cfg_st *config, const struct lease_st *last4, const struct lease_st *last6, struct lease_st* lease) { diff --git a/src/vpn.h b/src/vpn.h index ba517337..8510b2d9 100644 --- a/src/vpn.h +++ b/src/vpn.h @@ -1,5 +1,5 @@ -#ifndef SERVER_H -#define SERVER_H +#ifndef VPN_H +#define VPN_H #include #include @@ -105,29 +105,6 @@ struct req_data_st { unsigned int message_complete; }; -typedef enum { - AUTH_REQ = 1, - AUTH_REP = 2, -} cmd_request_t; - -typedef enum { - REP_AUTH_OK = 0, - REP_AUTH_FAILED = 1, -} cmd_auth_reply_t; - -struct cmd_auth_req_st { - uint8_t user_pass_present; - char user[MAX_USERNAME_SIZE]; - char pass[MAX_PASSWORD_SIZE]; - uint8_t tls_auth_ok; - char cert_user[MAX_USERNAME_SIZE]; -}; - -struct cmd_auth_resp_st { - uint8_t reply; - char vname[IFNAMSIZ]; /* interface name */ -}; - void vpn_server(struct worker_st* ws, struct tls_st *creds); const char *human_addr(const struct sockaddr *sa, socklen_t salen, @@ -138,4 +115,10 @@ int __attribute__ ((format(printf, 3, 4))) int cmd_parser (int argc, char **argv, struct cfg_st* config); +/* Helper casts */ +#define SA_IN_P(p) (&((struct sockaddr_in *)(p))->sin_addr) +#define SA_IN_U8_P(p) ((uint8_t*)(&((struct sockaddr_in *)(p))->sin_addr)) +#define SA_IN6_P(p) (&((struct sockaddr_in6 *)(p))->sin6_addr) +#define SA_IN6_U8_P(p) ((uint8_t*)(&((struct sockaddr_in6 *)(p))->sin6_addr)) + #endif diff --git a/src/http_auth.c b/src/worker-auth.c similarity index 98% rename from src/http_auth.c rename to src/worker-auth.c index 29bb2481..cec54ded 100644 --- a/src/http_auth.c +++ b/src/worker-auth.c @@ -34,7 +34,7 @@ #include #include -#include +#include #include #include @@ -152,7 +152,7 @@ static int recv_auth_reply(worker_st *ws) iov[1].iov_base = &resp.reply; iov[1].iov_len = 1; - iov[2].iov_base = &resp.vname; + iov[2].iov_base = resp.vname; iov[2].iov_len = sizeof(resp.vname); memset(&hdr, 0, sizeof(hdr)); @@ -315,6 +315,7 @@ struct cmd_auth_req_st areq; sc.expiration = time(0) + ws->config->cookie_validity; if (username) snprintf(sc.username, sizeof(sc.username), "%s", username); + memcpy(sc.tun_name, ws->tun_name, sizeof(sc.tun_name)); /* store cookie */ ret = store_cookie(ws, cookie, sizeof(cookie), &sc); @@ -432,6 +433,7 @@ struct cmd_auth_req_st areq; sc.expiration = time(0) + ws->config->cookie_validity; if (username) snprintf(sc.username, sizeof(sc.username), "%s", username); + memcpy(sc.tun_name, ws->tun_name, sizeof(sc.tun_name)); /* store cookie */ ret = store_cookie(ws, cookie, sizeof(cookie), &sc); diff --git a/src/vpn.c b/src/worker-vpn.c similarity index 90% rename from src/vpn.c rename to src/worker-vpn.c index 75d840ff..a31c5cb7 100644 --- a/src/vpn.c +++ b/src/worker-vpn.c @@ -38,7 +38,7 @@ #include #include -#include +#include #include #include @@ -305,14 +305,14 @@ finish: } /* if local is non zero it returns the local, otherwise the remote */ -static int get_ip(int fd, int family, unsigned int local, +static int get_ip(struct worker_st* ws, int fd, int family, unsigned int local, struct vpn_st* vinfo, char** buffer, size_t* buffer_size) { -unsigned char *ptr; -const char* p; +void* *ptr; +const void* p; struct ifreq ifr; unsigned int i, flags; -int ret; +int ret, e; memset(&ifr, 0, sizeof(ifr)); ifr.ifr_addr.sa_family = family; @@ -325,19 +325,24 @@ int ret; ret = ioctl(fd, flags, &ifr); if (ret != 0) { + e = errno; + oclog(ws, LOG_DEBUG, "ioctl error: %s", strerror(e)); goto fail; } if (family == AF_INET) { - ptr = (void*)&((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr; + ptr = SA_IN_P(&ifr.ifr_addr); } else if (family == AF_INET6) { - ptr = (void*)&((struct sockaddr_in6 *)&ifr.ifr_addr)->sin6_addr; + ptr = SA_IN6_P(&ifr.ifr_addr); } else { + oclog(ws, LOG_DEBUG, "Unknown family!"); return -1; } - p = inet_ntop(family, (void*)ptr, *buffer, *buffer_size); + p = inet_ntop(family, ptr, *buffer, *buffer_size); if (p == NULL) { + e = errno; + oclog(ws, LOG_DEBUG, "inet_ntop error: %s", strerror(e)); goto fail; } @@ -382,40 +387,42 @@ const char* p; return -1; /* get the remote IPs */ - ret = get_ip(fd, AF_INET6, 0, vinfo, &buffer, &buffer_size); + ret = get_ip(ws, fd, AF_INET6, 0, vinfo, &buffer, &buffer_size); if (ret < 0) - oclog(ws, LOG_INFO, "Cannot obtain IPv6 IP for %s\n", vinfo->name); + oclog(ws, LOG_DEBUG, "Cannot obtain IPv6 remote IP for %s\n", vinfo->name); - ret = get_ip(fd, AF_INET, 0, vinfo, &buffer, &buffer_size); + ret = get_ip(ws, fd, AF_INET, 0, vinfo, &buffer, &buffer_size); if (ret < 0) - oclog(ws, LOG_INFO, "Cannot obtain IPv4 IP for %s\n", vinfo->name); - - /* get the local IPs */ - ret = get_ip(fd, AF_INET6, 1, vinfo, &buffer, &buffer_size); - if (ret < 0) - oclog(ws, LOG_INFO, "Cannot obtain IPv6 local IP for %s\n", vinfo->name); - - ret = get_ip(fd, AF_INET, 1, vinfo, &buffer, &buffer_size); - if (ret < 0) - oclog(ws, LOG_INFO, "Cannot obtain IPv4 local IP for %s\n", vinfo->name); + oclog(ws, LOG_DEBUG, "Cannot obtain IPv4 remote IP for %s\n", vinfo->name); if (vinfo->ipv4 == NULL && vinfo->ipv6 == NULL) { ret = -1; goto fail; } - if (strcmp(vinfo->ipv4_dns, "local") == 0) + /* get the local IPs */ + ret = get_ip(ws, fd, AF_INET6, 1, vinfo, &buffer, &buffer_size); + if (ret < 0) + oclog(ws, LOG_DEBUG, "Cannot obtain IPv6 local IP for %s\n", vinfo->name); + + ret = get_ip(ws, fd, AF_INET, 1, vinfo, &buffer, &buffer_size); + if (ret < 0) + oclog(ws, LOG_DEBUG, "Cannot obtain IPv4 local IP for %s\n", vinfo->name); + + + if (vinfo->ipv4_dns && strcmp(vinfo->ipv4_dns, "local") == 0) vinfo->ipv4_dns = vinfo->ipv4_local; else vinfo->ipv4_dns = ws->config->network.ipv4_dns; - if (strcmp(vinfo->ipv6_dns, "local") == 0) + if (vinfo->ipv6_dns && strcmp(vinfo->ipv6_dns, "local") == 0) vinfo->ipv6_dns = vinfo->ipv6_local; else vinfo->ipv6_dns = ws->config->network.ipv6_dns; vinfo->routes_size = ws->config->network.routes_size; - memcpy(vinfo->routes, ws->config->network.routes, sizeof(vinfo->routes)); + if (ws->config->network.routes_size > 0) + vinfo->routes = ws->config->network.routes; vinfo->ipv4_netmask = ws->config->network.ipv4_netmask; vinfo->ipv6_netmask = ws->config->network.ipv6_netmask; @@ -447,11 +454,11 @@ int l, pktlen; int tls_fd, max; unsigned i; struct stored_cookie_st sc; -unsigned int tun_nr = 0; struct vpn_st vinfo; char* buffer; unsigned int buffer_size; + if (req->cookie_set == 0) { oclog(ws, LOG_INFO, "Connect request without authentication"); tls_puts(ws->session, "HTTP/1.1 503 Service Unavailable\r\n\r\n"); @@ -466,6 +473,7 @@ unsigned int buffer_size; tls_fatal_close(ws->session, GNUTLS_A_ACCESS_DENIED); exit(1); } + memcpy(ws->tun_name, sc.tun_name, sizeof(ws->tun_name)); if (strcmp(req->url, "/CSCOSSLC/tunnel") != 0) { oclog(ws, LOG_INFO, "Bad connect request: '%s'\n", req->url); @@ -481,7 +489,7 @@ unsigned int buffer_size; return -1; } - oclog(ws, LOG_INFO, "Connected\n"); + oclog(ws, LOG_INFO, "User '%s' connected.\n", sc.username); buffer_size = 2048; buffer = malloc(buffer_size);