11 files changed, 270 insertions, 36 deletions
diff --git a/noncore/settings/networksettings2/activateprofile.cpp b/noncore/settings/networksettings2/activateprofile.cpp index ba726bb..e4064e3 100644 --- a/noncore/settings/networksettings2/activateprofile.cpp +++ b/noncore/settings/networksettings2/activateprofile.cpp @@ -1,14 +1,16 @@ #include <qlistbox.h> +#include <qlabel.h> #include "activateprofile.h" ActivateProfile::ActivateProfile( const char * Interface ) : ActivateProfileGUI( 0, 0, TRUE ), NSD() { Possible = NSD.collectPossible( Interface ); + DeviceName_LBL->setText( Interface ); Profiles_LB->clear(); for( NodeCollection * NC = Possible.first(); NC; NC = Possible.next() ) { Profiles_LB->insertItem( NC->devicePixmap(), NC->name() ); diff --git a/noncore/settings/networksettings2/activateprofileGUI.ui b/noncore/settings/networksettings2/activateprofileGUI.ui index 296e044..12ab051 100644 --- a/noncore/settings/networksettings2/activateprofileGUI.ui +++ b/noncore/settings/networksettings2/activateprofileGUI.ui @@ -14,13 +14,13 @@ <width>231</width> <height>121</height> </rect> </property> <property stdset="1"> <name>caption</name> - <string>Activate Profile</string> + <string>Activate Network</string> </property> <property> <name>layoutMargin</name> </property> <property> <name>layoutSpacing</name> @@ -54,13 +54,13 @@ <property stdset="1"> <name>name</name> <cstring>TextLabel1</cstring> </property> <property stdset="1"> <name>text</name> - <string>Select profile for device :</string> + <string>Select profile to activate for </string> </property> </widget> <widget> <class>QLabel</class> <property stdset="1"> <name>name</name> diff --git a/noncore/settings/networksettings2/main.cpp b/noncore/settings/networksettings2/main.cpp index 7ec26a7..e2c00f6 100644 --- a/noncore/settings/networksettings2/main.cpp +++ b/noncore/settings/networksettings2/main.cpp @@ -1,9 +1,10 @@ #include "nsdata.h" #include "activateprofile.h" #include "networksettings.h" + #include <qpe/qpeapplication.h> #include <opie/oapplicationfactory.h> #ifdef GONE @@ -73,13 +74,25 @@ int main( int argc, char * argv[] ) { // init qt with app widget switch( Action ) { case ACT_REQUEST : { NetworkSettingsData NS; - NS.canStart( argv[1] ); + if( NS.canStart( argv[1] ) ) { + QString S; + S.sprintf( QPEApplication::qpeDir()+ + "/bin/networksettings2" ); + char * MyArgv[4]; + MyArgv[0] = "networksettings2"; + MyArgv[1] = "--prompt"; + MyArgv[2] = argv[1]; + MyArgv[3] = NULL; + NSResources->system().execAsUser( S, MyArgv ); + // if we come here , failed + printf( "%s-cNN-disallowed", argv[1] ); + } } break; case ACT_REGEN : { NetworkSettingsData NS; // regen returns 0 if OK rv = (NS.regenerate()) ? 1 : 0; diff --git a/noncore/settings/networksettings2/network/network_NNI.cpp b/noncore/settings/networksettings2/network/network_NNI.cpp index 054385a..3e368a2 100644 --- a/noncore/settings/networksettings2/network/network_NNI.cpp +++ b/noncore/settings/networksettings2/network/network_NNI.cpp @@ -106,29 +106,50 @@ bool ANetwork::hasDataFor( const QString & S ) { bool ANetwork::generateDataForCommonFile( SystemFile & S, long DevNr ) { QString NIC = runtime()->device()->netNode()->nodeClass()->genNic( DevNr ); if( S.name() == "interfaces" ) { // we can safely call from here since device item is deeper if( Data.UseDHCP ) { - S << "iface " << NIC << "-c" << connection()->number() << - "-allowed inet dhcp" << endl; - S << " up echo \"" << NIC << "\" > /tmp/profile-" << connection()->number() << - ".up" << Data.IPAddress << endl; + S << "iface " + << NIC + << "-c" + << connection()->number() + << "-allowed inet dhcp" + << endl; + S << " up echo \"" + << NIC + << "\" > /tmp/profile-" + << connection()->number() + << ".up" + << endl; if( Data.SendHostname ) { - S << " hostname "<< Data.Hostname << endl; + S << " hostname " + << Data.Hostname + << endl; } - S << " down rm -f /tmp/profile-" << connection()->number() << - ".up" << Data.IPAddress << endl; + S << " down rm -f /tmp/profile-" + << connection()->number() + << ".up" + << endl; } else { - S << "iface " << NIC << "-c" << connection()->number() << - "-allowed inet static" << endl; - S << " up echo \"" << NIC << "\" > /tmp/profile-" << connection()->number() << - ".up" << Data.IPAddress << endl; - S << " down rm -f /tmp/profile-" << connection()->number() << - ".up" << Data.IPAddress << endl; + S << "iface " + << NIC << "-c" + << connection()->number() + << "-allowed inet static" + << endl; + S << " up echo \"" + << NIC + << "\" > /tmp/profile-" + << connection()->number() + << ".up" + << endl; + S << " down rm -f /tmp/profile-" + << connection()->number() + << ".up" + << endl; S << " address " << Data.IPAddress << endl; S << " broadcast " << Data.Broadcast << endl; S << " netmask " << Data.NetMask << endl; // derive network address = IPAddress & netmask { QString NW; diff --git a/noncore/settings/networksettings2/network/networkrun.cpp b/noncore/settings/networksettings2/network/networkrun.cpp index ddb9a5f..c19235a 100644 --- a/noncore/settings/networksettings2/network/networkrun.cpp +++ b/noncore/settings/networksettings2/network/networkrun.cpp @@ -27,22 +27,22 @@ bool NetworkRun::setState( NodeCollection * NC, Action_t A ) { // we can bring UP if lower level is available if( NC->currentState() == Available ) { QString S; S.sprintf( "ifup %s=%s-c%d-allowed", II->Name.latin1(), II->Name.latin1(), connection()->number() ); - NSResources->system().execute( S ); + NSResources->system().runAsRoot( S ); } return 1; } else if( A == Down ) { if( NC->currentState() == IsUp ) { QString S; S.sprintf( "ifdown %s=%s-c%d-allowed", II->Name.latin1(), II->Name.latin1(), connection()->number() ); - NSResources->system().execute( S ); + NSResources->system().runAsRoot( S ); } return 1; } // delegate return RI->setState( NC, A ); } diff --git a/noncore/settings/networksettings2/networksettings2/resources.cpp b/noncore/settings/networksettings2/networksettings2/resources.cpp index 0301361..e6ce2b7 100644 --- a/noncore/settings/networksettings2/networksettings2/resources.cpp +++ b/noncore/settings/networksettings2/networksettings2/resources.cpp @@ -1,10 +1,14 @@ +#include <unistd.h> +#include <errno.h> +#include <fcntl.h> +#include <pwd.h> #include <qpixmap.h> +#include <qdir.h> #include <qpe/qlibrary.h> #include <qpe/qpeapplication.h> -#include <qdir.h> #include <opie2/odebug.h> #include <qtopia/resource.h> #include "netnode.h" #include "resources.h" @@ -72,12 +76,14 @@ TheNSResources::TheNSResources( void ) : NodeTypeNameMap(), // define system files addSystemFile( new SystemFile( "interfaces", "./interfaces" ) ); // get access to the system TheSystem = new System(); + + detectCurrentUser(); } TheNSResources::~TheNSResources( void ) { delete TheSystem; } @@ -229,6 +235,135 @@ void TheNSResources::renumberConnections( void ) { ++it ) { NC = it.current(); NC->setNumber( NC->maxConnectionNumber()+1 ); NC->setModified( 1 ); } } + +typedef struct EnvVars { + char * Name; + int Len; +} EnvVar_t; + +#define AnEV(x) x, sizeof(x)-1 + +static EnvVar_t EV[] = { + // AnEV( "HOME=" ), -> SPECIAL + // AnEV( "LOGNAME=" ), -> SPECIAL + AnEV( "USER=" ), + AnEV( "LD_LIBRARY_PATH=" ), + AnEV( "PATH=" ), + AnEV( "QTDIR=" ), + AnEV( "OPIEDIR=" ), + AnEV( "SHELL=" ), + { NULL, 0 } +}; + +void TheNSResources::detectCurrentUser( void ) { + // find current running qpe + QString QPEEnvFile = ""; + + // open proc dir and find all dirs in it + { QRegExp R("[0-9]+"); + QDir ProcDir( "/proc" ); + QString QPELoc = QPEApplication::qpeDir() + "bin/qpe"; + QFileInfo FI; + QStringList EL = ProcDir.entryList( QDir::Dirs ); + + // print it out + for ( QStringList::Iterator it = EL.begin(); + it != EL.end(); + ++it ) { + if( R.match( (*it) ) >= 0 ) { + QString S = ProcDir.path()+"/"+ (*it); + S.append( "/exe" ); + FI.setFile( S ); + // get the linke + S = FI.readLink(); + if( S == QPELoc ) { + // found running qpe + QPEEnvFile.sprintf( ProcDir.path()+ "/" + (*it) + "/environ" ); + break; + } + } + } + } + + if( QPEEnvFile.isEmpty() ) { + // could not find qpe + fprintf( stderr, "Could not find qpe\n" ); + return; + } + + // FI now contains path ProcDir to the cmd dir + { char * Buf = 0; + char TB[1024]; + long BufSize = 0; + int fd; + int rd; + + fd = open( QPEEnvFile.latin1(), O_RDONLY ); + if( fd < 0 ) { + fprintf( stderr, "Could not open %s : %d\n", + QPEEnvFile.latin1(), errno ); + return; + } + + while( (rd = read( fd, TB, sizeof(TB) ) ) > 0 ) { + Buf = (char *)realloc( Buf, BufSize+rd ); + memcpy( Buf+BufSize, TB, rd ); + BufSize += rd; + } + + char * Data = Buf; + char * DataEnd = Data+BufSize-1; + + // get env items out of list + while( Data < DataEnd ) { + if( strncmp( Data, "LOGNAME=", 8 ) == 0 ) { + CurrentUser.UserName = Data+8; + CurrentUser.EnvList.resize( CurrentUser.EnvList.size()+1 ); + CurrentUser.EnvList[CurrentUser.EnvList.size()-1] = + strdup( Data ); + } else if( strncmp( Data, "HOME=", 5 ) == 0 ) { + CurrentUser.HomeDir = Data+5; + CurrentUser.EnvList.resize( CurrentUser.EnvList.size()+1 ); + CurrentUser.EnvList[CurrentUser.EnvList.size()-1] = + strdup( Data ); + } else { + EnvVar_t * Run = EV; + while( Run->Name ) { + if( strncmp( Data, Run->Name, Run->Len ) == 0 ) { + CurrentUser.EnvList.resize( CurrentUser.EnvList.size()+1 ); + CurrentUser.EnvList[CurrentUser.EnvList.size()-1] = + strdup( Data ); + break; + } + Run ++; + } + } + + Data += strlen( Data )+1; + } + + free( Buf ); + + if( ! CurrentUser.UserName.isEmpty() ) { + // find user info + struct passwd pwd; + struct passwd * pwdres; + + if( getpwnam_r( CurrentUser.UserName.latin1(), + &pwd, TB, sizeof(TB), &pwdres ) || + pwdres == 0 ) { + fprintf( stderr, "Could not determine user %s : %d\n", + CurrentUser.UserName.latin1(), errno ); + return; + } + CurrentUser.Uid = pwd.pw_uid; + CurrentUser.Gid = pwd.pw_gid; + } else{ + CurrentUser.Uid = + CurrentUser.Gid = -1; + } + } +} diff --git a/noncore/settings/networksettings2/networksettings2/resources.h b/noncore/settings/networksettings2/networksettings2/resources.h index 4df3ce3..3048fb3 100644 --- a/noncore/settings/networksettings2/networksettings2/resources.h +++ b/noncore/settings/networksettings2/networksettings2/resources.h @@ -19,12 +19,24 @@ typedef void (*GetNetNodeListFt_t)(QList<ANetNode>& PNN ); typedef struct NetNode_S { ANetNode * NetNode; QLibrary * TheLibrary; long NodeCountInLib; } NetNode_t; +class CurrentQPEUser { + +public : + CurrentQPEUser() : UserName(), HomeDir(), EnvList() {} + + QString UserName; + QString HomeDir; + int Uid; + int Gid; + QArray<char *> EnvList; +}; + typedef QDict<NetNode_t> Name2NetNode_t; typedef QDict<ANetNodeInstance > Name2Instance_t; typedef QDict<NodeCollection> Name2Connection_t; typedef QDict<SystemFile> Name2SystemFile_t; class TheNSResources { @@ -80,14 +92,18 @@ public : void addConnection( NodeCollection * NC ); void removeConnection( const QString & N ); NodeCollection * findConnection( const QString & N ); Name2Connection_t & connections( void ) { return ConnectionsMap; } + CurrentQPEUser & currentUser( void ) + { return CurrentUser; } + private : + void detectCurrentUser( void ); QString tr( const char * path ); void findAvailableNetNodes( const QString &path ); bool loadNetNode( const QString &pluginFileName, const QString &resolveString = "create_plugin"); @@ -99,12 +115,14 @@ private : // all node type classes Name2NetNode_t AllNodeTypes; // all nodes Name2Instance_t AllNodes; + + CurrentQPEUser CurrentUser; }; extern TheNSResources * _NSResources; #define NSResources _NSResources #endif diff --git a/noncore/settings/networksettings2/networksettings2/system.cpp b/noncore/settings/networksettings2/networksettings2/system.cpp index a68f3c0..2133d34 100644 --- a/noncore/settings/networksettings2/networksettings2/system.cpp +++ b/noncore/settings/networksettings2/networksettings2/system.cpp @@ -1,17 +1,25 @@ -#include <stdlib.h> #include <sys/types.h> #include <sys/wait.h> -#include <qfile.h> -#include <qtextstream.h> + #include <net/if.h> #include <net/if_arp.h> #include <netinet/in.h> #include <arpa/inet.h> #include <sys/ioctl.h> #include <sys/socket.h> +#include <stdlib.h> +#include <fcntl.h> +#include <errno.h> +#include <unistd.h> + +#include <qdir.h> +#include <qregexp.h> +#include <qstringlist.h> +#include <qfile.h> +#include <qtextstream.h> #include "resources.h" #include "system.h" #define PROCNETDEV "/proc/net/dev" @@ -33,13 +41,13 @@ System::System( void ) : ProbedInterfaces() { System::~System( void ) { if( ProcDevNet ) delete ProcDevNet; } -int System::execute( const QString & S ) { +int System::runAsRoot( const QString & S ) { QString MyS = S; char * usr = getenv("USER"); int rv; if( S.isEmpty() ) { // loophole to start shell @@ -315,6 +323,33 @@ void System::probeInterfaces( void ) { } else { IFI->Netmask = ""; } fprintf( stderr, "NIC %s UP %d\n", NicName.latin1(), IFI->IsUp ); } } + +void System::execAsUser( QString & Cmd, char * argv[] ) { + CurrentQPEUser CU = NSResources->currentUser(); + + if( CU.UserName.isEmpty() ) { + // if we come here, the exec was not successfull + fprintf( stderr, "User not known \n" ); + return; + } + + // now we are ready to exec the requested command + setuid( CU.Uid ); + setgid( CU.Gid ); + + char ** envp = (char **)alloca( sizeof( char *) * + (CU.EnvList.count()+1) ); + + for( unsigned int i = 0 ; i < CU.EnvList.count() ; i ++ ) { + *(envp+i) = CU.EnvList[i]; + } + envp[CU.EnvList.count()]=NULL; + + execve( Cmd.latin1(), argv, envp ); + + // if we come here, the exec was not successfull + fprintf( stderr, "Could not exec : %d\n", errno ); +} diff --git a/noncore/settings/networksettings2/networksettings2/system.h b/noncore/settings/networksettings2/networksettings2/system.h index f89fe5d..96ee9bd 100644 --- a/noncore/settings/networksettings2/networksettings2/system.h +++ b/noncore/settings/networksettings2/networksettings2/system.h @@ -56,13 +56,18 @@ public : QDict<InterfaceInfo> & interfaces( void ) { return ProbedInterfaces; } InterfaceInfo * interface( const QString& N ) { return ProbedInterfaces[N]; } - int execute( const QString & S ); + // exec command as root + int runAsRoot( const QString & S ); + + // exec command as user + void execAsUser( QString & Cmd, char * argv[] ); + // refresh stats for this interface void refreshStatistics( InterfaceInfo & ); // reloads interfaces void probeInterfaces( void ); diff --git a/noncore/settings/networksettings2/nsdata.cpp b/noncore/settings/networksettings2/nsdata.cpp index eb63e02..b4d9aaa 100644 --- a/noncore/settings/networksettings2/nsdata.cpp +++ b/noncore/settings/networksettings2/nsdata.cpp @@ -12,13 +12,15 @@ static QString CfgFile; NetworkSettingsData::NetworkSettingsData( void ) { // init global resources structure new TheNSResources(); - CfgFile.sprintf( "%s/NETCONFIG", getenv("HOME") ); + CfgFile.sprintf( "%s/NETCONFIG", + NSResources->currentUser().HomeDir.latin1() ); + fprintf( stderr, "Cfg from %s\n", CfgFile.latin1() ); // load settings Force = 0; IsModified = 0; loadSettings(); } @@ -350,16 +352,18 @@ QList<NodeCollection> NetworkSettingsData::collectPossible( const char * Interfa // for all connections for( QDictIterator<NodeCollection> it(M); it.current(); ++it ) { NC = it.current(); // check if this profile handles the requested interface + fprintf( stderr, "check %s\n", NC->name().latin1() ); if( NC->handlesInterface( Interface ) && // if different Intf. NC->state() != Disabled && // if not enabled NC->state() != IsUp // if already used ) { + fprintf( stderr, "Append %s\n", NC->name().latin1() ); PossibleConnections.append( NC ); } } return PossibleConnections; } @@ -367,30 +371,29 @@ QList<NodeCollection> NetworkSettingsData::collectPossible( const char * Interfa /* Called by the system to see if interface can be brought UP if allowed, echo Interface-allowed else Interface-disallowed */ -void NetworkSettingsData::canStart( const char * Interface ) { +bool NetworkSettingsData::canStart( const char * Interface ) { // load situation NodeCollection * NC = 0; QList<NodeCollection> PossibleConnections; PossibleConnections = collectPossible( Interface ); + fprintf( stderr, "Possiblilies %d\n", + PossibleConnections.count() ); switch( PossibleConnections.count() ) { case 0 : // no connections break; case 1 : // one connection NC = PossibleConnections.first(); break; default : // need to ask user ? - // are we connected to a server - // system( "su %d networksettings2 --prompt %s\n", - // "", Interface ); - break; + return 1; } if( NC ) { switch( NC->state() ) { case Unchecked : case Unknown : @@ -407,18 +410,19 @@ void NetworkSettingsData::canStart( const char * Interface ) { } // FT case Available : case IsUp : // also called for 'ifdown' // device is ready -> done printf( "%s-c%d-allowed\n", Interface, NC->number() ); - return; + return 0; } - } else { - // if we come here no alternatives are possible - printf( "%s-cnn-disallowed\n", Interface ); - } + } + + // if we come here no alternatives are possible + printf( "%s-cnn-disallowed\n", Interface ); + return 0; } /* Called by the system to regenerate config files */ diff --git a/noncore/settings/networksettings2/nsdata.h b/noncore/settings/networksettings2/nsdata.h index b54df24..eb96930 100644 --- a/noncore/settings/networksettings2/nsdata.h +++ b/noncore/settings/networksettings2/nsdata.h @@ -18,13 +18,14 @@ public : bool isModified( void ) { return IsModified; } void setModified( bool m ) { IsModified = m; } QList<NodeCollection> collectPossible( const char * Interface ); - void canStart( const char * Interface ); + // return TRUE if we need gui to decide + bool canStart( const char * Interface ); bool regenerate( void ); void forceGeneration( bool m ) { Force = m; } private : |