1 /*
2  * Sample showing how to do SFTP write transfers.
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 192.168.0.1 user password sftp_write.c /tmp/secrets"
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     char mem[1024*100];
52     size_t nread;
53     char *ptr;
54 
55 #ifdef WIN32
56     WSADATA wsadata;
57     int err;
58 
59     err = WSAStartup(MAKEWORD(2, 0), &wsadata);
60     if(err != 0) {
61         fprintf(stderr, "WSAStartup failed with error: %d\n", err);
62         return 1;
63     }
64 #endif
65 
66     if(argc > 1) {
67         hostaddr = inet_addr(argv[1]);
68     }
69     else {
70         hostaddr = htonl(0x7F000001);
71     }
72 
73     if(argc > 2) {
74         username = argv[2];
75     }
76     if(argc > 3) {
77         password = argv[3];
78     }
79     if(argc > 4) {
80         loclfile = argv[4];
81     }
82     if(argc > 5) {
83         sftppath = argv[5];
84     }
85 
86     rc = libssh2_init(0);
87     if(rc != 0) {
88         fprintf(stderr, "libssh2 initialization failed (%d)\n", rc);
89         return 1;
90     }
91 
92     local = fopen(loclfile, "rb");
93     if(!local) {
94         fprintf(stderr, "Can't open local file %s\n", loclfile);
95         return -1;
96     }
97 
98     /*
99      * The application code is responsible for creating the socket
100      * and establishing the connection
101      */
102     sock = socket(AF_INET, SOCK_STREAM, 0);
103 
104     sin.sin_family = AF_INET;
105     sin.sin_port = htons(22);
106     sin.sin_addr.s_addr = hostaddr;
107     if(connect(sock, (struct sockaddr*)(&sin),
108             sizeof(struct sockaddr_in)) != 0) {
109         fprintf(stderr, "failed to connect!\n");
110         return -1;
111     }
112 
113     /* Create a session instance
114      */
115     session = libssh2_session_init();
116     if(!session)
117         return -1;
118 
119     /* Since we have set non-blocking, tell libssh2 we are blocking */
120     libssh2_session_set_blocking(session, 1);
121 
122     /* ... start it up. This will trade welcome banners, exchange keys,
123      * and setup crypto, compression, and MAC layers
124      */
125     rc = libssh2_session_handshake(session, sock);
126     if(rc) {
127         fprintf(stderr, "Failure establishing SSH session: %d\n", rc);
128         return -1;
129     }
130 
131     /* At this point we havn't yet authenticated.  The first thing to do
132      * is check the hostkey's fingerprint against our known hosts Your app
133      * may have it hard coded, may go to a file, may present it to the
134      * user, that's your call
135      */
136     fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_SHA1);
137     fprintf(stderr, "Fingerprint: ");
138     for(i = 0; i < 20; i++) {
139         fprintf(stderr, "%02X ", (unsigned char)fingerprint[i]);
140     }
141     fprintf(stderr, "\n");
142 
143     if(auth_pw) {
144         /* We could authenticate via password */
145         if(libssh2_userauth_password(session, username, password)) {
146             fprintf(stderr, "Authentication by password failed.\n");
147             goto shutdown;
148         }
149     }
150     else {
151         /* Or by public key */
152         const char *pubkey = "/home/username/.ssh/id_rsa.pub";
153         const char *privkey = "/home/username/.ssh/id_rsa.pub";
154         if(libssh2_userauth_publickey_fromfile(session, username,
155                                                pubkey, privkey,
156                                                password)) {
157             fprintf(stderr, "\tAuthentication by public key failed\n");
158             goto shutdown;
159         }
160     }
161 
162     fprintf(stderr, "libssh2_sftp_init()!\n");
163     sftp_session = libssh2_sftp_init(session);
164 
165     if(!sftp_session) {
166         fprintf(stderr, "Unable to init SFTP session\n");
167         goto shutdown;
168     }
169 
170     fprintf(stderr, "libssh2_sftp_open()!\n");
171     /* Request a file via SFTP */
172     sftp_handle =
173         libssh2_sftp_open(sftp_session, sftppath,
174                       LIBSSH2_FXF_WRITE|LIBSSH2_FXF_CREAT|LIBSSH2_FXF_TRUNC,
175                       LIBSSH2_SFTP_S_IRUSR|LIBSSH2_SFTP_S_IWUSR|
176                       LIBSSH2_SFTP_S_IRGRP|LIBSSH2_SFTP_S_IROTH);
177 
178     if(!sftp_handle) {
179         fprintf(stderr, "Unable to open file with SFTP\n");
180         goto shutdown;
181     }
182     fprintf(stderr, "libssh2_sftp_open() is done, now send data!\n");
183     do {
184         nread = fread(mem, 1, sizeof(mem), local);
185         if(nread <= 0) {
186             /* end of file */
187             break;
188         }
189         ptr = mem;
190 
191         do {
192             /* write data in a loop until we block */
193             rc = libssh2_sftp_write(sftp_handle, ptr, nread);
194             if(rc < 0)
195                 break;
196             ptr += rc;
197             nread -= rc;
198         } while(nread);
199 
200     } while(rc > 0);
201 
202     libssh2_sftp_close(sftp_handle);
203     libssh2_sftp_shutdown(sftp_session);
204 
205 shutdown:
206     libssh2_session_disconnect(session,
207                                "Normal Shutdown, Thank you for playing");
208     libssh2_session_free(session);
209 
210 #ifdef WIN32
211     closesocket(sock);
212 #else
213     close(sock);
214 #endif
215     if(local)
216         fclose(local);
217     fprintf(stderr, "all done\n");
218 
219     libssh2_exit();
220 
221     return 0;
222 }
223