mirror of
https://gitlab.com/openconnect/ocserv.git
synced 2026-02-09 16:26:59 +08:00
Do not let scripts block the server operation.
This commit is contained in:
@@ -266,6 +266,13 @@ static void check_cfg( struct cfg_st *config)
|
||||
else
|
||||
config->cert_req = GNUTLS_CERT_REQUEST;
|
||||
}
|
||||
|
||||
if (config->plain_passwd != NULL) {
|
||||
if (access(config->plain_passwd, R_OK) != 0) {
|
||||
fprintf(stderr, "cannot access password file %s\n", config->plain_passwd);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef ANYCONNECT_CLIENT_COMPAT
|
||||
if (config->cert) {
|
||||
|
||||
21
src/log.c
21
src/log.c
@@ -122,3 +122,24 @@ void __attribute__ ((format(printf, 4, 5)))
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void mslog_hex(const main_server_st * s, const struct proc_st* proc,
|
||||
int priority, const char *prefix, uint8_t* bin, unsigned bin_size)
|
||||
{
|
||||
char buf[512];
|
||||
int ret;
|
||||
size_t buf_size;
|
||||
gnutls_datum_t data = {bin, bin_size};
|
||||
|
||||
if (priority == LOG_DEBUG && s->config->debug == 0)
|
||||
return;
|
||||
|
||||
buf_size = sizeof(buf);
|
||||
ret = gnutls_hex_encode(&data, buf, &buf_size);
|
||||
if (ret < 0)
|
||||
return;
|
||||
|
||||
mslog(s, proc, priority, "%s %s", prefix, buf);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
#include "plain.h"
|
||||
|
||||
int send_auth_reply(main_server_st* s, struct proc_st* proc,
|
||||
cmd_auth_reply_t r, struct lease_st* lease)
|
||||
cmd_auth_reply_t r)
|
||||
{
|
||||
struct iovec iov[2];
|
||||
uint8_t cmd[2];
|
||||
@@ -62,7 +62,7 @@ int send_auth_reply(main_server_st* s, struct proc_st* proc,
|
||||
|
||||
hdr.msg_iov = iov;
|
||||
|
||||
if (r == REP_AUTH_OK && lease != NULL) {
|
||||
if (r == REP_AUTH_OK && proc->lease != NULL) {
|
||||
cmd[0] = AUTH_REP;
|
||||
|
||||
iov[0].iov_base = cmd;
|
||||
@@ -72,7 +72,7 @@ int send_auth_reply(main_server_st* s, struct proc_st* proc,
|
||||
resp.reply = r;
|
||||
memcpy(resp.cookie, proc->cookie, COOKIE_SIZE);
|
||||
memcpy(resp.session_id, proc->session_id, sizeof(resp.session_id));
|
||||
memcpy(resp.vname, lease->name, sizeof(resp.vname));
|
||||
memcpy(resp.vname, proc->lease->name, sizeof(resp.vname));
|
||||
memcpy(resp.user, proc->username, sizeof(resp.user));
|
||||
|
||||
iov[1].iov_base = &resp;
|
||||
@@ -87,7 +87,7 @@ int send_auth_reply(main_server_st* s, struct proc_st* proc,
|
||||
cmptr->cmsg_len = CMSG_LEN(sizeof(int));
|
||||
cmptr->cmsg_level = SOL_SOCKET;
|
||||
cmptr->cmsg_type = SCM_RIGHTS;
|
||||
memcpy(CMSG_DATA(cmptr), &lease->fd, sizeof(int));
|
||||
memcpy(CMSG_DATA(cmptr), &proc->lease->fd, sizeof(int));
|
||||
} else {
|
||||
cmd[0] = AUTH_REP;
|
||||
cmd[1] = REP_AUTH_FAILED;
|
||||
@@ -101,7 +101,7 @@ int send_auth_reply(main_server_st* s, struct proc_st* proc,
|
||||
}
|
||||
|
||||
int handle_auth_cookie_req(main_server_st* s, struct proc_st* proc,
|
||||
const struct cmd_auth_cookie_req_st * req, struct lease_st **lease)
|
||||
const struct cmd_auth_cookie_req_st * req)
|
||||
{
|
||||
int ret;
|
||||
struct stored_cookie_st *sc;
|
||||
@@ -146,7 +146,7 @@ time_t now = time(0);
|
||||
}
|
||||
}
|
||||
|
||||
ret = open_tun(s, lease);
|
||||
ret = open_tun(s, &proc->lease);
|
||||
if (ret < 0) {
|
||||
ret = -1; /* sorry */
|
||||
goto cleanup;
|
||||
@@ -177,7 +177,7 @@ struct stored_cookie_st *sc;
|
||||
ret = gnutls_rnd(GNUTLS_RND_NONCE, proc->session_id, sizeof(proc->session_id));
|
||||
if (ret < 0)
|
||||
return -2;
|
||||
proc->session_id_size = sizeof( proc->session_id);
|
||||
proc->session_id_size = sizeof(proc->session_id);
|
||||
|
||||
sc = calloc(1, sizeof(*sc));
|
||||
if (sc == NULL)
|
||||
@@ -202,7 +202,7 @@ struct stored_cookie_st *sc;
|
||||
}
|
||||
|
||||
int handle_auth_req(main_server_st *s, struct proc_st* proc,
|
||||
const struct cmd_auth_req_st * req, struct lease_st **lease)
|
||||
const struct cmd_auth_req_st * req)
|
||||
{
|
||||
int ret = -1;
|
||||
unsigned username_set = 0;
|
||||
@@ -256,7 +256,7 @@ unsigned username_set = 0;
|
||||
proc->groupname[sizeof(proc->groupname)-1] = 0;
|
||||
proc->hostname[sizeof(proc->hostname)-1] = 0;
|
||||
|
||||
ret = open_tun(s, lease);
|
||||
ret = open_tun(s, &proc->lease);
|
||||
if (ret < 0)
|
||||
ret = -1; /* sorry */
|
||||
}
|
||||
|
||||
138
src/main-misc.c
138
src/main-misc.c
@@ -108,12 +108,47 @@ int send_udp_fd(main_server_st* s, struct proc_st * proc, int fd)
|
||||
return(sendmsg(proc->fd, &hdr, 0));
|
||||
}
|
||||
|
||||
int handle_script_exit(main_server_st *s, struct proc_st* proc, int code)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (code == 0) {
|
||||
ret = send_auth_reply(s, proc, REP_AUTH_OK);
|
||||
if (ret < 0) {
|
||||
mslog(s, proc, LOG_ERR, "could not send reply auth cmd.");
|
||||
ret = ERR_BAD_COMMAND;
|
||||
goto fail;
|
||||
}
|
||||
} else {
|
||||
mslog(s, proc, LOG_INFO, "failed authentication attempt for user '%s'", proc->username);
|
||||
ret = send_auth_reply( s, proc, REP_AUTH_FAILED);
|
||||
if (ret < 0) {
|
||||
mslog(s, proc, LOG_ERR, "could not send reply auth cmd.");
|
||||
ret = ERR_BAD_COMMAND;
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
ret = 0;
|
||||
|
||||
fail:
|
||||
/* we close the lease tun fd both on success and failure.
|
||||
* The parent doesn't need to keep the tunfd.
|
||||
*/
|
||||
if (proc->lease) {
|
||||
if (proc->lease->fd >= 0)
|
||||
close(proc->lease->fd);
|
||||
proc->lease->fd = -1;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int handle_commands(main_server_st *s, struct proc_st* proc)
|
||||
{
|
||||
struct iovec iov[2];
|
||||
uint8_t cmd;
|
||||
struct msghdr hdr;
|
||||
struct lease_st *lease;
|
||||
union {
|
||||
struct cmd_auth_req_st auth;
|
||||
struct cmd_auth_cookie_req_st cauth;
|
||||
@@ -153,16 +188,15 @@ int handle_commands(main_server_st *s, struct proc_st* proc)
|
||||
case CMD_TUN_MTU:
|
||||
if (cmd_data_len != sizeof(cmd_data.tmtu)) {
|
||||
mslog(s, proc, LOG_ERR, "error in received message (cmd %u) length.", (unsigned)cmd);
|
||||
return -2;
|
||||
return ERR_BAD_COMMAND;
|
||||
}
|
||||
|
||||
set_tun_mtu(s, proc, cmd_data.tmtu.mtu);
|
||||
break;
|
||||
|
||||
case RESUME_STORE_REQ:
|
||||
if (cmd_data_len <= sizeof(cmd_data.sresume)-MAX_SESSION_DATA_SIZE) {
|
||||
mslog(s, proc, LOG_ERR, "error in received message (cmd %u) length.", (unsigned)cmd);
|
||||
return -2;
|
||||
return ERR_BAD_COMMAND;
|
||||
}
|
||||
ret = handle_resume_store_req(s, proc, &cmd_data.sresume);
|
||||
if (ret < 0) {
|
||||
@@ -174,7 +208,7 @@ int handle_commands(main_server_st *s, struct proc_st* proc)
|
||||
case RESUME_DELETE_REQ:
|
||||
if (cmd_data_len != sizeof(cmd_data.fresume)) {
|
||||
mslog(s, proc, LOG_ERR, "error in received message (cmd %u) length.", (unsigned)cmd);
|
||||
return -2;
|
||||
return ERR_BAD_COMMAND;
|
||||
}
|
||||
ret = handle_resume_delete_req(s, proc, &cmd_data.fresume);
|
||||
if (ret < 0) {
|
||||
@@ -187,7 +221,7 @@ int handle_commands(main_server_st *s, struct proc_st* proc)
|
||||
|
||||
if (cmd_data_len != sizeof(cmd_data.fresume)) {
|
||||
mslog(s, proc, LOG_ERR, "error in received message (%u) length.", (unsigned)cmd);
|
||||
return -2;
|
||||
return ERR_BAD_COMMAND;
|
||||
}
|
||||
ret = handle_resume_fetch_req(s, proc, &cmd_data.fresume, &reply);
|
||||
if (ret < 0) {
|
||||
@@ -199,29 +233,27 @@ int handle_commands(main_server_st *s, struct proc_st* proc)
|
||||
|
||||
if (ret < 0) {
|
||||
mslog(s, proc, LOG_ERR, "could not send reply cmd %d.", (unsigned) cmd);
|
||||
return -2;
|
||||
return ERR_BAD_COMMAND;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case AUTH_REQ:
|
||||
case AUTH_COOKIE_REQ:
|
||||
lease = NULL;
|
||||
|
||||
if (cmd == AUTH_REQ) {
|
||||
if (cmd_data_len != sizeof(cmd_data.auth)) {
|
||||
mslog(s, proc, LOG_ERR, "error in received message (%u) length.", (unsigned)cmd);
|
||||
return -2;
|
||||
return ERR_BAD_COMMAND;
|
||||
}
|
||||
|
||||
ret = handle_auth_req(s, proc, &cmd_data.auth, &lease);
|
||||
ret = handle_auth_req(s, proc, &cmd_data.auth);
|
||||
} else {
|
||||
if (cmd_data_len != sizeof(cmd_data.cauth)) {
|
||||
mslog(s, proc, LOG_ERR, "error in received message (%u) length.", (unsigned)cmd);
|
||||
return -2;
|
||||
return ERR_BAD_COMMAND;
|
||||
}
|
||||
|
||||
ret = handle_auth_cookie_req(s, proc, &cmd_data.cauth, &lease);
|
||||
ret = handle_auth_cookie_req(s, proc, &cmd_data.cauth);
|
||||
}
|
||||
|
||||
if (ret == 0) {
|
||||
@@ -231,9 +263,32 @@ int handle_commands(main_server_st *s, struct proc_st* proc)
|
||||
mslog(s, proc, LOG_INFO, "user '%s' tried to connect more than %u times", proc->username, s->config->max_same_clients);
|
||||
}
|
||||
|
||||
if (ret == 0) {
|
||||
if (proc->groupname[0] == 0)
|
||||
group = "[unknown]";
|
||||
else
|
||||
group = proc->groupname;
|
||||
|
||||
if (cmd == AUTH_REQ) {
|
||||
/* generate and store cookie */
|
||||
ret = generate_and_store_vals(s, proc);
|
||||
if (ret < 0) {
|
||||
ret = ERR_BAD_COMMAND;
|
||||
goto cleanup;
|
||||
}
|
||||
mslog(s, proc, LOG_INFO, "user '%s' of group '%s' authenticated", proc->username, group);
|
||||
} else {
|
||||
mslog(s, proc, LOG_INFO, "user '%s' of group '%s' re-authenticated (using cookie)", proc->username, group);
|
||||
}
|
||||
}
|
||||
|
||||
/* do scripts and utmp */
|
||||
if (ret == 0) {
|
||||
ret = user_connected(s, proc, lease);
|
||||
ret = user_connected(s, proc);
|
||||
if (ret == ERR_WAIT_FOR_SCRIPT) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ret < 0) {
|
||||
mslog(s, proc, LOG_INFO, "user '%s' disconnected due to script", proc->username);
|
||||
}
|
||||
@@ -242,60 +297,13 @@ int handle_commands(main_server_st *s, struct proc_st* proc)
|
||||
add_to_ip_ban_list(s, &proc->remote_addr, proc->remote_addr_len);
|
||||
}
|
||||
|
||||
if (ret == 0) {
|
||||
if (proc->groupname[0] == 0)
|
||||
group = "[unknown]";
|
||||
else
|
||||
group = proc->groupname;
|
||||
cleanup:
|
||||
/* no script was called. Handle it as a successful script call. */
|
||||
return handle_script_exit(s, proc, ret);
|
||||
|
||||
if (cmd == AUTH_REQ) {
|
||||
/* generate and store cookie */
|
||||
ret = generate_and_store_vals(s, proc);
|
||||
if (ret < 0) {
|
||||
ret = -2;
|
||||
goto lease_cleanup;
|
||||
}
|
||||
mslog(s, proc, LOG_INFO, "user '%s' of group '%s' authenticated", proc->username, group);
|
||||
} else {
|
||||
mslog(s, proc, LOG_INFO, "user '%s' of group '%s' re-authenticated (using cookie)", proc->username, group);
|
||||
}
|
||||
|
||||
ret = send_auth_reply(s, proc, REP_AUTH_OK, lease);
|
||||
if (ret < 0) {
|
||||
mslog(s, proc, LOG_ERR, "could not send reply cmd %d.", (unsigned)cmd);
|
||||
ret = -2;
|
||||
goto lease_cleanup;
|
||||
}
|
||||
|
||||
proc->lease = lease;
|
||||
proc->lease->in_use = 1;
|
||||
ret = 0;
|
||||
} else {
|
||||
mslog(s, proc, LOG_INFO, "failed authentication attempt for user '%s'", proc->username);
|
||||
ret = send_auth_reply( s, proc, REP_AUTH_FAILED, NULL);
|
||||
if (ret < 0) {
|
||||
mslog(s, proc, LOG_ERR, "could not send reply cmd.");
|
||||
ret = -2;
|
||||
goto lease_cleanup;
|
||||
}
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
lease_cleanup:
|
||||
/* we close the lease tun fd both on success and failure.
|
||||
* The parent doesn't need to know the tunfd.
|
||||
*/
|
||||
if (lease) {
|
||||
if (lease->fd >= 0)
|
||||
close(lease->fd);
|
||||
lease->fd = -1;
|
||||
}
|
||||
return ret;
|
||||
|
||||
break;
|
||||
default:
|
||||
mslog(s, proc, LOG_ERR, "unknown CMD 0x%x.", (unsigned)cmd);
|
||||
return -2;
|
||||
return ERR_BAD_COMMAND;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -43,14 +43,14 @@
|
||||
#include <cookies.h>
|
||||
#include <tun.h>
|
||||
#include <main.h>
|
||||
#include <script-list.h>
|
||||
#include <ccan/list/list.h>
|
||||
|
||||
static
|
||||
int call_script(main_server_st *s, struct proc_st* proc, struct lease_st* lease, unsigned up)
|
||||
int call_script(main_server_st *s, struct proc_st* proc, unsigned up)
|
||||
{
|
||||
pid_t pid;
|
||||
int ret, status;
|
||||
unsigned estatus;
|
||||
int ret;
|
||||
const char* script;
|
||||
|
||||
if (up != 0)
|
||||
@@ -67,34 +67,36 @@ const char* script;
|
||||
char local[64];
|
||||
char remote[64];
|
||||
|
||||
/* Note we don't use proc->lease and accept lease directly
|
||||
* because we are called before proc population is completed */
|
||||
if (getnameinfo((void*)&proc->remote_addr, proc->remote_addr_len, real, sizeof(real), NULL, 0, NI_NUMERICHOST) != 0)
|
||||
exit(1);
|
||||
|
||||
if (lease->lip4_len > 0) {
|
||||
if (getnameinfo((void*)&lease->lip4, lease->lip4_len, local, sizeof(local), NULL, 0, NI_NUMERICHOST) != 0)
|
||||
if (proc->lease->lip4_len > 0) {
|
||||
if (getnameinfo((void*)&proc->lease->lip4, proc->lease->lip4_len, local, sizeof(local), NULL, 0, NI_NUMERICHOST) != 0)
|
||||
exit(1);
|
||||
} else {
|
||||
if (getnameinfo((void*)&lease->lip6, lease->lip6_len, local, sizeof(local), NULL, 0, NI_NUMERICHOST) != 0)
|
||||
if (getnameinfo((void*)&proc->lease->lip6, proc->lease->lip6_len, local, sizeof(local), NULL, 0, NI_NUMERICHOST) != 0)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (lease->rip4_len > 0) {
|
||||
if (getnameinfo((void*)&lease->rip4, lease->rip4_len, remote, sizeof(remote), NULL, 0, NI_NUMERICHOST) != 0)
|
||||
if (proc->lease->rip4_len > 0) {
|
||||
if (getnameinfo((void*)&proc->lease->rip4, proc->lease->rip4_len, remote, sizeof(remote), NULL, 0, NI_NUMERICHOST) != 0)
|
||||
exit(1);
|
||||
} else {
|
||||
if (getnameinfo((void*)&lease->rip6, lease->rip6_len, remote, sizeof(remote), NULL, 0, NI_NUMERICHOST) != 0)
|
||||
if (getnameinfo((void*)&proc->lease->rip6, proc->lease->rip6_len, remote, sizeof(remote), NULL, 0, NI_NUMERICHOST) != 0)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
setenv("USERNAME", proc->username, 1);
|
||||
setenv("GROUPNAME", proc->groupname, 1);
|
||||
setenv("HOSTNAME", proc->hostname, 1);
|
||||
setenv("DEVICE", lease->name, 1);
|
||||
setenv("DEVICE", proc->lease->name, 1);
|
||||
setenv("IP_REAL", real, 1);
|
||||
setenv("IP_LOCAL", local, 1);
|
||||
setenv("IP_REMOTE", remote, 1);
|
||||
if (up)
|
||||
setenv("REASON", "connect", 1);
|
||||
else
|
||||
setenv("REASON", "disconnect", 1);
|
||||
|
||||
mslog(s, proc, LOG_DEBUG, "executing script %s", script);
|
||||
ret = execl(script, script, NULL);
|
||||
@@ -109,21 +111,16 @@ const char* script;
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = waitpid(pid, &status, 0);
|
||||
estatus = WEXITSTATUS(status);
|
||||
mslog(s, proc, LOG_DEBUG, "%s-script exit status: %u", (up!=0)?"connect":"disconnect", estatus);
|
||||
|
||||
if (estatus == 0) {
|
||||
return 0;
|
||||
if (up) {
|
||||
add_to_script_list(s, pid, up, proc);
|
||||
return ERR_WAIT_FOR_SCRIPT;
|
||||
} else {
|
||||
if (WIFSIGNALED(status))
|
||||
mslog(s, proc, LOG_DEBUG, "%s-script exit due to signal", (up!=0)?"connect":"disconnect");
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
add_utmp_entry(main_server_st *s, struct proc_st* proc, struct lease_st* lease)
|
||||
add_utmp_entry(main_server_st *s, struct proc_st* proc)
|
||||
{
|
||||
#ifdef HAVE_LIBUTIL
|
||||
struct utmpx entry;
|
||||
@@ -135,7 +132,7 @@ add_utmp_entry(main_server_st *s, struct proc_st* proc, struct lease_st* lease)
|
||||
memset(&entry, 0, sizeof(entry));
|
||||
entry.ut_type = USER_PROCESS;
|
||||
entry.ut_pid = proc->pid;
|
||||
snprintf(entry.ut_line, sizeof(entry.ut_line), "%s", lease->name);
|
||||
snprintf(entry.ut_line, sizeof(entry.ut_line), "%s", proc->lease->name);
|
||||
snprintf(entry.ut_user, sizeof(entry.ut_user), "%s", proc->username);
|
||||
if (proc->remote_addr_len == sizeof(struct sockaddr_in))
|
||||
memcpy(entry.ut_addr_v6, SA_IN_P(&proc->remote_addr), sizeof(struct in_addr));
|
||||
@@ -188,13 +185,13 @@ static void remove_utmp_entry(main_server_st *s, struct proc_st* proc)
|
||||
#endif
|
||||
}
|
||||
|
||||
int user_connected(main_server_st *s, struct proc_st* proc, struct lease_st* lease)
|
||||
int user_connected(main_server_st *s, struct proc_st* proc)
|
||||
{
|
||||
int ret;
|
||||
|
||||
add_utmp_entry(s, proc, lease);
|
||||
add_utmp_entry(s, proc);
|
||||
|
||||
ret = call_script(s, proc, lease, 1);
|
||||
ret = call_script(s, proc, 1);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
@@ -204,6 +201,6 @@ int ret;
|
||||
void user_disconnected(main_server_st *s, struct proc_st* proc)
|
||||
{
|
||||
remove_utmp_entry(s, proc);
|
||||
call_script(s, proc, proc->lease, 0);
|
||||
call_script(s, proc, 0);
|
||||
}
|
||||
|
||||
|
||||
95
src/main.c
95
src/main.c
@@ -32,6 +32,7 @@
|
||||
#include <errno.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <cloexec.h>
|
||||
#include <script-list.h>
|
||||
|
||||
#include <gnutls/x509.h>
|
||||
#include <tlslib.h>
|
||||
@@ -285,14 +286,48 @@ int s, y, e;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void remove_proc(main_server_st* s, struct proc_st *proc, unsigned k)
|
||||
{
|
||||
if (k)
|
||||
kill(proc->pid, SIGTERM);
|
||||
|
||||
user_disconnected(s, proc);
|
||||
|
||||
/* close the intercomm fd */
|
||||
if (proc->fd >= 0)
|
||||
close(proc->fd);
|
||||
proc->fd = -1;
|
||||
proc->pid = -1;
|
||||
|
||||
if (proc->lease)
|
||||
proc->lease->in_use = 0;
|
||||
list_del(&proc->list);
|
||||
free(proc);
|
||||
}
|
||||
|
||||
static void cleanup_children(main_server_st *s)
|
||||
{
|
||||
int status;
|
||||
int status, estatus, ret;
|
||||
pid_t pid;
|
||||
struct script_wait_st *stmp, *spos;
|
||||
|
||||
while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
|
||||
if (WEXITSTATUS(status) != 0 ||
|
||||
estatus = WEXITSTATUS(status);
|
||||
|
||||
/* check if someone was waiting for that pid */
|
||||
list_for_each_safe(&s->script_list.head, stmp, spos, list) {
|
||||
if (stmp->pid == pid) {
|
||||
mslog(s, stmp->proc, LOG_DEBUG, "%s-script exit status: %u", stmp->up?"connect":"disconnect", estatus);
|
||||
ret = handle_script_exit(s, stmp->proc, estatus);
|
||||
if (ret < 0)
|
||||
remove_proc(s, stmp->proc, 0);
|
||||
list_del(&stmp->list);
|
||||
free(stmp);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (estatus != 0 ||
|
||||
(WIFSIGNALED(status) && WTERMSIG(status) == SIGSEGV)) {
|
||||
if (WIFSIGNALED(status))
|
||||
mslog(s, NULL, LOG_ERR, "Child %u died with sigsegv\n", (unsigned)pid);
|
||||
@@ -311,8 +346,6 @@ static void handle_alarm(int signo)
|
||||
need_maintainance = 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void drop_privileges(main_server_st* s)
|
||||
{
|
||||
int ret, e;
|
||||
@@ -357,6 +390,7 @@ void clear_lists(main_server_st *s)
|
||||
{
|
||||
struct listener_st *ltmp, *lpos;
|
||||
struct proc_st *ctmp, *cpos;
|
||||
struct script_wait_st *script_tmp, *script_pos;
|
||||
struct banned_st *btmp, *bpos;
|
||||
|
||||
list_for_each_safe(&s->llist.head, ltmp, lpos, list) {
|
||||
@@ -379,6 +413,11 @@ void clear_lists(main_server_st *s)
|
||||
free(btmp);
|
||||
}
|
||||
|
||||
list_for_each_safe(&s->script_list.head, script_tmp, script_pos, list) {
|
||||
list_del(&script_tmp->list);
|
||||
free(script_tmp);
|
||||
}
|
||||
|
||||
tls_cache_deinit(s->tls_db);
|
||||
}
|
||||
|
||||
@@ -394,20 +433,6 @@ static void kill_children(main_server_st* s)
|
||||
}
|
||||
}
|
||||
|
||||
static void remove_proc(struct proc_st *ctmp)
|
||||
{
|
||||
/* close the intercomm fd */
|
||||
if (ctmp->fd >= 0)
|
||||
close(ctmp->fd);
|
||||
ctmp->fd = -1;
|
||||
ctmp->pid = -1;
|
||||
|
||||
if (ctmp->lease)
|
||||
ctmp->lease->in_use = 0;
|
||||
list_del(&ctmp->list);
|
||||
free(ctmp);
|
||||
}
|
||||
|
||||
static void handle_term(int signo)
|
||||
{
|
||||
/* kill all children */
|
||||
@@ -438,7 +463,7 @@ int connected = 0;
|
||||
cli_addr_size = sizeof(cli_addr);
|
||||
ret = recvfrom(listener->fd, buffer, sizeof(buffer), MSG_PEEK, (void*)&cli_addr, &cli_addr_size);
|
||||
if (ret < 0) {
|
||||
mslog(s, NULL, LOG_INFO, "Error receiving in UDP socket");
|
||||
mslog(s, NULL, LOG_INFO, "error receiving in UDP socket");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -453,11 +478,11 @@ int connected = 0;
|
||||
mslog(s, NULL, LOG_DEBUG, "DTLS hello version: %u.%u", (unsigned int)buffer[RECORD_PAYLOAD_POS], (unsigned int)buffer[RECORD_PAYLOAD_POS+1]);
|
||||
if (buffer[1] != 254 && (buffer[1] != 1 && buffer[2] != 0) &&
|
||||
buffer[RECORD_PAYLOAD_POS] != 254 && (buffer[RECORD_PAYLOAD_POS] != 0 && buffer[RECORD_PAYLOAD_POS+1] != 0)) {
|
||||
mslog(s, NULL, LOG_INFO, "Unknown DTLS version: %u.%u", (unsigned)buffer[1], (unsigned)buffer[2]);
|
||||
mslog(s, NULL, LOG_INFO, "unknown DTLS version: %u.%u", (unsigned)buffer[1], (unsigned)buffer[2]);
|
||||
goto fail;
|
||||
}
|
||||
if (buffer[0] != 22) {
|
||||
mslog(s, NULL, LOG_INFO, "Unexpected DTLS content type: %u", (unsigned int)buffer[0]);
|
||||
mslog(s, NULL, LOG_INFO, "unexpected DTLS content type: %u", (unsigned int)buffer[0]);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@@ -466,8 +491,8 @@ int connected = 0;
|
||||
session_id = &buffer[RECORD_PAYLOAD_POS+HANDSHAKE_SESSION_ID_POS+1];
|
||||
|
||||
/* search for the IP and the session ID in all procs */
|
||||
list_for_each(&s->clist.head, ctmp, list) {
|
||||
|
||||
list_for_each(&s->clist.head, ctmp, list) {
|
||||
if (session_id_size == ctmp->session_id_size &&
|
||||
memcmp(session_id, ctmp->session_id, session_id_size) == 0) {
|
||||
|
||||
@@ -480,15 +505,14 @@ int connected = 0;
|
||||
|
||||
ret = send_udp_fd(s, ctmp, listener->fd);
|
||||
if (ret < 0) {
|
||||
mslog(s, ctmp, LOG_ERR, "Error passing UDP socket");
|
||||
mslog(s, ctmp, LOG_ERR, "error passing UDP socket");
|
||||
return -1;
|
||||
}
|
||||
mslog(s, ctmp, LOG_DEBUG, "Passed UDP socket");
|
||||
mslog(s, ctmp, LOG_DEBUG, "passed UDP socket");
|
||||
ctmp->udp_fd_received = 1;
|
||||
connected = 1;
|
||||
|
||||
reopen_udp_port(listener);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -569,13 +593,14 @@ int main(int argc, char** argv)
|
||||
int cmd_fd[2];
|
||||
struct worker_st ws;
|
||||
struct cfg_st config;
|
||||
unsigned active_clients = 0, set;
|
||||
unsigned set;
|
||||
main_server_st s;
|
||||
|
||||
memset(&s, 0, sizeof(s));
|
||||
|
||||
list_head_init(&s.clist.head);
|
||||
list_head_init(&s.ban_list.head);
|
||||
list_head_init(&s.script_list.head);
|
||||
tun_st_init(&tun);
|
||||
tls_cache_init(&s.tls_db);
|
||||
|
||||
@@ -711,9 +736,9 @@ int main(int argc, char** argv)
|
||||
break;
|
||||
}
|
||||
|
||||
if (config.max_clients > 0 && active_clients >= config.max_clients) {
|
||||
if (config.max_clients > 0 && s.active_clients >= config.max_clients) {
|
||||
close(fd);
|
||||
mslog(&s, NULL, LOG_INFO, "Reached maximum client limit (active: %u)", active_clients);
|
||||
mslog(&s, NULL, LOG_INFO, "Reached maximum client limit (active: %u)", s.active_clients);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -762,6 +787,7 @@ int main(int argc, char** argv)
|
||||
fork_failed:
|
||||
close(cmd_fd[0]);
|
||||
} else { /* parent */
|
||||
/* add_proc */
|
||||
ctmp = calloc(1, sizeof(struct proc_st));
|
||||
if (ctmp == NULL) {
|
||||
kill(pid, SIGTERM);
|
||||
@@ -775,7 +801,7 @@ fork_failed:
|
||||
set_cloexec_flag (cmd_fd[0], 1);
|
||||
|
||||
list_add(&s.clist.head, &(ctmp->list));
|
||||
active_clients++;
|
||||
s.active_clients++;
|
||||
}
|
||||
close(cmd_fd[1]);
|
||||
close(fd);
|
||||
@@ -786,7 +812,7 @@ fork_failed:
|
||||
/* connection on UDP port */
|
||||
ret = forward_udp_to_owner(&s, ltmp);
|
||||
if (ret < 0) {
|
||||
mslog(&s, NULL, LOG_INFO, "Could not determine the owner of received UDP packet");
|
||||
mslog(&s, NULL, LOG_INFO, "could not determine the owner of received UDP packet");
|
||||
}
|
||||
|
||||
if (config.rate_limit_ms > 0)
|
||||
@@ -799,13 +825,8 @@ fork_failed:
|
||||
if (FD_ISSET(ctmp->fd, &rd)) {
|
||||
ret = handle_commands(&s, ctmp);
|
||||
if (ret < 0) {
|
||||
if (ret == -2) {
|
||||
/* received a bad command from worker */
|
||||
kill(ctmp->pid, SIGTERM);
|
||||
}
|
||||
user_disconnected(&s, ctmp);
|
||||
remove_proc(ctmp);
|
||||
active_clients--;
|
||||
remove_from_script_list(&s, ctmp);
|
||||
remove_proc(&s, ctmp, (ret==ERR_BAD_COMMAND)?1:0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
32
src/main.h
32
src/main.h
@@ -9,6 +9,9 @@
|
||||
#include <tlslib.h>
|
||||
#include "ipc.h"
|
||||
|
||||
#define ERR_WAIT_FOR_SCRIPT -5
|
||||
#define ERR_BAD_COMMAND -2
|
||||
|
||||
int cmd_parser (int argc, char **argv, struct cfg_st* config);
|
||||
void reload_cfg_file(struct cfg_st* config);
|
||||
void write_pid_file(void);
|
||||
@@ -32,12 +35,20 @@ struct listen_list_st {
|
||||
unsigned int total;
|
||||
};
|
||||
|
||||
struct script_wait_st {
|
||||
struct list_node list;
|
||||
|
||||
pid_t pid;
|
||||
unsigned int up; /* connect or disconnect script */
|
||||
struct proc_st* proc;
|
||||
};
|
||||
|
||||
struct proc_st {
|
||||
struct list_node list;
|
||||
int fd;
|
||||
pid_t pid;
|
||||
unsigned udp_fd_received; /* if the corresponding process has received a UDP fd */
|
||||
|
||||
|
||||
/* the tun lease this process has */
|
||||
struct lease_st* lease;
|
||||
|
||||
@@ -62,6 +73,10 @@ struct proc_list_st {
|
||||
unsigned int total;
|
||||
};
|
||||
|
||||
struct script_list_st {
|
||||
struct list_head head;
|
||||
};
|
||||
|
||||
struct banned_st {
|
||||
struct list_node list;
|
||||
time_t failed_time; /* The time authentication failed */
|
||||
@@ -84,14 +99,17 @@ typedef struct main_server_st {
|
||||
|
||||
struct listen_list_st llist;
|
||||
struct proc_list_st clist;
|
||||
struct script_list_st script_list;
|
||||
struct ban_list_st ban_list;
|
||||
|
||||
unsigned active_clients;
|
||||
} main_server_st;
|
||||
|
||||
void clear_lists(main_server_st *s);
|
||||
|
||||
int handle_commands(main_server_st *s, struct proc_st* cur);
|
||||
|
||||
int user_connected(main_server_st *s, struct proc_st* cur, struct lease_st*);
|
||||
int user_connected(main_server_st *s, struct proc_st* cur);
|
||||
void user_disconnected(main_server_st *s, struct proc_st* cur);
|
||||
|
||||
void expire_tls_sessions(main_server_st *s);
|
||||
@@ -115,17 +133,19 @@ void
|
||||
__attribute__ ((format(printf, 4, 5)))
|
||||
mslog(const main_server_st * s, const struct proc_st* proc,
|
||||
int priority, const char *fmt, ...);
|
||||
void mslog_hex(const main_server_st * s, const struct proc_st* proc,
|
||||
int priority, const char *prefix, uint8_t* bin, unsigned bin_size);
|
||||
|
||||
int open_tun(main_server_st* s, struct lease_st** l);
|
||||
int set_tun_mtu(main_server_st* s, struct proc_st * proc, unsigned mtu);
|
||||
|
||||
int send_auth_reply(main_server_st* s, struct proc_st* proc,
|
||||
cmd_auth_reply_t r, struct lease_st* lease);
|
||||
cmd_auth_reply_t r);
|
||||
int handle_auth_cookie_req(main_server_st* s, struct proc_st* proc,
|
||||
const struct cmd_auth_cookie_req_st * req, struct lease_st **lease);
|
||||
const struct cmd_auth_cookie_req_st * req);
|
||||
int generate_and_store_vals(main_server_st *s, struct proc_st* proc);
|
||||
int handle_auth_req(main_server_st *s, struct proc_st* proc,
|
||||
const struct cmd_auth_req_st * req, struct lease_st **lease);
|
||||
const struct cmd_auth_req_st * req);
|
||||
|
||||
int check_multiple_users(main_server_st *s, struct proc_st* proc);
|
||||
|
||||
@@ -133,4 +153,6 @@ void add_to_ip_ban_list(main_server_st* s, struct sockaddr_storage *addr, sockle
|
||||
void expire_banned(main_server_st* s);
|
||||
int check_if_banned(main_server_st* s, struct sockaddr_storage *addr, socklen_t addr_len);
|
||||
|
||||
int handle_script_exit(main_server_st *s, struct proc_st* proc, int code);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
*
|
||||
* DO NOT EDIT THIS FILE (ocserv-args.c)
|
||||
*
|
||||
* It has been AutoGen-ed March 12, 2013 at 11:39:41 PM by AutoGen 5.16
|
||||
* It has been AutoGen-ed March 13, 2013 at 06:29:47 PM by AutoGen 5.16
|
||||
* From the definitions ocserv-args.def
|
||||
* and the template file options
|
||||
*
|
||||
|
||||
@@ -191,9 +191,10 @@ cookie-validity = 43200
|
||||
|
||||
# Script to call when a client connects and obtains an IP
|
||||
# Parameters are passed on the environment.
|
||||
# USERNAME, GROUPNAME, HOSTNAME (the hostname selected by client),
|
||||
# REASON, USERNAME, GROUPNAME, HOSTNAME (the hostname selected by client),
|
||||
# DEVICE, IP_REAL (the real IP of the client), IP_LOCAL (the local IP
|
||||
# in the P-t-P connection), IP_REMOTE (the VPN IP of the client).
|
||||
# in the P-t-P connection), IP_REMOTE (the VPN IP of the client). REASON
|
||||
# may be "connect" or "disconnect".
|
||||
#connect-script = /usr/bin/myscript
|
||||
#disconnect-script = /usr/bin/myscript
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
*
|
||||
* DO NOT EDIT THIS FILE (ocserv-args.h)
|
||||
*
|
||||
* It has been AutoGen-ed March 12, 2013 at 11:39:41 PM by AutoGen 5.16
|
||||
* It has been AutoGen-ed March 13, 2013 at 06:29:46 PM by AutoGen 5.16
|
||||
* From the definitions ocserv-args.def
|
||||
* and the template file options
|
||||
*
|
||||
|
||||
35
src/script-list.h
Normal file
35
src/script-list.h
Normal file
@@ -0,0 +1,35 @@
|
||||
#ifndef SCRIPT_LIST_H
|
||||
# define SCRIPT_LIST_H
|
||||
|
||||
#include <main.h>
|
||||
|
||||
inline static
|
||||
void add_to_script_list(main_server_st* s, pid_t pid, unsigned up, struct proc_st* proc)
|
||||
{
|
||||
struct script_wait_st *stmp;
|
||||
|
||||
stmp = malloc(sizeof(*stmp));
|
||||
if (stmp == NULL)
|
||||
return;
|
||||
|
||||
stmp->proc = proc;
|
||||
stmp->pid = pid;
|
||||
stmp->up = up;
|
||||
|
||||
list_add(&s->script_list.head, &(stmp->list));
|
||||
}
|
||||
|
||||
inline static void remove_from_script_list(main_server_st* s, struct proc_st* proc)
|
||||
{
|
||||
struct script_wait_st *stmp, *spos;
|
||||
|
||||
list_for_each_safe(&s->script_list.head, stmp, spos, list) {
|
||||
if (stmp->proc == proc) {
|
||||
list_del(&stmp->list);
|
||||
free(stmp);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -406,6 +406,7 @@ int open_tun(main_server_st* s, struct lease_st** l)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
lease->in_use = 1;
|
||||
lease->fd = tunfd;
|
||||
*l = lease;
|
||||
|
||||
|
||||
@@ -527,10 +527,6 @@ struct cmd_auth_req_st areq;
|
||||
|
||||
ret = auth_user(ws, &areq);
|
||||
if (ret < 0) {
|
||||
if (username)
|
||||
oclog(ws, LOG_INFO, "Failed authentication attempt for '%s'", username);
|
||||
else
|
||||
oclog(ws, LOG_INFO, "Failed authentication attempt");
|
||||
goto auth_fail;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user