geom_gate userland utility improvements
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

359 lines
9.6 KiB

  1. /*
  2. * Sample showing how to do SFTP transfers in a non-blocking manner.
  3. *
  4. * It will first download a given source file, store it locally and then
  5. * upload the file again to a given destination file.
  6. *
  7. * Using the SFTP server running on 127.0.0.1
  8. */
  9. #include "libssh2_config.h"
  10. #include <libssh2.h>
  11. #include <libssh2_sftp.h>
  12. #ifdef HAVE_WINSOCK2_H
  13. # include <winsock2.h>
  14. #endif
  15. #ifdef HAVE_SYS_SOCKET_H
  16. # include <sys/socket.h>
  17. #endif
  18. #ifdef HAVE_NETINET_IN_H
  19. # include <netinet/in.h>
  20. #endif
  21. #ifdef HAVE_SYS_SELECT_H
  22. # include <sys/select.h>
  23. #endif
  24. # ifdef HAVE_UNISTD_H
  25. #include <unistd.h>
  26. #endif
  27. #ifdef HAVE_ARPA_INET_H
  28. # include <arpa/inet.h>
  29. #endif
  30. #ifdef HAVE_SYS_TIME_H
  31. # include <sys/time.h>
  32. #endif
  33. #include <sys/types.h>
  34. #include <fcntl.h>
  35. #include <errno.h>
  36. #include <stdio.h>
  37. #include <ctype.h>
  38. #define STORAGE "/tmp/sftp-storage" /* this is the local file name this
  39. example uses to store the downloaded
  40. file in */
  41. static int waitsocket(int socket_fd, LIBSSH2_SESSION *session)
  42. {
  43. struct timeval timeout;
  44. int rc;
  45. fd_set fd;
  46. fd_set *writefd = NULL;
  47. fd_set *readfd = NULL;
  48. int dir;
  49. timeout.tv_sec = 10;
  50. timeout.tv_usec = 0;
  51. FD_ZERO(&fd);
  52. FD_SET(socket_fd, &fd);
  53. /* now make sure we wait in the correct direction */
  54. dir = libssh2_session_block_directions(session);
  55. if(dir & LIBSSH2_SESSION_BLOCK_INBOUND)
  56. readfd = &fd;
  57. if(dir & LIBSSH2_SESSION_BLOCK_OUTBOUND)
  58. writefd = &fd;
  59. rc = select(socket_fd + 1, readfd, writefd, NULL, &timeout);
  60. return rc;
  61. }
  62. int main(int argc, char *argv[])
  63. {
  64. int sock, i, auth_pw = 1;
  65. struct sockaddr_in sin;
  66. const char *fingerprint;
  67. LIBSSH2_SESSION *session;
  68. const char *username = "username";
  69. const char *password = "password";
  70. const char *sftppath = "/tmp/TEST"; /* source path */
  71. const char *dest = "/tmp/TEST2"; /* destination path */
  72. int rc;
  73. LIBSSH2_SFTP *sftp_session;
  74. LIBSSH2_SFTP_HANDLE *sftp_handle;
  75. FILE *tempstorage;
  76. char mem[1000];
  77. struct timeval timeout;
  78. fd_set fd;
  79. fd_set fd2;
  80. #ifdef WIN32
  81. WSADATA wsadata;
  82. int err;
  83. err = WSAStartup(MAKEWORD(2, 0), &wsadata);
  84. if(err != 0) {
  85. fprintf(stderr, "WSAStartup failed with error: %d\n", err);
  86. return 1;
  87. }
  88. #endif
  89. rc = libssh2_init(0);
  90. if(rc != 0) {
  91. fprintf(stderr, "libssh2 initialization failed (%d)\n", rc);
  92. return 1;
  93. }
  94. /* Ultra basic "connect to port 22 on localhost"
  95. * The application is responsible for creating the socket establishing
  96. * the connection
  97. */
  98. sock = socket(AF_INET, SOCK_STREAM, 0);
  99. sin.sin_family = AF_INET;
  100. sin.sin_port = htons(22);
  101. sin.sin_addr.s_addr = htonl(0x7F000001);
  102. if(connect(sock, (struct sockaddr*)(&sin),
  103. sizeof(struct sockaddr_in)) != 0) {
  104. fprintf(stderr, "failed to connect!\n");
  105. return -1;
  106. }
  107. /* Create a session instance
  108. */
  109. session = libssh2_session_init();
  110. if(!session)
  111. return -1;
  112. /* ... start it up. This will trade welcome banners, exchange keys,
  113. * and setup crypto, compression, and MAC layers
  114. */
  115. rc = libssh2_session_handshake(session, sock);
  116. if(rc) {
  117. fprintf(stderr, "Failure establishing SSH session: %d\n", rc);
  118. return -1;
  119. }
  120. libssh2_session_set_blocking(session, 0);
  121. /* At this point we havn't yet authenticated. The first thing to do
  122. * is check the hostkey's fingerprint against our known hosts Your app
  123. * may have it hard coded, may go to a file, may present it to the
  124. * user, that's your call
  125. */
  126. fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_SHA1);
  127. fprintf(stderr, "Fingerprint: ");
  128. for(i = 0; i < 20; i++) {
  129. fprintf(stderr, "%02X ", (unsigned char)fingerprint[i]);
  130. }
  131. fprintf(stderr, "\n");
  132. if(argc > 1) {
  133. username = argv[1];
  134. }
  135. if(argc > 2) {
  136. password = argv[2];
  137. }
  138. if(argc > 3) {
  139. sftppath = argv[3];
  140. }
  141. if(argc > 4) {
  142. dest = argv[4];
  143. }
  144. tempstorage = fopen(STORAGE, "wb");
  145. if(!tempstorage) {
  146. fprintf(stderr, "Can't open temp storage file %s\n", STORAGE);
  147. goto shutdown;
  148. }
  149. if(auth_pw) {
  150. /* We could authenticate via password */
  151. while((rc = libssh2_userauth_password(session, username, password))
  152. == LIBSSH2_ERROR_EAGAIN);
  153. if(rc) {
  154. fprintf(stderr, "Authentication by password failed.\n");
  155. goto shutdown;
  156. }
  157. }
  158. else {
  159. /* Or by public key */
  160. while((rc =
  161. libssh2_userauth_publickey_fromfile(session, username,
  162. "/home/username/"
  163. ".ssh/id_rsa.pub",
  164. "/home/username/"
  165. ".ssh/id_rsa",
  166. password)) ==
  167. LIBSSH2_ERROR_EAGAIN);
  168. if(rc) {
  169. fprintf(stderr, "\tAuthentication by public key failed\n");
  170. goto shutdown;
  171. }
  172. }
  173. do {
  174. sftp_session = libssh2_sftp_init(session);
  175. if(!sftp_session) {
  176. if(libssh2_session_last_errno(session) ==
  177. LIBSSH2_ERROR_EAGAIN) {
  178. fprintf(stderr, "non-blocking init\n");
  179. waitsocket(sock, session); /* now we wait */
  180. }
  181. else {
  182. fprintf(stderr, "Unable to init SFTP session\n");
  183. goto shutdown;
  184. }
  185. }
  186. } while(!sftp_session);
  187. /* Request a file via SFTP */
  188. do {
  189. sftp_handle = libssh2_sftp_open(sftp_session, sftppath,
  190. LIBSSH2_FXF_READ, 0);
  191. if(!sftp_handle) {
  192. if(libssh2_session_last_errno(session) != LIBSSH2_ERROR_EAGAIN) {
  193. fprintf(stderr, "Unable to open file with SFTP\n");
  194. goto shutdown;
  195. }
  196. else {
  197. fprintf(stderr, "non-blocking open\n");
  198. waitsocket(sock, session); /* now we wait */
  199. }
  200. }
  201. } while(!sftp_handle);
  202. fprintf(stderr, "libssh2_sftp_open() is done, now receive data!\n");
  203. do {
  204. do {
  205. /* read in a loop until we block */
  206. rc = libssh2_sftp_read(sftp_handle, mem, sizeof(mem));
  207. fprintf(stderr, "libssh2_sftp_read returned %d\n",
  208. rc);
  209. if(rc > 0) {
  210. /* write to stderr */
  211. write(2, mem, rc);
  212. /* write to temporary storage area */
  213. fwrite(mem, rc, 1, tempstorage);
  214. }
  215. } while(rc > 0);
  216. if(rc != LIBSSH2_ERROR_EAGAIN) {
  217. /* error or end of file */
  218. break;
  219. }
  220. timeout.tv_sec = 10;
  221. timeout.tv_usec = 0;
  222. FD_ZERO(&fd);
  223. FD_ZERO(&fd2);
  224. FD_SET(sock, &fd);
  225. FD_SET(sock, &fd2);
  226. /* wait for readable or writeable */
  227. rc = select(sock + 1, &fd, &fd2, NULL, &timeout);
  228. if(rc <= 0) {
  229. /* negative is error
  230. 0 is timeout */
  231. fprintf(stderr, "SFTP download timed out: %d\n", rc);
  232. break;
  233. }
  234. } while(1);
  235. libssh2_sftp_close(sftp_handle);
  236. fclose(tempstorage);
  237. tempstorage = fopen(STORAGE, "rb");
  238. if(!tempstorage) {
  239. /* weird, we can't read the file we just wrote to... */
  240. fprintf(stderr, "can't open %s for reading\n", STORAGE);
  241. goto shutdown;
  242. }
  243. /* we're done downloading, now reverse the process and upload the
  244. temporarily stored data to the destination path */
  245. sftp_handle =
  246. libssh2_sftp_open(sftp_session, dest,
  247. LIBSSH2_FXF_WRITE|LIBSSH2_FXF_CREAT,
  248. LIBSSH2_SFTP_S_IRUSR|LIBSSH2_SFTP_S_IWUSR|
  249. LIBSSH2_SFTP_S_IRGRP|LIBSSH2_SFTP_S_IROTH);
  250. if(sftp_handle) {
  251. size_t nread;
  252. char *ptr;
  253. do {
  254. nread = fread(mem, 1, sizeof(mem), tempstorage);
  255. if(nread <= 0) {
  256. /* end of file */
  257. break;
  258. }
  259. ptr = mem;
  260. do {
  261. /* write data in a loop until we block */
  262. rc = libssh2_sftp_write(sftp_handle, ptr,
  263. nread);
  264. ptr += rc;
  265. nread -= nread;
  266. } while(rc >= 0);
  267. if(rc != LIBSSH2_ERROR_EAGAIN) {
  268. /* error or end of file */
  269. break;
  270. }
  271. timeout.tv_sec = 10;
  272. timeout.tv_usec = 0;
  273. FD_ZERO(&fd);
  274. FD_ZERO(&fd2);
  275. FD_SET(sock, &fd);
  276. FD_SET(sock, &fd2);
  277. /* wait for readable or writeable */
  278. rc = select(sock + 1, &fd, &fd2, NULL, &timeout);
  279. if(rc <= 0) {
  280. /* negative is error
  281. 0 is timeout */
  282. fprintf(stderr, "SFTP upload timed out: %d\n",
  283. rc);
  284. break;
  285. }
  286. } while(1);
  287. fprintf(stderr, "SFTP upload done!\n");
  288. }
  289. else {
  290. fprintf(stderr, "SFTP failed to open destination path: %s\n",
  291. dest);
  292. }
  293. libssh2_sftp_shutdown(sftp_session);
  294. shutdown:
  295. libssh2_session_disconnect(session, "Normal Shutdown");
  296. libssh2_session_free(session);
  297. #ifdef WIN32
  298. closesocket(sock);
  299. #else
  300. close(sock);
  301. #endif
  302. if(tempstorage)
  303. fclose(tempstorage);
  304. fprintf(stderr, "all done\n");
  305. libssh2_exit();
  306. return 0;
  307. }