1 /*
2  * Sample doing an SFTP directory listing.
3  *
4  * The sample code has default values for host name, user name, password and
5  * path, but you can specify them on the command line like:
6  *
7  * "sftpdir 192.168.0.1 user password /tmp/secretdir"
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 #ifdef HAVE_INTTYPES_H
30 # include <inttypes.h>
31 #endif
32 
33 #include <sys/types.h>
34 #include <fcntl.h>
35 #include <errno.h>
36 #include <stdio.h>
37 #include <ctype.h>
38 
39 #ifdef WIN32
40 #define __FILESIZE "I64"
41 #else
42 #define __FILESIZE "llu"
43 #endif
44 
main(int argc,char * argv[])45 int main(int argc, char *argv[])
46 {
47     unsigned long hostaddr;
48     int sock, i, auth_pw = 1;
49     struct sockaddr_in sin;
50     const char *fingerprint;
51     LIBSSH2_SESSION *session;
52     const char *username = "username";
53     const char *password = "password";
54     const char *sftppath = "/tmp/secretdir";
55     const char *pubkey = "/home/username/.ssh/id_rsa.pub";
56     const char *privkey = "/home/username/.ssh/id_rsa";
57     int rc;
58     LIBSSH2_SFTP *sftp_session;
59     LIBSSH2_SFTP_HANDLE *sftp_handle;
60 
61 #ifdef WIN32
62     WSADATA wsadata;
63     int err;
64 
65     err = WSAStartup(MAKEWORD(2, 0), &wsadata);
66     if(err != 0) {
67         fprintf(stderr, "WSAStartup failed with error: %d\n", err);
68         return 1;
69     }
70 #endif
71 
72     if(argc > 1) {
73         hostaddr = inet_addr(argv[1]);
74     }
75     else {
76         hostaddr = htonl(0x7F000001);
77     }
78 
79     if(argc > 2) {
80         username = argv[2];
81     }
82     if(argc > 3) {
83         password = argv[3];
84     }
85     if(argc > 4) {
86         sftppath = argv[4];
87     }
88 
89     rc = libssh2_init(0);
90     if(rc != 0) {
91         fprintf(stderr, "libssh2 initialization failed (%d)\n", rc);
92         return 1;
93     }
94 
95     /*
96      * The application code is responsible for creating the socket
97      * and establishing the connection
98      */
99     sock = socket(AF_INET, SOCK_STREAM, 0);
100 
101     sin.sin_family = AF_INET;
102     sin.sin_port = htons(22);
103     sin.sin_addr.s_addr = hostaddr;
104     if(connect(sock, (struct sockaddr*)(&sin),
105                sizeof(struct sockaddr_in)) != 0) {
106         fprintf(stderr, "failed to connect!\n");
107         return -1;
108     }
109 
110     /* Create a session instance
111      */
112     session = libssh2_session_init();
113     if(!session)
114         return -1;
115 
116     /* Since we have set non-blocking, tell libssh2 we are non-blocking */
117     libssh2_session_set_blocking(session, 0);
118 
119     /* ... start it up. This will trade welcome banners, exchange keys,
120      * and setup crypto, compression, and MAC layers
121      */
122     while((rc = libssh2_session_handshake(session, sock)) ==
123           LIBSSH2_ERROR_EAGAIN);
124     if(rc) {
125         fprintf(stderr, "Failure establishing SSH session: %d\n", rc);
126         return -1;
127     }
128 
129     /* At this point we havn't yet authenticated.  The first thing to do
130      * is check the hostkey's fingerprint against our known hosts Your app
131      * may have it hard coded, may go to a file, may present it to the
132      * user, that's your call
133      */
134     fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_SHA1);
135     fprintf(stderr, "Fingerprint: ");
136     for(i = 0; i < 20; i++) {
137         fprintf(stderr, "%02X ", (unsigned char)fingerprint[i]);
138     }
139     fprintf(stderr, "\n");
140 
141     if(auth_pw) {
142         /* We could authenticate via password */
143         while((rc = libssh2_userauth_password(session, username, password)) ==
144               LIBSSH2_ERROR_EAGAIN);
145         if(rc) {
146             fprintf(stderr, "Authentication by password failed.\n");
147             goto shutdown;
148         }
149     }
150     else {
151         /* Or by public key */
152         while((rc = libssh2_userauth_publickey_fromfile(session, username,
153                                                         pubkey, privkey,
154                                                         password)) ==
155               LIBSSH2_ERROR_EAGAIN);
156         if(rc) {
157             fprintf(stderr, "\tAuthentication by public key failed\n");
158             goto shutdown;
159         }
160     }
161 
162     fprintf(stderr, "libssh2_sftp_init()!\n");
163     do {
164         sftp_session = libssh2_sftp_init(session);
165 
166         if((!sftp_session) && (libssh2_session_last_errno(session) !=
167                                LIBSSH2_ERROR_EAGAIN)) {
168             fprintf(stderr, "Unable to init SFTP session\n");
169             goto shutdown;
170         }
171     } while(!sftp_session);
172 
173     fprintf(stderr, "libssh2_sftp_opendir()!\n");
174     /* Request a dir listing via SFTP */
175     do {
176         sftp_handle = libssh2_sftp_opendir(sftp_session, sftppath);
177 
178         if((!sftp_handle) && (libssh2_session_last_errno(session) !=
179                               LIBSSH2_ERROR_EAGAIN)) {
180             fprintf(stderr, "Unable to open dir with SFTP\n");
181             goto shutdown;
182         }
183     } while(!sftp_handle);
184 
185     fprintf(stderr, "libssh2_sftp_opendir() is done, now receive listing!\n");
186     do {
187         char mem[512];
188         LIBSSH2_SFTP_ATTRIBUTES attrs;
189 
190         /* loop until we fail */
191         while((rc = libssh2_sftp_readdir(sftp_handle, mem, sizeof(mem),
192                                          &attrs)) == LIBSSH2_ERROR_EAGAIN) {
193             ;
194         }
195         if(rc > 0) {
196             /* rc is the length of the file name in the mem
197                buffer */
198 
199             if(attrs.flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) {
200                 /* this should check what permissions it
201                    is and print the output accordingly */
202                 printf("--fix----- ");
203             }
204             else {
205                 printf("---------- ");
206             }
207 
208             if(attrs.flags & LIBSSH2_SFTP_ATTR_UIDGID) {
209                 printf("%4d %4d ", (int) attrs.uid, (int) attrs.gid);
210             }
211             else {
212                 printf("   -    - ");
213             }
214 
215             if(attrs.flags & LIBSSH2_SFTP_ATTR_SIZE) {
216                 printf("%8" __FILESIZE " ", attrs.filesize);
217             }
218 
219             printf("%s\n", mem);
220         }
221         else if(rc == LIBSSH2_ERROR_EAGAIN) {
222             /* blocking */
223             fprintf(stderr, "Blocking\n");
224         }
225         else {
226             break;
227         }
228 
229     } while(1);
230 
231     libssh2_sftp_closedir(sftp_handle);
232     libssh2_sftp_shutdown(sftp_session);
233 
234   shutdown:
235 
236     libssh2_session_disconnect(session, "Normal Shutdown");
237     libssh2_session_free(session);
238 
239 #ifdef WIN32
240     closesocket(sock);
241 #else
242     close(sock);
243 #endif
244     fprintf(stderr, "all done\n");
245 
246     libssh2_exit();
247 
248     return 0;
249 }
250