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.
 
 
 
 

288 lines
7.3 KiB

  1. /*
  2. * Sample showing how to do an SCP non-blocking upload transfer.
  3. */
  4. #include "libssh2_config.h"
  5. #include <libssh2.h>
  6. #ifdef HAVE_WINSOCK2_H
  7. # include <winsock2.h>
  8. #endif
  9. #ifdef HAVE_SYS_SOCKET_H
  10. # include <sys/socket.h>
  11. #endif
  12. #ifdef HAVE_NETINET_IN_H
  13. # include <netinet/in.h>
  14. #endif
  15. #ifdef HAVE_SYS_SELECT_H
  16. # include <sys/select.h>
  17. #endif
  18. # ifdef HAVE_UNISTD_H
  19. #include <unistd.h>
  20. #endif
  21. #ifdef HAVE_ARPA_INET_H
  22. # include <arpa/inet.h>
  23. #endif
  24. #ifdef HAVE_SYS_TIME_H
  25. # include <sys/time.h>
  26. #endif
  27. #include <sys/types.h>
  28. #include <fcntl.h>
  29. #include <errno.h>
  30. #include <stdio.h>
  31. #include <ctype.h>
  32. #include <time.h>
  33. static int waitsocket(int socket_fd, LIBSSH2_SESSION *session)
  34. {
  35. struct timeval timeout;
  36. int rc;
  37. fd_set fd;
  38. fd_set *writefd = NULL;
  39. fd_set *readfd = NULL;
  40. int dir;
  41. timeout.tv_sec = 10;
  42. timeout.tv_usec = 0;
  43. FD_ZERO(&fd);
  44. FD_SET(socket_fd, &fd);
  45. /* now make sure we wait in the correct direction */
  46. dir = libssh2_session_block_directions(session);
  47. if(dir & LIBSSH2_SESSION_BLOCK_INBOUND)
  48. readfd = &fd;
  49. if(dir & LIBSSH2_SESSION_BLOCK_OUTBOUND)
  50. writefd = &fd;
  51. rc = select(socket_fd + 1, readfd, writefd, NULL, &timeout);
  52. return rc;
  53. }
  54. int main(int argc, char *argv[])
  55. {
  56. unsigned long hostaddr;
  57. int sock, i, auth_pw = 1;
  58. struct sockaddr_in sin;
  59. const char *fingerprint;
  60. LIBSSH2_SESSION *session = NULL;
  61. LIBSSH2_CHANNEL *channel;
  62. const char *username = "username";
  63. const char *password = "password";
  64. const char *loclfile = "scp_write.c";
  65. const char *scppath = "/tmp/TEST";
  66. FILE *local;
  67. int rc;
  68. char mem[1024*100];
  69. size_t nread;
  70. char *ptr;
  71. struct stat fileinfo;
  72. time_t start;
  73. long total = 0;
  74. int duration;
  75. size_t prev;
  76. #ifdef WIN32
  77. WSADATA wsadata;
  78. int err;
  79. err = WSAStartup(MAKEWORD(2, 0), &wsadata);
  80. if(err != 0) {
  81. fprintf(stderr, "WSAStartup failed with error: %d\n", err);
  82. return 1;
  83. }
  84. #endif
  85. if(argc > 1) {
  86. hostaddr = inet_addr(argv[1]);
  87. }
  88. else {
  89. hostaddr = htonl(0x7F000001);
  90. }
  91. if(argc > 2) {
  92. username = argv[2];
  93. }
  94. if(argc > 3) {
  95. password = argv[3];
  96. }
  97. if(argc > 4) {
  98. loclfile = argv[4];
  99. }
  100. if(argc > 5) {
  101. scppath = argv[5];
  102. }
  103. rc = libssh2_init(0);
  104. if(rc != 0) {
  105. fprintf(stderr, "libssh2 initialization failed (%d)\n", rc);
  106. return 1;
  107. }
  108. local = fopen(loclfile, "rb");
  109. if(!local) {
  110. fprintf(stderr, "Can't local file %s\n", loclfile);
  111. return -1;
  112. }
  113. stat(loclfile, &fileinfo);
  114. /* Ultra basic "connect to port 22 on localhost"
  115. * Your code is responsible for creating the socket establishing the
  116. * connection
  117. */
  118. sock = socket(AF_INET, SOCK_STREAM, 0);
  119. sin.sin_family = AF_INET;
  120. sin.sin_port = htons(22);
  121. sin.sin_addr.s_addr = hostaddr;
  122. if(connect(sock, (struct sockaddr*)(&sin),
  123. sizeof(struct sockaddr_in)) != 0) {
  124. fprintf(stderr, "failed to connect!\n");
  125. return -1;
  126. }
  127. /* Create a session instance
  128. */
  129. session = libssh2_session_init();
  130. if(!session)
  131. return -1;
  132. /* Since we have set non-blocking, tell libssh2 we are non-blocking */
  133. libssh2_session_set_blocking(session, 0);
  134. /* ... start it up. This will trade welcome banners, exchange keys,
  135. * and setup crypto, compression, and MAC layers
  136. */
  137. while((rc = libssh2_session_handshake(session, sock))
  138. == LIBSSH2_ERROR_EAGAIN);
  139. if(rc) {
  140. fprintf(stderr, "Failure establishing SSH session: %d\n", rc);
  141. return -1;
  142. }
  143. /* At this point we havn't yet authenticated. The first thing to do
  144. * is check the hostkey's fingerprint against our known hosts Your app
  145. * may have it hard coded, may go to a file, may present it to the
  146. * user, that's your call
  147. */
  148. fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_SHA1);
  149. fprintf(stderr, "Fingerprint: ");
  150. for(i = 0; i < 20; i++) {
  151. fprintf(stderr, "%02X ", (unsigned char)fingerprint[i]);
  152. }
  153. fprintf(stderr, "\n");
  154. if(auth_pw) {
  155. /* We could authenticate via password */
  156. while((rc = libssh2_userauth_password(session, username, password)) ==
  157. LIBSSH2_ERROR_EAGAIN);
  158. if(rc) {
  159. fprintf(stderr, "Authentication by password failed.\n");
  160. goto shutdown;
  161. }
  162. }
  163. else {
  164. /* Or by public key */
  165. #define HOME "/home/username/"
  166. while((rc = libssh2_userauth_publickey_fromfile(session, username,
  167. HOME ".ssh/id_rsa.pub",
  168. HOME ".ssh/id_rsa",
  169. password)) ==
  170. LIBSSH2_ERROR_EAGAIN);
  171. if(rc) {
  172. fprintf(stderr, "\tAuthentication by public key failed\n");
  173. goto shutdown;
  174. }
  175. }
  176. /* Send a file via scp. The mode parameter must only have permissions! */
  177. do {
  178. channel = libssh2_scp_send(session, scppath, fileinfo.st_mode & 0777,
  179. (unsigned long)fileinfo.st_size);
  180. if((!channel) && (libssh2_session_last_errno(session) !=
  181. LIBSSH2_ERROR_EAGAIN)) {
  182. char *err_msg;
  183. libssh2_session_last_error(session, &err_msg, NULL, 0);
  184. fprintf(stderr, "%s\n", err_msg);
  185. goto shutdown;
  186. }
  187. } while(!channel);
  188. fprintf(stderr, "SCP session waiting to send file\n");
  189. start = time(NULL);
  190. do {
  191. nread = fread(mem, 1, sizeof(mem), local);
  192. if(nread <= 0) {
  193. /* end of file */
  194. break;
  195. }
  196. ptr = mem;
  197. total += nread;
  198. prev = 0;
  199. do {
  200. while((rc = libssh2_channel_write(channel, ptr, nread)) ==
  201. LIBSSH2_ERROR_EAGAIN) {
  202. waitsocket(sock, session);
  203. prev = 0;
  204. }
  205. if(rc < 0) {
  206. fprintf(stderr, "ERROR %d total %ld / %d prev %d\n", rc,
  207. total, (int)nread, (int)prev);
  208. break;
  209. }
  210. else {
  211. prev = nread;
  212. /* rc indicates how many bytes were written this time */
  213. nread -= rc;
  214. ptr += rc;
  215. }
  216. } while(nread);
  217. } while(!nread); /* only continue if nread was drained */
  218. duration = (int)(time(NULL)-start);
  219. fprintf(stderr, "%ld bytes in %d seconds makes %.1f bytes/sec\n",
  220. total, duration, total/(double)duration);
  221. fprintf(stderr, "Sending EOF\n");
  222. while(libssh2_channel_send_eof(channel) == LIBSSH2_ERROR_EAGAIN);
  223. fprintf(stderr, "Waiting for EOF\n");
  224. while(libssh2_channel_wait_eof(channel) == LIBSSH2_ERROR_EAGAIN);
  225. fprintf(stderr, "Waiting for channel to close\n");
  226. while(libssh2_channel_wait_closed(channel) == LIBSSH2_ERROR_EAGAIN);
  227. libssh2_channel_free(channel);
  228. channel = NULL;
  229. shutdown:
  230. while(libssh2_session_disconnect(session,
  231. "Normal Shutdown,") ==
  232. LIBSSH2_ERROR_EAGAIN);
  233. libssh2_session_free(session);
  234. #ifdef WIN32
  235. closesocket(sock);
  236. #else
  237. close(sock);
  238. #endif
  239. fprintf(stderr, "all done\n");
  240. libssh2_exit();
  241. return 0;
  242. }