Re: ipnat and tftp

This is a discussion on Re: ipnat and tftp within the IPFilter forums, part of the System Security and Security Related category; This is a multi-part message in MIME format. --------------050609040704060709050506 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-...


Go Back   Usenet Forums > System Security and Security Related > IPFilter

FAQ Members List Calendar Search Today's Posts Mark Forums Read
  #1 (permalink)  
Old 12-11-2006
Darren Reed
 
Posts: n/a
Default Re: ipnat and tftp

This is a multi-part message in MIME format.
--------------050609040704060709050506
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: 7bit

Darren Reed wrote:
> Hi,
>
> Since I saw your email, I sat down and worked on a TFTP proxy to fit
> in with IPFilter.
>
> To make it work, you can take one of two paths.
> 1) copy ip_tftp_pxy.c into the IPFilter source code tree, modify the
> ip_proxy.c
> file to include it and recompile IPFilter;
> 2) if you're using 4.1.13 or later, you can compile it as a standalone
> LKM and
> load it into IPFilter for use that way.
>
> Darren
>


Sorry, forgot to attach the .c file.

Darren


--------------050609040704060709050506
Content-Type: text/plain;
name="ip_tftp_pxy.c"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="ip_tftp_pxy.c"

/*
* Copyright (C) 2006 by Darren Reed.
*
* See the IPFILTER.LICENCE file for details on licencing.
*
*/
#include <sys/types.h>
#include <sys/modctl.h>
#include <sys/ddi.h>
#include <sys/uio.h>
#include <sys/sunddi.h>
#include <net/if.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/udp.h>
#include <netinet/tcp.h>
#include <netinet/ip_compat.h>
#include <netinet/ip_fil.h>
#include <netinet/ip_nat.h>
#include <netinet/ip_state.h>
#include <netinet/ip_proxy.h>

static int ipprtftpattach __P((dev_info_t *dip, ddi_attach_cmd_t cmd));
static int ipprtftpdetach __P((dev_info_t *dip, ddi_detach_cmd_t cmd));
static void ippr_tftp_fini __P((void));
static int ippr_tftp_new __P((fr_info_t *, ap_session_t *, nat_t *));
static int ippr_tftp_out __P((fr_info_t *, ap_session_t *, nat_t *));
static int ippr_tftp_in __P((fr_info_t *, ap_session_t *, nat_t *));
static int ippr_tftp_client __P((fr_info_t *, ap_session_t *, nat_t *));
static int ippr_tftp_server __P((fr_info_t *, ap_session_t *, nat_t *));

static int ippr_tftp_init __P((void));
static frentry_t tftpfr;

static aproxy_t tftp_proxy = {
NULL,
"tftp",
(char)IPPROTO_UDP,
0,
0,
ippr_tftp_init,
ippr_tftp_fini,
ippr_tftp_new,
NULL, /* del */
ippr_tftp_in,
ippr_tftp_out,
NULL, /* match */
NULL /* ctl */
};

int tftp_proxy_init = 0;

typedef struct tftpinfo {
nat_t *ti_datanat;
ipstate_t *ti_datastate;
int ti_lastcmd;
int ti_nextblk;
int ti_lastblk;
int ti_lasterror;
char ti_filename[80];
} tftpinfo_t;

#define TFTP_CMD_READ 1
#define TFTP_CMD_WRITE 2
#define TFTP_CMD_DATA 3
#define TFTP_CMD_ACK 4
#define TFTP_CMD_ERROR 5


#ifdef STANDALONE
static struct dev_ops drv_ops = {
DEVO_REV, /* devo_rev */
0, /* devo_refcnt */
nodev, /* devo_getinfo */
nulldev, /* devo_identify */
nulldev, /* devo_probe */
ipprtftpattach, /* devo_attach */
ipprtftpdetach, /* devo_detach */
nodev, /* devo_reset */
NULL, /* devo_cb_ops */
NULL, /* devo_bus_ops */
NULL, /* devo_power */
};

/*
* Module linkage information for the kernel.
*/
static struct modldrv modldrv = {
&mod_miscops,
"IPFilter TFTP Proxy",
&drv_ops /* driver ops */
};

static struct modlinkage modlinkage = {
MODREV_1,
&modldrv,
NULL
};



int _init()
{

if (mod_install(&modlinkage) != DDI_SUCCESS) {
return DDI_FAILURE;
}

if (appr_add(&tftp_proxy) != 0) {
printf("appr_add failed\n");
return DDI_FAILURE;
}

return DDI_SUCCESS;
}


int _fini()
{
if (appr_del(&tftp_proxy) != 0) {
return DDI_FAILURE;
}

if (mod_remove(&modlinkage) != DDI_SUCCESS)
return DDI_FAILURE;

return DDI_SUCCESS;
}


int _info(struct modinfo *modinfop)
{
return (mod_info(&modlinkage, modinfop));
}


static int ipprtftpattach(dip, cmd)
dev_info_t *dip;
ddi_attach_cmd_t cmd;
{

printf("ipprtftpattach(%p,%x)\n", dip, cmd);
if (cmd != DDI_ATTACH)
return DDI_FAILURE;

if (appr_add(&tftp_proxy) != 0)
return DDI_FAILURE;

return DDI_SUCCESS;
}


static int ipprtftpdetach(dip, cmd)
dev_info_t *dip;
ddi_detach_cmd_t cmd;
{

if (cmd != DDI_DETACH)
return DDI_FAILURE;

if (appr_del(&tftp_proxy) != 0)
return DDI_FAILURE;

return DDI_SUCCESS;
}

#endif /* STANDALONE */


/*
* RCMD application proxy initialization.
*/
int ippr_tftp_init()
{

bzero((char *)&tftpfr, sizeof(tftpfr));
tftpfr.fr_ref = 1;
tftpfr.fr_flags = FR_INQUE|FR_PASS|FR_QUICK|FR_KEEPSTATE;
MUTEX_INIT(&tftpfr.fr_lock, "TFTP proxy rule lock");
tftp_proxy_init = 1;

return 0;
}


void ippr_tftp_fini()
{

if (tftp_proxy_init == 1) {
MUTEX_DESTROY(&tftpfr.fr_lock);
tftp_proxy_init = 0;
}
}


int ippr_tftp_out(fin, aps, nat)
fr_info_t *fin;
ap_session_t *aps;
nat_t *nat;
{

if (nat->nat_dir == NAT_OUTBOUND)
return ippr_tftp_client(fin, aps, nat);
return ippr_tftp_server(fin, aps, nat);
}


int ippr_tftp_in(fin, aps, nat)
fr_info_t *fin;
ap_session_t *aps;
nat_t *nat;
{

if (nat->nat_dir == NAT_INBOUND)
return ippr_tftp_client(fin, aps, nat);
return ippr_tftp_server(fin, aps, nat);
}


int ippr_tftp_new(fin, aps, nat)
fr_info_t *fin;
ap_session_t *aps;
nat_t *nat;
{
udphdr_t *udp;
tftpinfo_t *ti;

KMALLOC(ti, tftpinfo_t *);
if (ti == NULL)
return -1;

aps->aps_data = ti;
aps->aps_psiz = sizeof(*ti);
ti->ti_lastcmd = 0;

nat = nat; /* LINT */
fin = fin; /* LINT */

udp = (udphdr_t *)fin->fin_dp;
aps->aps_sport = udp->uh_sport;
aps->aps_dport = udp->uh_dport;
return 0;
}


/*
* Setup for a new RCMD proxy.
*/
int ippr_tftp_backchannel(fin, aps, nat)
fr_info_t *fin;
ap_session_t *aps;
nat_t *nat;
{
tftpinfo_t *ti;
udphdr_t *udp;
fr_info_t fi;
u_short slen;
nat_t *nat2;

ti = aps->aps_data;
udp = (udphdr_t *)fin->fin_dp;
/*
* Add skeleton NAT entry for connection which will come back the
* other way.
*/
bcopy((char *)fin, (char *)&fi, sizeof(fi));
fi.fin_state = NULL;
fi.fin_nat = NULL;
fi.fin_flx |= FI_IGNORE;
fi.fin_data[1] = 0;
if (nat->nat_dir == NAT_OUTBOUND)
nat2 = nat_outlookup(&fi, NAT_SEARCH|IPN_UDP, nat->nat_p,
nat->nat_inip, nat->nat_oip);
else
nat2 = nat_inlookup(&fi, NAT_SEARCH|IPN_UDP, nat->nat_p,
nat->nat_inip, nat->nat_oip);
if (nat2 == NULL) {
struct in_addr swip,swip2;
int slen, nflags;
ip_t *ip;

ip = fin->fin_ip;
slen = ip->ip_len;
ip->ip_len = fin->fin_hlen + sizeof(*udp);
bzero((char *)udp, sizeof(*udp));
udp->uh_sport = htons(fi.fin_data[0]);
udp->uh_dport = 0; /* XXX - don't specify remote port */
udp->uh_ulen = 0;
udp->uh_sum = 0;
fi.fin_dp = (char *)udp;
fi.fin_fr = &tftpfr;
fi.fin_dlen = sizeof(*udp);
fi.fin_plen = fi.fin_hlen + sizeof(*udp);
fi.fin_flx &= FI_LOWTTL|FI_FRAG|FI_TCPUDP|FI_OPTIONS|FI_IGNORE;
nflags = NAT_SLAVE|IPN_UDP|SI_W_DPORT;

swip = ip->ip_src;
swip2 = ip->ip_dst;

if (nat->nat_dir == NAT_OUTBOUND) {
fi.fin_fi.fi_saddr = nat->nat_inip.s_addr;
ip->ip_src = nat->nat_inip;
} else {
fi.fin_fi.fi_saddr = nat->nat_oip.s_addr;
ip->ip_src = nat->nat_oip;
nflags |= NAT_NOTRULEPORT;
}

nat2 = nat_new(&fi, nat->nat_ptr, NULL, nflags, nat->nat_dir);

if (nat2 != NULL) {
(void) nat_proto(&fi, nat2, IPN_UDP);
nat_update(&fi, nat2, nat2->nat_ptr);
fi.fin_ifp = NULL;
if (nat->nat_dir == NAT_INBOUND) {
fi.fin_fi.fi_daddr = nat->nat_inip.s_addr;
ip->ip_dst = nat->nat_inip;
}
(void) fr_addstate(&fi, &nat2->nat_state, SI_W_DPORT);
if (fi.fin_state != NULL)
fr_statederef(&fi, (ipstate_t **)&fi.fin_state);
ti->ti_datanat = nat2;
ti->ti_datastate = fi.fin_state;
}
ip->ip_src = swip;
ip->ip_dst = swip2;
return 0;
}
return -1;
}


int ippr_tftp_client(fin, aps, nat)
fr_info_t *fin;
ap_session_t *aps;
nat_t *nat;
{
u_char *msg, *s, *t;
tftpinfo_t *ti;
u_short opcode;
udphdr_t *udp;
int len;

if (fin->fin_dlen < 4)
return 0;

ti = aps->aps_data;
msg = fin->fin_dp;
msg += sizeof(udphdr_t);
opcode = (msg[0] << 8) | msg[1];

switch (opcode)
{
case TFTP_CMD_READ :
case TFTP_CMD_WRITE :
if (fin->fin_out != 0)
return -1;
len = fin->fin_dlen - sizeof(*udp) - 2;
if (len > sizeof(ti->ti_filename) - 1)
len = sizeof(ti->ti_filename) - 1;
s = msg + 2;
for (t = (u_char *)ti->ti_filename; (len > 0); len--, s++) {
*t++ = *s;
if (*s == '\0')
break;
}
break;
default :
return -1;
}

ti = aps->aps_data;
ti->ti_lastcmd = opcode;
return 0;
}


int ippr_tftp_server(fin, aps, nat)
fr_info_t *fin;
ap_session_t *aps;
nat_t *nat;
{
tftpinfo_t *ti;
u_short opcode;
u_short arg;
u_char *msg;

if (fin->fin_dlen < 4)
return 0;

msg = fin->fin_dp;
msg += sizeof(udphdr_t);
opcode = (msg[0] << 8) | msg[1];

switch (opcode)
{
case TFTP_CMD_ACK :
/* This proxy should not see any ACKS for DATA blocks */
if (fin->fin_out != 1)
return -1;
arg = (msg[2] << 8) | msg[3];
if ((arg == 0) &&
(ti->ti_lastcmd == TFTP_CMD_READ ||
ti->ti_lastcmd == TFTP_CMD_WRITE))
ippr_tftp_backchannel(fin, aps, nat);
ti->ti_lastblk = arg;
break;
case TFTP_CMD_ERROR :
if (fin->fin_out != 1)
return -1;
ti->ti_lasterror = arg;
break;
default :
return -1;
}

ti = aps->aps_data;
ti->ti_lastcmd = opcode;
return 0;
}

--------------050609040704060709050506--
Reply With Quote
Reply
Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are Off
[IMG] code is Off
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On



All times are GMT +1. The time now is 12:17 AM.


Powered by vBulletin® Version 3.7.3
Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
Content Relevant URLs by vBSEO 3.0.0