The branch, master has been updated via c1a3f45560beaa84b933762bf526d466e489511e (commit) from dc0e5721b977a248c2b1e0b7e26b4549ed996d92 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit c1a3f45560beaa84b933762bf526d466e489511e Author: Oleksandr Shneyder <oleksandr.shneyder@treuchtlingen.de> Date: Wed Feb 1 14:07:10 2012 +0100 Modification of X2Go concept/protocol related to port detection: - remove ports used by X2Go session from database after session was finished if postgres backend is used. - before resuming X2Go session check if reserved ports still available in other case find new free ports, save them in database and send to x2goclient - run netstat -tl --all to find free ports for graphic, sound and sshfs tunnels in x2gostartagent and x2goresume-session - this modification approach maintains compatibility with older x2goclients for 99% of the server-client session connections. ----------------------------------------------------------------------- Summary of changes: debian/changelog | 11 ++++ x2goserver/bin/x2goresume-session | 67 ++++++++++++++++++++++++- x2goserver/bin/x2gostartagent | 17 +++---- x2goserver/lib/x2godbwrapper.pm | 56 +++++++++++++++------ x2goserver/lib/x2goresume | 5 ++- x2goserver/lib/{x2goinsertport => x2gormport} | 3 +- x2goserver/lib/x2gosqlitewrapper.pl | 18 ++++++- x2goserver/sbin/x2godbadmin | 4 +- 8 files changed, 149 insertions(+), 32 deletions(-) copy x2goserver/lib/{x2goinsertport => x2gormport} (95%) The diff of changes is: diff --git a/debian/changelog b/debian/changelog index 41e44b5..c7e72b0 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,7 +1,18 @@ x2goserver (3.1.0.0-0~x2go1) UNRELEASED; urgency=low + [ Mike Gabriel ] * Continue development... + [ Oleksandr Shneyder ] + * New upstream version (3.1.0.0) + - remove ports used by X2Go session from database after session was finished + if postgres backend is used. + - before resuming X2Go session check if reserved ports still available + in other case find new free ports, save them in database and send to + x2goclient + - run netstat -tl --all to find free ports for graphic, sound and sshfs + tunnels in x2gostartagent and x2goresume-session + -- Mike Gabriel <mike.gabriel@das-netzwerkteam.de> Wed, 01 Feb 2012 13:45:00 +0100 x2goserver (3.0.99.10-0~x2go1) unstable; urgency=low diff --git a/x2goserver/bin/x2goresume-session b/x2goserver/bin/x2goresume-session index 9023e86..009fd1d 100755 --- a/x2goserver/bin/x2goresume-session +++ b/x2goserver/bin/x2goresume-session @@ -54,6 +54,65 @@ then X2GO_FULLSCREEN=1 fi + +SESSIONINFO=`x2golistsessions | grep ${SESSION_NAME} | sed "s/|/,/g"` + +GR_PORT=`echo "$SESSIONINFO" | awk -F, {'print $9'}` +SOUND_PORT=`echo "$SESSIONINFO" | awk -F, {'print $10'}` +FS_PORT=`echo "$SESSIONINFO" | awk -F, {'print $14'}` +SERVER=`echo "$SESSIONINFO" | awk -F, {'print $4'}` + +$X2GO_LIB_PATH/x2gosyslog "$0" "debug" "old ports: $GR_PORT, $SOUND_PORT, $FS_PORT" + +#Get all used in system ports from netstat output +SYSTEM_PORTS=`netstat -nt -all | awk '{ n=split($0,lines,"\n"); for(i=1;i<=n;i++){split (lines[i],words," ");delim=split(words[4],ports,":"); if(delim>1)printf ("|%s|\n",ports[delim])} }'` + +#check if saved in DB ports free +if grep -q "|${GR_PORT}|" <<<$SYSTEM_PORTS ; then + $X2GO_LIB_PATH/x2gosyslog "$0" "debug" "port $GR_PORT is already in use" + $X2GO_LIB_PATH/x2gormport $HOSTNAME $SESSION_NAME $GR_PORT + GR_PORT="" +fi +if grep -q "|${SOUND_PORT}|" <<<$SYSTEM_PORTS ; then + $X2GO_LIB_PATH/x2gosyslog "$0" "debug" "port $SOUND_PORT is already in use" + $X2GO_LIB_PATH/x2gormport $HOSTNAME $SESSION_NAME $SOUND_PORT + SOUND_PORT="" +fi +if grep -q "|${FS_PORT}|" <<<$SYSTEM_PORTS ; then + $X2GO_LIB_PATH/x2gosyslog "$0" "debug" "port $FS_PORT is already in use" + $X2GO_LIB_PATH/x2gormport $HOSTNAME $SESSION_NAME $FS_PORT + FS_PORT="" +fi + +SSH_PORT=30000 #First ssh port 30001 + +#Get all used in system ports from X2Go database and netstat output +USED_PORTS=`$X2GO_LIB_PATH/x2gogetports $HOSTNAME ; netstat -nt -all | awk '{ n=split($0,lines,"\n"); for(i=1;i<=n;i++){split (lines[i],words," ");delim=split(words[4],ports,":"); if(delim>1)printf ("|%s|\n",ports[delim])} }'` + +while [ "$GR_PORT" == "" ] || [ "$SOUND_PORT" == "" ] || [ "$FS_PORT" == "" ]; do + OUTPUT="" + while [ "$OUTPUT" != "inserted" ]; do + SSH_PORT=$(($SSH_PORT + 1)) + + #get free port + SSH_PORT=`echo "for(\\$i=$SSH_PORT;\\$br ne \"true\";\\$i++){ if(\"$USED_PORTS\" =~ m/\\|\\$i\\|/){\\$br=\"false\";}else{\\$br=\"true\";print \\$i;}}"|perl` + + #check if port in /etc/services + SERV=`grep $SSH_PORT /etc/services` + if [ "$SERV" == "" ]; then + OUTPUT=`$X2GO_LIB_PATH/x2goinsertport $HOSTNAME $SESSION_NAME $SSH_PORT` + fi + done + if [ "$GR_PORT" == "" ]; then + GR_PORT=$SSH_PORT + elif [ "$SOUND_PORT" == "" ]; then + SOUND_PORT=$SSH_PORT + else + FS_PORT=$SSH_PORT + fi +done + + SESSION_DIR=${X2GO_ROOT}/C-${SESSION_NAME} OPTIONS=`cat ${SESSION_DIR}/options` @@ -63,6 +122,8 @@ FSTR=`echo "$OPTIONS" | awk -F, {'print $15'}` LSTR=`echo "$OPTIONS" | awk -F, {'print $2'}` PSTR=`echo "$OPTIONS" | awk -F, {'print $3'}` KTSTR=`echo "$OPTIONS" | awk -F, {'print $12'}` +LISTSTR=`echo "$OPTIONS" | awk -F, {'print $17'}` + KTSTR=`echo $KTSTR | sed "s/\//\\\\\\\\\//"` X2GO_KBD_TYPE=`echo $X2GO_KBD_TYPE | sed "s/\//\\\\\\\\\//"` @@ -77,6 +138,7 @@ NEWOPTIONS=`echo "$OPTIONS" | sed -e "s/$LSTR/link=$X2GO_LINK/"\ -e "s/$KTSTR/kbtype=$X2GO_KBD_TYPE/"\ -e "s/$GSTR/geometry=$X2GO_GEOMETRY/"\ -e "s/$RSTR/resize=$X2GO_RESIZE/"\ + -e "s/$LISTSTR/listen=$GR_PORT/"\ -e "s/$FSTR/fullscreen=$X2GO_FULLSCREEN/"` X2GO_CLIENT=`echo $SSH_CLIENT | awk '{print $1}'` @@ -87,7 +149,7 @@ fi echo "$NEWOPTIONS" >${SESSION_DIR}/options -$X2GO_LIB_PATH/x2goresume $X2GO_CLIENT $SESSION_NAME > /dev/null +$X2GO_LIB_PATH/x2goresume $X2GO_CLIENT $SESSION_NAME $GR_PORT $SOUND_PORT $FS_PORT > /dev/null # run x2goserver-extensions for pre-resume x2gofeature X2GO_RUN_EXTENSIONS &>/dev/null && x2goserver-run-extensions $SESSION_NAME pre-resume || true @@ -115,3 +177,6 @@ kill -HUP $X2GO_AGENT_PID &>/dev/null && { } +echo "gr_port=$GR_PORT" +echo "sound_port=$SOUND_PORT" +echo "fs_port=$FS_PORT" diff --git a/x2goserver/bin/x2gostartagent b/x2goserver/bin/x2gostartagent index a4952bc..3b802b4 100755 --- a/x2goserver/bin/x2gostartagent +++ b/x2goserver/bin/x2gostartagent @@ -116,6 +116,9 @@ fi USED_DISPLAYS=`$X2GO_LIB_PATH/x2gogetdisplays $HOSTNAME` +#Get all used in system ports from X2Go database and netstat output +USED_PORTS=`$X2GO_LIB_PATH/x2gogetports $HOSTNAME ; netstat -nt -all | awk '{ n=split($0,lines,"\n"); for(i=1;i<=n;i++){split (lines[i],words," ");delim=split(words[4],ports,":"); if(delim>1)printf ("|%s|\n",ports[delim])} }'` + while [ "$OUTPUT" != "inserted" ]; do X2GO_PORT=$(($X2GO_PORT + 1)) @@ -125,7 +128,7 @@ while [ "$OUTPUT" != "inserted" ]; do NX_PORT=$(($X2GO_PORT + 6000)) if [ -e "/tmp/.X${X2GO_PORT}-lock" ] || [ -e "/tmp/.X11-unix/X${X2GO_PORT}" ] || - netstat -ntl 2>/dev/null | grep -q ":${NX_PORT} "; then + grep -q "|${NX_PORT}|" <<<$USED_PORTS ; then OUTPUT="XXX" else SESSION_NAME=${USER}-${X2GO_PORT}-`date +"%s"` @@ -138,24 +141,18 @@ while [ "$OUTPUT" != "inserted" ]; do done -USED_PORTS=`$X2GO_LIB_PATH/x2gogetports $HOSTNAME` - - while [ "$GR_PORT" == "" ] || [ "$SOUND_PORT" == "" ] || [ "$FS_PORT" == "" ]; do OUTPUT="" while [ "$OUTPUT" != "inserted" ]; do SSH_PORT=$(($SSH_PORT + 1)) - #check if port in /etc/services + #get free port SSH_PORT=`echo "for(\\$i=$SSH_PORT;\\$br ne \"true\";\\$i++){ if(\"$USED_PORTS\" =~ m/\\|\\$i\\|/){\\$br=\"false\";}else{\\$br=\"true\";print \\$i;}}"|perl` + #check if port in /etc/services SERV=`grep $SSH_PORT /etc/services` if [ "$SERV" == "" ]; then - CR=`echo "use IO::Socket; \\$sock = new IO::Socket::INET ( LocalAddr => 'localhost',LocalPort => \"$SSH_PORT\",\ - Proto => 'tcp',Listen => 1,Reuse =>1 ) or die ;print \"OK\";close(\\$sock);"|perl 2>/dev/null` - if [ "$CR" == "OK" ]; then - OUTPUT=`$X2GO_LIB_PATH/x2goinsertport $HOSTNAME $SESSION_NAME $SSH_PORT` - fi + OUTPUT=`$X2GO_LIB_PATH/x2goinsertport $HOSTNAME $SESSION_NAME $SSH_PORT` fi done if [ "$GR_PORT" == "" ]; then diff --git a/x2goserver/lib/x2godbwrapper.pm b/x2goserver/lib/x2godbwrapper.pm index df707df..aec0294 100644 --- a/x2goserver/lib/x2godbwrapper.pm +++ b/x2goserver/lib/x2godbwrapper.pm @@ -86,7 +86,7 @@ if ($backend eq 'postgres') use base 'Exporter'; our @EXPORT=('db_listsessions','db_listsessions_all', 'db_getservers', 'db_getagent', 'db_resume', 'db_changestatus', - 'db_getdisplays', 'db_insertsession', 'db_getports', 'db_insertport', 'db_createsession', 'db_insertmount', + 'db_getdisplays', 'db_insertsession', 'db_getports', 'db_insertport', 'db_rmport', 'db_createsession', 'db_insertmount', 'db_getmounts', 'db_deletemount', 'db_getdisplay', 'dbsys_getmounts', 'dbsys_listsessionsroot', 'dbsys_listsessionsroot_all', 'dbsys_rmsessionsroot'); @@ -100,6 +100,8 @@ sub dbsys_rmsessionsroot my $sth=$dbh->prepare("delete from sessions where session_id='$sid'"); $sth->execute() or die; + $sth=$dbh->prepare("delete from used_ports where session_id='$sid'"); + $sth->execute() or die; } if($backend eq 'sqlite') { @@ -230,7 +232,7 @@ sub db_deletemount my $path=shift or die "argument \"path\" missed"; if ($backend eq 'postgres') { - my $dbh=DBI->connect("dbi:Pg:dbname=$db;host=$host;port=$port;sslmode=$sslmode", "$dbuser", "$dbpass",{AutoCommit => 1}) or die $_; + my $dbh=DBI->connect("dbi:Pg:dbname=$db;host=$host;port=$port;sslmode=$sslmode", "$dbuser", "$dbpass",{AutoCommit => 1}) or die $_; my $sth=$dbh->prepare("delete from mounts_view where session_id='$sid' and path='$path'"); $sth->execute(); $sth->finish(); @@ -251,7 +253,7 @@ sub db_insertmount my $res_ok=0; if ($backend eq 'postgres') { - my $dbh=DBI->connect("dbi:Pg:dbname=$db;host=$host;port=$port;sslmode=$sslmode", "$dbuser", "$dbpass",{AutoCommit => 1}) or die $_; + my $dbh=DBI->connect("dbi:Pg:dbname=$db;host=$host;port=$port;sslmode=$sslmode", "$dbuser", "$dbpass",{AutoCommit => 1}) or die $_; my $sth=$dbh->prepare("insert into mounts (session_id,path,client) values ('$sid','$path','$client')"); $sth->execute(); if (!$sth->err()) @@ -279,7 +281,7 @@ sub db_insertsession my $sid=shift or die "argument \"session_id\" missed"; if ($backend eq 'postgres') { - my $dbh=DBI->connect("dbi:Pg:dbname=$db;host=$host;port=$port;sslmode=$sslmode", "$dbuser", "$dbpass",{AutoCommit => 1}) or die $_; + my $dbh=DBI->connect("dbi:Pg:dbname=$db;host=$host;port=$port;sslmode=$sslmode", "$dbuser", "$dbpass",{AutoCommit => 1}) or die $_; my $sth=$dbh->prepare("insert into sessions (display,server,uname,session_id) values ('$display','$server','$uname','$sid')"); $sth->execute()or die $_; $sth->finish(); @@ -307,7 +309,7 @@ sub db_createsession my $sid=shift or die "argument \"session_id\" missed"; if ($backend eq 'postgres') { - my $dbh=DBI->connect("dbi:Pg:dbname=$db;host=$host;port=$port;sslmode=$sslmode", "$dbuser", "$dbpass",{AutoCommit => 1}) or die $_; + my $dbh=DBI->connect("dbi:Pg:dbname=$db;host=$host;port=$port;sslmode=$sslmode", "$dbuser", "$dbpass",{AutoCommit => 1}) or die $_; my $sth=$dbh->prepare("update sessions_view set status='R',last_time=now(), cookie='$cookie',agent_pid='$pid',client='$client',gr_port='$gr_port', sound_port='$snd_port',fs_port='$fs_port' where session_id='$sid'"); @@ -333,7 +335,7 @@ sub db_insertport my $sshport=shift or die "argument \"port\" missed"; if ($backend eq 'postgres') { - my $dbh=DBI->connect("dbi:Pg:dbname=$db;host=$host;port=$port;sslmode=$sslmode", "$dbuser", "$dbpass",{AutoCommit => 1}) or die $_; + my $dbh=DBI->connect("dbi:Pg:dbname=$db;host=$host;port=$port;sslmode=$sslmode", "$dbuser", "$dbpass",{AutoCommit => 1}) or die $_; my $sth=$dbh->prepare("insert into used_ports (server,session_id,port) values ('$server','$sid','$sshport')"); $sth->execute()or die; $sth->finish(); @@ -346,32 +348,56 @@ sub db_insertport syslog('debug', "db_insertport called, session ID: $sid, server: $server, SSH port: $sshport"); } +sub db_rmport +{ + my $server=shift or die "argument \"server\" missed"; + my $sid=shift or die "argument \"session_id\" missed"; + my $sshport=shift or die "argument \"port\" missed"; + if ($backend eq 'postgres') + { + my $dbh=DBI->connect("dbi:Pg:dbname=$db;host=$host;port=$port;sslmode=$sslmode", "$dbuser", "$dbpass",{AutoCommit => 1}) or die $_; + my $sth=$dbh->prepare("delete from used_ports where server='$server' and session_id='$sid' and port='$sshport'"); + $sth->execute()or die; + $sth->finish(); + $dbh->disconnect(); + } + if ($backend eq 'sqlite') + { + `$x2go_lib_path/x2gosqlitewrapper rmport $server $sid $sshport`; + } + syslog('debug', "db_rmport called, session ID: $sid, server: $server, SSH port: $sshport"); +} + sub db_resume { my $client=shift or die "argument \"client\" missed"; - my $sid=shift or die "argument \"session_id\" missed"; + my $sid=shift or die "argument \"session_id\" missed"; + my $gr_port=shift or die "argument \"gr_port\" missed"; + my $sound_port=shift or die "argument \"sound_port\" missed"; + my $fs_port=shift or die "argument \"fs_port\" missed"; if ($backend eq 'postgres') { - my $dbh=DBI->connect("dbi:Pg:dbname=$db;host=$host;port=$port;sslmode=$sslmode", "$dbuser", "$dbpass",{AutoCommit => 1}) or die $_; - my $sth=$dbh->prepare("update sessions_view set last_time=now(),status='R',client='$client' where session_id = '$sid'"); + my $dbh=DBI->connect("dbi:Pg:dbname=$db;host=$host;port=$port;sslmode=$sslmode", "$dbuser", "$dbpass",{AutoCommit => 1}) or die $_; + my $sth=$dbh->prepare("update sessions_view set last_time=now(),status='R',client='$client',gr_port='$gr_port', + sound_port='$sound_port',fs_port='$fs_port' where session_id = '$sid'"); $sth->execute()or die; $sth->finish(); $dbh->disconnect(); } if ($backend eq 'sqlite') { - `$x2go_lib_path/x2gosqlitewrapper resume $client $sid`; + `$x2go_lib_path/x2gosqlitewrapper resume $client $sid $gr_port $sound_port $fs_port`; } - syslog('debug', "db_resume called, session ID: $sid, client: $client"); + syslog('debug', "db_resume called, session ID: $sid, client: $client, gr_port: $gr_port, sound_port: $sound_port, fs_port: $fs_port"); } sub db_changestatus { my $status=shift or die "argument \"status\" missed"; - my $sid=shift or die "argument \"session_id\" missed"; + my $sid=shift or die "argument \"session_id\" missed"; if ($backend eq 'postgres') { - my $dbh=DBI->connect("dbi:Pg:dbname=$db;host=$host;port=$port;sslmode=$sslmode", "$dbuser", "$dbpass",{AutoCommit => 1}) or die $_; + my $dbh=DBI->connect("dbi:Pg:dbname=$db;host=$host;port=$port;sslmode=$sslmode", "$dbuser", "$dbpass",{AutoCommit => 1}) or die $_; my $sth=$dbh->prepare("update sessions_view set last_time=now(),status='$status' where session_id = '$sid'"); $sth->execute()or die; $sth->finish(); @@ -388,7 +414,7 @@ sub db_getdisplays { my @displays; #ignore $server - my $server=shift or die "argument \"server\" missed"; + my $server=shift or die "argument \"server\" missed"; if ($backend eq 'postgres') { my @strings; @@ -418,7 +444,7 @@ sub db_getports { my @ports; #ignore $server - my $server=shift or die "argument \"server\" missed"; + my $server=shift or die "argument \"server\" missed"; if ($backend eq 'postgres') { my @strings; diff --git a/x2goserver/lib/x2goresume b/x2goserver/lib/x2goresume index 2e64542..7391cd3 100755 --- a/x2goserver/lib/x2goresume +++ b/x2goserver/lib/x2goresume @@ -33,8 +33,11 @@ setlogmask( LOG_UPTO(x2gologlevel()) ); my $client=shift or die; my $sid=shift or die; +my $gr_port=shift or die; +my $snd_port=shift or die; +my $fs_port=shift or die; -db_resume($client, $sid); +db_resume($client, $sid, $gr_port, $snd_port, $fs_port); # closing syslog closelog; diff --git a/x2goserver/lib/x2goinsertport b/x2goserver/lib/x2gormport similarity index 95% copy from x2goserver/lib/x2goinsertport copy to x2goserver/lib/x2gormport index bc18d96..4ba632d 100755 --- a/x2goserver/lib/x2goinsertport +++ b/x2goserver/lib/x2gormport @@ -35,8 +35,7 @@ my $server=shift or die; my $sid=shift or die; my $port=shift or die; -db_insertport($server,$sid,$port); -print "inserted"; +db_rmport($server,$sid,$port); # closing syslog closelog; \ No newline at end of file diff --git a/x2goserver/lib/x2gosqlitewrapper.pl b/x2goserver/lib/x2gosqlitewrapper.pl index 53041f8..ac8a7c6 100755 --- a/x2goserver/lib/x2gosqlitewrapper.pl +++ b/x2goserver/lib/x2gosqlitewrapper.pl @@ -153,14 +153,28 @@ elsif($cmd eq "insertport") $sth->finish(); } +elsif($cmd eq "rmport") +{ + my $server=shift or die "argument \"server\" missed"; + my $sid=shift or die "argument \"session_id\" missed"; + my $sshport=shift or die "argument \"port\" missed"; + my $sth=$dbh->prepare("delete from used_ports where server=? and session_id=? and port=?"); + check_user($sid); + $sth->execute($server, $sid, $sshport) or die; + $sth->finish(); +} + elsif($cmd eq "resume") { my $client=shift or die "argument \"client\" missed"; my $sid=shift or die "argument \"session_id\" missed"; + my $gr_port=shift or die "argument \"gr_port\" missed"; + my $sound_port=shift or die "argument \"sound_port\" missed"; + my $fs_port=shift or die "argument \"fs_port\" missed"; check_user($sid); my $sth=$dbh->prepare("update sessions set last_time=datetime('now','localtime'),status='R', - client=? where session_id = ? and uname=?"); - $sth->execute($client, $sid, $realuser) or die; + client=?,gr_port=?,sound_port=?,fs_port=? where session_id = ? and uname=?"); + $sth->execute($client, $gr_port, $sound_port, $fs_port, $sid, $realuser) or die; $sth->finish(); } diff --git a/x2goserver/sbin/x2godbadmin b/x2goserver/sbin/x2godbadmin index 84dfc5d..fc86ca8 100755 --- a/x2goserver/sbin/x2godbadmin +++ b/x2goserver/sbin/x2godbadmin @@ -333,6 +333,9 @@ sub add_user() $sth=$dbh->prepare("GRANT INSERT, UPDATE, DELETE ON sessions, used_ports, mounts TO \"x2gouser_$user\""); $sth->execute(); + $sth=$dbh->prepare("GRANT SELECT ON used_ports TO \"x2gouser_$user\""); + $sth->execute(); + $sth=$dbh->prepare("GRANT SELECT, UPDATE, DELETE ON sessions_view, mounts_view, servers_view, ports_view TO \"x2gouser_$user\""); $sth->execute(); $sth->finish(); @@ -455,7 +458,6 @@ sub create_tables() "); $sth->execute() or die; - $sth=$dbh->prepare(" create or replace RULE insert_port_priv AS ON INSERT TO used_ports where NEW.creator_id <> current_user and current_user <> '$x2goadmin' hooks/post-receive -- x2goserver.git (X2Go Server) This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "x2goserver.git" (X2Go Server).