Exemplo n.º 1
0
int
mm_answer_pty(int sock, Buffer *m)
{
	extern struct monitor *pmonitor;
	Session *s;
	int res, fd0;

	debug3("%s entering", __func__);

	buffer_clear(m);
	s = session_new();
	if (s == NULL)
		goto error;
	s->authctxt = authctxt;
	s->pw = authctxt->pw;
	s->pid = pmonitor->m_pid;
	res = pty_allocate(&s->ptyfd, &s->ttyfd, s->tty, sizeof(s->tty));
	if (res == 0)
		goto error;
	pty_setowner(authctxt->pw, s->tty);

	buffer_put_int(m, 1);
	buffer_put_cstring(m, s->tty);

	/* We need to trick ttyslot */
	if (dup2(s->ttyfd, 0) == -1)
		fatal("%s: dup2", __func__);

	mm_record_login(s, authctxt->pw);

	/* Now we can close the file descriptor again */
	close(0);

	/* send messages generated by record_login */
	buffer_put_string(m, buffer_ptr(&loginmsg), buffer_len(&loginmsg));
	buffer_clear(&loginmsg);

	mm_request_send(sock, MONITOR_ANS_PTY, m);

	mm_send_fd(sock, s->ptyfd);
	mm_send_fd(sock, s->ttyfd);

	/* make sure nothing uses fd 0 */
	if ((fd0 = open(_PATH_DEVNULL, O_RDONLY)) < 0)
		fatal("%s: open(/dev/null): %s", __func__, strerror(errno));
	if (fd0 != 0)
		error("%s: fd0 %d != 0", __func__, fd0);

	/* slave is not needed */
	close(s->ttyfd);
	s->ttyfd = s->ptyfd;
	/* no need to dup() because nobody closes ptyfd */
	s->ptymaster = s->ptyfd;

	debug3("%s: tty %s ptyfd %d",  __func__, s->tty, s->ttyfd);

	return (0);

 error:
	if (s != NULL)
		mm_session_close(s);
	buffer_put_int(m, 0);
	mm_request_send(sock, MONITOR_ANS_PTY, m);
	return (0);
}
Exemplo n.º 2
0
/* Set up a session pty which will be used to execute the shell or program.
 * The pty is allocated now, and kept for when the shell/program executes.
 * Returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */
static int sessionpty(struct ChanSess * chansess) {

	unsigned int termlen;
	unsigned char namebuf[65];
	struct termios termio;

	TRACE(("enter sessionpty"));
	chansess->term = buf_getstring(ses.payload, &termlen);
	if (termlen > MAX_TERM_LEN) {
		/* TODO send disconnect ? */
		TRACE(("leave sessionpty: term len too long"));
		return DROPBEAR_FAILURE;
	}
	chansess->termc = buf_getint(ses.payload);
	chansess->termr = buf_getint(ses.payload);
	chansess->termw = buf_getint(ses.payload);
	chansess->termh = buf_getint(ses.payload);

	/* allocate the pty */
	assert(chansess->master == -1); /* haven't already got one */
	if (pty_allocate(&chansess->master, &chansess->slave, namebuf, 64) == 0) {
		TRACE(("leave sessionpty: failed to allocate pty"));
		return DROPBEAR_FAILURE;
	}
	
	chansess->tty = (char*)strdup(namebuf);
	if (!chansess->tty) {
		dropbear_exit("out of memory"); /* TODO disconnect */
	}

	pty_setowner(ses.authstate.pw, chansess->tty);
	pty_change_window_size(chansess->master, chansess->termr, chansess->termc,
			chansess->termw, chansess->termh);

	/* Term modes */
	/* We'll ignore errors and continue if we can't set modes.
	 * We're ignoring baud rates since they seem evil */
	if (tcgetattr(chansess->master, &termio) == 0) {
		unsigned char opcode;
		unsigned int value;
		const struct TermCode * termcode;

		while (((opcode = buf_getbyte(ses.payload)) != 0x00) &&
				opcode <= 159) {
			/* handle types of code */
			if (opcode > MAX_TERMCODE) {
				continue;
			}
			termcode = &termcodes[(unsigned int)opcode];
			
			value = buf_getint(ses.payload);

			switch (termcode->type) {

				case TERMCODE_NONE:
					break;

				case TERMCODE_CONTROLCHAR:
					termio.c_cc[termcode->mapcode] = value;
					break;

				case TERMCODE_INPUT:
					if (value) {
						termio.c_iflag |= termcode->mapcode;
					} else {
						termio.c_iflag &= ~(termcode->mapcode);
					}
					break;

				case TERMCODE_OUTPUT:
					if (value) {
						termio.c_oflag |= termcode->mapcode;
					} else {
						termio.c_oflag &= ~(termcode->mapcode);
					}
					break;

				case TERMCODE_LOCAL:
					if (value) {
						termio.c_lflag |= termcode->mapcode;
					} else {
						termio.c_lflag &= ~(termcode->mapcode);
					}
					break;

				case TERMCODE_CONTROL:
					if (value) {
						termio.c_cflag |= termcode->mapcode;
					} else {
						termio.c_cflag &= ~(termcode->mapcode);
					}
					break;
					
			}
		}
		if (tcsetattr(chansess->master, TCSANOW, &termio) < 0) {
			dropbear_log(LOG_INFO, "error setting terminal attributes");
		}
	}

	TRACE(("leave sessionpty"));
	return DROPBEAR_SUCCESS;
}