123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269 |
- #include "includes.h"
- #ifndef DISABLE_X11FWD
- #include "x11fwd.h"
- #include "session.h"
- #include "ssh.h"
- #include "dbutil.h"
- #include "chansession.h"
- #include "channel.h"
- #include "packet.h"
- #include "buffer.h"
- #include "auth.h"
- #define X11BASEPORT 6000
- #define X11BINDBASE 6010
- static void x11accept(struct Listener* listener, int sock);
- static int bindport(int fd);
- static int send_msg_channel_open_x11(int fd, struct sockaddr_in* addr);
- static int
- xauth_valid_string(const char *s)
- {
- size_t i;
- for (i = 0; s[i] != '\0'; i++) {
- if (!isalnum(s[i]) &&
- s[i] != '.' && s[i] != ':' && s[i] != '/' &&
- s[i] != '-' && s[i] != '_') {
- return DROPBEAR_FAILURE;
- }
- }
- return DROPBEAR_SUCCESS;
- }
- int x11req(struct ChanSess * chansess) {
- int fd = -1;
- if (!svr_pubkey_allows_x11fwd()) {
- return DROPBEAR_FAILURE;
- }
-
- if (chansess->x11listener != NULL) {
- return DROPBEAR_FAILURE;
- }
- chansess->x11singleconn = buf_getbool(ses.payload);
- chansess->x11authprot = buf_getstring(ses.payload, NULL);
- chansess->x11authcookie = buf_getstring(ses.payload, NULL);
- chansess->x11screennum = buf_getint(ses.payload);
- if (xauth_valid_string(chansess->x11authprot) == DROPBEAR_FAILURE ||
- xauth_valid_string(chansess->x11authcookie) == DROPBEAR_FAILURE) {
- dropbear_log(LOG_WARNING, "Bad xauth request");
- goto fail;
- }
-
- fd = socket(PF_INET, SOCK_STREAM, 0);
- if (fd < 0) {
- goto fail;
- }
-
- chansess->x11port = bindport(fd);
- if (chansess->x11port < 0) {
- goto fail;
- }
-
- if (listen(fd, 20) < 0) {
- goto fail;
- }
-
- setnonblocking(fd);
-
- chansess->x11listener = new_listener( &fd, 1, 0, chansess, x11accept, NULL);
- if (chansess->x11listener == NULL) {
- goto fail;
- }
- return DROPBEAR_SUCCESS;
- fail:
-
- m_free(chansess->x11authprot);
- m_free(chansess->x11authcookie);
- m_close(fd);
- return DROPBEAR_FAILURE;
- }
- static void x11accept(struct Listener* listener, int sock) {
- int fd;
- struct sockaddr_in addr;
- socklen_t len;
- int ret;
- struct ChanSess * chansess = (struct ChanSess *)(listener->typedata);
- len = sizeof(addr);
- fd = accept(sock, (struct sockaddr*)&addr, &len);
- if (fd < 0) {
- return;
- }
-
- if (chansess->x11singleconn) {
- x11cleanup(chansess);
- }
- ret = send_msg_channel_open_x11(fd, &addr);
- if (ret == DROPBEAR_FAILURE) {
- close(fd);
- }
- }
- void x11setauth(struct ChanSess *chansess) {
- char display[20];
- FILE * authprog = NULL;
- int val;
- if (chansess->x11listener == NULL) {
- return;
- }
-
- val = snprintf(display, sizeof(display), "localhost:%d.%u",
- chansess->x11port - X11BASEPORT, chansess->x11screennum);
- if (val < 0 || val >= (int)sizeof(display)) {
-
- return;
- }
- addnewvar("DISPLAY", display);
-
- val = snprintf(display, sizeof(display), "unix:%d.%u",
- chansess->x11port - X11BASEPORT, chansess->x11screennum);
- if (val < 0 || val >= (int)sizeof(display)) {
-
- return;
- }
-
- authprog = popen(XAUTH_COMMAND, "w");
- if (authprog) {
- fprintf(authprog, "add %s %s %s\n",
- display, chansess->x11authprot, chansess->x11authcookie);
- pclose(authprog);
- } else {
- fprintf(stderr, "Failed to run %s\n", XAUTH_COMMAND);
- }
- }
- void x11cleanup(struct ChanSess *chansess) {
- m_free(chansess->x11authprot);
- m_free(chansess->x11authcookie);
- TRACE(("chansess %p", (void*)chansess))
- if (chansess->x11listener != NULL) {
- remove_listener(chansess->x11listener);
- chansess->x11listener = NULL;
- }
- }
- static int x11_inithandler(struct Channel *channel) {
- channel->prio = DROPBEAR_CHANNEL_PRIO_INTERACTIVE;
- return 0;
- }
- static const struct ChanType chan_x11 = {
- 0,
- "x11",
- x11_inithandler,
- NULL,
- NULL,
- NULL
- };
- static int send_msg_channel_open_x11(int fd, struct sockaddr_in* addr) {
- char* ipstring = NULL;
- if (send_msg_channel_open_init(fd, &chan_x11) == DROPBEAR_SUCCESS) {
- ipstring = inet_ntoa(addr->sin_addr);
- buf_putstring(ses.writepayload, ipstring, strlen(ipstring));
- buf_putint(ses.writepayload, addr->sin_port);
- encrypt_packet();
- return DROPBEAR_SUCCESS;
- } else {
- return DROPBEAR_FAILURE;
- }
- }
- static int bindport(int fd) {
- struct sockaddr_in addr;
- uint16_t port;
- memset((void*)&addr, 0x0, sizeof(addr));
- addr.sin_family = AF_INET;
- addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
-
- for (port = X11BINDBASE; port < X11BINDBASE + 2000; port++) {
- addr.sin_port = htons(port);
- if (bind(fd, (struct sockaddr*)&addr,
- sizeof(struct sockaddr_in)) == 0) {
-
- return port;
- }
- if (errno == EADDRINUSE) {
-
- continue;
- }
-
- dropbear_log(LOG_DEBUG, "Failed to bind x11 socket");
- break;
- }
- return -1;
- }
- #endif
|