17 #define _OSSPEC_DEFINED
18 #define VC_LT_2005( version ) ( version < 1400 )
22 #if defined( __MVS__ ) || defined( __VMCMS__ )
24 #pragma convlit( suspend )
26 #if defined( __ILEC400__ )
34 #ifdef USER_SUPPLIED_PASSWORD
35 #undef SSH2_SERVER_NAME
37 #define SSH2_SERVER_NAME "testserver"
38 #define SSH_USER_NAME "testname"
61 #if defined( TEST_SESSION ) || defined( TEST_SESSION_LOOPBACK )
78 static const FAR_BSS URL_PARSE_INFO urlParseInfo[] = {
80 {
TEXT(
"1.2.3.4" ),
TEXT(
"1.2.3.4" ), 0, NULL },
81 {
TEXT(
"1.2.3.4:80" ),
TEXT(
"1.2.3.4" ), 80, NULL },
83 {
TEXT(
"[1:2:3:4]" ),
TEXT(
"[1:2:3:4]" ), 0, NULL },
84 {
TEXT(
"[1:2:3:4]:80" ),
TEXT(
"[1:2:3:4]" ), 80, NULL },
85 {
TEXT(
"user@[1:2:3:4]" ),
TEXT(
"[1:2:3:4]" ), 0,
TEXT(
"user" ) },
86 {
TEXT(
"[::1]" ),
TEXT(
"[::1]" ), 0, NULL },
89 {
TEXT(
"www.server.com" ),
TEXT(
"www.server.com" ), 0, NULL },
90 {
TEXT(
"www.server.com:80" ),
TEXT(
"www.server.com" ), 80, NULL },
91 {
TEXT(
"http://www.server.com/" ),
TEXT(
"www.server.com" ), 0, NULL },
92 {
TEXT(
"http://www.server.com:80" ),
TEXT(
"www.server.com" ), 80, NULL },
94 {
TEXT(
"http://www.server.com/location.php" ),
TEXT(
"www.server.com/location.php" ), 0, NULL },
95 {
TEXT(
"http://www.server.com:80/location.php" ),
TEXT(
"www.server.com/location.php" ), 80, NULL },
96 {
TEXT(
"http://www.server.com/location1/location2/location.php" ),
TEXT(
"www.server.com/location1/location2/location.php" ), 0, NULL },
99 {
TEXT(
" www.server.com : 80 " ),
TEXT(
"www.server.com" ), 80, NULL },
100 {
TEXT(
" user @ www.server.com : 80 " ),
TEXT(
"www.server.com" ), 80, NULL },
101 {
TEXT(
"http:// user @ www.server.com : 80 " ),
TEXT(
"www.server.com" ), 80,
TEXT(
"user" ) },
102 {
TEXT(
"www.server.com : 80 /location.php" ),
TEXT(
"www.server.com/location.php" ), 80, NULL },
104 { NULL, NULL, 0, NULL }
107 static const FAR_BSS URL_PARSE_INFO invalidUrlParseInfo[] = {
109 {
TEXT(
"www.server.com:2" ), NULL, 0, NULL },
110 {
TEXT(
"www.server.com:80abcd" ), NULL, 0, NULL },
111 {
TEXT(
"www.server.com:abcd" ), NULL, 0, NULL },
114 {
TEXT(
"http://" ), NULL, 0, NULL },
115 {
TEXT(
"http://xy" ), NULL, 0, NULL },
116 {
TEXT(
"@www.server.com" ), NULL, 0, NULL },
117 {
TEXT(
" @www.server.com" ), NULL, 0, NULL },
119 { NULL, NULL, 0, NULL }
127 puts(
"Testing session URL parsing..." );
135 printf(
"cryptCreateSession() failed with error code %d, line %d.\n",
141 for( i = 0; urlParseInfo[ i ].url != NULL; i++ )
143 C_CHR nameBuffer[ 256 ], userInfoBuffer[ 256 ];
147 memset( nameBuffer, 0, 16 );
148 memset( userInfoBuffer, 0, 16 );
156 urlParseInfo[ i ].url,
160 printf(
"Couldn't set URL '%s', status %d, line %d.\n",
161 urlParseInfo[ i ].url, status, __LINE__ );
168 nameBuffer, &nameLength );
172 if(
cryptStatusOK( status ) && urlParseInfo[ i ].userInfo != NULL )
181 printf(
"Couldn't get parsed URL info for '%s', status %d, "
182 "line %d.\n", urlParseInfo[ i ].url, status, __LINE__ );
185 if(
paramStrlen( urlParseInfo[ i ].
name ) != (
size_t ) nameLength || \
186 memcmp( nameBuffer, urlParseInfo[ i ].name, nameLength ) || \
187 ( urlParseInfo[ i ].port && port != urlParseInfo[ i ].port ) || \
188 ( urlParseInfo[ i ].userInfo != NULL && \
189 memcmp( userInfoBuffer, urlParseInfo[ i ].userInfo,
192 printf(
"Parsed URL info for '%s' is incorrect, line %d.\n",
193 urlParseInfo[ i ].url, __LINE__ );
199 for( i = 0; invalidUrlParseInfo[ i ].url != NULL; i++ )
209 invalidUrlParseInfo[ i ].url,
213 printf(
"Invalid URL '%s' was accepted as valid, line %d.\n",
214 invalidUrlParseInfo[ i ].url, __LINE__ );
223 printf(
"cryptDestroySession() failed with error code %d, line %d.\n",
227 puts(
"Session URL parsing succeeded.\n" );
238 puts(
"Testing session attribute handling..." );
247 printf(
"cryptCreateSession() failed with error code %d, line %d.\n",
258 printf(
"cryptSetAttributeString() failed with error code %d, "
259 "line %d.\n", status, __LINE__ );
289 printf(
"cryptSetAttributeString() for username/password pairs "
290 "failed with error code %d, line %d.\n", status, __LINE__ );
300 printf(
"Addition of duplicate user/password entry wasn't detected, "
301 "line %d.\n", __LINE__ );
312 printf(
"Addition of password without username wasn't detected, "
313 "line %d.\n", __LINE__ );
327 printf(
"Addition of username without password wasn't detected, "
328 "line %d.\n", __LINE__ );
336 printf(
"cryptDestroySession() failed with error code %d, line %d.\n",
340 puts(
"Session attribute handling succeeded.\n" );
350 #if defined( WINDOWS_THREADS ) || defined( UNIX_THREADS )
359 #ifdef WINDOWS_THREADS
360 unsigned __stdcall sshServerMultiThread(
void *
dummy )
362 void *sshServerMultiThread(
void *dummy )
368 #ifdef UNICODE_STRINGS
371 void *fileNamePtr = filenameBuffer;
374 printf(
"Server thread %lX activated.\n",
385 printf(
"cryptCreateSession() failed with error code %d, line %d.\n",
394 #ifdef UNICODE_STRINGS
395 mbstowcs( wcBuffer, filenameBuffer, strlen( filenameBuffer ) + 1 );
396 fileNamePtr = wcBuffer;
411 printf(
"Private key read/set failed with error code %d, line %d.\n",
415 printf(
"Server for thread %lX activated.\n",
421 "Attempt to activate SSH server session", status,
424 printf(
"Server for thread %lX has exited.\n",
431 #ifdef WINDOWS_THREADS
432 unsigned __stdcall sshClientMultiThread(
void *dummy )
434 void *sshClientMultiThread(
void *dummy )
440 printf(
"Client thread %lX activated.\n",
451 printf(
"cryptCreateSession() failed with error code %d, line %d.\n",
477 printf(
"cryptSetAttribute/AttributeString() failed with error code "
478 "%d, line %d.\n", status, __LINE__ );
481 printf(
"Client for thread %lX activated.\n",
488 "Attempt to activate SSH client session", status,
492 printf(
"Client for thread %lX has exited.\n",
506 #ifdef USE_SSH_EXTENDED
543 stringBuffer, &stringLength );
546 printf(
"%sCouldn't query channel ID/type, status %d, line %d.\n",
547 isServer ?
"SVR: " :
"", status, __LINE__ );
550 #ifdef UNICODE_STRINGS
551 stringBuffer[ stringLength /
sizeof(
wchar_t ) ] =
TEXT(
'\0' );
560 argBuffer, &argLength );
563 printf(
"%sCouldn't query channel arg, status %d, line %d.\n",
564 isServer ?
"SVR: " :
"", status, __LINE__ );
567 #ifdef UNICODE_STRINGS
568 argBuffer[ argLength /
sizeof(
wchar_t ) ] =
TEXT(
'\0' );
569 printf(
"SVR: Client opened channel #%d, type '%S', arg '%S'.\n",
570 channel, stringBuffer, argBuffer );
572 argBuffer[ argLength ] =
'\0';
573 printf(
"SVR: Client opened channel #%d, type '%s', arg '%s'.\n",
574 channel, stringBuffer, argBuffer );
583 printf(
"SVR: Client requested subsystem but server reported "
584 "request as '%s', line %d.\n", stringBuffer, __LINE__ );
588 #ifdef UNICODE_STRINGS
589 printf(
"SVR: Client opened channel #%d, type '%S'.\n",
590 channel, stringBuffer );
592 printf(
"SVR: Client opened channel #%d, type '%s'.\n",
593 channel, stringBuffer );
608 #ifdef USE_SSH_EXTENDED
614 isServer ?
"SVR: Couldn't get data channel number" : \
615 "Couldn't get data channel number",
624 isServer ?
"SVR: Client data read failed" : \
625 "Server data read failed",
630 printf(
"%s---- %s sent %d bytes on channel #%d ----\n",
631 isServer ?
"SVR: " :
"", isServer ?
"Client" :
"Server",
632 *bytesCopied, channel );
636 printf(
"%s---- End of output ----\n", isServer ?
"SVR: " :
"" );
650 stringBuffer, &length );
653 #ifdef UNICODE_STRINGS
654 stringBuffer[ length /
sizeof(
wchar_t ) ] =
TEXT(
'\0' );
655 printf(
"SVR: User name = '%S', ", stringBuffer );
657 stringBuffer[
length ] =
'\0';
658 printf(
"SVR: User name = '%s', ", stringBuffer );
663 stringBuffer, &length );
666 #ifdef UNICODE_STRINGS
667 stringBuffer[ length /
sizeof(
wchar_t ) ] =
TEXT(
'\0' );
668 printf(
"password = '%S'.\n", stringBuffer );
670 stringBuffer[
length ] =
'\0';
671 printf(
"password = '%s'.\n", stringBuffer );
676 printf(
"SVR: Couldn't read client authentication details, "
677 "status = %d, line %d.\n", status, __LINE__ );
729 TEXT(
"sorrel.humboldt.edu:222" ),
730 TEXT(
"www.ssh.com" ),
731 TEXT(
"www.openssh.com" ),
733 TEXT(
"natsu.mindrot.org" ),
737 #define SSH1_SERVER_NO 1
738 #define SSH2_SERVER_NO 4
744 #ifdef WINDOWS_THREADS
745 unsigned __stdcall ssh2ServerDualThread2(
void *dummy );
759 #ifdef SSH2_SERVER_NAME
760 const C_STR serverName = SSH2_SERVER_NAME;
762 const C_STR serverName = localSession ?
TEXT(
"localhost" ) : \
764 ssh1Info[ SSH1_SERVER_NO ] : \
765 ssh2Info[ SSH2_SERVER_NO ];
770 #ifdef USE_SSH_EXTENDED
788 printf(
"Timed out waiting for server to initialise, "
789 "line %d.\n", __LINE__ );
798 #ifdef WINDOWS_THREADS
800 goto dualThreadContinue;
803 printf(
"%sTesting %sSSH%s%s session...\n",
804 isServer ?
"SVR: " :
"",
805 localSession ?
"local " :
"",
814 if( !isServer && !localSession )
816 #ifdef UNICODE_STRINGS
817 printf(
" Remote host: %S.\n", serverName );
819 printf(
" Remote host: %s.\n", serverName );
830 printf(
"cryptCreateSession() failed with error code %d, line %d.\n",
840 #ifdef UNICODE_STRINGS
843 void *fileNamePtr = filenameBuffer;
850 #ifdef UNICODE_STRINGS
851 mbstowcs( wcBuffer, filenameBuffer, strlen( filenameBuffer ) + 1 );
852 fileNamePtr = wcBuffer;
900 #ifdef USER_SUPPLIED_PASSWORD
903 printf(
"Enter SSHv2 server password: " );
904 fgets( password, 255, stdin );
905 password[ strlen( password ) - 1 ] =
'\0';
908 password, strlen( password ) );
917 #ifdef USE_SSH_EXTENDED
921 status = createChannel( cryptSession,
TEXT(
"subsystem" ),
928 status = createChannel( cryptSession,
TEXT(
"direct-tcpip" ),
929 TEXT(
"localhost:1234" ) );
944 #ifdef USE_SSH_EXTENDED
948 status = createChannel( cryptSession,
TEXT(
"exec" ),
949 TEXT(
"/bin/netstat" ) );
971 puts(
"SSHv1 appears to be disbled in this build." );
973 puts( isServer ?
"SVR: SSH server session succeeded.\n" : \
974 "SSH client session succeeded.\n" );
978 printf(
"%scryptSetAttribute/AttributeString() failed with error "
979 "code %d, line %d.\n", isServer ?
"SVR: " :
"", status,
996 if( localSession && isServer )
1004 #ifdef WINDOWS_THREADS
1012 localCryptSession = cryptSession;
1013 _beginthreadex( NULL, 0, ssh2ServerDualThread2, NULL, 0,
1019 assert( localSession > 0 );
1020 cryptSession = localCryptSession;
1023 puts(
"SVR: Confirming authentication to client..." );
1035 if( !printAuthInfo( cryptSession ) )
1043 puts(
"SVR: Denying authentication to client, who should "
1054 "SVR: Attempt to deny auth.to client",
1058 if( !printAuthInfo( cryptSession ) )
1063 puts(
"SVR: Confirming authentication to client..." );
1083 puts(
"SSH client rejected key with invalid fingerprint." );
1085 puts( isServer ?
"SVR: SSH server session succeeded.\n" : \
1086 "SSH client session succeeded.\n" );
1091 "SVR: Attempt to activate SSH server session" : \
1092 "Attempt to activate SSH client session", status,
1106 puts(
" (Server could be down, faking it and continuing...)\n" );
1114 puts(
" (Incorrect username/password, continuing...)\n" );
1122 puts(
" (Insufficiently secure protocol parameters, "
1123 "continuing...)\n" );
1130 printf(
"Attempt to connect with invalid key fingerprint succeeded "
1131 "when it should\nhave failed, line %d.\n", __LINE__ );
1140 #ifdef USE_SSH_EXTENDED
1145 printf(
"cryptGetAttributeString() failed with error code "
1146 "%d, line %d.\n", status, __LINE__ );
1149 printf(
"%sCurrent channel is #%d.\n", isServer ?
"SVR: " :
"",
1160 #ifdef USE_SSH_EXTENDED
1161 if( !printChannelInfo( cryptSession, testType,
TRUE ) )
1171 printf(
"SVR: Client sent additional %d bytes post-"
1172 "handshake data.\n", bytesCopied );
1175 #ifdef USE_SSH_EXTENDED
1183 if( !printChannelInfo( cryptSession, testType,
TRUE ) )
1192 #if defined( WINDOWS_THREADS ) && 0
1199 status = sftpServer( cryptSession );
1202 printf(
"SVR: Couldn't receive SFTP data from client, status %d, "
1203 "line %d.\n", status, __LINE__ );
1207 puts(
"SVR: SFTP server session succeeded.\n" );
1215 status = sftpClient( cryptSession );
1218 printf(
"Couldn't send SFTP data to server, status %d, line "
1219 "%d.\n", status, __LINE__ );
1223 puts(
"SFTP client session succeeded.\n" );
1230 #ifdef USE_SSH_EXTENDED
1235 status = createChannel( cryptSession,
TEXT(
"direct-tcpip" ),
1236 TEXT(
"localhost:5678" ) );
1247 printf(
"Couldn't open second SSH chanel, status %d, line "
1248 "%d.\n", status, __LINE__ );
1251 printf(
"Opened additional channel #%d to server.\n", channel );
1260 status =
cryptPushData( cryptSession,
"Welcome to cryptlib, now go "
1261 "away.\r\n", 35, &bytesCopied );
1266 printf(
"SVR: Couldn't send data to client, status %d, line "
1267 "%d.\n", status, __LINE__ );
1276 if( !printDataInfo( cryptSession, buffer, &bytesCopied, isServer ) )
1295 printf(
"SVR: Couldn't select channel #1 to return data to "
1296 "client, status %d, line %d.\n", status, __LINE__ );
1300 for( i = 0; i < clientBytesCopied; i++ )
1302 if( buffer[ i ] <
' ' || buffer[ i ] >= 0x7F )
1305 status =
cryptPushData( cryptSession,
"Input was [", 11, &dummy );
1307 status =
cryptPushData( cryptSession, buffer, clientBytesCopied,
1315 printf(
"SVR: Couldn't send data to client, status %d, line "
1316 "%d.\n", status, __LINE__ );
1327 status =
cryptPushData( cryptSession,
"ls -l | head -25\n", 18,
1333 printf(
"Couldn't send data to server, status %d, line "
1334 "%d.\n", status, __LINE__ );
1337 puts(
"Sent 'ls -l | head -25'" );
1339 if( !printDataInfo( cryptSession, buffer, &bytesCopied,
1353 printf(
"Couldn't send data to server, status %d, line "
1354 "%d.\n", status, __LINE__ );
1363 if( !printDataInfo( cryptSession, buffer, &bytesCopied,
1386 printf(
"Couldn't close second SSH chanel, status %d, line "
1387 "%d.\n", status, __LINE__ );
1390 printf(
"Closed second channel to server.\n" );
1399 printf(
"cryptDestroySession() failed with error code %d, line %d.\n",
1404 puts( isServer ?
"SVR: SSH server session succeeded.\n" : \
1405 "SSH client session succeeded.\n" );
1428 #ifdef USE_SSH_EXTENDED
1436 #ifdef USE_SSH_EXTENDED
1444 #ifdef USE_SSH_EXTENDED
1476 #ifdef USE_SSH_EXTENDED
1491 #ifdef WINDOWS_THREADS
1493 unsigned __stdcall ssh1ServerThread(
void *dummy )
1499 unsigned __stdcall ssh2ServerThread(
void *dummy )
1505 unsigned __stdcall ssh2ServerDsaKeyThread(
void *dummy )
1511 unsigned __stdcall ssh2ServerEccKeyThread(
void *dummy )
1517 unsigned __stdcall ssh2ServerFingerprintThread(
void *dummy )
1523 unsigned __stdcall ssh2ServerMultichannelThread(
void *dummy )
1529 unsigned __stdcall ssh2ServerDualThread1(
void *dummy )
1535 unsigned __stdcall ssh2ServerDualThread2(
void *dummy )
1541 unsigned __stdcall sftpServerThread(
void *dummy )
1556 hThread = (
HANDLE ) _beginthreadex( NULL, 0,
1558 sftpServerThread : \
1560 ssh1ServerThread : \
1562 ssh2ServerDsaKeyThread : \
1564 ssh2ServerEccKeyThread : \
1566 ssh2ServerFingerprintThread : \
1568 ssh2ServerMultichannelThread : \
1570 ssh2ServerDualThread1 : \
1572 NULL, 0, &threadID );
1621 #ifdef USE_SSH_EXTENDED
1629 #ifdef USE_SSH_EXTENDED
1637 #ifdef USE_SSH_EXTENDED
1660 #if defined( WINDOWS_THREADS ) && 0
1676 #define BYTE _BYTE_DUMMY
1684 #define BYTE unsigned char
1688 #define sMemDisconnect( stream )
1689 #define sMemConnect sMemOpen
1690 #define stell( stream ) ( ( stream )->bufPos )
1698 int sMemOpen(
STREAM *stream,
void *buffer,
const int bufSize )
1700 memset( stream, 0,
sizeof(
STREAM ) );
1701 stream->buffer = (
void * ) buffer;
1706 int sread(
STREAM *stream,
void *buffer,
const int count )
1713 memcpy( buffer, stream->buffer + stream->
bufPos, count );
1718 int swrite(
STREAM *stream,
const void *buffer,
const int count )
1720 if( stream->buffer != NULL )
1727 memcpy( stream->buffer + stream->
bufPos, buffer, count );
1733 int sgetc(
STREAM *stream )
1742 ch = stream->buffer[ stream->
bufPos ];
1749 if( stream->buffer != NULL )
1768 int sPeek(
STREAM *stream )
1778 int sMemDataLeft(
const STREAM *stream )
1789 int importBignum(
BIGNUM *bn,
const void *buffer,
const int length,
1793 const void *bignumPtr ) {
return -1; }
1797 #define SSH_FXP_INIT 1
1798 #define SSH_FXP_VERSION 2
1799 #define SSH_FXP_OPEN 3
1800 #define SSH_FXP_CLOSE 4
1801 #define SSH_FXP_READ 5
1802 #define SSH_FXP_WRITE 6
1803 #define SSH_FXP_LSTAT 7
1804 #define SSH_FXP_FSTAT 8
1805 #define SSH_FXP_SETSTAT 9
1806 #define SSH_FXP_FSETSTAT 10
1807 #define SSH_FXP_OPENDIR 11
1808 #define SSH_FXP_READDIR 12
1809 #define SSH_FXP_REMOVE 13
1810 #define SSH_FXP_MKDIR 14
1811 #define SSH_FXP_RMDIR 15
1812 #define SSH_FXP_REALPATH 16
1813 #define SSH_FXP_STAT 17
1814 #define SSH_FXP_RENAME 18
1815 #define SSH_FXP_READLINK 19
1816 #define SSH_FXP_SYMLINK 20
1817 #define SSH_FXP_STATUS 101
1818 #define SSH_FXP_HANDLE 102
1819 #define SSH_FXP_DATA 103
1820 #define SSH_FXP_NAME 104
1821 #define SSH_FXP_ATTRS 105
1826 #define SSH_FILEXFER_ATTR_SIZE 0x01
1827 #define SSH_FILEXFER_ATTR_UIDGID 0x02
1828 #define SSH_FILEXFER_ATTR_PERMISSIONSv3 0x04
1829 #define SSH_FILEXFER_ATTR_ACMODTIME 0x08
1830 #define SSH_FILEXFER_ATTR_ACCESSTIME 0x08
1831 #define SSH_FILEXFER_ATTR_CREATETIME 0x10
1832 #define SSH_FILEXFER_ATTR_MODIFYTIME 0x20
1833 #define SSH_FILEXFER_ATTR_PERMISSIONSv4 0x40
1834 #define SSH_FILEXFER_ATTR_ACL 0x40
1835 #define SSH_FILEXFER_ATTR_OWNERGROUP 0x80
1836 #define SSH_FILEXFER_ATTR_SUBSECOND_TIMES 0x100
1837 #define SSH_FILEXFER_ATTR_EXTENDED 0x80000000
1841 #define SSH_FXF_READ 0x01
1842 #define SSH_FXF_WRITE 0x02
1843 #define SSH_FXF_APPEND 0x04
1844 #define SSH_FXF_CREAT 0x08
1845 #define SSH_FXF_TRUNC 0x10
1846 #define SSH_FXF_EXCL 0x20
1847 #define SSH_FXF_TEXT 0x40
1851 #define SSH_FILETYPE_REGULAR 1
1852 #define SSH_FILETYPE_DIRECTORY 2
1853 #define SSH_FILETYPE_SYMLINK 3
1854 #define SSH_FILETYPE_SPECIAL 4
1855 #define SSH_FILETYPE_UNKNOWN 5
1860 #define SSH_FX_EOF 1
1861 #define SSH_FX_NO_SUCH_FILE 2
1862 #define SSH_FX_PERMISSION_DENIED 3
1863 #define SSH_FX_FAILURE 4
1864 #define SSH_FX_BAD_MESSAGE 5
1865 #define SSH_FX_NO_CONNECTION 6
1866 #define SSH_FX_CONNECTION_LOST 7
1867 #define SSH_FX_OP_UNSUPPORTED 8
1868 #define SSH_FX_INVALID_HANDLE 9
1869 #define SSH_FX_NO_SUCH_PATH 10
1870 #define SSH_FX_FILE_ALREADY_EXISTS 11
1871 #define SSH_FX_WRITE_PROTECT 12
1872 #define SSH_FX_NO_MEDIA 13
1880 time_t ctime, atime, mtime;
1885 #define MAX_HANDLE_SIZE 16
1890 BYTE handle[ MAX_HANDLE_SIZE ];
1925 if( attributes->atime )
1927 if( attributes->mtime )
1937 if( attributes->ctime )
1939 if( attributes->atime )
1941 if( attributes->mtime )
1948 static int readAttributes(
STREAM *stream, SFTP_ATTRS *attributes,
const int version )
1952 memset( attributes, 0,
sizeof( SFTP_ATTRS ) );
1958 flags = readUint32( stream );
1963 if( flags & SSH_FILEXFER_ATTR_SIZE )
1964 readUint64( stream, &attributes->size );
1965 if( flags & SSH_FILEXFER_ATTR_UIDGID )
1967 readUint32( stream );
1968 readUint32( stream );
1970 if( flags & SSH_FILEXFER_ATTR_PERMISSIONSv3 )
1971 attributes->permissions = readUint32( stream );
1974 if( flags & SSH_FILEXFER_ATTR_ACMODTIME )
1976 readUint32Time( stream, &attributes->atime );
1977 readUint32Time( stream, &attributes->mtime );
1982 if( flags & SSH_FILEXFER_ATTR_SIZE )
1983 readUint64( stream, &attributes->size );
1984 if( flags & SSH_FILEXFER_ATTR_OWNERGROUP )
1986 readString32( stream, NULL, 0, NULL );
1987 readString32( stream, NULL, 0, NULL );
1989 if( flags & SSH_FILEXFER_ATTR_PERMISSIONSv4 )
1990 attributes->permissions = readUint32( stream );
1993 if( flags & SSH_FILEXFER_ATTR_ACCESSTIME )
1995 readUint64Time( stream, &attributes->atime );
1996 if( flags & SSH_FILEXFER_ATTR_SUBSECOND_TIMES )
1997 readUint32( stream );
1999 if( flags & SSH_FILEXFER_ATTR_CREATETIME )
2001 readUint64Time( stream, &attributes->ctime );
2002 if( flags & SSH_FILEXFER_ATTR_SUBSECOND_TIMES )
2003 readUint32( stream );
2005 if( flags & SSH_FILEXFER_ATTR_MODIFYTIME )
2007 readUint64Time( stream, &attributes->mtime );
2008 if( flags & SSH_FILEXFER_ATTR_SUBSECOND_TIMES )
2009 readUint32( stream );
2015 if( flags & SSH_FILEXFER_ATTR_ACL )
2016 readString32( stream, NULL, 0, NULL );
2017 if( flags & SSH_FILEXFER_ATTR_EXTENDED )
2019 int extAttrCount = readUint32( stream );
2022 return( extAttrCount );
2023 while( extAttrCount > 0 )
2025 readString32( stream, NULL, 0, NULL );
2026 readString32( stream, NULL, 0, NULL );
2034 static int writeAttributes(
STREAM *stream, SFTP_ATTRS *attributes,
const int version )
2042 flags |= SSH_FILEXFER_ATTR_SIZE;
2044 flags |= SSH_FILEXFER_ATTR_PERMISSIONSv3;
2045 if( attributes->atime )
2046 flags |= SSH_FILEXFER_ATTR_ACMODTIME;
2047 writeUint32( stream, flags );
2051 writeUint64( stream, attributes->size );
2053 writeUint32( stream, attributes->permissions );
2054 if( attributes->atime )
2056 writeUint32Time( stream, attributes->atime );
2057 writeUint32Time( stream, attributes->mtime );
2064 flags |= SSH_FILEXFER_ATTR_SIZE;
2066 flags |= SSH_FILEXFER_ATTR_PERMISSIONSv4;
2067 if( attributes->ctime )
2068 flags |= SSH_FILEXFER_ATTR_CREATETIME;
2069 if( attributes->atime )
2070 flags |= SSH_FILEXFER_ATTR_ACCESSTIME;
2071 if( attributes->mtime )
2072 flags |= SSH_FILEXFER_ATTR_MODIFYTIME;
2073 writeUint32( stream, flags );
2074 sputc( stream, attributes->isDirectory ? \
2075 SSH_FILETYPE_DIRECTORY : SSH_FILETYPE_REGULAR );
2079 writeUint64( stream, attributes->size );
2081 writeUint32( stream, attributes->permissions );
2082 if( attributes->ctime )
2083 writeUint64Time( stream, attributes->ctime );
2084 if( attributes->atime )
2085 writeUint64Time( stream, attributes->atime );
2086 if( attributes->mtime )
2087 writeUint64Time( stream, attributes->mtime );
2100 static int sizeofStatus(
const char *sshStatusString )
2107 static int readStatus(
STREAM *stream, SFTP_INFO *info )
2109 static const struct {
2110 const int sftpStatus, cryptlibStatus;
2111 } sftpStatusMap[] = {
2131 value = readUint32( stream );
2132 status = readUint32( stream );
2135 if( value != info->id )
2139 for( i = 0; sftpStatusMap[ i ].sftpStatus !=
CRYPT_ERROR && \
2140 sftpStatusMap[ i ].sftpStatus !=
status; i++ );
2141 status = sftpStatusMap[ i ].cryptlibStatus;
2146 static int writeStatus(
STREAM *stream, SFTP_INFO *info,
const int sshStatus,
2147 const char *sshStatusString )
2149 writeUint32( stream, info->id );
2150 writeUint32( stream, sshStatus );
2151 writeString32( stream, sshStatusString, strlen( sshStatusString ) );
2152 return( writeString32( stream,
"", 0 ) );
2155 static int readSftpPacket(
const CRYPT_SESSION cryptSession,
void *buffer,
2163 printf(
"SVR: Couldn't read data from SFTP client, status %d, line "
2164 "%d.\n", status, __LINE__ );
2170 static int writeSftpPacket(
const CRYPT_SESSION cryptSession,
const void *data,
2175 status =
cryptPushData( cryptSession, data, length, &bytesCopied );
2180 printf(
"SVR: Couldn't write data to SFTP client, status %d, line "
2181 "%d.\n", status, __LINE__ );
2184 if( bytesCopied < length )
2186 printf(
"SVR: Only wrote %d of %d bytes of SFTP data, line %d.\n",
2187 bytesCopied, length, __LINE__ );
2193 static int sendAck(
const CRYPT_SESSION cryptSession, SFTP_INFO *sftpInfo )
2200 sMemOpen( &stream, buffer, 128 );
2201 writeUint32( &stream, 1 + sizeofStatus(
"" ) );
2202 sputc( &stream, SSH_FXP_STATUS );
2203 writeStatus( &stream, sftpInfo, SSH_FX_OK,
"" );
2204 length = stell( &stream );
2205 sMemDisconnect( &stream );
2206 return( writeSftpPacket( cryptSession, buffer, length ) );
2212 SFTP_ATTRS sftpAttrs;
2221 memset( &sftpInfo, 0,
sizeof( SFTP_INFO ) );
2224 status = readSftpPacket( cryptSession, buffer,
BUFFER_SIZE );
2227 sMemConnect( &stream, buffer, status );
2228 length = readUint32( &stream );
2229 value = sgetc( &stream );
2230 if( ( length != 1 + 4 ) || ( value != SSH_FXP_INIT ) )
2232 sftpInfo.version = readUint32( &stream );
2233 sMemDisconnect( &stream );
2234 printf(
"SVR: Client supports SFTP version %d.\n", sftpInfo.version );
2236 writeUint32( &stream, 1 + 4 );
2237 sputc( &stream, SSH_FXP_VERSION );
2238 writeUint32( &stream, 3 );
2239 length = stell( &stream );
2240 sMemDisconnect( &stream );
2241 status = writeSftpPacket( cryptSession, buffer, length );
2246 status = readSftpPacket( cryptSession, buffer,
BUFFER_SIZE );
2249 printExtError( cryptSession,
"SVR: Attempt to read data from "
2250 "client", status, __LINE__ );
2253 sMemConnect( &stream, buffer, status );
2254 length = readUint32( &stream );
2255 value = sgetc( &stream );
2256 if( value == SSH_FXP_STAT )
2259 sftpInfo.id = readUint32( &stream );
2260 length = readUint32( &stream );
2261 sread( &stream, nameBuffer, length );
2262 sMemDisconnect( &stream );
2263 nameBuffer[
length ] =
'\0';
2264 printf(
"SVR: Client tried to stat file '%s'.\n", nameBuffer );
2265 if( strcmp( nameBuffer,
"." ) )
2267 puts(
"SVR: Don't know how to respond to stat request for this "
2273 memset( &sftpAttrs, 0,
sizeof( SFTP_ATTRS ) );
2274 sftpAttrs.isDirectory =
TRUE;
2275 sftpAttrs.permissions = 0777;
2277 sftpAttrs.atime = sftpAttrs.ctime = sftpAttrs.mtime = time( NULL );
2281 sputc( &stream, SSH_FXP_ATTRS );
2282 writeUint32( &stream, sftpInfo.id );
2283 writeAttributes( &stream, &sftpAttrs, sftpInfo.version );
2284 length = stell( &stream );
2285 sMemDisconnect( &stream );
2286 status = writeSftpPacket( cryptSession, buffer, length );
2291 status = readSftpPacket( cryptSession, buffer,
BUFFER_SIZE );
2294 printExtError( cryptSession,
"SVR: Attempt to read data from "
2295 "client", status, __LINE__ );
2298 sMemConnect( &stream, buffer, status );
2299 length = readUint32( &stream );
2300 value = sgetc( &stream );
2302 if( value == SSH_FXP_OPEN )
2305 sftpInfo.id = readUint32( &stream );
2306 length = readUint32( &stream );
2307 sread( &stream, nameBuffer, length );
2308 value = readUint32( &stream );
2309 readAttributes( &stream, &sftpAttrs, sftpInfo.version );
2310 sMemDisconnect( &stream );
2311 nameBuffer[
length ] =
'\0';
2312 printf(
"Client tried to open file '%s', mode %02X, length %d.\n",
2313 nameBuffer, value, sftpAttrs.size );
2320 sputc( &stream, SSH_FXP_HANDLE );
2321 writeUint32( &stream, sftpInfo.id );
2322 writeUint32( &stream, 1 );
2323 sputc( &stream, 1 );
2324 length = stell( &stream );
2325 sMemDisconnect( &stream );
2326 status = writeSftpPacket( cryptSession, buffer, length );
2332 xferTime = time( NULL );
2337 status = readSftpPacket( cryptSession, buffer,
BUFFER_SIZE );
2340 printExtError( cryptSession,
"SVR: Attempt to read data from "
2341 "client", status, __LINE__ );
2346 printf(
"SVR: Read 0 bytes from client.\n" );
2353 printf(
"SRV: -------- : %d.\r", xferCount );
2358 sMemConnect( &stream, buffer, status );
2359 length = readUint32( &stream );
2362 printf(
"Didn't read complete packet, length = %d, byte count = "
2365 value = sgetc( &stream );
2366 if( value != SSH_FXP_WRITE )
2368 sftpInfo.id = readUint32( &stream );
2369 readString32( &stream, nameBuffer, 128, &length );
2370 readUint64( &stream, &value );
2372 printf(
"SRV: %8d : %d.\r", value, length );
2373 xferCount += status - stell( &stream );
2375 sMemDisconnect( &stream );
2380 status = sendAck( cryptSession, &sftpInfo );
2385 xferTime = time( NULL ) - xferTime;
2386 printf(
"Transfer time = %d seconds, %ld bytes, %d bytes/sec.\n",
2387 xferTime, xferCount, xferCount / xferTime );
2390 if( value != SSH_FXP_CLOSE )
2392 printf(
"SVR: Client sent unexpected packet %d.\n", value );
2395 sftpInfo.id = readUint32( &stream );
2396 status = sendAck( cryptSession, &sftpInfo );
2399 status = readSftpPacket( cryptSession, buffer,
BUFFER_SIZE );
2402 puts(
"SVR: Client has closed the channel." );
2407 sMemConnect( &stream, buffer, status );
2408 length = readUint32( &stream );
2409 value = sgetc( &stream );
2414 #define SFTP_DATA_AMOUNT ( 1024 * 1024 )
2419 SFTP_ATTRS sftpAttrs;
2422 long totalLength = SFTP_DATA_AMOUNT;
2427 memset( &sftpInfo, 0,
sizeof( SFTP_INFO ) );
2431 writeUint32( &stream, 1 + 4 );
2432 sputc( &stream, SSH_FXP_INIT );
2433 writeUint32( &stream, 3 );
2434 length = stell( &stream );
2435 sMemDisconnect( &stream );
2436 status = writeSftpPacket( cryptSession, buffer, length );
2439 status = readSftpPacket( cryptSession, buffer,
BUFFER_SIZE );
2442 sMemConnect( &stream, buffer, status );
2443 length = readUint32( &stream );
2444 value = sgetc( &stream );
2445 if( ( length != 1 + 4 ) || ( value != SSH_FXP_VERSION ) )
2447 sftpInfo.version = readUint32( &stream );
2448 sMemDisconnect( &stream );
2449 printf(
"Server supports SFTP version %d.\n", sftpInfo.version );
2452 memset( &sftpAttrs, 0,
sizeof( SFTP_ATTRS ) );
2453 sftpAttrs.permissions = 0777;
2455 sftpAttrs.atime = sftpAttrs.ctime = sftpAttrs.mtime = time( NULL );
2459 sputc( &stream, SSH_FXP_OPEN );
2460 writeUint32( &stream, 1 );
2461 writeString32( &stream,
"test.dat", 8 );
2462 writeUint32( &stream, SSH_FXF_CREAT | SSH_FXF_WRITE );
2463 writeAttributes( &stream, &sftpAttrs, sftpInfo.version );
2464 length = stell( &stream );
2465 sMemDisconnect( &stream );
2466 status = writeSftpPacket( cryptSession, buffer, length );
2469 status = readSftpPacket( cryptSession, buffer,
BUFFER_SIZE );
2472 printExtError( cryptSession,
"Attempt to read data from server",
2476 sMemConnect( &stream, buffer, status );
2477 length = readUint32( &stream );
2478 value = sgetc( &stream );
2479 readUint32( &stream );
2480 readString32( &stream, sftpInfo.handle, MAX_HANDLE_SIZE,
2481 &sftpInfo.handleSize );
2482 sMemDisconnect( &stream );
2483 if( value != SSH_FXP_HANDLE )
2485 printf(
"Server sent packet %d, expected file handle.\n", value );
2494 sputc( &stream, SSH_FXP_WRITE );
2495 writeUint32( &stream, sftpInfo.id );
2496 writeString32( &stream, sftpInfo.handle, sftpInfo.handleSize );
2497 writeUint64( &stream, 0 );
2498 writeUint32( &stream, SFTP_DATA_AMOUNT );
2499 length = stell( &stream );
2500 memset( buffer + length,
'*',
BUFFER_SIZE - length );
2501 status = writeSftpPacket( cryptSession, buffer,
BUFFER_SIZE );
2505 while( totalLength > 0 )
2508 status = writeSftpPacket( cryptSession, buffer,
2516 status = readSftpPacket( cryptSession, buffer,
BUFFER_SIZE );
2519 printExtError( cryptSession,
"Attempt to read data from server",