Added connect and disconnect scripts

This commit is contained in:
Nikos Mavrogiannopoulos
2013-02-04 20:43:28 +01:00
parent 087e1f8522
commit 61ae5a9c06
11 changed files with 191 additions and 6 deletions

View File

@@ -9,7 +9,7 @@ ocserv_SOURCES = main.c main-auth.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 pam.c pam.h worker-resume.c worker.h hash.h \
hashtable.h main-resume.c main.h
hashtable.h main-resume.c main.h main-script.c
ocserv_SOURCES += ocserv-args.def ocserv-args.c ocserv-args.h

View File

@@ -122,6 +122,9 @@ unsigned j;
READ_STRING("crl", config->crl, 0);
READ_STRING("cert-user-oid", config->cert_user_oid, 0);
READ_STRING("connect-script", config->connect_script, 0);
READ_STRING("disconnect-script", config->disconnect_script, 0);
READ_STRING("tls-priorities", config->priorities, 0);
READ_STRING("chroot-dir", config->chroot_dir, 0);

View File

@@ -296,6 +296,13 @@ int handle_commands(main_server_st *s, struct proc_list_st* proc)
ret = handle_auth_cookie_req(s, proc, &cmd_data.cauth, &lease);
}
if (ret == 0) {
ret = call_connect_script(s, proc);
if (ret < 0) {
syslog(LOG_INFO, "User '%s' disconnected due to script", proc->username);
}
}
if (ret == 0) {
if (cmd == AUTH_REQ) {
/* generate and store cookie */
@@ -303,6 +310,7 @@ int handle_commands(main_server_st *s, struct proc_list_st* proc)
if (ret < 0)
return -2;
}
syslog(LOG_INFO, "User '%s' authenticated", proc->username);
ret = send_auth_reply(s, proc, REP_AUTH_OK, lease);

138
src/main-script.c Normal file
View File

@@ -0,0 +1,138 @@
/*
* Copyright (C) 2013 Nikos Mavrogiannopoulos
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/select.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <netdb.h>
#include <signal.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <gnutls/gnutls.h>
#include <gnutls/crypto.h>
#include <tlslib.h>
#include <vpn.h>
#include <cookies.h>
#include <tun.h>
#include <main.h>
#include <list.h>
void call_disconnect_script(main_server_st *s, struct proc_list_st* proc)
{
pid_t pid;
int ret;
if (s->config->disconnect_script == NULL)
return;
/* XXX: close fds */
pid = fork();
if (pid == 0) {
char real[64];
char local[64];
char remote[64];
if (getnameinfo((void*)&proc->remote_addr, proc->remote_addr_len, real, sizeof(real), NULL, 0, NI_NUMERICHOST) != 0)
exit(1);
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*)&proc->lease->lip6, proc->lease->lip6_len, local, sizeof(local), NULL, 0, NI_NUMERICHOST) != 0)
exit(1);
}
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*)&proc->lease->rip6, proc->lease->rip6_len, remote, sizeof(remote), NULL, 0, NI_NUMERICHOST) != 0)
exit(1);
}
ret = execlp(s->config->disconnect_script, s->config->disconnect_script,
proc->username, proc->lease->name, real, local, remote, NULL);
if (ret == -1)
exit(1);
exit(0);
} else if (pid == -1) {
syslog(LOG_ERR, "Could not fork()");
}
}
int call_connect_script(main_server_st *s, struct proc_list_st* proc)
{
pid_t pid;
int ret, status;
if (s->config->connect_script == NULL)
return 0;
/* XXX: close fds */
pid = fork();
if (pid == 0) {
char real[64];
char local[64];
char remote[64];
if (getnameinfo((void*)&proc->remote_addr, proc->remote_addr_len, real, sizeof(real), NULL, 0, NI_NUMERICHOST) != 0)
exit(1);
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*)&proc->lease->lip6, proc->lease->lip6_len, local, sizeof(local), NULL, 0, NI_NUMERICHOST) != 0)
exit(1);
}
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*)&proc->lease->rip6, proc->lease->rip6_len, remote, sizeof(remote), NULL, 0, NI_NUMERICHOST) != 0)
exit(1);
}
ret = execlp(s->config->connect_script, s->config->connect_script,
proc->username, proc->lease->name, real, local, remote, NULL);
if (ret == -1)
exit(1);
exit(0);
} else if (pid == -1) {
syslog(LOG_ERR, "Could not fork()");
return -1;
}
ret = waitpid(pid, &status, 0);
if (WEXITSTATUS(status) == 0)
return 0;
return -1;
}

View File

@@ -45,6 +45,7 @@
int syslog_open = 0;
static unsigned int terminate = 0;
static unsigned int need_maintainance = 0;
static unsigned int need_children_cleanup = 0;
struct listen_list_st {
struct list_head list;
@@ -159,7 +160,7 @@ listen_ports(struct cfg_st* config, struct listen_list_st *list, const char *nod
return 0;
}
static void handle_children(int signo)
static void cleanup_children(main_server_st *s)
{
int status;
pid_t pid;
@@ -174,6 +175,12 @@ pid_t pid;
} else
syslog(LOG_DEBUG, "Child %u died peacefully\n", (unsigned)pid);
}
need_children_cleanup = 0;
}
static void handle_children(int signo)
{
need_children_cleanup = 1;
}
static void handle_alarm(int signo)
@@ -579,6 +586,7 @@ fork_failed:
/* received a bad command from worker */
kill(ctmp->pid, SIGTERM);
}
call_disconnect_script(&s, ctmp);
remove_proc(ctmp);
active_clients--;
}
@@ -601,6 +609,11 @@ fork_failed:
}
alarm(MAINTAINANCE_TIME);
}
if (need_children_cleanup != 0) {
cleanup_children(&s);
}
}
return 0;

View File

@@ -7,6 +7,7 @@
#include <sys/socket.h>
#include <unistd.h>
#include <net/if.h>
#include "ipc.h"
int cmd_parser (int argc, char **argv, struct cfg_st* config);
@@ -17,7 +18,7 @@ struct proc_list_st {
struct sockaddr_storage remote_addr; /* peer address */
socklen_t remote_addr_len;
char username[MAX_USERNAME_SIZE]; /* the owner */
uint8_t cookie[COOKIE_SIZE]; /* the cookie associate with the session */
uint8_t cookie[COOKIE_SIZE]; /* the cookie associated with the session */
uint8_t session_id[GNUTLS_MAX_SESSION_ID];
/* the tun lease this process has */
@@ -32,6 +33,9 @@ typedef struct main_server_st {
int handle_commands(main_server_st *s, struct proc_list_st* cur);
int call_connect_script(main_server_st *s, struct proc_list_st* cur);
void call_disconnect_script(main_server_st *s, struct proc_list_st* cur);
void expire_tls_sessions(main_server_st *s);
int send_resume_fetch_reply(main_server_st* s, struct proc_list_st* proc,

View File

@@ -2,7 +2,7 @@
*
* DO NOT EDIT THIS FILE (ocserv-args.c)
*
* It has been AutoGen-ed January 31, 2013 at 12:25:38 AM by AutoGen 5.16
* It has been AutoGen-ed February 4, 2013 at 08:41:20 PM by AutoGen 5.16
* From the definitions ocserv-args.def
* and the template file options
*

View File

@@ -92,6 +92,14 @@ auth-timeout = 40
# of that cookie.
cookie-validity = 14400
# Script to call when a client connects and obtains an IP
# Parameters: username device IP-REAL IP-LOCAL IP-REMOTE
# IP-REAL is the remote IP of the client,
# IP-LOCAL is the local IP in the P-t-P connection and IP-REMOTE
# is the VPN client IP.
connect-script = /bin/echo
disconnect-script = /bin/echo
# Cookie database file. Where to store the cookies.
cookie-db = /path/to/db

View File

@@ -2,7 +2,7 @@
*
* DO NOT EDIT THIS FILE (ocserv-args.h)
*
* It has been AutoGen-ed January 31, 2013 at 12:25:38 AM by AutoGen 5.16
* It has been AutoGen-ed February 4, 2013 at 08:41:20 PM by AutoGen 5.16
* From the definitions ocserv-args.def
* and the template file options
*

View File

@@ -46,7 +46,7 @@ tls-priorities = "PERFORMANCE:%SERVER_PRECEDENCE:%COMPAT"
# Once a client is authenticated he's provided a cookie with
# which he can reconnect. This option sets the maximum lifetime
# of that cookie.
cookie-validity = 30
cookie-validity = 14400
# Cookie database file. Where to store the cookies.
cookie-db = /var/tmp/ocserv-cookie.db
@@ -58,6 +58,14 @@ run-as-group = nogroup
device = vpns
# Script to call when a client connects and obtains an IP
# Parameters: username device IP-REAL IP-LOCAL IP-REMOTE
# IP-REAL is the remote IP of the client,
# IP-LOCAL is the local IP in the P-t-P connection and IP-REMOTE
# is the VPN client IP.
connect-script = /bin/echo
disconnect-script = /bin/echo
# The pool from which the VPN user IPs will be drawn from.
ipv4-network = 192.168.1.0
ipv4-netmask = 255.255.255.0

View File

@@ -61,6 +61,9 @@ struct cfg_st {
unsigned foreground;
unsigned max_clients;
const char *connect_script;
const char *disconnect_script;
uid_t uid;
gid_t gid;