]> git.proxmox.com Git - rustc.git/blob - src/vendor/libssh2-sys/libssh2/src/scp.c
New upstream version 1.19.0+dfsg1
[rustc.git] / src / vendor / libssh2-sys / libssh2 / src / scp.c
1 /* Copyright (c) 2009-2010 by Daniel Stenberg
2 * Copyright (c) 2004-2008, Sara Golemon <sarag@libssh2.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms,
6 * with or without modification, are permitted provided
7 * that the following conditions are met:
8 *
9 * Redistributions of source code must retain the above
10 * copyright notice, this list of conditions and the
11 * following disclaimer.
12 *
13 * Redistributions in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following
15 * disclaimer in the documentation and/or other materials
16 * provided with the distribution.
17 *
18 * Neither the name of the copyright holder nor the names
19 * of any other contributors may be used to endorse or
20 * promote products derived from this software without
21 * specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
24 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
25 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
26 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
28 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
29 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
30 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
31 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
33 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
35 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
36 * OF SUCH DAMAGE.
37 */
38
39 #include "libssh2_priv.h"
40 #include <errno.h>
41 #include <stdlib.h>
42
43 #include "channel.h"
44 #include "session.h"
45
46
47 /* Max. length of a quoted string after libssh2_shell_quotearg() processing */
48 #define _libssh2_shell_quotedsize(s) (3 * strlen(s) + 2)
49
50 /*
51 This function quotes a string in a way suitable to be used with a
52 shell, e.g. the file name
53 one two
54 becomes
55 'one two'
56
57 The resulting output string is crafted in a way that makes it usable
58 with the two most common shell types: Bourne Shell derived shells
59 (sh, ksh, ksh93, bash, zsh) and C-Shell derivates (csh, tcsh).
60
61 The following special cases are handled:
62 o If the string contains an apostrophy itself, the apostrophy
63 character is written in quotation marks, e.g. "'".
64 The shell cannot handle the syntax 'doesn\'t', so we close the
65 current argument word, add the apostrophe in quotation marks "",
66 and open a new argument word instead (_ indicate the input
67 string characters):
68 _____ _ _
69 'doesn' "'" 't'
70
71 Sequences of apostrophes are combined in one pair of quotation marks:
72 a'''b
73 becomes
74 _ ___ _
75 'a'"'''"'b'
76
77 o If the string contains an exclamation mark (!), the C-Shell
78 interprets it as an event number. Using \! (not within quotation
79 marks or single quotation marks) is a mechanism understood by
80 both Bourne Shell and C-Shell.
81
82 If a quotation was already started, the argument word is closed
83 first:
84 a!b
85
86 become
87 _ _ _
88 'a'\!'b'
89
90 The result buffer must be large enough for the expanded result. A
91 bad case regarding expansion is alternating characters and
92 apostrophes:
93
94 a'b'c'd' (length 8) gets converted to
95 'a'"'"'b'"'"'c'"'"'d'"'" (length 24)
96
97 This is the worst case.
98
99 Maximum length of the result:
100 1 + 6 * (length(input) + 1) / 2) + 1
101
102 => 3 * length(input) + 2
103
104 Explanation:
105 o leading apostrophe
106 o one character / apostrophe pair (two characters) can get
107 represented as 6 characters: a' -> a'"'"'
108 o String terminator (+1)
109
110 A result buffer three times the size of the input buffer + 2
111 characters should be safe.
112
113 References:
114 o csh-compatible quotation (special handling for '!' etc.), see
115 http://www.grymoire.com/Unix/Csh.html#toc-uh-10
116
117 Return value:
118 Length of the resulting string (not counting the terminating '\0'),
119 or 0 in case of errors, e.g. result buffer too small
120
121 Note: this function could possible be used elsewhere within libssh2, but
122 until then it is kept static and in this source file.
123 */
124
125 static unsigned
126 shell_quotearg(const char *path, unsigned char *buf,
127 unsigned bufsize)
128 {
129 const char *src;
130 unsigned char *dst, *endp;
131
132 /*
133 * Processing States:
134 * UQSTRING: unquoted string: ... -- used for quoting exclamation
135 * marks. This is the initial state
136 * SQSTRING: single-quoted-string: '... -- any character may follow
137 * QSTRING: quoted string: "... -- only apostrophes may follow
138 */
139 enum { UQSTRING, SQSTRING, QSTRING } state = UQSTRING;
140
141 endp = &buf[bufsize];
142 src = path;
143 dst = buf;
144 while (*src && dst < endp - 1) {
145
146 switch (*src) {
147 /*
148 * Special handling for apostrophe.
149 * An apostrophe is always written in quotation marks, e.g.
150 * ' -> "'".
151 */
152
153 case '\'':
154 switch (state) {
155 case UQSTRING: /* Unquoted string */
156 if (dst+1 >= endp)
157 return 0;
158 *dst++ = '"';
159 break;
160 case QSTRING: /* Continue quoted string */
161 break;
162 case SQSTRING: /* Close single quoted string */
163 if (dst+2 >= endp)
164 return 0;
165 *dst++ = '\'';
166 *dst++ = '"';
167 break;
168 default:
169 break;
170 }
171 state = QSTRING;
172 break;
173
174 /*
175 * Special handling for exclamation marks. CSH interprets
176 * exclamation marks even when quoted with apostrophes. We convert
177 * it to the plain string \!, because both Bourne Shell and CSH
178 * interpret that as a verbatim exclamation mark.
179 */
180
181 case '!':
182 switch (state) {
183 case UQSTRING:
184 if (dst+1 >= endp)
185 return 0;
186 *dst++ = '\\';
187 break;
188 case QSTRING:
189 if (dst+2 >= endp)
190 return 0;
191 *dst++ = '"'; /* Closing quotation mark */
192 *dst++ = '\\';
193 break;
194 case SQSTRING: /* Close single quoted string */
195 if (dst+2 >= endp)
196 return 0;
197 *dst++ = '\'';
198 *dst++ = '\\';
199 break;
200 default:
201 break;
202 }
203 state = UQSTRING;
204 break;
205
206 /*
207 * Ordinary character: prefer single-quoted string
208 */
209
210 default:
211 switch (state) {
212 case UQSTRING:
213 if (dst+1 >= endp)
214 return 0;
215 *dst++ = '\'';
216 break;
217 case QSTRING:
218 if (dst+2 >= endp)
219 return 0;
220 *dst++ = '"'; /* Closing quotation mark */
221 *dst++ = '\'';
222 break;
223 case SQSTRING: /* Continue single quoted string */
224 break;
225 default:
226 break;
227 }
228 state = SQSTRING; /* Start single-quoted string */
229 break;
230 }
231
232 if (dst+1 >= endp)
233 return 0;
234 *dst++ = *src++;
235 }
236
237 switch (state) {
238 case UQSTRING:
239 break;
240 case QSTRING: /* Close quoted string */
241 if (dst+1 >= endp)
242 return 0;
243 *dst++ = '"';
244 break;
245 case SQSTRING: /* Close single quoted string */
246 if (dst+1 >= endp)
247 return 0;
248 *dst++ = '\'';
249 break;
250 default:
251 break;
252 }
253
254 if (dst+1 >= endp)
255 return 0;
256 *dst = '\0';
257
258 /* The result cannot be larger than 3 * strlen(path) + 2 */
259 /* assert((dst - buf) <= (3 * (src - path) + 2)); */
260
261 return dst - buf;
262 }
263
264 /*
265 * scp_recv
266 *
267 * Open a channel and request a remote file via SCP
268 *
269 */
270 static LIBSSH2_CHANNEL *
271 scp_recv(LIBSSH2_SESSION * session, const char *path, libssh2_struct_stat * sb)
272 {
273 int cmd_len;
274 int rc;
275 int tmp_err_code;
276 const char *tmp_err_msg;
277
278 if (session->scpRecv_state == libssh2_NB_state_idle) {
279 session->scpRecv_mode = 0;
280 session->scpRecv_size = 0;
281 session->scpRecv_mtime = 0;
282 session->scpRecv_atime = 0;
283
284 session->scpRecv_command_len =
285 _libssh2_shell_quotedsize(path) + sizeof("scp -f ") + (sb?1:0);
286
287 session->scpRecv_command =
288 LIBSSH2_ALLOC(session, session->scpRecv_command_len);
289
290 if (!session->scpRecv_command) {
291 _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
292 "Unable to allocate a command buffer for "
293 "SCP session");
294 return NULL;
295 }
296
297 snprintf((char *)session->scpRecv_command,
298 session->scpRecv_command_len,
299 "scp -%sf ", sb?"p":"");
300
301 cmd_len = strlen((char *)session->scpRecv_command);
302 cmd_len += shell_quotearg(path,
303 &session->scpRecv_command[cmd_len],
304 session->scpRecv_command_len - cmd_len);
305
306 session->scpRecv_command[cmd_len] = '\0';
307 session->scpRecv_command_len = cmd_len + 1;
308
309 _libssh2_debug(session, LIBSSH2_TRACE_SCP,
310 "Opening channel for SCP receive");
311
312 session->scpRecv_state = libssh2_NB_state_created;
313 }
314
315 if (session->scpRecv_state == libssh2_NB_state_created) {
316 /* Allocate a channel */
317 session->scpRecv_channel =
318 _libssh2_channel_open(session, "session",
319 sizeof("session") - 1,
320 LIBSSH2_CHANNEL_WINDOW_DEFAULT,
321 LIBSSH2_CHANNEL_PACKET_DEFAULT, NULL,
322 0);
323 if (!session->scpRecv_channel) {
324 if (libssh2_session_last_errno(session) !=
325 LIBSSH2_ERROR_EAGAIN) {
326 LIBSSH2_FREE(session, session->scpRecv_command);
327 session->scpRecv_command = NULL;
328 session->scpRecv_state = libssh2_NB_state_idle;
329 }
330 else {
331 _libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
332 "Would block starting up channel");
333 }
334 return NULL;
335 }
336
337 session->scpRecv_state = libssh2_NB_state_sent;
338 }
339
340 if (session->scpRecv_state == libssh2_NB_state_sent) {
341 /* Request SCP for the desired file */
342 rc = _libssh2_channel_process_startup(session->scpRecv_channel, "exec",
343 sizeof("exec") - 1,
344 (char *) session->scpRecv_command,
345 session->scpRecv_command_len);
346 if (rc == LIBSSH2_ERROR_EAGAIN) {
347 _libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
348 "Would block requesting SCP startup");
349 return NULL;
350 } else if (rc) {
351 LIBSSH2_FREE(session, session->scpRecv_command);
352 session->scpRecv_command = NULL;
353 goto scp_recv_error;
354 }
355 LIBSSH2_FREE(session, session->scpRecv_command);
356 session->scpRecv_command = NULL;
357
358 _libssh2_debug(session, LIBSSH2_TRACE_SCP, "Sending initial wakeup");
359 /* SCP ACK */
360 session->scpRecv_response[0] = '\0';
361
362 session->scpRecv_state = libssh2_NB_state_sent1;
363 }
364
365 if (session->scpRecv_state == libssh2_NB_state_sent1) {
366 rc = _libssh2_channel_write(session->scpRecv_channel, 0,
367 session->scpRecv_response, 1);
368 if (rc == LIBSSH2_ERROR_EAGAIN) {
369 _libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
370 "Would block sending initial wakeup");
371 return NULL;
372 } else if (rc != 1) {
373 goto scp_recv_error;
374 }
375
376 /* Parse SCP response */
377 session->scpRecv_response_len = 0;
378
379 session->scpRecv_state = libssh2_NB_state_sent2;
380 }
381
382 if ((session->scpRecv_state == libssh2_NB_state_sent2)
383 || (session->scpRecv_state == libssh2_NB_state_sent3)) {
384 while (sb && (session->scpRecv_response_len <
385 LIBSSH2_SCP_RESPONSE_BUFLEN)) {
386 unsigned char *s, *p;
387
388 if (session->scpRecv_state == libssh2_NB_state_sent2) {
389 rc = _libssh2_channel_read(session->scpRecv_channel, 0,
390 (char *) session->
391 scpRecv_response +
392 session->scpRecv_response_len, 1);
393 if (rc == LIBSSH2_ERROR_EAGAIN) {
394 _libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
395 "Would block waiting for SCP response");
396 return NULL;
397 }
398 else if (rc < 0) {
399 /* error, give up */
400 _libssh2_error(session, rc, "Failed reading SCP response");
401 goto scp_recv_error;
402 }
403 else if(rc == 0)
404 goto scp_recv_empty_channel;
405
406 session->scpRecv_response_len++;
407
408 if (session->scpRecv_response[0] != 'T') {
409 size_t err_len;
410 char *err_msg;
411
412 /* there can be
413 01 for warnings
414 02 for errors
415
416 The following string MUST be newline terminated
417 */
418 err_len =
419 _libssh2_channel_packet_data_len(session->
420 scpRecv_channel, 0);
421 err_msg = LIBSSH2_ALLOC(session, err_len + 1);
422 if (!err_msg) {
423 _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
424 "Failed to get memory ");
425 goto scp_recv_error;
426 }
427
428 /* Read the remote error message */
429 (void)_libssh2_channel_read(session->scpRecv_channel, 0,
430 err_msg, err_len);
431 /* If it failed for any reason, we ignore it anyway. */
432
433 /* zero terminate the error */
434 err_msg[err_len]=0;
435
436 _libssh2_debug(session, LIBSSH2_TRACE_SCP,
437 "got %02x %s", session->scpRecv_response[0],
438 err_msg);
439
440 _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
441 "Failed to recv file");
442
443 LIBSSH2_FREE(session, err_msg);
444 goto scp_recv_error;
445 }
446
447 if ((session->scpRecv_response_len > 1) &&
448 ((session->
449 scpRecv_response[session->scpRecv_response_len - 1] <
450 '0')
451 || (session->
452 scpRecv_response[session->scpRecv_response_len - 1] >
453 '9'))
454 && (session->
455 scpRecv_response[session->scpRecv_response_len - 1] !=
456 ' ')
457 && (session->
458 scpRecv_response[session->scpRecv_response_len - 1] !=
459 '\r')
460 && (session->
461 scpRecv_response[session->scpRecv_response_len - 1] !=
462 '\n')) {
463 _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
464 "Invalid data in SCP response");
465 goto scp_recv_error;
466 }
467
468 if ((session->scpRecv_response_len < 9)
469 || (session->
470 scpRecv_response[session->scpRecv_response_len - 1] !=
471 '\n')) {
472 if (session->scpRecv_response_len ==
473 LIBSSH2_SCP_RESPONSE_BUFLEN) {
474 /* You had your chance */
475 _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
476 "Unterminated response from SCP server");
477 goto scp_recv_error;
478 }
479 /* Way too short to be an SCP response, or not done yet,
480 short circuit */
481 continue;
482 }
483
484 /* We're guaranteed not to go under response_len == 0 by the
485 logic above */
486 while ((session->
487 scpRecv_response[session->scpRecv_response_len - 1] ==
488 '\r')
489 || (session->
490 scpRecv_response[session->scpRecv_response_len -
491 1] == '\n'))
492 session->scpRecv_response_len--;
493 session->scpRecv_response[session->scpRecv_response_len] =
494 '\0';
495
496 if (session->scpRecv_response_len < 8) {
497 /* EOL came too soon */
498 _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
499 "Invalid response from SCP server, "
500 "too short" );
501 goto scp_recv_error;
502 }
503
504 s = session->scpRecv_response + 1;
505
506 p = (unsigned char *) strchr((char *) s, ' ');
507 if (!p || ((p - s) <= 0)) {
508 /* No spaces or space in the wrong spot */
509 _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
510 "Invalid response from SCP server, "
511 "malformed mtime");
512 goto scp_recv_error;
513 }
514
515 *(p++) = '\0';
516 /* Make sure we don't get fooled by leftover values */
517 session->scpRecv_mtime = strtol((char *) s, NULL, 10);
518
519 s = (unsigned char *) strchr((char *) p, ' ');
520 if (!s || ((s - p) <= 0)) {
521 /* No spaces or space in the wrong spot */
522 _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
523 "Invalid response from SCP server, malformed mtime.usec");
524 goto scp_recv_error;
525 }
526
527 /* Ignore mtime.usec */
528 s++;
529 p = (unsigned char *) strchr((char *) s, ' ');
530 if (!p || ((p - s) <= 0)) {
531 /* No spaces or space in the wrong spot */
532 _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
533 "Invalid response from SCP server, too short or malformed");
534 goto scp_recv_error;
535 }
536
537 *p = '\0';
538 /* Make sure we don't get fooled by leftover values */
539 session->scpRecv_atime = strtol((char *) s, NULL, 10);
540
541 /* SCP ACK */
542 session->scpRecv_response[0] = '\0';
543
544 session->scpRecv_state = libssh2_NB_state_sent3;
545 }
546
547 if (session->scpRecv_state == libssh2_NB_state_sent3) {
548 rc = _libssh2_channel_write(session->scpRecv_channel, 0,
549 session->scpRecv_response, 1);
550 if (rc == LIBSSH2_ERROR_EAGAIN) {
551 _libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
552 "Would block waiting to send SCP ACK");
553 return NULL;
554 } else if (rc != 1) {
555 goto scp_recv_error;
556 }
557
558 _libssh2_debug(session, LIBSSH2_TRACE_SCP,
559 "mtime = %ld, atime = %ld",
560 session->scpRecv_mtime, session->scpRecv_atime);
561
562 /* We *should* check that atime.usec is valid, but why let
563 that stop use? */
564 break;
565 }
566 }
567
568 session->scpRecv_state = libssh2_NB_state_sent4;
569 }
570
571 if (session->scpRecv_state == libssh2_NB_state_sent4) {
572 session->scpRecv_response_len = 0;
573
574 session->scpRecv_state = libssh2_NB_state_sent5;
575 }
576
577 if ((session->scpRecv_state == libssh2_NB_state_sent5)
578 || (session->scpRecv_state == libssh2_NB_state_sent6)) {
579 while (session->scpRecv_response_len < LIBSSH2_SCP_RESPONSE_BUFLEN) {
580 char *s, *p, *e = NULL;
581
582 if (session->scpRecv_state == libssh2_NB_state_sent5) {
583 rc = _libssh2_channel_read(session->scpRecv_channel, 0,
584 (char *) session->
585 scpRecv_response +
586 session->scpRecv_response_len, 1);
587 if (rc == LIBSSH2_ERROR_EAGAIN) {
588 _libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
589 "Would block waiting for SCP response");
590 return NULL;
591 }
592 else if (rc < 0) {
593 /* error, bail out*/
594 _libssh2_error(session, rc, "Failed reading SCP response");
595 goto scp_recv_error;
596 }
597 else if(rc == 0)
598 goto scp_recv_empty_channel;
599
600 session->scpRecv_response_len++;
601
602 if (session->scpRecv_response[0] != 'C') {
603 _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
604 "Invalid response from SCP server");
605 goto scp_recv_error;
606 }
607
608 if ((session->scpRecv_response_len > 1) &&
609 (session->
610 scpRecv_response[session->scpRecv_response_len - 1] !=
611 '\r')
612 && (session->
613 scpRecv_response[session->scpRecv_response_len - 1] !=
614 '\n')
615 &&
616 (session->
617 scpRecv_response[session->scpRecv_response_len - 1]
618 < 32)) {
619 _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
620 "Invalid data in SCP response");
621 goto scp_recv_error;
622 }
623
624 if ((session->scpRecv_response_len < 7)
625 || (session->
626 scpRecv_response[session->scpRecv_response_len - 1] !=
627 '\n')) {
628 if (session->scpRecv_response_len ==
629 LIBSSH2_SCP_RESPONSE_BUFLEN) {
630 /* You had your chance */
631 _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
632 "Unterminated response from SCP server");
633 goto scp_recv_error;
634 }
635 /* Way too short to be an SCP response, or not done yet,
636 short circuit */
637 continue;
638 }
639
640 /* We're guaranteed not to go under response_len == 0 by the
641 logic above */
642 while ((session->
643 scpRecv_response[session->scpRecv_response_len - 1] ==
644 '\r')
645 || (session->
646 scpRecv_response[session->scpRecv_response_len -
647 1] == '\n')) {
648 session->scpRecv_response_len--;
649 }
650 session->scpRecv_response[session->scpRecv_response_len] =
651 '\0';
652
653 if (session->scpRecv_response_len < 6) {
654 /* EOL came too soon */
655 _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
656 "Invalid response from SCP server, too short");
657 goto scp_recv_error;
658 }
659
660 s = (char *) session->scpRecv_response + 1;
661
662 p = strchr(s, ' ');
663 if (!p || ((p - s) <= 0)) {
664 /* No spaces or space in the wrong spot */
665 _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
666 "Invalid response from SCP server, malformed mode");
667 goto scp_recv_error;
668 }
669
670 *(p++) = '\0';
671 /* Make sure we don't get fooled by leftover values */
672
673 session->scpRecv_mode = strtol(s, &e, 8);
674 if (e && *e) {
675 _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
676 "Invalid response from SCP server, invalid mode");
677 goto scp_recv_error;
678 }
679
680 s = strchr(p, ' ');
681 if (!s || ((s - p) <= 0)) {
682 /* No spaces or space in the wrong spot */
683 _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
684 "Invalid response from SCP server, too short or malformed");
685 goto scp_recv_error;
686 }
687
688 *s = '\0';
689 /* Make sure we don't get fooled by leftover values */
690 session->scpRecv_size = scpsize_strtol(p, &e, 10);
691 if (e && *e) {
692 _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
693 "Invalid response from SCP server, invalid size");
694 goto scp_recv_error;
695 }
696
697 /* SCP ACK */
698 session->scpRecv_response[0] = '\0';
699
700 session->scpRecv_state = libssh2_NB_state_sent6;
701 }
702
703 if (session->scpRecv_state == libssh2_NB_state_sent6) {
704 rc = _libssh2_channel_write(session->scpRecv_channel, 0,
705 session->scpRecv_response, 1);
706 if (rc == LIBSSH2_ERROR_EAGAIN) {
707 _libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
708 "Would block sending SCP ACK");
709 return NULL;
710 } else if (rc != 1) {
711 goto scp_recv_error;
712 }
713 _libssh2_debug(session, LIBSSH2_TRACE_SCP,
714 "mode = 0%lo size = %ld", session->scpRecv_mode,
715 session->scpRecv_size);
716
717 /* We *should* check that basename is valid, but why let that
718 stop us? */
719 break;
720 }
721 }
722
723 session->scpRecv_state = libssh2_NB_state_sent7;
724 }
725
726 if (sb) {
727 memset(sb, 0, sizeof(libssh2_struct_stat));
728
729 sb->st_mtime = session->scpRecv_mtime;
730 sb->st_atime = session->scpRecv_atime;
731 sb->st_size = session->scpRecv_size;
732 sb->st_mode = (unsigned short)session->scpRecv_mode;
733 }
734
735 session->scpRecv_state = libssh2_NB_state_idle;
736 return session->scpRecv_channel;
737
738 scp_recv_empty_channel:
739 /* the code only jumps here as a result of a zero read from channel_read()
740 so we check EOF status to avoid getting stuck in a loop */
741 if(libssh2_channel_eof(session->scpRecv_channel))
742 _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
743 "Unexpected channel close");
744 else
745 return session->scpRecv_channel;
746 /* fall-through */
747 scp_recv_error:
748 tmp_err_code = session->err_code;
749 tmp_err_msg = session->err_msg;
750 while (libssh2_channel_free(session->scpRecv_channel) ==
751 LIBSSH2_ERROR_EAGAIN);
752 session->err_code = tmp_err_code;
753 session->err_msg = tmp_err_msg;
754 session->scpRecv_channel = NULL;
755 session->scpRecv_state = libssh2_NB_state_idle;
756 return NULL;
757 }
758
759 /*
760 * libssh2_scp_recv
761 *
762 * DEPRECATED
763 *
764 * Open a channel and request a remote file via SCP. This receives files larger
765 * than 2 GB, but is unable to report the proper size on platforms where the
766 * st_size member of struct stat is limited to 2 GB (e.g. windows).
767 *
768 */
769 LIBSSH2_API LIBSSH2_CHANNEL *
770 libssh2_scp_recv(LIBSSH2_SESSION *session, const char *path, struct stat * sb)
771 {
772 LIBSSH2_CHANNEL *ptr;
773
774 /* scp_recv uses libssh2_struct_stat, so pass one if the caller gave us a struct to populate... */
775 libssh2_struct_stat sb_intl;
776 libssh2_struct_stat *sb_ptr;
777 sb_ptr = sb ? &sb_intl : NULL;
778
779 BLOCK_ADJUST_ERRNO(ptr, session, scp_recv(session, path, sb_ptr));
780
781 /* ...and populate the caller's with as much info as fits. */
782 if (sb) {
783 memset(sb, 0, sizeof(struct stat));
784
785 sb->st_mtime = sb_intl.st_mtime;
786 sb->st_atime = sb_intl.st_atime;
787 sb->st_size = (off_t)sb_intl.st_size;
788 sb->st_mode = sb_intl.st_mode;
789 }
790
791 return ptr;
792 }
793
794 /*
795 * libssh2_scp_recv2
796 *
797 * Open a channel and request a remote file via SCP. This supports files > 2GB
798 * on platforms that support it.
799 *
800 */
801 LIBSSH2_API LIBSSH2_CHANNEL *
802 libssh2_scp_recv2(LIBSSH2_SESSION *session, const char *path, libssh2_struct_stat * sb)
803 {
804 LIBSSH2_CHANNEL *ptr;
805 BLOCK_ADJUST_ERRNO(ptr, session, scp_recv(session, path, sb));
806 return ptr;
807 }
808
809 /*
810 * scp_send()
811 *
812 * Send a file using SCP
813 *
814 */
815 static LIBSSH2_CHANNEL *
816 scp_send(LIBSSH2_SESSION * session, const char *path, int mode,
817 libssh2_int64_t size, time_t mtime, time_t atime)
818 {
819 int cmd_len;
820 int rc;
821 int tmp_err_code;
822 const char *tmp_err_msg;
823
824 if (session->scpSend_state == libssh2_NB_state_idle) {
825 session->scpSend_command_len =
826 _libssh2_shell_quotedsize(path) + sizeof("scp -t ") +
827 ((mtime || atime)?1:0);
828
829 session->scpSend_command =
830 LIBSSH2_ALLOC(session, session->scpSend_command_len);
831
832 if (!session->scpSend_command) {
833 _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
834 "Unable to allocate a command buffer for "
835 "SCP session");
836 return NULL;
837 }
838
839 snprintf((char *)session->scpSend_command,
840 session->scpSend_command_len,
841 "scp -%st ", (mtime || atime)?"p":"");
842
843 cmd_len = strlen((char *)session->scpSend_command);
844 cmd_len += shell_quotearg(path,
845 &session->scpSend_command[cmd_len],
846 session->scpSend_command_len - cmd_len);
847
848 session->scpSend_command[cmd_len] = '\0';
849 session->scpSend_command_len = cmd_len + 1;
850
851 _libssh2_debug(session, LIBSSH2_TRACE_SCP,
852 "Opening channel for SCP send");
853 /* Allocate a channel */
854
855 session->scpSend_state = libssh2_NB_state_created;
856 }
857
858 if (session->scpSend_state == libssh2_NB_state_created) {
859 session->scpSend_channel =
860 _libssh2_channel_open(session, "session", sizeof("session") - 1,
861 LIBSSH2_CHANNEL_WINDOW_DEFAULT,
862 LIBSSH2_CHANNEL_PACKET_DEFAULT, NULL, 0);
863 if (!session->scpSend_channel) {
864 if (libssh2_session_last_errno(session) != LIBSSH2_ERROR_EAGAIN) {
865 /* previous call set libssh2_session_last_error(), pass it
866 through */
867 LIBSSH2_FREE(session, session->scpSend_command);
868 session->scpSend_command = NULL;
869 session->scpSend_state = libssh2_NB_state_idle;
870 }
871 else {
872 _libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
873 "Would block starting up channel");
874 }
875 return NULL;
876 }
877
878 session->scpSend_state = libssh2_NB_state_sent;
879 }
880
881 if (session->scpSend_state == libssh2_NB_state_sent) {
882 /* Request SCP for the desired file */
883 rc = _libssh2_channel_process_startup(session->scpSend_channel, "exec",
884 sizeof("exec") - 1,
885 (char *) session->scpSend_command,
886 session->scpSend_command_len);
887 if (rc == LIBSSH2_ERROR_EAGAIN) {
888 _libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
889 "Would block requesting SCP startup");
890 return NULL;
891 }
892 else if (rc) {
893 /* previous call set libssh2_session_last_error(), pass it
894 through */
895 LIBSSH2_FREE(session, session->scpSend_command);
896 session->scpSend_command = NULL;
897 _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
898 "Unknown error while getting error string");
899 goto scp_send_error;
900 }
901 LIBSSH2_FREE(session, session->scpSend_command);
902 session->scpSend_command = NULL;
903
904 session->scpSend_state = libssh2_NB_state_sent1;
905 }
906
907 if (session->scpSend_state == libssh2_NB_state_sent1) {
908 /* Wait for ACK */
909 rc = _libssh2_channel_read(session->scpSend_channel, 0,
910 (char *) session->scpSend_response, 1);
911 if (rc == LIBSSH2_ERROR_EAGAIN) {
912 _libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
913 "Would block waiting for response from remote");
914 return NULL;
915 }
916 else if (rc < 0) {
917 _libssh2_error(session, rc, "SCP failure");
918 goto scp_send_error;
919 }
920 else if(!rc)
921 /* remain in the same state */
922 goto scp_send_empty_channel;
923 else if (session->scpSend_response[0] != 0) {
924 _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
925 "Invalid ACK response from remote");
926 goto scp_send_error;
927 }
928 if (mtime || atime) {
929 /* Send mtime and atime to be used for file */
930 session->scpSend_response_len =
931 snprintf((char *) session->scpSend_response,
932 LIBSSH2_SCP_RESPONSE_BUFLEN, "T%ld 0 %ld 0\n",
933 (long)mtime, (long)atime);
934 _libssh2_debug(session, LIBSSH2_TRACE_SCP, "Sent %s",
935 session->scpSend_response);
936 }
937
938 session->scpSend_state = libssh2_NB_state_sent2;
939 }
940
941 /* Send mtime and atime to be used for file */
942 if (mtime || atime) {
943 if (session->scpSend_state == libssh2_NB_state_sent2) {
944 rc = _libssh2_channel_write(session->scpSend_channel, 0,
945 session->scpSend_response,
946 session->scpSend_response_len);
947 if (rc == LIBSSH2_ERROR_EAGAIN) {
948 _libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
949 "Would block sending time data for SCP file");
950 return NULL;
951 } else if (rc != (int)session->scpSend_response_len) {
952 _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
953 "Unable to send time data for SCP file");
954 goto scp_send_error;
955 }
956
957 session->scpSend_state = libssh2_NB_state_sent3;
958 }
959
960 if (session->scpSend_state == libssh2_NB_state_sent3) {
961 /* Wait for ACK */
962 rc = _libssh2_channel_read(session->scpSend_channel, 0,
963 (char *) session->scpSend_response, 1);
964 if (rc == LIBSSH2_ERROR_EAGAIN) {
965 _libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
966 "Would block waiting for response");
967 return NULL;
968 }
969 else if (rc < 0) {
970 _libssh2_error(session, rc, "SCP failure");
971 goto scp_send_error;
972 }
973 else if(!rc)
974 /* remain in the same state */
975 goto scp_send_empty_channel;
976 else if (session->scpSend_response[0] != 0) {
977 _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
978 "Invalid SCP ACK response");
979 goto scp_send_error;
980 }
981
982 session->scpSend_state = libssh2_NB_state_sent4;
983 }
984 } else {
985 if (session->scpSend_state == libssh2_NB_state_sent2) {
986 session->scpSend_state = libssh2_NB_state_sent4;
987 }
988 }
989
990 if (session->scpSend_state == libssh2_NB_state_sent4) {
991 /* Send mode, size, and basename */
992 const char *base = strrchr(path, '/');
993 if (base)
994 base++;
995 else
996 base = path;
997
998 session->scpSend_response_len =
999 snprintf((char *) session->scpSend_response,
1000 LIBSSH2_SCP_RESPONSE_BUFLEN, "C0%o %"
1001 LIBSSH2_INT64_T_FORMAT " %s\n", mode,
1002 size, base);
1003 _libssh2_debug(session, LIBSSH2_TRACE_SCP, "Sent %s",
1004 session->scpSend_response);
1005
1006 session->scpSend_state = libssh2_NB_state_sent5;
1007 }
1008
1009 if (session->scpSend_state == libssh2_NB_state_sent5) {
1010 rc = _libssh2_channel_write(session->scpSend_channel, 0,
1011 session->scpSend_response,
1012 session->scpSend_response_len);
1013 if (rc == LIBSSH2_ERROR_EAGAIN) {
1014 _libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
1015 "Would block send core file data for SCP file");
1016 return NULL;
1017 } else if (rc != (int)session->scpSend_response_len) {
1018 _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
1019 "Unable to send core file data for SCP file");
1020 goto scp_send_error;
1021 }
1022
1023 session->scpSend_state = libssh2_NB_state_sent6;
1024 }
1025
1026 if (session->scpSend_state == libssh2_NB_state_sent6) {
1027 /* Wait for ACK */
1028 rc = _libssh2_channel_read(session->scpSend_channel, 0,
1029 (char *) session->scpSend_response, 1);
1030 if (rc == LIBSSH2_ERROR_EAGAIN) {
1031 _libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
1032 "Would block waiting for response");
1033 return NULL;
1034 }
1035 else if (rc < 0) {
1036 _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
1037 "Invalid ACK response from remote");
1038 goto scp_send_error;
1039 }
1040 else if (rc == 0)
1041 goto scp_send_empty_channel;
1042
1043 else if (session->scpSend_response[0] != 0) {
1044 size_t err_len;
1045 char *err_msg;
1046
1047 err_len =
1048 _libssh2_channel_packet_data_len(session->scpSend_channel, 0);
1049 err_msg = LIBSSH2_ALLOC(session, err_len + 1);
1050 if (!err_msg) {
1051 _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
1052 "failed to get memory");
1053 goto scp_send_error;
1054 }
1055
1056 /* Read the remote error message */
1057 rc = _libssh2_channel_read(session->scpSend_channel, 0,
1058 err_msg, err_len);
1059 if (rc > 0) {
1060 err_msg[err_len]=0;
1061 _libssh2_debug(session, LIBSSH2_TRACE_SCP,
1062 "got %02x %s", session->scpSend_response[0],
1063 err_msg);
1064 }
1065 LIBSSH2_FREE(session, err_msg);
1066 _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
1067 "failed to send file");
1068 goto scp_send_error;
1069 }
1070 }
1071
1072 session->scpSend_state = libssh2_NB_state_idle;
1073 return session->scpSend_channel;
1074
1075 scp_send_empty_channel:
1076 /* the code only jumps here as a result of a zero read from channel_read()
1077 so we check EOF status to avoid getting stuck in a loop */
1078 if(libssh2_channel_eof(session->scpSend_channel)) {
1079 _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
1080 "Unexpected channel close");
1081 }
1082 else
1083 return session->scpSend_channel;
1084 /* fall-through */
1085 scp_send_error:
1086 tmp_err_code = session->err_code;
1087 tmp_err_msg = session->err_msg;
1088 while (libssh2_channel_free(session->scpSend_channel) ==
1089 LIBSSH2_ERROR_EAGAIN);
1090 session->err_code = tmp_err_code;
1091 session->err_msg = tmp_err_msg;
1092 session->scpSend_channel = NULL;
1093 session->scpSend_state = libssh2_NB_state_idle;
1094 return NULL;
1095 }
1096
1097 /*
1098 * libssh2_scp_send_ex
1099 *
1100 * Send a file using SCP. Old API.
1101 */
1102 LIBSSH2_API LIBSSH2_CHANNEL *
1103 libssh2_scp_send_ex(LIBSSH2_SESSION *session, const char *path, int mode,
1104 size_t size, long mtime, long atime)
1105 {
1106 LIBSSH2_CHANNEL *ptr;
1107 BLOCK_ADJUST_ERRNO(ptr, session,
1108 scp_send(session, path, mode, size,
1109 (time_t)mtime, (time_t)atime));
1110 return ptr;
1111 }
1112
1113 /*
1114 * libssh2_scp_send64
1115 *
1116 * Send a file using SCP
1117 */
1118 LIBSSH2_API LIBSSH2_CHANNEL *
1119 libssh2_scp_send64(LIBSSH2_SESSION *session, const char *path, int mode,
1120 libssh2_int64_t size, time_t mtime, time_t atime)
1121 {
1122 LIBSSH2_CHANNEL *ptr;
1123 BLOCK_ADJUST_ERRNO(ptr, session,
1124 scp_send(session, path, mode, size, mtime, atime));
1125 return ptr;
1126 }