libssh 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
+
[](https://badge.fury.io/rb/libssh)
|
2
3
|
[](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
|
}
|