📄 msproxy_clientprotocol.c
字号:
slog(LOG_DEBUG, "%s: server will use as source address: %s", function, sockshost2string(&packet->res.host, NULL, 0)); slog(LOG_DEBUG, "%s: packet #6", function); bzero(&req, sizeof(req)); req.clientid = packet->state.msproxy.clientid; req.serverid = packet->state.msproxy.serverid; req.command = htons(MSPROXY_CONNECTED); if (send_msprequest(control, &packet->state.msproxy, &req) == -1) return -1; /* make response look sensible. */ packet->res.version = packet->req.version; packet->res.reply = MSPROXY_SUCCESS; packet->res.flag = 0; packet->res.auth = NULL; return 0;}static intmsproxy_bind(s, control, packet) int s; int control; struct socks_t *packet;{ const char *function = "msproxy_bind()"; struct msproxy_request_t req; struct msproxy_response_t res; struct sockaddr_in addr; socklen_t len; slog(LOG_DEBUG, function); bzero(&req, sizeof(req)); req.clientid = packet->state.msproxy.clientid; req.serverid = packet->state.msproxy.serverid; req.command = htons(MSPROXY_BIND); req.packet._3.magic2 = htons(0x0100); req.packet._3.bindaddr = packet->req.host.addr.ipv4.s_addr; req.packet._3.bindport = packet->req.host.port; req.packet._3.magic3 = htons(0x0200); len = sizeof(addr); /* LINTED pointer casts may be troublesome */ if (getsockname(s, (struct sockaddr *)&addr, &len) != 0) return -1; req.packet._3.boundport = addr.sin_port; if (send_msprequest(control, &packet->state.msproxy, &req) == -1) return -1; if (recv_mspresponse(control, &packet->state.msproxy, &res) == -1) return -1; if (res.serverid != packet->state.msproxy.serverid) serrx(EXIT_FAILURE, "expected serverid = 0x%x, is 0x%x", packet->state.msproxy.serverid, res.serverid); if (ntohs(res.command) != MSPROXY_BIND_ACK) { swarnx("expected res.command = 0x%x, is 0x%x", MSPROXY_BIND_ACK, ntohs(res.command)); packet->res.reply = MSPROXY_NOTALLOWED; return -1; } packet->state.msproxy.bindid = res.packet._3.magic10; packet->res.host.atype = SOCKS_ADDR_IPV4; packet->res.host.port = res.packet._3.boundport; packet->res.host.addr.ipv4.s_addr = res.packet._3.boundaddr; slog(LOG_DEBUG, "%s: server bound for us: %s", function, sockshost2string(&packet->res.host, NULL, 0)); slog(LOG_DEBUG, "%s: packet #4", function); bzero(&req, sizeof(req)); req.clientid = packet->state.msproxy.clientid; req.serverid = packet->state.msproxy.serverid; req.command = htons(MSPROXY_BIND2); req.packet._4.magic1 = htons(0x0100); req.packet._4.magic2 = packet->state.msproxy.bindid; req.packet._4.magic3 = htons(0x0500); memcpy(req.packet._4.pad3 + 2, &addr.sin_port, sizeof(addr.sin_port)); req.packet._4.magic4 = htons(0x0200); req.packet._4.boundport = addr.sin_port; if (send_msprequest(control, &packet->state.msproxy, &req) == -1) return -1; if (recv_mspresponse(control, &packet->state.msproxy, &res) == -1) return -1; if (res.serverid != packet->state.msproxy.serverid) serrx(EXIT_FAILURE, "expected res.serverid = 0x%x, is 0x%x", packet->state.msproxy.serverid, res.serverid); if (res.clientack != 0x01) serrx(EXIT_FAILURE, "expected res.clientack = 0x%x, is 0x%x", 0x01, res.clientack); if (ntohs(res.command) != MSPROXY_BIND2_ACK) { swarnx("expected res.command = %x, is 0x%x", MSPROXY_BIND2_ACK, ntohs(res.command)); return -1; } slog(LOG_DEBUG, "%s: packet #5", function); bzero(&req, sizeof(req)); req.clientid = packet->state.msproxy.clientid; req.serverid = packet->state.msproxy.serverid; req.command = htons(MSPROXY_LISTEN); req.packet._5.magic6 = htons(0x0200); req.packet._5.destport = packet->res.host.port; req.packet._5.destaddr = packet->res.host.addr.ipv4.s_addr; if (send_msprequest(control, &packet->state.msproxy, &req) == -1) return -1; /* * When the server accepts the client, it will send us a new * controlpacket. That will be caught in sigio(). */ slog(LOG_DEBUG, "%s: waiting for forwarded connection...", function); /* make response look sensible. */ packet->res.version = packet->req.version; packet->res.reply = MSPROXY_SUCCESS; packet->res.flag = 0; packet->res.auth = NULL; return 0;}intmsproxy_sigio(s) int s;{ const char *function = "msproxy_sigio()"; static int init; const int errno_s = errno; struct socksfd_t *socksfd; int p; /* * The msproxy protocol sends a udp packet which we must ack * before it will connect to us. We set up the controlsocket * for signaldriven i/o so we can ack it asynchronously. * */ SASSERTX(socks_addrisok((unsigned int)s)); socksfd = socks_getaddr((unsigned int)s); SASSERTX(socksfd->state.version == MSPROXY_V2); if (!init) { /* could be smarter about this... */ struct sigaction sigact; sigemptyset(&sigact.sa_mask); sigact.sa_flags = SA_RESTART; sigact.sa_handler = sigio; if (sigaction(SIGIO, &sigact, &oldsigio) != 0) return -1; init = 1; } if (fcntl(socksfd->control, F_SETOWN, getpid()) == -1) return -1; p = 1; if (ioctl(socksfd->control, FIOASYNC, &p) == -1) return -1; slog(LOG_DEBUG, "%s: set up sigio for %d", function, socksfd->control); errno = errno_s; return 0;}/* ARGSUSED */static voidsigio(sig) int sig;{ const char *function = "sigio()"; const int errno_s = errno; int i, max, dset; struct socksfd_t *socksfd; fd_set rset; struct timeval timeout; int dbits; slog(LOG_DEBUG, function); /* * Find the socket we were signalled for. */ dbits = -1; FD_ZERO(&rset); for (i = 0, max = getdtablesize(); i < max; ++i) { if ((socksfd = socks_getaddr((unsigned int)i)) == NULL) continue; if (socksfd->state.command != SOCKS_BIND || socksfd->state.version != MSPROXY_V2 || !socksfd->state.inprogress) continue; if (!socks_addrisok((unsigned int)i)) continue; SASSERTX(fdisopen(socksfd->control)); FD_SET(socksfd->control, &rset); dbits = MAX(dbits, socksfd->control); } if (dbits == -1) { if (oldsigio.sa_handler != NULL) oldsigio.sa_handler(sig); return; /* old signal handler. */ } dset = 0; do { fd_set newrset; timeout.tv_sec = 0; timeout.tv_usec = 0; newrset = rset; switch (selectn(dbits + 1, &newrset, NULL, NULL, &timeout)) { case -1: SERR(-1); /* NOTREACHED */ case 0: dset = 0; slog(LOG_DEBUG, "%s: no descriptors readable", function); if (oldsigio.sa_handler != NULL) oldsigio.sa_handler(sig); break; default: { dset = 1; for (i = 0, max = getdtablesize(); i < max; ++i) { if ((socksfd = socks_getaddr((unsigned int)i)) == NULL) continue; if (FD_ISSET(socksfd->control, &newrset)) { struct sockshost_t host; struct msproxy_request_t req; struct msproxy_response_t res; int p; SASSERTX(socksfd->state.command == SOCKS_BIND && socksfd->state.version == MSPROXY_V2 && socksfd->state.inprogress); slog(LOG_DEBUG, "%s: attempting to receive bind info...", function); FD_CLR(socksfd->control, &newrset); if (recv_mspresponse(socksfd->control, &socksfd->state.msproxy, &res) == -1) continue; if (ntohs(res.command) != MSPROXY_BINDINFO) { swarnx("%s: expected res.command = %x, is 0x%x", function, MSPROXY_BINDINFO, ntohs(res.command)); continue; } /* no need for more signals on this socket. */ p = 0; if (ioctl(socksfd->control, FIOASYNC, &p) == -1) { swarn("%s: ioctl(socksfd->control)", function); continue; } slog(LOG_DEBUG, "%s: turned off sigio for %d", function, socksfd->control); /* * if we asked server to bind INADDR_ANY, we don't know * what address it bound until now. */ host.atype = SOCKS_ADDR_IPV4; host.port = res.packet._5.boundport; host.addr.ipv4.s_addr = res.packet._5.boundaddr; sockshost2sockaddr(&host, &socksfd->remote); slog(LOG_DEBUG, "%s: server bound address %s", function, sockshost2string(&host, NULL, 0)); host.atype = SOCKS_ADDR_IPV4; host.port = res.packet._5.clientport; host.addr.ipv4.s_addr = res.packet._5.clientaddr; sockshost2sockaddr(&host, &socksfd->accepted); slog(LOG_DEBUG, "%s: server accepted: %s", function, sockshost2string(&host, NULL, 0)); slog(LOG_DEBUG, "%s: server will connect to us from port %d", function, ntohs(res.packet._5.serverport)); /* LINTED pointer casts may be troublesome */ ((struct sockaddr_in *)&socksfd->reply)->sin_port = res.packet._5.serverport; slog(LOG_DEBUG, "%s: packet #6", function); bzero(&req, sizeof(req)); req.clientid = socksfd->state.msproxy.clientid; req.serverid = socksfd->state.msproxy.serverid; req.command = htons(MSPROXY_BINDINFO_ACK); req.packet._6.magic1 = res.packet._5.magic1; req.packet._6.magic5 = htons(0x0100); req.packet._6.magic10 = socksfd->state.msproxy.bindid; req.packet._6.magic15 = htons(0x0100); req.packet._6.magic16 = socksfd->state.msproxy.bindid; req.packet._6.magic20 = htons(0x0200); req.packet._6.clientport = res.packet._5.clientport; req.packet._6.clientaddr = res.packet._5.clientaddr; req.packet._6.magic30 = res.packet._5.magic10; req.packet._6.magic35 = res.packet._5.magic15; req.packet._6.serverport = res.packet._5.serverport; req.packet._6.srcport = res.packet._5.srcport; req.packet._6.boundport = res.packet._5.boundport; req.packet._6.boundaddr = res.packet._5.boundaddr; if (send_msprequest(socksfd->control, &socksfd->state.msproxy, &req) == -1) continue; if (recv_mspresponse(socksfd->control, &socksfd->state.msproxy, &res) == -1) continue; /* all done. Can accept(). */ socksfd->state.inprogress = 0; } } } } } while (dset != 0); errno = errno_s;}intrecv_mspresponse(s, state, response) int s; struct msproxy_state_t *state; struct msproxy_response_t *response;{ const char *function = "recv_mspresponse()"; /* CONSTCOND */ char responsemem[MAX(sizeof(*response), 1024)]; ssize_t r; /* CONSTCOND */ while (1) { if ((r = read(s, responsemem, sizeof(responsemem))) < MSPROXY_MINLENGTH) { swarn("%s: expected to read atleast %d, read %d", function, MSPROXY_MINLENGTH, r); return -1; } if (mem2response(response, responsemem, (size_t)r) == NULL) { swarnx("%s: bad response from server", function); return -1; } if (state->seq_recv > 0) { if (response->sequence == state->seq_recv + 1) break; /* all ok. */ else if (response->sequence < state->seq_recv) { /* * sequence number less that last, sometimes this happens too, * don't know why. */ slog(LOG_DEBUG, "%s: sequence (%d) < seq_recv (%d)", function, response->sequence, state->seq_recv); break; } else if (response->sequence == state->seq_recv) { slog(LOG_DEBUG, "%s: seq_recv: %d, dup response, seqnumber: 0x%x", function, state->seq_recv, response->sequence); if (response->clientack == state->seq_sent) { slog(LOG_DEBUG, "%s: ack matches last sent though, hoping it's a new one...", function); break; } } else if (response->sequence > state->seq_recv) { slog(LOG_DEBUG, "%s: sequence (%d) > seq_recv (%d)", function, response->sequence, state->seq_recv); break; } } else break; /* not started incrementing yet. */ } state->seq_recv = response->sequence; return r;}intsend_msprequest(s, state, request) int s; struct msproxy_state_t *state; struct msproxy_request_t *request;{ const char *function = "send_msprequest()"; ssize_t w; char requestmem[sizeof(struct msproxy_request_t)], *p; request->magic25 = htonl(MSPROXY_VERSION); request->serverack = state->seq_recv; /* don't start incrementing sequence until we are acking packet #2. */ request->sequence = (unsigned char)(request->serverack >= 2 ? state->seq_sent + 1 : 0); memcpy(request->RWSP, "RWSP", sizeof(request->RWSP)); p = request2mem(request, requestmem); /* all requests must be atleast MSPROXY_MINLENGTH it seems. */ if (p - requestmem < MSPROXY_MINLENGTH) { bzero(p, (size_t)(MSPROXY_MINLENGTH - (p - requestmem))); p = requestmem + MSPROXY_MINLENGTH; } if ((w = write(s, requestmem, (size_t)(p - requestmem))) != (ssize_t)(p - requestmem)) { swarn("%s: write()", function); return -1; } state->seq_sent = request->sequence; return w;}static char *mem2response(res, mem, len) struct msproxy_response_t *res; char *mem; size_t len;{ const char *function = "mem2response()"; if (len < sizeof(res->packetid)) return NULL; memcpy(&res->packetid, mem, sizeof(res->packetid)); mem += sizeof(res->packetid); len -= sizeof(res->packetid); if (len < sizeof(res->magic5)) return NULL; memcpy(&res->magic5, mem, sizeof(res->magic5)); mem += sizeof(res->magic5); len -= sizeof(res->magic5); if (len < sizeof(res->serverid)) return NULL; memcpy(&res->serverid, mem, sizeof(res->serverid)); mem += sizeof(res->serverid); len -= sizeof(res->serverid);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -