Skip to content

Commit

Permalink
Make client-connect function to work asynchronously
Browse files Browse the repository at this point in the history
This commit introcudes asyncronious (or deferred) client-connect function.
It works just as auth_user_pass_verify function which can return result using temporary file OpenVPN creates to prevent main OpenVPN thread stall while the user is connecting.
You should set useclientconnectdeferfile=true in radiusplugin config file for this function to work. It would fall back to synchronous method if asynchronous method can't be used.
Asynchronous client-connect call is not merged upstream as for OpenVPN 2.3.8 and requires patches from Fabian Knittel.
  • Loading branch information
ValdikSS committed Nov 22, 2015
1 parent b7c8f99 commit 889a50a
Show file tree
Hide file tree
Showing 9 changed files with 340 additions and 89 deletions.
28 changes: 28 additions & 0 deletions Config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ Config::Config(void)
this->clientcertnotrequired=false;
this->overwriteccfiles=true;
this->useauthcontrolfile=false;
this->useclientconnectdeferfile=false;
this->accountingonly=false;
this->nonfatalaccounting=false;
this->defacctinteriminterval=0;
Expand Down Expand Up @@ -64,6 +65,7 @@ Config::Config(char * configfile)
this->clientcertnotrequired=false;
this->overwriteccfiles=true;
this->useauthcontrolfile=false;
this->useclientconnectdeferfile=false;
this->accountingonly=false;
this->nonfatalaccounting=false;
this->defacctinteriminterval=0;
Expand Down Expand Up @@ -158,6 +160,16 @@ int Config::parseConfigFile(const char * configfile)
else if (stmp =="false") this->useauthcontrolfile=false;
else return BAD_FILE;

}
if (strncmp(line.c_str(),"useclientconnectdeferfile=",26)==0)
{

string stmp=line.substr(26,line.size()-26);
deletechars(&stmp);
if(stmp == "true") this->useclientconnectdeferfile=true;
else if (stmp =="false") this->useclientconnectdeferfile=false;
else return BAD_FILE;

}
if (strncmp(line.c_str(),"accountingonly=",15)==0)
{
Expand Down Expand Up @@ -557,6 +569,22 @@ void Config::setUseAuthControlFile(bool b)
this->useauthcontrolfile=b;
}

/** Getter method for the clientconnectdeferfile variable.
* @return A bool of clientconnectdeferfile .
*/
bool Config::getUseClientConnectDeferFile(void)
{
return this->useclientconnectdeferfile;
}

/** The setter method for the clientconnectdeferfile varibale
* @param overwrite Set to true if the plugin if client-connect control files should be if supported by the OpenVPN version.
*/
void Config::setUseClientConnectDeferFile(bool b)
{
this->useclientconnectdeferfile=b;
}


bool Config::getAccountingOnly(void)
{
Expand Down
4 changes: 4 additions & 0 deletions Config.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ class Config
string openvpnconfig; /**<Path to OpenVPN config.*/
bool overwriteccfiles; /**<If true the plugin overwrites the client config files.*/
bool useauthcontrolfile; /**<If true and the OpenVPN version supports auth control files, the acf is used.*/
bool useclientconnectdeferfile; /**<If true and the OpenVPN version supports client-connect defer files, it is used.*/
bool accountingonly; /**<Only the accounting is done by the plugin.*/
bool nonfatalaccounting; /**<If errors during the accounting occurs, the users can still connect.*/
int defacctinteriminterval; /**<Default Acct-Interim-Interval in seconds.*/
Expand Down Expand Up @@ -100,6 +101,9 @@ class Config

bool getUseAuthControlFile(void);
void setUseAuthControlFile(bool);

bool getUseClientConnectDeferFile(void);
void setUseClientConnectDeferFile(bool);

bool getAccountingOnly(void);
void setAccountingOnly(bool);
Expand Down
52 changes: 51 additions & 1 deletion PluginContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,15 @@ void PluginContext::addNewUser(UserPlugin * newuser)
this->newusers.push_back(newuser);
}

/**The method return the first element in the list of waiting users.
/**The method adds an new user to the user list of users waiting for accounting
* @param newuser A pointer to the user.
*/
void PluginContext::addNewAcctUser(UserPlugin * newuser)
{
this->newacctusers.push_back(newuser);
}

/**The method return the first element in the list of waiting for authentication users.
*/
UserPlugin * PluginContext::getNewUser()
{
Expand All @@ -224,6 +232,18 @@ UserPlugin * PluginContext::getNewUser()

}

/**The method return the first element in the list of waiting for accounting users.
*/
UserPlugin * PluginContext::getNewAcctUser()
{


UserPlugin * user = this->newacctusers.front();
this->newacctusers.pop_front();
return user;

}

pthread_cond_t * PluginContext::getCondSend(void )
{
return &condsend;
Expand All @@ -243,12 +263,36 @@ pthread_mutex_t * PluginContext::getMutexRecv(void )
return &mutexrecv;
}

pthread_cond_t * PluginContext::getAcctCondSend(void )
{
return &acctcondsend;
}
pthread_cond_t * PluginContext::getAcctCondRecv(void )
{
return &acctcondrecv;
}

pthread_mutex_t * PluginContext::getAcctMutexSend(void )
{
return &acctmutexsend;
}

pthread_mutex_t * PluginContext::getAcctMutexRecv(void )
{
return &acctmutexrecv;
}


pthread_t * PluginContext::getThread()
{
return &thread;
}

pthread_t * PluginContext::getAcctThread()
{
return &acctthread;
}

int PluginContext::getResult()
{
return result;
Expand All @@ -265,6 +309,12 @@ bool PluginContext::UserWaitingtoAuth()
else return false;
}

bool PluginContext::UserWaitingtoAcct()
{
if (this->newacctusers.size()>0) return true;
else return false;
}


bool PluginContext::getStopThread()
{
Expand Down
18 changes: 18 additions & 0 deletions PluginContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ class PluginContext

map<string, UserPlugin *> users; /**< The user list of the plugin in for the foreground process which are authenticated.*/
list< UserPlugin *> newusers; /**< The user list of the plugin in for the foreground process which are waiting for authentication.*/
list< UserPlugin *> newacctusers; /**< The user list of the plugin in for the foreground process which are waiting for accounting.*/

list <int> nasportlist; /**< The port list. Every user gets an unipue port on connect. The number is deleted if the user disconnects, a new user can
get the number again. This is important for dynamic IP address assignment via the radius server.*/
Expand All @@ -67,6 +68,11 @@ class PluginContext
pthread_cond_t condrecv;
pthread_mutex_t mutexrecv;
pthread_t thread;
pthread_cond_t acctcondsend;
pthread_mutex_t acctmutexsend;
pthread_cond_t acctcondrecv;
pthread_mutex_t acctmutexrecv;
pthread_t acctthread;
bool stopthread;
bool startthread;
int result;
Expand Down Expand Up @@ -113,10 +119,21 @@ class PluginContext
pthread_mutex_t * getMutexRecv(void);
//void setMutex(pthread_mutex_t);

pthread_cond_t * getAcctCondSend(void);
//void setCond(pthread_cond_t);
pthread_cond_t * getAcctCondRecv(void);

pthread_mutex_t * getAcctMutexSend(void);
pthread_mutex_t * getAcctMutexRecv(void);
//void setMutex(pthread_mutex_t);

UserPlugin * getNewUser();
UserPlugin * getNewAcctUser();
void addNewUser(UserPlugin * newuser);
void addNewAcctUser(UserPlugin * newuser);

pthread_t * getThread();
pthread_t * getAcctThread();

int getResult();
void setResult(int);
Expand All @@ -125,6 +142,7 @@ class PluginContext
void setStopThread(bool);

bool UserWaitingtoAuth();
bool UserWaitingtoAcct();

bool getStartThread();
void setStartThread(bool);
Expand Down
13 changes: 13 additions & 0 deletions UserPlugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ UserPlugin::UserPlugin() : User()
this->accounted=false;
this->authenticated=false;
this->authcontrolfile="";
this->clientconnectdeferfile="";
}

/**The destructor, nothing happens here.*/
Expand All @@ -51,6 +52,7 @@ UserPlugin & UserPlugin::operator=(const UserPlugin &u)
this->password=u.password;
this->untrustedport=u.untrustedport;
this->authcontrolfile=u.authcontrolfile;
this->clientconnectdeferfile=u.clientconnectdeferfile;
}
return *this;

Expand Down Expand Up @@ -78,6 +80,7 @@ UserPlugin::UserPlugin(const UserPlugin &u) : User(u)
this->accounted=u.accounted;
this->untrustedport=u.untrustedport;
this->authcontrolfile=u.authcontrolfile;
this->clientconnectdeferfile=u.clientconnectdeferfile;
}

/**The getter method of the password.
Expand Down Expand Up @@ -149,4 +152,14 @@ void UserPlugin::setAuthControlFile(string file)
authcontrolfile=file;
}

string UserPlugin::getClientConnectDeferFile(void )
{
return clientconnectdeferfile;
}

void UserPlugin::setClientConnectDeferFile(string file)
{
clientconnectdeferfile=file;
}


4 changes: 4 additions & 0 deletions UserPlugin.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ class UserPlugin : public User
private:
string password; /**<The user password.*/
string authcontrolfile; /**<The auth control file of the user.*/
string clientconnectdeferfile; /**<The client-connect defer file of the user.*/
bool authenticated; /**<Indicates if a user is authenticated.*/
bool accounted; /**<Indicates if a user is accounted.*/

Expand All @@ -55,6 +56,9 @@ class UserPlugin : public User

string getAuthControlFile(void);
void setAuthControlFile(string);

string getClientConnectDeferFile(void);
void setClientConnectDeferFile(string);

UserPlugin & operator=(const UserPlugin &);

Expand Down
13 changes: 11 additions & 2 deletions radiusplugin.cnf
Original file line number Diff line number Diff line change
Expand Up @@ -41,15 +41,24 @@ overwriteccfiles=true
# Allows the plugin to use auth control files if OpenVPN (>= 2.1 rc8) provides them.
# The plugin needs write permission to the folder, by default it is the OpenVPN directory (e.g. /etc/openvpm)
# The OpenVPN option tmp-dir changes the directory.
# If this option is disabled, OpenVPN would stall while clients are authenticating.
# default is false
# useauthcontrolfile=false
useauthcontrolfile=true

# Allows the plugin to use client-connect deferred files if OpenVPN provides them.
# As for OpenVPN 2.3.8 this functionality is not merged upstream and requires patches from Fabian Knittel.
# The plugin needs write permission to the folder, by default it is the OpenVPN directory (e.g. /etc/openvpn)
# The OpenVPN option tmp-dir changes the directory.
# This option would be disable if OpenVPN doesn't support needed functionality.
# If this option is disabled, OpenVPN would stall while clients are authenticating.
# default is false
useclientconnectdeferfile=true

# Only the accouting functionality is used, if no user name to forwarded to the plugin, the common name of certificate is used
# as user name for radius accounting.
# default is false
# accountingonly=false


# If the accounting is non essential, nonfatalaccounting can be set to true.
# If set to true all errors during the accounting procedure are ignored, which can be
# - radius accounting can fail
Expand Down
Loading

0 comments on commit 889a50a

Please sign in to comment.