aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNatanael Copa <ncopa@alpinelinux.org>2019-12-26 13:07:46 +0100
committerNatanael Copa <ncopa@alpinelinux.org>2019-12-26 13:10:34 +0100
commitf853c4e3ca0c6161fd59ddb75b3f4e57c2d024f5 (patch)
tree86dfbae23064ee7e3fb78b3c1c5aca78cbf91927
parentb98ba48c0925b8f0093983262b8d3fb122ee97dc (diff)
downloadalpine_aports-f853c4e3ca0c6161fd59ddb75b3f4e57c2d024f5.tar.bz2
alpine_aports-f853c4e3ca0c6161fd59ddb75b3f4e57c2d024f5.tar.xz
alpine_aports-f853c4e3ca0c6161fd59ddb75b3f4e57c2d024f5.zip
main/libssh: security fix for CVE-2019-14889
fixes #11042
-rw-r--r--main/libssh/APKBUILD11
-rw-r--r--main/libssh/CVE-2019-14889.patch1957
2 files changed, 1965 insertions, 3 deletions
diff --git a/main/libssh/APKBUILD b/main/libssh/APKBUILD
index b862822c11..dfc9712bb8 100644
--- a/main/libssh/APKBUILD
+++ b/main/libssh/APKBUILD
@@ -2,7 +2,7 @@
2# Maintainer: Natanael Copa <ncopa@alpinelinux.org> 2# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
3pkgname=libssh 3pkgname=libssh
4pkgver=0.7.6 4pkgver=0.7.6
5pkgrel=0 5pkgrel=1
6pkgdesc="Library for accessing ssh client services through C libraries" 6pkgdesc="Library for accessing ssh client services through C libraries"
7url="http://www.libssh.org/" 7url="http://www.libssh.org/"
8arch="all" 8arch="all"
@@ -11,10 +11,14 @@ makedepends="zlib-dev libressl-dev cmake doxygen"
11subpackages="$pkgname-dev" 11subpackages="$pkgname-dev"
12options="!check" 12options="!check"
13source="https://www.libssh.org/files/0.7/libssh-$pkgver.tar.xz 13source="https://www.libssh.org/files/0.7/libssh-$pkgver.tar.xz
14 fix-includes.patch" 14 fix-includes.patch
15 CVE-2019-14889.patch
16 "
15builddir="$srcdir"/$pkgname-$pkgver 17builddir="$srcdir"/$pkgname-$pkgver
16 18
17# secfixes: 19# secfixes:
20# 0.7.6-r1:
21# - CVE-2019-14889
18# 0.7.6-r0: 22# 0.7.6-r0:
19# - CVE-2018-10933 23# - CVE-2018-10933
20 24
@@ -33,4 +37,5 @@ package() {
33} 37}
34 38
35sha512sums="2a01402b5a9fab9ecc29200544ed45d3f2c40871ed1c8241ca793f8dc7fdb3ad2150f6a522c4321affa9b8778e280dc7ed10f76adfc4a73f0751ae735a42f56c libssh-0.7.6.tar.xz 39sha512sums="2a01402b5a9fab9ecc29200544ed45d3f2c40871ed1c8241ca793f8dc7fdb3ad2150f6a522c4321affa9b8778e280dc7ed10f76adfc4a73f0751ae735a42f56c libssh-0.7.6.tar.xz
36055a8f6b97c65384a5a3ab8fe00c69d94cc30092fe926093dbbc122ce301fbe9d76127aa07b5e6107d7fa9dd2aad6b165fa0958b56520253b5d64428ff42a318 fix-includes.patch" 40055a8f6b97c65384a5a3ab8fe00c69d94cc30092fe926093dbbc122ce301fbe9d76127aa07b5e6107d7fa9dd2aad6b165fa0958b56520253b5d64428ff42a318 fix-includes.patch
41ed832fd00cb1ccae94e4b9e6771d92822dd1ef0e3fcc4649fab04dcde9f959909b7564fe1533e48eb4d016d3fef2dd711e1b9be5bda286545bd18bb81ae9cb6a CVE-2019-14889.patch"
diff --git a/main/libssh/CVE-2019-14889.patch b/main/libssh/CVE-2019-14889.patch
new file mode 100644
index 0000000000..ba049a10fc
--- /dev/null
+++ b/main/libssh/CVE-2019-14889.patch
@@ -0,0 +1,1957 @@
1From 4aea835974996b2deb011024c53f4ff4329a95b5 Mon Sep 17 00:00:00 2001
2From: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
3Date: Thu, 31 Oct 2019 17:56:34 +0100
4Subject: CVE-2019-14889: scp: Reformat scp.c
5
6Fixes T181
7
8Signed-off-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
9Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
10(cherry picked from commit 42c727d0c186a1e2fa84a31ab40e16e58b404ab3)
11---
12 src/scp.c | 1200 +++++++++++++++++++++++++++++++++++--------------------------
13 1 file changed, 698 insertions(+), 502 deletions(-)
14
15diff --git a/src/scp.c b/src/scp.c
16index fd9aaaaa..5de0e6ff 100644
17--- a/src/scp.c
18+++ b/src/scp.c
19@@ -57,30 +57,47 @@
20 *
21 * @returns A ssh_scp handle, NULL if the creation was impossible.
22 */
23-ssh_scp ssh_scp_new(ssh_session session, int mode, const char *location){
24- ssh_scp scp=malloc(sizeof(struct ssh_scp_struct));
25- if(scp == NULL){
26- ssh_set_error(session,SSH_FATAL,"Error allocating memory for ssh_scp");
27- return NULL;
28- }
29- ZERO_STRUCTP(scp);
30- if((mode&~SSH_SCP_RECURSIVE) != SSH_SCP_WRITE && (mode &~SSH_SCP_RECURSIVE) != SSH_SCP_READ){
31- ssh_set_error(session,SSH_FATAL,"Invalid mode %d for ssh_scp_new()",mode);
32- ssh_scp_free(scp);
33- return NULL;
34- }
35- scp->location=strdup(location);
36- if (scp->location == NULL) {
37- ssh_set_error(session,SSH_FATAL,"Error allocating memory for ssh_scp");
38+ssh_scp ssh_scp_new(ssh_session session, int mode, const char *location)
39+{
40+ ssh_scp scp = NULL;
41+
42+ if (session == NULL) {
43+ goto error;
44+ }
45+
46+ scp = (ssh_scp)calloc(1, sizeof(struct ssh_scp_struct));
47+ if (scp == NULL) {
48+ ssh_set_error(session, SSH_FATAL,
49+ "Error allocating memory for ssh_scp");
50+ goto error;
51+ }
52+
53+ if ((mode & ~SSH_SCP_RECURSIVE) != SSH_SCP_WRITE &&
54+ (mode & ~SSH_SCP_RECURSIVE) != SSH_SCP_READ)
55+ {
56+ ssh_set_error(session, SSH_FATAL,
57+ "Invalid mode %d for ssh_scp_new()", mode);
58+ goto error;
59+ }
60+
61+ scp->location = strdup(location);
62+ if (scp->location == NULL) {
63+ ssh_set_error(session, SSH_FATAL,
64+ "Error allocating memory for ssh_scp");
65+ goto error;
66+ }
67+
68+ scp->session = session;
69+ scp->mode = mode & ~SSH_SCP_RECURSIVE;
70+ scp->recursive = (mode & SSH_SCP_RECURSIVE) != 0;
71+ scp->channel = NULL;
72+ scp->state = SSH_SCP_NEW;
73+
74+ return scp;
75+
76+error:
77 ssh_scp_free(scp);
78 return NULL;
79- }
80- scp->session=session;
81- scp->mode=mode & ~SSH_SCP_RECURSIVE;
82- scp->recursive = (mode & SSH_SCP_RECURSIVE) != 0;
83- scp->channel=NULL;
84- scp->state=SSH_SCP_NEW;
85- return scp;
86 }
87
88 /**
89@@ -94,59 +111,78 @@ ssh_scp ssh_scp_new(ssh_session session, int mode, const char *location){
90 */
91 int ssh_scp_init(ssh_scp scp)
92 {
93- int r;
94- char execbuffer[1024];
95- uint8_t code;
96- if(scp==NULL)
97- return SSH_ERROR;
98- if(scp->state != SSH_SCP_NEW){
99- ssh_set_error(scp->session,SSH_FATAL,"ssh_scp_init called under invalid state");
100- return SSH_ERROR;
101- }
102- SSH_LOG(SSH_LOG_PROTOCOL,"Initializing scp session %s %son location '%s'",
103- scp->mode==SSH_SCP_WRITE?"write":"read",
104- scp->recursive?"recursive ":"",
105- scp->location);
106- scp->channel=ssh_channel_new(scp->session);
107- if(scp->channel == NULL){
108- scp->state=SSH_SCP_ERROR;
109- return SSH_ERROR;
110- }
111- r= ssh_channel_open_session(scp->channel);
112- if(r==SSH_ERROR){
113- scp->state=SSH_SCP_ERROR;
114- return SSH_ERROR;
115- }
116- if(scp->mode == SSH_SCP_WRITE)
117- snprintf(execbuffer,sizeof(execbuffer),"scp -t %s %s",
118- scp->recursive ? "-r":"", scp->location);
119- else
120- snprintf(execbuffer,sizeof(execbuffer),"scp -f %s %s",
121- scp->recursive ? "-r":"", scp->location);
122- if(ssh_channel_request_exec(scp->channel,execbuffer) == SSH_ERROR){
123- scp->state=SSH_SCP_ERROR;
124- return SSH_ERROR;
125- }
126- if(scp->mode == SSH_SCP_WRITE){
127- r=ssh_channel_read(scp->channel,&code,1,0);
128- if(r<=0){
129- ssh_set_error(scp->session,SSH_FATAL, "Error reading status code: %s",ssh_get_error(scp->session));
130- scp->state=SSH_SCP_ERROR;
131- return SSH_ERROR;
132- }
133- if(code != 0){
134- ssh_set_error(scp->session,SSH_FATAL, "scp status code %ud not valid", code);
135- scp->state=SSH_SCP_ERROR;
136- return SSH_ERROR;
137- }
138- } else {
139- ssh_channel_write(scp->channel,"",1);
140- }
141- if(scp->mode == SSH_SCP_WRITE)
142- scp->state=SSH_SCP_WRITE_INITED;
143- else
144- scp->state=SSH_SCP_READ_INITED;
145- return SSH_OK;
146+ int rc;
147+ char execbuffer[1024] = {0};
148+ uint8_t code;
149+
150+ if (scp == NULL) {
151+ return SSH_ERROR;
152+ }
153+
154+ if (scp->state != SSH_SCP_NEW) {
155+ ssh_set_error(scp->session, SSH_FATAL,
156+ "ssh_scp_init called under invalid state");
157+ return SSH_ERROR;
158+ }
159+
160+ SSH_LOG(SSH_LOG_PROTOCOL,
161+ "Initializing scp session %s %son location '%s'",
162+ scp->mode == SSH_SCP_WRITE?"write":"read",
163+ scp->recursive?"recursive ":"",
164+ scp->location);
165+
166+ scp->channel = ssh_channel_new(scp->session);
167+ if (scp->channel == NULL) {
168+ scp->state = SSH_SCP_ERROR;
169+ return SSH_ERROR;
170+ }
171+
172+ rc = ssh_channel_open_session(scp->channel);
173+ if (rc == SSH_ERROR) {
174+ scp->state = SSH_SCP_ERROR;
175+ return SSH_ERROR;
176+ }
177+
178+ if (scp->mode == SSH_SCP_WRITE) {
179+ snprintf(execbuffer, sizeof(execbuffer), "scp -t %s %s",
180+ scp->recursive ? "-r":"", scp->location);
181+ } else {
182+ snprintf(execbuffer, sizeof(execbuffer), "scp -f %s %s",
183+ scp->recursive ? "-r":"", scp->location);
184+ }
185+
186+ if (ssh_channel_request_exec(scp->channel, execbuffer) == SSH_ERROR) {
187+ scp->state = SSH_SCP_ERROR;
188+ return SSH_ERROR;
189+ }
190+
191+ if (scp->mode == SSH_SCP_WRITE) {
192+ rc = ssh_channel_read(scp->channel, &code, 1, 0);
193+ if (rc <= 0) {
194+ ssh_set_error(scp->session, SSH_FATAL,
195+ "Error reading status code: %s",
196+ ssh_get_error(scp->session));
197+ scp->state = SSH_SCP_ERROR;
198+ return SSH_ERROR;
199+ }
200+
201+ if (code != 0) {
202+ ssh_set_error(scp->session, SSH_FATAL,
203+ "scp status code %ud not valid", code);
204+ scp->state = SSH_SCP_ERROR;
205+ return SSH_ERROR;
206+ }
207+ } else {
208+ ssh_channel_write(scp->channel, "", 1);
209+ }
210+
211+ if (scp->mode == SSH_SCP_WRITE) {
212+ scp->state = SSH_SCP_WRITE_INITED;
213+ } else {
214+ scp->state = SSH_SCP_READ_INITED;
215+ }
216+
217+ return SSH_OK;
218 }
219
220 /**
221@@ -160,33 +196,40 @@ int ssh_scp_init(ssh_scp scp)
222 */
223 int ssh_scp_close(ssh_scp scp)
224 {
225- char buffer[128];
226- int err;
227- if(scp==NULL)
228- return SSH_ERROR;
229- if(scp->channel != NULL){
230- if(ssh_channel_send_eof(scp->channel) == SSH_ERROR){
231- scp->state=SSH_SCP_ERROR;
232- return SSH_ERROR;
233- }
234- /* avoid situations where data are buffered and
235- * not yet stored on disk. This can happen if the close is sent
236- * before we got the EOF back
237- */
238- while(!ssh_channel_is_eof(scp->channel)){
239- err=ssh_channel_read(scp->channel,buffer,sizeof(buffer),0);
240- if(err==SSH_ERROR || err==0)
241- break;
242+ char buffer[128] = {0};
243+ int rc;
244+
245+ if (scp == NULL) {
246+ return SSH_ERROR;
247 }
248- if(ssh_channel_close(scp->channel) == SSH_ERROR){
249- scp->state=SSH_SCP_ERROR;
250- return SSH_ERROR;
251+
252+ if (scp->channel != NULL) {
253+ if (ssh_channel_send_eof(scp->channel) == SSH_ERROR) {
254+ scp->state = SSH_SCP_ERROR;
255+ return SSH_ERROR;
256+ }
257+ /* avoid situations where data are buffered and
258+ * not yet stored on disk. This can happen if the close is sent
259+ * before we got the EOF back
260+ */
261+ while (!ssh_channel_is_eof(scp->channel)) {
262+ rc = ssh_channel_read(scp->channel, buffer, sizeof(buffer), 0);
263+ if (rc == SSH_ERROR || rc == 0) {
264+ break;
265+ }
266+ }
267+
268+ if (ssh_channel_close(scp->channel) == SSH_ERROR) {
269+ scp->state = SSH_SCP_ERROR;
270+ return SSH_ERROR;
271+ }
272+
273+ ssh_channel_free(scp->channel);
274+ scp->channel = NULL;
275 }
276- ssh_channel_free(scp->channel);
277- scp->channel=NULL;
278- }
279- scp->state=SSH_SCP_NEW;
280- return SSH_OK;
281+
282+ scp->state = SSH_SCP_NEW;
283+ return SSH_OK;
284 }
285
286 /**
287@@ -198,16 +241,22 @@ int ssh_scp_close(ssh_scp scp)
288 */
289 void ssh_scp_free(ssh_scp scp)
290 {
291- if(scp==NULL)
292- return;
293- if(scp->state != SSH_SCP_NEW)
294- ssh_scp_close(scp);
295- if(scp->channel)
296- ssh_channel_free(scp->channel);
297- SAFE_FREE(scp->location);
298- SAFE_FREE(scp->request_name);
299- SAFE_FREE(scp->warning);
300- SAFE_FREE(scp);
301+ if (scp == NULL) {
302+ return;
303+ }
304+
305+ if (scp->state != SSH_SCP_NEW) {
306+ ssh_scp_close(scp);
307+ }
308+
309+ if (scp->channel) {
310+ ssh_channel_free(scp->channel);
311+ }
312+
313+ SAFE_FREE(scp->location);
314+ SAFE_FREE(scp->request_name);
315+ SAFE_FREE(scp->warning);
316+ SAFE_FREE(scp);
317 }
318
319 /**
320@@ -224,81 +273,106 @@ void ssh_scp_free(ssh_scp scp)
321 *
322 * @see ssh_scp_leave_directory()
323 */
324-int ssh_scp_push_directory(ssh_scp scp, const char *dirname, int mode){
325- char buffer[1024];
326- int r;
327- uint8_t code;
328- char *dir;
329- char *perms;
330- if(scp==NULL)
331- return SSH_ERROR;
332- if(scp->state != SSH_SCP_WRITE_INITED){
333- ssh_set_error(scp->session,SSH_FATAL,"ssh_scp_push_directory called under invalid state");
334- return SSH_ERROR;
335- }
336- dir=ssh_basename(dirname);
337- perms=ssh_scp_string_mode(mode);
338- snprintf(buffer, sizeof(buffer), "D%s 0 %s\n", perms, dir);
339- SAFE_FREE(dir);
340- SAFE_FREE(perms);
341- r=ssh_channel_write(scp->channel,buffer,strlen(buffer));
342- if(r==SSH_ERROR){
343- scp->state=SSH_SCP_ERROR;
344- return SSH_ERROR;
345- }
346- r=ssh_channel_read(scp->channel,&code,1,0);
347- if(r<=0){
348- ssh_set_error(scp->session,SSH_FATAL, "Error reading status code: %s",ssh_get_error(scp->session));
349- scp->state=SSH_SCP_ERROR;
350- return SSH_ERROR;
351- }
352- if(code != 0){
353- ssh_set_error(scp->session,SSH_FATAL, "scp status code %ud not valid", code);
354- scp->state=SSH_SCP_ERROR;
355- return SSH_ERROR;
356- }
357- return SSH_OK;
358+int ssh_scp_push_directory(ssh_scp scp, const char *dirname, int mode)
359+{
360+ char buffer[1024] = {0};
361+ int rc;
362+ uint8_t code;
363+ char *dir = NULL;
364+ char *perms = NULL;
365+
366+ if (scp == NULL) {
367+ return SSH_ERROR;
368+ }
369+
370+ if (scp->state != SSH_SCP_WRITE_INITED) {
371+ ssh_set_error(scp->session, SSH_FATAL,
372+ "ssh_scp_push_directory called under invalid state");
373+ return SSH_ERROR;
374+ }
375+
376+ dir = ssh_basename(dirname);
377+ perms = ssh_scp_string_mode(mode);
378+ snprintf(buffer, sizeof(buffer), "D%s 0 %s\n", perms, dir);
379+ SAFE_FREE(dir);
380+ SAFE_FREE(perms);
381+
382+ rc = ssh_channel_write(scp->channel, buffer, strlen(buffer));
383+ if (rc == SSH_ERROR) {
384+ scp->state = SSH_SCP_ERROR;
385+ return SSH_ERROR;
386+ }
387+
388+ rc = ssh_channel_read(scp->channel, &code, 1, 0);
389+ if (rc <= 0) {
390+ ssh_set_error(scp->session, SSH_FATAL,
391+ "Error reading status code: %s",
392+ ssh_get_error(scp->session));
393+ scp->state = SSH_SCP_ERROR;
394+ return SSH_ERROR;
395+ }
396+
397+ if (code != 0) {
398+ ssh_set_error(scp->session, SSH_FATAL, "scp status code %ud not valid",
399+ code);
400+ scp->state = SSH_SCP_ERROR;
401+ return SSH_ERROR;
402+ }
403+
404+ return SSH_OK;
405 }
406
407 /**
408 * @brief Leave a directory.
409 *
410- * @returns SSH_OK if the directory has been left,SSH_ERROR if an
411+ * @returns SSH_OK if the directory has been left, SSH_ERROR if an
412 * error occured.
413 *
414 * @see ssh_scp_push_directory()
415 */
416- int ssh_scp_leave_directory(ssh_scp scp){
417- char buffer[]="E\n";
418- int r;
419- uint8_t code;
420- if(scp==NULL)
421- return SSH_ERROR;
422- if(scp->state != SSH_SCP_WRITE_INITED){
423- ssh_set_error(scp->session,SSH_FATAL,"ssh_scp_leave_directory called under invalid state");
424- return SSH_ERROR;
425- }
426- r=ssh_channel_write(scp->channel,buffer,strlen(buffer));
427- if(r==SSH_ERROR){
428- scp->state=SSH_SCP_ERROR;
429- return SSH_ERROR;
430- }
431- r=ssh_channel_read(scp->channel,&code,1,0);
432- if(r<=0){
433- ssh_set_error(scp->session,SSH_FATAL, "Error reading status code: %s",ssh_get_error(scp->session));
434- scp->state=SSH_SCP_ERROR;
435- return SSH_ERROR;
436- }
437- if(code != 0){
438- ssh_set_error(scp->session,SSH_FATAL, "scp status code %ud not valid", code);
439- scp->state=SSH_SCP_ERROR;
440- return SSH_ERROR;
441- }
442- return SSH_OK;
443+int ssh_scp_leave_directory(ssh_scp scp)
444+{
445+ char buffer[] = "E\n";
446+ int rc;
447+ uint8_t code;
448+
449+ if (scp == NULL) {
450+ return SSH_ERROR;
451+ }
452+
453+ if (scp->state != SSH_SCP_WRITE_INITED) {
454+ ssh_set_error(scp->session, SSH_FATAL,
455+ "ssh_scp_leave_directory called under invalid state");
456+ return SSH_ERROR;
457+ }
458+
459+ rc = ssh_channel_write(scp->channel, buffer, strlen(buffer));
460+ if (rc == SSH_ERROR) {
461+ scp->state = SSH_SCP_ERROR;
462+ return SSH_ERROR;
463+ }
464+
465+ rc = ssh_channel_read(scp->channel, &code, 1, 0);
466+ if (rc <= 0) {
467+ ssh_set_error(scp->session, SSH_FATAL, "Error reading status code: %s",
468+ ssh_get_error(scp->session));
469+ scp->state = SSH_SCP_ERROR;
470+ return SSH_ERROR;
471+ }
472+
473+ if (code != 0) {
474+ ssh_set_error(scp->session, SSH_FATAL, "scp status code %ud not valid",
475+ code);
476+ scp->state = SSH_SCP_ERROR;
477+ return SSH_ERROR;
478+ }
479+
480+ return SSH_OK;
481 }
482
483 /**
484- * @brief Initialize the sending of a file to a scp in sink mode, using a 64-bit size.
485+ * @brief Initialize the sending of a file to a scp in sink mode, using a 64-bit
486+ * size.
487 *
488 * @param[in] scp The scp handle.
489 *
490@@ -314,44 +388,61 @@ int ssh_scp_push_directory(ssh_scp scp, const char *dirname, int mode){
491 *
492 * @see ssh_scp_push_file()
493 */
494-int ssh_scp_push_file64(ssh_scp scp, const char *filename, uint64_t size, int mode){
495- char buffer[1024];
496- int r;
497- uint8_t code;
498- char *file;
499- char *perms;
500- if(scp==NULL)
501- return SSH_ERROR;
502- if(scp->state != SSH_SCP_WRITE_INITED){
503- ssh_set_error(scp->session,SSH_FATAL,"ssh_scp_push_file called under invalid state");
504- return SSH_ERROR;
505- }
506- file=ssh_basename(filename);
507- perms=ssh_scp_string_mode(mode);
508- SSH_LOG(SSH_LOG_PROTOCOL,"SCP pushing file %s, size %" PRIu64 " with permissions '%s'",file,size,perms);
509- snprintf(buffer, sizeof(buffer), "C%s %" PRIu64 " %s\n", perms, size, file);
510- SAFE_FREE(file);
511- SAFE_FREE(perms);
512- r=ssh_channel_write(scp->channel,buffer,strlen(buffer));
513- if(r==SSH_ERROR){
514- scp->state=SSH_SCP_ERROR;
515- return SSH_ERROR;
516- }
517- r=ssh_channel_read(scp->channel,&code,1,0);
518- if(r<=0){
519- ssh_set_error(scp->session,SSH_FATAL, "Error reading status code: %s",ssh_get_error(scp->session));
520- scp->state=SSH_SCP_ERROR;
521- return SSH_ERROR;
522- }
523- if(code != 0){
524- ssh_set_error(scp->session,SSH_FATAL, "scp status code %ud not valid", code);
525- scp->state=SSH_SCP_ERROR;
526- return SSH_ERROR;
527- }
528- scp->filelen = size;
529- scp->processed = 0;
530- scp->state=SSH_SCP_WRITE_WRITING;
531- return SSH_OK;
532+int ssh_scp_push_file64(ssh_scp scp, const char *filename, uint64_t size,
533+ int mode)
534+{
535+ char buffer[1024] = {0};
536+ int rc;
537+ char *file = NULL;
538+ char *perms = NULL;
539+ uint8_t code;
540+
541+ if (scp == NULL) {
542+ return SSH_ERROR;
543+ }
544+
545+ if (scp->state != SSH_SCP_WRITE_INITED) {
546+ ssh_set_error(scp->session, SSH_FATAL,
547+ "ssh_scp_push_file called under invalid state");
548+ return SSH_ERROR;
549+ }
550+
551+ file = ssh_basename(filename);
552+ perms = ssh_scp_string_mode(mode);
553+ SSH_LOG(SSH_LOG_PROTOCOL,
554+ "SCP pushing file %s, size %" PRIu64 " with permissions '%s'",
555+ file, size, perms);
556+ snprintf(buffer, sizeof(buffer), "C%s %" PRIu64 " %s\n", perms, size, file);
557+ SAFE_FREE(file);
558+ SAFE_FREE(perms);
559+
560+ rc = ssh_channel_write(scp->channel, buffer, strlen(buffer));
561+ if (rc == SSH_ERROR) {
562+ scp->state = SSH_SCP_ERROR;
563+ return SSH_ERROR;
564+ }
565+
566+ rc = ssh_channel_read(scp->channel, &code, 1, 0);
567+ if (rc <= 0) {
568+ ssh_set_error(scp->session, SSH_FATAL,
569+ "Error reading status code: %s",
570+ ssh_get_error(scp->session));
571+ scp->state = SSH_SCP_ERROR;
572+ return SSH_ERROR;
573+ }
574+
575+ if (code != 0) {
576+ ssh_set_error(scp->session, SSH_FATAL,
577+ "scp status code %ud not valid", code);
578+ scp->state = SSH_SCP_ERROR;
579+ return SSH_ERROR;
580+ }
581+
582+ scp->filelen = size;
583+ scp->processed = 0;
584+ scp->state = SSH_SCP_WRITE_WRITING;
585+
586+ return SSH_OK;
587 }
588
589 /**
590@@ -369,8 +460,9 @@ int ssh_scp_push_file64(ssh_scp scp, const char *filename, uint64_t size, int mo
591 * @returns SSH_OK if the file is ready to be sent, SSH_ERROR if an
592 * error occured.
593 */
594-int ssh_scp_push_file(ssh_scp scp, const char *filename, size_t size, int mode){
595- return ssh_scp_push_file64(scp, filename, (uint64_t) size, mode);
596+int ssh_scp_push_file(ssh_scp scp, const char *filename, size_t size, int mode)
597+{
598+ return ssh_scp_push_file64(scp, filename, (uint64_t) size, mode);
599 }
600
601 /**
602@@ -385,41 +477,60 @@ int ssh_scp_push_file(ssh_scp scp, const char *filename, size_t size, int mode){
603 *
604 * @returns The return code, SSH_ERROR a error occured.
605 */
606-int ssh_scp_response(ssh_scp scp, char **response){
607- unsigned char code;
608- int r;
609- char msg[128];
610- if(scp==NULL)
611- return SSH_ERROR;
612- r=ssh_channel_read(scp->channel,&code,1,0);
613- if(r == SSH_ERROR)
614- return SSH_ERROR;
615- if(code == 0)
616- return 0;
617- if(code > 2){
618- ssh_set_error(scp->session,SSH_FATAL, "SCP: invalid status code %ud received", code);
619- scp->state=SSH_SCP_ERROR;
620- return SSH_ERROR;
621- }
622- r=ssh_scp_read_string(scp,msg,sizeof(msg));
623- if(r==SSH_ERROR)
624- return r;
625- /* Warning */
626- if(code == 1){
627- ssh_set_error(scp->session,SSH_REQUEST_DENIED, "SCP: Warning: status code 1 received: %s", msg);
628- SSH_LOG(SSH_LOG_RARE,"SCP: Warning: status code 1 received: %s", msg);
629- if(response)
630- *response=strdup(msg);
631- return 1;
632- }
633- if(code == 2){
634- ssh_set_error(scp->session,SSH_FATAL, "SCP: Error: status code 2 received: %s", msg);
635- if(response)
636- *response=strdup(msg);
637- return 2;
638- }
639- /* Not reached */
640- return SSH_ERROR;
641+int ssh_scp_response(ssh_scp scp, char **response)
642+{
643+ unsigned char code;
644+ int rc;
645+ char msg[128] = {0};
646+
647+ if (scp == NULL) {
648+ return SSH_ERROR;
649+ }
650+
651+ rc = ssh_channel_read(scp->channel, &code, 1, 0);
652+ if (rc == SSH_ERROR) {
653+ return SSH_ERROR;
654+ }
655+
656+ if (code == 0) {
657+ return 0;
658+ }
659+
660+ if (code > 2) {
661+ ssh_set_error(scp->session, SSH_FATAL,
662+ "SCP: invalid status code %ud received", code);
663+ scp->state = SSH_SCP_ERROR;
664+ return SSH_ERROR;
665+ }
666+
667+ rc = ssh_scp_read_string(scp, msg, sizeof(msg));
668+ if (rc == SSH_ERROR) {
669+ return rc;
670+ }
671+
672+ /* Warning */
673+ if (code == 1) {
674+ ssh_set_error(scp->session, SSH_REQUEST_DENIED,
675+ "SCP: Warning: status code 1 received: %s", msg);
676+ SSH_LOG(SSH_LOG_RARE,
677+ "SCP: Warning: status code 1 received: %s", msg);
678+ if (response) {
679+ *response = strdup(msg);
680+ }
681+ return 1;
682+ }
683+
684+ if (code == 2) {
685+ ssh_set_error(scp->session, SSH_FATAL,
686+ "SCP: Error: status code 2 received: %s", msg);
687+ if (response) {
688+ *response = strdup(msg);
689+ }
690+ return 2;
691+ }
692+
693+ /* Not reached */
694+ return SSH_ERROR;
695 }
696
697 /**
698@@ -434,57 +545,72 @@ int ssh_scp_response(ssh_scp scp, char **response){
699 * @returns SSH_OK if the write was successful, SSH_ERROR an error
700 * occured while writing.
701 */
702-int ssh_scp_write(ssh_scp scp, const void *buffer, size_t len){
703- int w;
704- int r;
705- uint8_t code;
706- if(scp==NULL)
707- return SSH_ERROR;
708- if(scp->state != SSH_SCP_WRITE_WRITING){
709- ssh_set_error(scp->session,SSH_FATAL,"ssh_scp_write called under invalid state");
710- return SSH_ERROR;
711- }
712- if(scp->processed + len > scp->filelen)
713- len = (size_t) (scp->filelen - scp->processed);
714- /* hack to avoid waiting for window change */
715- r = ssh_channel_poll(scp->channel, 0);
716- if (r == SSH_ERROR) {
717- scp->state = SSH_SCP_ERROR;
718- return SSH_ERROR;
719- }
720- w=ssh_channel_write(scp->channel,buffer,len);
721- if(w != SSH_ERROR)
722- scp->processed += w;
723- else {
724- scp->state=SSH_SCP_ERROR;
725- //return=channel_get_exit_status(scp->channel);
726- return SSH_ERROR;
727- }
728- /* Far end sometimes send a status message, which we need to read
729- * and handle */
730- r = ssh_channel_poll(scp->channel,0);
731- if(r > 0){
732- r = ssh_channel_read(scp->channel, &code, 1, 0);
733- if(r == SSH_ERROR){
734- return SSH_ERROR;
735- }
736- if(code == 1 || code == 2){
737- ssh_set_error(scp->session,SSH_REQUEST_DENIED, "SCP: Error: status code %i received", code);
738- return SSH_ERROR;
739- }
740- }
741- /* Check if we arrived at end of file */
742- if(scp->processed == scp->filelen) {
743- code = 0;
744- w = ssh_channel_write(scp->channel, &code, 1);
745- if(w == SSH_ERROR){
746- scp->state = SSH_SCP_ERROR;
747- return SSH_ERROR;
748- }
749- scp->processed=scp->filelen=0;
750- scp->state=SSH_SCP_WRITE_INITED;
751- }
752- return SSH_OK;
753+int ssh_scp_write(ssh_scp scp, const void *buffer, size_t len)
754+{
755+ int w;
756+ int rc;
757+ uint8_t code;
758+
759+ if (scp == NULL) {
760+ return SSH_ERROR;
761+ }
762+
763+ if (scp->state != SSH_SCP_WRITE_WRITING) {
764+ ssh_set_error(scp->session, SSH_FATAL,
765+ "ssh_scp_write called under invalid state");
766+ return SSH_ERROR;
767+ }
768+
769+ if (scp->processed + len > scp->filelen) {
770+ len = (size_t) (scp->filelen - scp->processed);
771+ }
772+
773+ /* hack to avoid waiting for window change */
774+ rc = ssh_channel_poll(scp->channel, 0);
775+ if (rc == SSH_ERROR) {
776+ scp->state = SSH_SCP_ERROR;
777+ return SSH_ERROR;
778+ }
779+
780+ w = ssh_channel_write(scp->channel, buffer, len);
781+ if (w != SSH_ERROR) {
782+ scp->processed += w;
783+ } else {
784+ scp->state = SSH_SCP_ERROR;
785+ //return = channel_get_exit_status(scp->channel);
786+ return SSH_ERROR;
787+ }
788+
789+ /* Far end sometimes send a status message, which we need to read
790+ * and handle */
791+ rc = ssh_channel_poll(scp->channel, 0);
792+ if (rc > 0) {
793+ rc = ssh_channel_read(scp->channel, &code, 1, 0);
794+ if (rc == SSH_ERROR) {
795+ return SSH_ERROR;
796+ }
797+
798+ if (code == 1 || code == 2) {
799+ ssh_set_error(scp->session, SSH_REQUEST_DENIED,
800+ "SCP: Error: status code %i received", code);
801+ return SSH_ERROR;
802+ }
803+ }
804+
805+ /* Check if we arrived at end of file */
806+ if (scp->processed == scp->filelen) {
807+ code = 0;
808+ w = ssh_channel_write(scp->channel, &code, 1);
809+ if (w == SSH_ERROR) {
810+ scp->state = SSH_SCP_ERROR;
811+ return SSH_ERROR;
812+ }
813+
814+ scp->processed = scp->filelen = 0;
815+ scp->state = SSH_SCP_WRITE_INITED;
816+ }
817+
818+ return SSH_OK;
819 }
820
821 /**
822@@ -501,27 +627,36 @@ int ssh_scp_write(ssh_scp scp, const void *buffer, size_t len){
823 * @returns SSH_OK if the string was read, SSH_ERROR if an error
824 * occured while reading.
825 */
826-int ssh_scp_read_string(ssh_scp scp, char *buffer, size_t len){
827- size_t r=0;
828- int err=SSH_OK;
829- if(scp==NULL)
830- return SSH_ERROR;
831- while(r<len-1){
832- err=ssh_channel_read(scp->channel,&buffer[r],1,0);
833- if(err==SSH_ERROR){
834- break;
835- }
836- if(err==0){
837- ssh_set_error(scp->session,SSH_FATAL,"End of file while reading string");
838- err=SSH_ERROR;
839- break;
840- }
841- r++;
842- if(buffer[r-1] == '\n')
843- break;
844- }
845- buffer[r]=0;
846- return err;
847+int ssh_scp_read_string(ssh_scp scp, char *buffer, size_t len)
848+{
849+ size_t read = 0;
850+ int err = SSH_OK;
851+
852+ if (scp == NULL) {
853+ return SSH_ERROR;
854+ }
855+
856+ while (read < len - 1) {
857+ err = ssh_channel_read(scp->channel, &buffer[read], 1, 0);
858+ if (err == SSH_ERROR) {
859+ break;
860+ }
861+
862+ if (err == 0) {
863+ ssh_set_error(scp->session, SSH_FATAL,
864+ "End of file while reading string");
865+ err = SSH_ERROR;
866+ break;
867+ }
868+
869+ read++;
870+ if (buffer[read - 1] == '\n') {
871+ break;
872+ }
873+ }
874+
875+ buffer[read] = 0;
876+ return err;
877 }
878
879 /**
880@@ -544,90 +679,105 @@ int ssh_scp_read_string(ssh_scp scp, char *buffer, size_t len){
881 * @see ssh_scp_accept_request()
882 * @see ssh_scp_request_get_warning()
883 */
884-int ssh_scp_pull_request(ssh_scp scp){
885- char buffer[MAX_BUF_SIZE] = {0};
886- char *mode=NULL;
887- char *p,*tmp;
888- uint64_t size;
889- char *name=NULL;
890- int err;
891- if(scp==NULL)
892- return SSH_ERROR;
893- if(scp->state != SSH_SCP_READ_INITED){
894- ssh_set_error(scp->session,SSH_FATAL,"ssh_scp_pull_request called under invalid state");
895- return SSH_ERROR;
896- }
897- err=ssh_scp_read_string(scp,buffer,sizeof(buffer));
898- if(err==SSH_ERROR){
899- if(ssh_channel_is_eof(scp->channel)){
900- scp->state=SSH_SCP_TERMINATED;
901- return SSH_SCP_REQUEST_EOF;
902- }
903- return err;
904- }
905- p=strchr(buffer,'\n');
906- if(p!=NULL)
907- *p='\0';
908- SSH_LOG(SSH_LOG_PROTOCOL,"Received SCP request: '%s'",buffer);
909- switch(buffer[0]){
910+int ssh_scp_pull_request(ssh_scp scp)
911+{
912+ char buffer[MAX_BUF_SIZE] = {0};
913+ char *mode = NULL;
914+ char *p, *tmp;
915+ uint64_t size;
916+ char *name = NULL;
917+ int rc;
918+
919+ if (scp == NULL) {
920+ return SSH_ERROR;
921+ }
922+
923+ if (scp->state != SSH_SCP_READ_INITED) {
924+ ssh_set_error(scp->session, SSH_FATAL,
925+ "ssh_scp_pull_request called under invalid state");
926+ return SSH_ERROR;
927+ }
928+
929+ rc = ssh_scp_read_string(scp, buffer, sizeof(buffer));
930+ if (rc == SSH_ERROR) {
931+ if (ssh_channel_is_eof(scp->channel)) {
932+ scp->state = SSH_SCP_TERMINATED;
933+ return SSH_SCP_REQUEST_EOF;
934+ }
935+ return rc;
936+ }
937+
938+ p = strchr(buffer, '\n');
939+ if (p != NULL) {
940+ *p = '\0';
941+ }
942+
943+ SSH_LOG(SSH_LOG_PROTOCOL, "Received SCP request: '%s'", buffer);
944+ switch(buffer[0]) {
945 case 'C':
946- /* File */
947+ /* File */
948 case 'D':
949- /* Directory */
950- p=strchr(buffer,' ');
951- if(p==NULL)
952- goto error;
953- *p='\0';
954- p++;
955- //mode=strdup(&buffer[1]);
956- scp->request_mode=ssh_scp_integer_mode(&buffer[1]);
957- tmp=p;
958- p=strchr(p,' ');
959- if(p==NULL)
960- goto error;
961- *p=0;
962- size = strtoull(tmp,NULL,10);
963- p++;
964- name=strdup(p);
965- SAFE_FREE(scp->request_name);
966- scp->request_name=name;
967- if(buffer[0]=='C'){
968- scp->filelen=size;
969- scp->request_type=SSH_SCP_REQUEST_NEWFILE;
970- } else {
971- scp->filelen='0';
972- scp->request_type=SSH_SCP_REQUEST_NEWDIR;
973- }
974- scp->state=SSH_SCP_READ_REQUESTED;
975- scp->processed = 0;
976- return scp->request_type;
977- break;
978+ /* Directory */
979+ p = strchr(buffer, ' ');
980+ if (p == NULL) {
981+ goto error;
982+ }
983+ *p = '\0';
984+ p++;
985+ //mode = strdup(&buffer[1]);
986+ scp->request_mode = ssh_scp_integer_mode(&buffer[1]);
987+ tmp = p;
988+ p = strchr(p, ' ');
989+ if (p == NULL) {
990+ goto error;
991+ }
992+ *p = 0;
993+ size = strtoull(tmp, NULL, 10);
994+ p++;
995+ name = strdup(p);
996+ SAFE_FREE(scp->request_name);
997+ scp->request_name = name;
998+ if (buffer[0] == 'C') {
999+ scp->filelen = size;
1000+ scp->request_type = SSH_SCP_REQUEST_NEWFILE;
1001+ } else {
1002+ scp->filelen = '0';
1003+ scp->request_type = SSH_SCP_REQUEST_NEWDIR;
1004+ }
1005+ scp->state = SSH_SCP_READ_REQUESTED;
1006+ scp->processed = 0;
1007+ return scp->request_type;
1008+ break;
1009 case 'E':
1010- scp->request_type=SSH_SCP_REQUEST_ENDDIR;
1011- ssh_channel_write(scp->channel,"",1);
1012- return scp->request_type;
1013+ scp->request_type = SSH_SCP_REQUEST_ENDDIR;
1014+ ssh_channel_write(scp->channel, "", 1);
1015+ return scp->request_type;
1016 case 0x1:
1017- ssh_set_error(scp->session,SSH_REQUEST_DENIED,"SCP: Warning: %s",&buffer[1]);
1018- scp->request_type=SSH_SCP_REQUEST_WARNING;
1019- SAFE_FREE(scp->warning);
1020- scp->warning=strdup(&buffer[1]);
1021- return scp->request_type;
1022+ ssh_set_error(scp->session, SSH_REQUEST_DENIED,
1023+ "SCP: Warning: %s", &buffer[1]);
1024+ scp->request_type = SSH_SCP_REQUEST_WARNING;
1025+ SAFE_FREE(scp->warning);
1026+ scp->warning = strdup(&buffer[1]);
1027+ return scp->request_type;
1028 case 0x2:
1029- ssh_set_error(scp->session,SSH_FATAL,"SCP: Error: %s",&buffer[1]);
1030- return SSH_ERROR;
1031+ ssh_set_error(scp->session, SSH_FATAL,
1032+ "SCP: Error: %s", &buffer[1]);
1033+ return SSH_ERROR;
1034 case 'T':
1035- /* Timestamp */
1036+ /* Timestamp */
1037 default:
1038- ssh_set_error(scp->session,SSH_FATAL,"Unhandled message: (%d)%s",buffer[0],buffer);
1039- return SSH_ERROR;
1040- }
1041-
1042- /* a parsing error occured */
1043- error:
1044- SAFE_FREE(name);
1045- SAFE_FREE(mode);
1046- ssh_set_error(scp->session,SSH_FATAL,"Parsing error while parsing message: %s",buffer);
1047- return SSH_ERROR;
1048+ ssh_set_error(scp->session, SSH_FATAL,
1049+ "Unhandled message: (%d)%s", buffer[0], buffer);
1050+ return SSH_ERROR;
1051+ }
1052+
1053+ /* a parsing error occured */
1054+error:
1055+ SAFE_FREE(name);
1056+ SAFE_FREE(mode);
1057+ ssh_set_error(scp->session, SSH_FATAL,
1058+ "Parsing error while parsing message: %s", buffer);
1059+ return SSH_ERROR;
1060 }
1061
1062 /**
1063@@ -641,24 +791,31 @@ int ssh_scp_pull_request(ssh_scp scp){
1064 * @returns SSH_OK if the message was sent, SSH_ERROR if the sending
1065 * the message failed, or sending it in a bad state.
1066 */
1067-int ssh_scp_deny_request(ssh_scp scp, const char *reason){
1068- char buffer[MAX_BUF_SIZE];
1069- int err;
1070- if(scp==NULL)
1071- return SSH_ERROR;
1072- if(scp->state != SSH_SCP_READ_REQUESTED){
1073- ssh_set_error(scp->session,SSH_FATAL,"ssh_scp_deny_request called under invalid state");
1074- return SSH_ERROR;
1075- }
1076- snprintf(buffer,sizeof(buffer),"%c%s\n",2,reason);
1077- err=ssh_channel_write(scp->channel,buffer,strlen(buffer));
1078- if(err==SSH_ERROR) {
1079- return SSH_ERROR;
1080- }
1081- else {
1082- scp->state=SSH_SCP_READ_INITED;
1083- return SSH_OK;
1084- }
1085+int ssh_scp_deny_request(ssh_scp scp, const char *reason)
1086+{
1087+ char buffer[MAX_BUF_SIZE] = {0};
1088+ int rc;
1089+
1090+ if (scp == NULL) {
1091+ return SSH_ERROR;
1092+ }
1093+
1094+ if (scp->state != SSH_SCP_READ_REQUESTED) {
1095+ ssh_set_error(scp->session, SSH_FATAL,
1096+ "ssh_scp_deny_request called under invalid state");
1097+ return SSH_ERROR;
1098+ }
1099+
1100+ snprintf(buffer, sizeof(buffer), "%c%s\n", 2, reason);
1101+ rc = ssh_channel_write(scp->channel, buffer, strlen(buffer));
1102+ if (rc == SSH_ERROR) {
1103+ return SSH_ERROR;
1104+ }
1105+
1106+ else {
1107+ scp->state = SSH_SCP_READ_INITED;
1108+ return SSH_OK;
1109+ }
1110 }
1111
1112 /**
1113@@ -670,24 +827,32 @@ int ssh_scp_deny_request(ssh_scp scp, const char *reason){
1114 * @returns SSH_OK if the message was sent, SSH_ERROR if sending the
1115 * message failed, or sending it in a bad state.
1116 */
1117-int ssh_scp_accept_request(ssh_scp scp){
1118- char buffer[]={0x00};
1119- int err;
1120- if(scp==NULL)
1121- return SSH_ERROR;
1122- if(scp->state != SSH_SCP_READ_REQUESTED){
1123- ssh_set_error(scp->session,SSH_FATAL,"ssh_scp_deny_request called under invalid state");
1124- return SSH_ERROR;
1125- }
1126- err=ssh_channel_write(scp->channel,buffer,1);
1127- if(err==SSH_ERROR) {
1128- return SSH_ERROR;
1129- }
1130- if(scp->request_type==SSH_SCP_REQUEST_NEWFILE)
1131- scp->state=SSH_SCP_READ_READING;
1132- else
1133- scp->state=SSH_SCP_READ_INITED;
1134- return SSH_OK;
1135+int ssh_scp_accept_request(ssh_scp scp)
1136+{
1137+ char buffer[] = {0x00};
1138+ int rc;
1139+ if (scp == NULL) {
1140+ return SSH_ERROR;
1141+ }
1142+
1143+ if (scp->state != SSH_SCP_READ_REQUESTED) {
1144+ ssh_set_error(scp->session, SSH_FATAL,
1145+ "ssh_scp_deny_request called under invalid state");
1146+ return SSH_ERROR;
1147+ }
1148+
1149+ rc = ssh_channel_write(scp->channel, buffer, 1);
1150+ if (rc == SSH_ERROR) {
1151+ return SSH_ERROR;
1152+ }
1153+
1154+ if (scp->request_type == SSH_SCP_REQUEST_NEWFILE) {
1155+ scp->state = SSH_SCP_READ_READING;
1156+ } else {
1157+ scp->state = SSH_SCP_READ_INITED;
1158+ }
1159+
1160+ return SSH_OK;
1161 }
1162
1163 /** @brief Read from a remote scp file
1164@@ -700,48 +865,64 @@ int ssh_scp_accept_request(ssh_scp scp){
1165 * @returns The nNumber of bytes read, SSH_ERROR if an error occured
1166 * while reading.
1167 */
1168-int ssh_scp_read(ssh_scp scp, void *buffer, size_t size){
1169- int r;
1170- int code;
1171- if(scp==NULL)
1172- return SSH_ERROR;
1173- if(scp->state == SSH_SCP_READ_REQUESTED && scp->request_type == SSH_SCP_REQUEST_NEWFILE){
1174- r=ssh_scp_accept_request(scp);
1175- if(r==SSH_ERROR)
1176- return r;
1177- }
1178- if(scp->state != SSH_SCP_READ_READING){
1179- ssh_set_error(scp->session,SSH_FATAL,"ssh_scp_read called under invalid state");
1180- return SSH_ERROR;
1181- }
1182- if(scp->processed + size > scp->filelen)
1183- size = (size_t) (scp->filelen - scp->processed);
1184- if(size > 65536)
1185- size=65536; /* avoid too large reads */
1186- r=ssh_channel_read(scp->channel,buffer,size,0);
1187- if(r != SSH_ERROR)
1188- scp->processed += r;
1189- else {
1190- scp->state=SSH_SCP_ERROR;
1191- return SSH_ERROR;
1192- }
1193- /* Check if we arrived at end of file */
1194- if(scp->processed == scp->filelen) {
1195- scp->processed=scp->filelen=0;
1196- ssh_channel_write(scp->channel,"",1);
1197- code=ssh_scp_response(scp,NULL);
1198- if(code == 0){
1199- scp->state=SSH_SCP_READ_INITED;
1200- return r;
1201- }
1202- if(code==1){
1203- scp->state=SSH_SCP_READ_INITED;
1204- return SSH_ERROR;
1205- }
1206- scp->state=SSH_SCP_ERROR;
1207- return SSH_ERROR;
1208- }
1209- return r;
1210+int ssh_scp_read(ssh_scp scp, void *buffer, size_t size)
1211+{
1212+ int rc;
1213+ int code;
1214+
1215+ if (scp == NULL) {
1216+ return SSH_ERROR;
1217+ }
1218+
1219+ if (scp->state == SSH_SCP_READ_REQUESTED &&
1220+ scp->request_type == SSH_SCP_REQUEST_NEWFILE)
1221+ {
1222+ rc = ssh_scp_accept_request(scp);
1223+ if (rc == SSH_ERROR) {
1224+ return rc;
1225+ }
1226+ }
1227+
1228+ if (scp->state != SSH_SCP_READ_READING) {
1229+ ssh_set_error(scp->session, SSH_FATAL,
1230+ "ssh_scp_read called under invalid state");
1231+ return SSH_ERROR;
1232+ }
1233+
1234+ if (scp->processed + size > scp->filelen) {
1235+ size = (size_t) (scp->filelen - scp->processed);
1236+ }
1237+
1238+ if (size > 65536) {
1239+ size = 65536; /* avoid too large reads */
1240+ }
1241+
1242+ rc = ssh_channel_read(scp->channel, buffer, size, 0);
1243+ if (rc != SSH_ERROR) {
1244+ scp->processed += rc;
1245+ } else {
1246+ scp->state = SSH_SCP_ERROR;
1247+ return SSH_ERROR;
1248+ }
1249+
1250+ /* Check if we arrived at end of file */
1251+ if (scp->processed == scp->filelen) {
1252+ scp->processed = scp->filelen = 0;
1253+ ssh_channel_write(scp->channel, "", 1);
1254+ code = ssh_scp_response(scp, NULL);
1255+ if (code == 0) {
1256+ scp->state = SSH_SCP_READ_INITED;
1257+ return rc;
1258+ }
1259+ if (code == 1) {
1260+ scp->state = SSH_SCP_READ_INITED;
1261+ return SSH_ERROR;
1262+ }
1263+ scp->state = SSH_SCP_ERROR;
1264+ return SSH_ERROR;
1265+ }
1266+
1267+ return rc;
1268 }
1269
1270 /**
1271@@ -751,10 +932,13 @@ int ssh_scp_read(ssh_scp scp, void *buffer, size_t size){
1272 * @returns The file name, NULL on error. The string should not be
1273 * freed.
1274 */
1275-const char *ssh_scp_request_get_filename(ssh_scp scp){
1276- if(scp==NULL)
1277- return NULL;
1278- return scp->request_name;
1279+const char *ssh_scp_request_get_filename(ssh_scp scp)
1280+{
1281+ if (scp == NULL) {
1282+ return NULL;
1283+ }
1284+
1285+ return scp->request_name;
1286 }
1287
1288 /**
1289@@ -763,10 +947,13 @@ const char *ssh_scp_request_get_filename(ssh_scp scp){
1290 *
1291 * @returns The UNIX permission, e.g 0644, -1 on error.
1292 */
1293-int ssh_scp_request_get_permissions(ssh_scp scp){
1294- if(scp==NULL)
1295- return -1;
1296- return scp->request_mode;
1297+int ssh_scp_request_get_permissions(ssh_scp scp)
1298+{
1299+ if (scp == NULL) {
1300+ return -1;
1301+ }
1302+
1303+ return scp->request_mode;
1304 }
1305
1306 /** @brief Get the size of the file being pushed from the other party.
1307@@ -776,20 +963,24 @@ int ssh_scp_request_get_permissions(ssh_scp scp){
1308 * be truncated.
1309 * @see ssh_scp_request_get_size64()
1310 */
1311-size_t ssh_scp_request_get_size(ssh_scp scp){
1312- if(scp==NULL)
1313- return 0;
1314- return (size_t)scp->filelen;
1315+size_t ssh_scp_request_get_size(ssh_scp scp)
1316+{
1317+ if (scp == NULL) {
1318+ return 0;
1319+ }
1320+ return (size_t)scp->filelen;
1321 }
1322
1323 /** @brief Get the size of the file being pushed from the other party.
1324 *
1325 * @returns The numeric size of the file being read.
1326 */
1327-uint64_t ssh_scp_request_get_size64(ssh_scp scp){
1328- if(scp==NULL)
1329- return 0;
1330- return scp->filelen;
1331+uint64_t ssh_scp_request_get_size64(ssh_scp scp)
1332+{
1333+ if (scp == NULL) {
1334+ return 0;
1335+ }
1336+ return scp->filelen;
1337 }
1338
1339 /**
1340@@ -799,9 +990,10 @@ uint64_t ssh_scp_request_get_size64(ssh_scp scp){
1341 *
1342 * @returns An integer value, e.g. 420 for "0644".
1343 */
1344-int ssh_scp_integer_mode(const char *mode){
1345- int value=strtoul(mode,NULL,8) & 0xffff;
1346- return value;
1347+int ssh_scp_integer_mode(const char *mode)
1348+{
1349+ int value = strtoul(mode, NULL, 8) & 0xffff;
1350+ return value;
1351 }
1352
1353 /**
1354@@ -812,10 +1004,11 @@ int ssh_scp_integer_mode(const char *mode){
1355 * @returns A pointer to a malloc'ed string containing the scp mode,
1356 * e.g. "0644".
1357 */
1358-char *ssh_scp_string_mode(int mode){
1359- char buffer[16];
1360- snprintf(buffer,sizeof(buffer),"%.4o",mode);
1361- return strdup(buffer);
1362+char *ssh_scp_string_mode(int mode)
1363+{
1364+ char buffer[16] = {0};
1365+ snprintf(buffer, sizeof(buffer), "%.4o", mode);
1366+ return strdup(buffer);
1367 }
1368
1369 /**
1370@@ -826,10 +1019,13 @@ char *ssh_scp_string_mode(int mode){
1371 * @returns A warning string, or NULL on error. The string should
1372 * not be freed.
1373 */
1374-const char *ssh_scp_request_get_warning(ssh_scp scp){
1375- if(scp==NULL)
1376- return NULL;
1377- return scp->warning;
1378+const char *ssh_scp_request_get_warning(ssh_scp scp)
1379+{
1380+ if (scp == NULL) {
1381+ return NULL;
1382+ }
1383+
1384+ return scp->warning;
1385 }
1386
1387 /** @} */
1388--
1389cgit v1.2.1
1390
1391From 82c375b7c99141a5495e62060e0b7f9c97981e7e Mon Sep 17 00:00:00 2001
1392From: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
1393Date: Fri, 25 Oct 2019 13:24:28 +0200
1394Subject: CVE-2019-14889: scp: Log SCP warnings received from the server
1395
1396Fixes T181
1397
1398Previously, warnings received from the server were ignored. With this
1399change the warning message sent by the server will be logged.
1400
1401Signed-off-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
1402Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
1403(cherry picked from commit c75d417d06867fd792b788e6281334621c2cd335)
1404---
1405 src/scp.c | 75 ++++++++++-----------------------------------------------------
1406 1 file changed, 11 insertions(+), 64 deletions(-)
1407
1408diff --git a/src/scp.c b/src/scp.c
1409index 5de0e6ff..166f3d2f 100644
1410--- a/src/scp.c
1411+++ b/src/scp.c
1412@@ -113,7 +113,6 @@ int ssh_scp_init(ssh_scp scp)
1413 {
1414 int rc;
1415 char execbuffer[1024] = {0};
1416- uint8_t code;
1417
1418 if (scp == NULL) {
1419 return SSH_ERROR;
1420@@ -157,19 +156,8 @@ int ssh_scp_init(ssh_scp scp)
1421 }
1422
1423 if (scp->mode == SSH_SCP_WRITE) {
1424- rc = ssh_channel_read(scp->channel, &code, 1, 0);
1425- if (rc <= 0) {
1426- ssh_set_error(scp->session, SSH_FATAL,
1427- "Error reading status code: %s",
1428- ssh_get_error(scp->session));
1429- scp->state = SSH_SCP_ERROR;
1430- return SSH_ERROR;
1431- }
1432-
1433- if (code != 0) {
1434- ssh_set_error(scp->session, SSH_FATAL,
1435- "scp status code %ud not valid", code);
1436- scp->state = SSH_SCP_ERROR;
1437+ rc = ssh_scp_response(scp, NULL);
1438+ if (rc != 0) {
1439 return SSH_ERROR;
1440 }
1441 } else {
1442@@ -277,7 +265,6 @@ int ssh_scp_push_directory(ssh_scp scp, const char *dirname, int mode)
1443 {
1444 char buffer[1024] = {0};
1445 int rc;
1446- uint8_t code;
1447 char *dir = NULL;
1448 char *perms = NULL;
1449
1450@@ -303,19 +290,8 @@ int ssh_scp_push_directory(ssh_scp scp, const char *dirname, int mode)
1451 return SSH_ERROR;
1452 }
1453
1454- rc = ssh_channel_read(scp->channel, &code, 1, 0);
1455- if (rc <= 0) {
1456- ssh_set_error(scp->session, SSH_FATAL,
1457- "Error reading status code: %s",
1458- ssh_get_error(scp->session));
1459- scp->state = SSH_SCP_ERROR;
1460- return SSH_ERROR;
1461- }
1462-
1463- if (code != 0) {
1464- ssh_set_error(scp->session, SSH_FATAL, "scp status code %ud not valid",
1465- code);
1466- scp->state = SSH_SCP_ERROR;
1467+ rc = ssh_scp_response(scp, NULL);
1468+ if (rc != 0) {
1469 return SSH_ERROR;
1470 }
1471
1472@@ -334,7 +310,6 @@ int ssh_scp_leave_directory(ssh_scp scp)
1473 {
1474 char buffer[] = "E\n";
1475 int rc;
1476- uint8_t code;
1477
1478 if (scp == NULL) {
1479 return SSH_ERROR;
1480@@ -352,18 +327,8 @@ int ssh_scp_leave_directory(ssh_scp scp)
1481 return SSH_ERROR;
1482 }
1483
1484- rc = ssh_channel_read(scp->channel, &code, 1, 0);
1485- if (rc <= 0) {
1486- ssh_set_error(scp->session, SSH_FATAL, "Error reading status code: %s",
1487- ssh_get_error(scp->session));
1488- scp->state = SSH_SCP_ERROR;
1489- return SSH_ERROR;
1490- }
1491-
1492- if (code != 0) {
1493- ssh_set_error(scp->session, SSH_FATAL, "scp status code %ud not valid",
1494- code);
1495- scp->state = SSH_SCP_ERROR;
1496+ rc = ssh_scp_response(scp, NULL);
1497+ if (rc != 0) {
1498 return SSH_ERROR;
1499 }
1500
1501@@ -395,7 +360,6 @@ int ssh_scp_push_file64(ssh_scp scp, const char *filename, uint64_t size,
1502 int rc;
1503 char *file = NULL;
1504 char *perms = NULL;
1505- uint8_t code;
1506
1507 if (scp == NULL) {
1508 return SSH_ERROR;
1509@@ -422,19 +386,8 @@ int ssh_scp_push_file64(ssh_scp scp, const char *filename, uint64_t size,
1510 return SSH_ERROR;
1511 }
1512
1513- rc = ssh_channel_read(scp->channel, &code, 1, 0);
1514- if (rc <= 0) {
1515- ssh_set_error(scp->session, SSH_FATAL,
1516- "Error reading status code: %s",
1517- ssh_get_error(scp->session));
1518- scp->state = SSH_SCP_ERROR;
1519- return SSH_ERROR;
1520- }
1521-
1522- if (code != 0) {
1523- ssh_set_error(scp->session, SSH_FATAL,
1524- "scp status code %ud not valid", code);
1525- scp->state = SSH_SCP_ERROR;
1526+ rc = ssh_scp_response(scp, NULL);
1527+ if (rc != 0) {
1528 return SSH_ERROR;
1529 }
1530
1531@@ -498,7 +451,7 @@ int ssh_scp_response(ssh_scp scp, char **response)
1532
1533 if (code > 2) {
1534 ssh_set_error(scp->session, SSH_FATAL,
1535- "SCP: invalid status code %ud received", code);
1536+ "SCP: invalid status code %u received", code);
1537 scp->state = SSH_SCP_ERROR;
1538 return SSH_ERROR;
1539 }
1540@@ -585,14 +538,8 @@ int ssh_scp_write(ssh_scp scp, const void *buffer, size_t len)
1541 * and handle */
1542 rc = ssh_channel_poll(scp->channel, 0);
1543 if (rc > 0) {
1544- rc = ssh_channel_read(scp->channel, &code, 1, 0);
1545- if (rc == SSH_ERROR) {
1546- return SSH_ERROR;
1547- }
1548-
1549- if (code == 1 || code == 2) {
1550- ssh_set_error(scp->session, SSH_REQUEST_DENIED,
1551- "SCP: Error: status code %i received", code);
1552+ rc = ssh_scp_response(scp, NULL);
1553+ if (rc != 0) {
1554 return SSH_ERROR;
1555 }
1556 }
1557--
1558cgit v1.2.1
1559
1560From 2ba1dea5493fb2f5a5be2dd263ce46ccb5f8ec76 Mon Sep 17 00:00:00 2001
1561From: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
1562Date: Tue, 22 Oct 2019 16:08:24 +0200
1563Subject: CVE-2019-14889: misc: Add function to quote file names
1564
1565The added function quote file names strings to be used in a shell.
1566Special cases are treated for the charactes '\'' and '!'.
1567
1568Fixes T181
1569
1570Signed-off-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
1571Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
1572(cherry picked from commit c4ad1aba9860e02fe03ef3f58a047964e9e765fc)
1573---
1574 include/libssh/misc.h | 8 +++
1575 src/misc.c | 184 ++++++++++++++++++++++++++++++++++++++++++++++++++
1576 2 files changed, 192 insertions(+)
1577
1578diff --git a/include/libssh/misc.h b/include/libssh/misc.h
1579index bc50cff8..0531d4f3 100644
1580--- a/include/libssh/misc.h
1581+++ b/include/libssh/misc.h
1582@@ -50,6 +50,12 @@ struct ssh_timestamp {
1583 long useconds;
1584 };
1585
1586+enum ssh_quote_state_e {
1587+ NO_QUOTE,
1588+ SINGLE_QUOTE,
1589+ DOUBLE_QUOTE
1590+};
1591+
1592 struct ssh_list *ssh_list_new(void);
1593 void ssh_list_free(struct ssh_list *list);
1594 struct ssh_iterator *ssh_list_get_iterator(const struct ssh_list *list);
1595@@ -81,4 +87,6 @@ int ssh_timeout_update(struct ssh_timestamp *ts, int timeout);
1596
1597 int ssh_match_group(const char *group, const char *object);
1598
1599+int ssh_quote_file_name(const char *file_name, char *buf, size_t buf_len);
1600+
1601 #endif /* MISC_H_ */
1602diff --git a/src/misc.c b/src/misc.c
1603index 18c9745e..b042b46d 100644
1604--- a/src/misc.c
1605+++ b/src/misc.c
1606@@ -1108,4 +1108,188 @@ char *strndup(const char *s, size_t n)
1607 }
1608 #endif /* ! HAVE_STRNDUP */
1609
1610+/**
1611+ * @internal
1612+ *
1613+ * @brief Quote file name to be used on shell.
1614+ *
1615+ * Try to put the given file name between single quotes. There are special
1616+ * cases:
1617+ *
1618+ * - When the '\'' char is found in the file name, it is double quoted
1619+ * - example:
1620+ * input: a'b
1621+ * output: 'a'"'"'b'
1622+ * - When the '!' char is found in the file name, it is replaced by an unquoted
1623+ * verbatim char "\!"
1624+ * - example:
1625+ * input: a!b
1626+ * output 'a'\!'b'
1627+ *
1628+ * @param[in] file_name File name string to be quoted before used on shell
1629+ * @param[out] buf Buffer to receive the final quoted file name. Must
1630+ * have room for the final quoted string. The maximum
1631+ * output length would be (3 * strlen(file_name) + 1)
1632+ * since in the worst case each character would be
1633+ * replaced by 3 characters, plus the terminating '\0'.
1634+ * @param[in] buf_len The size of the provided output buffer
1635+ *
1636+ * @returns SSH_ERROR on error; length of the resulting string not counting the
1637+ * string terminator '\0'
1638+ * */
1639+int ssh_quote_file_name(const char *file_name, char *buf, size_t buf_len)
1640+{
1641+ const char *src = NULL;
1642+ char *dst = NULL;
1643+ size_t required_buf_len;
1644+
1645+ enum ssh_quote_state_e state = NO_QUOTE;
1646+
1647+ if (file_name == NULL || buf == NULL || buf_len == 0) {
1648+ SSH_LOG(SSH_LOG_WARNING, "Invalid parameter");
1649+ return SSH_ERROR;
1650+ }
1651+
1652+ /* Only allow file names smaller than 32kb. */
1653+ if (strlen(file_name) > 32 * 1024) {
1654+ SSH_LOG(SSH_LOG_WARNING, "File name too long");
1655+ return SSH_ERROR;
1656+ }
1657+
1658+ /* Paranoia check */
1659+ required_buf_len = (size_t)3 * strlen(file_name) + 1;
1660+ if (required_buf_len > buf_len) {
1661+ SSH_LOG(SSH_LOG_WARNING, "Buffer too small");
1662+ return SSH_ERROR;
1663+ }
1664+
1665+ src = file_name;
1666+ dst = buf;
1667+
1668+ while ((*src != '\0')) {
1669+ switch (*src) {
1670+
1671+ /* The '\'' char is double quoted */
1672+
1673+ case '\'':
1674+ switch (state) {
1675+ case NO_QUOTE:
1676+ /* Start a new double quoted string. The '\'' char will be
1677+ * copied to the beginning of it at the end of the loop. */
1678+ *dst++ = '"';
1679+ break;
1680+ case SINGLE_QUOTE:
1681+ /* Close the current single quoted string and start a new double
1682+ * quoted string. The '\'' char will be copied to the beginning
1683+ * of it at the end of the loop. */
1684+ *dst++ = '\'';
1685+ *dst++ = '"';
1686+ break;
1687+ case DOUBLE_QUOTE:
1688+ /* If already in the double quoted string, keep copying the
1689+ * sequence of chars. */
1690+ break;
1691+ default:
1692+ /* Should never be reached */
1693+ goto error;
1694+ }
1695+
1696+ /* When the '\'' char is found, the resulting state will be
1697+ * DOUBLE_QUOTE in any case*/
1698+ state = DOUBLE_QUOTE;
1699+ break;
1700+
1701+ /* The '!' char is replaced by unquoted "\!" */
1702+
1703+ case '!':
1704+ switch (state) {
1705+ case NO_QUOTE:
1706+ /* The '!' char is interpreted in some shells (e.g. CSH) even
1707+ * when is quoted with single quotes. Replace it with unquoted
1708+ * "\!" which is correctly interpreted as the '!' character. */
1709+ *dst++ = '\\';
1710+ break;
1711+ case SINGLE_QUOTE:
1712+ /* Close the current quoted string and replace '!' for unquoted
1713+ * "\!" */
1714+ *dst++ = '\'';
1715+ *dst++ = '\\';
1716+ break;
1717+ case DOUBLE_QUOTE:
1718+ /* Close current quoted string and replace "!" for unquoted
1719+ * "\!" */
1720+ *dst++ = '"';
1721+ *dst++ = '\\';
1722+ break;
1723+ default:
1724+ /* Should never be reached */
1725+ goto error;
1726+ }
1727+
1728+ /* When the '!' char is found, the resulting state will be NO_QUOTE
1729+ * in any case*/
1730+ state = NO_QUOTE;
1731+ break;
1732+
1733+ /* Ordinary chars are single quoted */
1734+
1735+ default:
1736+ switch (state) {
1737+ case NO_QUOTE:
1738+ /* Start a new single quoted string */
1739+ *dst++ = '\'';
1740+ break;
1741+ case SINGLE_QUOTE:
1742+ /* If already in the single quoted string, keep copying the
1743+ * sequence of chars. */
1744+ break;
1745+ case DOUBLE_QUOTE:
1746+ /* Close current double quoted string and start a new single
1747+ * quoted string. */
1748+ *dst++ = '"';
1749+ *dst++ = '\'';
1750+ break;
1751+ default:
1752+ /* Should never be reached */
1753+ goto error;
1754+ }
1755+
1756+ /* When an ordinary char is found, the resulting state will be
1757+ * SINGLE_QUOTE in any case*/
1758+ state = SINGLE_QUOTE;
1759+ break;
1760+ }
1761+
1762+ /* Copy the current char to output */
1763+ *dst++ = *src++;
1764+ }
1765+
1766+ /* Close the quoted string when necessary */
1767+
1768+ switch (state) {
1769+ case NO_QUOTE:
1770+ /* No open string */
1771+ break;
1772+ case SINGLE_QUOTE:
1773+ /* Close current single quoted string */
1774+ *dst++ = '\'';
1775+ break;
1776+ case DOUBLE_QUOTE:
1777+ /* Close current double quoted string */
1778+ *dst++ = '"';
1779+ break;
1780+ default:
1781+ /* Should never be reached */
1782+ goto error;
1783+ }
1784+
1785+ /* Put the string terminator */
1786+ *dst = '\0';
1787+
1788+ return dst - buf;
1789+
1790+error:
1791+ return SSH_ERROR;
1792+}
1793+
1794 /** @} */
1795--
1796cgit v1.2.1
1797
1798From 391c78de9d0f7baec3a44d86a76f4e1324eb9529 Mon Sep 17 00:00:00 2001
1799From: Andreas Schneider <asn@cryptomilk.org>
1800Date: Fri, 6 Dec 2019 09:40:30 +0100
1801Subject: CVE-2019-14889: scp: Don't allow file path longer than 32kb
1802
1803Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
1804Reviewed-by: Jakub Jelen <jjelen@redhat.com>
1805(cherry picked from commit 0b5ee397260b6e08dffa2c1ce515a153aaeda765)
1806---
1807 src/scp.c | 6 ++++++
1808 1 file changed, 6 insertions(+)
1809
1810diff --git a/src/scp.c b/src/scp.c
1811index 166f3d2f..4b00aa5f 100644
1812--- a/src/scp.c
1813+++ b/src/scp.c
1814@@ -80,6 +80,12 @@ ssh_scp ssh_scp_new(ssh_session session, int mode, const char *location)
1815 goto error;
1816 }
1817
1818+ if (strlen(location) > 32 * 1024) {
1819+ ssh_set_error(session, SSH_FATAL,
1820+ "Location path is too long");
1821+ goto error;
1822+ }
1823+
1824 scp->location = strdup(location);
1825 if (scp->location == NULL) {
1826 ssh_set_error(session, SSH_FATAL,
1827--
1828cgit v1.2.1
1829
1830From b0edec4e8d01ad73b0d26ad4070d7e1a1e86dfc8 Mon Sep 17 00:00:00 2001
1831From: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
1832Date: Thu, 31 Oct 2019 18:10:27 +0100
1833Subject: CVE-2019-14889: scp: Quote location to be used on shell
1834
1835Single quote file paths to be used on commands to be executed on remote
1836shell.
1837
1838Fixes T181
1839
1840Signed-off-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
1841Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
1842(cherry picked from commit 3830c7ae6eec751b7618d3fc159cb5bb3c8806a6)
1843---
1844 src/scp.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++------
1845 1 file changed, 56 insertions(+), 6 deletions(-)
1846
1847diff --git a/src/scp.c b/src/scp.c
1848index 4b00aa5f..652551e3 100644
1849--- a/src/scp.c
1850+++ b/src/scp.c
1851@@ -29,6 +29,7 @@
1852
1853 #include "libssh/priv.h"
1854 #include "libssh/scp.h"
1855+#include "libssh/misc.h"
1856
1857 /**
1858 * @defgroup libssh_scp The SSH scp functions
1859@@ -119,6 +120,9 @@ int ssh_scp_init(ssh_scp scp)
1860 {
1861 int rc;
1862 char execbuffer[1024] = {0};
1863+ char *quoted_location = NULL;
1864+ size_t quoted_location_len = 0;
1865+ size_t scp_location_len;
1866
1867 if (scp == NULL) {
1868 return SSH_ERROR;
1869@@ -130,33 +134,79 @@ int ssh_scp_init(ssh_scp scp)
1870 return SSH_ERROR;
1871 }
1872
1873- SSH_LOG(SSH_LOG_PROTOCOL,
1874- "Initializing scp session %s %son location '%s'",
1875+ if (scp->location == NULL) {
1876+ ssh_set_error(scp->session, SSH_FATAL,
1877+ "Invalid scp context: location is NULL");
1878+ return SSH_ERROR;
1879+ }
1880+
1881+ SSH_LOG(SSH_LOG_PROTOCOL, "Initializing scp session %s %son location '%s'",
1882 scp->mode == SSH_SCP_WRITE?"write":"read",
1883- scp->recursive?"recursive ":"",
1884+ scp->recursive ? "recursive " : "",
1885 scp->location);
1886
1887 scp->channel = ssh_channel_new(scp->session);
1888 if (scp->channel == NULL) {
1889+ ssh_set_error(scp->session, SSH_FATAL,
1890+ "Channel creation failed for scp");
1891 scp->state = SSH_SCP_ERROR;
1892 return SSH_ERROR;
1893 }
1894
1895 rc = ssh_channel_open_session(scp->channel);
1896 if (rc == SSH_ERROR) {
1897+ ssh_set_error(scp->session, SSH_FATAL,
1898+ "Failed to open channel for scp");
1899+ scp->state = SSH_SCP_ERROR;
1900+ return SSH_ERROR;
1901+ }
1902+
1903+ /* In the worst case, each character would be replaced by 3 plus the string
1904+ * terminator '\0' */
1905+ scp_location_len = strlen(scp->location);
1906+ quoted_location_len = ((size_t)3 * scp_location_len) + 1;
1907+ /* Paranoia check */
1908+ if (quoted_location_len < scp_location_len) {
1909+ ssh_set_error(scp->session, SSH_FATAL,
1910+ "Buffer overflow detected");
1911+ scp->state = SSH_SCP_ERROR;
1912+ return SSH_ERROR;
1913+ }
1914+
1915+ quoted_location = (char *)calloc(1, quoted_location_len);
1916+ if (quoted_location == NULL) {
1917+ ssh_set_error(scp->session, SSH_FATAL,
1918+ "Failed to allocate memory for quoted location");
1919+ scp->state = SSH_SCP_ERROR;
1920+ return SSH_ERROR;
1921+ }
1922+
1923+ rc = ssh_quote_file_name(scp->location, quoted_location,
1924+ quoted_location_len);
1925+ if (rc <= 0) {
1926+ ssh_set_error(scp->session, SSH_FATAL,
1927+ "Failed to single quote command location");
1928+ SAFE_FREE(quoted_location);
1929 scp->state = SSH_SCP_ERROR;
1930 return SSH_ERROR;
1931 }
1932
1933 if (scp->mode == SSH_SCP_WRITE) {
1934 snprintf(execbuffer, sizeof(execbuffer), "scp -t %s %s",
1935- scp->recursive ? "-r":"", scp->location);
1936+ scp->recursive ? "-r" : "", quoted_location);
1937 } else {
1938 snprintf(execbuffer, sizeof(execbuffer), "scp -f %s %s",
1939- scp->recursive ? "-r":"", scp->location);
1940+ scp->recursive ? "-r" : "", quoted_location);
1941 }
1942
1943- if (ssh_channel_request_exec(scp->channel, execbuffer) == SSH_ERROR) {
1944+ SAFE_FREE(quoted_location);
1945+
1946+ SSH_LOG(SSH_LOG_DEBUG, "Executing command: %s", execbuffer);
1947+
1948+ rc = ssh_channel_request_exec(scp->channel, execbuffer);
1949+ if (rc == SSH_ERROR){
1950+ ssh_set_error(scp->session, SSH_FATAL,
1951+ "Failed executing command: %s", execbuffer);
1952 scp->state = SSH_SCP_ERROR;
1953 return SSH_ERROR;
1954 }
1955--
1956cgit v1.2.1
1957