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