⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 aaa.c

📁 第二层隧道模块l2tp源码,开发环境为linux
💻 C
字号:
/* * Layer Two Tunnelling Protocol Daemon * Copyright (C) 1998 Adtran, Inc. * Copyright (C) 2002 Jeff McAdams * * Mark Spencer * * This software is distributed under the terms * of the GPL, which you should have received * along with this source. * * Authorization, Accounting, and Access control * */#include <stdio.h>#include <stdlib.h>#include <netinet/in.h>#include <arpa/inet.h>#include <string.h>#include <errno.h>#include "l2tp.h"extern void bufferDump (char *, int);/* FIXME: Accounting? */static struct addr_ent *uaddr[ADDR_HASH_SIZE];void init_addr (){    int x;    for (x = 0; x < ADDR_HASH_SIZE; x++)        uaddr[x] = NULL;}static int ip_used (unsigned int addr){    struct addr_ent *tmp;    tmp = uaddr[addr % ADDR_HASH_SIZE];    while (tmp)    {        if (tmp->addr == addr)            return -1;        tmp = tmp->next;    }    return 0;}void mk_challenge (char *c, int length){    get_entropy(c, length);    /* int x;    int *s = (int *) c;    for (x = 0; x < length / sizeof (int); x++)        s[x] = rand (); */}void reserve_addr (unsigned int addr){    /* Mark this address as in use */    struct addr_ent *tmp, *tmp2;    addr = ntohl (addr);    if (ip_used (addr))        return;    tmp = uaddr[addr % ADDR_HASH_SIZE];    tmp2 = (struct addr_ent *) malloc (sizeof (struct addr_ent));    uaddr[addr % ADDR_HASH_SIZE] = tmp2;    tmp2->next = tmp;    tmp2->addr = addr;}void unreserve_addr (unsigned int addr){    struct addr_ent *tmp, *last = NULL, *z;    addr = ntohl (addr);    tmp = uaddr[addr % ADDR_HASH_SIZE];    while (tmp)    {        if (tmp->addr == addr)        {            if (last)            {                last->next = tmp->next;            }            else            {                uaddr[addr % ADDR_HASH_SIZE] = tmp->next;            }            z = tmp;            tmp = tmp->next;            free (z);        }        else        {            last = tmp;            tmp = tmp->next;        }    }}unsigned int get_addr (struct iprange *ipr){    unsigned int x, y;    int status;    struct iprange *ipr2;    while (ipr)    {        if (ipr->sense == SENSE_ALLOW)            for (x = ntohl (ipr->start); x <= ntohl (ipr->end); x++)            {                /* Found an IP in an ALLOW range, check to be sure it is                   consistant through the remaining regions */                if (!ip_used (x))                {                    status = SENSE_ALLOW;                    ipr2 = ipr->next;                    while (ipr2)                    {                        if ((x >= ntohl (ipr2->start))                            && (x <= ntohl (ipr2->end)))                            status = ipr2->sense;                        ipr2 = ipr2->next;                    }                    y = htonl (x);                    if (status == SENSE_ALLOW)                        return y;                }            };        ipr = ipr->next;    }    return 0;}int get_secret (char *us, char *them, char *secret, int size){    FILE *f;    char buf[STRLEN];    char *u, *t, *s;    int num = 0;    f = fopen (gconfig.authfile, "r");    if (!f)    {        log (LOG_WARN, "%s : Unable to open '%s' for authentication\n",             __FUNCTION__, gconfig.authfile);        return 0;    }    while (!feof (f))    {        num++;        fgets (buf, sizeof (buf), f);        if (feof (f))            break;        /* Strip comments */        for (t = buf; *t; t++)            *t = ((*t == '#') || (*t == ';')) ? 0 : *t;        /* Strip trailing whitespace */        for (t = buf + strlen (buf) - 1; (t >= buf) && (*t < 33); t--)            *t = 0;        if (!strlen (buf))            continue;           /* Empty line */        u = buf;        while (*u && (*u < 33))            u++;        /* us */        if (!*u)        {            log (LOG_WARN,                 "%s: Invalid authentication info (no us), line %d\n",                 __FUNCTION__, num);            continue;        }        t = u;        while (*t > 32)            t++;        *(t++) = 0;        while (*t && (*t < 33))            t++;        /* them */        if (!*t)        {            log (LOG_WARN,                 "%s: Invalid authentication info (nothem), line %d\n",                 __FUNCTION__, num);            continue;        }        s = t;        while (*s > 33)            s++;        *(s++) = 0;        while (*s && (*s < 33))            s++;        if (!*s)        {            log (LOG_WARN,                 "%s: Invalid authentication info (no secret), line %d\n",                 __FUNCTION__, num);            continue;        }        if ((!strcasecmp (u, us) || !strcasecmp (u, "*")) &&            (!strcasecmp (t, them) || !strcasecmp (t, "*")))        {#ifdef DEBUG_AUTH            log (LOG_DEBUG,                 "%s: we are '%s', they are '%s', secret is '%s'\n",                 __FUNCTION__, u, t, s);#endif            strncpy (secret, s, size);            return -1;        }    }    return 0;}int handle_challenge (struct tunnel *t, struct challenge *chal){    char *us;    char *them;    if (!t->lns && !t->lac)    {        log (LOG_DEBUG, "%s: No LNS or LAC to handle challenge!\n",             __FUNCTION__);        return -1;    }#ifdef DEBUG_AUTH    log (LOG_DEBUG, "%s: making response for tunnel: %d\n", __FUNCTION__,         t->ourtid);#endif    if (t->lns)    {        if (t->lns->hostname[0])            us = t->lns->hostname;        else            us = hostname;        if (t->lns->peername[0])            them = t->lns->peername;        else            them = t->hostname;    }    else    {        if (t->lac->hostname[0])            us = t->lac->hostname;        else            us = hostname;        if (t->lac->peername[0])            them = t->lac->peername;        else            them = t->hostname;    }    if (!get_secret (us, them, chal->secret, sizeof (chal->secret)))    {        log (LOG_DEBUG, "%s: no secret found for us='%s' and them='%s'\n",             __FUNCTION__, us, them);        return -1;    }#if DEBUG_AUTH    log (LOG_DEBUG, "*%s: Here comes the chal->ss:\n", __FUNCTION__);    bufferDump (&chal->ss, 1);    log (LOG_DEBUG, "%s: Here comes the secret\n", __FUNCTION__);    bufferDump (chal->secret, strlen (chal->secret));    log (LOG_DEBUG, "%s: Here comes the challenge\n", __FUNCTION__);    bufferDump (chal->challenge, strlen (chal->challenge));#endif    memset (chal->response, 0, MD_SIG_SIZE);    MD5Init (&chal->md5);    MD5Update (&chal->md5, &chal->ss, 1);    MD5Update (&chal->md5, chal->secret, strlen (chal->secret));    MD5Update (&chal->md5, chal->challenge, strlen(chal->challenge));    MD5Final (chal->response, &chal->md5);#ifdef DEBUG_AUTH    log (LOG_DEBUG, "response is %X%X%X%X to '%s' and %X%X%X%X, %d\n",         *((int *) &chal->response[0]),         *((int *) &chal->response[4]),         *((int *) &chal->response[8]),         *((int *) &chal->response[12]),         chal->secret,         *((int *) &chal->challenge[0]),         *((int *) &chal->challenge[4]),         *((int *) &chal->challenge[8]),         *((int *) &chal->challenge[12]), chal->ss);#endif    chal->state = STATE_CHALLENGED;    return 0;}struct lns *get_lns (struct tunnel *t){    /*     * Look through our list of LNS's and     * find a reasonable LNS for this call     * if one is available     */    struct lns *lns;    struct iprange *ipr;    int allow, checkdefault = 0;    /* If access control is disabled, we give the default       otherwise, we give nothing */    allow = 0;    lns = lnslist;    if (!lns)    {        lns = deflns;        checkdefault = -1;    }    while (lns)    {        ipr = lns->lacs;        while (ipr)        {            if ((ntohl (t->peer.sin_addr.s_addr) >= ntohl (ipr->start)) &&                (ntohl (t->peer.sin_addr.s_addr) <= ntohl (ipr->end)))            {#ifdef DEBUG_AAA                log (LOG_DEBUG,                     "get_lns: Rule %s to %s, sense %s matched %s\n",                     IPADDY (ipr->start), IPADDY (ipr->end),                     (ipr->sense ? "allow" : "deny"), IPADDY (t->addr));#endif                allow = ipr->sense;            }            ipr = ipr->next;        }        if (allow)            return lns;        lns = lns->next;        if (!lns && !checkdefault)        {            lns = deflns;            checkdefault = -1;        }    }    if (gconfig.accesscontrol)        return NULL;    else        return deflns;}#ifdef DEBUG_HIDDENvoid print_md5 (void *md5){    int *i = (int *) md5;    log (LOG_DEBUG, "%X%X%X%X\n", i[0], i[1], i[2], i[3], i[4]);}inline void print_challenge (struct challenge *chal){    log (LOG_DEBUG, "vector: ");    print_md5 (chal->vector);    log (LOG_DEBUG, "secret: %s\n", chal->secret);}#endifvoid encrypt_avp (struct buffer *buf, _u16 len, struct tunnel *t){    /* Encrypts an AVP of len, at data.  We assume there       are two "spare bytes" before the data pointer,l but otherwise       this is just a normal AVP that is about to be returned from       an avpsend routine */    struct avp_hdr *new_hdr =        (struct avp_hdr *) (buf->start + buf->len - len);    struct avp_hdr *old_hdr =        (struct avp_hdr *) (buf->start + buf->len - len + 2);    _u16 length, flags, attr;   /* New length, old flags */    char *ptr, *end;    int cnt;    unsigned char digest[MD_SIG_SIZE];    unsigned char *previous_segment;    /* FIXME: Should I pad more randomly? Right now I pad to nearest 16 bytes */    length =        ((len - sizeof (struct avp_hdr) + 1) / 16 + 1) * 16 +        sizeof (struct avp_hdr);    flags = htons (old_hdr->length) & 0xF000;    new_hdr->length = htons (length | flags | HBIT);    new_hdr->vendorid = old_hdr->vendorid;    new_hdr->attr = attr = old_hdr->attr;    /* This is really the length field of the hidden sub-format */    old_hdr->attr = htons (len - sizeof (struct avp_hdr));    /* Okay, now we've rewritten the header, as it should be.  Let's start       encrypting the actual data now */    buf->len -= len;    buf->len += length;    /* Back to the beginning of real data, including the original length AVP */    MD5Init (&t->chal_them.md5);    MD5Update (&t->chal_them.md5, (void *) &attr, 2);    MD5Update (&t->chal_them.md5, t->chal_them.secret,               strlen (t->chal_them.secret));    MD5Update (&t->chal_them.md5, t->chal_them.vector, VECTOR_SIZE);    MD5Final (digest, &t->chal_them.md5);    /* Though not a "MUST" in the spec, our subformat length is always a multiple of 16 */    ptr = ((char *) new_hdr) + sizeof (struct avp_hdr);    end = ((char *) new_hdr) + length;    previous_segment = ptr;    while (ptr < end)    {#if DEBUG_HIDDEN        log (LOG_DEBUG, "%s: The digest to be XOR'ed\n", __FUNCTION__);        bufferDump (digest, MD_SIG_SIZE);        log (LOG_DEBUG, "%s: The plaintext to be XOR'ed\n", __FUNCTION__);        bufferDump (ptr, MD_SIG_SIZE);#endif        for (cnt = 0; cnt < MD_SIG_SIZE; cnt++, ptr++)        {            *ptr = *ptr ^ digest[cnt];        }#if DEBUG_HIDDEN        log (LOG_DEBUG, "%s: The result of XOR\n", __FUNCTION__);        bufferDump (previous_segment, MD_SIG_SIZE);#endif        if (ptr < end)        {            MD5Init (&t->chal_them.md5);            MD5Update (&t->chal_them.md5, t->chal_them.secret,                       strlen (t->chal_them.secret));            MD5Update (&t->chal_them.md5, previous_segment, MD_SIG_SIZE);            MD5Final (digest, &t->chal_them.md5);        }        previous_segment = ptr;    }}int decrypt_avp (char *buf, struct tunnel *t){    /* Decrypts a hidden AVP pointed to by buf.  The       new header will be exptected to be two characters       offset from the old */    int cnt = 0;    int len, olen, flags;    char digest[MD_SIG_SIZE];    char *ptr, *end;    _u16 attr;    struct avp_hdr *old_hdr = (struct avp_hdr *) buf;    struct avp_hdr *new_hdr = (struct avp_hdr *) (buf + 2);    int saved_segment_len;      /* maybe less 16; may be used if the cipher is longer than 16 octets */    char saved_segment[MD_SIG_SIZE];    ptr = ((char *) old_hdr) + sizeof (struct avp_hdr);    olen = old_hdr->length & 0x0FFF;    end = buf + olen;    if (!t->chal_us.vector)    {        log (LOG_DEBUG,             "decrypt_avp: Hidden bit set, but no random vector specified!\n");        return -EINVAL;    }    /* First, let's decrypt all the data.  We're not guaranteed       that it will be padded to a 16 byte boundary, so we       have to be more careful than when encrypting */    attr = ntohs (old_hdr->attr);    MD5Init (&t->chal_us.md5);    MD5Update (&t->chal_us.md5, (void *) &attr, 2);    MD5Update (&t->chal_us.md5, t->chal_us.secret,               strlen (t->chal_us.secret));    MD5Update (&t->chal_us.md5, t->chal_us.vector, t->chal_us.vector_len);    MD5Final (digest, &t->chal_us.md5);#ifdef DEBUG_HIDDEN    log (LOG_DEBUG, "attribute is %d and challenge is: ", attr);    print_challenge (&t->chal_us);    log (LOG_DEBUG, "md5 is: ");    print_md5 (digest);#endif    while (ptr < end)    {        if (cnt >= MD_SIG_SIZE)        {            MD5Init (&t->chal_us.md5);            MD5Update (&t->chal_us.md5, t->chal_us.secret,                       strlen (t->chal_us.secret));            MD5Update (&t->chal_us.md5, saved_segment, MD_SIG_SIZE);            MD5Final (digest, &t->chal_us.md5);            cnt = 0;        }        /* at the beginning of each segment, we save the current segment (16 octets or less) of cipher          * so that the next round of MD5 (if there is a next round) hash could use it          */        if (cnt == 0)        {            saved_segment_len =                (end - ptr < MD_SIG_SIZE) ? (end - ptr) : MD_SIG_SIZE;            memcpy (saved_segment, ptr, saved_segment_len);        }        *ptr = *ptr ^ digest[cnt++];        ptr++;    }    /* Hopefully we're all nice and decrypted now.  Let's rewrite the header.        First save the old flags, and get the new stuff */    flags = old_hdr->length & 0xF000 & ~HBIT;    len = ntohs (new_hdr->attr) + sizeof (struct avp_hdr);    if (len > olen - 2)    {        log (LOG_DEBUG,             "decrypt_avp: Decrypted length is too long (%d > %d)\n", len,             olen - 2);        return -EINVAL;    }    new_hdr->attr = old_hdr->attr;    new_hdr->vendorid = old_hdr->vendorid;    new_hdr->length = len | flags;    return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -