From 79d36d41a578451a37c134981d5698dec3d5a4d3 Mon Sep 17 00:00:00 2001 From: Linus Nordberg Date: Wed, 8 May 2013 17:08:14 +0200 Subject: [PATCH] Add rs_packet_add_avp() and use it. rs_packet_create_authn_request() now uses rs_packet_add_avp() instead of rs_packet_append_avp() which makes it possible to create a authentication packet without knowing the shared secret. Calling rs_packet_add_avp() on a packet is incompatible with using rs_packet_append_avp() on the same packet but since rs_packet_create_authn_request() adds attribute-value pairs for user name and password only if those arguments are supplied, code that doesn't use user name and password (i.e. mech_eap) should still be fine. --- lib/include/radsec/radsec.h | 12 +++++++++++- lib/packet.c | 45 +++++++++++++++++++++++++++++++++++++++++++-- lib/radius/radpkt.c | 6 +++++- 3 files changed, 59 insertions(+), 4 deletions(-) diff --git a/lib/include/radsec/radsec.h b/lib/include/radsec/radsec.h index 230f671..fe6690a 100644 --- a/lib/include/radsec/radsec.h +++ b/lib/include/radsec/radsec.h @@ -321,7 +321,17 @@ int rs_packet_create_authn_request(struct rs_connection *conn, const char *user_name, const char *user_pw); -/*** Append \a tail to packet \a pkt. */ +/** Add a new attribute-value pair to \a pkt. */ +int rs_packet_add_avp(struct rs_packet *pkt, + unsigned int attr, unsigned int vendor, + const void *data, size_t data_len); + +/** Append a new attribute to packet \a pkt. Note that this function + encodes the attribute and therefore might require the secret + shared with the thought recipient to be set in pkt->rpkt. Note + also that this function marks \a pkt as already encoded and can + not be used on packets with non-encoded value-pairs already + added. */ int rs_packet_append_avp(struct rs_packet *pkt, unsigned int attribute, unsigned int vendor, diff --git a/lib/packet.c b/lib/packet.c index ba7ddb8..63bf370 100644 --- a/lib/packet.c +++ b/lib/packet.c @@ -172,14 +172,16 @@ rs_packet_create_authn_request (struct rs_connection *conn, if (user_name) { - err = rs_packet_append_avp (pkt, PW_USER_NAME, 0, user_name, 0); + err = rs_packet_add_avp (pkt, PW_USER_NAME, 0, user_name, + strlen (user_name)); if (err) return err; } if (user_pw) { - err = rs_packet_append_avp (pkt, PW_USER_PASSWORD, 0, user_pw, 0); + err = rs_packet_add_avp (pkt, PW_USER_PASSWORD, 0, user_pw, + strlen (user_pw)); if (err) return err; } @@ -200,6 +202,45 @@ rs_packet_destroy (struct rs_packet *pkt) } int +rs_packet_add_avp (struct rs_packet *pkt, + unsigned int attr, unsigned int vendor, + const void *data, size_t data_len) + +{ + const DICT_ATTR *da; + VALUE_PAIR *vp; + int err; + + assert (pkt); + assert (pkt->conn); + assert (pkt->conn->ctx); + + da = nr_dict_attr_byvalue (attr, vendor); + if (da == NULL) + return rs_err_conn_push (pkt->conn, RSE_ATTR_TYPE_UNKNOWN, + "nr_dict_attr_byvalue"); + vp = rs_malloc (pkt->conn->ctx, sizeof(*vp)); + if (vp == NULL) + return rs_err_conn_push (pkt->conn, RSE_NOMEM, NULL); + if (nr_vp_init (vp, da) == NULL) + { + nr_vp_free (&vp); + return rs_err_conn_push (pkt->conn, RSE_INTERNAL, NULL); + } + err = nr_vp_set_data (vp, data, data_len); + if (err < 0) + { + nr_vp_free (&vp); + return rs_err_conn_push (pkt->conn, -err, "nr_vp_set_data"); + } + nr_vps_append (&pkt->rpkt->vps, vp); + + return RSE_OK; +} + +/* TODO: Rename rs_packet_append_avp, indicating that encoding is + being done. */ +int rs_packet_append_avp (struct rs_packet *pkt, unsigned int attr, unsigned int vendor, const void *data, size_t data_len) diff --git a/lib/radius/radpkt.c b/lib/radius/radpkt.c index bb8f75e..d9486ea 100644 --- a/lib/radius/radpkt.c +++ b/lib/radius/radpkt.c @@ -871,7 +871,11 @@ ssize_t nr_packet_attr_append(RADIUS_PACKET *packet, data_len = strlen(data); } - packet->flags |= RS_PACKET_ENCODED; /* ignore any VPs */ + /* We're going to mark the whole packet as encoded so we + better not have any unencoded value-pairs attached. */ + if (packet->vps) + return -RSE_INVAL; + packet->flags |= RS_PACKET_ENCODED; attr = packet->data + packet->length; end = attr + packet->sizeof_data; -- 2.1.4