[rancid] fortinet problem

john heasley heas at shrubbery.net
Sat Oct 2 14:38:10 UTC 2010


Sat, Oct 02, 2010 at 08:39:40AM +0200, F?rtbauer Wolfgang:
> Dear John,
> 
> I finally found the patch: 
> http://www.shrubbery.net/pipermail/rancid-discuss/2009-June/004005.html
> and applied it (manually) against my rancid-2.3.4.
> It's working! Thanks a lot Diego!
> 
> Probalby this patch could be added to the main code?!
> 
> to answer your question John: the prompt ends with a '#' for readonly-users
> and a '$' for read-write users

Thanks.  When did this change from '->'?  is there a need to support the
old prompt?

> BR
> Wolfgang
> 
> 
> 
> Wolfgang F?rtbauer
> Leitung IT
> 
> ASAMER Holding AG
> Unterthalham Strasse 2
> 4694 Ohlsdorf
> AUSTRIA
> tel +43 50 799 - 2500
> fax +43 7612 799 - 9526
> mobile  +43 664 8332326
> w.fuertbauer at asamer.at
> www.asamer.at
> 
> 
> This message is confidential. It may not be disclosed to, or used by, anyone other than the addressee. If you receive this
> message by mistake, please advise the sender.
> 
> 
> 
> -----Urspr?ngliche Nachricht-----
> Von: john heasley [mailto:heas at shrubbery.net]
> Gesendet: Fr 01.10.2010 17:56
> An: F?rtbauer Wolfgang
> Cc: john heasley; rancid-discuss at shrubbery.net
> Betreff: Re: [rancid] fortinet problem
>  
> Fri, Oct 01, 2010 at 09:34:15AM +0200, F?rtbauer Wolfgang:
> > Dear John,
> > 
> > Output of nlogin is:
> > 
> > rancid at aohmonitoring01:~> nlogin <fortinet>
> > <fortinet>
> > spawn ssh -c 3des -x -l monitoring <fortinet>
> > monitoring@<fortinet>'s password:
> > FGT50A3906508751 #
> > FGT50A3906508751 # Timeout
> 
> wie geht es.  nlogin looks for the prompt to end with "-> "; why is it "#"
> here?  ISTR someone saying that the format had changed and trying to
> understand when and under what circumstances, but not being able to verify.
> 



Content-Description: rancid-2.3.4_fortigate_2x-3x.patch
> --- rancid-2.3.4/bin/Makefile.in	2010-10-02 08:31:22.000000000 +0200
> +++ rancid-patch/bin/Makefile.in	2010-10-02 08:29:48.000000000 +0200
> @@ -54,7 +54,7 @@
>  	$(srcdir)/hlogin.in $(srcdir)/hrancid.in $(srcdir)/htlogin.in \
>  	$(srcdir)/htrancid.in $(srcdir)/jerancid.in \
>  	$(srcdir)/jlogin.in $(srcdir)/jrancid.in $(srcdir)/mrancid.in \
> -	$(srcdir)/mrvlogin.in $(srcdir)/mrvrancid.in \
> +	$(srcdir)/mrvlogin.in $(srcdir)/mrvrancid.in $(srcdir)/fnlogin.in \
>  	$(srcdir)/nlogin.in $(srcdir)/nrancid.in $(srcdir)/nslogin.in \
>  	$(srcdir)/nsrancid.in $(srcdir)/nxrancid.in $(srcdir)/par.in \
>  	$(srcdir)/prancid.in $(srcdir)/rancid-fe.in \
> @@ -75,7 +75,7 @@
>  	arancid arrancid avologin avorancid blogin brancid cat5rancid \
>  	clogin rancid cssrancid elogin erancid f5rancid f10rancid \
>  	flogin francid fnrancid hlogin hrancid htlogin htrancid jlogin \
> -	jrancid jerancid mrancid mrvlogin mrvrancid nlogin nrancid \
> +	jrancid jerancid mrancid mrvlogin mrvrancid fnlogin nlogin nrancid \
>  	nslogin nsrancid nxrancid prancid rivlogin rivrancid rrancid \
>  	srancid tlogin tntlogin tntrancid trancid xrancid xrrancid \
>  	zrancid
> @@ -247,7 +247,7 @@
>  	blogin brancid cat5rancid clogin control_rancid cssrancid \
>  	elogin erancid f5rancid f10rancid flogin fnrancid francid \
>  	hlogin hrancid htlogin htrancid jerancid jlogin jrancid \
> -	mrancid mrvlogin mrvrancid nlogin nrancid nslogin nsrancid \
> +	mrancid mrvlogin mrvrancid fnlogin nlogin nrancid nslogin nsrancid \
>  	nxrancid par prancid rancid-fe rancid rivlogin rivrancid \
>  	rrancid srancid tlogin tntlogin tntrancid trancid xrancid \
>  	xrrancid zrancid lg.cgi lgform.cgi rancid-cvs rancid-run
> @@ -383,6 +383,8 @@
>  	cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
>  mrvrancid: $(top_builddir)/config.status $(srcdir)/mrvrancid.in
>  	cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
> +fnlogin: $(top_builddir)/config.status $(srcdir)/fnlogin.in
> +	cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
>  nlogin: $(top_builddir)/config.status $(srcdir)/nlogin.in
>  	cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
>  nrancid: $(top_builddir)/config.status $(srcdir)/nrancid.in
> --- rancid-2.3.4/bin/fnlogin.in	1970-01-01 01:00:00.000000000 +0100
> +++ rancid-patch/bin/fnlogin.in	2010-10-02 08:29:48.000000000 +0200
> @@ -0,0 +1,591 @@
> +#! @EXPECT_PATH@ --
> +##
> +## $Id: fnlogin.in,v 1.51 2009/04/16 21:22:58 heas Exp $
> +## patched to accomplish fortinet from nlogin
> +## by: Daniel G. Epstein <dan at rootlike.com>
> +## adapted by: Diego Ercolani <diego.ercolani at ssis.sm>
> +##
> +## @PACKAGE@ @VERSION@
> +## Copyright (c) 1997-2009 by Terrapin Communications, Inc.
> +## All rights reserved.
> +##
> +## This code is derived from software contributed to and maintained by
> +## Terrapin Communications, Inc. by Henry Kilmer, John Heasley, Andrew Partan,
> +## Pete Whiting, Austin Schutz, and Andrew Fort.
> +##
> +## Redistribution and use in source and binary forms, with or without
> +## modification, are permitted provided that the following conditions
> +## are met:
> +## 1. Redistributions of source code must retain the above copyright
> +##    notice, this list of conditions and the following disclaimer.
> +## 2. Redistributions in binary form must reproduce the above copyright
> +##    notice, this list of conditions and the following disclaimer in the
> +##    documentation and/or other materials provided with the distribution.
> +## 3. All advertising materials mentioning features or use of this software
> +##    must display the following acknowledgement:
> +##        This product includes software developed by Terrapin Communications,
> +##        Inc. and its contributors for RANCID.
> +## 4. Neither the name of Terrapin Communications, Inc. nor the names of its
> +##    contributors may be used to endorse or promote products derived from
> +##    this software without specific prior written permission.
> +## 5. It is requested that non-binding fixes and modifications be contributed
> +##    back to Terrapin Communications, Inc.
> +##
> +## THIS SOFTWARE IS PROVIDED BY Terrapin Communications, INC. AND CONTRIBUTORS
> +## ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
> +## TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
> +## PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COMPANY OR CONTRIBUTORS
> +## BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
> +## CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
> +## SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
> +## INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
> +## CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
> +## ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
> +## POSSIBILITY OF SUCH DAMAGE.
> +# 
> +#  The expect login scripts were based on Erik Sherk's gwtn, by permission.
> +# 
> +# Netscreen hacks implemented by Stephen Gill <gillsr at yahoo.com>.
> +# Fortinet hacks by Daniel G. Epstein <dan at rootlike.com>
> +#
> +# fnlogin - fortinet login
> +#
> +# Most options are intuitive for logging into a netscreen firewall.
> +#
> +# Misc notes
> +#      netscreen does not have the concept of "enable", once logged in, a
> +#      users permissions can not change.
> +
> +# Usage line
> +set usage "Usage: $argv0 \[-dSV\] \[-c command\] \[-Evar=x\] \
> +\[-f cloginrc-file\] \[-p user-password\] \
> +\[-s script-file\] \[-t timeout\] \[-u username\] \
> +\[-v vty-password\] \[-x command-file\] \
> +\[-y ssh_cypher_type\] router \[router...\]\n"
> +
> +# env(CLOGIN) may contain:
> +#      x == do not set xterm banner or name
> +
> +# Password file
> +set password_file $env(HOME)/.cloginrc
> +# Default is to login to the firewall
> +set do_command 0
> +set do_script 0
> +# The default is to look in the password file to find the passwords.  This
> +# tracks if we receive them on the command line.
> +set do_passwd 1
> +set do_enapasswd 1
> +# Save config, if prompted
> +set do_saveconfig 0
> +
> +# Find the user in the ENV, or use the unix userid.
> +if {[ info exists env(CISCO_USER) ]} {
> +    set default_user $env(CISCO_USER)
> +} elseif {[ info exists env(USER) ]} {
> +    set default_user $env(USER)
> +} elseif {[ info exists env(LOGNAME) ]} {
> +    set default_user $env(LOGNAME)
> +} else {
> +    # This uses "id" which I think is portable.  At least it has existed
> +    # (without options) on all machines/OSes I've been on recently -
> +    # unlike whoami or id -nu.
> +    if [ catch {exec id} reason ] {
> +       send_error "\nError: could not exec id: $reason\n"
> +       exit 1
> +    }
> +    regexp {\(([^)]*)} "$reason" junk default_user
> +}
> +if {[ info exists env(CLOGINRC) ]} {
> +    set password_file $env(CLOGINRC)
> +}
> +
> +# Sometimes firewall take awhile to answer (the default is 10 sec)
> +set timeout 45
> +
> +# Process the command line
> +for {set i 0} {$i < $argc} {incr i} {
> +    set arg [lindex $argv $i]
> +
> +    switch  -glob -- $arg {
> +       # Expect debug mode
> +       -d* {
> +           exp_internal 1
> +       # Username
> +       } -u* {
> +           if {! [  regexp .\[uU\](.+) $arg ignore user]} {
> +               incr i
> +               set username [ lindex $argv $i ]
> +           }
> +       # VTY Password
> +       } -p* {
> +           if {! [  regexp .\[pP\](.+) $arg ignore userpasswd]} {
> +               incr i
> +               set userpasswd [ lindex $argv $i ]
> +           }
> +           set do_passwd 0
> +       # Environment variable to pass to -s scripts
> +       } -E* {
> +           if {[ regexp .\[E\](.+)=(.+) $arg ignore varname varvalue]} {
> +               set E$varname $varvalue
> +           } else {
> +               send_user "\nError: invalid format for -E in $arg\n"
> +               exit 1
> +           }
> +       # Command to run.
> +       } -c* {
> +           if {! [  regexp .\[cC\](.+) $arg ignore command]} {
> +               incr i
> +               set command [ lindex $argv $i ]
> +           }
> +           set do_command 1
> +       # Expect script to run.
> +       } -s* {
> +           if {! [  regexp .\[sS\](.+) $arg ignore sfile]} {
> +               incr i
> +               set sfile [ lindex $argv $i ]
> +           }
> +           if { ! [ file readable $sfile ] } {
> +               send_user "\nError: Can't read $sfile\n"
> +               exit 1
> +           }
> +           set do_script 1
> +       # save config on exit
> +       } -S* {
> +           set do_saveconfig 1
> +       # cypher type
> +        } -y* {
> +            if {! [  regexp .\[eE\](.+) $arg ignore cypher]} {
> +                incr i
> +                set cypher [ lindex $argv $i ]
> +            }
> +       # alternate cloginrc file
> +       } -f* {
> +           if {! [ regexp .\[fF\](.+) $arg ignore password_file]} {
> +               incr i
> +               set password_file [ lindex $argv $i ]
> +           }
> +       } -t* {
> +           incr i
> +           set timeout [ lindex $argv $i ]
> +        } -x* {
> +            if {! [  regexp .\[xX\](.+) $arg ignore cmd_file]} {
> +                incr i
> +                set cmd_file [ lindex $argv $i ]
> +            }
> +           if [ catch {set cmd_fd [open $cmd_file r]} reason ] {
> +               send_user "\nError: $reason\n"
> +               exit 1
> +           }
> +            set cmd_text [read $cmd_fd]
> +            close $cmd_fd
> +            set command [join [split $cmd_text \n] \;]
> +            set do_command 1
> +       # Version string
> +       } -V* {
> +           send_user "@PACKAGE@ @VERSION@\n"
> +           exit 0
> +       # Does tacacs automatically enable us?
> +        } -autoenable {
> +           # ignore autoenable
> +       } -* {
> +           send_user "\nError: Unknown argument! $arg\n"
> +           send_user $usage
> +           exit 1
> +       } default {
> +           break
> +       }
> +    }
> +}
> +# Process firewalls...no firewalls listed is an error.
> +if { $i == $argc } {
> +    send_user "\nError: $usage"
> +}
> +
> +# Only be quiet if we are running a script (it can log its output
> +# on its own)
> +if { $do_script } {
> +    log_user 0
> +} else {
> +    log_user 1
> +}
> +
> +#
> +# Done configuration/variable setting.  Now run with it...
> +#
> +
> +# Sets Xterm title if interactive...if its an xterm and the user cares
> +proc label { host } {
> +    global env
> +    # if CLOGIN has an 'x' in it, don't set the xterm name/banner
> +    if [info exists env(CLOGIN)] {
> +       if {[string first "x" $env(CLOGIN)] != -1} { return }
> +    }
> +    # take host from ENV(TERM)
> +    if [info exists env(TERM)] {
> +       if [regexp \^(xterm|vs) $env(TERM) ignore ] {
> +           send_user "\033]1;[lindex [split $host "."] 0]\a"
> +           send_user "\033]2;$host\a"
> +        }
> +    }
> +}
> +
> +# This is a helper function to make the password file easier to
> +# maintain.  Using this the password file has the form:
> +# add password sl*     pete cow
> +# add password at*     steve
> +# add password *       hanky-pie
> +proc add {var args} { global int_$var ; lappend int_$var $args}
> +proc include {args} {
> +    global env
> +    regsub -all "(^{|}$)" $args {} args
> +    if { [ regexp "^/" $args ignore ] == 0 } {
> +       set args $env(HOME)/$args
> +    }
> +    source_password_file $args
> +}
> +
> +proc find {var router} {
> +    upvar int_$var list
> +    if { [info exists list] } {
> +       foreach line $list {
> +           if { [string match [lindex $line 0] $router ] } {
> +               return [lrange $line 1 end]
> +           }
> +       }
> +    }
> +    return {}
> +}
> +
> +# Loads the password file.  Note that as this file is tcl, and that
> +# it is sourced, the user better know what to put in there, as it
> +# could install more than just password info...  I will assume however,
> +# that a "bad guy" could just as easy put such code in the clogin
> +# script, so I will leave .cloginrc as just an extention of that script
> +proc source_password_file { password_file } {
> +    global env
> +    if { ! [file exists $password_file] } {
> +       send_user "\nError: password file ($password_file) does not exist\n"
> +       exit 1
> +    }
> +    file stat $password_file fileinfo
> +    if { [expr ($fileinfo(mode) & 007)] != 0000 } {
> +       send_user "\nError: $password_file must not be world readable/writable\n"
> +       exit 1
> +    }
> +    if [ catch {source $password_file} reason ] {
> +       send_user "\nError: $reason\n"
> +       exit 1
> +    }
> +}
> +
> +# Log into the firewall.
> +# returns: 0 on success, 1 on failure
> +proc login { router user userpswd passwd enapasswd prompt cmethod cyphertype } {
> +    global spawn_id in_proc do_command do_script sshcmd
> +    set in_proc 1
> +    set uprompt_seen 0
> +
> +    # Telnet to the firewall & try to login.
> +    set progs [llength $cmethod]
> +    foreach prog [lrange $cmethod 0 end] {
> +       incr progs -1
> +       if [string match "telnet*" $prog] {
> +           regexp {telnet(:([^[:space:]]+))*} $prog command suffix port
> +           if {"$port" == ""} {
> +               set retval [ catch {spawn telnet $router} reason ]
> +           } else {
> +               set retval [ catch {spawn telnet $router $port} reason ]
> +           }
> +           if { $retval } {
> +               send_user "\nError: telnet failed: $reason\n"
> +               return 1
> +           }
> +       } elseif [string match "ssh*" $prog] {
> +           regexp {ssh(:([^[:space:]]+))*} $prog methcmd suffix port
> +           if {"$port" == ""} {
> +               set cmd [join [lindex $sshcmd 0] " "]
> +               set retval [ catch {eval spawn [split "$cmd -c $cyphertype -x -l $user $router" { }]} reason ]
> +           } else {
> +               set cmd [join [lindex $sshcmd 0] " "]
> +               set retval [ catch {eval spawn [split "$cmd -c $cyphertype -x -l $user -p $port $router" { }]} reason ]
> +           }
> +           if { $retval } {
> +               send_user "\nError: $sshcmd failed: $reason\n"
> +               return 1
> +           }
> +       } elseif ![string compare $prog "rsh"] {
> +           send_error "\nError: unsupported method: rsh\n"
> +           if { $progs == 0 } {
> +               return 1
> +           }
> +           continue;
> +       } else {
> +           send_user "\nError: unknown connection method: $prog\n"
> +           return 1
> +       }
> +
> +    sleep 0.3
> +
> +    # This helps cleanup each expect clause.
> +    expect_after {
> +       timeout {
> +           send_user "\nError: TIMEOUT reached\n"
> +           catch {close}; catch {wait};
> +           if { $in_proc} {
> +               return 1
> +           } else {
> +               continue
> +           }
> +        } eof {
> +           send_user "\nError: EOF received\n"
> +           catch {close}; catch {wait};
> +           if { $in_proc} {
> +               return 1
> +           } else {
> +               continue
> +           }
> +        }
> +    }
> +
> +    # Here we get a little tricky.  There are several possibilities:
> +    # the firewall can ask for a username and passwd and then
> +    # talk to the TACACS server to authenticate you, or if the
> +    # TACACS server is not working, then it will use the enable
> +    # passwd.  Or, the firewall might not have TACACS turned on,
> +    # then it will just send the passwd.
> +    # if telnet fails with connection refused, try ssh
> +    expect {
> +       -re "(Connection refused|Secure connection \[^\n\r]+ refused)" {
> +           catch {close}; catch {wait};
> +           if !$progs {
> +               send_user "\nError: Connection Refused ($prog): $router\n"
> +               return 1
> +           }
> +       }
> +       -re "(Connection closed by|Connection to \[^\n\r]+ closed)" {
> +           catch {close}; catch {wait};
> +           if !$progs {
> +               send_user "\nError: Connection closed ($prog): $router\n"
> +               return 1
> +           }
> +       }
> +       eof { send_user "\nError: Couldn't login: $router\n"; wait; return 1 }
> +       -nocase "unknown host\r" {
> +           send_user "\nError: Unknown host $router\n";
> +           catch {close}; catch {wait};
> +           return 1
> +       }
> +       "Host is unreachable" {
> +           send_user "\nError: Host Unreachable: $router\n";
> +           catch {close}; catch {wait};
> +           return 1
> +       }
> +       "No address associated with name" {
> +           send_user "\nError: Unknown host $router\n";
> +           catch {close}; catch {wait};
> +           return 1
> +       }
> +       -re "(Host key not found |The authenticity of host .* be established).*\(yes\/no\)\?" {
> +           send "yes\r"
> +           send_user "\nHost $router added to the list of known hosts.\n"
> +           exp_continue }
> +       -re "HOST IDENTIFICATION HAS CHANGED.* \(yes\/no\)\?" {
> +           send "no\r"
> +           send_user "\nError: The host key for $router has changed.  Update the SSH known_hosts file accordingly.\n"
> +           catch {close}; catch {wait};
> +           return 1
> +       }
> +       -re "Offending key for .* \(yes\/no\)\?" {
> +           send "no\r"
> +           send_user "\nError: host key mismatch for $router.  Update the SSH known_hosts file accordingly.\n"
> +           catch {close}; catch {wait};
> +           return 1
> +       }
> +       -re "(denied|Sorry)"    {
> +                                 send_user "\nError: Check your passwd for $router\n"
> +                                 catch {close}; catch {wait}; return 1
> +                               }
> +       "Login failed"          {
> +                                 send_user "\nError: Check your passwd for $router\n";
> +                                 catch {close}; catch {wait}; return 1
> +                                }
> +       -re "(login:)"                  {
> +                                         sleep 1;
> +                                         send -- "$user\r"
> +                                         set uprompt_seen 1
> +                                         exp_continue
> +                                       }
> +       -re "@\[^\r\n]+\[Pp]assword:"   {
> +                                         # ssh pwd prompt
> +                                         sleep 1
> +                                         send -- "$userpswd\r"
> +                                         exp_continue
> +                                       }
> +       "\[Pp]assword:"                 {
> +                                         sleep 1;
> +                                         if {$uprompt_seen == 1} {
> +                                               send -- "$userpswd\r"
> +                                         } else {
> +                                               send -- "$passwd\r"
> +                                         }
> +                                         exp_continue
> +                                       }
> +       -- "$prompt"                    { break; }
> +     }
> +    }
> +    set in_proc 0
> +    return 0
> +}
> +
> +# Run commands given on the command line.
> +proc run_commands { prompt command } {
> +    global in_proc
> +    set in_proc 1
> +
> +    # Disable output paging.
> +    send -- "config system console\r" 
> +    expect -re $prompt; send -- "set output standard\r"
> +    expect -re $prompt; send -- "end\r"
> +    expect -re $prompt;
> +
> +    set commands [split $command \;]
> +    set num_commands [llength $commands]
> +    for {set i 0} {$i < $num_commands} { incr i} {
> +       send -- "[subst [lindex $commands $i]]\r"
> +#      send_user "**************** [subst [lindex $commands $i]] ************\n"
> +       expect {
> +            -re "$prompt"                      { send "\r"
> +                                                 sleep 0.5
> +                                               }
> +           -gl "--More--"                      { send " "
> +                                                 exp_continue
> +           -re "\[\n\r]+"                      { exp_continue }
> +                                               }
> +       }
> +     }   
> +#    send_user "******* fuori da ciclo for *******\n"
> +     expect {
> +         -re "$prompt$"                                {
> +                                                 send "exit\r"
> +                                                 sleep 0.5
> +                                                 exp_continue
> +                                               }
> +         -re "\[\n\r]+"                                { exp_continue }
> +         -gl "Configuration modified, save?"   {
> +                                                 send "n\r"
> +                                                 exp_continue
> +                                               }
> +         timeout                                       { catch {close}; catch {wait};
> +                                                 return 0
> +                                               }
> +         eof                                   { return 0 }
> +        }
> +    set in_proc 0
> +}
> +
> +#
> +# For each firewall... (this is main loop)
> +#
> +source_password_file $password_file
> +set in_proc 0
> +set exitval 0
> +foreach router [lrange $argv $i end] {
> +    set router [string tolower $router]
> +    send_user "$router\n"
> +
> +    # FortiOS 2.x prompts can end in either '#' or '$'
> +    set prompt "\[#\\$] "
> +
> +    # Figure out passwords
> +   if { $do_passwd || $do_enapasswd } {
> +      set pswd [find password $router]
> +      if { [llength $pswd] == 0 } {
> +        send_user "\nError: no password for $router in $password_file.\n"
> +        continue
> +      }
> +     set passwd [join [lindex $pswd 0] ""]
> +     set enapasswd [join [lindex $pswd 1]  ""]
> +    } else {
> +       set passwd $userpasswd
> +       set enapasswd $enapasswd
> +    }
> +
> +    # Figure out username
> +    if {[info exists username]} {
> +      # command line username
> +      set ruser $username
> +    } else {
> +      set ruser [join [find user $router] ""]
> +      if { "$ruser" == "" } { set ruser $default_user }
> +    }
> +
> +    # Figure out username's password (if different from the vty password)
> +    if {[info exists userpasswd]} {
> +      # command line username
> +      set userpswd $userpasswd
> +    } else {
> +      set userpswd [join [find userpassword $router] ""]
> +      if { "$userpswd" == "" } { set userpswd $passwd }
> +    }
> +
> +
> +    # Figure out cypher type
> +    if {[info exists cypher]} {
> +      # command line cypher type
> +      set cyphertype $cypher
> +    } else {
> +      set cyphertype [find cyphertype $router]
> +      if { "$cyphertype" == "" } { set cyphertype "3des" }
> +    }
> +
> +    # Figure out connection method
> +    set cmethod [find method $router]
> +    if { "$cmethod" == "" } { set cmethod {{telnet} {ssh}} }
> +
> +    # Figure out the SSH executable name
> +    set sshcmd [find sshcmd $router]
> +    if { "$sshcmd" == "" } { set sshcmd {ssh} }
> +
> +    # Login to the router
> +    if {[login $router $ruser $userpswd $passwd $enapasswd $prompt $cmethod $cyphertype]} {
> +       incr exitval
> +       continue
> +    }
> +
> +    # we are logged in, now figure out the full prompt based on what the device sends us.
> +    send "\r"
> +    expect {
> +       -re "\[\r\n]+"          { exp_continue; }
> +       -re "^(.+$prompt)"      { set junk $expect_out(0,string); }
> +       if {[$junk = "(^\\$ $)"]} {
> +         set prompt $junk;
> +       } else {
> +         if {[$junk = "(^# $)"]} { set prompt $junk ; }
> +       };
> +    }
> +
> +    if { $do_command } {
> +       if {[run_commands $prompt $command]} {
> +           incr exitval
> +           continue
> +       }
> +    } elseif { $do_script } {
> +       # Disable output paging.
> +       send "config system console\r"
> +       send "set output standard\r"
> +       send "end\r"
> +       expect -re $prompt      {}
> +       source $sfile
> +       catch {close};
> +   } else {
> +       label $router
> +       log_user 1
> +       interact
> +    }
> +
> +    # End of for each firewall
> +    catch {wait};
> +    sleep 0.3
> +}
> +exit $exitval
> +
> --- rancid-2.3.4/bin/fnrancid.in	2010-10-02 08:31:34.000000000 +0200
> +++ rancid-patch/bin/fnrancid.in	2010-10-02 08:29:48.000000000 +0200
> @@ -48,6 +48,7 @@
>  # usage: rancid [-dV] [-l] [-f filename | hostname]
>  #
>  use Getopt::Std;
> +use Data::Dumper;
>  getopts('dflV');
>  if ($opt_V) {
>      print "@PACKAGE@ @VERSION@\n";
> @@ -59,10 +60,11 @@
>  $file = $opt_f;
>  $host = $ARGV[0];
>  $found_end = 0;
> -$timeo = 90;				# nlogin timeout in seconds
> +$timeo = 90;				# fnlogin timeout in seconds
>  
>  my(@commandtable, %commands, @commands);# command lists
>  my($aclsort) = ("ipsort");		# ACL sorting mode
> +$aclsort = "";					# disable sort
>  my($filter_commstr);			# SNMP community string filtering
>  my($filter_pwds);			# password filtering mode
>  
> @@ -174,10 +176,35 @@
>  	tr/\015//d;
>  	next if /^\s*$/;
>  	last if (/$prompt/);
> -
>  	next if (/^System Time:/);
>  	next if (/^FortiClient application signature package:/);
> -	ProcessHistory("","","","$_");
> +    if(/^\s*(System time:) (.*)/) {
> +           ProcessHistory("System time","","","$1 ****removed****");
> +      #print STDERR "!$1 ****removed****\n";
> +      next;
> +         }
> +    if(/^\s*(Virus-DB:) (.*)/) {
> +           ProcessHistory("$1","","","$1 ****removed****\n");
> +      #print STDERR "!$1 ****removed****\n";
> +      next;
> +         }
> +    if(/^\s*(Extended DB:) (.*)/) {
> +           ProcessHistory("$1","","","$1 ****removed****\n");
> +      #print STDERR "!$1 ****removed****\n";
> +      next;
> +         }
> +    if(/^\s*(IPS-DB:) (.*)/) {
> +           ProcessHistory("$1","","","$1 ****removed****\n");
> +      #print STDERR "!$1 ****removed****\n";
> +      next;
> +         }
> +    if(/^get system status/) {
> +      # sometimes compare on the console so filter out
> +      next;
> +    }
> +    # - Comment system info in file with '!'.
> +   ProcessHistory("","","","!$_");
> +
>      }
>      ProcessHistory("SYSTEM","","","\n");
>      return(0);
> @@ -197,11 +224,22 @@
>      while (<INPUT>) {
>  	tr/\015//d;
>  	next if /^\s*$/;
> +    next if(/^\s*!System time:/); # System time is fortigate extraction time so remove it
> +    # remove occurrances of conf_file_ver
> +    if ( /^\s*(#conf_file_ver=)([0-9]+)(.*)/i && $filter_pwds >0 ) {
> +      #print STDERR "removed serial number -->!$1$2$3\n";
> +      ProcessHistory("conf_file_ver","","","!$1**removed**$3\n");
> +      next;
> +    }
>  	last if (/$prompt/);
>  
>  	next if (/^conf_file_ver=/);
> -	if (/(^set.*)('Enc .*')(.*)/) {
> -	    ProcessHistory("ENC","","","!$1 'Enc **encoding removed**' $3\n");
> +    # Remove all the variability from the configuration versions
> +    # if filter_pwds is enabled, filter out also variabilities between configurations
> +    # password encription is different between extraction so filtering out encoding
> +    if ( /^\s*(set [^\s]*)\s(Enc\s[^\s]+)(.*)/i && $filter_pwds >0 ) {
> +     #   print STDERR "removed password-->!$1 ENC **encoding removed** $3\n";
> +        ProcessHistory("ENC","","","!$1 ENC **encoding removed**' $3\n");
>  	    next;
>  	}
>  	ProcessHistory("","","","$_");
> @@ -216,7 +254,7 @@
>  # Main
>  @commandtable = (
>  	{'get system status'	=> 'GetSystem'},
> -	{'get conf'		=> 'GetConf'}
> +	{'show full-configuration'		=> 'GetConf'}
>  );
>  # Use an array to preserve the order of the commands and a hash for mapping
>  # commands to the subroutine and track commands that have been completed.
> @@ -245,13 +283,13 @@
>      print STDOUT "opening file $host\n" if ($log);
>      open(INPUT,"<$host") || die "open failed for $host: $!\n";
>  } else {
> -    print STDERR "executing nlogin -t $timeo -c\"$cisco_cmds\" $host\n" if ($debug);
> -    print STDOUT "executing nlogin -t $timeo -c\"$cisco_cmds\" $host\n" if ($log);
> +    print STDERR "executing fnlogin -t $timeo -c\"$cisco_cmds\" $host\n" if ($debug);
> +    print STDOUT "executing fnlogin -t $timeo -c\"$cisco_cmds\" $host\n" if ($log);
>      if (defined($ENV{NOPIPE})) {
> -	system "nlogin -t $timeo -c \"$cisco_cmds\" $host </dev/null > $host.raw 2>&1" || die "nlogin failed for $host: $!\n";
> +	system "fnlogin -t $timeo -c \"$cisco_cmds\" $host </dev/null > $host.raw 2>&1" || die "nlogin failed for $host: $!\n";
>  	open(INPUT, "< $host.raw") || die "nlogin failed for $host: $!\n";
>      } else {
> -	open(INPUT,"nlogin -t $timeo -c \"$cisco_cmds\" $host </dev/null |") || die "nlogin failed for $host: $!\n";
> +	open(INPUT,"fnlogin -t $timeo -c \"$cisco_cmds\" $host </dev/null |") || die "nlogin failed for $host: $!\n";
>      }
>  }
>  
> @@ -279,14 +317,34 @@
>  TOP: while(<INPUT>) {
>      tr/\015//d;
>      if (/^Error:/) {
> -	print STDOUT ("$host nlogin error: $_");
> -	print STDERR ("$host nlogin error: $_") if ($debug);
> +	print STDOUT ("$host fnlogin error: $_");
> +	print STDERR ("$host fnlogin error: $_") if ($debug);
>  	last;
>      }
> -    while (/>\s*($cmds_regexp)\s*$/) {
> -	$cmd = $1;
> -	if (!defined($prompt)) { $prompt = " >\s*"; }
> -	print STDERR ("HIT COMMAND:$_") if ($debug);
> +    while (/^.+(#|\$)\s*($cmds_regexp)\s*$/) {
> +        $cmd = $2;
> +        # - FortiGate prompts end with either '#' or '$'. Further, they may
> +        # be prepended with a '~' if the hostname is too long. Therefore, 
> +        # we need to figure out what our prompt really is.
> +        if (!defined($prompt)) {
> +          if ( $_ =~ m/^.+\~\$/ ) {
> +            $prompt = '\~\$ .*' ;
> +          } else {
> +            if ( $_ =~ m/^.+\$/ ) {
> +              $prompt = ' \$ .*' ;
> +            } else {
> +              if ( $_ =~ m/^.+\~#/ ) {
> +                $prompt = '\~# .*' ;
> +              } else {
> +                if ( $_ =~ m/^.+#/ ) {
> +                  $prompt = ' # .*' ;
> +                }
> +              }
> +            }
> +          }
> +        }
> +        print STDERR ("HIT COMMAND:$_") if ($debug);
> +
>  	if (!defined($commands{$cmd})) {
>  	    print STDERR "$host: found unexpected command - \"$cmd\"\n";
>  	    last TOP;
> --- rancid-2.3.4/configure	2010-10-02 08:31:58.000000000 +0200
> +++ rancid-patch/configure	2010-10-02 08:29:49.000000000 +0200
> @@ -6042,7 +6042,7 @@
>  
>  ac_config_files="$ac_config_files bin/flogin bin/francid"
>  
> -ac_config_files="$ac_config_files bin/fnrancid"
> +ac_config_files="$ac_config_files bin/fnlogin bin/fnrancid"
>  
>  ac_config_files="$ac_config_files bin/hlogin bin/hrancid"
>  



More information about the Rancid-discuss mailing list