added some functions to handle extended attributes in radmsg.c

This commit is contained in:
hyung-hwan 2021-08-12 16:18:15 +00:00
parent 94e4cb6d4f
commit 5baf471e07
3 changed files with 478 additions and 167 deletions

View File

@ -57,14 +57,19 @@ typedef enum qse_rad_code_t qse_rad_code_t;
#define QSE_RAD_MAX_AUTHENTICATOR_LEN 16 #define QSE_RAD_MAX_AUTHENTICATOR_LEN 16
#define QSE_RAD_MAX_ATTR_VALUE_LEN (QSE_TYPE_MAX(qse_uint8_t) - QSE_SIZEOF(qse_rad_attr_hdr_t)) #define QSE_RAD_MAX_ATTR_VALUE_LEN (QSE_TYPE_MAX(qse_uint8_t) - QSE_SIZEOF(qse_rad_attr_hdr_t))
#define QSE_RAD_MAX_VSATTR_VALUE_LEN (QSE_TYPE_MAX(qse_uint8_t) - QSE_SIZEOF(qse_rad_attr_hdr_t) - QSE_SIZEOF(qse_rad_vsattr_hdr_t)) #define QSE_RAD_MAX_XATTR_VALUE_LEN (QSE_TYPE_MAX(qse_uint8_t) - QSE_SIZEOF(qse_rad_xattr_hdr_t))
#define QSE_RAD_MAX_EXTVSATTR_VALUE_LEN (QSE_TYPE_MAX(qse_uint8_t) - QSE_SIZEOF(qse_rad_extvsattr_hdr_t)) #define QSE_RAD_MAX_LXATTR_VALUE_LEN (QSE_TYPE_MAX(qse_uint8_t) - QSE_SIZEOF(qse_rad_lxattr_hdr_t))
#define QSE_RAD_MAX_VSATTR_VALUE_LEN (QSE_TYPE_MAX(qse_uint8_t) - QSE_SIZEOF(qse_rad_vsattr_hdr_t))
#define QSE_RAD_MAX_XVSATTR_VALUE_LEN (QSE_TYPE_MAX(qse_uint8_t) - QSE_SIZEOF(qse_rad_xvsattr_hdr_t))
#define QSE_RAD_MAX_LXVSATTR_VALUE_LEN (QSE_TYPE_MAX(qse_uint8_t) - QSE_SIZEOF(qse_rad_lxvsattr_hdr_t))
typedef struct qse_rad_hdr_t qse_rad_hdr_t; typedef struct qse_rad_hdr_t qse_rad_hdr_t;
typedef struct qse_rad_attr_hdr_t qse_rad_attr_hdr_t; typedef struct qse_rad_attr_hdr_t qse_rad_attr_hdr_t;
typedef struct qse_rad_xattr_hdr_t qse_rad_xattr_hdr_t;
typedef struct qse_rad_lxattr_hdr_t qse_rad_lxattr_hdr_t;
typedef struct qse_rad_vsattr_hdr_t qse_rad_vsattr_hdr_t; typedef struct qse_rad_vsattr_hdr_t qse_rad_vsattr_hdr_t;
typedef struct qse_rad_extvsattr_hdr_t qse_rad_extvsattr_hdr_t; /* evs */ typedef struct qse_rad_xvsattr_hdr_t qse_rad_xvsattr_hdr_t;
typedef struct qse_rad_lxvsattr_hdr_t qse_rad_lxvsattr_hdr_t; /* evs */
typedef struct qse_rad_attr_uint32_t qse_rad_attr_uint32_t; typedef struct qse_rad_attr_uint32_t qse_rad_attr_uint32_t;
#if (QSE_SIZEOF_UINT64_T > 0) #if (QSE_SIZEOF_UINT64_T > 0)
@ -82,24 +87,61 @@ struct qse_rad_hdr_t
struct qse_rad_attr_hdr_t struct qse_rad_attr_hdr_t
{ {
qse_uint8_t id; /* qse_rad_attr_id_t */ qse_uint8_t type; /* qse_rad_attr_type_t */
qse_uint8_t length; qse_uint8_t length;
}; };
struct qse_rad_xattr_hdr_t
{
qse_uint8_t type; /* qse_rad_attr_type_t - one of 241-244 */
qse_uint8_t length;
qse_uint8_t xtype; /* extended type */
};
struct qse_rad_lxattr_hdr_t
{
qse_uint8_t type; /* qse_rad_attr_type_t - 245 or 256*/
qse_uint8_t length;
qse_uint8_t xtype; /* extended type */
qse_uint8_t xflags; /* bit 7: continuation, bit 6-0: reserved. */
};
struct qse_rad_vsattr_hdr_t struct qse_rad_vsattr_hdr_t
{ {
qse_uint8_t id; /* type */ qse_uint8_t type; /* type - 26 */
qse_uint8_t length; /* length */ qse_uint8_t length; /* length */
qse_uint32_t vendor; /* in network-byte order */ qse_uint32_t vendor; /* in network-byte order */
/* followed by a standard attribute */
qse_rad_attr_hdr_t vs;
}; };
struct qse_rad_extvsattr_hdr_t struct qse_rad_xvsattr_hdr_t
{ {
qse_uint8_t id; /* one of 241-244 */ qse_uint8_t type; /* one of 241-244 */
qse_uint8_t length; qse_uint8_t length;
qse_uint8_t xid; /* extended type. 26 for evs */ qse_uint8_t xtype; /* extended type. 26 for evs(extended vendor specific) attribute */
qse_uint32_t vendor; /* in network-byte order */ qse_uint32_t vendor; /* in network-byte order */
qse_uint8_t evsid;
/* followed by a standard attribute */
qse_rad_attr_hdr_t xvs;
};
struct qse_rad_lxvsattr_hdr_t
{
qse_uint8_t type; /* 245, 246*/
qse_uint8_t length;
qse_uint8_t xtype; /* extended type. 26 for evs(extended vendor specific) attribute */
qse_uint32_t vendor; /* in network-byte order */
/* followed by an extended attribute */
struct
{
qse_uint8_t type;
qse_uint8_t flags; /* bit 7: continuation, bit 6-0: reserved. */
qse_uint8_t length;
} lxvs;
}; };
struct qse_rad_attr_uint32_t struct qse_rad_attr_uint32_t
@ -126,7 +168,7 @@ typedef int (*qse_rad_attr_walker_t) (
void* ctx void* ctx
); );
enum qse_rad_attr_id_t enum qse_rad_attr_type_t
{ {
QSE_RAD_ATTR_USER_NAME = 1, /* string */ QSE_RAD_ATTR_USER_NAME = 1, /* string */
QSE_RAD_ATTR_USER_PASSWORD = 2, /* string encrypted */ QSE_RAD_ATTR_USER_PASSWORD = 2, /* string encrypted */
@ -154,9 +196,20 @@ enum qse_rad_attr_id_t
QSE_RAD_ATTR_NAS_PORT_TYPE = 61, /* integer */ QSE_RAD_ATTR_NAS_PORT_TYPE = 61, /* integer */
QSE_RAD_ATTR_ACCT_INTERIM_INTERVAL = 85, /* integer */ QSE_RAD_ATTR_ACCT_INTERIM_INTERVAL = 85, /* integer */
QSE_RAD_ATTR_NAS_PORT_ID = 87, /* string */ QSE_RAD_ATTR_NAS_PORT_ID = 87, /* string */
QSE_RAD_ATTR_FRAMED_IPV6_PREFIX = 97 /* ipv6prefix */ QSE_RAD_ATTR_FRAMED_IPV6_PREFIX = 97, /* ipv6prefix */
QSE_RAD_ATTR_EXTENDED_1 = 241,
QSE_RAD_ATTR_EXTENDED_2 = 242,
QSE_RAD_ATTR_EXTENDED_3 = 243,
QSE_RAD_ATTR_EXTENDED_4 = 244,
QSE_RAD_ATTR_EXTENDED_5 = 245, /* long extended */
QSE_RAD_ATTR_EXTENDED_6 = 246, /* long extended */
}; };
#define QSE_RAD_ATTR_IS_SHORT_EXTENDED(attrtype) ((attrtype) >= QSE_RAD_ATTR_EXTENDED_1 && (attrtype) <= QSE_RAD_ATTR_EXTENDED_4)
#define QSE_RAD_ATTR_IS_LONG_EXTENDED(attrtype) ((attrtype) >= QSE_RAD_ATTR_EXTENDED_5 && (attrtype) <= QSE_RAD_ATTR_EXTENDED_6)
#define QSE_RAD_ATTR_IS_EXTENDED(attrtype) ((attrtype) >= QSE_RAD_ATTR_EXTENDED_1 && (attrtype) <= QSE_RAD_ATTR_EXTENDED_6)
enum qse_rad_attr_acct_status_type_t enum qse_rad_attr_acct_status_type_t
{ {
QSE_RAD_ATTR_ACCT_STATUS_TYPE_START = 1, /* accounting start */ QSE_RAD_ATTR_ACCT_STATUS_TYPE_START = 1, /* accounting start */
@ -213,10 +266,25 @@ QSE_EXPORT void qse_rad_initialize (
QSE_EXPORT qse_rad_attr_hdr_t* qse_rad_find_attribute ( QSE_EXPORT qse_rad_attr_hdr_t* qse_rad_find_attribute (
qse_rad_hdr_t* hdr, qse_rad_hdr_t* hdr,
qse_uint8_t attrid, qse_uint8_t attrtype,
int index int index
); );
QSE_EXPORT qse_rad_vsattr_hdr_t* qse_rad_find_vsattr (
qse_rad_hdr_t* hdr,
qse_uint32_t vendor,
qse_uint8_t attrtype,
int index
);
QSE_EXPORT qse_rad_xvsattr_hdr_t* qse_rad_find_extended_vsattr (
qse_rad_hdr_t* hdr,
qse_uint32_t vendor,
qse_uint8_t xtype,
qse_uint8_t attrtype,
int index
);
QSE_EXPORT qse_rad_attr_hdr_t* qse_rad_find_vendor_specific_attribute ( QSE_EXPORT qse_rad_attr_hdr_t* qse_rad_find_vendor_specific_attribute (
qse_rad_hdr_t* hdr, qse_rad_hdr_t* hdr,
qse_uint32_t vendor, qse_uint32_t vendor,
@ -238,24 +306,55 @@ QSE_EXPORT int qse_rad_insert_attribute (
qse_uint8_t len qse_uint8_t len
); );
QSE_EXPORT int qse_rad_insert_extended_attribute (
qse_rad_hdr_t* auth,
int max,
qse_uint8_t xtype,
qse_uint8_t attrtype,
const void* ptr,
qse_uint8_t len,
qse_uint8_t lxflags
);
QSE_EXPORT int qse_rad_insert_vendor_specific_attribute ( QSE_EXPORT int qse_rad_insert_vendor_specific_attribute (
qse_rad_hdr_t* auth, qse_rad_hdr_t* auth,
int max, int max,
qse_uint32_t vendor, qse_uint32_t vendor,
qse_uint8_t attrid, qse_uint8_t attrtype,
const void* ptr, const void* ptr,
qse_uint8_t len qse_uint8_t len
); );
QSE_EXPORT int qse_rad_insert_extended_vendor_specific_attribute (
qse_rad_hdr_t* auth,
int max,
qse_uint32_t vendor,
qse_uint8_t xtype, /* QSE_RAD_ATTR_EXTENDED_X */
qse_uint8_t attrtype,
const void* ptr,
qse_uint8_t len,
qse_uint8_t lxflags
);
QSE_EXPORT int qse_rad_delete_attribute ( QSE_EXPORT int qse_rad_delete_attribute (
qse_rad_hdr_t* hdr, qse_rad_hdr_t* auth,
qse_uint8_t attrid qse_uint8_t attrtype,
int index
); );
QSE_EXPORT int qse_rad_delete_vendor_specific_attribute ( QSE_EXPORT int qse_rad_delete_vendor_specific_attribute (
qse_rad_hdr_t* hdr, qse_rad_hdr_t* auth,
qse_uint32_t vendor, qse_uint32_t vendor,
qse_uint8_t attrid qse_uint8_t attrtype,
int index
);
QSE_EXPORT int qse_rad_delete_extended_vendor_specific_attribute (
qse_rad_hdr_t* auth,
qse_uint32_t vendor,
qse_uint8_t xtype, /* QSE_RAD_ATTR_EXTENDED_X */
qse_uint8_t attrtype,
int index
); );
QSE_EXPORT int qse_rad_insert_string_attribute ( QSE_EXPORT int qse_rad_insert_string_attribute (
@ -318,18 +417,6 @@ QSE_EXPORT int qse_rad_insert_giga_attribute (
qse_uint64_t value qse_uint64_t value
); );
QSE_EXPORT int qse_rad_insert_extended_vendor_specific_attribute (
qse_rad_hdr_t* auth,
int max,
qse_uint8_t base, /* one of 241-244 */
qse_uint32_t vendor,
qse_uint8_t attrid,
const void* ptr,
qse_uint8_t len
);
/* TODO: QSE_EXPORT int qse_rad_delete_extended_vendor_specific_attribute () */
QSE_EXPORT int qse_rad_set_user_password ( QSE_EXPORT int qse_rad_set_user_password (
qse_rad_hdr_t* auth, qse_rad_hdr_t* auth,
int max, int max,

View File

@ -1453,7 +1453,6 @@ static int process_attribute (
flags.has_tlv = 1; flags.has_tlv = 1;
} }
// TODO: what is tlv???
if (block_tlv) if (block_tlv)
{ {
/* /*
@ -1662,7 +1661,7 @@ static int load_file (qse_raddic_t* dic, const qse_char_t* fn, const qse_char_t*
const qse_char_t* b = qse_basename(src_file); const qse_char_t* b = qse_basename(src_file);
if (b != src_file) if (b != src_file)
{ {
fname = qse_substbasenamedup (src_file, fn, dic->mmgr); fname = qse_substbasenamedup(src_file, fn, dic->mmgr);
if (!fname) if (!fname)
{ {
qse_raddic_seterrfmt (dic, QSE_RADDIC_ENOMEM, QSE_T("%s[%zd]: out of memory before including %s"), fn); qse_raddic_seterrfmt (dic, QSE_RADDIC_ENOMEM, QSE_T("%s[%zd]: out of memory before including %s"), fn);

View File

@ -89,90 +89,240 @@ static void fill_authenticator_randomly (void* authenticator, int length)
} }
} }
static qse_rad_attr_hdr_t* find_attribute (qse_rad_attr_hdr_t* attr, int* len, qse_uint8_t attrid) static qse_rad_attr_hdr_t* find_attribute (qse_rad_attr_hdr_t* attr, int* len, qse_uint8_t attrtype)
{ {
int rem = *len; int rem = *len;
while (rem >= QSE_SIZEOF(*attr)) while (rem >= QSE_SIZEOF(*attr))
{ {
/* sanity checks */ /* sanity checks */
if (rem < attr->length) return NULL; if (rem < attr->length) return QSE_NULL;
if (attr->length < QSE_SIZEOF(*attr)) if (attr->length < QSE_SIZEOF(*attr))
{ {
/* attribute length cannot be less than the header size. /* attribute length cannot be less than the header size.
* the packet could be corrupted... */ * the packet could be corrupted... */
return NULL; return QSE_NULL;
} }
rem -= attr->length; rem -= attr->length;
if (attr->id == attrid) if (attr->type == attrtype)
{ {
*len = rem; *len = rem; /* remaining length */
return attr; return attr;
} }
attr = (qse_rad_attr_hdr_t*) ((char*) attr + attr->length); attr = (qse_rad_attr_hdr_t*)((qse_uint8_t*)attr + attr->length);
} }
return NULL; return QSE_NULL;
} }
qse_rad_attr_hdr_t* qse_rad_find_attribute (qse_rad_hdr_t* hdr, qse_uint8_t attrid, int index) static qse_rad_attr_hdr_t* find_extended_attribute (qse_rad_attr_hdr_t* attr, int* len, qse_uint8_t xtype, qse_uint8_t attrtype)
{ {
qse_rad_attr_hdr_t *attr = (qse_rad_attr_hdr_t*)(hdr+1); int rem = *len;
int len = qse_ntoh16(hdr->length) - QSE_SIZEOF(*hdr);
attr = find_attribute (attr, &len, attrid); /* xtype must be one of the followings:
while (attr) * QSE_RAD_ATTR_EXTENDED_1
* QSE_RAD_ATTR_EXTENDED_2
* QSE_RAD_ATTR_EXTENDED_3
* QSE_RAD_ATTR_EXTENDED_4
* QSE_RAD_ATTR_EXTENDED_5
* QSE_RAD_ATTR_EXTENDED_6
*/
while (rem >= QSE_SIZEOF(*attr))
{ {
if (index <= 0) return attr; /* sanity checks */
index--; if (rem < attr->length) return QSE_NULL;
attr = find_attribute ((qse_rad_attr_hdr_t*)((char*)attr+attr->length), &len, attrid);
}
return NULL; /* attribute length cannot be less than the header size.
} * the packet could be corrupted... */
if (attr->length < QSE_SIZEOF(*attr)) goto oops;
qse_rad_attr_hdr_t* qse_rad_find_vendor_specific_attribute (qse_rad_hdr_t* hdr, qse_uint32_t vendor, qse_uint8_t attrid, int index) rem -= attr->length;
{ if (attr->type == xtype)
qse_rad_attr_hdr_t *attr = (qse_rad_attr_hdr_t*)(hdr+1);
int len = qse_ntoh16(hdr->length) - QSE_SIZEOF(*hdr);
attr = find_attribute (attr, &len, QSE_RAD_ATTR_VENDOR_SPECIFIC);
while (attr)
{
qse_rad_vsattr_hdr_t* vsattr;
if (attr->length >= QSE_SIZEOF(*vsattr)) /* sanity check */
{ {
vsattr = (qse_rad_vsattr_hdr_t*)attr; qse_uint8_t xattrtype;
if (qse_ntoh32(vsattr->vendor) == vendor) if (QSE_RAD_ATTR_IS_LONG_EXTENDED(xtype))
{ {
qse_rad_attr_hdr_t* subattr; qse_rad_lxattr_hdr_t* lxattr;
int sublen = vsattr->length - QSE_SIZEOF(*vsattr); lxattr = (qse_rad_lxattr_hdr_t*)attr;
if (lxattr->length < QSE_SIZEOF(*lxattr)) goto oops;
xattrtype = lxattr->xtype;
}
else
{
qse_rad_xattr_hdr_t* xattr;
xattr = (qse_rad_xattr_hdr_t*)attr;
if (xattr->length < QSE_SIZEOF(*xattr)) goto oops;
xattrtype = xattr->xtype;
}
if (sublen >= QSE_SIZEOF(*subattr)) /* sanity check */ if (xattrtype == attrtype)
{
*len = rem;
return attr;
}
}
attr = (qse_rad_attr_hdr_t*)((qse_uint8_t*)attr + attr->length);
}
oops:
return QSE_NULL;
}
qse_rad_attr_hdr_t* qse_rad_find_attribute (qse_rad_hdr_t* hdr, qse_uint8_t attrtype, int index)
{
qse_rad_attr_hdr_t *attr = (qse_rad_attr_hdr_t*)(hdr+1);
if (qse_ntoh16(hdr->length) >= QSE_SIZEOF(*hdr))
{
int len = qse_ntoh16(hdr->length) - QSE_SIZEOF(*hdr);
attr = find_attribute(attr, &len, attrtype);
while (attr)
{
if (index <= 0) return attr;
index--;
attr = find_attribute((qse_rad_attr_hdr_t*)((qse_uint8_t*)attr+attr->length), &len, attrtype);
}
}
return QSE_NULL;
}
qse_rad_attr_hdr_t* qse_rad_find_extended_attribute (qse_rad_hdr_t* hdr, qse_uint8_t xtype, qse_uint8_t attrtype, int index)
{
qse_rad_attr_hdr_t *attr = (qse_rad_attr_hdr_t*)(hdr + 1);
if (QSE_RAD_ATTR_IS_EXTENDED(xtype) && qse_ntoh16(hdr->length) >= QSE_SIZEOF(*hdr))
{
int len = qse_ntoh16(hdr->length) - QSE_SIZEOF(*hdr);
attr = find_extended_attribute(attr, &len, xtype, attrtype);
while (attr)
{
if (index <= 0) return attr;
index--;
attr = find_extended_attribute((qse_rad_attr_hdr_t*)((qse_uint8_t*)attr + attr->length), &len, xtype, attrtype);
}
}
return QSE_NULL;
}
qse_rad_vsattr_hdr_t* qse_rad_find_vsattr (qse_rad_hdr_t* hdr, qse_uint32_t vendor, qse_uint8_t attrtype, int index)
{
qse_rad_attr_hdr_t *attr = (qse_rad_attr_hdr_t*)(hdr+1);
if (qse_ntoh16(hdr->length) >= QSE_SIZEOF(*hdr))
{
int len = qse_ntoh16(hdr->length) - QSE_SIZEOF(*hdr);
attr = find_attribute(attr, &len, QSE_RAD_ATTR_VENDOR_SPECIFIC);
while (attr)
{
qse_rad_vsattr_hdr_t* vsattr;
if (attr->length >= QSE_SIZEOF(*vsattr)) /* sanity check */
{
vsattr = (qse_rad_vsattr_hdr_t*)attr;
if (qse_ntoh32(vsattr->vendor) == vendor && vsattr->vs.type == attrtype)
{ {
subattr = (qse_rad_attr_hdr_t*)(vsattr + 1); int val_len;
if (subattr->id == attrid && subattr->length == sublen)
val_len = (int)vsattr->length - QSE_SIZEOF(*vsattr);
if ((int)vsattr->vs.length == val_len + QSE_SIZEOF(vsattr->vs))
{ {
if (index <= 0) return subattr; if (index <= 0) return vsattr;
index--; index--;
} }
} }
} }
attr = find_attribute((qse_rad_attr_hdr_t*)((qse_uint8_t*)attr + attr->length), &len, QSE_RAD_ATTR_VENDOR_SPECIFIC);
} }
attr = find_attribute ((qse_rad_attr_hdr_t*)((char*)attr+attr->length), &len, QSE_RAD_ATTR_VENDOR_SPECIFIC);
} }
return NULL; return QSE_NULL;
}
qse_rad_xvsattr_hdr_t* qse_rad_find_extended_vsattr (qse_rad_hdr_t* hdr, qse_uint32_t vendor, qse_uint8_t xtype, qse_uint8_t attrtype, int index)
{
qse_rad_attr_hdr_t *attr = (qse_rad_attr_hdr_t*)(hdr+1);
if (QSE_RAD_ATTR_IS_EXTENDED(xtype) && qse_ntoh16(hdr->length) >= QSE_SIZEOF(*hdr))
{
int len = qse_ntoh16(hdr->length) - QSE_SIZEOF(*hdr);
attr = find_extended_attribute(attr, &len, xtype, QSE_RAD_ATTR_VENDOR_SPECIFIC);
while (attr)
{
if (QSE_RAD_ATTR_IS_LONG_EXTENDED(xtype))
{
qse_rad_lxvsattr_hdr_t* lxvsattr;
if (attr->length >= QSE_SIZEOF(*lxvsattr)) /* sanity check */
{
lxvsattr = (qse_rad_lxvsattr_hdr_t*)attr;
if (qse_ntoh32(lxvsattr->vendor) == vendor && lxvsattr->lxvs.type == attrtype)
{
int val_len;
val_len = (int)lxvsattr->length - QSE_SIZEOF(*lxvsattr);
if ((int)lxvsattr->lxvs.length == val_len + QSE_SIZEOF(lxvsattr->lxvs))
{
/* the caller must check if the extended type is long.
* if long, it must cast back to qse_rad_lxvsattr_hdr_t* */
if (index <= 0) return (qse_rad_xvsattr_hdr_t*)lxvsattr;
index--;
}
}
}
}
else
{
qse_rad_xvsattr_hdr_t* xvsattr;
if (attr->length >= QSE_SIZEOF(*xvsattr)) /* sanity check */
{
xvsattr = (qse_rad_xvsattr_hdr_t*)attr;
if (qse_ntoh32(xvsattr->vendor) == vendor && xvsattr->xvs.type == attrtype)
{
int val_len;
val_len = (int)xvsattr->length - QSE_SIZEOF(*xvsattr);
if ((int)xvsattr->xvs.length == val_len + QSE_SIZEOF(xvsattr->xvs))
{
if (index <= 0) return xvsattr;
index--;
}
}
}
}
attr = find_extended_attribute((qse_rad_attr_hdr_t*)((qse_uint8_t*)attr + attr->length), &len, xtype, QSE_RAD_ATTR_VENDOR_SPECIFIC);
}
}
return QSE_NULL;
}
qse_rad_attr_hdr_t* qse_rad_find_vendor_specific_attribute (qse_rad_hdr_t* hdr, qse_uint32_t vendor, qse_uint8_t attrtype, int index)
{
qse_rad_vsattr_hdr_t* vsattr;
vsattr = qse_rad_find_vsattr(hdr, vendor, attrtype, index);
return vsattr? &vsattr->vs: QSE_NULL;
} }
int qse_rad_walk_attributes (const qse_rad_hdr_t* hdr, qse_rad_attr_walker_t walker, void* ctx) int qse_rad_walk_attributes (const qse_rad_hdr_t* hdr, qse_rad_attr_walker_t walker, void* ctx)
{ {
int totlen, rem; int totlen, rem;
qse_rad_attr_hdr_t *attr; qse_rad_attr_hdr_t* attr;
totlen = qse_ntoh16(hdr->length); totlen = qse_ntoh16(hdr->length);
if (totlen < QSE_SIZEOF(*hdr)) return -1; if (totlen < QSE_SIZEOF(*hdr)) return -1;
@ -192,33 +342,30 @@ int qse_rad_walk_attributes (const qse_rad_hdr_t* hdr, qse_rad_attr_walker_t wal
rem -= attr->length; rem -= attr->length;
if (attr->id == QSE_RAD_ATTR_VENDOR_SPECIFIC) if (attr->type == QSE_RAD_ATTR_VENDOR_SPECIFIC)
{ {
qse_rad_vsattr_hdr_t* vsattr; qse_rad_vsattr_hdr_t* vsattr;
qse_rad_attr_hdr_t* subattr; int val_len;
int sublen;
if (attr->length < QSE_SIZEOF(*vsattr)) return -1; if (attr->length < QSE_SIZEOF(*vsattr)) return -1;
vsattr = (qse_rad_vsattr_hdr_t*)attr; vsattr = (qse_rad_vsattr_hdr_t*)attr;
sublen = vsattr->length - QSE_SIZEOF(*vsattr); val_len = (int)vsattr->length - QSE_SIZEOF(*vsattr);
if (sublen < QSE_SIZEOF(*subattr)) return -1; if ((int)vsattr->vs.length != val_len + QSE_SIZEOF(vsattr->vs)) return -1;
subattr = (qse_rad_attr_hdr_t*)(vsattr + 1);
if (subattr->length != sublen) return -1;
/* if this vendor happens to be 0, walker can't tell /* if this vendor happens to be 0, walker can't tell
* if it is vendor specific or not because 0 is passed in * if it is vendor specific or not because 0 is passed in
* for non-VSAs. but i don't care. in reality, * for non-VSAs. but i don't care. in reality,
* 0 is reserved in IANA enterpirse number assignments. * 0 is reserved in IANA enterpirse number assignments.
* (http://www.iana.org/assignments/enterprise-numbers) */ * (http://www.iana.org/assignments/enterprise-numbers) */
if (walker (hdr, qse_ntoh32(vsattr->vendor), subattr, ctx) <= -1) return -1; if (walker(hdr, qse_ntoh32(vsattr->vendor), &vsattr->vs, ctx) <= -1) return -1;
} }
else else
{ {
if (walker (hdr, 0, attr, ctx) <= -1) return -1; if (walker(hdr, 0, attr, ctx) <= -1) return -1;
} }
attr = (qse_rad_attr_hdr_t*) ((char*) attr + attr->length); attr = (qse_rad_attr_hdr_t*)((qse_uint8_t*) attr + attr->length);
} }
return 0; return 0;
@ -239,8 +386,8 @@ int qse_rad_insert_attribute (
if (new_auth_len > max) return -1; if (new_auth_len > max) return -1;
attr = (qse_rad_attr_hdr_t*) ((char*)auth + auth_len); attr = (qse_rad_attr_hdr_t*)((qse_uint8_t*)auth + auth_len);
attr->id = id; attr->type = id;
attr->length = new_auth_len - auth_len; attr->length = new_auth_len - auth_len;
QSE_MEMCPY (attr + 1, ptr, len); QSE_MEMCPY (attr + 1, ptr, len);
auth->length = qse_hton16(new_auth_len); auth->length = qse_hton16(new_auth_len);
@ -248,36 +395,135 @@ int qse_rad_insert_attribute (
return 0; return 0;
} }
int qse_rad_insert_vendor_specific_attribute ( int qse_rad_insert_extended_attribute (
qse_rad_hdr_t* auth, int max, qse_rad_hdr_t* auth, int max, qse_uint8_t xtype,
qse_uint32_t vendor, qse_uint8_t attrid, const void* ptr, qse_uint8_t len) qse_uint8_t attrtype, const void* ptr, qse_uint8_t len, qse_uint8_t lxflags)
{ {
qse_rad_vsattr_hdr_t* attr; qse_rad_xattr_hdr_t* xattr;
qse_rad_attr_hdr_t* subattr;
int auth_len = qse_ntoh16(auth->length); int auth_len = qse_ntoh16(auth->length);
int new_auth_len; int new_auth_len, maxvallen, hdrlen;
if (QSE_RAD_ATTR_IS_SHORT_EXTENDED(xtype))
{
maxvallen = QSE_RAD_MAX_XATTR_VALUE_LEN;
hdrlen = QSE_SIZEOF(qse_rad_xattr_hdr_t);
}
else if (QSE_RAD_ATTR_IS_LONG_EXTENDED(xtype))
{
maxvallen = QSE_RAD_MAX_LXATTR_VALUE_LEN;
hdrlen = QSE_SIZEOF(qse_rad_lxattr_hdr_t);
}
else return -1;
/*if (len > QSE_RAD_MAX_VSATTR_VALUE_LEN) return -1;*/ /*if (len > maxvallen) return -1;*/
if (len > QSE_RAD_MAX_VSATTR_VALUE_LEN) len = QSE_RAD_MAX_VSATTR_VALUE_LEN; if (len > maxvallen) len = maxvallen;
new_auth_len = auth_len + len + QSE_SIZEOF(*attr) + QSE_SIZEOF(*subattr); new_auth_len = auth_len + hdrlen + len;
if (new_auth_len > max) return -1; if (new_auth_len > max) return -1;
attr = (qse_rad_vsattr_hdr_t*) ((char*)auth + auth_len); xattr = (qse_rad_xattr_hdr_t*)((qse_uint8_t*)auth + auth_len);
attr->id = QSE_RAD_ATTR_VENDOR_SPECIFIC; xattr->type = xtype;
attr->length = new_auth_len - auth_len; xattr->length = new_auth_len - auth_len;
attr->vendor = qse_hton32 (vendor); if (QSE_RAD_ATTR_IS_LONG_EXTENDED(xtype))
{
qse_rad_lxattr_hdr_t* lxattr;
lxattr = (qse_rad_lxattr_hdr_t*)xattr;
lxattr->xtype = attrtype;
lxattr->xflags = lxflags;
QSE_MEMCPY (lxattr + 1, ptr, len);
}
else
{
xattr->xtype = attrtype;
QSE_MEMCPY (xattr + 1, ptr, len);
}
auth->length = qse_hton16(new_auth_len);
subattr = (qse_rad_attr_hdr_t*)(attr + 1); return 0;
subattr->id = attrid; }
subattr->length = len + QSE_SIZEOF(*subattr);
QSE_MEMCPY (subattr + 1, ptr, len); int qse_rad_insert_vendor_specific_attribute (
qse_rad_hdr_t* auth, int max,
qse_uint32_t vendor, qse_uint8_t attrtype, const void* ptr, qse_uint8_t len)
{
qse_rad_vsattr_hdr_t* vsattr;
int auth_len = qse_ntoh16(auth->length);
int new_auth_len;
/*if (len > QSE_RAD_MAX_VSATTR_VALUE_LEN) return -1;*/
if (len > QSE_RAD_MAX_VSATTR_VALUE_LEN) len = QSE_RAD_MAX_VSATTR_VALUE_LEN;
new_auth_len = auth_len + QSE_SIZEOF(*vsattr) + len;
if (new_auth_len > max) return -1;
vsattr = (qse_rad_vsattr_hdr_t*)((qse_uint8_t*)auth + auth_len);
vsattr->type = QSE_RAD_ATTR_VENDOR_SPECIFIC;
vsattr->length = new_auth_len - auth_len;
vsattr->vendor = qse_hton32(vendor);
vsattr->vs.type = attrtype;
vsattr->vs.length = QSE_SIZEOF(vsattr->vs) + len;
QSE_MEMCPY (vsattr + 1, ptr, len);
auth->length = qse_hton16(new_auth_len); auth->length = qse_hton16(new_auth_len);
return 0; return 0;
} }
int qse_rad_insert_extended_vendor_specific_attribute (
qse_rad_hdr_t* auth, int max, qse_uint32_t vendor, qse_uint8_t xtype,
qse_uint8_t attrtype, const void* ptr, qse_uint8_t len, qse_uint8_t lxflags)
{
/* RFC6929 */
qse_rad_xvsattr_hdr_t* xvsattr;
int auth_len = qse_ntoh16(auth->length);
int new_auth_len, maxvallen, hdrlen;
if (QSE_RAD_ATTR_IS_SHORT_EXTENDED(xtype))
{
maxvallen = QSE_RAD_MAX_XVSATTR_VALUE_LEN;
hdrlen = QSE_SIZEOF(qse_rad_xvsattr_hdr_t);
}
else if (QSE_RAD_ATTR_IS_LONG_EXTENDED(xtype))
{
maxvallen = QSE_RAD_MAX_LXVSATTR_VALUE_LEN;
hdrlen = QSE_SIZEOF(qse_rad_lxvsattr_hdr_t);
}
else return -1;
/*if (len > maxvallen) return -1;*/
if (len > maxvallen) len = QSE_RAD_MAX_XVSATTR_VALUE_LEN;
new_auth_len = auth_len + hdrlen + len;
if (new_auth_len > max) return -1;
xvsattr = (qse_rad_xvsattr_hdr_t*)((qse_uint8_t*)auth + auth_len);
xvsattr->type = xtype;
xvsattr->length = new_auth_len - auth_len;
xvsattr->xtype = QSE_RAD_ATTR_VENDOR_SPECIFIC;
xvsattr->vendor = qse_hton32(vendor);
if (QSE_RAD_ATTR_IS_LONG_EXTENDED(xtype))
{
/* this function is still low-level. it doesn't handle continuation of big data */
qse_rad_lxvsattr_hdr_t* lxvsattr;
lxvsattr = (qse_rad_lxvsattr_hdr_t*)xvsattr;
lxvsattr->lxvs.type = attrtype;
lxvsattr->lxvs.flags = lxflags;
lxvsattr->lxvs.length = len + QSE_SIZEOF(lxvsattr->lxvs);
QSE_MEMCPY (lxvsattr + 1, ptr, len);
}
else
{
xvsattr->xvs.type = attrtype;
xvsattr->xvs.length = len + QSE_SIZEOF(xvsattr->xvs);
QSE_MEMCPY (xvsattr + 1, ptr, len);
}
auth->length = qse_hton16(new_auth_len);
return 0;
}
static int delete_attribute (qse_rad_hdr_t* auth, qse_rad_attr_hdr_t* attr) static int delete_attribute (qse_rad_hdr_t* auth, qse_rad_attr_hdr_t* attr)
{ {
qse_uint16_t auth_len; qse_uint16_t auth_len;
@ -294,26 +540,34 @@ static int delete_attribute (qse_rad_hdr_t* auth, qse_rad_attr_hdr_t* attr)
return 0; return 0;
} }
int qse_rad_delete_attribute (qse_rad_hdr_t* auth, qse_uint8_t attrid) int qse_rad_delete_attribute (qse_rad_hdr_t* auth, qse_uint8_t attrtype, int index)
{ {
qse_rad_attr_hdr_t* attr; qse_rad_attr_hdr_t* attr;
attr = qse_rad_find_attribute (auth, attrid, 0); attr = qse_rad_find_attribute(auth, attrtype, index);
if (attr == NULL) return 0; /* not found */ if (!attr) return 0; /* not found */
return (delete_attribute (auth, attr) <= -1)? -1: 1; return (delete_attribute(auth, attr) <= -1)? -1: 1;
} }
int qse_rad_delete_vendor_specific_attribute ( int qse_rad_delete_vendor_specific_attribute (
qse_rad_hdr_t* auth, qse_uint32_t vendor, qse_uint8_t attrid) qse_rad_hdr_t* auth, qse_uint32_t vendor, qse_uint8_t attrtype, int index)
{ {
qse_rad_attr_hdr_t* attr;
qse_rad_vsattr_hdr_t* vsattr; qse_rad_vsattr_hdr_t* vsattr;
attr = qse_rad_find_vendor_specific_attribute (auth, vendor, attrid, 0); vsattr = qse_rad_find_vsattr(auth, vendor, attrtype, 0);
if (attr == NULL) return 0; /* not found */ if (!vsattr) return 0; /* not found */
return (delete_attribute(auth, (qse_rad_attr_hdr_t*)vsattr) <= -1)? -1: 1;
}
vsattr = (qse_rad_vsattr_hdr_t*)((qse_uint8_t*)attr - QSE_SIZEOF(qse_rad_vsattr_hdr_t)); int qse_rad_delete_extended_vendor_specific_attribute (
return (delete_attribute (auth, (qse_rad_attr_hdr_t*)vsattr) <= -1)? -1: 1; qse_rad_hdr_t* auth, qse_uint32_t vendor, qse_uint8_t xtype, qse_uint8_t attrtype, int index)
{
qse_rad_xvsattr_hdr_t* xvsattr;
xvsattr = qse_rad_find_extended_vsattr(auth, vendor, xtype, attrtype, 0);
if (!xvsattr) return 0; /* not found */
return (delete_attribute(auth, (qse_rad_attr_hdr_t*)xvsattr) <= -1)? -1: 1;
} }
int qse_rad_insert_string_attribute ( int qse_rad_insert_string_attribute (
@ -321,8 +575,8 @@ int qse_rad_insert_string_attribute (
qse_uint8_t id, const qse_mchar_t* value) qse_uint8_t id, const qse_mchar_t* value)
{ {
return (vendor == 0)? return (vendor == 0)?
qse_rad_insert_attribute (auth, max, id, value, qse_mbslen(value)): qse_rad_insert_attribute(auth, max, id, value, qse_mbslen(value)):
qse_rad_insert_vendor_specific_attribute (auth, max, vendor, id, value, qse_mbslen(value)); qse_rad_insert_vendor_specific_attribute(auth, max, vendor, id, value, qse_mbslen(value));
} }
int qse_rad_insert_wide_string_attribute ( int qse_rad_insert_wide_string_attribute (
@ -333,10 +587,10 @@ int qse_rad_insert_wide_string_attribute (
qse_mchar_t* val; qse_mchar_t* val;
qse_size_t mbslen; qse_size_t mbslen;
val = qse_wcstombsdup (value, &mbslen, QSE_MMGR_GETDFL()); val = qse_wcstombsdup(value, &mbslen, QSE_MMGR_GETDFL());
n = (vendor == 0)? n = (vendor == 0)?
qse_rad_insert_attribute (auth, max, id, val, mbslen): qse_rad_insert_attribute(auth, max, id, val, mbslen):
qse_rad_insert_vendor_specific_attribute (auth, max, vendor, id, val, mbslen); qse_rad_insert_vendor_specific_attribute(auth, max, vendor, id, val, mbslen);
QSE_MMGR_FREE (QSE_MMGR_GETDFL(), val); QSE_MMGR_FREE (QSE_MMGR_GETDFL(), val);
return n; return n;
@ -347,8 +601,8 @@ int qse_rad_insert_string_attribute_with_length (
qse_uint8_t id, const qse_mchar_t* value, qse_uint8_t length) qse_uint8_t id, const qse_mchar_t* value, qse_uint8_t length)
{ {
return (vendor == 0)? return (vendor == 0)?
qse_rad_insert_attribute (auth, max, id, value, length): qse_rad_insert_attribute(auth, max, id, value, length):
qse_rad_insert_vendor_specific_attribute (auth, max, vendor, id, value, length); qse_rad_insert_vendor_specific_attribute(auth, max, vendor, id, value, length);
} }
int qse_rad_insert_wide_string_attribute_with_length ( int qse_rad_insert_wide_string_attribute_with_length (
@ -359,10 +613,10 @@ int qse_rad_insert_wide_string_attribute_with_length (
qse_mchar_t* val; qse_mchar_t* val;
qse_size_t mbslen; qse_size_t mbslen;
val = qse_wcsntombsdup (value, length, &mbslen, QSE_MMGR_GETDFL()); val = qse_wcsntombsdup(value, length, &mbslen, QSE_MMGR_GETDFL());
n = (vendor == 0)? n = (vendor == 0)?
qse_rad_insert_attribute (auth, max, id, val, mbslen): qse_rad_insert_attribute(auth, max, id, val, mbslen):
qse_rad_insert_vendor_specific_attribute (auth, max, vendor, id, val, mbslen); qse_rad_insert_vendor_specific_attribute(auth, max, vendor, id, val, mbslen);
QSE_MMGR_FREE (QSE_MMGR_GETDFL(), val); QSE_MMGR_FREE (QSE_MMGR_GETDFL(), val);
return n; return n;
@ -373,8 +627,8 @@ int qse_rad_insert_uint32_attribute (
{ {
qse_uint32_t val = qse_hton32(value); qse_uint32_t val = qse_hton32(value);
return (vendor == 0)? return (vendor == 0)?
qse_rad_insert_attribute (auth, max, id, &val, QSE_SIZEOF(val)): qse_rad_insert_attribute(auth, max, id, &val, QSE_SIZEOF(val)):
qse_rad_insert_vendor_specific_attribute (auth, max, vendor, id, &val, QSE_SIZEOF(val)); qse_rad_insert_vendor_specific_attribute(auth, max, vendor, id, &val, QSE_SIZEOF(val));
} }
int qse_rad_insert_ipv6prefix_attribute ( int qse_rad_insert_ipv6prefix_attribute (
@ -419,8 +673,8 @@ int qse_rad_insert_ipv6prefix_attribute (
} }
return (vendor == 0)? return (vendor == 0)?
qse_rad_insert_attribute (auth, max, id, &ipv6prefix, j + 2): qse_rad_insert_attribute(auth, max, id, &ipv6prefix, j + 2):
qse_rad_insert_vendor_specific_attribute (auth, max, vendor, id, &ipv6prefix, j + 2); qse_rad_insert_vendor_specific_attribute(auth, max, vendor, id, &ipv6prefix, j + 2);
} }
int qse_rad_insert_giga_attribute ( int qse_rad_insert_giga_attribute (
@ -432,67 +686,32 @@ int qse_rad_insert_giga_attribute (
if (vendor == 0) if (vendor == 0)
{ {
if (qse_rad_insert_attribute (auth, max, low_id, &low, QSE_SIZEOF(low)) <= -1) return -1; if (qse_rad_insert_attribute(auth, max, low_id, &low, QSE_SIZEOF(low)) <= -1) return -1;
if (value > QSE_TYPE_MAX(qse_uint32_t)) if (value > QSE_TYPE_MAX(qse_uint32_t))
{ {
qse_uint32_t high; qse_uint32_t high;
high = value >> (QSE_SIZEOF(qse_uint32_t) * 8); high = value >> (QSE_SIZEOF(qse_uint32_t) * 8);
high = qse_hton32(high); high = qse_hton32(high);
if (qse_rad_insert_attribute (auth, max, high_id, &high, QSE_SIZEOF(high)) <= -1) return -1; if (qse_rad_insert_attribute(auth, max, high_id, &high, QSE_SIZEOF(high)) <= -1) return -1;
} }
} }
else else
{ {
if (qse_rad_insert_vendor_specific_attribute (auth, max, vendor, low_id, &low, QSE_SIZEOF(low)) <= -1) return -1; if (qse_rad_insert_vendor_specific_attribute(auth, max, vendor, low_id, &low, QSE_SIZEOF(low)) <= -1) return -1;
if (value > QSE_TYPE_MAX(qse_uint32_t)) if (value > QSE_TYPE_MAX(qse_uint32_t))
{ {
qse_uint32_t high; qse_uint32_t high;
high = value >> (QSE_SIZEOF(qse_uint32_t) * 8); high = value >> (QSE_SIZEOF(qse_uint32_t) * 8);
high = qse_hton32(high); high = qse_hton32(high);
if (qse_rad_insert_vendor_specific_attribute (auth, max, vendor, high_id, &high, QSE_SIZEOF(high)) <= -1) return -1; if (qse_rad_insert_vendor_specific_attribute(auth, max, vendor, high_id, &high, QSE_SIZEOF(high)) <= -1) return -1;
} }
} }
return 0; return 0;
} }
int qse_rad_insert_extended_vendor_specific_attribute (
qse_rad_hdr_t* auth, int max, qse_uint8_t base, qse_uint32_t vendor,
qse_uint8_t attrid, const void* ptr, qse_uint8_t len)
{
/* RFC6929 */
qse_rad_extvsattr_hdr_t* attr;
int auth_len = qse_ntoh16(auth->length);
int new_auth_len;
if (base < 241 && base > 244) return -1;
/* TODO: for 245 and 246, switch to long-extended format */
/*if (len > QSE_RAD_MAX_EXTVSATTR_VALUE_LEN) return -1;*/
if (len > QSE_RAD_MAX_EXTVSATTR_VALUE_LEN) len = QSE_RAD_MAX_EXTVSATTR_VALUE_LEN;
new_auth_len = auth_len + len + QSE_SIZEOF(*attr);
if (new_auth_len > max) return -1;
attr = (qse_rad_extvsattr_hdr_t*) ((char*)auth + auth_len);
attr->id = base;
attr->length = new_auth_len - auth_len;
attr->xid = QSE_RAD_ATTR_VENDOR_SPECIFIC;
attr->vendor = qse_hton32(vendor);
attr->evsid = attrid;
/* no special header for the evs-value */
QSE_MEMCPY (attr + 1, ptr, len);
auth->length = qse_hton16(new_auth_len);
return 0;
}
#define PASS_BLKSIZE QSE_RAD_MAX_AUTHENTICATOR_LEN #define PASS_BLKSIZE QSE_RAD_MAX_AUTHENTICATOR_LEN
#define ALIGN(x,factor) ((((x) + (factor) - 1) / (factor)) * (factor)) #define ALIGN(x,factor) ((((x) + (factor) - 1) / (factor)) * (factor))
@ -550,8 +769,14 @@ int qse_rad_set_user_password (qse_rad_hdr_t* auth, int max, const qse_mchar_t*
} }
/* ok if not found or deleted. but not ok if an error occurred */ /* ok if not found or deleted. but not ok if an error occurred */
if (qse_rad_delete_attribute (auth, QSE_RAD_ATTR_USER_PASSWORD) <= -1) goto oops; while (1)
if (qse_rad_insert_attribute (auth, max, QSE_RAD_ATTR_USER_PASSWORD, hashed, padlen) <= -1) goto oops; {
int n;
n = qse_rad_delete_attribute(auth, QSE_RAD_ATTR_USER_PASSWORD, 0);
if (n <= -1) goto oops;
if (n == 0) break;
}
if (qse_rad_insert_attribute(auth, max, QSE_RAD_ATTR_USER_PASSWORD, hashed, padlen) <= -1) goto oops;
return 0; return 0;