rlogin 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (4) hide show
  1. data/lib/rlogin.rb +218 -0
  2. data/licence.txt +19 -0
  3. data/test/client.rb +17 -0
  4. metadata +57 -0
data/lib/rlogin.rb ADDED
@@ -0,0 +1,218 @@
1
+ require 'socket'
2
+
3
+ module Net
4
+ # This class implements the BSD Rlogin as it is defined in the RFC 1282.
5
+ class Rlogin
6
+ RECEIVED_SETTINGS = 0x00
7
+ WINDOW_SIZE_MAGIC_COOKIE = "\xff\xffss"
8
+ REQUEST_CLEAR_BUFFER = 0x02
9
+ REQUEST_SWITCH_TO_RAW = 0x10
10
+ REQUEST_SWITCH_TO_NORMAL = 0x20
11
+ REQUEST_WINDOW_SIZE = 0x80
12
+
13
+ attr_reader :host, :port, :username, :password, :local_host, :local_port,
14
+ :client_user_name, :server_user_name, :terminal_type, :speed,
15
+ :rows, :columns, :pixel_x, :pixel_y, :login_token,
16
+ :password_token, :prompt, :logout_token, :logger
17
+
18
+ # Creates a new Rlogin client for the passed host and username. Additonal
19
+ # parameter can be passed as a options hash. Options are:
20
+ # :host:: hostname, dns or ipadress of the remote server
21
+ # :port:: port of the rlogind daemon on the remote server (DEFAULT: 513)
22
+ # :username:: username used for login
23
+ # :password:: password used for login
24
+ # :local_host:: the interface to connect from (DEFAULT: 0.0.0.0)
25
+ # :local_port:: the port to connect from (DEFAULT: 1023)
26
+ # :client_user_name:: client user name (DEFAULT: "")
27
+ # :server_user_name:: server user name (DEFAULT: "")
28
+ # :terminal_type:: the terminal type (DEFAULT: xterm)
29
+ # :speed:: the terminal boud rate (DEFAULT: 38400)
30
+ # :rows:: rows of the emulated terminal (DEFAULT: 24)
31
+ # :columns:: columns of the emulated terminal (DEFAULT: 80)
32
+ # :pixel_x:: x pixel of the emulated terminal (DEFAULT: 0)
33
+ # :pixel_y:: y pixel of the emulated terminal (DEFAULT: 0)
34
+ # :login_token:: the login regex (DEFAULT: /login:\s$/)
35
+ # :password_token:: the password regex (DEFAULT: /Password:\s$/)
36
+ # :prompt:: the prompt regex (DEFAULT: /^[^\n]*[#\$]> $/)
37
+ # :logout_token:: the logout regex (DEFAULT: /exit\s+logout$/)
38
+ # :logger:: the logger that will be used for logging messages
39
+ #
40
+ # Net::Rlogin.new("example.xom", "user", :password => "secret") do |session|
41
+ # puts session.cmd("ls -al")
42
+ # end
43
+ def initialize(host, username, options = {}, &block) # :yields: session
44
+ # connection settings
45
+ @host = host
46
+ @port = options[:port] || 513
47
+ @username = username
48
+ @password = options[:password] || nil
49
+ @local_host = options[:local_host] || "0.0.0.0"
50
+ @local_port = options[:local_port] || 1023
51
+ @client_user_name = options[:client_user_name] || ""
52
+ @server_user_name = options[:server_user_name] || ""
53
+ @terminal_type = options[:terminal_type] || "xterm"
54
+ @speed = options[:speed] || 38400
55
+ @rows = options[:rows] || 24
56
+ @columns = options[:columns] || 80
57
+ @pixel_x = options[:pixel_x] || 0
58
+ @pixel_y = options[:pixel_y] || 0
59
+
60
+ # parser settings
61
+ @login_token = options[:login_token] || /login:\s$/
62
+ @password_token = options[:password_token] || /Password:\s$/
63
+ @prompt = options[:prompt] || /^[^\n]*[#\$]> $/
64
+ @logout_token = options[:logout_token] || /exit\s+logout$/
65
+
66
+ # logging
67
+ @logger = options[:logger]
68
+
69
+ # buffer
70
+ @receive_buffer = ""
71
+ @logged_in = false
72
+
73
+ # start the session if a block is given
74
+ self.session(&block) if block
75
+ end
76
+
77
+ # openes a session and closes the session after the passed block
78
+ # has finished
79
+ #
80
+ # rlogin = Net::Rlogin.new("example.xom", "user", :password => "secret")
81
+ # rlogin.session do |session|
82
+ # puts session.cmd("ls -al")
83
+ # end
84
+ def session(&block) # :yields: session
85
+ @socket = TCPSocket.open(@host, @port, @local_host, @local_port)
86
+
87
+ # print connection settings and get return code
88
+ @socket.print(connection_settings)
89
+ return_code = @socket.recv(1).unpack("c").first
90
+
91
+ if return_code == RECEIVED_SETTINGS
92
+ login
93
+ block.call(self)
94
+ logout
95
+ else
96
+ if @logger
97
+ error = @socket.read
98
+ @logger.error("connection couldn't be established: %s" % error)
99
+ end
100
+ @socket.close
101
+ end
102
+ end
103
+
104
+ # executes the passed command on the remote server and returns the result.
105
+ # return_cmd:: true = show the command that has been send
106
+ # return_prompt:: true = show the returning command prompt
107
+ # terminator:: use a different termiantor (DEFAULT: prompt)
108
+ def cmd(command, return_cmd = false, return_prompt = false, terminator = nil)
109
+ if @logged_in
110
+ prompt = terminator || @prompt
111
+ enter_command(command)
112
+ result = receive_until_token(prompt)
113
+ result.gsub!(/^#{command}\s\s?/, "") unless return_cmd
114
+ result.gsub!(/#{prompt}?/, "") unless return_prompt
115
+ return result
116
+ else
117
+ raise Exception.new("Connection is not initiated (use session)")
118
+ end
119
+ end
120
+
121
+ # reutrns true if the connection is online false otherwiese
122
+ def logged_in?
123
+ @logged_in
124
+ end
125
+
126
+ # logout using exit command
127
+ def logout
128
+ if @logged_in
129
+ cmd("exit", true, true, @logout_token)
130
+ handle_logout
131
+ end
132
+ end
133
+
134
+ private
135
+
136
+ # parse repsonse and handle the control bytes until the passed token
137
+ # was found in the recieved content
138
+ def receive_until_token(token)
139
+ received = ""
140
+ begin
141
+ byte = @socket.recv(1)
142
+ @receive_buffer << byte
143
+ received << byte
144
+
145
+ # handle control bytes
146
+ case byte
147
+ when REQUEST_WINDOW_SIZE
148
+ @logger.debug("request: window / screen size") if @logger
149
+ @socket.print(window_size_message)
150
+ when REQUEST_CLEAR_BUFFER
151
+ @logger.debug("request: clear buffer") if @logger
152
+ @receive_buffer = ""
153
+ when REQUEST_SWITCH_TO_RAW
154
+ @logger.debug("request: switch to raw") if @logger
155
+ # ...
156
+ when REQUEST_SWITCH_TO_NORMAL
157
+ @logger.debug("request: switch to normal") if @logger
158
+ # ...
159
+ end
160
+ end while !(@receive_buffer =~ token)
161
+ @logger.debug("received: #{received.inspect}") if @logger
162
+ received
163
+ end
164
+
165
+ # login using the login credentials
166
+ def login
167
+ receive_until_token(@login_token)
168
+ enter_login unless @logged_in
169
+ if @password # if password was passed, else try without password
170
+ receive_until_token(@password_token)
171
+ enter_password unless @logged_in
172
+ end
173
+ receive_until_token(@prompt)
174
+ @logger.info("logged in") if @logger
175
+ end
176
+
177
+ # sends the username to the remote server
178
+ def enter_login
179
+ @logger.info("enter login: %s" % @username) if @logger
180
+ enter_command(@username)
181
+ end
182
+
183
+ # sends the password to the remote server
184
+ def enter_password
185
+ @logger.info("enter password") if @logger
186
+ enter_command(@password)
187
+ @logged_in = true
188
+ end
189
+
190
+ # sends a string terminated by \n (LF) to the server
191
+ def enter_command(cmd)
192
+ @socket.print("#{cmd}\n")
193
+ end
194
+
195
+ # handles the logout and clear up session
196
+ def handle_logout
197
+ @logged_in = false
198
+ @receive_buffer = ""
199
+ @socket.close
200
+ @logger.info("logged out") if @logger
201
+ end
202
+
203
+ # builds the connection setting string that will be send on startup
204
+ def connection_settings
205
+ "\0%s\0%s\0%s/%d\0" % [
206
+ @client_user_name, @server_user_name, @terminal_type, @speed
207
+ ]
208
+ end
209
+
210
+ # builds the window size string that will be send when the window size
211
+ # magic cookie was found (normaly after connection settings have been send
212
+ # successfully)
213
+ def window_size_message
214
+ WINDOW_SIZE_MAGIC_COOKIE + [@rows, @columns, @pixel_x, @pixel_y].pack("nnnn")
215
+ end
216
+ end
217
+ end
218
+
data/licence.txt ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2009 Vincent Landgraf
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ THE SOFTWARE.
data/test/client.rb ADDED
@@ -0,0 +1,17 @@
1
+ require "../lib/rlogin"
2
+
3
+ username, host = ARGV.shift.split("@")
4
+ password = ARGV.shift
5
+
6
+ Net::Rlogin.new(host, username, :password => password) do |session|
7
+ print "##### $> "
8
+ begin
9
+ cmd = STDIN.gets.chomp
10
+ if cmd =~ /exit/
11
+ session.logout
12
+ else
13
+ print session.cmd(cmd, false, true)
14
+ end
15
+ end while session.logged_in?
16
+ end
17
+
metadata ADDED
@@ -0,0 +1,57 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rlogin
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Vincent Landgraf
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-08-19 00:00:00 +02:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: Simple builder classes for creating markup.
17
+ email: vilandgr+rlogin@googlemail.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - licence.txt
24
+ files:
25
+ - lib/rlogin.rb
26
+ - test/client.rb
27
+ - licence.txt
28
+ has_rdoc: true
29
+ homepage: http://rlogin.rubyforge.org
30
+ licenses: []
31
+
32
+ post_install_message:
33
+ rdoc_options: []
34
+
35
+ require_paths:
36
+ - lib
37
+ required_ruby_version: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ version: "0"
42
+ version:
43
+ required_rubygems_version: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: "0"
48
+ version:
49
+ requirements: []
50
+
51
+ rubyforge_project: rlogin
52
+ rubygems_version: 1.3.5
53
+ signing_key:
54
+ specification_version: 3
55
+ summary: Net::Rlogin package to connect with rlogind servers
56
+ test_files: []
57
+