1 /*
2
3 sftp_client.c
4
5 Author: Pekka Riikonen <priikone@silcnet.org>
6
7 Copyright (C) 2001 - 2007 Pekka Riikonen
8
9 The contents of this file are subject to one of the Licenses specified
10 in the COPYING file; You may not use this file except in compliance
11 with the License.
12
13 The software distributed under the License is distributed on an "AS IS"
14 basis, in the hope that it will be useful, but WITHOUT WARRANTY OF ANY
15 KIND, either expressed or implied. See the COPYING file for more
16 information.
17
18 */
19
20 /* Tests:
21 silc_sftp_client_start();
22 silc_sftp_client_receive_process();
23 silc_sftp_opendir();
24 silc_sftp_readdir();
25 silc_sftp_open();
26 silc_sftp_read();
27 silc_sftp_fstat();
28 silc_sftp_lstat();
29 silc_sftp_close();
30 */
31
32 #include "silc.h"
33 #include "silcsftp.h"
34
35 typedef struct {
36 SilcSchedule schedule;
37 SilcStream stream;
38 SilcSFTP sftp;
39 } *Client;
40
41 Client gclient;
42
43 char *dir;
44 char *file;
45 bool opendir;
46 SilcUInt64 offset;
47 bool success = FALSE;
48
49 static void sftp_name(SilcSFTP sftp, SilcSFTPStatus status,
50 const SilcSFTPName name, void *context);
51 static void sftp_handle(SilcSFTP sftp, SilcSFTPStatus status,
52 SilcSFTPHandle handle, void *context);
53 static void sftp_data(SilcSFTP sftp, SilcSFTPStatus status,
54 const unsigned char *data, SilcUInt32 data_len,
55 void *context);
56 static void end_test(void);
57
sftp_status(SilcSFTP sftp,SilcSFTPStatus status,const char * message,const char * lang_tag,void * context)58 static void sftp_status(SilcSFTP sftp, SilcSFTPStatus status,
59 const char *message, const char *lang_tag,
60 void *context)
61 {
62 fprintf(stderr, "Status %d\n", status);
63 if (status != SILC_SFTP_STATUS_OK) {
64 SILC_LOG_DEBUG(("Error status"));
65 success = FALSE;
66 end_test();
67 return;
68 }
69
70 success = TRUE;
71 end_test();
72 }
73
sftp_attr(SilcSFTP sftp,SilcSFTPStatus status,const SilcSFTPAttributes attrs,void * context)74 static void sftp_attr(SilcSFTP sftp, SilcSFTPStatus status,
75 const SilcSFTPAttributes attrs, void *context)
76 {
77 SilcSFTPHandle handle = (SilcSFTPHandle)context;
78 int i;
79
80 fprintf(stderr, "Status %d\n", status);
81 if (status != SILC_SFTP_STATUS_OK) {
82 SILC_LOG_DEBUG(("Error status"));
83 success = FALSE;
84 end_test();
85 return;
86 }
87
88
89 SILC_LOG_DEBUG(("Attr.flags: %d", attrs->flags));
90 SILC_LOG_DEBUG(("Attr.size: %lu", attrs->size));
91 SILC_LOG_DEBUG(("Attr.uid: %d", attrs->uid));
92 SILC_LOG_DEBUG(("Attr.gid: %d", attrs->gid));
93 SILC_LOG_DEBUG(("Attr.permissions: %d", attrs->permissions));
94 SILC_LOG_DEBUG(("Attr.atime: %d", attrs->atime));
95 SILC_LOG_DEBUG(("Attr.mtime: %d", attrs->mtime));
96 SILC_LOG_DEBUG(("Attr.extended count: %d", attrs->extended_count));
97 for (i = 0; i < attrs->extended_count; i++) {
98 SILC_LOG_HEXDUMP(("Attr.extended_type[i]:", i),
99 attrs->extended_type[i]->data,
100 silc_buffer_len(attrs->extended_type[i]));
101 SILC_LOG_HEXDUMP(("Attr.extended_data[i]:", i),
102 attrs->extended_data[i]->data,
103 silc_buffer_len(attrs->extended_data[i]));
104 }
105
106 if (!file) {
107 fprintf(stderr, "Closing file\n");
108 silc_sftp_close(sftp, handle, sftp_status, context);
109 return;
110 }
111
112 fprintf(stderr, "LStatting file %s\n", file);
113 silc_sftp_lstat(sftp, file, sftp_attr, context);
114 file = NULL;
115 }
116
sftp_data(SilcSFTP sftp,SilcSFTPStatus status,const unsigned char * data,SilcUInt32 data_len,void * context)117 static void sftp_data(SilcSFTP sftp, SilcSFTPStatus status,
118 const unsigned char *data, SilcUInt32 data_len,
119 void *context)
120 {
121 SilcSFTPHandle handle = (SilcSFTPHandle)context;
122
123 if (status != SILC_SFTP_STATUS_OK) {
124 SilcSFTPAttributesStruct attrs;
125
126 fprintf(stderr, "Status %d\n", status);
127
128 if (status != SILC_SFTP_STATUS_EOF) {
129 SILC_LOG_DEBUG(("Error status"));
130 success = FALSE;
131 end_test();
132 return;
133 }
134
135 if (!strcmp(file, "/sftp/sftp_server.c")) {
136 fprintf(stderr, "FStatting file handle %s\n", file);
137 silc_sftp_fstat(sftp, handle, sftp_attr, context);
138 return;
139 }
140
141 /* Open another file */
142 opendir = FALSE;
143 memset(&attrs, 0, sizeof(attrs));
144 file = "/sftp/sftp_server.c";
145 fprintf(stderr, "Opening file %s\n", file);
146 offset = 0;
147 silc_sftp_open(sftp, file, SILC_SFTP_FXF_READ,
148 &attrs, sftp_handle, gclient);
149 return;
150 }
151
152 SILC_LOG_HEXDUMP(("data"), (unsigned char *)data, data_len);
153
154 offset += data_len;
155
156 /* Attempt to read more */
157 fprintf(stderr, "Reading more of file %s\n", file);
158 silc_sftp_read(sftp, handle, offset, 2048, sftp_data, handle);
159 }
160
sftp_name(SilcSFTP sftp,SilcSFTPStatus status,const SilcSFTPName name,void * context)161 static void sftp_name(SilcSFTP sftp, SilcSFTPStatus status,
162 const SilcSFTPName name, void *context)
163 {
164 Client client = (Client)context;
165 int i;
166
167 SILC_LOG_DEBUG(("Name"));
168 fprintf(stderr, "Status %d\n", status);
169
170 if (status != SILC_SFTP_STATUS_OK) {
171 SILC_LOG_DEBUG(("Error status"));
172 success = FALSE;
173 end_test();
174 return;
175 }
176
177 fprintf(stderr, "Directory: %s\n", dir);
178 for (i = 0; i < name->count; i++) {
179 fprintf(stderr, "%s\n", name->long_filename[i]);
180 }
181
182 if (!strcmp(dir, "sftp")) {
183 SilcSFTPAttributesStruct attrs;
184
185 /* open */
186 opendir = FALSE;
187 memset(&attrs, 0, sizeof(attrs));
188 file = "passwd";
189 fprintf(stderr, "Opening file %s\n", file);
190 offset = 0;
191 silc_sftp_open(sftp, file, SILC_SFTP_FXF_READ,
192 &attrs, sftp_handle, client);
193 return;
194 }
195
196 if (!strcmp(dir, "/"))
197 dir = "sftp";
198
199 fprintf(stderr, "Opening %s\n", dir);
200
201 /* opendir */
202 opendir = TRUE;
203 silc_sftp_opendir(sftp, dir, sftp_handle, client);
204 }
205
sftp_handle(SilcSFTP sftp,SilcSFTPStatus status,SilcSFTPHandle handle,void * context)206 static void sftp_handle(SilcSFTP sftp, SilcSFTPStatus status,
207 SilcSFTPHandle handle, void *context)
208 {
209 Client client = (Client)context;
210
211 SILC_LOG_DEBUG(("Handle"));
212 fprintf(stderr, "Status %d\n", status);
213 if (status != SILC_SFTP_STATUS_OK) {
214 SILC_LOG_DEBUG(("Error status"));
215 success = FALSE;
216 end_test();
217 return;
218 }
219
220 if (opendir) {
221 fprintf(stderr, "Reading %s\n", dir);
222 /* Readdir */
223 silc_sftp_readdir(sftp, handle, sftp_name, client);
224 } else {
225 fprintf(stderr, "Reading file %s\n", file);
226
227 /* Read */
228 silc_sftp_read(sftp, handle, 0, 2048, sftp_data, handle);
229 }
230 }
231
sftp_version(SilcSFTP sftp,SilcSFTPStatus status,SilcSFTPVersion version,void * context)232 static void sftp_version(SilcSFTP sftp, SilcSFTPStatus status,
233 SilcSFTPVersion version, void *context)
234 {
235 Client client = (Client)context;
236 fprintf(stderr, "Version: %d\n", (int)version);
237
238 SILC_LOG_DEBUG(("Version"));
239 fprintf(stderr, "Status %d\n", status);
240 if (status != SILC_SFTP_STATUS_OK) {
241 SILC_LOG_DEBUG(("Error status"));
242 success = FALSE;
243 end_test();
244 return;
245 }
246
247 /* opendir */
248 dir = "/";
249 fprintf(stderr, "Opening %s\n", dir);
250 opendir = TRUE;
251 silc_sftp_opendir(sftp, dir, sftp_handle, client);
252 }
253
sftp_error(SilcSFTP sftp,SilcSFTPStatus status,void * context)254 static void sftp_error(SilcSFTP sftp, SilcSFTPStatus status,
255 void *context)
256 {
257 Client client = context;
258 SILC_LOG_DEBUG(("Error %d", status));
259 silc_stream_destroy(client->stream);
260 success = FALSE;
261 end_test();
262 }
263
connect_callback(SilcNetStatus status,SilcStream stream,void * context)264 static void connect_callback(SilcNetStatus status, SilcStream stream,
265 void *context)
266 {
267 Client client = context;
268
269 if (!stream) {
270 SILC_LOG_DEBUG(("Connect error"));
271 success = FALSE;
272 end_test();
273 }
274
275 /* Start SFTP session */
276 client->stream = stream;
277 client->sftp = silc_sftp_client_start(stream, client->schedule, sftp_version,
278 sftp_error, client);
279 if (!client->sftp) {
280 success = FALSE;
281 end_test();
282 }
283 }
284
main(int argc,char ** argv)285 int main(int argc, char **argv)
286 {
287 Client client = silc_calloc(1, sizeof(*client));
288
289 gclient = client;
290
291 if (argc > 1) {
292 if (!strcmp(argv[1], "-d"))
293 silc_log_debug(TRUE);
294 if (argc > 2 && !strcmp(argv[2], "-x"))
295 silc_log_debug_hexdump(TRUE);
296 silc_log_set_debug_string("*");
297 }
298
299 client->schedule = silc_schedule_init(0, NULL);
300 if (!client->schedule)
301 return -1;
302
303 /* Connecto to server */
304 silc_net_tcp_connect(NULL, "127.0.0.1", 5000, client->schedule,
305 connect_callback, client);
306
307 silc_schedule(client->schedule);
308 return 0;
309 }
310
end_test(void)311 static void end_test(void)
312 {
313 SILC_LOG_DEBUG(("Testing was %s", success ? "SUCCESS" : "FAILURE"));
314 fprintf(stderr, "Testing was %s\n", success ? "SUCCESS" : "FAILURE");
315 exit(success);
316 }
317