Add rs_packet_add_avp() and use it.
authorLinus Nordberg <linus@nordberg.se>
Wed, 8 May 2013 15:08:14 +0000 (17:08 +0200)
committerLinus Nordberg <linus@nordberg.se>
Wed, 8 May 2013 15:13:46 +0000 (17:13 +0200)
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
lib/packet.c
lib/radius/radpkt.c

index 230f671..fe6690a 100644 (file)
@@ -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,
index ba7ddb8..63bf370 100644 (file)
@@ -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)
index bb8f75e..d9486ea 100644 (file)
@@ -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;