1#!/usr/local/bin/expect -f 2############################################################################### 3# Written by Chris Dunlap <cdunlap@llnl.gov>. 4# Copyright (C) 2007-2018 Lawrence Livermore National Security, LLC. 5# Copyright (C) 2001-2007 The Regents of the University of California. 6# UCRL-CODE-2002-009. 7# 8# This file is part of ConMan: The Console Manager. 9# For details, see <https://dun.github.io/conman/>. 10############################################################################### 11# This script connects to a host using the SSH protocol. 12# 13# This script can be specified in "conman.conf" in the following manner: 14# 15# console name="zot" dev="/path/to/ssh.exp HOST PORT USER PSWD" 16# 17# HOST is the hostname of the remote server. 18# PORT is the port number (typically 22). 19# USER is the username being authenticated. 20# PSWD is the corresponding password. 21# 22# Since this command-line will persist in the process listing for the duration 23# of the connection, passing sensitive information like PSWD in this manner is 24# not recommended. Instead, consider using either a command-line argument 25# default or the password database (see below). 26############################################################################### 27 28## 29# Set "exp_internal" to 1 to print diagnostics describing internal operations. 30# This is helpful in diagnosing pattern-match failures. 31## 32 exp_internal 0 33 34## 35# Set "log_user" to 1 to show the underlying dialogue establishing a connection 36# to the console. 37## 38 log_user 0 39 40## 41# The "timeout" specifies the number of seconds before the connection attempt 42# times-out and terminates the connection. 43## 44 set timeout 10 45 46## 47# The "password_db" specifies the location of the password database. 48# This avoids exposing sensitive information on the command-line without 49# needing to modify this script. 50# Whitespace and lines beginning with '#' are ignored. The file format is: 51# <host-regex> : <user> : <pswd> 52## 53 set password_db "/etc/conman.pswd" 54 55## 56# Command-line argument defaults can be specified here. This avoids exposing 57# sensitive information on the command-line. 58## 59# set port "22" 60# set user "foo" 61# set pswd "bar" 62 63############################################################################### 64 65set env(PATH) "/usr/bin:/bin" 66 67proc get_password {host user index} { 68 global password_db 69 set db_pswd {} 70 if {! [info exists password_db]} { 71 return 72 } 73 if {[catch {open $password_db} input]} { 74 return 75 } 76 while {[gets $input line] != -1} { 77 if {[regexp {^[ \t]*#} $line]} { 78 continue 79 } 80 set record [split $line ":"] 81 set db_host [string trim [lindex $record 0]] 82 if {[catch {regexp "^$db_host$" $host} got_host_match]} { 83 continue 84 } 85 if {! $got_host_match && [string length $db_host]} { 86 continue 87 } 88 set db_user [string trim [lindex $record 1]] 89 if {[string compare $db_user $user]} { 90 continue 91 } 92 set db_pswd [string trim [lindex $record $index]] 93 break 94 } 95 close $input 96 return $db_pswd 97} 98 99if {! $argc} { 100 set prog [lindex [split $argv0 "/"] end] 101 send_user "Usage: $prog <host> <port> <user> <pswd>\r\n" 102 exit 1 103} 104if {$argc > 0} { 105 set host [lindex $argv 0] 106} 107if {$argc > 1} { 108 set port [lindex $argv 1] 109} 110if {$argc > 2} { 111 set user [lindex $argv 2] 112} 113if {$argc > 3} { 114 set pswd [lindex $argv 3] 115} 116set authenticated 0 117if {! [info exists host]} { 118 send_user "Error: Unspecified hostname.\r\n" 119 exit 1 120} 121if {! [info exists port]} { 122 send_user "Error: Unspecified port number.\r\n" 123 exit 1 124} 125if {! [info exists user]} { 126 send_user "Error: Unspecified username.\r\n" 127 exit 1 128} 129if {! [info exists pswd]} { 130 set pswd [get_password $host $user 2] 131 if {! [string length $pswd]} { 132 send_user "Error: Unspecified password.\r\n" 133 exit 1 134 } 135} 136if {[catch "spawn ssh -a -e \& -l $user -p $port -x $host" spawn_result]} { 137 send_user "Error: $spawn_result.\r\n" 138 exit 1 139} 140expect { 141 -gl "Permission denied" { 142 send_user "Error: Permission denied.\r\n" 143 exit 1 144 } 145 -re "^ssh: (\[^\r]*)\r+\n" { 146 send_user "Error: $expect_out(1,string).\r\n" 147 exit 1 148 } 149 eof { 150 send_user "Error: Connection closed by remote host.\r\n" 151 exit 1 152 } 153 timeout { 154 if {$authenticated == 0} { 155 send_user "Error: Timed-out.\r\n" 156 exit 1 157 } 158 } 159 -nocase -gl "Are you sure you want to continue connecting (yes/no)? \$" { 160 send "yes\r" 161 exp_continue -continue_timer 162 } 163 -re "Enter passphrase for key .*: \$" { 164 if {$authenticated == 0} { 165 send "\r" 166 } 167 exp_continue -continue_timer 168 } 169 -re "^$user@.* password: \$" { 170 if {$authenticated == 0} { 171 send "$pswd\r" 172 incr authenticated 173 exp_continue -continue_timer 174 } else { 175 send_user "Error: Permission denied.\r\n" 176 exit 1 177 } 178 } 179 -re "(:|#|%|\\\$) \$" { 180 ; 181 } 182 -re "\[^\r]*\r+\n" { 183 exp_continue -continue_timer 184 } 185} 186send_user "Connection established via ssh (pid $spawn_result).\r\n" 187 188interact 189# Since the default ssh escape character was changed from "~" to "&", 190# "&B" will generate a serial-break. 191