1 /// Small wrapper for libssh2
2 /// just link with it on Linux
3 /// it'll need a couple dlls and a lib on windows.
4 
5 module arsd.libssh2;
6 
7 version(libssh_example)
8 void main() {
9 	import std.socket;
10 
11 	if(libssh2_init(0))
12 		throw new Exception("libssh2_init");
13 	scope(exit)
14 		libssh2_exit();
15 
16 	auto socket = new Socket(AddressFamily.INET, SocketType.STREAM);
17 	socket.connect(new InternetAddress("localhost", 22));
18 	scope(exit) socket.close();
19 
20 	auto session = libssh2_session_init_ex(null, null, null, null);
21 	if(session is null) throw new Exception("init session");
22 	scope(exit)
23 		libssh2_session_disconnect_ex(session, 0, "normal", "EN");
24 
25 	if(libssh2_session_handshake(session, socket.handle))
26 		throw new Exception("handshake");
27 
28 	auto fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_SHA1);
29 
30 	/*
31 	import core.stdc.stdio;
32 	for(int i = 0; i < 20; i++)
33 		printf("%02X ", fingerprint[i]);
34 	*/
35 
36 	/*
37 	auto got = libssh2_userauth_list(session, "me", 2);
38 	if(got is null) throw new Exception("list");
39 	import core.stdc.stdio;
40 	printf("%s\n", got);
41 	*/
42 
43 	if(auto err = libssh2_userauth_publickey_fromfile_ex(session, "me".ptr, "me".length, "/home/me/.ssh/id_rsa.pub", "/home/me/.ssh/id_rsa", null))
44 		throw new Exception("auth");
45 
46 
47 	auto channel = libssh2_channel_open_ex(session, "session".ptr, "session".length, LIBSSH2_CHANNEL_WINDOW_DEFAULT, LIBSSH2_CHANNEL_PACKET_DEFAULT, null, 0);
48 
49 	if(channel is null)
50 		throw new Exception("channel open");
51 
52 	scope(exit)
53 		libssh2_channel_free(channel);
54 
55 	libssh2_channel_setenv_ex(channel, "ELVISBG".dup.ptr, "ELVISBG".length, "dark".ptr, "dark".length);
56 
57 	if(libssh2_channel_request_pty_ex(channel, "xterm", "xterm".length, null, 0, 80, 24, 0, 0))
58 		throw new Exception("pty");
59 
60 	if(libssh2_channel_process_startup(channel, "shell".ptr, "shell".length, null, 0))
61 		throw new Exception("process_startup");
62 
63 	libssh2_keepalive_config(session, 0, 60);
64 	libssh2_session_set_blocking(session, 0);
65 
66 
67 	char[1024] buffer;
68 	again:
69 	auto got = libssh2_channel_read_ex(channel, 0, buffer.ptr, buffer.length);
70 	if(got == LIBSSH2_ERROR_EAGAIN) {
71 		import core.thread;
72 		Thread.sleep(msecs(500));
73 		goto again;
74 	}
75 
76 	import std.stdio;
77 	writeln(buffer[0 .. got]);
78 }
79 
80 
81 
82 
83 alias socket_t = int;
84 
85 version(Windows) {
86 	pragma(lib, "libssh2");
87 } else {
88 	pragma(lib, "ssh2");
89 }
90 
91 version(X86)
92 	alias ssize_t = int;
93 else version(X86_64)
94 	alias ssize_t = long;
95 
96 extern(C) {
97 	struct LIBSSH2_SESSION {}
98 	LIBSSH2_SESSION* libssh2_session_init_ex(void* myalloc, void* myfree, void* myrealloc, void* abstract_);
99 
100 	int libssh2_session_handshake(LIBSSH2_SESSION* session, socket_t socket);
101 
102 	enum int LIBSSH2_HOSTKEY_HASH_MD5 = 1;
103 	enum int LIBSSH2_HOSTKEY_HASH_SHA1 = 2;
104 	const(char)* libssh2_hostkey_hash(LIBSSH2_SESSION*, int hash_type);
105 
106 	int libssh2_userauth_publickey_fromfile_ex(
107 		LIBSSH2_SESSION* session,
108 		const char *username,
109 		uint ousername_len,
110 		const char *publickey,
111 		const char *privatekey,
112 		const char *passphrase);
113 
114 	struct LIBSSH2_CHANNEL {}
115 	LIBSSH2_CHANNEL* libssh2_channel_open_ex(
116 		LIBSSH2_SESSION *session,
117 		const char *channel_type,
118 		uint channel_type_len,
119 		uint window_size,
120 		uint packet_size,
121 		const char *message,
122 		uint message_len); 
123 	// channel_open_session calls the above
124 
125 	int libssh2_channel_setenv_ex(
126 		LIBSSH2_CHANNEL* channel,
127 		char* varname,
128 		uint varname_len,
129 		const char *value,
130 		uint value_len);
131 
132 	enum LIBSSH2_CHANNEL_WINDOW_DEFAULT = (256*1024);
133 	enum LIBSSH2_CHANNEL_PACKET_DEFAULT = 32768;
134 
135 	int libssh2_channel_request_pty_ex(LIBSSH2_CHANNEL *channel, const char *term, uint term_len, const char *modes, uint modes_len, int width, int height, int width_px, int height_px); 
136 
137 	int libssh2_channel_process_startup(
138 		LIBSSH2_CHANNEL* channel,
139 		const char *request,
140 		uint request_len,
141 		const char *message,
142 		uint message_len);
143  
144 
145 	int libssh2_channel_free(LIBSSH2_CHANNEL *channel); 
146 	int libssh2_session_disconnect_ex(LIBSSH2_SESSION *session, int reason, const char *description, const char *lang); 
147 	int libssh2_session_free(LIBSSH2_SESSION *session); 
148 
149 	int libssh2_init(int flags);
150 	void libssh2_exit();
151 
152 	// stream_id 0 == normal, 1 == error.
153 	ssize_t libssh2_channel_read_ex(LIBSSH2_CHANNEL *channel, int stream_id, void *buf, size_t buflen);
154 
155 	ssize_t libssh2_channel_write_ex(LIBSSH2_CHANNEL *channel,
156                                   int stream_id, const(void)* buf,
157                                   size_t buflen);
158 
159 	void libssh2_session_set_blocking(LIBSSH2_SESSION* session, int blocking);
160 
161 	void libssh2_keepalive_config(LIBSSH2_SESSION *session,
162 		int want_reply,
163 		uint interval);
164 
165 	int libssh2_keepalive_send(LIBSSH2_SESSION *session,
166 		int *seconds_to_next);
167 
168 	LIBSSH2_CHANNEL * libssh2_channel_direct_tcpip_ex(LIBSSH2_SESSION *session, const char *host, int port, const char *shost, int sport); 
169 
170 	int libssh2_channel_request_pty_size_ex(LIBSSH2_CHANNEL *channel,
171 		int width, int height,
172 		int width_px,
173 		int height_px);
174 
175 	char *
176  libssh2_userauth_list(LIBSSH2_SESSION *session, const char *username,
177                        uint username_len);
178 
179 	int libssh2_channel_eof(LIBSSH2_CHANNEL*);
180 	int libssh2_channel_close(LIBSSH2_CHANNEL*);
181 	int libssh2_channel_wait_closed(LIBSSH2_CHANNEL *channel);
182 
183 	enum LIBSSH2_ERROR_EAGAIN = -37;
184 
185 	int libssh2_session_flag(LIBSSH2_SESSION*, int, int);
186 	enum LIBSSH2_FLAG_SIGPIPE = 1;
187 	enum LIBSSH2_FLAG_COMPRESS = 2;
188 
189 }