libssh 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +2 -0
- data/CHANGELOG.md +4 -0
- data/README.md +5 -1
- data/example/exec.rb +2 -0
- data/example/scp_download.rb +51 -0
- data/example/scp_upload.rb +31 -0
- data/example/sshkit.rb +11 -0
- data/ext/libssh_ruby/channel.c +91 -0
- data/ext/libssh_ruby/key.c +36 -0
- data/ext/libssh_ruby/libssh_ruby.c +38 -0
- data/ext/libssh_ruby/libssh_ruby.h +1 -0
- data/ext/libssh_ruby/scp.c +457 -0
- data/ext/libssh_ruby/session.c +386 -2
- data/lib/libssh.rb +0 -4
- data/lib/libssh/version.rb +1 -1
- data/lib/sshkit/backends/libssh.rb +108 -5
- data/libssh.gemspec +2 -1
- metadata +23 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f05291298150e6683ac9b6647515440e7dafe6a7
|
4
|
+
data.tar.gz: 9c174e89993c04dee954032011fdf13987947bfa
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4760b23e84edef76e93604c38a0903bbf04ea682652754c5df1029fb21b688cf728acf5fa211253827884002612a1a5a038d7f33ff8c10e91c8b60b181c11396
|
7
|
+
data.tar.gz: 82a03d32630272ddd632527ba70e83daa87b2a84af5d35aa8cee8a8ff83947e9ed241b6ed2d7363e62f6871342a66c5041ad5b2110a0f25e17e536d1aad9b90b
|
data/.rubocop.yml
CHANGED
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# LibSSH
|
2
|
+
[![Gem Version](https://badge.fury.io/rb/libssh.svg)](https://badge.fury.io/rb/libssh)
|
2
3
|
[![Build Status](https://travis-ci.org/eagletmt/libssh-ruby.svg?branch=master)](https://travis-ci.org/eagletmt/libssh-ruby)
|
3
4
|
|
4
5
|
Ruby binding for [libssh](https://www.libssh.org/) .
|
@@ -30,7 +31,7 @@ Or install it yourself as:
|
|
30
31
|
|
31
32
|
## Usage
|
32
33
|
|
33
|
-
See [example
|
34
|
+
See [example](example) directory.
|
34
35
|
|
35
36
|
### With SSHKit
|
36
37
|
|
@@ -43,6 +44,9 @@ require 'sshkit/backends/libssh'
|
|
43
44
|
set :sshkit_backend, SSHKit::Backend::Libssh
|
44
45
|
```
|
45
46
|
|
47
|
+
## Documentation
|
48
|
+
http://www.rubydoc.info/github/eagletmt/libssh-ruby
|
49
|
+
|
46
50
|
## Development
|
47
51
|
|
48
52
|
After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
data/example/exec.rb
CHANGED
@@ -0,0 +1,51 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'libssh'
|
3
|
+
|
4
|
+
host = 'barkhorn'
|
5
|
+
remote_path = '/etc/passwd'
|
6
|
+
|
7
|
+
GC.stress = true
|
8
|
+
session = LibSSH::Session.new
|
9
|
+
# session.log_verbosity = :debug
|
10
|
+
session.host = host
|
11
|
+
session.parse_config
|
12
|
+
session.add_identity('%d/id_ed25519')
|
13
|
+
|
14
|
+
session.connect
|
15
|
+
if session.server_known != LibSSH::SERVER_KNOWN_OK
|
16
|
+
raise
|
17
|
+
end
|
18
|
+
if session.userauth_publickey_auto != LibSSH::AUTH_SUCCESS
|
19
|
+
raise 'authorization failed'
|
20
|
+
end
|
21
|
+
|
22
|
+
scp = LibSSH::Scp.new(session, :read, remote_path)
|
23
|
+
scp.init do
|
24
|
+
loop do
|
25
|
+
case scp.pull_request
|
26
|
+
when LibSSH::Scp::REQUEST_NEWFILE
|
27
|
+
size = scp.request_size
|
28
|
+
puts "size=#{size}, filename=#{scp.request_filename}, mode=#{scp.request_permissions.to_s(8)}"
|
29
|
+
scp.accept_request
|
30
|
+
|
31
|
+
n = 0
|
32
|
+
buf = ''
|
33
|
+
while n < size
|
34
|
+
s = scp.read(size)
|
35
|
+
puts "Read #{s.size}"
|
36
|
+
n += s.size
|
37
|
+
buf << s
|
38
|
+
end
|
39
|
+
puts buf
|
40
|
+
when LibSSH::Scp::REQUEST_NEWDIR
|
41
|
+
puts "newdir: name=#{scp.request_filename}, mode=#{scp.request_permissions.to_s(8)}"
|
42
|
+
scp.accept_request
|
43
|
+
when LibSSH::Scp::REQUEST_ENDDIR
|
44
|
+
puts 'enddir'
|
45
|
+
when LibSSH::Scp::REQUEST_WARNING
|
46
|
+
puts "warning: #{scp.request_warning}"
|
47
|
+
when LibSSH::Scp::REQUEST_EOF
|
48
|
+
break
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'libssh'
|
3
|
+
require 'pathname'
|
4
|
+
|
5
|
+
host = 'barkhorn'
|
6
|
+
target_dir = '/tmp'
|
7
|
+
|
8
|
+
GC.stress = true
|
9
|
+
session = LibSSH::Session.new
|
10
|
+
# session.log_verbosity = :debug
|
11
|
+
session.host = host
|
12
|
+
session.parse_config
|
13
|
+
session.add_identity('%d/id_ed25519')
|
14
|
+
|
15
|
+
session.connect
|
16
|
+
if session.server_known != LibSSH::SERVER_KNOWN_OK
|
17
|
+
raise
|
18
|
+
end
|
19
|
+
if session.userauth_publickey_auto != LibSSH::AUTH_SUCCESS
|
20
|
+
raise 'authorization failed'
|
21
|
+
end
|
22
|
+
|
23
|
+
scp = LibSSH::Scp.new(session, :write, target_dir)
|
24
|
+
scp.init do
|
25
|
+
path = Pathname.new(__dir__).parent.join('README.md')
|
26
|
+
scp.push_file(path.basename.to_s, path.size, path.stat.mode & 0xfff)
|
27
|
+
path.read do |buf|
|
28
|
+
scp.write(buf)
|
29
|
+
end
|
30
|
+
puts "Uploaded #{path} to #{host}:#{File.join(target_dir, path.basename)}"
|
31
|
+
end
|
data/example/sshkit.rb
CHANGED
@@ -7,6 +7,10 @@ require 'sshkit/dsl'
|
|
7
7
|
SSHKit.config.backend = SSHKit::Backend::Libssh
|
8
8
|
SSHKit.config.backend.configure do |backend|
|
9
9
|
backend.pty = ENV.key?('REQUEST_PTY')
|
10
|
+
backend.ssh_options[:user] = ENV['SSH_USER']
|
11
|
+
if ENV.key?('SSH_PORT')
|
12
|
+
backend.ssh_options[:port] = ENV['SSH_PORT'].to_i
|
13
|
+
end
|
10
14
|
end
|
11
15
|
SSHKit.config.output = SSHKit::Formatter::Pretty.new($stdout)
|
12
16
|
SSHKit.config.output_verbosity = :debug
|
@@ -20,3 +24,10 @@ on %w[barkhorn rossmann], in: :parallel do
|
|
20
24
|
execute :ruby, '-e', Shellwords.escape('puts "stdout"; $stderr.puts "stderr"')
|
21
25
|
execute :false, raise_on_non_zero_exit: false
|
22
26
|
end
|
27
|
+
|
28
|
+
on %w[barkhorn rossmann], in: :parallel do |host|
|
29
|
+
upload! __FILE__, '/tmp/sshkit.rb'
|
30
|
+
upload! StringIO.new("libssh\n"), '/tmp/libssh.txt'
|
31
|
+
|
32
|
+
download! '/etc/passwd', "/tmp/#{host}-passwd"
|
33
|
+
end
|
data/ext/libssh_ruby/channel.c
CHANGED
@@ -80,6 +80,14 @@ static void *nogvl_close(void *ptr) {
|
|
80
80
|
return NULL;
|
81
81
|
}
|
82
82
|
|
83
|
+
/*
|
84
|
+
* @overload close
|
85
|
+
* Close a channel.
|
86
|
+
* @since 0.1.0
|
87
|
+
* @return [nil]
|
88
|
+
* @see http://api.libssh.org/stable/group__libssh__channel.html
|
89
|
+
* ssh_channel_close
|
90
|
+
*/
|
83
91
|
static VALUE m_close(VALUE self) {
|
84
92
|
ChannelHolder *holder;
|
85
93
|
struct nogvl_channel_args args;
|
@@ -98,6 +106,15 @@ static void *nogvl_open_session(void *ptr) {
|
|
98
106
|
return NULL;
|
99
107
|
}
|
100
108
|
|
109
|
+
/*
|
110
|
+
* @overload open_session
|
111
|
+
* Open a session channel, and close it after the block.
|
112
|
+
* @since 0.1.0
|
113
|
+
* @yieldparam [Channel] channel self
|
114
|
+
* @return [Object] Return value of the block
|
115
|
+
* @see http://api.libssh.org/stable/group__libssh__channel.html
|
116
|
+
* ssh_channel_open_session
|
117
|
+
*/
|
101
118
|
static VALUE m_open_session(VALUE self) {
|
102
119
|
ChannelHolder *holder;
|
103
120
|
struct nogvl_channel_args args;
|
@@ -127,6 +144,15 @@ static void *nogvl_request_exec(void *ptr) {
|
|
127
144
|
return NULL;
|
128
145
|
}
|
129
146
|
|
147
|
+
/*
|
148
|
+
* @overload request_exec(cmd)
|
149
|
+
* Run a shell command without an interactive shell.
|
150
|
+
* @since 0.1.0
|
151
|
+
* @param [String] cmd The command to execute
|
152
|
+
* @return [nil]
|
153
|
+
* @see http://api.libssh.org/stable/group__libssh__channel.html
|
154
|
+
* ssh_channel_request_exec
|
155
|
+
*/
|
130
156
|
static VALUE m_request_exec(VALUE self, VALUE cmd) {
|
131
157
|
ChannelHolder *holder;
|
132
158
|
struct nogvl_request_exec_args args;
|
@@ -145,6 +171,14 @@ static void *nogvl_request_pty(void *ptr) {
|
|
145
171
|
return NULL;
|
146
172
|
}
|
147
173
|
|
174
|
+
/*
|
175
|
+
* @overload request_pty
|
176
|
+
* Request a PTY.
|
177
|
+
* @since 0.1.0
|
178
|
+
* @return [nil]
|
179
|
+
* @see http://api.libssh.org/stable/group__libssh__channel.html
|
180
|
+
* ssh_channel_request_pty
|
181
|
+
*/
|
148
182
|
static VALUE m_request_pty(VALUE self) {
|
149
183
|
ChannelHolder *holder;
|
150
184
|
struct nogvl_channel_args args;
|
@@ -172,6 +206,17 @@ static void *nogvl_read(void *ptr) {
|
|
172
206
|
return NULL;
|
173
207
|
}
|
174
208
|
|
209
|
+
/*
|
210
|
+
* @overload read(count, is_stderr: false, timeout: -1)
|
211
|
+
* Read data from a channel.
|
212
|
+
* @since 0.1.0
|
213
|
+
* @param [Fixnum] count The count of bytes to be read.
|
214
|
+
* @param [Boolean] is_stderr Read from the stderr flow or not.
|
215
|
+
* @param [Fixnum] timeout A timeout in seconds. +-1+ means infinite timeout.
|
216
|
+
* @return [String] Data read from the channel.
|
217
|
+
* @see http://api.libssh.org/stable/group__libssh__channel.html
|
218
|
+
* ssh_channel_read_timeout
|
219
|
+
*/
|
175
220
|
static VALUE m_read(int argc, VALUE *argv, VALUE self) {
|
176
221
|
ChannelHolder *holder;
|
177
222
|
VALUE count, opts;
|
@@ -205,6 +250,14 @@ static VALUE m_read(int argc, VALUE *argv, VALUE self) {
|
|
205
250
|
return ret;
|
206
251
|
}
|
207
252
|
|
253
|
+
/*
|
254
|
+
* @overload eof?
|
255
|
+
* Check if remote ha sent an EOF.
|
256
|
+
* @since 0.1.0
|
257
|
+
* @return [Boolean]
|
258
|
+
* @see http://api.libssh.org/stable/group__libssh__channel.html
|
259
|
+
* ssh_channel_is_eof
|
260
|
+
*/
|
208
261
|
static VALUE m_eof_p(VALUE self) {
|
209
262
|
ChannelHolder *holder;
|
210
263
|
|
@@ -226,6 +279,18 @@ static void *nogvl_poll(void *ptr) {
|
|
226
279
|
return NULL;
|
227
280
|
}
|
228
281
|
|
282
|
+
/*
|
283
|
+
* @overload poll(is_stderr: false, timeout: -1)
|
284
|
+
* Poll a channel for data to read.
|
285
|
+
* @since 0.1.0
|
286
|
+
* @param [Boolean] is_stderr A boolean to select the stderr stream.
|
287
|
+
* @param [Fixnum] timeout A timeout in milliseconds. A negative value means an
|
288
|
+
* infinite timeout.
|
289
|
+
* @return [Fixnum, nil] The number of bytes available for reading. +nil+ if
|
290
|
+
* timed out.
|
291
|
+
* @see http://api.libssh.org/stable/group__libssh__channel.html
|
292
|
+
* ssh_channel_poll_timeout
|
293
|
+
*/
|
229
294
|
static VALUE m_poll(int argc, VALUE *argv, VALUE self) {
|
230
295
|
ChannelHolder *holder;
|
231
296
|
VALUE opts;
|
@@ -265,6 +330,15 @@ static void *nogvl_get_exit_status(void *ptr) {
|
|
265
330
|
return NULL;
|
266
331
|
}
|
267
332
|
|
333
|
+
/*
|
334
|
+
* @overload get_exit_status
|
335
|
+
* Get the exit status of the channel.
|
336
|
+
* @since 0.1.0
|
337
|
+
* @return [Fixnum, nil] The exit status. +nil+ if no exit status has been
|
338
|
+
* returned.
|
339
|
+
* @see http://api.libssh.org/stable/group__libssh__channel.html
|
340
|
+
* ssh_channel_get_exit_status
|
341
|
+
*/
|
268
342
|
static VALUE m_get_exit_status(VALUE self) {
|
269
343
|
ChannelHolder *holder;
|
270
344
|
struct nogvl_channel_args args;
|
@@ -292,6 +366,15 @@ static void *nogvl_write(void *ptr) {
|
|
292
366
|
return NULL;
|
293
367
|
}
|
294
368
|
|
369
|
+
/*
|
370
|
+
* @overload write(data)
|
371
|
+
* Write data on the channel.
|
372
|
+
* @since 0.1.0
|
373
|
+
* @param [String] data Data to write.
|
374
|
+
* @return [Fixnum] The number of bytes written.
|
375
|
+
* @see http://api.libssh.org/stable/group__libssh__channel.html
|
376
|
+
* ssh_channel_write
|
377
|
+
*/
|
295
378
|
static VALUE m_write(VALUE self, VALUE data) {
|
296
379
|
ChannelHolder *holder;
|
297
380
|
struct nogvl_write_args args;
|
@@ -312,6 +395,14 @@ static void *nogvl_send_eof(void *ptr) {
|
|
312
395
|
return NULL;
|
313
396
|
}
|
314
397
|
|
398
|
+
/*
|
399
|
+
* @overload send_eof
|
400
|
+
* Send EOF on the channel.
|
401
|
+
* @since 0.1.0
|
402
|
+
* @return [nil]
|
403
|
+
* @see http://api.libssh.org/stable/group__libssh__channel.html
|
404
|
+
* ssh_channel_send_eof
|
405
|
+
*/
|
315
406
|
static VALUE m_send_eof(VALUE self) {
|
316
407
|
ChannelHolder *holder;
|
317
408
|
struct nogvl_channel_args args;
|
data/ext/libssh_ruby/key.c
CHANGED
@@ -41,6 +41,13 @@ KeyHolder *libssh_ruby_key_holder(VALUE key) {
|
|
41
41
|
return holder;
|
42
42
|
}
|
43
43
|
|
44
|
+
/*
|
45
|
+
* @overload sha1
|
46
|
+
* Return the hash in SHA1 form.
|
47
|
+
* @since 0.1.0
|
48
|
+
* @return [String]
|
49
|
+
* @see http://api.libssh.org/stable/group__libssh__pki.html
|
50
|
+
*/
|
44
51
|
static VALUE m_sha1(VALUE self) {
|
45
52
|
KeyHolder *holder;
|
46
53
|
unsigned char *c_hash;
|
@@ -55,19 +62,48 @@ static VALUE m_sha1(VALUE self) {
|
|
55
62
|
return hash;
|
56
63
|
}
|
57
64
|
|
65
|
+
/*
|
66
|
+
* @overload type
|
67
|
+
* Return the type of a SSH key.
|
68
|
+
* @since 0.1.0
|
69
|
+
* @return [Fixnum]
|
70
|
+
* @see http://api.libssh.org/stable/group__libssh__pki.html ssh_key_type
|
71
|
+
*/
|
58
72
|
static VALUE m_type(VALUE self) {
|
59
73
|
return INT2FIX(ssh_key_type(libssh_ruby_key_holder(self)->key));
|
60
74
|
}
|
61
75
|
|
76
|
+
/*
|
77
|
+
* @overload type_str
|
78
|
+
* Return the type of a SSH key in string format.
|
79
|
+
* @since 0.1.0
|
80
|
+
* @return [String]
|
81
|
+
* @see http://api.libssh.org/stable/group__libssh__pki.html ssh_key_type and
|
82
|
+
* ssh_key_type_to_char
|
83
|
+
*/
|
62
84
|
static VALUE m_type_str(VALUE self) {
|
63
85
|
return rb_str_new_cstr(
|
64
86
|
ssh_key_type_to_char(ssh_key_type(libssh_ruby_key_holder(self)->key)));
|
65
87
|
}
|
66
88
|
|
89
|
+
/*
|
90
|
+
* @overload public?
|
91
|
+
* Check if the key is a public key.
|
92
|
+
* @since 0.1.0
|
93
|
+
* @return [Boolean]
|
94
|
+
* @see http://api.libssh.org/stable/group__libssh__pki.html ssh_key_is_public
|
95
|
+
*/
|
67
96
|
static VALUE m_public_p(VALUE self) {
|
68
97
|
return ssh_key_is_public(libssh_ruby_key_holder(self)->key) ? Qtrue : Qfalse;
|
69
98
|
}
|
70
99
|
|
100
|
+
/*
|
101
|
+
* @overload private?
|
102
|
+
* Check if the key is a private key.
|
103
|
+
* @since 0.1.0
|
104
|
+
* @return [Boolean]
|
105
|
+
* @see http://api.libssh.org/stable/group__libssh__pki.html ssh_key_is_private
|
106
|
+
*/
|
71
107
|
static VALUE m_private_p(VALUE self) {
|
72
108
|
return ssh_key_is_private(libssh_ruby_key_holder(self)->key) ? Qtrue : Qfalse;
|
73
109
|
}
|
@@ -2,6 +2,29 @@
|
|
2
2
|
|
3
3
|
VALUE rb_mLibSSH;
|
4
4
|
|
5
|
+
/*
|
6
|
+
* @overload version(req_version = 0)
|
7
|
+
* When +req_version+ is given, check if libssh is the required version.
|
8
|
+
* When +req_version+ isn't given, return the libssh version string.
|
9
|
+
*
|
10
|
+
* @since 0.2.0
|
11
|
+
* @param [Fixnum] req_version The version required.
|
12
|
+
* @return [String, nil] The libssh version string if it's newer than
|
13
|
+
* +req_version+ .
|
14
|
+
* @see http://api.libssh.org/stable/group__libssh__misc.html
|
15
|
+
*/
|
16
|
+
static VALUE m_version(int argc, VALUE *argv, RB_UNUSED_VAR(VALUE self)) {
|
17
|
+
VALUE req_version;
|
18
|
+
int c_req_version = 0;
|
19
|
+
|
20
|
+
rb_scan_args(argc, argv, "01", &req_version);
|
21
|
+
if (!NIL_P(req_version)) {
|
22
|
+
Check_Type(req_version, T_FIXNUM);
|
23
|
+
c_req_version = FIX2INT(req_version);
|
24
|
+
}
|
25
|
+
return rb_str_new_cstr(ssh_version(c_req_version));
|
26
|
+
}
|
27
|
+
|
5
28
|
void Init_libssh_ruby(void) {
|
6
29
|
rb_mLibSSH = rb_define_module("LibSSH");
|
7
30
|
#define SERVER(name) \
|
@@ -20,8 +43,23 @@ void Init_libssh_ruby(void) {
|
|
20
43
|
AUTH(AGAIN);
|
21
44
|
#undef AUTH
|
22
45
|
|
46
|
+
rb_define_const(rb_mLibSSH, "LIBSSH_VERSION_MAJOR",
|
47
|
+
INT2FIX(LIBSSH_VERSION_MAJOR));
|
48
|
+
rb_define_const(rb_mLibSSH, "LIBSSH_VERSION_MINOR",
|
49
|
+
INT2FIX(LIBSSH_VERSION_MINOR));
|
50
|
+
rb_define_const(rb_mLibSSH, "LIBSSH_VERSION_MICRO",
|
51
|
+
INT2FIX(LIBSSH_VERSION_MICRO));
|
52
|
+
rb_define_const(rb_mLibSSH, "LIBSSH_VERSION_INT",
|
53
|
+
INT2FIX(LIBSSH_VERSION_INT));
|
54
|
+
rb_define_const(rb_mLibSSH, "LIBSSH_VERSION",
|
55
|
+
rb_str_new_cstr(SSH_STRINGIFY(LIBSSH_VERSION)));
|
56
|
+
|
57
|
+
rb_define_singleton_method(rb_mLibSSH, "version", RUBY_METHOD_FUNC(m_version),
|
58
|
+
-1);
|
59
|
+
|
23
60
|
Init_libssh_session();
|
24
61
|
Init_libssh_channel();
|
25
62
|
Init_libssh_error();
|
26
63
|
Init_libssh_key();
|
64
|
+
Init_libssh_scp();
|
27
65
|
}
|