/* Create a new channel, and start the open request. This is intended * for X11, agent, tcp forwarding, and should be filled with channel-specific * options, with the calling function calling encrypt_packet() after * completion. It is mandatory for the caller to encrypt_packet() if * DROPBEAR_SUCCESS is returned */ int send_msg_channel_open_init(int fd, const char * typestring) { struct Channel* chan; chan = newchannel(0, CHANNEL_ID_AGENT, 0, 0); if (!chan) { return DROPBEAR_FAILURE; } /* set fd non-blocking */ if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) { return DROPBEAR_FAILURE; } chan->infd = chan->outfd = fd; ses.maxfd = MAX(ses.maxfd, fd); /* now open the channel connection */ CHECKCLEARTOWRITE(); buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_OPEN); buf_putstring(ses.writepayload, typestring, strlen(typestring)); buf_putint(ses.writepayload, chan->index); buf_putint(ses.writepayload, RECV_MAXWINDOW); buf_putint(ses.writepayload, RECV_MAXPACKET); return DROPBEAR_SUCCESS; }
static void listenloop(char *listfile, int ctlfd, char *buf, int size) { int fd, n; while ((fd = open(listfile, ORDWR)) >= 0) { n = read(fd, buf, size - 1); fprint(errfd, "read from listen file returned %d\n", n); if (n <= 0) { syslog(0, "ssh", "read on listen failed: %r"); break; } buf[n >= 0? n: 0] = '\0'; fprint(errfd, "read %s\n", buf); switch (fork()) { case 0: /* child */ close(ctlfd); newchannel(fd, netdir, atoi(buf)); /* never returns */ case -1: syslog(0, "ssh", "fork failed: %r"); hangup(ctlfd); exits("fork"); } close(fd); } if (fd < 0) syslog(0, "ssh", "listen failed: %r"); }
/* Handle a new channel request, performing any channel-type-specific setup */ void recv_msg_channel_open() { unsigned char* type; unsigned int typelen; unsigned int typeval; unsigned int remotechan, transwindow, transmaxpacket; struct Channel* channel; unsigned int errtype = SSH_OPEN_UNKNOWN_CHANNEL_TYPE; TRACE(("enter recv_msg_channel_open")); /* get the packet contents */ type = buf_getstring(ses.payload, &typelen); remotechan = buf_getint(ses.payload); transwindow = buf_getint(ses.payload); transwindow = MIN(transwindow, MAX_TRANS_WINDOW); transmaxpacket = buf_getint(ses.payload); transmaxpacket = MIN(transmaxpacket, MAX_TRANS_PAYLOAD_LEN); /* figure what type of packet it is */ if (typelen > MAX_NAME_LEN) { goto failure; } if (strcmp(type, "session") == 0) { typeval = CHANNEL_ID_SESSION; #ifndef DISABLE_LOCALTCPFWD } else if (strcmp(type, "direct-tcpip") == 0) { typeval = CHANNEL_ID_TCPDIRECT; #endif } else { goto failure; } /* create the channel */ channel = newchannel(remotechan, typeval, transwindow, transmaxpacket); if (channel == NULL) { errtype = SSH_OPEN_RESOURCE_SHORTAGE; goto failure; } /* type specific initialisation */ if (typeval == CHANNEL_ID_SESSION) { newchansess(channel); #ifndef DISABLE_LOCALTCPFWD } else if (typeval == CHANNEL_ID_TCPDIRECT) { if (newtcpdirect(channel) == DROPBEAR_FAILURE) { deletechannel(channel); goto failure; } #endif } /* success */ send_msg_channel_open_confirmation(channel, channel->recvwindow, channel->recvmaxpacket); goto cleanup; failure: send_msg_channel_open_failure(remotechan, errtype, "", ""); cleanup: m_free(type); TRACE(("leave recv_msg_channel_open")); }