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