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 port on a Cyclades terminal server using the 12# telnet protocol (protocol socket_server or socket_server_ssh). It supports 13# consoles using no authentication (authtype none) and local authentication 14# (authtype local). However, if console authentication is not needed, better 15# scalability will be achieved using the native telnet support within ConMan 16# (console name="zot" dev="HOST:PORT"). 17# 18# This script can be specified in "conman.conf" in the following manner: 19# 20# console name="zot" dev="/path/to/cyclades-telnet.exp HOST PORT [USER PSWD]" 21# 22# HOST is the hostname of the terminal server. 23# PORT is the port number associated with the console. 24# USER is the username being authenticated. 25# PSWD is the corresponding password. 26# 27# Both USER and PSWD must be specified if the console requires authentication. 28# 29# Since this command-line will persist in the process listing for the duration 30# of the connection, passing sensitive information like PSWD in this manner is 31# not recommended. Instead, consider using either a command-line argument 32# default or the password database (see below). 33############################################################################### 34 35## 36# Set "exp_internal" to 1 to print diagnostics describing internal operations. 37# This is helpful in diagnosing pattern-match failures. 38## 39 exp_internal 0 40 41## 42# Set "log_user" to 1 to show the underlying dialogue establishing a connection 43# to the console. 44## 45 log_user 0 46 47## 48# The "timeout" specifies the number of seconds before the connection attempt 49# times-out and terminates the connection. 50## 51 set timeout 10 52 53## 54# The "password_db" specifies the location of the password database. 55# This avoids exposing sensitive information on the command-line without 56# needing to modify this script. 57# Whitespace and lines beginning with '#' are ignored. The file format is: 58# <host-regex> : <user> : <pswd> 59## 60 set password_db "/etc/conman.pswd" 61 62## 63# Command-line argument defaults can be specified here. This avoids exposing 64# sensitive information on the command-line. 65## 66# set user "root" 67# set pswd "tslinux" 68 69############################################################################### 70 71set env(PATH) "/usr/bin:/bin" 72 73proc get_password {host user index} { 74 global password_db 75 set db_pswd {} 76 if {! [info exists password_db]} { 77 return 78 } 79 if {[catch {open $password_db} input]} { 80 return 81 } 82 while {[gets $input line] != -1} { 83 if {[regexp {^[ \t]*#} $line]} { 84 continue 85 } 86 set record [split $line ":"] 87 set db_host [string trim [lindex $record 0]] 88 if {[catch {regexp "^$db_host$" $host} got_host_match]} { 89 continue 90 } 91 if {! $got_host_match && [string length $db_host]} { 92 continue 93 } 94 set db_user [string trim [lindex $record 1]] 95 if {[string compare $db_user $user]} { 96 continue 97 } 98 set db_pswd [string trim [lindex $record $index]] 99 break 100 } 101 close $input 102 return $db_pswd 103} 104 105if {! $argc} { 106 set prog [lindex [split $argv0 "/"] end] 107 send_user "Usage: $prog <host> <port> \[<user> <pswd>]\r\n" 108 exit 1 109} 110if {$argc > 0} { 111 set host [lindex $argv 0] 112} 113if {$argc > 1} { 114 set port [lindex $argv 1] 115} 116if {$argc > 2} { 117 set user [lindex $argv 2] 118} 119if {$argc > 3} { 120 set pswd [lindex $argv 3] 121} 122set authenticated 0 123if {! [info exists host]} { 124 send_user "Error: Unspecified hostname.\r\n" 125 exit 1 126} 127if {! [info exists port]} { 128 send_user "Error: Unspecified port number.\r\n" 129 exit 1 130} 131if {! [info exists user]} { 132 set authenticated 1 133 set user {} 134} elseif {! [info exists pswd]} { 135 set pswd [get_password $host $user 2] 136 if {! [string length $pswd]} { 137 send_user "Error: Unspecified password.\r\n" 138 exit 1 139 } 140} 141if {[catch "spawn telnet $host $port" spawn_result]} { 142 send_user "Error: $spawn_result.\r\n" 143 exit 1 144} 145expect { 146 -gl "Authentication failure" { 147 send_user "Error: Permission denied.\r\n" 148 exit 1 149 } 150 -gl "Connection refused" { 151 send_user "Error: Connection refused.\r\n" 152 exit 1 153 } 154 -re "(ttyS\[0-9]*) is being used by \\((.*)\\)" { 155 send_user "Error: Console session for $expect_out(1,string) in use by $expect_out(2,string).\r\n" 156 exit 1 157 } 158 -gl "is being used by" { 159 send_user "Error: Console session already in use.\r\n" 160 exit 1 161 } 162 -gl "closed by remote host" { 163 send_user "Error: Connection closed by remote host.\r\n" 164 exit 1 165 } 166 -re "^telnet: (\[^\r]*)\r+\n" { 167 send_user "Error: $expect_out(1,string).\r\n" 168 exit 1 169 } 170 eof { 171 send_user "Error: Connection closed by remote host.\r\n" 172 exit 1 173 } 174 timeout { 175 if {$authenticated == 0} { 176 send_user "Error: Timed-out waiting to authenticate.\r\n" 177 exit 1 178 } 179 } 180 -nocase -gl "login: \$" { 181 if {$authenticated == 0} { 182 send "$user\r" 183 exp_continue -continue_timer 184 } else { 185 send_user "Error: Permission denied.\r\n" 186 exit 1 187 } 188 } 189 -nocase -gl "password: \$" { 190 if {$authenticated == 0} { 191 send "$pswd\r" 192 incr authenticated 193 exp_continue -continue_timer 194 } else { 195 send_user "Error: Permission denied.\r\n" 196 exit 1 197 } 198 } 199 -re "\[^\r]*\r+\n" { 200 exp_continue -continue_timer 201 } 202} 203send_user "Connection established via telnet (pid $spawn_result).\r\n" 204 205interact { 206 # Replace "&B" with serial-break. 207 "&B" { 208 set timeout 2 209 send "\035send brk\r\n" 210 expect "telnet> send brk" 211 } 212} 213