Annotation of embedaddon/strongswan/src/libradius/radius_message.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  * Copyright (C) 2009 Martin Willi
                      3:  * HSR Hochschule fuer Technik Rapperswil
                      4:  *
                      5:  * This program is free software; you can redistribute it and/or modify it
                      6:  * under the terms of the GNU General Public License as published by the
                      7:  * Free Software Foundation; either version 2 of the License, or (at your
                      8:  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
                      9:  *
                     10:  * This program is distributed in the hope that it will be useful, but
                     11:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
                     12:  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
                     13:  * for more details.
                     14:  */
                     15: 
                     16: #include "radius_message.h"
                     17: 
                     18: #include <utils/debug.h>
                     19: #include <bio/bio_reader.h>
                     20: #include <crypto/hashers/hasher.h>
                     21: 
                     22: typedef struct private_radius_message_t private_radius_message_t;
                     23: typedef struct rmsg_t rmsg_t;
                     24: typedef struct rattr_t rattr_t;
                     25: 
                     26: /**
                     27:  * RADIUS message header
                     28:  */
                     29: struct rmsg_t {
                     30:        /** message code, radius_message_code_t */
                     31:        uint8_t code;
                     32:        /** message identifier */
                     33:        uint8_t identifier;
                     34:        /** length of Code, Identifier, Length, Authenticator and Attributes */
                     35:        uint16_t length;
                     36:        /** message authenticator, MD5 hash */
                     37:        uint8_t authenticator[HASH_SIZE_MD5];
                     38:        /** variable list of packed attributes */
                     39:        uint8_t attributes[];
                     40: } __attribute__((packed));
                     41: 
                     42: /**
                     43:  * RADIUS message attribute.
                     44:  */
                     45: struct rattr_t {
                     46:        /** attribute type, radius_attribute_type_t */
                     47:        uint8_t type;
                     48:        /** length of the attribute, including the Type, Length and Value fields */
                     49:        uint8_t length;
                     50:        /** variable length attribute value */
                     51:        uint8_t value[];
                     52: } __attribute__((packed));
                     53: 
                     54: /**
                     55:  * Private data of an radius_message_t object.
                     56:  */
                     57: struct private_radius_message_t {
                     58: 
                     59:        /**
                     60:         * Public radius_message_t interface.
                     61:         */
                     62:        radius_message_t public;
                     63: 
                     64:        /**
                     65:         * message data, allocated
                     66:         */
                     67:        rmsg_t *msg;
                     68: 
                     69:        /**
                     70:         * User-Password to encrypt and encode, if any
                     71:         */
                     72:        chunk_t password;
                     73: };
                     74: 
                     75: /**
                     76:  * Described in header.
                     77:  */
                     78: void libradius_init(void)
                     79: {
                     80:        /* empty */
                     81: }
                     82: 
                     83: ENUM_BEGIN(radius_message_code_names, RMC_ACCESS_REQUEST, RMC_ACCOUNTING_RESPONSE,
                     84:        "Access-Request",
                     85:        "Access-Accept",
                     86:        "Access-Reject",
                     87:        "Accounting-Request",
                     88:        "Accounting-Response");
                     89: ENUM_NEXT(radius_message_code_names, RMC_ACCESS_CHALLENGE, RMC_ACCESS_CHALLENGE, RMC_ACCOUNTING_RESPONSE,
                     90:        "Access-Challenge");
                     91: ENUM_NEXT(radius_message_code_names, RMC_DISCONNECT_REQUEST, RMC_COA_NAK, RMC_ACCESS_CHALLENGE,
                     92:        "Disconnect-Request",
                     93:        "Disconnect-ACK",
                     94:        "Disconnect-NAK",
                     95:        "CoA-Request",
                     96:        "CoA-ACK",
                     97:        "CoA-NAK");
                     98: ENUM_END(radius_message_code_names, RMC_COA_NAK);
                     99: 
                    100: ENUM_BEGIN(radius_attribute_type_names, RAT_USER_NAME, RAT_MIP6_HOME_LINK_PREFIX,
                    101:        "User-Name",
                    102:        "User-Password",
                    103:        "CHAP-Password",
                    104:        "NAS-IP-Address",
                    105:        "NAS-Port",
                    106:        "Service-Type",
                    107:        "Framed-Protocol",
                    108:        "Framed-IP-Address",
                    109:        "Framed-IP-Netmask",
                    110:        "Framed-Routing",
                    111:        "Filter-Id",
                    112:        "Framed-MTU",
                    113:        "Framed-Compression",
                    114:        "Login-IP-Host",
                    115:        "Login-Service",
                    116:        "Login-TCP-Port",
                    117:        "Unassigned",
                    118:        "Reply-Message",
                    119:        "Callback-Number",
                    120:        "Callback-Id",
                    121:        "Unassigned",
                    122:        "Framed-Route",
                    123:        "Framed-IPX-Network",
                    124:        "State",
                    125:        "Class",
                    126:        "Vendor-Specific",
                    127:        "Session-Timeout",
                    128:        "Idle-Timeout",
                    129:        "Termination-Action",
                    130:        "Called-Station-Id",
                    131:        "Calling-Station-Id",
                    132:        "NAS-Identifier",
                    133:        "Proxy-State",
                    134:        "Login-LAT-Service",
                    135:        "Login-LAT-Node",
                    136:        "Login-LAT-Group",
                    137:        "Framed-AppleTalk-Link",
                    138:        "Framed-AppleTalk-Network",
                    139:        "Framed-AppleTalk-Zone",
                    140:        "Acct-Status-Type",
                    141:        "Acct-Delay-Time",
                    142:        "Acct-Input-Octets",
                    143:        "Acct-Output-Octets",
                    144:        "Acct-Session-Id",
                    145:        "Acct-Authentic",
                    146:        "Acct-Session-Time",
                    147:        "Acct-Input-Packets",
                    148:        "Acct-Output-Packets",
                    149:        "Acct-Terminate-Cause",
                    150:        "Acct-Multi-Session-Id",
                    151:        "Acct-Link-Count",
                    152:        "Acct-Input-Gigawords",
                    153:        "Acct-Output-Gigawords",
                    154:        "Unassigned",
                    155:        "Event-Timestamp",
                    156:        "Egress-VLANID",
                    157:        "Ingress-Filters",
                    158:        "Egress-VLAN-Name",
                    159:        "User-Priority-Table",
                    160:        "CHAP-Challenge",
                    161:        "NAS-Port-Type",
                    162:        "Port-Limit",
                    163:        "Login-LAT-Port",
                    164:        "Tunnel-Type",
                    165:        "Tunnel-Medium-Type",
                    166:        "Tunnel-Client-Endpoint",
                    167:        "Tunnel-Server-Endpoint",
                    168:        "Acct-Tunnel-Connection",
                    169:        "Tunnel-Password",
                    170:        "ARAP-Password",
                    171:        "ARAP-Features",
                    172:        "ARAP-Zone-Access",
                    173:        "ARAP-Security",
                    174:        "ARAP-Security-Data",
                    175:        "Password-Retry",
                    176:        "Prompt",
                    177:        "Connect-Info",
                    178:        "Configuration-Token",
                    179:        "EAP-Message",
                    180:        "Message-Authenticator",
                    181:        "Tunnel-Private-Group-ID",
                    182:        "Tunnel-Assignment-ID",
                    183:        "Tunnel-Preference",
                    184:        "ARAP-Challenge-Response",
                    185:        "Acct-Interim-Interval",
                    186:        "Acct-Tunnel-Packets-Lost",
                    187:        "NAS-Port-Id",
                    188:        "Framed-Pool",
                    189:        "CUI",
                    190:        "Tunnel-Client-Auth-ID",
                    191:        "Tunnel-Server-Auth-ID",
                    192:        "NAS-Filter-Rule",
                    193:        "Unassigned",
                    194:        "Originating-Line-Info",
                    195:        "NAS-IPv6-Address",
                    196:        "Framed-Interface-Id",
                    197:        "Framed-IPv6-Prefix",
                    198:        "Login-IPv6-Host",
                    199:        "Framed-IPv6-Route",
                    200:        "Framed-IPv6-Pool",
                    201:        "Error-Cause",
                    202:        "EAP-Key-Name",
                    203:        "Digest-Response",
                    204:        "Digest-Realm",
                    205:        "Digest-Nonce",
                    206:        "Digest-Response-Auth",
                    207:        "Digest-Nextnonce",
                    208:        "Digest-Method",
                    209:        "Digest-URI",
                    210:        "Digest-Qop",
                    211:        "Digest-Algorithm",
                    212:        "Digest-Entity-Body-Hash",
                    213:        "Digest-CNonce",
                    214:        "Digest-Nonce-Count",
                    215:        "Digest-Username",
                    216:        "Digest-Opaque",
                    217:        "Digest-Auth-Param",
                    218:        "Digest-AKA-Auts",
                    219:        "Digest-Domain",
                    220:        "Digest-Stale",
                    221:        "Digest-HA1",
                    222:        "SIP-AOR",
                    223:        "Delegated-IPv6-Prefix",
                    224:        "MIP6-Feature-Vector",
                    225:        "MIP6-Home-Link-Prefix");
                    226: ENUM_NEXT(radius_attribute_type_names, RAT_FRAMED_IPV6_ADDRESS, RAT_STATEFUL_IPV6_ADDRESS_POOL, RAT_MIP6_HOME_LINK_PREFIX,
                    227:        "Framed-IPv6-Address",
                    228:        "DNS-Server-IPv6-Address",
                    229:        "Route-IPv6-Information",
                    230:        "Delegated-IPv6-Prefix-Pool",
                    231:        "Stateful-IPv6-Address-Pool");
                    232: ENUM_END(radius_attribute_type_names, RAT_STATEFUL_IPV6_ADDRESS_POOL);
                    233: 
                    234: /**
                    235:  * Attribute enumerator implementation
                    236:  */
                    237: typedef struct {
                    238:        /** implements enumerator interface */
                    239:        enumerator_t public;
                    240:        /** currently pointing attribute */
                    241:        rattr_t *next;
                    242:        /** bytes left */
                    243:        int left;
                    244: } attribute_enumerator_t;
                    245: 
                    246: METHOD(enumerator_t, attribute_enumerate, bool,
                    247:        attribute_enumerator_t *this, va_list args)
                    248: {
                    249:        chunk_t *data;
                    250:        int *type;
                    251: 
                    252:        VA_ARGS_VGET(args, type, data);
                    253:        if (this->left == 0)
                    254:        {
                    255:                return FALSE;
                    256:        }
                    257:        if (this->left < sizeof(rattr_t) ||
                    258:                this->left < this->next->length)
                    259:        {
                    260:                DBG1(DBG_IKE, "RADIUS message truncated");
                    261:                return FALSE;
                    262:        }
                    263:        *type = this->next->type;
                    264:        data->ptr = this->next->value;
                    265:        data->len = this->next->length - sizeof(rattr_t);
                    266:        this->left -= this->next->length;
                    267:        this->next = ((void*)this->next) + this->next->length;
                    268:        return TRUE;
                    269: }
                    270: 
                    271: METHOD(radius_message_t, create_enumerator, enumerator_t*,
                    272:        private_radius_message_t *this)
                    273: {
                    274:        attribute_enumerator_t *e;
                    275: 
                    276:        if (ntohs(this->msg->length) < sizeof(rmsg_t) + sizeof(rattr_t))
                    277:        {
                    278:                return enumerator_create_empty();
                    279:        }
                    280:        INIT(e,
                    281:                .public = {
                    282:                        .enumerate = enumerator_enumerate_default,
                    283:                        .venumerate = _attribute_enumerate,
                    284:                        .destroy = (void*)free,
                    285:                },
                    286:                .next = (rattr_t*)this->msg->attributes,
                    287:                .left = ntohs(this->msg->length) - sizeof(rmsg_t),
                    288:        );
                    289:        return &e->public;
                    290: }
                    291: 
                    292: /**
                    293:  * Vendor attribute enumerator implementation
                    294:  */
                    295: typedef struct {
                    296:        /** implements enumerator interface */
                    297:        enumerator_t public;
                    298:        /** inner attribute enumerator */
                    299:        enumerator_t *inner;
                    300:        /** current vendor ID */
                    301:        uint32_t vendor;
                    302:        /** reader for current vendor ID */
                    303:        bio_reader_t *reader;
                    304: } vendor_enumerator_t;
                    305: 
                    306: METHOD(enumerator_t, vendor_enumerate, bool,
                    307:        vendor_enumerator_t *this, va_list args)
                    308: {
                    309:        chunk_t inner_data, *data;
                    310:        int inner_type, *vendor, *type;
                    311:        uint8_t type8, len;
                    312: 
                    313:        VA_ARGS_VGET(args, vendor, type, data);
                    314: 
                    315:        while (TRUE)
                    316:        {
                    317:                if (this->reader)
                    318:                {
                    319:                        if (this->reader->remaining(this->reader) >= 2 &&
                    320:                                this->reader->read_uint8(this->reader, &type8) &&
                    321:                                this->reader->read_uint8(this->reader, &len) && len >= 2 &&
                    322:                                this->reader->read_data(this->reader, len - 2, data))
                    323:                        {
                    324:                                *vendor = this->vendor;
                    325:                                *type = type8;
                    326:                                return TRUE;
                    327:                        }
                    328:                        this->reader->destroy(this->reader);
                    329:                        this->reader = NULL;
                    330:                }
                    331:                if (this->inner->enumerate(this->inner, &inner_type, &inner_data))
                    332:                {
                    333:                        if (inner_type == RAT_VENDOR_SPECIFIC)
                    334:                        {
                    335:                                this->reader = bio_reader_create(inner_data);
                    336:                                if (!this->reader->read_uint32(this->reader, &this->vendor))
                    337:                                {
                    338:                                        this->reader->destroy(this->reader);
                    339:                                        this->reader = NULL;
                    340:                                }
                    341:                        }
                    342:                }
                    343:                else
                    344:                {
                    345:                        return FALSE;
                    346:                }
                    347:        }
                    348: }
                    349: METHOD(enumerator_t, vendor_destroy, void,
                    350:        vendor_enumerator_t *this)
                    351: {
                    352:        DESTROY_IF(this->reader);
                    353:        this->inner->destroy(this->inner);
                    354:        free(this);
                    355: }
                    356: 
                    357: METHOD(radius_message_t, create_vendor_enumerator, enumerator_t*,
                    358:        private_radius_message_t *this)
                    359: {
                    360:        vendor_enumerator_t *e;
                    361: 
                    362:        INIT(e,
                    363:                .public = {
                    364:                        .enumerate = enumerator_enumerate_default,
                    365:                        .venumerate = _vendor_enumerate,
                    366:                        .destroy = _vendor_destroy,
                    367:                },
                    368:                .inner = create_enumerator(this),
                    369:        );
                    370: 
                    371:        return &e->public;
                    372: }
                    373: 
                    374: METHOD(radius_message_t, add, void,
                    375:        private_radius_message_t *this, radius_attribute_type_t type, chunk_t data)
                    376: {
                    377:        rattr_t *attribute;
                    378: 
                    379:        if (type == RAT_USER_PASSWORD && !this->password.len)
                    380:        {
                    381:                /* store a null-padded password */
                    382:                this->password = chunk_alloc(round_up(data.len, HASH_SIZE_MD5));
                    383:                memset(this->password.ptr + data.len, 0, this->password.len - data.len);
                    384:                memcpy(this->password.ptr, data.ptr, data.len);
                    385:                return;
                    386:        }
                    387: 
                    388:        data.len = min(data.len, MAX_RADIUS_ATTRIBUTE_SIZE);
                    389:        this->msg = realloc(this->msg,
                    390:                                                ntohs(this->msg->length) + sizeof(rattr_t) + data.len);
                    391:        attribute = ((void*)this->msg) + ntohs(this->msg->length);
                    392:        attribute->type = type;
                    393:        attribute->length = data.len + sizeof(rattr_t);
                    394:        memcpy(attribute->value, data.ptr, data.len);
                    395:        this->msg->length = htons(ntohs(this->msg->length) + attribute->length);
                    396: }
                    397: 
                    398: METHOD(radius_message_t, crypt, bool,
                    399:        private_radius_message_t *this, chunk_t salt, chunk_t in, chunk_t out,
                    400:        chunk_t secret, hasher_t *hasher)
                    401: {
                    402:        char b[HASH_SIZE_MD5];
                    403: 
                    404:        /**
                    405:         * From RFC2548 (encryption):
                    406:         * b(1) = MD5(S + R + A)    c(1) = p(1) xor b(1)   C = c(1)
                    407:         * b(2) = MD5(S + c(1))     c(2) = p(2) xor b(2)   C = C + c(2)
                    408:         *      . . .
                    409:         * b(i) = MD5(S + c(i-1))   c(i) = p(i) xor b(i)   C = C + c(i)
                    410:         *
                    411:         * P/C = Plain/Crypted => in/out
                    412:         * S = secret
                    413:         * R = authenticator
                    414:         * A = salt
                    415:         */
                    416:        if (in.len != out.len)
                    417:        {
                    418:                return FALSE;
                    419:        }
                    420:        if (in.len % HASH_SIZE_MD5 || in.len < HASH_SIZE_MD5)
                    421:        {
                    422:                return FALSE;
                    423:        }
                    424:        if (out.ptr != in.ptr)
                    425:        {
                    426:                memcpy(out.ptr, in.ptr, in.len);
                    427:        }
                    428:        /* Preparse seed for first round:
                    429:         * b(1) = MD5(S + R + A) */
                    430:        if (!hasher->get_hash(hasher, secret, NULL) ||
                    431:                !hasher->get_hash(hasher,
                    432:                                                  chunk_from_thing(this->msg->authenticator), NULL) ||
                    433:                !hasher->get_hash(hasher, salt, b))
                    434:        {
                    435:                return FALSE;
                    436:        }
                    437:        while (in.len)
                    438:        {
                    439:                /* p(i) = b(i) xor c(1) */
                    440:                memxor(out.ptr, b, HASH_SIZE_MD5);
                    441: 
                    442:                out = chunk_skip(out, HASH_SIZE_MD5);
                    443:                if (out.len)
                    444:                {
                    445:                        /* Prepare seed for next round::
                    446:                         * b(i) = MD5(S + c(i-1)) */
                    447:                        if (!hasher->get_hash(hasher, secret, NULL) ||
                    448:                                !hasher->get_hash(hasher,
                    449:                                                                  chunk_create(in.ptr, HASH_SIZE_MD5), b))
                    450:                        {
                    451:                                return FALSE;
                    452:                        }
                    453:                }
                    454:                in = chunk_skip(in, HASH_SIZE_MD5);
                    455:        }
                    456:        return TRUE;
                    457: }
                    458: 
                    459: METHOD(radius_message_t, sign, bool,
                    460:        private_radius_message_t *this, uint8_t *req_auth, chunk_t secret,
                    461:        hasher_t *hasher, signer_t *signer, rng_t *rng, bool msg_auth)
                    462: {
                    463:        if (rng)
                    464:        {
                    465:                /* build Request-Authenticator */
                    466:                if (!rng->get_bytes(rng, HASH_SIZE_MD5, this->msg->authenticator))
                    467:                {
                    468:                        return FALSE;
                    469:                }
                    470:        }
                    471:        else
                    472:        {
                    473:                /* prepare build of Response-Authenticator */
                    474:                if (req_auth)
                    475:                {
                    476:                        memcpy(this->msg->authenticator, req_auth, HASH_SIZE_MD5);
                    477:                }
                    478:                else
                    479:                {
                    480:                        memset(this->msg->authenticator, 0, sizeof(this->msg->authenticator));
                    481:                }
                    482:        }
                    483: 
                    484:        if (this->password.len)
                    485:        {
                    486:                /* encrypt password inline */
                    487:                if (!crypt(this, chunk_empty, this->password, this->password,
                    488:                                   secret, hasher))
                    489:                {
                    490:                        return FALSE;
                    491:                }
                    492:                add(this, RAT_USER_PASSWORD, this->password);
                    493:                chunk_clear(&this->password);
                    494:        }
                    495: 
                    496:        if (msg_auth)
                    497:        {
                    498:                char buf[HASH_SIZE_MD5];
                    499: 
                    500:                /* build Message-Authenticator attribute, using 16 null bytes */
                    501:                memset(buf, 0, sizeof(buf));
                    502:                add(this, RAT_MESSAGE_AUTHENTICATOR, chunk_create(buf, sizeof(buf)));
                    503:                if (!signer->get_signature(signer,
                    504:                                chunk_create((u_char*)this->msg, ntohs(this->msg->length)),
                    505:                                ((u_char*)this->msg) + ntohs(this->msg->length) - HASH_SIZE_MD5))
                    506:                {
                    507:                        return FALSE;
                    508:                }
                    509:        }
                    510: 
                    511:        if (!rng)
                    512:        {
                    513:                chunk_t msg;
                    514: 
                    515:                /* build Response-Authenticator */
                    516:                msg = chunk_create((u_char*)this->msg, ntohs(this->msg->length));
                    517:                if (!hasher->get_hash(hasher, msg, NULL) ||
                    518:                        !hasher->get_hash(hasher, secret, this->msg->authenticator))
                    519:                {
                    520:                        return FALSE;
                    521:                }
                    522:        }
                    523:        return TRUE;
                    524: }
                    525: 
                    526: METHOD(radius_message_t, verify, bool,
                    527:        private_radius_message_t *this, uint8_t *req_auth, chunk_t secret,
                    528:        hasher_t *hasher, signer_t *signer)
                    529: {
                    530:        char buf[HASH_SIZE_MD5], res_auth[HASH_SIZE_MD5];
                    531:        enumerator_t *enumerator;
                    532:        int type;
                    533:        chunk_t data, msg;
                    534:        bool has_eap = FALSE, has_auth = FALSE;
                    535: 
                    536:        msg = chunk_create((u_char*)this->msg, ntohs(this->msg->length));
                    537: 
                    538:        if (this->msg->code != RMC_ACCESS_REQUEST)
                    539:        {
                    540:                /* replace Response by Request Authenticator for verification */
                    541:                memcpy(res_auth, this->msg->authenticator, HASH_SIZE_MD5);
                    542:                if (req_auth)
                    543:                {
                    544:                        memcpy(this->msg->authenticator, req_auth, HASH_SIZE_MD5);
                    545:                }
                    546:                else
                    547:                {
                    548:                        memset(this->msg->authenticator, 0, HASH_SIZE_MD5);
                    549:                }
                    550: 
                    551:                /* verify Response-Authenticator */
                    552:                if (!hasher->get_hash(hasher, msg, NULL) ||
                    553:                        !hasher->get_hash(hasher, secret, buf) ||
                    554:                        !memeq_const(buf, res_auth, HASH_SIZE_MD5))
                    555:                {
                    556:                        DBG1(DBG_CFG, "RADIUS Response-Authenticator verification failed");
                    557:                        return FALSE;
                    558:                }
                    559:        }
                    560: 
                    561:        /* verify Message-Authenticator attribute */
                    562:        enumerator = create_enumerator(this);
                    563:        while (enumerator->enumerate(enumerator, &type, &data))
                    564:        {
                    565:                if (type == RAT_MESSAGE_AUTHENTICATOR)
                    566:                {
                    567:                        if (data.len != HASH_SIZE_MD5)
                    568:                        {
                    569:                                DBG1(DBG_CFG, "RADIUS Message-Authenticator invalid length");
                    570:                                enumerator->destroy(enumerator);
                    571:                                return FALSE;
                    572:                        }
                    573:                        memcpy(buf, data.ptr, data.len);
                    574:                        memset(data.ptr, 0, data.len);
                    575:                        if (signer->verify_signature(signer, msg,
                    576:                                                                                 chunk_create(buf, sizeof(buf))))
                    577:                        {
                    578:                                /* restore Message-Authenticator */
                    579:                                memcpy(data.ptr, buf, data.len);
                    580:                                has_auth = TRUE;
                    581:                                break;
                    582:                        }
                    583:                        else
                    584:                        {
                    585:                                DBG1(DBG_CFG, "RADIUS Message-Authenticator verification failed");
                    586:                                enumerator->destroy(enumerator);
                    587:                                return FALSE;
                    588:                        }
                    589:                }
                    590:                else if (type == RAT_EAP_MESSAGE)
                    591:                {
                    592:                        has_eap = TRUE;
                    593:                }
                    594:        }
                    595:        enumerator->destroy(enumerator);
                    596: 
                    597:        if (this->msg->code != RMC_ACCESS_REQUEST)
                    598:        {
                    599:                /* restore Response-Authenticator */
                    600:                memcpy(this->msg->authenticator, res_auth, HASH_SIZE_MD5);
                    601:        }
                    602: 
                    603:        if (has_eap && !has_auth)
                    604:        {       /* Message-Authenticator is required if we have an EAP-Message */
                    605:                DBG1(DBG_CFG, "RADIUS Message-Authenticator attribute missing");
                    606:                return FALSE;
                    607:        }
                    608:        return TRUE;
                    609: }
                    610: 
                    611: METHOD(radius_message_t, get_code, radius_message_code_t,
                    612:        private_radius_message_t *this)
                    613: {
                    614:        return this->msg->code;
                    615: }
                    616: 
                    617: METHOD(radius_message_t, get_identifier, uint8_t,
                    618:        private_radius_message_t *this)
                    619: {
                    620:        return this->msg->identifier;
                    621: }
                    622: 
                    623: METHOD(radius_message_t, set_identifier, void,
                    624:        private_radius_message_t *this, uint8_t identifier)
                    625: {
                    626:        this->msg->identifier = identifier;
                    627: }
                    628: 
                    629: METHOD(radius_message_t, get_authenticator, uint8_t*,
                    630:        private_radius_message_t *this)
                    631: {
                    632:        return this->msg->authenticator;
                    633: }
                    634: 
                    635: 
                    636: METHOD(radius_message_t, get_encoding, chunk_t,
                    637:        private_radius_message_t *this)
                    638: {
                    639:        return chunk_create((u_char*)this->msg, ntohs(this->msg->length));
                    640: }
                    641: 
                    642: METHOD(radius_message_t, destroy, void,
                    643:        private_radius_message_t *this)
                    644: {
                    645:        chunk_clear(&this->password);
                    646:        free(this->msg);
                    647:        free(this);
                    648: }
                    649: 
                    650: /**
                    651:  * Generic constructor
                    652:  */
                    653: static private_radius_message_t *radius_message_create_empty()
                    654: {
                    655:        private_radius_message_t *this;
                    656: 
                    657:        INIT(this,
                    658:                .public = {
                    659:                        .create_enumerator = _create_enumerator,
                    660:                        .create_vendor_enumerator = _create_vendor_enumerator,
                    661:                        .add = _add,
                    662:                        .get_code = _get_code,
                    663:                        .get_identifier = _get_identifier,
                    664:                        .set_identifier = _set_identifier,
                    665:                        .get_authenticator = _get_authenticator,
                    666:                        .get_encoding = _get_encoding,
                    667:                        .sign = _sign,
                    668:                        .verify = _verify,
                    669:                        .crypt = _crypt,
                    670:                        .destroy = _destroy,
                    671:                },
                    672:        );
                    673: 
                    674:        return this;
                    675: }
                    676: 
                    677: /**
                    678:  * See header
                    679:  */
                    680: radius_message_t *radius_message_create(radius_message_code_t code)
                    681: {
                    682:        private_radius_message_t *this = radius_message_create_empty();
                    683: 
                    684:        INIT(this->msg,
                    685:                .code = code,
                    686:                .identifier = 0,
                    687:                .length = htons(sizeof(rmsg_t)),
                    688:        );
                    689: 
                    690:        return &this->public;
                    691: }
                    692: 
                    693: /**
                    694:  * See header
                    695:  */
                    696: radius_message_t *radius_message_parse(chunk_t data)
                    697: {
                    698:        private_radius_message_t *this = radius_message_create_empty();
                    699: 
                    700:        this->msg = malloc(data.len);
                    701:        memcpy(this->msg, data.ptr, data.len);
                    702:        if (data.len < sizeof(rmsg_t) ||
                    703:                ntohs(this->msg->length) != data.len)
                    704:        {
                    705:                DBG1(DBG_IKE, "RADIUS message has invalid length");
                    706:                destroy(this);
                    707:                return NULL;
                    708:        }
                    709:        return &this->public;
                    710: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>