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

📄 ssh.c

📁 cryptlib安全工具包
💻 C
📖 第 1 页 / 共 5 页
字号:
				if( cryptStatusOK( status ) )
					{
					status = cryptSetAttribute( cryptSession,
									CRYPT_SESSINFO_PRIVATEKEY, privateKey );
					cryptDestroyContext( privateKey );
					}
				}
			else
				{
#ifdef USER_SUPPLIED_PASSWORD
				char password[ 256 ];

				printf( "Enter SSHv2 server password: " );
				fgets( password, 255, stdin );
				password[ strlen( password ) - 1 ] = '\0';
				status = cryptSetAttributeString( cryptSession,
									CRYPT_SESSINFO_PASSWORD,
									password, strlen( password ) );
#else
				status = cryptSetAttributeString( cryptSession,
									CRYPT_SESSINFO_PASSWORD,
									SSH_PASSWORD,
									paramStrlen( SSH_PASSWORD ) );
#endif /* User-supplied password */
				}
			}
		if( cryptStatusOK( status ) && \
			( testType == SSH_TEST_SUBSYSTEM ) )
			status = createChannel( cryptSession, TEXT( "subsystem" ),
									TEXT( "sftp" ) );
		if( cryptStatusOK( status ) && \
			( testType == SSH_TEST_PORTFORWARDING || \
			  testType == SSH_TEST_MULTICHANNEL ) )
			createChannel( cryptSession, TEXT( "direct-tcpip" ),
							TEXT( "localhost:1234" ) );
		if( cryptStatusOK( status ) && \
			( testType == SSH_TEST_FINGERPRINT ) )
			{
			BYTE fingerPrint[ CRYPT_MAX_HASHSIZE ];

			/* Set a dummy (all-zero) fingerprint to force the connect to
			   fail */
			memset( fingerPrint, 0, CRYPT_MAX_HASHSIZE );
			status = cryptSetAttributeString( cryptSession,
											  CRYPT_SESSINFO_SERVER_FINGERPRINT,
											  fingerPrint, 16 );
			}
		if( cryptStatusOK( status ) && \
			( testType == SSH_TEST_EXEC ) )
			status = createChannel( cryptSession, TEXT( "exec" ),
									TEXT( "/bin/netstat" ) );
		}
	if( cryptStatusOK( status ) )
		status = cryptSetAttribute( cryptSession, CRYPT_SESSINFO_VERSION,
									( testType == SSH_TEST_SSH1 ) ? 1 : 2 );
	if( cryptStatusOK( status ) && isServer && \
		( testType != SSH_TEST_CONFIRMAUTH && \
		  testType != SSH_TEST_DUALTHREAD ) )
		{
		/* If we're not testing manual confirmation of client auth, have
		   cryptlib automatically confirm the auth */
		status = cryptSetAttribute( cryptSession, CRYPT_SESSINFO_AUTHRESPONSE,
									TRUE );
		}
	if( cryptStatusError( status ) )
		{
		/* If we're trying to enable SSHv1 and it fails, this isn't an error
		   since this protocol is disabled by default */
		if( testType == SSH_TEST_SSH1 )
			{
			puts( "SSHv1 appears to be disbled in this build." );
			cryptDestroySession( cryptSession );
			puts( isServer ? "SVR: SSH server session succeeded.\n" : \
							 "SSH client session succeeded.\n" );
			return( CRYPT_ERROR_NOTAVAIL );
			}

		printf( "%scryptSetAttribute/AttributeString() failed with error "
				"code %d, line %d.\n", isServer ? "SVR: " : "", status, 
				__LINE__ );
		return( FALSE );
		}

	/* Activate the session.  Since we need to be able to process out-of-
	   band signalling such as channel control messages, we set a non-zero
	   timeout for reads */
	cryptSetAttribute( cryptSession, CRYPT_OPTION_NET_READTIMEOUT, 5 );
	if( localSession && isServer )
		/* Tell the client that we're ready to go */
		releaseMutex();
	status = cryptSetAttribute( cryptSession, CRYPT_SESSINFO_ACTIVE, TRUE );
	if( isServer )
		{
#ifdef WINDOWS_THREADS
		if( isServer && testType == SSH_TEST_DUALTHREAD && \
			status == CRYPT_ENVELOPE_RESOURCE )
			{
			static CRYPT_SESSION localCryptSession = 0;
			unsigned threadID;

			/* Start a second thread to complete the handshake and exit */
			localCryptSession = cryptSession;
			_beginthreadex( NULL, 0, ssh2ServerDualThread2, NULL, 0, 
							&threadID );
			return( TRUE );

			/* The second thread continues from here */
dualThreadContinue:
			assert( localSession > 0 );
			cryptSession = localCryptSession;

			/* Allow the auth.and complete the handshake */
			puts( "SVR: Confirming authentication to client..." );
			status = cryptSetAttribute( cryptSession,
										CRYPT_SESSINFO_AUTHRESPONSE, TRUE );
			if( cryptStatusOK( status ) )
				status = cryptSetAttribute( cryptSession,
											CRYPT_SESSINFO_ACTIVE, TRUE );
			}
#endif /* WINDOWS_THREADS */
		if( status == CRYPT_ENVELOPE_RESOURCE )
			{
			/* The client has tried to authenticate themselves, print the
			   info */
			if( !printAuthInfo( cryptSession ) )
				return( FALSE );

			/* Deny the auth.and force them to retry */
			puts( "SVR: Denying authentication to client, who should reauth..." );
			status = cryptSetAttribute( cryptSession,
										CRYPT_SESSINFO_AUTHRESPONSE, FALSE );
			if( cryptStatusOK( status ) )
				status = cryptSetAttribute( cryptSession,
											CRYPT_SESSINFO_ACTIVE, TRUE );
			if( status != CRYPT_ENVELOPE_RESOURCE )
				{
				printf( "SVR: Attempt to deny auth.to client failed with error "
						"code %d, line %d.\n", status, __LINE__ );
				return( FALSE );
				}
			if( !printAuthInfo( cryptSession ) )
				return( FALSE );

			/* Allow the auth.and complete the handshake */
			puts( "SVR: Confirming authentication to client..." );
			status = cryptSetAttribute( cryptSession,
										CRYPT_SESSINFO_AUTHRESPONSE, TRUE );
			if( cryptStatusOK( status ) )
				status = cryptSetAttribute( cryptSession,
											CRYPT_SESSINFO_ACTIVE, TRUE );
			}

		/* Now that the handshake is complete, display the connection info */
		if( cryptStatusOK( status ) && !printConnectInfo( cryptSession ) )
			return( FALSE );
		}
	if( cryptStatusError( status ) )
		{
		if( testType == SSH_TEST_FINGERPRINT )
			{
			/* We've forced the connect to fail by using a dummy fingerprint,
			   everything is OK */
			if( isServer )
				printf( "SVR: " );
			puts( "SSH client rejected key with invalid fingerprint." );
			cryptDestroySession( cryptSession );
			puts( isServer ? "SVR: SSH server session succeeded.\n" : \
							 "SSH client session succeeded.\n" );
			fflush( stdout );
			return( TRUE );
			}
		printExtError( cryptSession, isServer ? \
					   "SVR: Attempt to activate SSH server session" : \
					   "Attempt to activate SSH client session", status,
					   __LINE__ );
		cryptDestroySession( cryptSession );
		if( status == CRYPT_ERROR_OPEN || status == CRYPT_ERROR_NOTFOUND )
			{
			/* These servers are constantly appearing and disappearing so if
			   we get a straight connect error we don't treat it as a serious
			   failure */
			puts( "  (Server could be down, faking it and continuing...)\n" );
			return( CRYPT_ERROR_FAILED );
			}
		if( status == CRYPT_ERROR_WRONGKEY )
			{
			/* This is another possible soft error condition, the default
			   username and password shouldn't be able to get into many
			   machines */
			puts( "  (Incorrect username/password, continuing...)\n" );
			return( TRUE );
			}
		if( status == CRYPT_ERROR_NOSECURE )
			{
			/* Another soft error condition, the server can't handle the
			   security level we want (usually occurs when trying to perform
			   an SSHv2 connect to an SSHv1 server) */
			puts( "  (Insufficiently secure protocol parameters, "
				  "continuing...)\n" );
			return( TRUE );
			}
		return( FALSE );
		}
	if( testType == SSH_TEST_FINGERPRINT )
		{
		printf( "Attempt to connect with invalid key fingerprint succeeded "
				"when it should\nhave failed, line %d.\n", __LINE__ );
		return( FALSE );
		}

	/* Report the session security info */
	if( !printSecurityInfo( cryptSession, isServer, TRUE ) )
		return( FALSE );
	status = cryptGetAttribute( cryptSession, CRYPT_SESSINFO_SSH_CHANNEL,
								&channel );
	if( cryptStatusError( status ) )
		{
		printf( "cryptGetAttributeString() failed with error code "
				"%d, line %d.\n", status, __LINE__ );
		return( FALSE );
		}
	printf( "%sCurrent channel is #%d.\n", isServer ? "SVR: " : "",
			channel );
	fflush( stdout );

	/* Report additional channel-specific information */
	if( isServer )
		{
		/* Display info on any channels that the client has opened */
		if( !printChannelInfo( cryptSession, testType, TRUE ) )
			return( FALSE );

		/* Process any additional information that the client may throw
		   at us after the user-auth has completed */
		status = cryptPopData( cryptSession, buffer, BUFFER_SIZE,
							   &bytesCopied );
		if( cryptStatusOK( status ) && bytesCopied > 0 )
			{
			printf( "SVR: Client sent additional %d bytes post-"
					"handshake data.\n", bytesCopied );
			fflush( stdout );
			}
		else
			{
			if( status == CRYPT_ENVELOPE_RESOURCE )
				{
				/* The client performed additional control actions that were
				   handled inline as part of the data-pop, report the
				   details */
				if( !printChannelInfo( cryptSession, testType, TRUE ) )
					return( FALSE );
				}
			}
		}

	/* If we're using the SFTP subsystem as a server, use the special-case
	   routines for this */
#ifdef WINDOWS_THREADS
	if( testType == SSH_TEST_SUBSYSTEM )
		{
		if( isServer )
			{
			int sftpServer( const CRYPT_SESSION cryptSession );

			status = sftpServer( cryptSession );
			if( cryptStatusError( status ) )
				{
				printf( "SVR: Couldn't receive SFTP data from client, status %d, "
						"line %d.\n", status, __LINE__ );
				return( FALSE );
				}
			cryptDestroySession( cryptSession );
			puts( "SVR: SFTP server session succeeded.\n" );
			fflush( stdout );
			return( TRUE );
			}
		else
			{
			int sftpClient( const CRYPT_SESSION cryptSession );

			status = sftpClient( cryptSession );
			if( cryptStatusError( status ) )
				{
				printf( "Couldn't send SFTP data to server, status %d, line "
						"%d.\n", status, __LINE__ );
				return( FALSE );
				}
			cryptDestroySession( cryptSession );
			puts( "SFTP client session succeeded.\n" );
			fflush( stdout );
			return( TRUE );
			}
		}
#endif /* WINDOWS_THREADS */

	/* If we're performing a multi-channel test, open a second channel (the
	   server handles this as part of its general connect-handling) */
	if( testType == SSH_TEST_MULTICHANNEL && !isServer )
		{
		status = createChannel( cryptSession, TEXT( "direct-tcpip" ),
								TEXT( "localhost:5678" ) );
		if( cryptStatusOK( status ) )
			status = cryptGetAttribute( cryptSession,
										CRYPT_SESSINFO_SSH_CHANNEL,
										&channel );
		if( cryptStatusOK( status ) )
			status = cryptSetAttribute( cryptSession,
										CRYPT_SESSINFO_SSH_CHANNEL_ACTIVE,
										TRUE );
		if( cryptStatusError( status ) )
			{
			printf( "Couldn't open second SSH chanel, status %d, line "
					"%d.\n", status, __LINE__ );
			return( FALSE );
			}
		printf( "Opened additional channel #%d to server.\n", channel );
		fflush( stdout );
		}

	/* Send data over the SSH link */
	if( isServer )
		{
		/* Send a status message to the client */
		status = cryptPushData( cryptSession, "Welcome to cryptlib, now go "
								"away.\r\n", 35, &bytesCopied );
		if( cryptStatusOK( status ) )
			status = cryptFlushData( cryptSession );
		if( cryptStatusError( status ) || bytesCopied != 35 )
			{
			printf( "SVR: Couldn't send data to client, status %d, line "
					"%d.\n", status, __LINE__ );
			return( FALSE );
			}
		}

	/* Wait a bit while data arrives */
	delayThread( 2 );

	/* Print the first lot of output from the other side */
	if( !printDataInfo( cryptSession, buffer, &bytesCopied, isServer ) )
		return( FALSE );

	/* If we're the server, echo the command to the client */
	if( isServer )
		{
		const int clientBytesCopied = bytesCopied;
		int dummy, i;

		/* If it's a multi-channel test, send the response back on a
		   different channel.  The currently-selected channel will be the
		   last one that the client opened (#2), so we can hardcode in
		   #1 for testing purposes */
		if( testType == SSH_TEST_MULTICHANNEL )
			{
			status = cryptSetAttribute( cryptSession,
										CRYPT_SESSINFO_SSH_CHANNEL, 1 );
			if( cryptStatusError( status ) )
				{
				printf( "SVR: Couldn't select channel #1 to return data to "
						"client, status %d, line %d.\n", status, __LINE__ );
				return( FALSE );
				}
			}
		for( i = 0; i < clientBytesCopied; i++ )
			{
			if( buffer[ i ] < ' ' || buffer[ i ] >= 0x7F )
				buffer[ i ] = '.';
			}
		status = cryptPushData( cryptSession, "Input was [", 11, &dummy );
		if( cryptStatusOK( status ) && clientBytesCopied > 0 )
			status = cryptPushData( cryptSession, buffer, clientBytesCopied,
									&bytesCopied );
		if( cryptStatusOK( status ) )
			status = cryptPushData( cryptSession, "]\r\n", 3, &dummy );
		if( cryptStatusOK( status ) )
			status = cryptFlushData( cryptSession );
		if( cryptStatusError( status ) || bytesCopied != clientBytesCopied )
			{
			printf( "SVR: Couldn't send data to client, status %d, line "
					"%d.\n", status, __LINE__ );
			return( FALSE );
			}
		}
	else
		{
		/* We're the client, if it's a session to a Unix ssh server, send a
		   sample command and display the output */
		if( !localSession )
			{
			/* Send a command to the server and get the results */
			status = cryptPushData( cryptSession, "ls -l | head -25\n", 18,
									&bytesCopied );
			if( cryptStatusOK( status ) )
				status = cryptFlushData( cryptSession );
			if( cryptStatusError( status ) || bytesCopied != 18 )
				{
				printf( "Couldn't send data to server, status %d, line "
						"%d.\n", status, __LINE__ );
				return( FALSE );
				}
			puts( "Sent 'ls -l | head -25'" );
			delayThread( 3 );
			if( !printDataInfo( cryptSession, buffer, &bytesCopied, 
								isServer ) )
				return( FALSE );

⌨️ 快捷键说明

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