return;
}
+static void print_hex(RADIUS_PACKET *packet)
+{
+ int i;
+
+ if (!packet->data) return;
+
+ printf(" Code:\t\t%u\n", packet->data[0]);
+ printf(" Id:\t\t%u\n", packet->data[1]);
+ printf(" Length:\t%u\n", ((packet->data[2] << 8) |
+ (packet->data[3])));
+ printf(" Vector:\t");
+ for (i = 4; i < 20; i++) {
+ printf("%02x", packet->data[i]);
+ }
+ printf("\n");
+
+ if (packet->data_len > 20) {
+ int total;
+ const uint8_t *ptr;
+ printf(" Data:");
+
+ total = packet->data_len - 20;
+ ptr = packet->data + 20;
+
+ while (total > 0) {
+ int attrlen;
+
+ printf("\t\t");
+ if (total < 2) { /* too short */
+ printf("%02x\n", *ptr);
+ break;
+ }
+
+ if (ptr[1] > total) { /* too long */
+ for (i = 0; i < total; i++) {
+ printf("%02x ", ptr[i]);
+ }
+ break;
+ }
+
+ printf("%02x %02x ", ptr[0], ptr[1]);
+ attrlen = ptr[1] - 2;
+ ptr += 2;
+ total -= 2;
+
+ for (i = 0; i < attrlen; i++) {
+ if ((i > 0) && ((i & 0x0f) == 0x00))
+ printf("\t\t\t");
+ printf("%02x ", ptr[i]);
+ if ((i & 0x0f) == 0x0f) printf("\n");
+ }
+
+ if ((attrlen & 0x0f) != 0x00) printf("\n");
+
+ ptr += attrlen;
+ total -= attrlen;
+ }
+ }
+ fflush(stdout);
+}
+
+
/*
* Wrapper for sendto which handles sendfromto, IPv6, and all
* possible combinations.
memcpy(output, passwd, len + 2);
}
-static int vp2data(const RADIUS_PACKET *packet, const RADIUS_PACKET *original,
- const char *secret, const VALUE_PAIR *vp, uint8_t *ptr,
- size_t offset, size_t room)
+/*
+ * Returns the end of the data.
+ */
+static uint8_t *vp2data(const RADIUS_PACKET *packet,
+ const RADIUS_PACKET *original,
+ const char *secret, const VALUE_PAIR *vp, uint8_t *ptr,
+ size_t room)
{
uint32_t lvalue;
size_t len;
len = 1; /* just in case */
array[0] = vp->vp_integer & 0xff;
data = array;
- offset = 0;
break;
case PW_TYPE_SHORT:
array[0] = (vp->vp_integer >> 8) & 0xff;
array[1] = vp->vp_integer & 0xff;
data = array;
- offset = 0;
break;
case PW_TYPE_INTEGER:
len = 4; /* just in case */
lvalue = htonl(vp->vp_integer);
memcpy(array, &lvalue, sizeof(lvalue));
-
- /*
- * Perhaps discard the first octet.
- */
- data = &array[offset];
- len -= offset;
+ data = array;
break;
case PW_TYPE_IPADDR:
data = vp->vp_tlv;
if (!data) {
fr_strerror_printf("ERROR: Cannot encode NULL TLV");
- return -1;
+ return NULL;
}
break;
default: /* unknown type: ignore it */
fr_strerror_printf("ERROR: Unknown attribute type %d", vp->type);
- return -1;
+ return NULL;
}
/*
- * Bound the data to 255 bytes.
+ * Bound the data to the calling size
*/
- if (len + offset > room) {
- len = room - offset;
- }
+ if (len > room) len = room;
/*
* Encrypt the various password styles
*/
switch (vp->flags.encrypt) {
case FLAG_ENCRYPT_USER_PASSWORD:
- make_passwd(ptr + offset, &len,
- data, len,
+ make_passwd(ptr, &len, data, len,
secret, packet->vector);
break;
case FLAG_ENCRYPT_TUNNEL_PASSWORD:
/*
- * Check if 255 - offset - total_length is less
- * than 18. If so, we can't fit the data into
- * the available space, and we discard the
- * attribute.
+ * Check if there's enough room. If there isn't,
+ * we discard the attribute.
*
* This is ONLY a problem if we have multiple VSA's
* in one Vendor-Specific, though.
*/
- if ((room - offset) < 18) return 0;
+ if (room < 18) return ptr;
switch (packet->code) {
case PW_AUTHENTICATION_ACK:
default:
if (!original) {
fr_strerror_printf("ERROR: No request packet, cannot encrypt %s attribute in the vp.", vp->name);
- return -1;
+ return NULL;
}
- make_tunnel_passwd(ptr + offset, &len,
- data, len, room - offset,
+ make_tunnel_passwd(ptr, &len, data, len, room,
secret, original->vector);
break;
case PW_ACCOUNTING_REQUEST:
case PW_DISCONNECT_REQUEST:
case PW_COA_REQUEST:
- make_tunnel_passwd(ptr + offset, &len,
- data, len, room - offset,
+ make_tunnel_passwd(ptr, &len, data, len, room,
secret, packet->vector);
break;
}
* always fits.
*/
case FLAG_ENCRYPT_ASCEND_SECRET:
- make_secret(ptr + offset, packet->vector,
- secret, data);
+ make_secret(ptr, packet->vector, secret, data);
len = AUTH_VECTOR_LEN;
break;
/*
* Just copy the data over
*/
- memcpy(ptr + offset, data, len);
+ memcpy(ptr, data, len);
break;
} /* switch over encryption flags */
- return len;
+ return ptr + len;
}
int maxattr = 0;
int length;
unsigned int attribute;
- uint8_t *ptr;
+ uint8_t *ptr, *end;
VALUE_PAIR *vp, *tlv;
attribute = vps->attribute & 0xffff00ff;
}
maxattr = vp->attribute & 0xff00;
- length = vp2data(NULL, NULL, NULL, vp, ptr + 2, 0,
- tlv->vp_tlv + tlv->length - ptr);
- if (length < 0) {
+ end = vp2data(NULL, NULL, NULL, vp, ptr + 2,
+ tlv->vp_tlv + tlv->length - ptr);
+ if (!end) {
vp->length = ptr - vp->vp_tlv;
return tlv; /* should be a more serious error... */
}
+ length = (end - ptr);
+
/*
* Pack the attribute.
*/
const char *secret, const VALUE_PAIR *vp, uint8_t *start)
{
int vendorcode;
- int offset, len, total_length;
+ int len, total_length;
uint32_t lvalue;
uint8_t *ptr, *length_ptr, *vsa_length_ptr, *tlv_length_ptr;
+ uint8_t *end;
ptr = start;
+ end = ptr + 255;
vendorcode = total_length = 0;
length_ptr = vsa_length_ptr = tlv_length_ptr = NULL;
*length_ptr += vsa_tlen + vsa_llen + vsa_offset;
}
- offset = 0;
- if (vp->flags.has_tag) {
- if (TAG_VALID(vp->flags.tag)) {
- ptr[0] = vp->flags.tag & 0xff;
- offset = 1;
-
- } else if (vp->flags.encrypt == FLAG_ENCRYPT_TUNNEL_PASSWORD) {
- /*
- * Tunnel passwords REQUIRE a tag, even
- * if don't have a valid tag.
- */
- ptr[0] = 0;
- offset = 1;
- } /* else don't write a tag */
- } /* else the attribute doesn't have a tag */
-
- len = vp2data(packet, original, secret, vp, ptr, offset,
- 255 - total_length);
- if (len < 0) return -1;
+ /*
+ * Insert tags for string attributes. They go BEFORE
+ * the string.
+ */
+ if (vp->flags.has_tag && (vp->type == PW_TYPE_STRING) &&
+ (TAG_VALID(vp->flags.tag) ||
+ (vp->flags.encrypt == FLAG_ENCRYPT_TUNNEL_PASSWORD))) {
+ ptr[0] = vp->flags.tag;
+ end = vp2data(packet, original, secret, vp, ptr + 1,
+ (end - ptr) - 1);
+ } else {
+ end = vp2data(packet, original, secret, vp, ptr,
+ (end - ptr));
+ }
+ if (!end) return -1;
/*
- * Account for the tag (if any).
+ * Insert tags for integer attributes. They go at the START
+ * of the integer, and over-write the first byte.
*/
- len += offset;
+ if (vp->flags.has_tag && (vp->type == PW_TYPE_INTEGER)) {
+ ptr[0] = vp->flags.tag;
+ }
/*
* RFC 2865 section 5 says that zero-length attributes
* one vendor. Don't they have anything better to do
* with their time?
*/
- if ((len == 0) &&
+ if ((end == ptr) &&
(vp->attribute != PW_CHARGEABLE_USER_IDENTITY)) return 0;
+ len = (end - ptr);
+
/*
* Update the various lengths.
*/