Example #1
0
static int
alias_pna_out(struct libalias *la, struct ip *pip,
              struct alias_link *lnk,
              char *data,
              int dlen)
{
    struct alias_link *pna_links;
    u_short msg_id, msg_len;
    char *work;
    u_short alias_port, port;
    struct tcphdr *tc;

    work = data;
    work += 5;
    while (work + 4 < data + dlen) {
        memcpy(&msg_id, work, 2);
        work += 2;
        memcpy(&msg_len, work, 2);
        work += 2;
        if (ntohs(msg_id) == 0) {
            /* end of options */
            return (0);
        }
        if ((ntohs(msg_id) == 1) || (ntohs(msg_id) == 7)) {
            memcpy(&port, work, 2);
            pna_links = FindUdpTcpOut(la, pip->ip_src, GetDestAddress(lnk),
                                      port, 0, IPPROTO_UDP, 1);
            if (pna_links != NULL) {
#ifndef NO_FW_PUNCH
                /* Punch hole in firewall */
                PunchFWHole(pna_links);
#endif
                tc = (struct tcphdr *)ip_next(pip);
                alias_port = GetAliasPort(pna_links);
                memcpy(work, &alias_port, 2);

                /* Compute TCP checksum for revised packet */
                tc->th_sum = 0;
#ifdef _KERNEL
                tc->th_x2 = 1;
#else
                tc->th_sum = TcpChecksum(pip);
#endif
            }
        }
        work += ntohs(msg_len);
    }

    return (0);
}
Example #2
0
static void
AliasHandleCUSeeMeOut(struct libalias *la, struct ip *pip, struct alias_link *lnk)
{
	struct udphdr *ud = ip_next(pip);

	if (ntohs(ud->uh_ulen) - sizeof(struct udphdr) >= sizeof(struct cu_header)) {
		struct cu_header *cu;
		struct alias_link *cu_lnk;

		cu = udp_next(ud);
		if (cu->addr)
			cu->addr = (u_int32_t) GetAliasAddress(lnk).s_addr;

		cu_lnk = FindUdpTcpOut(la, pip->ip_src, GetDestAddress(lnk),
		    ud->uh_dport, 0, IPPROTO_UDP, 1);

#ifndef NO_FW_PUNCH
		if (cu_lnk)
			PunchFWHole(cu_lnk);
#endif
	}
}
void
AliasHandleCUSeeMeOut(struct ip *pip, struct alias_link *link)
{
  struct udphdr *ud;

  ud = (struct udphdr *)((char *)pip + (pip->ip_hl << 2));
  if (ntohs(ud->uh_ulen) - sizeof(struct udphdr) >= sizeof(struct cu_header)) {
    struct cu_header *cu;
    struct alias_link *cu_link;

    cu = (struct cu_header *)(ud + 1);
    if (cu->addr)
      cu->addr = (u_int32_t)GetAliasAddress(link).s_addr;

    cu_link = FindUdpTcpOut(pip->ip_src, GetDestAddress(link),
                            ud->uh_dport, 0, IPPROTO_UDP, 1);
                         
#ifndef NO_FW_PUNCH
    if (cu_link)
        PunchFWHole(cu_link);
#endif
  }
}
Example #4
0
static int
alias_rtsp_out(struct libalias *la, struct ip *pip,
               struct alias_link *lnk,
               char *data,
               const char *port_str)
{
    int hlen, tlen, dlen;
    struct tcphdr *tc;
    int i, j, pos, state, port_dlen, new_dlen, delta;
    u_short p[2], new_len;
    u_short sport, eport, base_port;
    u_short salias = 0, ealias = 0, base_alias = 0;
    const char *transport_str = "transport:";
    char newdata[2048], *port_data, *port_newdata, stemp[80];
    int links_created = 0, pkt_updated = 0;
    struct alias_link *rtsp_lnk = NULL;
    struct in_addr null_addr;

    /* Calculate data length of TCP packet */
    tc = (struct tcphdr *)ip_next(pip);
    hlen = (pip->ip_hl + tc->th_off) << 2;
    tlen = ntohs(pip->ip_len);
    dlen = tlen - hlen;

    /* Find keyword, "Transport: " */
    pos = search_string(data, dlen, transport_str);
    if (pos < 0) {
        return (-1);
    }
    port_data = data + pos;
    port_dlen = dlen - pos;

    memcpy(newdata, data, pos);
    port_newdata = newdata + pos;

    while (port_dlen > (int)strlen(port_str)) {
        /* Find keyword, appropriate port string */
        pos = search_string(port_data, port_dlen, port_str);
        if (pos < 0) {
            break;
        }
        memcpy(port_newdata, port_data, pos + 1);
        port_newdata += (pos + 1);

        p[0] = p[1] = 0;
        sport = eport = 0;
        state = 0;
        for (i = pos; i < port_dlen; i++) {
            switch (state) {
            case 0:
                if (port_data[i] == '=') {
                    state++;
                }
                break;
            case 1:
                if (ISDIGIT(port_data[i])) {
                    p[0] = p[0] * 10 + port_data[i] - '0';
                } else {
                    if (port_data[i] == ';') {
                        state = 3;
                    }
                    if (port_data[i] == '-') {
                        state++;
                    }
                }
                break;
            case 2:
                if (ISDIGIT(port_data[i])) {
                    p[1] = p[1] * 10 + port_data[i] - '0';
                } else {
                    state++;
                }
                break;
            case 3:
                base_port = p[0];
                sport = htons(p[0]);
                eport = htons(p[1]);

                if (!links_created) {

                    links_created = 1;
                    /*
                     * Find an even numbered port
                     * number base that satisfies the
                     * contiguous number of ports we
                     * need
                     */
                    null_addr.s_addr = 0;
                    if (0 == (salias = FindNewPortGroup(la, null_addr,
                                                        FindAliasAddress(la, pip->ip_src),
                                                        sport, 0,
                                                        RTSP_PORT_GROUP,
                                                        IPPROTO_UDP, 1))) {
#ifdef LIBALIAS_DEBUG
                        fprintf(stderr,
                                "PacketAlias/RTSP: Cannot find contiguous RTSP data ports\n");
#endif
                    } else {

                        base_alias = ntohs(salias);
                        for (j = 0; j < RTSP_PORT_GROUP; j++) {
                            /*
                             * Establish link
                             * to port found in
                             * RTSP packet
                             */
                            rtsp_lnk = FindRtspOut(la, GetOriginalAddress(lnk), null_addr,
                                                   htons(base_port + j), htons(base_alias + j),
                                                   IPPROTO_UDP);
                            if (rtsp_lnk != NULL) {
#ifndef NO_FW_PUNCH
                                /*
                                 * Punch
                                 * hole in
                                 * firewall
                                 */
                                PunchFWHole(rtsp_lnk);
#endif
                            } else {
#ifdef LIBALIAS_DEBUG
                                fprintf(stderr,
                                        "PacketAlias/RTSP: Cannot allocate RTSP data ports\n");
#endif
                                break;
                            }
                        }
                    }
                    ealias = htons(base_alias + (RTSP_PORT_GROUP - 1));
                }
                if (salias && rtsp_lnk) {

                    pkt_updated = 1;

                    /* Copy into IP packet */
                    sprintf(stemp, "%d", ntohs(salias));
                    memcpy(port_newdata, stemp, strlen(stemp));
                    port_newdata += strlen(stemp);

                    if (eport != 0) {
                        *port_newdata = '-';
                        port_newdata++;

                        /* Copy into IP packet */
                        sprintf(stemp, "%d", ntohs(ealias));
                        memcpy(port_newdata, stemp, strlen(stemp));
                        port_newdata += strlen(stemp);
                    }
                    *port_newdata = ';';
                    port_newdata++;
                }
                state++;
                break;
            }
            if (state > 3) {
                break;
            }
        }
        port_data += i;
        port_dlen -= i;
    }

    if (!pkt_updated)
        return (-1);

    memcpy(port_newdata, port_data, port_dlen);
    port_newdata += port_dlen;
    *port_newdata = '\0';

    /* Create new packet */
    new_dlen = port_newdata - newdata;
    memcpy(data, newdata, new_dlen);

    SetAckModified(lnk);
    tc = (struct tcphdr *)ip_next(pip);
    delta = GetDeltaSeqOut(tc->th_seq, lnk);
    AddSeq(lnk, delta + new_dlen - dlen, pip->ip_hl, pip->ip_len,
           tc->th_seq, tc->th_off);

    new_len = htons(hlen + new_dlen);
    DifferentialChecksum(&pip->ip_sum,
                         &new_len,
                         &pip->ip_len,
                         1);
    pip->ip_len = new_len;

    tc->th_sum = 0;
#ifdef _KERNEL
    tc->th_x2 = 1;
#else
    tc->th_sum = TcpChecksum(pip);
#endif
    return (0);
}
Example #5
0
static void
NewFtpMessage(struct libalias *la, struct ip *pip,
    struct alias_link *lnk,
    int maxpacketsize,
    int ftp_message_type)
{
	struct alias_link *ftp_lnk;

/* Security checks. */
	if (pip->ip_src.s_addr != la->true_addr.s_addr)
		return;

	if (la->true_port < IPPORT_RESERVED)
		return;

/* Establish link to address and port found in FTP control message. */
	ftp_lnk = FindUdpTcpOut(la, la->true_addr, GetDestAddress(lnk),
	    htons(la->true_port), 0, IPPROTO_TCP, 1);

	if (ftp_lnk != NULL) {
		int slen, hlen, tlen, dlen;
		struct tcphdr *tc;

#ifndef NO_FW_PUNCH
		/* Punch hole in firewall */
		PunchFWHole(ftp_lnk);
#endif

/* Calculate data length of TCP packet */
		tc = (struct tcphdr *)ip_next(pip);
		hlen = (pip->ip_hl + tc->th_off) << 2;
		tlen = ntohs(pip->ip_len);
		dlen = tlen - hlen;

/* Create new FTP message. */
		{
			char stemp[MAX_MESSAGE_SIZE + 1];
			char *sptr;
			u_short alias_port;
			u_char *ptr;
			int a1, a2, a3, a4, p1, p2;
			struct in_addr alias_address;

/* Decompose alias address into quad format */
			alias_address = GetAliasAddress(lnk);
			ptr = (u_char *) & alias_address.s_addr;
			a1 = *ptr++;
			a2 = *ptr++;
			a3 = *ptr++;
			a4 = *ptr;

			alias_port = GetAliasPort(ftp_lnk);

/* Prepare new command */
			switch (ftp_message_type) {
			case FTP_PORT_COMMAND:
			case FTP_227_REPLY:
				/* Decompose alias port into pair format. */
				ptr = (char *)&alias_port;
				p1 = *ptr++;
				p2 = *ptr;

				if (ftp_message_type == FTP_PORT_COMMAND) {
					/* Generate PORT command string. */
					sprintf(stemp, "PORT %d,%d,%d,%d,%d,%d\r\n",
					    a1, a2, a3, a4, p1, p2);
				} else {
					/* Generate 227 reply string. */
					sprintf(stemp,
					    "227 Entering Passive Mode (%d,%d,%d,%d,%d,%d)\r\n",
					    a1, a2, a3, a4, p1, p2);
				}
				break;
			case FTP_EPRT_COMMAND:
				/* Generate EPRT command string. */
				sprintf(stemp, "EPRT |1|%d.%d.%d.%d|%d|\r\n",
				    a1, a2, a3, a4, ntohs(alias_port));
				break;
			case FTP_229_REPLY:
				/* Generate 229 reply string. */
				sprintf(stemp, "229 Entering Extended Passive Mode (|||%d|)\r\n",
				    ntohs(alias_port));
				break;
			}

/* Save string length for IP header modification */
			slen = strlen(stemp);

/* Copy modified buffer into IP packet. */
			sptr = (char *)pip;
			sptr += hlen;
			strncpy(sptr, stemp, maxpacketsize - hlen);
		}

/* Save information regarding modified seq and ack numbers */
		{
			int delta;

			SetAckModified(lnk);
			tc = (struct tcphdr *)ip_next(pip);				
			delta = GetDeltaSeqOut(tc->th_seq, lnk);
			AddSeq(lnk, delta + slen - dlen, pip->ip_hl, 
			    pip->ip_len, tc->th_seq, tc->th_off);
		}

/* Revise IP header */
		{
			u_short new_len;

			new_len = htons(hlen + slen);
			DifferentialChecksum(&pip->ip_sum,
			    &new_len,
			    &pip->ip_len,
			    1);
			pip->ip_len = new_len;
		}

/* Compute TCP checksum for revised packet */
		tc->th_sum = 0;
#ifdef _KERNEL
		tc->th_x2 = 1;
#else
		tc->th_sum = TcpChecksum(pip);
#endif
	} else {
#ifdef LIBALIAS_DEBUG
		fprintf(stderr,
		    "PacketAlias/HandleFtpOut: Cannot allocate FTP data port\n");
#endif
	}
}
static void
AliasHandleIrcOut(struct libalias *la,
    struct ip *pip,		/* IP packet to examine */
    struct alias_link *lnk,	/* Which link are we on? */
    int maxsize			/* Maximum size of IP packet including
				 * headers */
)
{
	int hlen, tlen, dlen;
	struct in_addr true_addr;
	u_short true_port;
	char *sptr;
	struct tcphdr *tc;
	int i;			/* Iterator through the source */

/* Calculate data length of TCP packet */
	tc = (struct tcphdr *)ip_next(pip);
	hlen = (pip->ip_hl + tc->th_off) << 2;
	tlen = ntohs(pip->ip_len);
	dlen = tlen - hlen;

	/*
	 * Return if data length is too short - assume an entire PRIVMSG in
	 * each packet.
	 */
	if (dlen < (int)sizeof(":[email protected] PRIVMSG A :aDCC 1 1a") - 1)
		return;

/* Place string pointer at beginning of data */
	sptr = (char *)pip;
	sptr += hlen;
	maxsize -= hlen;	/* We're interested in maximum size of
				 * data, not packet */

	/* Search for a CTCP command [Note 1] */
	for (i = 0; i < dlen; i++) {
		if (sptr[i] == '\001')
			goto lFOUND_CTCP;
	}
	return;			/* No CTCP commands in  */
	/* Handle CTCP commands - the buffer may have to be copied */
lFOUND_CTCP:
	{
		char newpacket[65536];	/* Estimate of maximum packet size
					 * :) */
		unsigned int copyat = i;	/* Same */
		unsigned int iCopy = 0;	/* How much data have we written to
					 * copy-back string? */
		unsigned long org_addr;	/* Original IP address */
		unsigned short org_port;	/* Original source port
						 * address */

lCTCP_START:
		if (i >= dlen || iCopy >= sizeof(newpacket))
			goto lPACKET_DONE;
		newpacket[iCopy++] = sptr[i++];	/* Copy the CTCP start
						 * character */
		/* Start of a CTCP */
		if (i + 4 >= dlen)	/* Too short for DCC */
			goto lBAD_CTCP;
		if (sptr[i + 0] != 'D')
			goto lBAD_CTCP;
		if (sptr[i + 1] != 'C')
			goto lBAD_CTCP;
		if (sptr[i + 2] != 'C')
			goto lBAD_CTCP;
		if (sptr[i + 3] != ' ')
			goto lBAD_CTCP;
		/* We have a DCC command - handle it! */
		i += 4;		/* Skip "DCC " */
		if (iCopy + 4 > sizeof(newpacket))
			goto lPACKET_DONE;
		newpacket[iCopy++] = 'D';
		newpacket[iCopy++] = 'C';
		newpacket[iCopy++] = 'C';
		newpacket[iCopy++] = ' ';

		DBprintf(("Found DCC\n"));
		/*
		 * Skip any extra spaces (should not occur according to
		 * protocol, but DCC breaks CTCP protocol anyway
		 */
		while (sptr[i] == ' ') {
			if (++i >= dlen) {
				DBprintf(("DCC packet terminated in just spaces\n"));
				goto lPACKET_DONE;
			}
		}

		DBprintf(("Transferring command...\n"));
		while (sptr[i] != ' ') {
			newpacket[iCopy++] = sptr[i];
			if (++i >= dlen || iCopy >= sizeof(newpacket)) {
				DBprintf(("DCC packet terminated during command\n"));
				goto lPACKET_DONE;
			}
		}
		/* Copy _one_ space */
		if (i + 1 < dlen && iCopy < sizeof(newpacket))
			newpacket[iCopy++] = sptr[i++];

		DBprintf(("Done command - removing spaces\n"));
		/*
		 * Skip any extra spaces (should not occur according to
		 * protocol, but DCC breaks CTCP protocol anyway
		 */
		while (sptr[i] == ' ') {
			if (++i >= dlen) {
				DBprintf(("DCC packet terminated in just spaces (post-command)\n"));
				goto lPACKET_DONE;
			}
		}

		DBprintf(("Transferring filename...\n"));
		while (sptr[i] != ' ') {
			newpacket[iCopy++] = sptr[i];
			if (++i >= dlen || iCopy >= sizeof(newpacket)) {
				DBprintf(("DCC packet terminated during filename\n"));
				goto lPACKET_DONE;
			}
		}
		/* Copy _one_ space */
		if (i + 1 < dlen && iCopy < sizeof(newpacket))
			newpacket[iCopy++] = sptr[i++];

		DBprintf(("Done filename - removing spaces\n"));
		/*
		 * Skip any extra spaces (should not occur according to
		 * protocol, but DCC breaks CTCP protocol anyway
		 */
		while (sptr[i] == ' ') {
			if (++i >= dlen) {
				DBprintf(("DCC packet terminated in just spaces (post-filename)\n"));
				goto lPACKET_DONE;
			}
		}

		DBprintf(("Fetching IP address\n"));
		/* Fetch IP address */
		org_addr = 0;
		while (i < dlen && isdigit(sptr[i])) {
			if (org_addr > ULONG_MAX / 10UL) {	/* Terminate on overflow */
				DBprintf(("DCC Address overflow (org_addr == 0x%08lx, next char %c\n", org_addr, sptr[i]));
				goto lBAD_CTCP;
			}
			org_addr *= 10;
			org_addr += sptr[i++] - '0';
		}
		DBprintf(("Skipping space\n"));
		if (i + 1 >= dlen || sptr[i] != ' ') {
			DBprintf(("Overflow (%d >= %d) or bad character (%02x) terminating IP address\n", i + 1, dlen, sptr[i]));
			goto lBAD_CTCP;
		}
		/*
		 * Skip any extra spaces (should not occur according to
		 * protocol, but DCC breaks CTCP protocol anyway, so we
		 * might as well play it safe
		 */
		while (sptr[i] == ' ') {
			if (++i >= dlen) {
				DBprintf(("Packet failure - space overflow.\n"));
				goto lPACKET_DONE;
			}
		}
		DBprintf(("Fetching port number\n"));
		/* Fetch source port */
		org_port = 0;
		while (i < dlen && isdigit(sptr[i])) {
			if (org_port > 6554) {	/* Terminate on overflow
						 * (65536/10 rounded up */
				DBprintf(("DCC: port number overflow\n"));
				goto lBAD_CTCP;
			}
			org_port *= 10;
			org_port += sptr[i++] - '0';
		}
		/* Skip illegal addresses (or early termination) */
		if (i >= dlen || (sptr[i] != '\001' && sptr[i] != ' ')) {
			DBprintf(("Bad port termination\n"));
			goto lBAD_CTCP;
		}
		DBprintf(("Got IP %lu and port %u\n", org_addr, (unsigned)org_port));

		/* We've got the address and port - now alias it */
		{
			struct alias_link *dcc_lnk;
			struct in_addr destaddr;


			true_port = htons(org_port);
			true_addr.s_addr = htonl(org_addr);
			destaddr.s_addr = 0;

			/* Sanity/Security checking */
			if (!org_addr || !org_port ||
			    pip->ip_src.s_addr != true_addr.s_addr ||
			    org_port < IPPORT_RESERVED)
				goto lBAD_CTCP;

			/*
			 * Steal the FTP_DATA_PORT - it doesn't really
			 * matter, and this would probably allow it through
			 * at least _some_ firewalls.
			 */
			dcc_lnk = FindUdpTcpOut(la, true_addr, destaddr,
			    true_port, 0,
			    IPPROTO_TCP, 1);
			DBprintf(("Got a DCC link\n"));
			if (dcc_lnk) {
				struct in_addr alias_address;	/* Address from aliasing */
				u_short alias_port;	/* Port given by
							 * aliasing */
				int n;

#ifndef NO_FW_PUNCH
				/* Generate firewall hole as appropriate */
				PunchFWHole(dcc_lnk);
#endif

				alias_address = GetAliasAddress(lnk);
				n = snprintf(&newpacket[iCopy],
				    sizeof(newpacket) - iCopy,
				    "%lu ", (u_long) htonl(alias_address.s_addr));
				if (n < 0) {
					DBprintf(("DCC packet construct failure.\n"));
					goto lBAD_CTCP;
				}
				if ((iCopy += n) >= sizeof(newpacket)) {	/* Truncated/fit exactly
										 * - bad news */
					DBprintf(("DCC constructed packet overflow.\n"));
					goto lBAD_CTCP;
				}
				alias_port = GetAliasPort(dcc_lnk);
				n = snprintf(&newpacket[iCopy],
				    sizeof(newpacket) - iCopy,
				    "%u", htons(alias_port));
				if (n < 0) {
					DBprintf(("DCC packet construct failure.\n"));
					goto lBAD_CTCP;
				}
				iCopy += n;
				/*
				 * Done - truncated cases will be taken
				 * care of by lBAD_CTCP
				 */
				DBprintf(("Aliased IP %lu and port %u\n", alias_address.s_addr, (unsigned)alias_port));
			}
		}
		/*
		 * An uninteresting CTCP - state entered right after '\001'
		 * has been pushed.  Also used to copy the rest of a DCC,
		 * after IP address and port has been handled
		 */
lBAD_CTCP:
		for (; i < dlen && iCopy < sizeof(newpacket); i++, iCopy++) {
			newpacket[iCopy] = sptr[i];	/* Copy CTCP unchanged */
			if (sptr[i] == '\001') {
				goto lNORMAL_TEXT;
			}
		}
		goto lPACKET_DONE;
		/* Normal text */
lNORMAL_TEXT:
		for (; i < dlen && iCopy < sizeof(newpacket); i++, iCopy++) {
			newpacket[iCopy] = sptr[i];	/* Copy CTCP unchanged */
			if (sptr[i] == '\001') {
				goto lCTCP_START;
			}
		}
		/* Handle the end of a packet */
lPACKET_DONE:
		iCopy = iCopy > maxsize - copyat ? maxsize - copyat : iCopy;
		memcpy(sptr + copyat, newpacket, iCopy);

/* Save information regarding modified seq and ack numbers */
		{
			int delta;

			SetAckModified(lnk);
			delta = GetDeltaSeqOut(pip, lnk);
			AddSeq(pip, lnk, delta + copyat + iCopy - dlen);
		}

		/* Revise IP header */
		{
			u_short new_len;

			new_len = htons(hlen + iCopy + copyat);
			DifferentialChecksum(&pip->ip_sum,
			    &new_len,
			    &pip->ip_len,
			    1);
			pip->ip_len = new_len;
		}

		/* Compute TCP checksum for revised packet */
		tc->th_sum = 0;
#ifdef _KERNEL
		tc->th_x2 = 1;
#else
		tc->th_sum = TcpChecksum(pip);
#endif
		return;
	}
}