⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ssh.c

📁 cryptlib安全工具包
💻 C
📖 第 1 页 / 共 5 页
字号:
	{
	CRYPT_SESSION cryptSession;
	int status;

	printf( "Client thread %lX activated.\n", THREAD_SELF() );
	fflush( stdout );

	/* Create the session and try to activate it.  We don't do anything
	   beyond that point since this is a test of multi-thread handling
	   capability, not session handling */
	status = cryptCreateSession( &cryptSession, CRYPT_UNUSED,
								 CRYPT_SESSION_SSH );
	if( cryptStatusError( status ) )
		{
		printf( "cryptCreateSession() failed with error code %d, line %d.\n",
				status, __LINE__ );
		THREAD_EXIT();
		}
	if( !setLocalConnect( cryptSession, 22 ) )
		{
		THREAD_EXIT();
		}
	status = cryptSetAttribute( cryptSession,
								CRYPT_OPTION_NET_CONNECTTIMEOUT, 10 );
	if( cryptStatusOK( status ) )
		status = cryptSetAttributeString( cryptSession,
										  CRYPT_SESSINFO_USERNAME,
										  SSH_USER_NAME,
										  paramStrlen( SSH_USER_NAME ) );
	if( cryptStatusOK( status ) )
		status = cryptSetAttributeString( cryptSession,
										  CRYPT_SESSINFO_PASSWORD,
										  SSH_PASSWORD,
										  paramStrlen( SSH_PASSWORD ) );
	if( cryptStatusError( status ) )
		{
		printf( "cryptSetAttribute/AttributeString() failed with error code "
				"%d, line %d.\n", status, __LINE__ );
		THREAD_EXIT();
		}
	printf( "Client for thread %lX activated.\n", THREAD_SELF() );
	status = cryptSetAttribute( cryptSession, CRYPT_SESSINFO_ACTIVE, TRUE );
	printConnectInfo( cryptSession );
	if( cryptStatusError( status ) )
		printExtError( cryptSession,
					   "Attempt to activate SSH client session", status,
					   __LINE__ );
	cryptDestroySession( cryptSession );
	printf( "Client for thread %lX has exited.\n", THREAD_SELF() );
	fflush( stdout );

	THREAD_EXIT();
	}

int testSessionSSHClientServerMultiThread( void )
	{
	return( multiThreadDispatch( sshClientMultiThread, 
								 sshServerMultiThread, MAX_NO_THREADS ) );
	}
#endif /* OS-specific threading functions */

/* Create an SSH channel */

static int createChannel( const CRYPT_SESSION cryptSession,
						  const C_STR type, const C_STR arg1 )
	{
	int status;

	status = cryptSetAttribute( cryptSession, CRYPT_SESSINFO_SSH_CHANNEL,
								CRYPT_UNUSED );
	if( cryptStatusOK( status ) )
		status = cryptSetAttributeString( cryptSession,
										  CRYPT_SESSINFO_SSH_CHANNEL_TYPE,
										  type, paramStrlen( type ) );
	if( cryptStatusOK( status ) )
		status = cryptSetAttributeString( cryptSession,
										  CRYPT_SESSINFO_SSH_CHANNEL_ARG1,
										  arg1, paramStrlen( arg1 ) );
	return( status );
	}

/* Print information on an SSH channel */

static BOOLEAN printChannelInfo( const CRYPT_SESSION cryptSession,
								 const SSH_TEST_TYPE testType,
								 const BOOLEAN isServer )
	{
	C_CHR stringBuffer[ CRYPT_MAX_TEXTSIZE + 1 ];
	C_CHR argBuffer[ CRYPT_MAX_TEXTSIZE + 1 ];
	int channel, stringLength, argLength = 0, status;

	status = cryptGetAttribute( cryptSession, CRYPT_SESSINFO_SSH_CHANNEL,
								&channel );
	if( cryptStatusOK( status ) )
		status = cryptGetAttributeString( cryptSession,
										  CRYPT_SESSINFO_SSH_CHANNEL_TYPE,
										  stringBuffer, &stringLength );
	if( cryptStatusError( status ) )
		{
		printf( "%sCouldn't query channel ID/type, status %d, line %d.\n",
				isServer ? "SVR: " : "", status, __LINE__ );
		return( FALSE );
		}
#ifdef UNICODE_STRINGS
	stringBuffer[ stringLength / sizeof( wchar_t ) ] = TEXT( '\0' );
#else
	stringBuffer[ stringLength ] = '\0';
#endif /* UNICODE_STRINGS */
	if( !paramStrcmp( stringBuffer, TEXT( "subsystem" ) ) || \
		!paramStrcmp( stringBuffer, TEXT( "direct-tcpip" ) ) )
		{
		status = cryptGetAttributeString( cryptSession,
										  CRYPT_SESSINFO_SSH_CHANNEL_ARG1,
										  argBuffer, &argLength );
		if( cryptStatusError( status ) )
			{
			printf( "%sCouldn't query channel arg, status %d, line %d.\n",
					isServer ? "SVR: " : "", status, __LINE__ );
			return( FALSE );
			}
#ifdef UNICODE_STRINGS
		argBuffer[ argLength / sizeof( wchar_t ) ] = TEXT( '\0' );
		printf( "SVR: Client opened channel #%d, type '%S', arg '%S'.\n",
				channel, stringBuffer, argBuffer );
#else
		argBuffer[ argLength ] = '\0';
		printf( "SVR: Client opened channel #%d, type '%s', arg '%s'.\n",
				channel, stringBuffer, argBuffer );
#endif /* UNICODE_STRINGS */
		fflush( stdout );

		return( TRUE );
		}

	if( testType == SSH_TEST_SUBSYSTEM )
		{
		printf( "SVR: Client requested subsystem but server reported "
				"request as '%s', line %d.\n", stringBuffer, __LINE__ );
		return( FALSE );
		}

#ifdef UNICODE_STRINGS
	printf( "SVR: Client opened channel #%d, type '%S'.\n",
			channel, stringBuffer );
#else
	printf( "SVR: Client opened channel #%d, type '%s'.\n",
			channel, stringBuffer );
#endif /* UNICODE_STRINGS */
	fflush( stdout );
	return( TRUE );
	}

/* Print information on data sent over an SSH channel */

static BOOLEAN printDataInfo( CRYPT_SESSION cryptSession,
							  char *buffer, int *bytesCopied,
							  const BOOLEAN isServer )
	{
	int channel, status;

	status = cryptPopData( cryptSession, buffer, BUFFER_SIZE, bytesCopied );
	if( cryptStatusError( status ) )
		{
		printExtError( cryptSession, 
					   isServer ? "SVR: Client data read failed" : \
								  "Server data read failed", 
					   status, __LINE__ );
		return( FALSE );
		}
	buffer[ *bytesCopied ] = '\0';
	cryptGetAttribute( cryptSession, CRYPT_SESSINFO_SSH_CHANNEL, &channel );
	printf( "%s---- %s sent %d bytes on channel %d ----\n",
			isServer ? "SVR: " : "", isServer ? "Client" : "Server",
			*bytesCopied, channel );
	if( isServer )
		printf( "SVR: " );
	puts( buffer );
	printf( "%s---- End of output ----\n", isServer ? "SVR: " : "" );
	fflush( stdout );

	return( TRUE );
	}

/* Print information on SSH authorisation info */

static BOOLEAN printAuthInfo( CRYPT_SESSION cryptSession )
	{
	C_CHR stringBuffer[ CRYPT_MAX_TEXTSIZE + 1 ];
	int length, status;

	status = cryptGetAttributeString( cryptSession, CRYPT_SESSINFO_USERNAME,
									  stringBuffer, &length );
	if( cryptStatusOK( status ) )
		{
#ifdef UNICODE_STRINGS
		stringBuffer[ length / sizeof( wchar_t ) ] = TEXT( '\0' );
		printf( "SVR: User name = '%S', ", stringBuffer );
#else
		stringBuffer[ length ] = '\0';
		printf( "SVR: User name = '%s', ", stringBuffer );
#endif /* UNICODE_STRINGS */
		}
	if( cryptStatusOK( status ) )
		status = cryptGetAttributeString( cryptSession, CRYPT_SESSINFO_PASSWORD,
										  stringBuffer, &length );
	if( cryptStatusOK( status ) )
		{
#ifdef UNICODE_STRINGS
		stringBuffer[ length / sizeof( wchar_t ) ] = TEXT( '\0' );
		printf( "password = '%S'.\n", stringBuffer );
#else
		stringBuffer[ length ] = '\0';
		printf( "password = '%s'.\n", stringBuffer );
#endif /* UNICODE_STRINGS */
		}
	if( cryptStatusError( status ) )
		{
		printf( "SVR: Couldn't read client authentication details, "
				"status = %d, line %d.\n", status, __LINE__ );
		return( FALSE );
		}
	fflush( stdout );

	return( TRUE );
	}

/****************************************************************************
*																			*
*								SSH Routines Test							*
*																			*
****************************************************************************/

/* There are various servers running that we can use for testing, the
   following remapping allows us to switch between them.  Notes:

	Server 1: Local loopback.
	Server 2: Sends extraneous lines of text before the SSH ID string
			  (technically allowed by the RFC, but probably not in the way
			  that it's being used here).
	Server 3: Reference ssh.com implementation.
	Server 4: Reference OpenSSH implementation.
	Server 5: Generic embedded device implementation.

   To test local -> remote/remote -> local forwarding:

	ssh localhost -v -l test -pw test -L 110:pop3.test.com:110
	ssh localhost -v -l test -pw test -R 110:pop3.test.com:110

  For test purposes we connect to the OpenSSH server for the SSHv2 test
  because this is the most frequently-used one around, so maintaining
  compatibility with it whenever it changes is important.  Using it for test
  connects is slightly antisocial but in practice few people seem to run the
  self-test and we never get past the initial handshake phase so it shouldn't
  be a big deal.  Testing SSHv1 is a bit tricky since there are few of these
  servers still around, in the absence of a convenient test server we just
  try a local connect, which either times out or goes through an SSHv2
  handshake if there's a server there */

static const C_STR FAR_BSS ssh1Info[] = {
	NULL,
	TEXT( "localhost" ),
	NULL
	};
static const C_STR FAR_BSS ssh2Info[] = {
	NULL,
	TEXT( "localhost" ),
	TEXT( "sorrel.humboldt.edu:222" ),
	TEXT( "www.ssh.com" ),
	TEXT( "www.openssh.com" ),
	NULL
	};

#define SSH1_SERVER_NO	1
#define SSH2_SERVER_NO	4

/* If we're testing dual-thread handling of sessions, we need to provide a
   forward declaration of the threading function since it's called from 
   within the SSH connect code */

#ifdef WINDOWS_THREADS
  unsigned __stdcall ssh2ServerDualThread2( void *dummy );
#endif /* WINDOWS_THREADS */

/* Establish an SSH session.  The generic SSHv1 client test will always step
   up to SSHv2 if the server is v2 (which almost all are), so v1 can't
   easily be generically tested without hardcoding v1-only into
   session/ssh.c.  However, the loopback test, which forces the use of a
   v1-only server, does test the client as a v1 client */

static int connectSSH( const CRYPT_SESSION_TYPE sessionType,
					   const SSH_TEST_TYPE testType,
					   const BOOLEAN localSession )
	{
	CRYPT_SESSION cryptSession;
#ifdef SSH2_SERVER_NAME
	const C_STR serverName = SSH2_SERVER_NAME;
#else
	const C_STR serverName = localSession ? TEXT( "localhost" ) : \
							 ( testType == SSH_TEST_SSH1 ) ? \
								ssh1Info[ SSH1_SERVER_NO ] : \
								ssh2Info[ SSH2_SERVER_NO ];
#endif /* SSH2_SERVER_NAME */
	const BOOLEAN isServer = ( sessionType == CRYPT_SESSION_SSH_SERVER ) ? \
							   TRUE : FALSE;
	char buffer[ BUFFER_SIZE ];
	int channel, bytesCopied, status;

	/* If this is a local session, synchronise the client and server */
	if( localSession )
		{
		if( isServer )
			{
			/* Acquire the init mutex */
			acquireMutex();
			}
		else
			{
			/* We're the client Wait for the server to finish initialising */
			if( waitMutex() == CRYPT_ERROR_TIMEOUT )
				{
				printf( "Timed out waiting for server to initialise, "
						"line %d.\n", __LINE__ );
				return( FALSE );
				}
			}
		}

	/* If this is the dual-thread server test and we're the second server 
	   thread, skip the portions that have already been handled by the first 
	   thread */
#ifdef WINDOWS_THREADS
	if( isServer && testType == SSH_TEST_DUALTHREAD2 )
		goto dualThreadContinue;
#endif /* WINDOWS_THREADS */

	printf( "%sTesting %sSSH%s%s session...\n",
			isServer ? "SVR: " : "",
			localSession ? "local " : "",
			( testType == SSH_TEST_SSH1 ) ? "v1" : "v2",
			( testType == SSH_TEST_SUBSYSTEM ) ? " SFTP" : \
				( testType == SSH_TEST_PORTFORWARDING ) ? " port-forwarding" : \
				( testType == SSH_TEST_EXEC ) ? " remote exec" : \
				( testType == SSH_TEST_MULTICHANNEL ) ? " multi-channel" : \
				( testType == SSH_TEST_CLIENTCERT ) ? " pubkey-auth" : "" );
	if( !isServer && !localSession )
#ifdef UNICODE_STRINGS
		printf( "  Remote host: %S.\n", serverName );
#else
		printf( "  Remote host: %s.\n", serverName );
#endif /* UNICODE_STRINGS */
	fflush( stdout );

	/* Create the session */
	status = cryptCreateSession( &cryptSession, CRYPT_UNUSED, sessionType );
	if( status == CRYPT_ERROR_PARAM3 )	/* SSH session access not available */
		return( CRYPT_ERROR_NOTAVAIL );
	if( cryptStatusError( status ) )
		{
		printf( "cryptCreateSession() failed with error code %d, line %d.\n",
				status, __LINE__ );
		return( FALSE );
		}

	/* Set up the server and user information and activate the session */
	if( isServer )
		{
		CRYPT_CONTEXT privateKey;

		if( !setLocalConnect( cryptSession, 22 ) )
			return( FALSE );
		status = getPrivateKey( &privateKey, SSH_PRIVKEY_FILE,
								USER_PRIVKEY_LABEL, TEST_PRIVKEY_PASSWORD );
		if( cryptStatusOK( status ) )
			{
			status = cryptSetAttribute( cryptSession,
										CRYPT_SESSINFO_PRIVATEKEY, privateKey );
			cryptDestroyContext( privateKey );
			}
		}
	else
		{
		if( localSession )
			{
			if( !setLocalConnect( cryptSession, 22 ) )
				return( FALSE );
			}
		else
			{
			status = cryptSetAttributeString( cryptSession,
									CRYPT_SESSINFO_SERVER_NAME,
									serverName, paramStrlen( serverName ) );
			}
		if( cryptStatusOK( status ) )
			status = cryptSetAttributeString( cryptSession,
									CRYPT_SESSINFO_USERNAME,
									SSH_USER_NAME,
									paramStrlen( SSH_USER_NAME ) );
		if( cryptStatusOK( status ) )
			{
			if( testType == SSH_TEST_CLIENTCERT )
				{
				CRYPT_CONTEXT privateKey;

				status = getPrivateKey( &privateKey, USER_PRIVKEY_FILE,
									USER_PRIVKEY_LABEL, TEST_PRIVKEY_PASSWORD );

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -