libssh 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,25 @@
1
+ #include "libssh_ruby.h"
2
+
3
+ VALUE rb_eLibSSHError;
4
+ ID id_code;
5
+
6
+ void Init_libssh_error(void) {
7
+ rb_eLibSSHError =
8
+ rb_define_class_under(rb_mLibSSH, "Error", rb_eStandardError);
9
+ id_code = rb_intern("code");
10
+
11
+ rb_define_attr(rb_eLibSSHError, "code", 1, 0);
12
+ }
13
+
14
+ void libssh_ruby_raise(ssh_session session) {
15
+ VALUE exc, code, message;
16
+ VALUE argv[1];
17
+
18
+ code = INT2FIX(ssh_get_error_code(session));
19
+ message = rb_str_new_cstr(ssh_get_error(session));
20
+ argv[0] = message;
21
+ exc = rb_class_new_instance(1, argv, rb_eLibSSHError);
22
+ rb_ivar_set(exc, id_code, code);
23
+
24
+ rb_exc_raise(exc);
25
+ }
@@ -0,0 +1,9 @@
1
+ require 'mkmf'
2
+
3
+ $CFLAGS << ' -Wall -W'
4
+
5
+ have_header('libssh/libssh.h')
6
+ have_library('ssh')
7
+ have_const('SSH_KEYTYPE_ED25519', 'libssh/libssh.h')
8
+
9
+ create_makefile('libssh/libssh_ruby')
@@ -0,0 +1,98 @@
1
+ #include "libssh_ruby.h"
2
+
3
+ VALUE rb_cLibSSHKey;
4
+
5
+ static void key_free(void *);
6
+ static size_t key_memsize(const void *);
7
+
8
+ static const rb_data_type_t key_type = {
9
+ "ssh_key", {NULL, key_free, key_memsize, {NULL, NULL}}, NULL,
10
+ NULL, RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_FREE_IMMEDIATELY,
11
+ };
12
+
13
+ static VALUE key_alloc(VALUE klass) {
14
+ KeyHolder *holder = ALLOC(KeyHolder);
15
+ holder->key = NULL;
16
+ return TypedData_Wrap_Struct(klass, &key_type, holder);
17
+ }
18
+
19
+ static void key_free(void *arg) {
20
+ KeyHolder *holder = arg;
21
+ if (holder->key != NULL) {
22
+ ssh_key_free(holder->key);
23
+ }
24
+ ruby_xfree(holder);
25
+ }
26
+
27
+ static size_t key_memsize(RB_UNUSED_VAR(const void *arg)) {
28
+ return sizeof(KeyHolder);
29
+ }
30
+
31
+ static VALUE m_initialize(VALUE self) {
32
+ KeyHolder *holder;
33
+ TypedData_Get_Struct(self, KeyHolder, &key_type, holder);
34
+ holder->key = ssh_key_new();
35
+ return self;
36
+ }
37
+
38
+ KeyHolder *libssh_ruby_key_holder(VALUE key) {
39
+ KeyHolder *holder;
40
+ TypedData_Get_Struct(key, KeyHolder, &key_type, holder);
41
+ return holder;
42
+ }
43
+
44
+ static VALUE m_sha1(VALUE self) {
45
+ KeyHolder *holder;
46
+ unsigned char *c_hash;
47
+ size_t len;
48
+ VALUE hash;
49
+
50
+ holder = libssh_ruby_key_holder(self);
51
+ ssh_get_publickey_hash(holder->key, SSH_PUBLICKEY_HASH_SHA1, &c_hash, &len);
52
+ hash = rb_str_new((char *)c_hash, len);
53
+ ssh_clean_pubkey_hash(&c_hash);
54
+
55
+ return hash;
56
+ }
57
+
58
+ static VALUE m_type(VALUE self) {
59
+ return INT2FIX(ssh_key_type(libssh_ruby_key_holder(self)->key));
60
+ }
61
+
62
+ static VALUE m_type_str(VALUE self) {
63
+ return rb_str_new_cstr(
64
+ ssh_key_type_to_char(ssh_key_type(libssh_ruby_key_holder(self)->key)));
65
+ }
66
+
67
+ static VALUE m_public_p(VALUE self) {
68
+ return ssh_key_is_public(libssh_ruby_key_holder(self)->key) ? Qtrue : Qfalse;
69
+ }
70
+
71
+ static VALUE m_private_p(VALUE self) {
72
+ return ssh_key_is_private(libssh_ruby_key_holder(self)->key) ? Qtrue : Qfalse;
73
+ }
74
+
75
+ void Init_libssh_key(void) {
76
+ rb_cLibSSHKey = rb_define_class_under(rb_mLibSSH, "Key", rb_cObject);
77
+ rb_define_alloc_func(rb_cLibSSHKey, key_alloc);
78
+
79
+ #define E(name) \
80
+ rb_define_const(rb_cLibSSHKey, "KEYTYPE_" #name, INT2FIX(SSH_KEYTYPE_##name))
81
+ E(UNKNOWN);
82
+ E(DSS);
83
+ E(RSA);
84
+ E(RSA1);
85
+ E(ECDSA);
86
+ #ifdef HAVE_CONST_SSH_KEYTYPE_ED25519
87
+ E(ED25519);
88
+ #endif
89
+ #undef E
90
+
91
+ rb_define_method(rb_cLibSSHKey, "initialize", RUBY_METHOD_FUNC(m_initialize),
92
+ 0);
93
+ rb_define_method(rb_cLibSSHKey, "sha1", RUBY_METHOD_FUNC(m_sha1), 0);
94
+ rb_define_method(rb_cLibSSHKey, "type", RUBY_METHOD_FUNC(m_type), 0);
95
+ rb_define_method(rb_cLibSSHKey, "type_str", RUBY_METHOD_FUNC(m_type_str), 0);
96
+ rb_define_method(rb_cLibSSHKey, "public?", RUBY_METHOD_FUNC(m_public_p), 0);
97
+ rb_define_method(rb_cLibSSHKey, "private?", RUBY_METHOD_FUNC(m_private_p), 0);
98
+ }
@@ -0,0 +1,27 @@
1
+ #include "libssh_ruby.h"
2
+
3
+ VALUE rb_mLibSSH;
4
+
5
+ void Init_libssh_ruby(void) {
6
+ rb_mLibSSH = rb_define_module("LibSSH");
7
+ #define SERVER(name) \
8
+ rb_define_const(rb_mLibSSH, "SERVER_" #name, INT2FIX(SSH_SERVER_##name))
9
+ SERVER(KNOWN_OK);
10
+ SERVER(KNOWN_CHANGED);
11
+ SERVER(FOUND_OTHER);
12
+ SERVER(NOT_KNOWN);
13
+ SERVER(FILE_NOT_FOUND);
14
+ #undef SERVER
15
+ #define AUTH(name) \
16
+ rb_define_const(rb_mLibSSH, "AUTH_" #name, INT2FIX(SSH_AUTH_##name))
17
+ AUTH(DENIED);
18
+ AUTH(PARTIAL);
19
+ AUTH(SUCCESS);
20
+ AUTH(AGAIN);
21
+ #undef AUTH
22
+
23
+ Init_libssh_session();
24
+ Init_libssh_channel();
25
+ Init_libssh_error();
26
+ Init_libssh_key();
27
+ }
@@ -0,0 +1,34 @@
1
+ #ifndef LIBSSH_RUBY_H
2
+ #define LIBSSH_RUBY_H 1
3
+
4
+ /* Don't use deprecated functions */
5
+ #define LIBSSH_LEGACY_0_4
6
+
7
+ #include <ruby/ruby.h>
8
+ #include <libssh/libssh.h>
9
+
10
+ extern VALUE rb_mLibSSH;
11
+ extern VALUE rb_cLibSSHKey;
12
+
13
+ void Init_libssh_ruby(void);
14
+ void Init_libssh_session(void);
15
+ void Init_libssh_channel(void);
16
+ void Init_libssh_error(void);
17
+ void Init_libssh_key(void);
18
+
19
+ void libssh_ruby_raise(ssh_session session);
20
+
21
+ struct SessionHolderStruct {
22
+ ssh_session session;
23
+ };
24
+ typedef struct SessionHolderStruct SessionHolder;
25
+
26
+ struct KeyHolderStruct {
27
+ ssh_key key;
28
+ };
29
+ typedef struct KeyHolderStruct KeyHolder;
30
+
31
+ SessionHolder *libssh_ruby_session_holder(VALUE session);
32
+ KeyHolder *libssh_ruby_key_holder(VALUE key);
33
+
34
+ #endif /* LIBSSH_RUBY_H */
@@ -0,0 +1,281 @@
1
+ #include "libssh_ruby.h"
2
+ #include <ruby/thread.h>
3
+
4
+ #define RAISE_IF_ERROR(rc) \
5
+ if ((rc) == SSH_ERROR) libssh_ruby_raise(holder->session)
6
+
7
+ VALUE rb_cLibSSHSession;
8
+
9
+ static ID id_none, id_warn, id_info, id_debug, id_trace;
10
+ static ID id_password, id_publickey, id_hostbased, id_interactive,
11
+ id_gssapi_mic;
12
+
13
+ static void session_mark(void *);
14
+ static void session_free(void *);
15
+ static size_t session_memsize(const void *);
16
+
17
+ const rb_data_type_t session_type = {
18
+ "ssh_session",
19
+ {session_mark, session_free, session_memsize, {NULL, NULL}},
20
+ NULL,
21
+ NULL,
22
+ RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_FREE_IMMEDIATELY,
23
+ };
24
+
25
+ SessionHolder *libssh_ruby_session_holder(VALUE session) {
26
+ SessionHolder *holder;
27
+ TypedData_Get_Struct(session, SessionHolder, &session_type, holder);
28
+ return holder;
29
+ }
30
+
31
+ static VALUE session_alloc(VALUE klass) {
32
+ SessionHolder *holder = ALLOC(SessionHolder);
33
+ holder->session = NULL;
34
+ return TypedData_Wrap_Struct(klass, &session_type, holder);
35
+ }
36
+
37
+ static void session_mark(RB_UNUSED_VAR(void *arg)) {}
38
+
39
+ static void session_free(void *arg) {
40
+ SessionHolder *holder = arg;
41
+ if (holder->session != NULL) {
42
+ ssh_free(holder->session);
43
+ holder->session = NULL;
44
+ }
45
+ ruby_xfree(holder);
46
+ }
47
+
48
+ static size_t session_memsize(RB_UNUSED_VAR(const void *arg)) {
49
+ return sizeof(SessionHolder);
50
+ }
51
+
52
+ static VALUE m_initialize(VALUE self) {
53
+ SessionHolder *holder;
54
+
55
+ TypedData_Get_Struct(self, SessionHolder, &session_type, holder);
56
+ holder->session = ssh_new();
57
+ return self;
58
+ }
59
+
60
+ static VALUE m_set_log_verbosity(VALUE self, VALUE verbosity) {
61
+ ID id_verbosity;
62
+ int c_verbosity;
63
+ SessionHolder *holder;
64
+
65
+ Check_Type(verbosity, T_SYMBOL);
66
+ id_verbosity = SYM2ID(verbosity);
67
+
68
+ if (id_verbosity == id_none) {
69
+ c_verbosity = SSH_LOG_NONE;
70
+ } else if (id_verbosity == id_warn) {
71
+ c_verbosity = SSH_LOG_WARN;
72
+ } else if (id_verbosity == id_info) {
73
+ c_verbosity = SSH_LOG_INFO;
74
+ } else if (id_verbosity == id_debug) {
75
+ c_verbosity = SSH_LOG_DEBUG;
76
+ } else if (id_verbosity == id_trace) {
77
+ c_verbosity = SSH_LOG_TRACE;
78
+ } else {
79
+ rb_raise(rb_eArgError, "invalid verbosity: %" PRIsVALUE, verbosity);
80
+ }
81
+
82
+ TypedData_Get_Struct(self, SessionHolder, &session_type, holder);
83
+ RAISE_IF_ERROR(ssh_options_set(holder->session, SSH_OPTIONS_LOG_VERBOSITY,
84
+ &c_verbosity));
85
+
86
+ return Qnil;
87
+ }
88
+
89
+ static VALUE m_set_host(VALUE self, VALUE host) {
90
+ SessionHolder *holder;
91
+
92
+ TypedData_Get_Struct(self, SessionHolder, &session_type, holder);
93
+ RAISE_IF_ERROR(ssh_options_set(holder->session, SSH_OPTIONS_HOST,
94
+ StringValueCStr(host)));
95
+
96
+ return Qnil;
97
+ }
98
+
99
+ static VALUE m_parse_config(int argc, VALUE *argv, VALUE self) {
100
+ SessionHolder *holder;
101
+ VALUE path;
102
+ char *c_path;
103
+
104
+ rb_scan_args(argc, argv, "01", &path);
105
+
106
+ if (NIL_P(path)) {
107
+ c_path = NULL;
108
+ } else {
109
+ c_path = StringValueCStr(path);
110
+ }
111
+
112
+ TypedData_Get_Struct(self, SessionHolder, &session_type, holder);
113
+ if (ssh_options_parse_config(holder->session, c_path) == 0) {
114
+ return Qtrue;
115
+ } else {
116
+ return Qfalse;
117
+ }
118
+ }
119
+
120
+ static VALUE m_add_identity(VALUE self, VALUE path) {
121
+ SessionHolder *holder;
122
+
123
+ TypedData_Get_Struct(self, SessionHolder, &session_type, holder);
124
+ RAISE_IF_ERROR(ssh_options_set(holder->session, SSH_OPTIONS_ADD_IDENTITY,
125
+ StringValueCStr(path)));
126
+
127
+ return Qnil;
128
+ }
129
+
130
+ struct nogvl_session_args {
131
+ ssh_session session;
132
+ int rc;
133
+ };
134
+
135
+ static void *nogvl_connect(void *ptr) {
136
+ struct nogvl_session_args *args = ptr;
137
+ args->rc = ssh_connect(args->session);
138
+ return NULL;
139
+ }
140
+
141
+ static VALUE m_connect(VALUE self) {
142
+ SessionHolder *holder;
143
+ struct nogvl_session_args args;
144
+
145
+ TypedData_Get_Struct(self, SessionHolder, &session_type, holder);
146
+ args.session = holder->session;
147
+ rb_thread_call_without_gvl(nogvl_connect, &args, RUBY_UBF_IO, NULL);
148
+ RAISE_IF_ERROR(args.rc);
149
+
150
+ return Qnil;
151
+ }
152
+
153
+ static VALUE m_server_known(VALUE self) {
154
+ SessionHolder *holder;
155
+ int rc;
156
+
157
+ TypedData_Get_Struct(self, SessionHolder, &session_type, holder);
158
+ rc = ssh_is_server_known(holder->session);
159
+ RAISE_IF_ERROR(rc);
160
+ return INT2FIX(rc);
161
+ }
162
+
163
+ static VALUE m_userauth_none(VALUE self) {
164
+ SessionHolder *holder;
165
+ int rc;
166
+
167
+ TypedData_Get_Struct(self, SessionHolder, &session_type, holder);
168
+ rc = ssh_userauth_none(holder->session, NULL);
169
+ RAISE_IF_ERROR(rc);
170
+ return INT2FIX(rc);
171
+ }
172
+
173
+ static VALUE m_userauth_list(VALUE self) {
174
+ SessionHolder *holder;
175
+ int list;
176
+ VALUE ary;
177
+
178
+ TypedData_Get_Struct(self, SessionHolder, &session_type, holder);
179
+ list = ssh_userauth_list(holder->session, NULL);
180
+ RAISE_IF_ERROR(list);
181
+
182
+ ary = rb_ary_new();
183
+ if (list & SSH_AUTH_METHOD_NONE) {
184
+ rb_ary_push(ary, ID2SYM(id_none));
185
+ }
186
+ if (list & SSH_AUTH_METHOD_PASSWORD) {
187
+ rb_ary_push(ary, ID2SYM(id_password));
188
+ }
189
+ if (list & SSH_AUTH_METHOD_PUBLICKEY) {
190
+ rb_ary_push(ary, ID2SYM(id_publickey));
191
+ }
192
+ if (list & SSH_AUTH_METHOD_HOSTBASED) {
193
+ rb_ary_push(ary, ID2SYM(id_hostbased));
194
+ }
195
+ if (list & SSH_AUTH_METHOD_INTERACTIVE) {
196
+ rb_ary_push(ary, ID2SYM(id_interactive));
197
+ }
198
+ if (list & SSH_AUTH_METHOD_GSSAPI_MIC) {
199
+ rb_ary_push(ary, ID2SYM(id_gssapi_mic));
200
+ }
201
+ return ary;
202
+ }
203
+
204
+ static void *nogvl_userauth_publickey_auto(void *ptr) {
205
+ struct nogvl_session_args *args = ptr;
206
+ args->rc = ssh_userauth_publickey_auto(args->session, NULL, NULL);
207
+ return NULL;
208
+ }
209
+
210
+ static VALUE m_userauth_publickey_auto(VALUE self) {
211
+ SessionHolder *holder;
212
+ struct nogvl_session_args args;
213
+
214
+ TypedData_Get_Struct(self, SessionHolder, &session_type, holder);
215
+ args.session = holder->session;
216
+ rb_thread_call_without_gvl(nogvl_userauth_publickey_auto, &args, RUBY_UBF_IO,
217
+ NULL);
218
+ return INT2FIX(args.rc);
219
+ }
220
+
221
+ static VALUE m_get_publickey(VALUE self) {
222
+ SessionHolder *holder;
223
+ KeyHolder *key_holder;
224
+ VALUE key;
225
+
226
+ TypedData_Get_Struct(self, SessionHolder, &session_type, holder);
227
+ key = rb_obj_alloc(rb_cLibSSHKey);
228
+ key_holder = libssh_ruby_key_holder(key);
229
+ RAISE_IF_ERROR(ssh_get_publickey(holder->session, &key_holder->key));
230
+ return key;
231
+ }
232
+
233
+ static VALUE m_write_knownhost(VALUE self) {
234
+ SessionHolder *holder;
235
+
236
+ holder = libssh_ruby_session_holder(self);
237
+ RAISE_IF_ERROR(ssh_write_knownhost(holder->session));
238
+ return Qnil;
239
+ }
240
+
241
+ void Init_libssh_session() {
242
+ rb_cLibSSHSession = rb_define_class_under(rb_mLibSSH, "Session", rb_cObject);
243
+ rb_define_alloc_func(rb_cLibSSHSession, session_alloc);
244
+
245
+ #define I(name) id_##name = rb_intern(#name)
246
+ I(none);
247
+ I(warn);
248
+ I(info);
249
+ I(debug);
250
+ I(trace);
251
+ I(password);
252
+ I(publickey);
253
+ I(hostbased);
254
+ I(interactive);
255
+ I(gssapi_mic);
256
+ #undef I
257
+
258
+ rb_define_method(rb_cLibSSHSession, "initialize",
259
+ RUBY_METHOD_FUNC(m_initialize), 0);
260
+ rb_define_method(rb_cLibSSHSession, "log_verbosity=",
261
+ RUBY_METHOD_FUNC(m_set_log_verbosity), 1);
262
+ rb_define_method(rb_cLibSSHSession, "host=", RUBY_METHOD_FUNC(m_set_host), 1);
263
+ rb_define_method(rb_cLibSSHSession, "parse_config",
264
+ RUBY_METHOD_FUNC(m_parse_config), -1);
265
+ rb_define_method(rb_cLibSSHSession, "add_identity",
266
+ RUBY_METHOD_FUNC(m_add_identity), 1);
267
+ rb_define_method(rb_cLibSSHSession, "connect", RUBY_METHOD_FUNC(m_connect),
268
+ 0);
269
+ rb_define_method(rb_cLibSSHSession, "server_known",
270
+ RUBY_METHOD_FUNC(m_server_known), 0);
271
+ rb_define_method(rb_cLibSSHSession, "userauth_none",
272
+ RUBY_METHOD_FUNC(m_userauth_none), 0);
273
+ rb_define_method(rb_cLibSSHSession, "userauth_list",
274
+ RUBY_METHOD_FUNC(m_userauth_list), 0);
275
+ rb_define_method(rb_cLibSSHSession, "userauth_publickey_auto",
276
+ RUBY_METHOD_FUNC(m_userauth_publickey_auto), 0);
277
+ rb_define_method(rb_cLibSSHSession, "get_publickey",
278
+ RUBY_METHOD_FUNC(m_get_publickey), 0);
279
+ rb_define_method(rb_cLibSSHSession, "write_knownhost",
280
+ RUBY_METHOD_FUNC(m_write_knownhost), 0);
281
+ }