1 /*
2  * Sample showing how to do SFTP non-blocking mkdir.
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 /tmp/sftp_write_nonblock.c"
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 *sftppath = "/tmp/sftp_mkdir_nonblock";
46     int rc;
47     LIBSSH2_SFTP *sftp_session;
48 
49 #ifdef WIN32
50     WSADATA wsadata;
51     int err;
52 
53     err = WSAStartup(MAKEWORD(2, 0), &wsadata);
54     if(err != 0) {
55         fprintf(stderr, "WSAStartup failed with error: %d\n", err);
56         return 1;
57     }
58 #endif
59 
60     if(argc > 1) {
61         hostaddr = inet_addr(argv[1]);
62     }
63     else {
64         hostaddr = htonl(0x7F000001);
65     }
66 
67     if(argc > 2) {
68         username = argv[2];
69     }
70     if(argc > 3) {
71         password = argv[3];
72     }
73     if(argc > 4) {
74         sftppath = argv[4];
75     }
76 
77     rc = libssh2_init(0);
78     if(rc != 0) {
79         fprintf(stderr, "libssh2 initialization failed (%d)\n", rc);
80         return 1;
81     }
82 
83     /*
84      * The application code is responsible for creating the socket
85      * and establishing the connection
86      */
87     sock = socket(AF_INET, SOCK_STREAM, 0);
88 
89     sin.sin_family = AF_INET;
90     sin.sin_port = htons(22);
91     sin.sin_addr.s_addr = hostaddr;
92     if(connect(sock, (struct sockaddr*)(&sin),
93             sizeof(struct sockaddr_in)) != 0) {
94         fprintf(stderr, "failed to connect!\n");
95         return -1;
96     }
97 
98     /* Create a session instance
99      */
100     session = libssh2_session_init();
101     if(!session)
102         return -1;
103 
104     /* ... start it up. This will trade welcome banners, exchange keys,
105      * and setup crypto, compression, and MAC layers
106      */
107     rc = libssh2_session_handshake(session, sock);
108     if(rc) {
109         fprintf(stderr, "Failure establishing SSH session: %d\n", rc);
110         return -1;
111     }
112 
113     /* At this point we havn't yet authenticated.  The first thing to do
114      * is check the hostkey's fingerprint against our known hosts Your app
115      * may have it hard coded, may go to a file, may present it to the
116      * user, that's your call
117      */
118     fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_SHA1);
119     fprintf(stderr, "Fingerprint: ");
120     for(i = 0; i < 20; i++) {
121         fprintf(stderr, "%02X ", (unsigned char)fingerprint[i]);
122     }
123     fprintf(stderr, "\n");
124 
125     if(auth_pw) {
126         /* We could authenticate via password */
127         if(libssh2_userauth_password(session, username, password)) {
128             fprintf(stderr, "Authentication by password failed.\n");
129             goto shutdown;
130         }
131     }
132     else {
133         /* Or by public key */
134         if(libssh2_userauth_publickey_fromfile(session, username,
135                             "/home/username/.ssh/id_rsa.pub",
136                             "/home/username/.ssh/id_rsa",
137                             password)) {
138             fprintf(stderr, "\tAuthentication by public key failed\n");
139             goto shutdown;
140         }
141     }
142 
143     fprintf(stderr, "libssh2_sftp_init()!\n");
144     sftp_session = libssh2_sftp_init(session);
145 
146     if(!sftp_session) {
147         fprintf(stderr, "Unable to init SFTP session\n");
148         goto shutdown;
149     }
150 
151     /* Since we have set non-blocking, tell libssh2 we are non-blocking */
152     libssh2_session_set_blocking(session, 0);
153 
154     fprintf(stderr, "libssh2_sftp_mkdirnb()!\n");
155     /* Make a directory via SFTP */
156     while(libssh2_sftp_mkdir(sftp_session, sftppath,
157                               LIBSSH2_SFTP_S_IRWXU|
158                               LIBSSH2_SFTP_S_IRGRP|LIBSSH2_SFTP_S_IXGRP|
159                               LIBSSH2_SFTP_S_IROTH|LIBSSH2_SFTP_S_IXOTH)
160            == LIBSSH2_ERROR_EAGAIN);
161 
162     libssh2_sftp_shutdown(sftp_session);
163 
164  shutdown:
165 
166     libssh2_session_disconnect(session, "Normal Shutdown");
167     libssh2_session_free(session);
168 
169 #ifdef WIN32
170     closesocket(sock);
171 #else
172     close(sock);
173 #endif
174     fprintf(stderr, "all done\n");
175 
176     libssh2_exit();
177 
178     return 0;
179 }
180