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