Hello, Dr. Torge Szczepanek, le Wed 18 Mar 2015 16:30:49 +0100, a écrit : > > Here are patches to add IPv6 support to openvpn-auth-radius: > > > > - support for Framed-IPv6-Route > > - support optional gateway parameter > > - support for announcing routes to bird > > - support for Framed-IPv6-Address > > These patches cannot be applied to the current unstable version. Can you > please provide updated patches, that can be applied cleanly to the current > unstable version and test them before?
Ah, right. These patch files were for upstream's version, sorry. I actually have already-tested patches against unstable, here they are (we use them intensively in production, so they're really well-tested). > In addition the optional gateway parameter patch seems to contain > functions, which are also within the patch for Bug#773280. Can you > please validate, if your code is now obsolete? (File dev.txt) Indeed, my "dev" patch is the same idea as Bug#773280, except his solution is simpler but will fail e.g. with IPv6 when we don't have a framed IPv6 (i.e no Framed-IPv6-Address RADIUS attribute), so we really have to specify the device. In the attached patches, I have just added the extra test that he does (!= 0.0.0.0). Samuel
--- a/AccountingProcess.cpp +++ b/AccountingProcess.cpp @@ -93,12 +93,14 @@ void AccountingProcess::Accounting(Plugi //get the information from the foreground process user->setUsername(context->acctsocketforegr.recvStr()); user->setSessionId(context->acctsocketforegr.recvStr()) ; + user->setDev(context->acctsocketforegr.recvStr()) ; user->setPortnumber(context->acctsocketforegr.recvInt()); user->setCallingStationId(context->acctsocketforegr.recvStr()); user->setFramedIp(context->acctsocketforegr.recvStr()); user->setCommonname(context->acctsocketforegr.recvStr()); user->setAcctInterimInterval(context->acctsocketforegr.recvInt()); user->setFramedRoutes(context->acctsocketforegr.recvStr()); + user->setFramedRoutes6(context->acctsocketforegr.recvStr()); user->setKey(context->acctsocketforegr.recvStr()); user->setStatusFileKey(context->acctsocketforegr.recvStr()); user->setUntrustedPort(context->acctsocketforegr.recvStr()); --- a/AuthenticationProcess.cpp +++ b/AuthenticationProcess.cpp @@ -73,6 +73,7 @@ void AuthenticationProcess::Authenticati //get the user informations user->setUsername(context->authsocketforegr.recvStr()); user->setPassword(context->authsocketforegr.recvStr()); + user->setDev(context->authsocketforegr.recvStr()); user->setPortnumber(context->authsocketforegr.recvInt()); user->setSessionId(context->authsocketforegr.recvStr()); user->setCallingStationId(context->authsocketforegr.recvStr()); @@ -106,6 +107,9 @@ void AuthenticationProcess::Authenticati //send the framed ip to the parent process context->authsocketforegr.send(user->getFramedIp()); + //send the IPv6 routes to the parent process + context->authsocketforegr.send(user->getFramedRoutes6()); + //send the interval to the parent process context->authsocketforegr.send(user->getAcctInterimInterval()); --- a/radiusplugin.cpp +++ b/radiusplugin.cpp @@ -442,6 +442,8 @@ extern "C" } + newuser->setDev ( get_env ( "dev", envp ) ); + newuser->setUntrustedPort ( get_env ( "untrusted_port", envp ) ); newuser->setStatusFileKey(newuser->getCommonname() +string ( "," ) + untrusted_ip + string ( ":" ) + get_env ( "untrusted_port", envp ) ); newuser->setKey(untrusted_ip + string ( ":" ) + get_env ( "untrusted_port", envp ) ); @@ -571,12 +573,14 @@ extern "C" context->acctsocketbackgr.send ( ADD_USER ); context->acctsocketbackgr.send ( newuser->getUsername() ); context->acctsocketbackgr.send ( newuser->getSessionId() ); + context->acctsocketbackgr.send ( newuser->getDev() ); context->acctsocketbackgr.send ( newuser->getPortnumber() ); context->acctsocketbackgr.send ( newuser->getCallingStationId() ); context->acctsocketbackgr.send ( newuser->getFramedIp() ); context->acctsocketbackgr.send ( newuser->getCommonname() ); context->acctsocketbackgr.send ( newuser->getAcctInterimInterval() ); context->acctsocketbackgr.send ( newuser->getFramedRoutes() ); + context->acctsocketbackgr.send ( newuser->getFramedRoutes6() ); context->acctsocketbackgr.send ( newuser->getKey() ); context->acctsocketbackgr.send ( newuser->getStatusFileKey()); context->acctsocketbackgr.send ( newuser->getUntrustedPort() ); @@ -1055,6 +1059,7 @@ void * auth_user_pass_verify(void * c) context->authsocketbackgr.send ( COMMAND_VERIFY ); context->authsocketbackgr.send ( newuser->getUsername() ); context->authsocketbackgr.send ( newuser->getPassword() ); + context->authsocketbackgr.send ( newuser->getDev() ); context->authsocketbackgr.send ( newuser->getPortnumber() ); context->authsocketbackgr.send ( newuser->getSessionId() ); context->authsocketbackgr.send ( newuser->getCallingStationId() ); @@ -1076,6 +1081,10 @@ void * auth_user_pass_verify(void * c) newuser->setFramedIp ( context->authsocketbackgr.recvStr() ); if ( DEBUG ( context->getVerbosity() ) ) cerr << getTime() << "RADIUS-PLUGIN: FOREGROUND THREAD: Received framed ip for user: "<< newuser->getFramedIp() << ".\n"; + //get the routes from background process + newuser->setFramedRoutes6 ( context->authsocketbackgr.recvStr() ); + if ( DEBUG ( context->getVerbosity() ) ) + cerr << getTime() << "RADIUS-PLUGIN: FOREGROUND THREAD: Received IPv6 routes for user: "<< newuser->getFramedRoutes6() << ".\n"; // get the interval from the background process --- a/UserAcct.cpp +++ b/UserAcct.cpp @@ -594,13 +594,13 @@ int UserAcct::sendStopPacket(PluginConte void UserAcct::delSystemRoutes(PluginContext * context) { char * route; - char framedip[16]; + char framedip[40]; - char routestring[100]; - char framednetmask_cidr[3]; - char framedgw[16]; + char routestring[200]; + char framednetmask_cidr[4]; + char framedgw[40]; char framedmetric[5]; - char * framedroutes; + char * framedroutes, * framedroutes6; int j=0,k=0,len=0; //copy the framed route string to an char array, it is easier to @@ -694,17 +694,23 @@ void UserAcct::delSystemRoutes(PluginCon } //create system call - strncat(routestring, "route del -net ",15); + strncat(routestring, "ip route del ",13); strncat(routestring, framedip ,16); strncat(routestring, "/" ,1); strncat(routestring, framednetmask_cidr, 2); - strncat(routestring, " gw ", 4); - strncat(routestring, framedgw, 16); + if (framedgw[0]!='\0' && strncmp(framedgw, "0.0.0.0", 8) != 0) + { + strncat(routestring, " via ", 5); + strncat(routestring, framedgw, 16); + } if (framedmetric[0]!='\0') { strncat(routestring, " metric ", 8); strncat(routestring, framedmetric , 5); } + strncat(routestring," dev ",5); + strcat(routestring,this->getDev().c_str()); + strncat(routestring," proto static",13); //redirect the output stderr to /dev/null strncat(routestring," 2> /dev/null",13); @@ -739,6 +745,147 @@ void UserAcct::delSystemRoutes(PluginCon delete [] framedroutes; + //copy the framed route string to an char array, it is easier to + //analyse + framedroutes6=new char[this->getFramedRoutes6().size()+1]; + memset(framedroutes6,0,this->getFramedRoutes6().size()+1); + + // copy in a temp-string, because strtok deletes the delimiter, if it used anywhere + strncpy(framedroutes6,this->getFramedRoutes6().c_str(),this->getFramedRoutes6().size()); + + //are there framed routes + if (framedroutes6[0]!='\0') + { + //get the first route + route=strtok(framedroutes6,";"); + len=strlen(route); + if (len > 150) //this is too big!! but the length is variable + { + cerr << getTime() <<"RADIUS-PLUGIN: BACKGROUND-ACCT: Argument for Framed Route is too long (>150 Characters).\n"; + } + else + { + while (route!=NULL) + { + //set the arrays to 0 + memset(routestring,0,200); + memset(framednetmask_cidr,0,4); + memset(framedip,0,40); + memset(framedgw,0,40); + memset(framedmetric,0,5); + + j=0;k=0; + //get ip address and add it to framedip + while(route[j]!='/' && j<len) + { + if (route[j]!=' ') + { + framedip[k]=route[j]; + k++; + } + j++; + } + k=0; + j++; + //get the framednetmask and add it to framednetmack_cidr + while(route[j]!=' ' && j<=len) + { + framednetmask_cidr[k]=route[j]; + k++; + j++; + } + k=0; + //jump spaces + while(route[j]==' ' && j<=len) + { + j++; + } + //get the gateway + while(route[j]!='/' && j<=len) + { + if (route[j]!=' ') + { + framedgw[k]=route[j]; + k++; + } + j++; + } + j++; + //find gateway netmask (this isn't used + //at the command route under linux) + while(route[j]!=' ' && j<=len) + { + j++; + } + //jump spaces + while(route[j]==' ' && j<=len) + { + j++; + } + k=0; + if (j<=len) //is there a metric (optional) + { + k=0; + //find the metric + while(route[j]!=' ' && j<=len) + { + framedmetric[k]=route[j]; + k++; + j++; + } + } + + //create system call + strncat(routestring, "ip -6 route del ",16); + strncat(routestring, framedip ,40); + strncat(routestring, "/" ,1); + strncat(routestring, framednetmask_cidr, 3); + if (framedgw[0]!='\0') + { + strncat(routestring, " via ", 5); + strncat(routestring, framedgw, 40); + } + if (framedmetric[0]!='\0') + { + strncat(routestring, " metric ", 8); + strncat(routestring, framedmetric , 5); + } + strncat(routestring," dev ",5); + strcat(routestring,this->getDev().c_str()); + strncat(routestring," proto static",13); + //redirect the output stderr to /dev/null + strncat(routestring," 2> /dev/null",13); + + + if (DEBUG (context->getVerbosity())) + cerr << getTime() << "RADIUS-PLUGIN: BACKGROUND-ACCT: Create IPv6 route string "<< routestring <<".\n"; + + //system call + if(system(routestring)!=0) + //if(1)//-> the debugg can't context system() + { + cerr << getTime() << "RADIUS-PLUGIN: BACKGROUND-ACCT: Route " << routestring << " could not set. Route already set or bad route string.\n"; + } + else + { + if (DEBUG (context->getVerbosity())) + cerr << getTime() << "RADIUS-PLUGIN: BACKGROUND-ACCT: Add route to system routing table.\n"; + + } + //get the next route + route=strtok(NULL,";"); + } + } + + } + else + { + if (DEBUG (context->getVerbosity())) + cerr << getTime() << "RADIUS-PLUGIN: BACKGROUND-ACCT: No IPv6 routes for user in AccessAcceptPacket.\n"; + } + //free the char array + delete [] framedroutes6; + } /** The method adds ths routes of the user to the system routing table. @@ -747,13 +894,13 @@ void UserAcct::delSystemRoutes(PluginCon void UserAcct::addSystemRoutes(PluginContext * context) { char * route; - char framedip[16]; + char framedip[40]; - char routestring[100]; - char framednetmask_cidr[3]; - char framedgw[16]; + char routestring[200]; + char framednetmask_cidr[4]; + char framedgw[40]; char framedmetric[5]; - char * framedroutes; + char * framedroutes, * framedroutes6; int j=0,k=0,len=0; //copy the framed route string to an char array, it is easier to @@ -848,17 +995,23 @@ void UserAcct::addSystemRoutes(PluginCon //create system call - strncat(routestring, "route add -net ",15); + strncat(routestring, "ip route add ",13); strncat(routestring, framedip ,16); strncat(routestring, "/" ,1); strncat(routestring, framednetmask_cidr, 2); - strncat(routestring, " gw ", 4); - strncat(routestring, framedgw, 16); + if (framedgw[0]!='\0' && strncmp(framedgw, "0.0.0.0", 8) != 0) + { + strncat(routestring, " via ", 5); + strncat(routestring, framedgw, 16); + } if (framedmetric[0]!='\0') { strncat(routestring, " metric ", 8); strncat(routestring, framedmetric , 5); } + strncat(routestring," dev ",5); + strcat(routestring,this->getDev().c_str()); + strncat(routestring," proto static",13); //redirect the output stderr to /dev/null strncat(routestring," 2> /dev/null",13); @@ -888,9 +1041,150 @@ void UserAcct::addSystemRoutes(PluginCon if (DEBUG (context->getVerbosity())) cerr << getTime() << "RADIUS-PLUGIN: BACKGROUND-ACCT: No routes for user.\n"; } - //fre the chat array + //free the char array delete [] framedroutes; + //copy the framed route string to an char array, it is easier to + //analyse + framedroutes6=new char[this->getFramedRoutes6().size()+1]; + memset(framedroutes6,0,this->getFramedRoutes6().size()+1); + + // copy in a temp-string, becaue strtok deletes the delimiter, if it used anywhere + strncpy(framedroutes6,this->getFramedRoutes6().c_str(),this->getFramedRoutes6().size()); + + //are there framed routes + if (framedroutes6[0]!='\0') + { + //get the first route + route=strtok(framedroutes6,";"); + len=strlen(route); + if (len > 150) //this is to big!! but the length is variable + { + cerr << getTime() <<"RADIUS-PLUGIN: BACKGROUND-ACCT: Argument for Framed Route is to long (>150 Characters).\n"; + } + else + { + while (route!=NULL) + { + //set the arrays to 0 + memset(routestring,0,200); + memset(framednetmask_cidr,0,4); + memset(framedip,0,40); + memset(framedgw,0,40); + memset(framedmetric,0,5); + + j=0;k=0; + //get ip address and add it to framedip + while(route[j]!='/' && j<len) + { + if (route[j]!=' ') + { + framedip[k]=route[j]; + k++; + } + j++; + } + k=0; + j++; + //get the framednetmask and add it to framednetmask_cidr + while(route[j]!=' ' && j<=len) + { + framednetmask_cidr[k]=route[j]; + k++; + j++; + } + k=0; + //jump spaces + while(route[j]==' ' && j<=len) + { + j++; + } + //get the gateway + while(route[j]!='/' && j<=len) + { + if (route[j]!=' ') + { + framedgw[k]=route[j]; + k++; + } + j++; + } + j++; + //find gateway netmask (this isn't used + //at the command route under linux) + while(route[j]!=' ' && j<=len) + { + j++; + } + //jump spaces + while(route[j]==' ' && j<=len) + { + j++; + } + k=0; + if (j<=len) //is there a metric (optional) + { + k=0; + //find the metric + while(route[j]!=' ' && j<=len) + { + framedmetric[k]=route[j]; + k++; + j++; + } + } + + + //create system call + strncat(routestring, "ip -6 route add ",21); + strncat(routestring, framedip ,40); + strncat(routestring, "/" ,1); + strncat(routestring, framednetmask_cidr, 3); + if (framedgw[0]!='\0') + { + strncat(routestring, " via ", 5); + strncat(routestring, framedgw, 40); + } + if (framedmetric[0]!='\0') + { + strncat(routestring, " metric ", 8); + strncat(routestring, framedmetric , 5); + } + strncat(routestring," dev ",5); + strcat(routestring,this->getDev().c_str()); + strncat(routestring," proto static",13); + //redirect the output stderr to /dev/null + strncat(routestring," 2> /dev/null",13); + + + if (DEBUG (context->getVerbosity())) + cerr << getTime() << "RADIUS-PLUGIN: BACKGROUND-ACCT: Create IPv6 route string "<< routestring << " dev " << this->getDev() << ".\n"; + + //system call route + if(system(routestring)!=0) + //if(1)//-> the debugg can't context system() + { + cerr << getTime() << "RADIUS-PLUGIN: BACKGROUND-ACCT: Route " << routestring << " could not set. Route already set or bad route string.\n"; + } + else + { + if (DEBUG (context->getVerbosity())) + cerr << getTime() << "RADIUS-PLUGIN: BACKGROUND-ACCT: Add route to system routing table.\n"; + + } + //get the next route + route=strtok(NULL,";"); + } + } + } + else + { + if (DEBUG (context->getVerbosity())) + cerr << getTime() << "RADIUS-PLUGIN: BACKGROUND-ACCT: No IPv6 routes for user.\n"; + } + //free the char array + delete [] framedroutes6; + } --- a/UserAuth.cpp +++ b/UserAuth.cpp @@ -250,6 +250,25 @@ void UserAuth::parseResponsePacket(Radiu + range=packet->findAttributes(99); + iter1=range.first; + iter2=range.second; + string froutes6; + + while (iter1!=iter2) + { + + froutes6.append((char *) iter1->second.getValue(), iter1->second.getLength()-2); + froutes6.append(";"); + iter1++; + } + this->setFramedRoutes6(froutes6); + + if (DEBUG (context->getVerbosity())) + cerr << getTime() << "RADIUS-PLUGIN: BACKGROUND AUTH: framed ipv6 route: " << this->getFramedRoutes6() <<".\n"; + + + range=packet->findAttributes(85); iter1=range.first; iter2=range.second; @@ -1484,15 +1503,16 @@ int UserAuth::createCcdFile(PluginContex ofstream ccdfile; char * route; - char framedip[16]; + char framedip[40]; char ipstring[100]; in_addr_t ip2; in_addr ip3; string filename; char framedroutes[4096]; - char framednetmask_cidr[3]; // ->/24 + char framedroutes6[4096]; + char framednetmask_cidr[4]; // ->/128 char framednetmask[16]; // ->255.255.255.0 - char framedgw[16]; + char framedgw[40]; char framedmetric[5]; //what is the biggest metric? unsigned long d1,d2; @@ -1501,11 +1521,12 @@ int UserAuth::createCcdFile(PluginContex int len=0; - if(context->conf.getOverWriteCCFiles()==true && (this->getFramedIp().length() > 0 || this->getFramedRoutes().length() > 0)) + if(context->conf.getOverWriteCCFiles()==true && (this->getFramedIp().length() > 0 || this->getFramedRoutes().length() > 0 || this->getFramedRoutes6().length() > 0)) { memset(ipstring,0,100); memset(framedip,0,16); memset(framedroutes,0,4096); + memset(framedroutes6,0,4096); //create the filename, ccd-path + commonname filename=context->conf.getCcdPath()+this->getCommonname(); @@ -1524,6 +1545,9 @@ int UserAuth::createCcdFile(PluginContex // copy in a temp-string, becaue strtok deletes the delimiter, if it is used anywhere strncpy(framedroutes,this->getFramedRoutes().c_str(),4095); + // copy in a temp-string, becaue strtok deletes the delimiter, if it is used anywhere + strncpy(framedroutes6,this->getFramedRoutes6().c_str(),4095); + if (ccdfile.is_open()) { @@ -1706,6 +1730,105 @@ int UserAuth::createCcdFile(PluginContex route=strtok(NULL,";"); } + } + } + + //set the IPv6 framed routes in the file for the openvpn process + if (framedroutes6[0]!='\0') + { + if (DEBUG (context->getVerbosity())) + cerr << getTime() << "RADIUS-PLUGIN: BACKGROUND AUTH: Write framed routes to ccd-file.\n"; + + route=strtok(framedroutes6,";"); + len=strlen(route); + if (len > 150) //this is too big! but the length is variable + { + cerr << getTime() <<"RADIUS-PLUGIN: Argument for Framed Route is to long (>50 Characters).\n"; + return 1; + } + else + { + while (route!=NULL) + { + j=0;k=0; + //set everything back for the next route entry + memset(framednetmask_cidr,0,4); + memset(framedip,0,40); + memset(framednetmask,0,40); + memset(framedgw,0,40); + memset(framedmetric,0,5); + + //add ip address to string + while(route[j]!='/' && j<len) + { + if (route[j]!=' ') + { + framedip[k]=route[j]; + k++; + } + j++; + } + k=0; + j++; + //add netmask + while(route[j]!=' ' && j<=len) + { + framednetmask_cidr[k]=route[j]; + k++; + j++; + } + k=0; + //jump spaces + while(route[j]==' ' && j<len) + { + j++; + } + //find gateway + while(route[j]!='/' && j<len) + { + if (route[j]!=' ') + { + framedgw[k]=route[j]; + k++; + } + j++; + } + j++; + + //find gateway netmask (this isn't used + //at the command route under linux) + while(route[j]!=' ' && j<len) + { + j++; + } + //jump spaces + + while(route[j]==' ' && j<len ) + { + j++; + } + k=0; + if (j<=len) + { + + k=0; + //find the metric + while(route[j]!=' ' && j<len) + { + framedmetric[k]=route[j]; + k++; + j++; + } + } + + if (DEBUG (context->getVerbosity())) + cerr << getTime() << "RADIUS-PLUGIN: Write route string: iroute-ipv6 " << framedip << "/" << framednetmask_cidr << " " << framedgw << " " << framedmetric << " to ccd-file.\n"; + + //write iroute to client file + ccdfile << "iroute-ipv6 " << framedip << "/"<< framednetmask_cidr << "\n"; + + route=strtok(NULL,";"); + } } } --- a/User.cpp +++ b/User.cpp @@ -24,8 +24,10 @@ /** The constructor sets the acctinteriminterval and the portnumber to 0.*/ User::User() { + this->dev=""; this->framedip=""; this->framedroutes=""; + this->framedroutes6=""; this->key=""; this->statusfilekey=""; this->untrustedport=""; @@ -41,8 +43,10 @@ User::User() * @param num The portnumber.*/ /*User::User(int num) { + this->dev=""; this->framedip=""; this->framedroutes=""; + this->framedroutes6=""; this->key=""; this->untrustedport=""; this->acctinteriminterval=0; @@ -68,8 +72,10 @@ User & User::operator=(const User & u) { this->username=u.username; this->commonname=u.commonname; + this->dev=u.dev; this->framedroutes=u.framedroutes; this->framedip=u.framedip; + this->framedroutes6=u.framedroutes6; this->key=u.key; this->statusfilekey=u.statusfilekey; this->callingstationid=u.callingstationid; @@ -100,8 +106,10 @@ User::User(const User & u) { this->username=u.username; this->commonname=u.commonname; + this->dev=u.dev; this->framedroutes=u.framedroutes; this->framedip=u.framedip; + this->framedroutes6=u.framedroutes6; this->key=u.key; this->statusfilekey=u.statusfilekey; this->callingstationid=u.callingstationid; @@ -149,6 +157,19 @@ void User::setCommonname(string cn) this->commonname=cn; } +/** The getter method for the device. + * @return The device as a string.*/ +string User::getDev(void) +{ + return this->dev; +} +/** The setter method for the device. + * @param dev The device.*/ +void User::setDev(string dev) +{ + this->dev=dev; +} + /** The getter method for the framed routes. * @return The framed routes as a string.*/ string User::getFramedRoutes(void) @@ -157,12 +178,26 @@ string User::getFramedRoutes(void) } /** The setter method for the framedroutes. * @param froutes The framedroutes, if there are more - * routes they are diveded through a ';'.*/ + * routes they are divided through a ';'.*/ void User::setFramedRoutes(string froutes) { this->framedroutes=froutes; } +/** The getter method for the framed IPv6 routes. + * @return The framed IPv6 routes as a string.*/ +string User::getFramedRoutes6(void) +{ + return this->framedroutes6; +} +/** The setter method for the framed IPv6 routes. + * @param froutes6 The framed IPv6 routes, if there are more + * routes they are divided through a ';'.*/ +void User::setFramedRoutes6(string froutes6) +{ + this->framedroutes6=froutes6; +} + /** The getter method for the framed ip. * @return The framed ip as a string.*/ string User::getFramedIp(void) --- a/User.h +++ b/User.h @@ -44,8 +44,10 @@ class User protected: string username; /**<The username.*/ string commonname; /**<The commonname.*/ + string dev; /**<The device.*/ string framedroutes; /**<The framedroutes, they are stored as a string. if there are more routes, they must be delimted by an ';'*/ string framedip; /**<The framed ip.*/ + string framedroutes6; /**<The framed IPv6 routes, they are stored as a string. If there are more routes, they must be delimited by an ';'*/ string callingstationid; /**<The calling station id, in this case the real ip addres of the client.*/ string key; /**<A unique key to find the user in a map. */ string statusfilekey; /**<Unique identifier in the status log file (version 1) "commonname,untrusted_ip:untrusted_port"*/ @@ -73,9 +75,15 @@ public: void setCommonname(string); + string getDev(void); + void setDev(string); + string getFramedRoutes(void); void setFramedRoutes(string); + string getFramedRoutes6(void); + void setFramedRoutes6(string); + string getFramedIp(void); void setFramedIp(string);
--- a/AccountingProcess.cpp +++ b/AccountingProcess.cpp @@ -97,6 +97,7 @@ void AccountingProcess::Accounting(Plugi user->setPortnumber(context->acctsocketforegr.recvInt()); user->setCallingStationId(context->acctsocketforegr.recvStr()); user->setFramedIp(context->acctsocketforegr.recvStr()); + user->setFramedIp6(context->acctsocketforegr.recvStr()); user->setCommonname(context->acctsocketforegr.recvStr()); user->setAcctInterimInterval(context->acctsocketforegr.recvInt()); user->setFramedRoutes(context->acctsocketforegr.recvStr()); @@ -106,7 +107,7 @@ void AccountingProcess::Accounting(Plugi user->setUntrustedPort(context->acctsocketforegr.recvStr()); context->acctsocketforegr.recvBuf(user); if (DEBUG (context->getVerbosity())) - cerr << getTime() << "RADIUS-PLUGIN: BACKGROUND ACCT: New user acct: username: " << user->getUsername() << ", interval: " << user->getAcctInterimInterval() << ", calling station: " << user->getCallingStationId() << ", commonname: " << user->getCommonname() << ", framed ip: " << user->getFramedIp() <<".\n"; + cerr << getTime() << "RADIUS-PLUGIN: BACKGROUND ACCT: New user acct: username: " << user->getUsername() << ", interval: " << user->getAcctInterimInterval() << ", calling station: " << user->getCallingStationId() << ", commonname: " << user->getCommonname() << ", framed ip: " << user->getFramedIp() << ", framed ipv6: " << user->getFramedIp6() <<".\n"; //set the starttime --- a/AuthenticationProcess.cpp +++ b/AuthenticationProcess.cpp @@ -110,6 +110,9 @@ void AuthenticationProcess::Authenticati //send the IPv6 routes to the parent process context->authsocketforegr.send(user->getFramedRoutes6()); + //send the framed IPv6 to the parent process + context->authsocketforegr.send(user->getFramedIp6()); + //send the interval to the parent process context->authsocketforegr.send(user->getAcctInterimInterval()); --- a/RadiusClass/utilities/dictionary +++ b/RadiusClass/utilities/dictionary @@ -123,6 +123,8 @@ ATTRIBUTE NAS-IPv6-Address 95 ipaddr6 ATTRIBUTE Login-IPv6-Host 98 ipaddr6 ATTRIBUTE Framed-IPv6-Route 99 string ATTRIBUTE Framed-IPv6-Pool 100 string +ATTRIBUTE Framed-IPv6-Address 168 ipaddr6 + ATTRIBUTE X-Ascend-FCP-Parameter 119 string ATTRIBUTE Ascend-Modem-PortNo 120 integer ATTRIBUTE Ascend-Modem-SlotNo 121 integer --- a/RadiusClass/utilities/vsa.h +++ b/RadiusClass/utilities/vsa.h @@ -161,6 +161,8 @@ //ATTRIBUTE Login-IPv6-Host 98 ipaddr6 //ATTRIBUTE Framed-IPv6-Route 99 string //ATTRIBUTE Framed-IPv6-Pool 100 string + //ATTRIBUTE Framed-IPv6-Address 168 ipaddr6 + // //ATTRIBUTE X-Ascend-FCP-Parameter 119 string //ATTRIBUTE Ascend-Modem-PortNo 120 integer //ATTRIBUTE Ascend-Modem-SlotNo 121 integer --- a/RadiusClass/vsa.h +++ b/RadiusClass/vsa.h @@ -161,6 +161,8 @@ //ATTRIBUTE Login-IPv6-Host 98 ipaddr6 //ATTRIBUTE Framed-IPv6-Route 99 string //ATTRIBUTE Framed-IPv6-Pool 100 string + //ATTRIBUTE Framed-IPv6-Address 168 ipaddr6 + // //ATTRIBUTE X-Ascend-FCP-Parameter 119 string //ATTRIBUTE Ascend-Modem-PortNo 120 integer //ATTRIBUTE Ascend-Modem-SlotNo 121 integer --- a/User.cpp +++ b/User.cpp @@ -27,6 +27,7 @@ User::User() this->dev=""; this->framedip=""; this->framedroutes=""; + this->framedip6=""; this->framedroutes6=""; this->key=""; this->statusfilekey=""; @@ -46,6 +47,7 @@ User::User() this->dev=""; this->framedip=""; this->framedroutes=""; + this->framedip6=""; this->framedroutes6=""; this->key=""; this->untrustedport=""; @@ -73,8 +75,9 @@ User & User::operator=(const User & u) this->username=u.username; this->commonname=u.commonname; this->dev=u.dev; - this->framedroutes=u.framedroutes; this->framedip=u.framedip; + this->framedroutes=u.framedroutes; + this->framedip6=u.framedip6; this->framedroutes6=u.framedroutes6; this->key=u.key; this->statusfilekey=u.statusfilekey; @@ -107,8 +110,9 @@ User::User(const User & u) this->username=u.username; this->commonname=u.commonname; this->dev=u.dev; - this->framedroutes=u.framedroutes; this->framedip=u.framedip; + this->framedroutes=u.framedroutes; + this->framedip6=u.framedip6; this->framedroutes6=u.framedroutes6; this->key=u.key; this->statusfilekey=u.statusfilekey; @@ -211,6 +215,19 @@ void User::setFramedIp(string ip) this->framedip=ip; } +/** The getter method for the framed IPv6. + * @return The framed IPv6 as a string.*/ +string User::getFramedIp6(void) +{ + return this->framedip6; +} +/** The setter method for the framedip6. + * @param ip The framedip.*/ +void User::setFramedIp6(string ip) +{ + this->framedip6=ip; +} + /** The getter method for the fkey. * @return The unique key as a string.*/ string User::getKey(void) --- a/User.h +++ b/User.h @@ -48,6 +48,7 @@ protected: string framedroutes; /**<The framedroutes, they are stored as a string. if there are more routes, they must be delimted by an ';'*/ string framedip; /**<The framed ip.*/ string framedroutes6; /**<The framed IPv6 routes, they are stored as a string. If there are more routes, they must be delimited by an ';'*/ + string framedip6; /**<The framed ipv6.*/ string callingstationid; /**<The calling station id, in this case the real ip addres of the client.*/ string key; /**<A unique key to find the user in a map. */ string statusfilekey; /**<Unique identifier in the status log file (version 1) "commonname,untrusted_ip:untrusted_port"*/ @@ -87,6 +88,9 @@ public: string getFramedIp(void); void setFramedIp(string); + string getFramedIp6(void); + void setFramedIp6(string); + string getKey(void); void setKey(string); --- a/UserAuth.cpp +++ b/UserAuth.cpp @@ -268,6 +268,19 @@ void UserAuth::parseResponsePacket(Radiu cerr << getTime() << "RADIUS-PLUGIN: BACKGROUND AUTH: framed ipv6 route: " << this->getFramedRoutes6() <<".\n"; + range=packet->findAttributes(168); + iter1=range.first; + iter2=range.second; + + + if (iter1!=iter2) + { + this->setFramedIp6(iter1->second.ip6FromBuf()); + } + + if (DEBUG (context->getVerbosity())) + cerr << getTime() << "RADIUS-PLUGIN: BACKGROUND AUTH: framed IPv6: " << this->getFramedIp6() <<".\n"; + range=packet->findAttributes(85); iter1=range.first; @@ -1522,7 +1535,7 @@ int UserAuth::createCcdFile(PluginContex int len=0; - if(context->conf.getOverWriteCCFiles()==true && (this->getFramedIp().length() > 0 || this->getFramedRoutes().length() > 0 || this->getFramedRoutes6().length() > 0)) + if(context->conf.getOverWriteCCFiles()==true && (this->getFramedIp().length() > 0 || this->getFramedRoutes().length() > 0 || this->getFramedIp6().length() > 0 || this->getFramedRoutes6().length() > 0)) { memset(ipstring,0,100); memset(framedip,0,16); @@ -1782,6 +1795,32 @@ int UserAuth::createCcdFile(PluginContex } } + //set the IPv6 address in the file + if (this->framedip6[0]!='\0') + { + if (DEBUG (context->getVerbosity())) + cerr << getTime() << "RADIUS-PLUGIN: BACKGROUND AUTH: Write framed IPv6 to ccd-file.\n"; + + //build the ifconfig + ipstring[0] = 0; + strncat(ipstring, "ifconfig-ipv6-push ",19); + strncat(ipstring, this->getFramedIp6().c_str() , 39); + strncat(ipstring, " ", 1); + + if(context->conf.getP2p6()[0]!='\0') + { + strncat(ipstring, context->conf.getP2p6() , 39); + if (DEBUG (context->getVerbosity())) + cerr << getTime() << "RADIUS-PLUGIN: BACKGROUND AUTH: Create ifconfig-ipv6-push for topology p2p.\n"; + } + + if (DEBUG (context->getVerbosity())) + cerr << getTime() << "RADIUS-PLUGIN: Write " << ipstring << " ccd-file.\n"; + + + ccdfile << ipstring <<"\n"; + } + //set the IPv6 framed routes in the file for the openvpn process if (framedroutes6[0]!='\0') { --- a/radiusplugin.cpp +++ b/radiusplugin.cpp @@ -577,6 +577,7 @@ extern "C" context->acctsocketbackgr.send ( newuser->getPortnumber() ); context->acctsocketbackgr.send ( newuser->getCallingStationId() ); context->acctsocketbackgr.send ( newuser->getFramedIp() ); + context->acctsocketbackgr.send ( newuser->getFramedIp6() ); context->acctsocketbackgr.send ( newuser->getCommonname() ); context->acctsocketbackgr.send ( newuser->getAcctInterimInterval() ); context->acctsocketbackgr.send ( newuser->getFramedRoutes() ); @@ -1085,6 +1086,10 @@ void * auth_user_pass_verify(void * c) newuser->setFramedRoutes6 ( context->authsocketbackgr.recvStr() ); if ( DEBUG ( context->getVerbosity() ) ) cerr << getTime() << "RADIUS-PLUGIN: FOREGROUND THREAD: Received IPv6 routes for user: "<< newuser->getFramedRoutes6() << ".\n"; + //get the framed IPv6 + newuser->setFramedIp6 ( context->authsocketbackgr.recvStr() ); + if ( DEBUG ( context->getVerbosity() ) ) + cerr << getTime() << "RADIUS-PLUGIN: FOREGROUND THREAD: Received framed IPv6 for user: "<< newuser->getFramedIp6() << "." << endl; // get the interval from the background process --- a/Config.cpp +++ b/Config.cpp @@ -39,6 +39,7 @@ Config::Config(void) this->vsascript=""; memset(this->subnet,0,16); memset(this->p2p,0,16); + memset(this->p2p6,0,40); } /** The constructor initializes all char arrays with 0. After the initialization @@ -51,6 +52,7 @@ Config::Config(char * configfile) { memset(this->subnet,0,16); memset(this->p2p,0,16); + memset(this->p2p6,0,40); this->ccdPath=""; this->openvpnconfig=""; this->vsanamedpipe=""; @@ -110,6 +112,14 @@ int Config::parseConfigFile(const char * } line.copy(this->p2p,line.size()-4,4); } + if (strncmp(line.c_str(),"p2p6=",5)==0) + { + if((line.size()-5)>39) + { + return BAD_FILE; + } + line.copy(this->p2p6,line.size()-5,5); + } if (strncmp(line.c_str(),"vsascript=",10)==0) { this->vsascript=line.substr(10,line.size()-10); @@ -375,6 +385,23 @@ char * Config::getP2p(void) return this->p2p; } +/** The setter method for the p2p6 address. + * @param ip A string with p2p6 address. + */ +void Config::setP2p6(char * ip) +{ + strncpy(this->p2p6,ip, 40); +} + + +/** The getter method for the p2p6 address. + * @return A pointer to the p2p6 address. + */ +char * Config::getP2p6(void) +{ + return this->p2p6; +} + /** The setter method for the vsascript. * @param script A path of the script. */ --- a/Config.h +++ b/Config.h @@ -43,6 +43,7 @@ private: string statusfile; /**< The path and filename of the status file, where openvpn writes the status information.*/ char subnet[16]; /**<The subnet which is assigned to the client in topology option.*/ char p2p[16]; /**<The OpenVPN server address which is assigned to the client in topology p2p.*/ + char p2p6[40]; /**<The OpenVPN server IPv6 address which is assigned to the client in topology p2p.*/ string vsascript; /**<A script whcih handles vendor specific attributes.*/ string vsanamedpipe; /**<The named pipe to the vsascript.*/ bool usernameascommonname; /**<Use the username as commonname in the plugin (for OpenVPN option username-as-common-name (no commonname in the enviroment!)).*/ @@ -76,6 +77,9 @@ public: char * getP2p(void); void setP2p(char * ); + char * getP2p6(void); + void setP2p6(char * ); + string getVsaScript(void); void setVsaScript(string); --- a/radiusplugin.cnf +++ b/radiusplugin.cnf @@ -30,6 +30,9 @@ subnet=255.255.255.0 # If you use topology option "p2p", fill in the right network, e.g. from OpenVPN option "--server NETWORK NETMASK" # p2p=10.8.0.1 +# If using Framed-IPv6-Address, fill in the gateway, e.g. from OpenVPN option "--server-ipv6 ADDRESS" +# p2p6=fc00::1 + # Allows the plugin to overwrite the client config in client config file directory, # default is true --- a/RadiusClass/RadiusAttribute.h +++ b/RadiusClass/RadiusAttribute.h @@ -68,6 +68,7 @@ public: int intFromBuf(void); string ipFromBuf(void); + string ip6FromBuf(void); void dumpRadiusAttrib(void); --- a/RadiusClass/RadiusAttribute.cpp +++ b/RadiusClass/RadiusAttribute.cpp @@ -568,3 +568,26 @@ string RadiusAttribute::ipFromBuf(void) } return string(ip3); } + +/** The method converts the value into an IPv6. + * The attribute must have the right datatype IPADDRESS6. + * @return The ip address as a string. + */ +string RadiusAttribute::ip6FromBuf(void) +{ + int num,i,len; + char ip2[3],ip3[40]; + memset(ip3,0,40); + len=(this->length-2); + if(len>16) + len=16; + for (i=0;i<len;i++) + { + num=(int)this->value[i]; + sprintf(ip2,"%02x",num); + strcat(ip3,ip2); + if((i%2)==1 && i<len-1) + strcat(ip3,":"); + } + return string(ip3); +}