1 /*
2 * Sample showing how to do SFTP append of a local file onto a remote one.
3 *
4 * The sample code has default values for host name, user name, password
5 * and path to copy, but you can specify them on the command line like:
6 *
7 * sftp_append 192.168.0.1 user password localfile /tmp/remotefile
8 */
9
10 #include "libssh2_config.h"
11 #include <libssh2.h>
12 #include <libssh2_sftp.h>
13
14 #ifdef HAVE_WINSOCK2_H
15 # include <winsock2.h>
16 #endif
17 #ifdef HAVE_SYS_SOCKET_H
18 # include <sys/socket.h>
19 #endif
20 #ifdef HAVE_NETINET_IN_H
21 # include <netinet/in.h>
22 #endif
23 # ifdef HAVE_UNISTD_H
24 #include <unistd.h>
25 #endif
26 #ifdef HAVE_ARPA_INET_H
27 # include <arpa/inet.h>
28 #endif
29
30 #include <sys/types.h>
31 #include <fcntl.h>
32 #include <errno.h>
33 #include <stdio.h>
34 #include <ctype.h>
35
main(int argc,char * argv[])36 int main(int argc, char *argv[])
37 {
38 unsigned long hostaddr;
39 int sock, i, auth_pw = 1;
40 struct sockaddr_in sin;
41 const char *fingerprint;
42 LIBSSH2_SESSION *session;
43 const char *username = "username";
44 const char *password = "password";
45 const char *loclfile = "sftp_write.c";
46 const char *sftppath = "/tmp/TEST";
47 int rc;
48 FILE *local;
49 LIBSSH2_SFTP *sftp_session;
50 LIBSSH2_SFTP_HANDLE *sftp_handle;
51 LIBSSH2_SFTP_ATTRIBUTES attrs;
52 char mem[1024*100];
53 size_t nread;
54 char *ptr;
55
56 #ifdef WIN32
57 WSADATA wsadata;
58 int err;
59
60 err = WSAStartup(MAKEWORD(2, 0), &wsadata);
61 if(err) {
62 fprintf(stderr, "WSAStartup failed with error: %d\n", err);
63 return 1;
64 }
65 #endif
66
67 if(argc > 1) {
68 hostaddr = inet_addr(argv[1]);
69 }
70 else {
71 hostaddr = htonl(0x7F000001);
72 }
73
74 if(argc > 2) {
75 username = argv[2];
76 }
77 if(argc > 3) {
78 password = argv[3];
79 }
80 if(argc > 4) {
81 loclfile = argv[4];
82 }
83 if(argc > 5) {
84 sftppath = argv[5];
85 }
86
87 rc = libssh2_init(0);
88 if(rc) {
89 fprintf(stderr, "libssh2 initialization failed (%d)\n", rc);
90 return 1;
91 }
92
93 local = fopen(loclfile, "rb");
94 if(!local) {
95 fprintf(stderr, "Can't open local file %s\n", loclfile);
96 return -1;
97 }
98
99 /*
100 * The application code is responsible for creating the socket
101 * and establishing the connection
102 */
103 sock = socket(AF_INET, SOCK_STREAM, 0);
104
105 sin.sin_family = AF_INET;
106 sin.sin_port = htons(22);
107 sin.sin_addr.s_addr = hostaddr;
108 if(connect(sock, (struct sockaddr*)(&sin),
109 sizeof(struct sockaddr_in)) != 0) {
110 fprintf(stderr, "failed to connect!\n");
111 return -1;
112 }
113
114 /* Create a session instance
115 */
116 session = libssh2_session_init();
117 if(!session)
118 return -1;
119
120 /* Since we have set non-blocking, tell libssh2 we are blocking */
121 libssh2_session_set_blocking(session, 1);
122
123 /* ... start it up. This will trade welcome banners, exchange keys,
124 * and setup crypto, compression, and MAC layers
125 */
126 rc = libssh2_session_handshake(session, sock);
127 if(rc) {
128 fprintf(stderr, "Failure establishing SSH session: %d\n", rc);
129 return -1;
130 }
131
132 /* At this point we havn't yet authenticated. The first thing to do
133 * is check the hostkey's fingerprint against our known hosts Your app
134 * may have it hard coded, may go to a file, may present it to the
135 * user, that's your call
136 */
137 fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_SHA1);
138 fprintf(stderr, "Fingerprint: ");
139 for(i = 0; i < 20; i++) {
140 fprintf(stderr, "%02X ", (unsigned char)fingerprint[i]);
141 }
142 fprintf(stderr, "\n");
143
144 if(auth_pw) {
145 /* We could authenticate via password */
146 if(libssh2_userauth_password(session, username, password)) {
147 fprintf(stderr, "Authentication by password failed.\n");
148 goto shutdown;
149 }
150 }
151 else {
152 /* Or by public key */
153 #define HOME "/home/username/"
154 if(libssh2_userauth_publickey_fromfile(session, username,
155 HOME ".ssh/id_rsa.pub",
156 HOME ".ssh/id_rsa",
157 password)) {
158 fprintf(stderr, "\tAuthentication by public key failed\n");
159 goto shutdown;
160 }
161 }
162
163 fprintf(stderr, "libssh2_sftp_init()!\n");
164 sftp_session = libssh2_sftp_init(session);
165
166 if(!sftp_session) {
167 fprintf(stderr, "Unable to init SFTP session\n");
168 goto shutdown;
169 }
170
171 fprintf(stderr, "libssh2_sftp_open() for READ and WRITE!\n");
172 /* Request a file via SFTP */
173
174 sftp_handle =
175 libssh2_sftp_open(sftp_session, sftppath,
176 LIBSSH2_FXF_WRITE|LIBSSH2_FXF_READ,
177 LIBSSH2_SFTP_S_IRUSR|LIBSSH2_SFTP_S_IWUSR|
178 LIBSSH2_SFTP_S_IRGRP|LIBSSH2_SFTP_S_IROTH);
179 if(!sftp_handle) {
180 fprintf(stderr, "Unable to open file with SFTP\n");
181 goto shutdown;
182 }
183
184 if(libssh2_sftp_fstat_ex(sftp_handle, &attrs, 0) < 0) {
185 fprintf(stderr, "libssh2_sftp_fstat_ex failed\n");
186 goto shutdown;
187 }
188 else
189 libssh2_sftp_seek64(sftp_handle, attrs.filesize);
190 fprintf(stderr, "Did a seek to position %ld\n", (long) attrs.filesize);
191
192 fprintf(stderr, "libssh2_sftp_open() a handle for APPEND\n");
193
194 if(!sftp_handle) {
195 fprintf(stderr, "Unable to open file with SFTP\n");
196 goto shutdown;
197 }
198 fprintf(stderr, "libssh2_sftp_open() is done, now send data!\n");
199 do {
200 nread = fread(mem, 1, sizeof(mem), local);
201 if(nread <= 0) {
202 /* end of file */
203 break;
204 }
205 ptr = mem;
206
207 do {
208 /* write data in a loop until we block */
209 rc = libssh2_sftp_write(sftp_handle, ptr, nread);
210 if(rc < 0)
211 break;
212 ptr += rc;
213 nread -= rc;
214 } while(nread);
215
216 } while(rc > 0);
217
218 libssh2_sftp_close(sftp_handle);
219 libssh2_sftp_shutdown(sftp_session);
220
221 shutdown:
222 libssh2_session_disconnect(session,
223 "Normal Shutdown, Thank you for playing");
224 libssh2_session_free(session);
225
226 #ifdef WIN32
227 closesocket(sock);
228 #else
229 close(sock);
230 #endif
231 if(local)
232 fclose(local);
233 fprintf(stderr, "all done\n");
234
235 libssh2_exit();
236
237 return 0;
238 }
239