summaryrefslogtreecommitdiffstats
path: root/contrib/ipfilter/ip_msnrpc_pxy.c
diff options
context:
space:
mode:
authordarrenr <darrenr@FreeBSD.org>2005-04-25 17:31:50 +0000
committerdarrenr <darrenr@FreeBSD.org>2005-04-25 17:31:50 +0000
commitd438802dcb3e270d6fcc65f075c808c64853a7c2 (patch)
treee2e1c7115044e6dfc86ff65598566fa32e5f7421 /contrib/ipfilter/ip_msnrpc_pxy.c
parent590450fec65a8e72a8965117398bc8f14938b4a8 (diff)
downloadFreeBSD-src-d438802dcb3e270d6fcc65f075c808c64853a7c2.zip
FreeBSD-src-d438802dcb3e270d6fcc65f075c808c64853a7c2.tar.gz
import ipfilter 4.1.8 into the vendor branch
Diffstat (limited to 'contrib/ipfilter/ip_msnrpc_pxy.c')
-rw-r--r--contrib/ipfilter/ip_msnrpc_pxy.c328
1 files changed, 328 insertions, 0 deletions
diff --git a/contrib/ipfilter/ip_msnrpc_pxy.c b/contrib/ipfilter/ip_msnrpc_pxy.c
new file mode 100644
index 0000000..187a964
--- /dev/null
+++ b/contrib/ipfilter/ip_msnrpc_pxy.c
@@ -0,0 +1,328 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 2000-2003 by Darren Reed
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ *
+ * Simple DCE transparent proxy for MSN RPC.
+ *
+ * ******* NOTE: THIS PROXY DOES NOT DO ADDRESS TRANSLATION ********
+ *
+ * Id: ip_msnrpc_pxy.c,v 2.17.2.1 2005/02/04 10:22:55 darrenr Exp
+ */
+
+#define IPF_MSNRPC_PROXY
+
+#define IPF_MINMSNRPCLEN 24
+#define IPF_MSNRPCSKIP (2 + 19 + 2 + 2 + 2 + 19 + 2 + 2)
+
+
+typedef struct msnrpchdr {
+ u_char mrh_major; /* major # == 5 */
+ u_char mrh_minor; /* minor # == 0 */
+ u_char mrh_type;
+ u_char mrh_flags;
+ u_32_t mrh_endian;
+ u_short mrh_dlen; /* data size */
+ u_short mrh_alen; /* authentication length */
+ u_32_t mrh_cid; /* call identifier */
+ u_32_t mrh_hint; /* allocation hint */
+ u_short mrh_ctxt; /* presentation context hint */
+ u_char mrh_ccnt; /* cancel count */
+ u_char mrh_ans;
+} msnrpchdr_t;
+
+int ippr_msnrpc_init __P((void));
+void ippr_msnrpc_fini __P((void));
+int ippr_msnrpc_new __P((fr_info_t *, ap_session_t *, nat_t *));
+int ippr_msnrpc_out __P((fr_info_t *, ap_session_t *, nat_t *));
+int ippr_msnrpc_in __P((fr_info_t *, ap_session_t *, nat_t *));
+int ippr_msnrpc_check __P((ip_t *, msnrpchdr_t *));
+
+static frentry_t msnfr;
+
+int msn_proxy_init = 0;
+
+/*
+ * Initialize local structures.
+ */
+int ippr_msnrpc_init()
+{
+ bzero((char *)&msnfr, sizeof(msnfr));
+ msnfr.fr_ref = 1;
+ msnfr.fr_flags = FR_INQUE|FR_PASS|FR_QUICK|FR_KEEPSTATE;
+ MUTEX_INIT(&msnfr.fr_lock, "MSN RPC proxy rule lock");
+ msn_proxy_init = 1;
+
+ return 0;
+}
+
+
+void ippr_msnrpc_fini()
+{
+ if (msn_proxy_init == 1) {
+ MUTEX_DESTROY(&msnfr.fr_lock);
+ msn_proxy_init = 0;
+ }
+}
+
+
+int ippr_msnrpc_new(fin, aps, nat)
+fr_info_t *fin;
+ap_session_t *aps;
+nat_t *nat;
+{
+ msnrpcinfo_t *mri;
+
+ KMALLOC(mri, msnrpcinfo_t *);
+ if (mri == NULL)
+ return -1;
+ aps->aps_data = mri;
+ aps->aps_psiz = sizeof(msnrpcinfo_t);
+
+ bzero((char *)mri, sizeof(*mri));
+ mri->mri_cmd[0] = 0xff;
+ mri->mri_cmd[1] = 0xff;
+ return 0;
+}
+
+
+int ippr_msnrpc_check(ip, mrh)
+ip_t *ip;
+msnrpchdr_t *mrh;
+{
+ if (mrh->mrh_major != 5)
+ return -1;
+ if (mrh->mrh_minor != 0)
+ return -1;
+ if (mrh->mrh_alen != 0)
+ return -1;
+ if (mrh->mrh_endian == 0x10) {
+ /* Both gateway and packet match endian */
+ if (mrh->mrh_dlen > ip->ip_len)
+ return -1;
+ if (mrh->mrh_type == 0 || mrh->mrh_type == 2)
+ if (mrh->mrh_hint > ip->ip_len)
+ return -1;
+ } else if (mrh->mrh_endian == 0x10000000) {
+ /* XXX - Endian mismatch - should be swapping! */
+ return -1;
+ } else {
+ return -1;
+ }
+ return 0;
+}
+
+
+int ippr_msnrpc_out(fin, ip, aps, nat)
+fr_info_t *fin;
+ip_t *ip;
+ap_session_t *aps;
+nat_t *nat;
+{
+ msnrpcinfo_t *mri;
+ msnrpchdr_t *mrh;
+ tcphdr_t *tcp;
+ int dlen;
+
+ mri = aps->aps_data;
+ if (mri == NULL)
+ return 0;
+
+ tcp = (tcphdr_t *)fin->fin_dp;
+ dlen = fin->fin_dlen - (TCP_OFF(tcp) << 2);
+ if (dlen < IPF_MINMSNRPCLEN)
+ return 0;
+
+ mrh = (msnrpchdr_t *)((char *)tcp + (TCP_OFF(tcp) << 2));
+ if (ippr_msnrpc_check(ip, mrh))
+ return 0;
+
+ mri->mri_valid++;
+
+ switch (mrh->mrh_type)
+ {
+ case 0x0b : /* BIND */
+ case 0x00 : /* REQUEST */
+ break;
+ case 0x0c : /* BIND ACK */
+ case 0x02 : /* RESPONSE */
+ default:
+ return 0;
+ }
+ mri->mri_cmd[1] = mrh->mrh_type;
+ return 0;
+}
+
+
+int ippr_msnrpc_in(fin, ip, aps, nat)
+fr_info_t *fin;
+ip_t *ip;
+ap_session_t *aps;
+nat_t *nat;
+{
+ tcphdr_t *tcp, tcph, *tcp2 = &tcph;
+ int dlen, sz, sz2, i;
+ msnrpcinfo_t *mri;
+ msnrpchdr_t *mrh;
+ fr_info_t fi;
+ u_short len;
+ char *s;
+
+ mri = aps->aps_data;
+ if (mri == NULL)
+ return 0;
+ tcp = (tcphdr_t *)fin->fin_dp;
+ dlen = fin->fin_dlen - (TCP_OFF(tcp) << 2);
+ if (dlen < IPF_MINMSNRPCLEN)
+ return 0;
+
+ mrh = (msnrpchdr_t *)((char *)tcp + (TCP_OFF(tcp) << 2));
+ if (ippr_msnrpc_check(ip, mrh))
+ return 0;
+
+ mri->mri_valid++;
+
+ switch (mrh->mrh_type)
+ {
+ case 0x0c : /* BIND ACK */
+ if (mri->mri_cmd[1] != 0x0b)
+ return 0;
+ break;
+ case 0x02 : /* RESPONSE */
+ if (mri->mri_cmd[1] != 0x00)
+ return 0;
+ break;
+ case 0x0b : /* BIND */
+ case 0x00 : /* REQUEST */
+ default:
+ return 0;
+ }
+ mri->mri_cmd[0] = mrh->mrh_type;
+ dlen -= sizeof(*mrh);
+
+ /*
+ * Only processes RESPONSE's
+ */
+ if (mrh->mrh_type != 0x02)
+ return 0;
+
+ /*
+ * Skip over some bytes...what are these really ?
+ */
+ if (dlen <= 44)
+ return 0;
+ s = (char *)(mrh + 1) + 20;
+ dlen -= 20;
+ bcopy(s, (char *)&len, sizeof(len));
+ if (len == 1) {
+ s += 20;
+ dlen -= 20;
+ } else if (len == 2) {
+ s += 24;
+ dlen -= 24;
+ } else
+ return 0;
+
+ if (dlen <= 10)
+ return 0;
+ dlen -= 10;
+ bcopy(s, (char *)&sz, sizeof(sz));
+ s += sizeof(sz);
+ bcopy(s, (char *)&sz2, sizeof(sz2));
+ s += sizeof(sz2);
+ if (sz2 != sz)
+ return 0;
+ if (sz > dlen)
+ return 0;
+ if (*s++ != 5)
+ return 0;
+ if (*s++ != 0)
+ return 0;
+ sz -= IPF_MSNRPCSKIP;
+ s += IPF_MSNRPCSKIP;
+ dlen -= IPF_MSNRPCSKIP;
+
+ do {
+ if (sz < 7 || dlen < 7)
+ break;
+ bcopy(s, (char *)&len, sizeof(len));
+ if (dlen < len)
+ break;
+ if (sz < len)
+ break;
+
+ if (len != 1)
+ break;
+ sz -= 3;
+ i = *(s + 2);
+ s += 3;
+ dlen -= 3;
+
+ bcopy(s, (char *)&len, sizeof(len));
+ if (dlen < len)
+ break;
+ if (sz < len)
+ break;
+ s += sizeof(len);
+
+ switch (i)
+ {
+ case 7 :
+ if (len == 2) {
+ bcopy(s, (char *)&mri->mri_rport, 2);
+ mri->mri_flags |= 1;
+ }
+ break;
+ case 9 :
+ if (len == 4) {
+ bcopy(s, (char *)&mri->mri_raddr, 4);
+ mri->mri_flags |= 2;
+ }
+ break;
+ default :
+ break;
+ }
+ sz -= len;
+ s += len;
+ dlen -= len;
+ } while (sz > 0);
+
+ if (mri->mri_flags == 3) {
+ int slen;
+
+ bcopy((char *)fin, (char *)&fi, sizeof(fi));
+ bzero((char *)tcp2, sizeof(*tcp2));
+
+ slen = ip->ip_len;
+ ip->ip_len = fin->fin_hlen + sizeof(*tcp2);
+ bcopy((char *)fin, (char *)&fi, sizeof(fi));
+ bzero((char *)tcp2, sizeof(*tcp2));
+ tcp2->th_win = htons(8192);
+ TCP_OFF_A(tcp2, 5);
+ fi.fin_data[0] = htons(mri->mri_rport);
+ tcp2->th_sport = mri->mri_rport;
+ fi.fin_data[1] = 0;
+ tcp2->th_dport = 0;
+ fi.fin_state = NULL;
+ fi.fin_nat = NULL;
+ fi.fin_dlen = sizeof(*tcp2);
+ fi.fin_plen = fi.fin_hlen + sizeof(*tcp2);
+ fi.fin_dp = (char *)tcp2;
+ fi.fin_fi.fi_daddr = ip->ip_dst.s_addr;
+ fi.fin_fi.fi_saddr = mri->mri_raddr.s_addr;
+ if (!fi.fin_fr)
+ fi.fin_fr = &msnfr;
+ if (fr_stlookup(&fi, NULL, NULL)) {
+ RWLOCK_EXIT(&ipf_state);
+ } else {
+ (void) fr_addstate(&fi, NULL, SI_W_DPORT|SI_CLONE);
+ if (fi.fin_state != NULL)
+ fr_statederef(&fi, (ipstate_t **)&fi.fin_state);
+ }
+ ip->ip_len = slen;
+ }
+ mri->mri_flags = 0;
+ return 0;
+}
OpenPOWER on IntegriCloud