comparison lib/sshv2.c @ 654:f6e2ec8faf56

2004-12-31 Brian Masney <masneyb@gftp.org> * lib/sshv2.c (sshv2_read_response) - added debugging messages if compiled with -DDEBUG. Added sshv2_response_return_code() and sshv2_buffer_get_int64(). (sshv2_buffer_get_int32) - added check_response argument to this function. This suppresses a signed/unsigned mismatch warning from gcc. (sshv2_decode_file_attributes) - decode all of the attributes that are returned from the server. (sshv2_get_next_file) - don't look at the long file name returned from the server. This also fixes a bug where no files were being returned to the user when the remote server was running the commercial SSH daemon
author masneyb
date Fri, 31 Dec 2004 22:55:23 +0000
parents 4ab29ec829bf
children 1b28a63d125a
comparison
equal deleted inserted replaced
653:07dc89f95076 654:f6e2ec8faf56
769 return (numread); 769 return (numread);
770 rem -= numread; 770 rem -= numread;
771 pos += numread; 771 pos += numread;
772 } 772 }
773 773
774 #ifdef DEBUG
775 printf ("\rReceived message: ");
776 for (rem=0; rem<message->length; rem++)
777 printf ("%x ", message->buffer[rem] & 0xff);
778 printf ("\n");
779 #endif
780
774 message->buffer[message->length] = '\0'; 781 message->buffer[message->length] = '\0';
775 782
776 sshv2_log_command (request, gftp_logging_recv, message->command, 783 sshv2_log_command (request, gftp_logging_recv, message->command,
777 message->buffer, message->length); 784 message->buffer, message->length);
778 785
835 return (ret); 842 return (ret);
836 } 843 }
837 844
838 845
839 static int 846 static int
847 sshv2_response_return_code (gftp_request * request, sshv2_message * message,
848 unsigned int ret)
849 {
850 switch (ret)
851 {
852 case SSH_FX_OK:
853 case SSH_FX_EOF:
854 case SSH_FX_NO_SUCH_FILE:
855 case SSH_FX_PERMISSION_DENIED:
856 case SSH_FX_FAILURE:
857 case SSH_FX_OP_UNSUPPORTED:
858 return (GFTP_ERETRYABLE);
859 default:
860 return (sshv2_wrong_response (request, message));
861 }
862 }
863
864
865 static int
840 sshv2_buffer_get_int32 (gftp_request * request, sshv2_message * message, 866 sshv2_buffer_get_int32 (gftp_request * request, sshv2_message * message,
841 int expected_response, guint32 * num) 867 unsigned int expected_response, int check_response,
868 guint32 * num)
842 { 869 {
843 guint32 snum; 870 guint32 snum;
844 871
845 if (message->end - message->pos < 4) 872 if (message->end - message->pos < 4)
846 return (sshv2_wrong_response (request, message)); 873 return (sshv2_wrong_response (request, message));
847 874
848 memcpy (&snum, message->pos, 4); 875 memcpy (&snum, message->pos, 4);
849 snum = ntohl (snum); 876 snum = ntohl (snum);
850 message->pos += 4; 877 message->pos += 4;
851 878
852 if (expected_response >= 0 && snum != expected_response) 879 if (check_response && snum != expected_response)
853 { 880 return (sshv2_response_return_code (request, message, snum));
854 switch (snum)
855 {
856 case SSH_FX_OK:
857 case SSH_FX_EOF:
858 case SSH_FX_NO_SUCH_FILE:
859 case SSH_FX_PERMISSION_DENIED:
860 case SSH_FX_FAILURE:
861 case SSH_FX_OP_UNSUPPORTED:
862 return (GFTP_ERETRYABLE);
863 default:
864 return (sshv2_wrong_response (request, message));
865 }
866 }
867 881
868 if (num != NULL) 882 if (num != NULL)
869 *num = snum; 883 *num = snum;
870 884
871 return (0); 885 return (0);
872 } 886 }
873 887
874 888
889 static int
890 sshv2_buffer_get_int64 (gftp_request * request, sshv2_message * message,
891 unsigned int expected_response, int check_response,
892 #if G_HAVE_GINT64
893 guint64 * num)
894 {
895 guint64 snum;
896 #else
897 guint32 * num)
898 {
899 guint32 snum;
900 #endif
901 guint32 hinum, lonum;
902 int ret;
903
904 if ((ret = sshv2_buffer_get_int32 (request, message, 0, 0, &hinum)) < 0)
905 return (ret);
906
907 if ((ret = sshv2_buffer_get_int32 (request, message, 0, 0, &lonum)) < 0)
908 return (ret);
909
910 #if G_HAVE_GINT64
911 snum = (gint64) lonum | ((gint64) hinum >> 32);
912 #else
913 snum = lonum;
914 #endif
915
916 if (check_response && snum != expected_response)
917 return (sshv2_response_return_code (request, message, snum));
918
919 if (num != NULL)
920 *num = snum;
921
922 return (0);
923 }
924
925
875 static char * 926 static char *
876 sshv2_buffer_get_string (gftp_request * request, sshv2_message * message) 927 sshv2_buffer_get_string (gftp_request * request, sshv2_message * message,
877 { 928 int return_string)
929 {
930 guint32 len, buflen;
878 char *string; 931 char *string;
879 guint32 len; 932
880 933 if (sshv2_buffer_get_int32 (request, message, 0, 0, &len) < 0)
881 if (sshv2_buffer_get_int32 (request, message, -1, &len) < 0)
882 return (NULL); 934 return (NULL);
883 935
884 if (len > SSH_MAX_STRING_SIZE || (message->end - message->pos < len)) 936 buflen = message->end - message->pos;
937 if (len > SSH_MAX_STRING_SIZE || (buflen < len))
885 { 938 {
886 sshv2_wrong_response (request, message); 939 sshv2_wrong_response (request, message);
887 return (NULL); 940 return (NULL);
888 } 941 }
889 942
890 string = g_malloc (len + 1); 943 if (return_string)
891 memcpy (string, message->pos, len); 944 {
892 string[len] = '\0'; 945 string = g_malloc (len + 1);
946 memcpy (string, message->pos, len);
947 string[len] = '\0';
948 }
949 else
950 string = NULL;
951
893 message->pos += len; 952 message->pos += len;
894 return (string); 953 return (string);
895 } 954 }
896 955
897 956
931 SSH_FXP_NAME); 990 SSH_FXP_NAME);
932 if (ret < 0) 991 if (ret < 0)
933 return (ret); 992 return (ret);
934 993
935 message.pos += 4; 994 message.pos += 4;
936 if ((ret = sshv2_buffer_get_int32 (request, &message, 1, NULL)) < 0) 995 if ((ret = sshv2_buffer_get_int32 (request, &message, 1, 1, NULL)) < 0)
937 return (ret); 996 return (ret);
938 997
939 if ((request->directory = sshv2_buffer_get_string (request, &message)) == NULL) 998 if ((request->directory = sshv2_buffer_get_string (request, &message, 1)) == NULL)
940 return (GFTP_EFATAL); 999 return (GFTP_EFATAL);
941 1000
942 sshv2_message_free (&message); 1001 sshv2_message_free (&message);
943 return (0); 1002 return (0);
944 } 1003 }
1181 1240
1182 static int 1241 static int
1183 sshv2_decode_file_attributes (gftp_request * request, sshv2_message * message, 1242 sshv2_decode_file_attributes (gftp_request * request, sshv2_message * message,
1184 gftp_file * fle) 1243 gftp_file * fle)
1185 { 1244 {
1186 guint32 attrs, hinum, num, count, i; 1245 guint32 attrs, num, count, i;
1187 int ret; 1246 int ret;
1188 1247
1189 if ((ret = sshv2_buffer_get_int32 (request, message, -1, &attrs)) < 0) 1248 if ((ret = sshv2_buffer_get_int32 (request, message, 0, 0, &attrs)) < 0)
1190 return (ret); 1249 return (ret);
1191 1250
1192 if (attrs & SSH_FILEXFER_ATTR_SIZE) 1251 if (attrs & SSH_FILEXFER_ATTR_SIZE)
1193 { 1252 {
1194 if ((ret = sshv2_buffer_get_int32 (request, message, -1, &hinum)) < 0) 1253 if ((ret = sshv2_buffer_get_int64 (request, message, 0, 0, &fle->size)) < 0)
1195 return (ret); 1254 return (ret);
1196 1255 }
1197 if ((ret = sshv2_buffer_get_int32 (request, message, -1, &num)) < 0) 1256
1257 if (attrs & SSH_FILEXFER_ATTR_UIDGID)
1258 {
1259 if ((ret = sshv2_buffer_get_int32 (request, message, 0, 0, &num)) < 0)
1198 return (ret); 1260 return (ret);
1199 1261 fle->user = g_strdup_printf ("%d", num);
1200 #if G_HAVE_GINT64 1262
1201 fle->size = (gint64) num | ((gint64) hinum >> 32); 1263 if ((ret = sshv2_buffer_get_int32 (request, message, 0, 0, &num)) < 0)
1202 #else
1203 fle->size = num;
1204 #endif
1205 }
1206
1207 if (attrs & SSH_FILEXFER_ATTR_UIDGID)
1208 {
1209 if ((ret = sshv2_buffer_get_int32 (request, message, -1, NULL)) < 0)
1210 return (ret); 1264 return (ret);
1211 1265 fle->group = g_strdup_printf ("%d", num);
1212 if ((ret = sshv2_buffer_get_int32 (request, message, -1, NULL)) < 0) 1266 }
1267
1268 if (attrs & SSH_FILEXFER_ATTR_PERMISSIONS)
1269 {
1270 if ((ret = sshv2_buffer_get_int32 (request, message, 0, 0, &num)) < 0)
1213 return (ret); 1271 return (ret);
1214 } 1272
1215 1273 fle->st_mode = num;
1216 if (attrs & SSH_FILEXFER_ATTR_PERMISSIONS) 1274 }
1217 { 1275
1218 if ((ret = sshv2_buffer_get_int32 (request, message, -1, &num)) < 0) 1276 if (attrs & SSH_FILEXFER_ATTR_ACMODTIME)
1277 {
1278 if ((ret = sshv2_buffer_get_int32 (request, message, 0, 0, NULL)) < 0)
1279 return (num);
1280
1281 if ((ret = sshv2_buffer_get_int32 (request, message, 0, 0, &num)) < 0)
1219 return (ret); 1282 return (ret);
1220 1283
1221 fle->st_mode = num;
1222 }
1223
1224 if (attrs & SSH_FILEXFER_ATTR_ACMODTIME)
1225 {
1226 if ((ret = sshv2_buffer_get_int32 (request, message, -1, NULL)) < 0)
1227 return (num);
1228
1229 if ((ret = sshv2_buffer_get_int32 (request, message, -1, &num)) < 0)
1230 return (ret);
1231
1232 fle->datetime = num; 1284 fle->datetime = num;
1233 } 1285 }
1234 1286
1235 if (attrs & SSH_FILEXFER_ATTR_EXTENDED) 1287 if (attrs & SSH_FILEXFER_ATTR_EXTENDED)
1236 { 1288 {
1237 if ((ret = sshv2_buffer_get_int32 (request, message, -1, &count)) < 0) 1289 if ((ret = sshv2_buffer_get_int32 (request, message, 0, 0, &count)) < 0)
1238 return (ret); 1290 return (ret);
1239 1291
1240 for (i=0; i<count; i++) 1292 for (i=0; i<count; i++)
1241 { 1293 {
1242 if ((ret = sshv2_buffer_get_int32 (request, message, -1, &num)) < 0 || 1294 if ((ret = sshv2_buffer_get_int32 (request, message, 0, 0,
1295 &num)) < 0 ||
1243 message->pos + num + 4 > message->end) 1296 message->pos + num + 4 > message->end)
1244 return (GFTP_EFATAL); 1297 return (GFTP_EFATAL);
1245 1298
1246 message->pos += num + 4; 1299 message->pos += num + 4;
1247 1300
1248 if ((ret = sshv2_buffer_get_int32 (request, message, -1, &num)) < 0 || 1301 if ((ret = sshv2_buffer_get_int32 (request, message, 0, 0,
1302 &num)) < 0 ||
1249 message->pos + num + 4 > message->end) 1303 message->pos + num + 4 > message->end)
1250 return (GFTP_EFATAL); 1304 return (GFTP_EFATAL);
1251 1305
1252 message->pos += num + 4; 1306 message->pos += num + 4;
1253 } 1307 }
1258 1312
1259 1313
1260 static int 1314 static int
1261 sshv2_get_next_file (gftp_request * request, gftp_file * fle, int fd) 1315 sshv2_get_next_file (gftp_request * request, gftp_file * fle, int fd)
1262 { 1316 {
1263 guint32 len, longnamelen;
1264 int ret, retsize, iret; 1317 int ret, retsize, iret;
1265 sshv2_params *params; 1318 sshv2_params *params;
1266 char *longname; 1319 char *stpos;
1320 guint32 len;
1267 1321
1268 g_return_val_if_fail (request != NULL, GFTP_EFATAL); 1322 g_return_val_if_fail (request != NULL, GFTP_EFATAL);
1269 g_return_val_if_fail (request->protonum == GFTP_SSHV2_NUM, GFTP_EFATAL); 1323 g_return_val_if_fail (request->protonum == GFTP_SSHV2_NUM, GFTP_EFATAL);
1270 g_return_val_if_fail (fle != NULL, GFTP_EFATAL); 1324 g_return_val_if_fail (fle != NULL, GFTP_EFATAL);
1271 1325
1313 1367
1314 if (ret == SSH_FXP_NAME) 1368 if (ret == SSH_FXP_NAME)
1315 { 1369 {
1316 params->message.pos = params->message.buffer + 4; 1370 params->message.pos = params->message.buffer + 4;
1317 if ((iret = sshv2_buffer_get_int32 (request, 1371 if ((iret = sshv2_buffer_get_int32 (request,
1318 &params->message, -1, 1372 &params->message, 0, 0,
1319 &params->count)) < 0) 1373 &params->count)) < 0)
1320 return (iret); 1374 return (iret);
1321 } 1375 }
1322 } 1376 }
1323 1377
1324 if (ret == SSH_FXP_NAME) 1378 if (ret == SSH_FXP_NAME)
1325 { 1379 {
1326 if (sshv2_buffer_get_int32 (request, &params->message, -1, &len) < 0 || 1380 stpos = params->message.pos;
1327 params->message.pos + len > params->message.end) 1381 if ((fle->file = sshv2_buffer_get_string (request, &params->message, 1)) == NULL)
1328 return (GFTP_EFATAL); 1382 return (GFTP_EFATAL);
1329 1383
1330 params->message.pos += len; 1384 sshv2_buffer_get_string (request, &params->message, 0);
1331
1332 if (sshv2_buffer_get_int32 (request, &params->message, -1,
1333 &longnamelen) < 0 ||
1334 params->message.pos + longnamelen > params->message.end)
1335 return (GFTP_EFATAL);
1336
1337 longname = params->message.pos;
1338 longname[longnamelen] = '\0';
1339
1340 /* The commercial SSH2 puts a / and * after some entries */
1341 if (longname[longnamelen - 1] == '*')
1342 longname[--longnamelen] = '\0';
1343 if (longname[longnamelen - 1] == '/')
1344 longname[--longnamelen] = '\0';
1345
1346 params->message.pos += longnamelen;
1347
1348 if ((ret = gftp_parse_ls (request, longname, fle, 0)) < 0)
1349 {
1350 request->logging_function (gftp_logging_error, request,
1351 _("Warning: Cannot parse listing %s\n"),
1352 longname);
1353
1354 gftp_file_destroy (fle, 0);
1355 return (ret);
1356 }
1357 1385
1358 if ((ret = sshv2_decode_file_attributes (request, &params->message, 1386 if ((ret = sshv2_decode_file_attributes (request, &params->message,
1359 fle)) < 0) 1387 fle)) < 0)
1360 { 1388 {
1361 gftp_file_destroy (fle, 0); 1389 gftp_file_destroy (fle, 0);
1362 return (ret); 1390 return (ret);
1363 } 1391 }
1364 1392
1365 retsize = strlen (longname); 1393 retsize = params->message.pos - stpos;
1366 params->count--; 1394 params->count--;
1367 } 1395 }
1368 else if (ret == SSH_FXP_STATUS) 1396 else if (ret == SSH_FXP_STATUS)
1369 { 1397 {
1370 sshv2_message_free (&params->message); 1398 sshv2_message_free (&params->message);
1404 SSH_FXP_NAME); 1432 SSH_FXP_NAME);
1405 if (ret < 0) 1433 if (ret < 0)
1406 return (ret); 1434 return (ret);
1407 1435
1408 message.pos += 4; 1436 message.pos += 4;
1409 if ((ret = sshv2_buffer_get_int32 (request, &message, 1, NULL)) < 0) 1437 if ((ret = sshv2_buffer_get_int32 (request, &message, 1, 1, NULL)) < 0)
1410 return (ret); 1438 return (ret);
1411 1439
1412 if ((dir = sshv2_buffer_get_string (request, &message)) == NULL) 1440 if ((dir = sshv2_buffer_get_string (request, &message, 1)) == NULL)
1413 return (GFTP_EFATAL); 1441 return (GFTP_EFATAL);
1414 1442
1415 if (request->directory) 1443 if (request->directory)
1416 g_free (request->directory); 1444 g_free (request->directory);
1417 1445
1448 memset (&message, 0, sizeof (message)); 1476 memset (&message, 0, sizeof (message));
1449 if ((ret = sshv2_read_response (request, &message, -1)) < 0) 1477 if ((ret = sshv2_read_response (request, &message, -1)) < 0)
1450 return (ret); 1478 return (ret);
1451 1479
1452 message.pos += 4; 1480 message.pos += 4;
1453 if ((ret = sshv2_buffer_get_int32 (request, &message, SSH_FX_OK, NULL)) < 0) 1481 if ((ret = sshv2_buffer_get_int32 (request, &message, SSH_FX_OK, 1, NULL)) < 0)
1454 return (ret); 1482 return (ret);
1455 1483
1456 sshv2_message_free (&message); 1484 sshv2_message_free (&message);
1457 1485
1458 return (0); 1486 return (0);
1483 memset (&message, 0, sizeof (message)); 1511 memset (&message, 0, sizeof (message));
1484 if ((ret = sshv2_read_response (request, &message, -1)) < 0) 1512 if ((ret = sshv2_read_response (request, &message, -1)) < 0)
1485 return (ret); 1513 return (ret);
1486 1514
1487 message.pos += 4; 1515 message.pos += 4;
1488 if ((ret = sshv2_buffer_get_int32 (request, &message, SSH_FX_OK, NULL)) < 0) 1516 if ((ret = sshv2_buffer_get_int32 (request, &message, SSH_FX_OK, 1, NULL)) < 0)
1489 return (ret); 1517 return (ret);
1490 1518
1491 sshv2_message_free (&message); 1519 sshv2_message_free (&message);
1492 1520
1493 return (0); 1521 return (0);
1525 memset (&message, 0, sizeof (message)); 1553 memset (&message, 0, sizeof (message));
1526 if ((ret = sshv2_read_response (request, &message, -1)) < 0) 1554 if ((ret = sshv2_read_response (request, &message, -1)) < 0)
1527 return (ret); 1555 return (ret);
1528 1556
1529 message.pos += 4; 1557 message.pos += 4;
1530 if ((ret = sshv2_buffer_get_int32 (request, &message, SSH_FX_OK, NULL)) < 0) 1558 if ((ret = sshv2_buffer_get_int32 (request, &message, SSH_FX_OK, 1, NULL)) < 0)
1531 return (ret); 1559 return (ret);
1532 1560
1533 sshv2_message_free (&message); 1561 sshv2_message_free (&message);
1534 1562
1535 return (0); 1563 return (0);
1563 memset (&message, 0, sizeof (message)); 1591 memset (&message, 0, sizeof (message));
1564 if ((ret = sshv2_read_response (request, &message, -1)) < 0) 1592 if ((ret = sshv2_read_response (request, &message, -1)) < 0)
1565 return (ret); 1593 return (ret);
1566 1594
1567 message.pos += 4; 1595 message.pos += 4;
1568 if ((ret = sshv2_buffer_get_int32 (request, &message, SSH_FX_OK, NULL)) < 0) 1596 if ((ret = sshv2_buffer_get_int32 (request, &message, SSH_FX_OK, 1, NULL)) < 0)
1569 return (ret); 1597 return (ret);
1570 1598
1571 sshv2_message_free (&message); 1599 sshv2_message_free (&message);
1572 1600
1573 return (0); 1601 return (0);
1617 memset (&message, 0, sizeof (message)); 1645 memset (&message, 0, sizeof (message));
1618 if ((ret = sshv2_read_response (request, &message, -1)) < 0) 1646 if ((ret = sshv2_read_response (request, &message, -1)) < 0)
1619 return (ret); 1647 return (ret);
1620 1648
1621 message.pos += 4; 1649 message.pos += 4;
1622 if ((ret = sshv2_buffer_get_int32 (request, &message, SSH_FX_OK, NULL)) < 0) 1650 if ((ret = sshv2_buffer_get_int32 (request, &message, SSH_FX_OK, 1, NULL)) < 0)
1623 return (ret); 1651 return (ret);
1624 1652
1625 sshv2_message_free (&message); 1653 sshv2_message_free (&message);
1626 1654
1627 return (0); 1655 return (0);
1660 memset (&message, 0, sizeof (message)); 1688 memset (&message, 0, sizeof (message));
1661 if ((ret = sshv2_read_response (request, &message, -1)) < 0) 1689 if ((ret = sshv2_read_response (request, &message, -1)) < 0)
1662 return (ret); 1690 return (ret);
1663 1691
1664 message.pos += 4; 1692 message.pos += 4;
1665 if ((ret = sshv2_buffer_get_int32 (request, &message, SSH_FX_OK, NULL)) < 0) 1693 if ((ret = sshv2_buffer_get_int32 (request, &message, SSH_FX_OK, 1, NULL)) < 0)
1666 return (ret); 1694 return (ret);
1667 1695
1668 sshv2_message_free (&message); 1696 sshv2_message_free (&message);
1669 1697
1670 return (0); 1698 return (0);
1913 { 1941 {
1914 if (ret < 0) 1942 if (ret < 0)
1915 return (ret); 1943 return (ret);
1916 1944
1917 message.pos += 4; 1945 message.pos += 4;
1918 if ((ret = sshv2_buffer_get_int32 (request, &message, SSH_FX_EOF, 1946 if ((ret = sshv2_buffer_get_int32 (request, &message, SSH_FX_EOF, 1,
1919 NULL)) < 0) 1947 NULL)) < 0)
1920 return (ret); 1948 return (ret);
1921 1949
1922 sshv2_message_free (&message); 1950 sshv2_message_free (&message);
1923 return (0); 1951 return (0);
1988 params->dont_log_status = 0; 2016 params->dont_log_status = 0;
1989 if (ret != SSH_FXP_STATUS) 2017 if (ret != SSH_FXP_STATUS)
1990 return (sshv2_wrong_response (request, &message)); 2018 return (sshv2_wrong_response (request, &message));
1991 2019
1992 message.pos += 4; 2020 message.pos += 4;
1993 if ((ret = sshv2_buffer_get_int32 (request, &message, SSH_FX_OK, &num)) < 0) 2021 if ((ret = sshv2_buffer_get_int32 (request, &message, SSH_FX_OK, 1, &num)) < 0)
1994 { 2022 {
1995 if (num == SSH_FX_EOF) 2023 if (num == SSH_FX_EOF)
1996 return (0); 2024 return (0);
1997 2025
1998 return (ret); 2026 return (ret);