Bugzilla – Attachment 213 Details for
Bug 479
add description how to run a ssh tunnel without a full shell on the remote site
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
scvs - a perl script
scvs (text/plain), 14.55 KB, created by
Ralf Hauser
on 2003-01-31 02:59:02 AEDT
(
hide
)
Description:
scvs - a perl script
Filename:
MIME Type:
Creator:
Ralf Hauser
Created:
2003-01-31 02:59:02 AEDT
Size:
14.55 KB
patch
obsolete
>#!/usr/bin/perl ># ># $Id: scvs,v 1.16 2003/01/30 15:18:02 sti Exp $ ># ># (c) 1999, Tim Hemel <tim@n2it.net> ># 2000, Michael Steiner <steiner@acm.org> (added a few safety checks; converted ># to a drop-in replacement for normal cvs, e.g., for emacs vc-mode; ># more command-line options, support for case where local pserver is running, ...) ># ># More info see http://cuba.xs4all.nl/~tim/scvs/. See also ># http://cuba.xs4all.nl/~tim/articles/Tunneling%20with%20SSH%20and%20SSL/ for an alternative solution ># based on SSL (via stunnel) ># ># SCVS - "secure cvs" ># ># scvs [-h(elp)|--help] [-D(ebug)] [+Z|-Z (zzh shell)] [-S ssh-user\@ssh-host] [+C|-C (new cvs version)] ># [-d real-cvsroot] [cvsoptions] cvscommand [cvscommandoptions] ># ># This program executes a cvs client and lets it run its traffic through an ># encrypted SSH tunnel. ># ># The remote repository can be specified on the commandline (e.g., with -d), ># or in the CVSROOT environment variable. For example: :pserver:cvs@cvs.n2it.net:/cvs. ># This option MUST be the FIRST of regular cvs options (but after special -D, +/-Z, -S and +/-C options) ># to scvs if it is given. ># IMPORTANT: The heuristics for chosing ssh tunneling is that there is a host given ># as 'localhost' or 127.0.0.1 and the method is 'pserver'. Otherwise, the script just ># hands over to vanilla cvs. I.e., to get ssh tunneling you have to checkout with ># something like "scvs ... -d :pserver:YOUR-ID@localhost:...."! ># ># After having checked out a file, the CVS/Root file contains the fake tunnel ># cvs server on the localhost. This saves you from using the -d option all the ># time. Be careful however when using both scvs and cvs on the same directory. ># Preferably all cvs traffic should be done with scvs. ># ># Note 0: You might have to change some of the settings below such as the paths. ># In particular, non-IBM users of the biblios repository do have to change ># SSH_DEFAULT_USER from "sirene-cvs-ibm" to "sirene-cvs-extern". ># ># Note 1: If you have local cvs server running, please check below where ># CVS_SUPPORTS_CLIENT_PORT is defined. ># ># Note 2: There is a heuristics which uses the ssh-tunneling only if the hostname ># specified in CVS/Root is localhost and the method is pserver. This allows using ># scvs in a transparent manner (e.g., ln -s ~/bin/scvs ~/bin/cvs) as cvs which is ># convenient in conjunction with Emacs VC-mode. ># ># Note 3: This script runs reasonably well on UNIXes such as Linux and ># SunOS. It runs also on Windows in conjunction with the cygnus ># toolkit which can be found on (http://sources.redhat.com/cygwin/). ># However, if you should make sure that you have a new version of the cygnus tools ># (an old one had problems in the ssh version that it did not go into the background ># appropriately with -f or &). Furthermore, it seems that on windows it might work better ># when you take the cvs command from WinCVS (http://www.wincvs.org/) instead of the ># one from cygnus (=> change CVS_CMD below or adapt /usr/bin/cvs in your cygnus ># filesystem accordingly ...) ># ># WARNINGS: ># ># - if scvs hangs it might be that ssh encounters a new server key and is waiting ># for your approval. Unfortunately, the corresponding stdout is eaten somewhere ># in this script. You might try just writing 'yes', but the better approach is to ># run ssh sepearately to approve the key. ># - Under some circumstances, you might have to hit Ctrl-return under win2k/cygwin ># when doing scvs login ># - The current cygwin cvs stumbles when meeting a CVS tree that was created by ># wincvs thus containing ^M and can result in update hanging. ># See http://ccvs.cvshome.org/issues/show_bug.cgi?id=92 ># - if you have a (local) firewall, make sure that you allow local TCP connections to remote ># hosts with port 22. If your firewall also controls localhost connection, you have ># to allow localhost connections to TCP port 2401 (if $CVS_SUPPORTS_CLIENT_PORT=0) ># or all localhost connections on TCP ports (if $CVS_SUPPORTS_CLIENT_PORT=1). ># ># TODO: ># ># * Implement better error detection and recovery. ># * Better parsing of the repository (it will not detect strange syntaxes). ># * Better command line option parsing ># > >############################################################################# ># CVS settings > >$CVS_CMD="/usr/bin/cvs"; > >$CVS_PORT=2401; > >############################################################################# ># SSH settings ># (These are the defaults: All except the first can be set on the command-line) > ># Use ssh v2 by default >$SSH_CMD="ssh -2"; # For commercial ssh it probably should be "ssh2", otherwise "ssh -2" > ># This should be the user on whose behalf the tunneling is made. It is ># typically a user that cannot do any harm, has no password and uses a program ># like nologin (but one that will wait) as a shell. >$SSH_DEFAULT_USER="sirene-cvs-ibm"; # alternatives: sirene-cvs-extern or sirene-cvs-ibm > ># This value is used if the repository cannot be determined from the ># commandline or the CVSROOT variable. Modify this for your local situation. >$SSH_DEFAULT_HOST="ftp.semper.org"; > ># Port at which the sshd on the remote server runs. Default is 22. ># $SSH_PORT=22; > ># User has zzh dummy login shell on server (default). If 0, we assume the user ># has a login shell which knows how to handle 'sleep 10' (e.g., a standard login ># shell with 'sleep' in the path or a customized which just hangs enough in the ># background that the tunnel is still alive when cvs is started. (However, note ># that if the user has a standard login shell, you might be better off to simply ># define the environment variable 'CVS_RSH' as 'ssh' and check out the ># repository with '-d :ext:user@host:cvs-directory' ...). Except for ># read-only cvs users it probably doesn't make a real security difference given ># the difficulties one has in setting restricted permissions in CVSROOT ># and all the executable scripts laying around there .. >$SSH_ZZH_LOGIN_SHELL=1; > ># The default of the local port is also the standard CVS pserver port. However, ># if locally a cvs server running then this will not work. ># (a) new cvs version (>= 1.11.1) ># These versions allow to override the port number via the environment ># variable 'CVS_CLIENT_PORT'. (Note that it would now also be possible to ># encode it into the repository-string with the new extended syntax ># ":pserver:[[user][:password]@]host[:[port]]/path". However, using the ># environment variable seems more flexible. ># (b) old cvs version (< 1.11.1) ># In these versions there is no way to specify a different port number to ># cvs. This means that all scvs clients on the same machine need to share ># port 2041. This is possible for all users sharing the same remote-user id, ># only the ssh tunneling will fail, so our program should detect that and ># continue anyway. However, for users with different remote ids a collision ># of usage will result in an error. ># In any case it also means that you _cannot_ run a local CVS pserver! ># A successful connection is then only possible if the other users know the ># password for $SSH_USER@$SSH_HOST, or if there is no password. >$CVS_SUPPORTS_CLIENT_PORT=1; # default is on the safe side > >############################################################################# ># & parse_repository ({{rep}}) ># . extracts the method, user, host, port and directory from {{rep}}. ># . There are four possibilities: ># - /path/to/repository ># - :method:/path/to/repository ># - :user@hostname:/path/to/repository ># - :method:user@hostname:/path/to/repository ># ># . This function is far from perfect and will produce strange results with ># non-standard repositories. Has only been tested for :pserver: method. ># >sub parse_repository >{ > my $rep = $_[0]; > my ($dir,$user,$host,$method); > > # determine the directory > $rep =~ s/:(\/.*)$// && do { $dir=$1; }; > if (not $dir) > { $rep =~ s/(\/.*)$// && do {$dir = $1; }; } > > # determine the hostname and the username > $rep =~ s/:([^:]*)@(.*)$// && do { $user = $1; $host = $2; }; > if (not $host) > { $rep =~ s/:([^:]+)$// && do { $host = $1; }; } > > # all that is left now is the method > $rep =~ s/^:([^:]*)// && do { $method = $1; }; > > # if there is still anything left, we have an error, warn the user > if ($rep) > { print STDERR "Warning: repository parsed wrong ('$rep' ignored).\n"; } > > #print STDERR "DEBUG: dir=$dir, user=$user, host=$host, method=$method\n"; > return ($method, $user, $host, $dir); >} > >sub get_current_cvsroot { > -d "./CVS/" || return undef; # if we start a repository that's legal > -f "./CVS/Root" || die "invalid directory CVS: no ./CVS/Root file\n$usage"; > > open(ROOT, "./CVS/Root") || die "can't open './CVS/Root'\n$usage"; > return <ROOT>; >} > > >############################################################################# ># main > >$usage="Usage: scvs [-h(elp)|--help] [-D(ebug)] [+Z|-Z (zzh shell (default:".($SSH_ZZH_LOGIN_SHELL?"+Z":"-Z")."))] [-S ssh-user\@ssh-host (default: $SSH_DEFAULT_USER\@$SSH_DEFAULT_HOST)] [+C|-C (new cvs version (default:".($CVS_SUPPORTS_CLIENT_PORT?"+C":"-C").")] [-d real-cvsroot] [cvsoptions] cvscommand [cvscommandoptions] > SSH-wrapper around cvs for :pserver: repositories\n"; > > > >if (($ARGV[0] eq "-h") || ($ARGV[0] eq "--help")) { > print STDERR $usage; > system("$CVS_CMD --help"); > exit 0; >} > ># should be changed to a general cmdline parsing routine. ># get the repository's name from the commandline or the CVSROOT environment ># variable. >if ($ARGV[0] eq "-D") { > $debug=1; > print STDERR "DEBUG: called as ``$0'' ``".join("'' ``", @ARGV)."''\n"; > shift; >} > >if ($ARGV[0] eq "-Z") { > $SSH_ZZH_LOGIN_SHELL=0; > shift; >} elsif ($ARGV[0] eq "+Z") { > $SSH_ZZH_LOGIN_SHELL=1; > shift; >} >print STDERR "DEBUG: ssh user has ".($SSH_ZZH_LOGIN_SHELL?"zzh":"standard")." shell\n" if $debug; > >if ($ARGV[0] eq "-S") >{ > if ($ARGV[1] =~ /^(.*)?@(.*)?$/) { > $SSH_USER=$1; > $SSH_HOST=$2; > } else { > print STDERR "Error: Syntax of -S should be [ssh-user]@[ssh-host]\n$usage"; > exit -2; > } > shift; shift; >} > >if ($ARGV[0] eq "-C") { > $CVS_SUPPORTS_CLIENT_PORT=0; > shift; >} elsif ($ARGV[0] eq "+C") { > $CVS_SUPPORTS_CLIENT_PORT=1; > shift; >} >print STDERR "DEBUG: ssh user has ".($CVS_SUPPORTS_CLIENT_PORT?"new":"old")." cvs\n" if $debug; > >if ($ARGV[0] eq "-d") { > $rep="$ARGV[1]"; > $rep_cmdline=1; > shift; shift; >} elsif (chop($rep = &get_current_cvsroot())) { > $rep_cmdline=0; >} elsif ($rep = $ENV{'CVSROOT'}) { > $rep_cmdline=0; >} else { > die "No repository given\n$usage"; >} > ># parse the repository >($method, $user, $host, $dir) = &parse_repository($rep); >print STDERR "DEBUG: $rep => ('$method', '$user', '$host', '$dir') \n" if ($debug); > ># check if this is really a repository where ssh-tunneling is required ># The heuristics is that there is a host given as 'localhost' and the ># method is 'pserver'. Given that with scvs we anyway can't run a local pserver ># this is a safe bet. >if (($method !~ /pserver/i) || ($host !~ /(localhost|127\.0\.0\.1)/i)) { > # not a ssh-tunneled repository => call cvs immediately > # 1. concatenate and correctly quote (emacs VC-mode & -m !!) arguments > $cvs_args = ""; > if ($#ARGV >= 0) { > @cvs_args= (); > foreach $_ (@ARGV) { > ($cvs_args[++$#cvs_args] = $_ ) =~ s/'/'"'"'/g; #' > } > $cvs_args = "'".join("' '", @cvs_args)."'"; > } > # 2. add it to command. if required add also repository explicitly. > $cvs_cmd = "$CVS_CMD ".($rep_cmdline ? "-d " . $rep . " " : "").$cvs_args; > print STDERR "DEBUG: direct cvs-cmd: '$cvs_cmd' \n" if ($debug); > # 3. run command locally > $exitcode = system($cvs_cmd); > print STDERR "DEBUG: cvs-cmd exit: '$exitcode' = '(". > $exitcode/256 .",". $exitcode % 256 > .")'\n" if ($debug); > exit($exitcode); >} else { > # unset host here to get ssh-host set to default host (or host > # explicitly given with -S) > $host = undef; >} > ># construct the local fake cvs server name. >if ($method) { $cvs_serv = ":$method:"; } >if ($user) { $cvs_serv .= "$user\@"; } >if ($rep) { $cvs_serv .= "localhost:"; } >if ($dir) { $cvs_serv .= $dir; } > >print STDERR "DEBUG: cvs_serv = $cvs_serv\n" if ($debug); > ># construct the tunneling command >$SSH_HOST ||= $host; >$SSH_HOST ||= $SSH_DEFAULT_HOST; # if not already set, use defaults if existing >$SSH_USER ||= $SSH_DEFAULT_USER; # if not already set, use defaults if existing >if ($SSH_USER) > { $ssh_serv="$SSH_USER\@$SSH_HOST"; } >else > { $ssh_serv="$SSH_HOST"; } >print STDERR "DEBUG: SSH_HOST=$ssh_serv\n" if ($debug); > >if ($SSH_ZZH_LOGIN_SHELL) { > $remote_cmd = "open"; >} else { > $remote_cmd = "sleep 10"; >} > >if ($CVS_SUPPORTS_CLIENT_PORT){ > $SSH_LOCAL_PORT=sprintf("%d", 13000 + rand(1000)); # random port > $CVS_CMD="env CVS_CLIENT_PORT=$SSH_LOCAL_PORT ".$CVS_CMD; >} else { > $SSH_LOCAL_PORT=$CVS_PORT; >} > >$tunnel_cmd = "$SSH_CMD $ssh_serv -q -x" > . ( ($SSH_PORT) ? " -p $SSH_PORT" : "" ) > . " -L $SSH_LOCAL_PORT:localhost:$CVS_PORT ".$remote_cmd." &"; >print STDERR "DEBUG: tunnel-cmd: '$tunnel_cmd' \n" if ($debug); > ># execute the tunneling, and read the response from the server >if ($SSH_ZZH_LOGIN_SHELL) { > open (TUNNELSH,"$tunnel_cmd |") or die "Could not execute $tunnel_cmd!"; > chomp ($magicword = <TUNNELSH>); > print STDERR "magicword = $magicword!\n" if ($debug); >} else { > (system("$tunnel_cmd")==0) or die "Could not execute $tunnel_cmd!"; >} > ># Now we can call system to execute the cvs command. ># first concatentate the existing arguments and make sure that quotes are escaped! ># this is important to make it also work with emacs VC mode in case you use ># there quotes ... >$cvs_args = ""; >if ($#ARGV >= 0) { > @cvs_args= (); > foreach $_ (@ARGV) { > ($cvs_args[++$#cvs_args] = $_ ) =~ s/'/'"'"'/g;#' > } > $cvs_args = "'".join("' '", @cvs_args)."'"; >} ># then setup the whole cvs command >$cvs_cmd = "$CVS_CMD ". ( ($cvs_serv) ? ("-d '". $cvs_serv . "' ") : () ) . $cvs_args; >print STDERR "DEBUG: cvs-cmd: '$cvs_cmd' \n" if ($debug); >$exitcode = system($cvs_cmd); >print STDERR "DEBUG: cvs-cmd exit: '$exitcode' = '(". > $exitcode/256 .",". $exitcode % 256 > .")'\n" if ($debug); ># as cvs also returns exit-codes in normal operations (e.g., for diffs) ># there is no easy way to check here whether the cvs command worked or not > ># close the tunnel >if ($SSH_ZZH_LOGIN_SHELL) { > # terminate ZZH shell to terminate ssh session ... > $tunnel_close_cmd = > "$SSH_CMD $ssh_serv -q -x" > . ( ($SSH_PORT) ? " -p $SSH_PORT" : "" ) > . " $magicword"; > print STDERR "DEBUG: tunnel_close_cmd: '$tunnel_close_cmd' \n" if ($debug); > system($tunnel_close_cmd); # ignore return value, we just want to close ssh-session >} > >exit($exitcode/256); >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Raw
Actions:
View
Attachments on
bug 479
: 213 |
214