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 console managed by HP's "Lights Out 100" option 12# using the telnet protocol. The LO100 is a traditional IPMI BMC and does 13# not share hardware or firmware with the HP Integrated Lights-Out (iLO) 14# management processor. 15# 16# This script can be specified in "conman.conf" in the following manner: 17# 18# console name="zot" dev="/path/to/hp-lo100.exp HOST PORT USER PSWD" 19# 20# HOST is the hostname of the remote server. 21# PORT is the port number (typically 23). 22# USER is the username being authenticated. 23# PSWD is the corresponding password. 24# 25# Since this command-line will persist in the process listing for the duration 26# of the connection, passing sensitive information like PSWD in this manner is 27# not recommended. Instead, consider using either a command-line argument 28# default or the password database (see below). 29############################################################################### 30 31## 32# Set "exp_internal" to 1 to print diagnostics describing internal operations. 33# This is helpful in diagnosing pattern-match failures. 34## 35 exp_internal 0 36 37## 38# Set "log_user" to 1 to show the underlying dialogue establishing a connection 39# to the console. 40## 41 log_user 0 42 43## 44# The "timeout" specifies the number of seconds before the connection attempt 45# times-out and terminates the connection. 46## 47 set timeout 10 48 49## 50# The "password_db" specifies the location of the password database. 51# This avoids exposing sensitive information on the command-line without 52# needing to modify this script. 53# Whitespace and lines beginning with '#' are ignored. The file format is: 54# <host-regex> : <user> : <pswd> 55## 56 set password_db "/etc/conman.pswd" 57 58## 59# Command-line argument defaults can be specified here. This avoids exposing 60# sensitive information on the command-line. 61## 62# set port "23" 63# set user "foo" 64# set pswd "bar" 65 66############################################################################### 67 68set env(PATH) "/usr/bin:/bin" 69 70proc get_password {host user index} { 71 global password_db 72 set db_pswd {} 73 if {! [info exists password_db]} { 74 return 75 } 76 if {[catch {open $password_db} input]} { 77 return 78 } 79 while {[gets $input line] != -1} { 80 if {[regexp {^[ \t]*#} $line]} { 81 continue 82 } 83 set record [split $line ":"] 84 set db_host [string trim [lindex $record 0]] 85 if {[catch {regexp "^$db_host$" $host} got_host_match]} { 86 continue 87 } 88 if {! $got_host_match && [string length $db_host]} { 89 continue 90 } 91 set db_user [string trim [lindex $record 1]] 92 if {[string compare $db_user $user]} { 93 continue 94 } 95 set db_pswd [string trim [lindex $record $index]] 96 break 97 } 98 close $input 99 return $db_pswd 100} 101 102if {! $argc} { 103 set prog [lindex [split $argv0 "/"] end] 104 send_user "Usage: $prog <host> <port> <user> <pswd>\r\n" 105 exit 1 106} 107if {$argc > 0} { 108 set host [lindex $argv 0] 109} 110if {$argc > 1} { 111 set port [lindex $argv 1] 112} 113if {$argc > 2} { 114 set user [lindex $argv 2] 115} 116if {$argc > 3} { 117 set pswd [lindex $argv 3] 118} 119set state 0 120# 121# Valid States: 122# 0: initial 123# 1: connected to $host:$port 124# 2: sent $user 125# 3: sent $pswd 126# 4: sent ESC+Q 127# 5: connected to lo100 128# 129if {! [info exists host]} { 130 send_user "Error: Unspecified hostname.\r\n" 131 exit 1 132} 133if {! [info exists port]} { 134 send_user "Error: Unspecified port number.\r\n" 135 exit 1 136} 137if {! [info exists user]} { 138 send_user "Error: Unspecified username.\r\n" 139 exit 1 140} 141if {! [info exists pswd]} { 142 set pswd [get_password $host $user 2] 143 if {! [string length $pswd]} { 144 send_user "Error: Unspecified password.\r\n" 145 exit 1 146 } 147} 148if {[catch "spawn telnet $host $port" spawn_result]} { 149 send_user "Error: $spawn_result.\r\n" 150 exit 1 151} 152expect { 153 -re "^Connected to " { 154 if {$state == 0} { 155 incr state 156 } 157 exp_continue -continue_timer 158 } 159 -re "^telnet: (\[^\r]*)\r+\n" { 160 send_user "Error: $expect_out(1,string).\r\n" 161 exit 1 162 } 163 -gl "Login incorrect" { 164 send_user "Error: Permission denied.\r\n" 165 exit 1 166 } 167 -gl "CLI session stopped" { 168 send_user "Error: CLI session stopped.\r\n" 169 exit 1 170 } 171 -gl "Requested service is unavailable, it is already in use" { 172 send_user "Error: Console session already in use.\r\n" 173 exit 1 174 } 175 eof { 176 if {$state == 0} { 177 send_user "Error: Unable to connect to $host:$port.\r\n" 178 exit 1 179 } 180 send_user "Error: Connection closed by remote host.\r\n" 181 exit 1 182 } 183 timeout { 184 send_user "Error: Timed-out.\r\n" 185 exit 1 186 } 187 -nocase -re "login: +\$" { 188 if {$state != 1} { 189 send_user "Error: Permission denied.\r\n" 190 exit 1 191 } 192 send "$user\r" 193 incr state 194 exp_continue -continue_timer 195 } 196 -nocase -re "Password: +\$" { 197 if {$state != 2} { 198 send_user "Error: Permission denied.\r\n" 199 exit 1 200 } 201 send "$pswd\r" 202 incr state 203 exp_continue -continue_timer 204 } 205 -gl "/./-> \$" { 206 if {$state == 3} { 207 send "\033Q\r" 208 incr state 209 } 210 exp_continue -continue_timer 211 } 212 -re "\[^\r]*\r+\n" { 213 if {$state != 4} { 214 exp_continue -continue_timer 215 } 216 incr state 217 ; # success 218 } 219} 220send_user "Connection established via telnet (pid $spawn_result).\r\n" 221 222set timeout 5 223interact { 224 # Replace "&B" with serial-break. 225 "&B" { 226 send "\033\002" 227 } 228 # Match subsequent patterns against spawned process, not user's keystrokes. 229 -o 230 # Disable "ESC (" sequence for stopping console and returning to CLI prompt. 231 -re "/./-> \$" { 232 send "\033Q\r" 233 } 234} 235