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