Skip to content
Snippets Groups Projects
Select Git revision
  • dailybuild_linux-x64
  • dailybuild_win32
  • master default protected
  • dd_msg_reader_use_dd_msg_area_chooser_and_area_sort_update
  • sqlite
  • rip_abstraction
  • dailybuild_macos-armv8
  • dd_file_lister_filanem_in_desc_color
  • mode7
  • dd_msg_reader_are_you_there_warning_improvement
  • c23-playing
  • syncterm-1.3
  • syncterm-1.2
  • test-build
  • hide_remote_connection_with_telgate
  • 638-can-t-control-c-during-a-file-search
  • add_body_to_pager_email
  • mingw32-build
  • cryptlib-3.4.7
  • ree/mastermind
  • sbbs320d
  • syncterm-1.6
  • syncterm-1.5
  • syncterm-1.4
  • sbbs320b
  • syncterm-1.3
  • syncterm-1.2
  • syncterm-1.2rc6
  • syncterm-1.2rc5
  • push
  • syncterm-1.2rc4
  • syncterm-1.2rc2
  • syncterm-1.2rc1
  • sbbs319b
  • sbbs318b
  • goodbuild_linux-x64_Sep-01-2020
  • goodbuild_win32_Sep-01-2020
  • goodbuild_linux-x64_Aug-31-2020
  • goodbuild_win32_Aug-31-2020
  • goodbuild_win32_Aug-30-2020
40 results

ssh.c

Blame
  • ssh.c 6.25 KiB
    /* Copyright (C), 2007 by Stephen Hurd */
    
    /* $Id$ */
    
    #include <stdlib.h>
    
    #include "gen_defs.h"
    #include "genwrap.h"
    #include "sockwrap.h"
    #include "threadwrap.h"
    
    #include "bbslist.h"
    #include "conn.h"
    #include "uifcinit.h"
    
    #include "st_crypt.h"
    
    static SOCKET	sock;
    CRYPT_SESSION	ssh_session;
    int				ssh_active=FALSE;
    
    static void cryptlib_error_message(int status, char * msg)
    {
    	char	str[32];
    	char	str2[32];
    	char	*errmsg;
    	int		err_len;
    
    	sprintf(str,"Error %d %s\r\n\r\n",status, msg);
    	cl.GetAttributeString(ssh_session, CRYPT_ATTRIBUTE_ERRORMESSAGE, NULL, &err_len);
    	errmsg=(char *)malloc(err_len+strlen(str)+5);
    	strcpy(errmsg, str);
    	cl.GetAttributeString(ssh_session, CRYPT_ATTRIBUTE_ERRORMESSAGE, errmsg+strlen(str), &err_len);
    	errmsg[strlen(str)+err_len]=0;
    	strcat(errmsg,"\r\n\r\n");
    	sprintf(str2,"Error %s", msg);
    	uifcmsg(str2, errmsg);
    	free(errmsg);
    }
    
    void ssh_input_thread(void *args)
    {
    	fd_set	rds;
    	int status;
    	int rd;
    	size_t	buffered;
    	size_t	buffer;
    	struct timeval tv;
    
    	conn_api.input_thread_running=1;
    	while(ssh_active && !conn_api.terminate) {
    		FD_ZERO(&rds);
    		FD_SET(sock, &rds);
    		tv.tv_sec = 0;
    		tv.tv_usec = 100;
    
    		rd=select(sock+1, &rds, NULL, NULL, &tv);
    		if(rd==-1) {
    			if(errno==EBADF)
    				break;
    			rd=0;
    		}
    		if(rd == 0)
    			continue;
    		while(rd) {
    			status=cl.PopData(ssh_session, conn_api.rd_buf, conn_api.rd_buf_size, &rd);
    			if(cryptStatusError(status)) {
    				if(status==CRYPT_ERROR_COMPLETE || status == CRYPT_ERROR_READ) {	/* connection closed */
    					ssh_active=FALSE;
    					break;
    				}
    				cryptlib_error_message(status, "recieving data");
    				break;
    			}
    			else {
    				buffered=0;
    				while(buffered < rd) {
    					pthread_mutex_lock(&(conn_inbuf.mutex));
    					buffer=conn_buf_wait_free(&conn_inbuf, rd-buffered, 100);
    					buffered+=conn_buf_put(&conn_inbuf, conn_api.rd_buf+buffered, buffer);
    					pthread_mutex_unlock(&(conn_inbuf.mutex));
    				}
    			}
    		}
    	}
    	conn_api.input_thread_running=0;
    }
    
    void ssh_output_thread(void *args)
    {
    	int		wr;
    	int		ret;
    	size_t	sent;
    	int		status;
    
    	conn_api.output_thread_running=1;
    	while(ssh_active && !conn_api.terminate) {
    		pthread_mutex_lock(&(conn_outbuf.mutex));
    		wr=conn_buf_wait_bytes(&conn_outbuf, 1, 100);
    		if(wr) {
    			wr=conn_buf_get(&conn_outbuf, conn_api.wr_buf, conn_api.wr_buf_size);
    			pthread_mutex_unlock(&(conn_outbuf.mutex));
    			sent=0;
    			while(sent < wr) {
    				status=cl.PushData(ssh_session, conn_api.wr_buf+sent, wr-sent, &ret);
    				if(cryptStatusError(status)) {
    					if(status==CRYPT_ERROR_COMPLETE) {	/* connection closed */
    						ssh_active=FALSE;
    						break;
    					}
    					cryptlib_error_message(status, "sending data");
    					break;
    				}
    				sent += ret;
    			}
    			if(sent)
    				cl.FlushData(ssh_session);
    		}
    		else
    			pthread_mutex_unlock(&(conn_outbuf.mutex));
    	}
    	conn_api.output_thread_running=0;
    }
    
    int ssh_connect(struct bbslist *bbs)
    {
    	int off=1;
    	int status;
    	char password[MAX_PASSWD_LEN+1];
    	char username[MAX_USER_LEN+1];
    
    	init_uifc(TRUE, TRUE);
    
    	if(!crypt_loaded) {
    		uifcmsg("Cannot load cryptlib - SSH inoperative",	"`Cannot load cryptlib`\n\n"
    					"Cannot load the file "
    #ifdef _WIN32
    					"cl32.dll"
    #else
    					"libcl.so"
    #endif
    					"\nThis file is required for SSH functionality.\n\n"
    					"The newest version is always available from:\n"
    					"http://www.cs.auckland.ac.nz/~pgut001/cryptlib/"
    					);
    		return(conn_api.terminate=-1);
    	}
    
    	sock=conn_socket_connect(bbs);
    	if(sock==INVALID_SOCKET)
    		return(-1);
    
    	ssh_active=FALSE;
    
    	uifc.pop("Creating Session");
    	status=cl.CreateSession(&ssh_session, CRYPT_UNUSED, CRYPT_SESSION_SSH);
    	if(cryptStatusError(status)) {
    		char	str[1024];
    		sprintf(str,"Error %d creating session",status);
    		uifcmsg("Error creating session",str);
    		conn_api.terminate=1;
    		uifc.pop(NULL);
    		return(-1);
    	}
    
    	/* we need to disable Nagle on the socket. */
    	setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, ( char * )&off, sizeof ( off ) );
    
    	SAFECOPY(password,bbs->password);
    	SAFECOPY(username,bbs->user);
    
    	uifc.pop(NULL);
    
    	if(!username[0])
    		uifcinput("UserID",MAX_USER_LEN,username,0,"No stored UserID.");
    
    	uifc.pop("Setting Username");
    	/* Add username/password */
    	status=cl.SetAttributeString(ssh_session, CRYPT_SESSINFO_USERNAME, username, strlen(username));
    	if(cryptStatusError(status)) {
    		char	str[1024];
    		sprintf(str,"Error %d setting username",status);
    		uifcmsg("Error setting username",str);
    		conn_api.terminate=1;
    		uifc.pop(NULL);
    		return(-1);
    	}
    
    	uifc.pop(NULL);
    	if(!password[0])
    		uifcinput("Password",MAX_PASSWD_LEN,password,K_PASSWORD,"Incorrect password.  Try again.");
    
    	uifc.pop("Setting Password");
    	status=cl.SetAttributeString(ssh_session, CRYPT_SESSINFO_PASSWORD, password, strlen(password));
    	if(cryptStatusError(status)) {
    		char	str[1024];
    		sprintf(str,"Error %d setting password",status);
    		uifcmsg("Error setting password",str);
    		conn_api.terminate=1;
    		uifc.pop(NULL);
    		return(-1);
    	}
    
    	uifc.pop(NULL);
    	uifc.pop("Setting Username");
    	/* Pass socket to cryptlib */
    	status=cl.SetAttribute(ssh_session, CRYPT_SESSINFO_NETWORKSOCKET, sock);
    	if(cryptStatusError(status)) {
    		char	str[1024];
    		sprintf(str,"Error %d passing socket",status);
    		uifcmsg("Error passing socket",str);
    		conn_api.terminate=1;
    		uifc.pop(NULL);
    		return(-1);
    	}
    
    	/* Activate the session */
    	uifc.pop(NULL);
    	uifc.pop("Activating Session");
    	status=cl.SetAttribute(ssh_session, CRYPT_SESSINFO_ACTIVE, 1);
    	if(cryptStatusError(status)) {
    		cryptlib_error_message(status, "activating session");
    		conn_api.terminate=1;
    		uifc.pop(NULL);
    		return(-1);
    	}
    
    	ssh_active=TRUE;
    	uifc.pop(NULL);
    
    	create_conn_buf(&conn_inbuf, BUFFER_SIZE);
    	create_conn_buf(&conn_outbuf, BUFFER_SIZE);
    	conn_api.rd_buf=(unsigned char *)malloc(BUFFER_SIZE);
    	conn_api.rd_buf_size=BUFFER_SIZE;
    	conn_api.wr_buf=(unsigned char *)malloc(BUFFER_SIZE);
    	conn_api.wr_buf_size=BUFFER_SIZE;
    
    	_beginthread(ssh_output_thread, 0, NULL);
    	_beginthread(ssh_input_thread, 0, NULL);
    
    	uifc.pop(NULL);
    
    	return(0);
    }
    
    int ssh_close(void)
    {
    	conn_api.terminate=1;
    	ssh_active=FALSE;
    	cl.SetAttribute(ssh_session, CRYPT_SESSINFO_ACTIVE, 0);
    	while(conn_api.input_thread_running || conn_api.output_thread_running)
    		SLEEP(1);
    	cl.DestroySession(ssh_session);
    	closesocket(sock);
    	sock=INVALID_SOCKET;
    	destroy_conn_buf(&conn_inbuf);
    	destroy_conn_buf(&conn_outbuf);
    	FREE_AND_NULL(conn_api.rd_buf);
    	FREE_AND_NULL(conn_api.wr_buf);
    	return(0);
    }