From 7ec5099b5f5c79419a54a6cdedea618d98b60569 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 5 Nov 2003 10:44:19 +0000 Subject: Commit initial version git-svn-id: file:///home/lennart/svn/public/seppl/trunk@2 91a2fd9b-5dcb-0310-a70a-d71e310228e6 --- kernel/ipt_CRYPT.c | 190 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 190 insertions(+) create mode 100644 kernel/ipt_CRYPT.c (limited to 'kernel/ipt_CRYPT.c') diff --git a/kernel/ipt_CRYPT.c b/kernel/ipt_CRYPT.c new file mode 100644 index 0000000..9f7d055 --- /dev/null +++ b/kernel/ipt_CRYPT.c @@ -0,0 +1,190 @@ +/* $Id: newmail.c 31 2003-10-22 22:59:07Z lennart $ */ + +/*** + This file is part of seppl + + seppl is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + seppl is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with seppl; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA +***/ + +#include +#include +#include +#include +#include +#include +struct in_device; +#include +#include +#include + +#include "seppl.h" +#include "ipt_CRYPT.h" + +#ifdef MODULE_LICENSE +MODULE_LICENSE("GPL"); +#endif +#ifdef MODULE_DESCRIPTION +MODULE_DESCRIPTION("SEPPL iptables Encryption Target"); +#endif +#ifdef MODULE_AUTHOR +MODULE_AUTHOR("Lennart Poettering <"PACKAGE_BUGREPORT">"); +#endif + +static unsigned int ipt_CRYPT_target(struct sk_buff **pskb, unsigned int hooknum, const struct net_device *in, const struct net_device *out, const void *_ti, void *userinfo) { + const struct ipt_crypt_info *ti = _ti; + struct iphdr *ih = (*pskb)->nh.iph; + unsigned d, new_l, crypt_l, ihl = ih->ihl<<2; + struct seppl_uncrypt_hdr *uh; + struct seppl_crypt_hdr *ch; + u8 *iv, *pl; + int ivs = ti->key->ivsize; + int bs = ti->key->blocksize; + struct sock *sk; + struct scatterlist sg[1]; + + // Calculate new packet size + new_l = ihl + sizeof(struct seppl_uncrypt_hdr) + ivs + ((sizeof(struct seppl_crypt_hdr) + ntohs(ih->tot_len) - ihl + bs - 1) / bs) * bs; + d = new_l - htons(ih->tot_len); + crypt_l = new_l - ihl - sizeof(struct seppl_uncrypt_hdr) - ivs; + + //DEBUGP("CRYPT: tot_len=%i, new_l=%i, d=%i, crypt_l=%i\n", htons(ih->tot_len), new_l, d, crypt_l); + + // Copy the skb if needed and increase it correctly + if (skb_tailroom(*pskb) < d || skb_cloned(*pskb)) { + struct sk_buff *n; + + if (!(n = skb_copy_expand(*pskb, skb_headroom(*pskb), d, GFP_ATOMIC))) { + if (net_ratelimit()) + printk(KERN_ERR "ipt_CRYPT: Unable to allocate larger skb, dropping packet.\n"); + + return NF_DROP; + } + + if ((*pskb)->sk) + skb_set_owner_w(n, (*pskb)->sk); + + kfree_skb(*pskb); + *pskb = n; + ih = (*pskb)->nh.iph; + } + + skb_put(*pskb, d); + + // Calculate some pointers + //ih = ... /* IP-Header */ + uh = (struct seppl_uncrypt_hdr*) ((u8*) ih + ihl); /* Unencrypted header */ + iv = ((u8*) uh) + sizeof(struct seppl_uncrypt_hdr); /* IV */ + ch = (struct seppl_crypt_hdr*) (iv + ivs); /* Crypted header */ + pl = ((u8*) ch) + sizeof(struct seppl_crypt_hdr); /* Payload */ + + // Copy the payload + memmove(pl, uh, ntohs(ih->tot_len) - ihl); + + // Fill the uncrypted header + uh->algorithm = ti->key->algorithm; + strncpy(uh->key_name, ti->key->name, 7); + + // Copy the IV + seppl_copy_iv(ti->key, iv); + + // Fill the crypted header + ch->ident = 0x00; + ch->saved_protocol = ih->protocol; + ch->saved_tot_len = ih->tot_len; + ch->saved_frag_off = ih->frag_off; + + // Fill the IP header + ih->protocol = SEPPL_PROTOCOL; + ih->tot_len = htons(new_l); + ih->frag_off = 0; + + // Checksum FIXME: Is this really needed? + ih->check = 0; + ih->check = ip_fast_csum((char *) ih, ih->ihl); + + // Crypt + sg[0].page = virt_to_page((void*) ch); + sg[0].offset = (((long) (void *) ch) & ~PAGE_MASK); + sg[0].length = crypt_l; + + crypto_cipher_set_iv(ti->key->tfm, iv, ti->key->ivsize); + + if (crypto_cipher_encrypt(ti->key->tfm, sg, sg, sg[0].length)) { + if (net_ratelimit()) + printk(KERN_ERR "ipt_CRYPT: encrypt() failure\n"); + return NF_DROP; + } + + // Finish + (*pskb)->ip_summed = CHECKSUM_NONE; + (*pskb)->nfcache |= NFC_UNKNOWN | NFC_ALTERED; + + return IPT_CONTINUE; +} + +static int ipt_CRYPT_check(const char *table, const struct ipt_entry *e, void *_ti, unsigned int ti_size, unsigned int hook_mask) { + struct ipt_crypt_info *ti = _ti; + + if (ti_size != IPT_ALIGN(sizeof(struct ipt_crypt_info))) { + printk(KERN_ERR "ipt_CRYPT: Structure too small\n"); + return 0; + } + + if (strcmp(table, "mangle") != 0) { + printk(KERN_ERR "ipt_CRYPT: Not in mangle table\n"); + return 0; + } + + if ((hook_mask & ~(1 << NF_IP_POST_ROUTING)) != 0) { + printk(KERN_ERR "ipt_CRYPT: Not in POSTROUTING chain\n"); + return 0; + } + + if (!(ti->key = seppl_claim_key(ti->algorithm, ti->name))) { + printk(KERN_ERR "ipt_CRYPT: Cannot find key\n"); + return 0; + } + + return 1; +} + +static void ipt_CRYPT_destroy(void *_ti, unsigned int ti_size) { + struct ipt_crypt_info *ti = _ti; + + seppl_release_key(ti->key); +} + +static struct ipt_target ipt_CRYPT_reg = { + { NULL, NULL }, + "CRYPT", + ipt_CRYPT_target, + ipt_CRYPT_check, + ipt_CRYPT_destroy, + THIS_MODULE +}; + +static int __init init(void) { + return ipt_register_target(&ipt_CRYPT_reg); +} + +static void __exit fini(void) { + ipt_unregister_target(&ipt_CRYPT_reg); +} + +module_init(init); +module_exit(fini); + +EXPORT_NO_SYMBOLS; -- cgit