Have rad_decode() verify responses.
authorLuke Howard <lukeh@padl.com>
Sat, 9 Oct 2010 09:54:37 +0000 (11:54 +0200)
committerLinus Nordberg <linus@nordu.net>
Mon, 11 Oct 2010 16:50:25 +0000 (18:50 +0200)
lib/examples/client-blocking.c
lib/include/radsec/radsec-impl.h
lib/include/radsec/radsec.h
lib/include/radsec/request-impl.h
lib/packet.c
lib/request.c

index 66f4859..365b3b0 100644 (file)
@@ -55,10 +55,16 @@ blocking_client (const char *av1, const char *av2)
 
 #if !defined(USE_REQUEST_OBJECT)
   if (rs_packet_send (req, NULL))
-    return rs_err_conn_pop (conn);
-  req = NULL;
-  if (rs_conn_receive_packet (conn, &resp))
-    return rs_err_conn_pop (conn);
+    {
+      rs_packet_destroy (req);
+      return rs_err_conn_pop (conn);
+    }
+  if (rs_conn_receive_packet (conn, req, &resp))
+    {
+      rs_packet_destroy (req);
+      return rs_err_conn_pop (conn);
+    }
+  rs_packet_destroy (req);
 #else
   {
     struct rs_request *request;
index 3ce01d0..6e5ee83 100644 (file)
@@ -76,6 +76,7 @@ struct rs_packet {
     char hdr_read_flag;
     uint8_t hdr[4];
     RADIUS_PACKET *rpkt;
+    struct rs_packet *original;
 };
 
 struct rs_attr {
index db1e1a7..dd784cc 100644 (file)
@@ -97,6 +97,7 @@ int rs_conn_select_server(struct rs_connection *conn, const char *name);
 int rs_conn_get_current_server(struct rs_connection *conn,
                               const char *name, size_t buflen);
 int rs_conn_receive_packet(struct rs_connection *conn,
+                          struct rs_packet *request,
                           struct rs_packet **pkt_out);
 int rs_conn_fd(struct rs_connection *conn);
 
index 4fa0ca9..339dfea 100644 (file)
@@ -7,10 +7,4 @@ struct rs_request
   struct rs_packet *req;
   struct rs_packet *resp;
   struct rs_conn_callbacks saved_cb;
-  int verified;
 };
-
-#define VENDORPEC_MS                        311 /* RFC 2548 */
-
-#define PW_MS_MPPE_SEND_KEY                 16
-#define PW_MS_MPPE_RECV_KEY                 17
index 9abd698..7872a5a 100644 (file)
@@ -44,6 +44,16 @@ static int
 _do_send (struct rs_packet *pkt)
 {
   int err;
+  VALUE_PAIR *vp;
+
+  assert (pkt->rpkt);
+  assert (!pkt->original);
+
+  vp = paircreate (PW_MESSAGE_AUTHENTICATOR, PW_TYPE_OCTETS);
+  if (!vp)
+    return rs_err_conn_push_fl (pkt->conn, RSE_NOMEM, __FILE__, __LINE__,
+                               "rad_encode: %s", fr_strerror ());
+  pairadd (&pkt->rpkt->vps, vp);
 
   if (rad_encode (pkt->rpkt, NULL, pkt->conn->active_peer->secret))
     return rs_err_conn_push_fl (pkt->conn, RSE_FR, __FILE__, __LINE__,
@@ -51,7 +61,6 @@ _do_send (struct rs_packet *pkt)
   if (rad_sign (pkt->rpkt, NULL, pkt->conn->active_peer->secret))
     return rs_err_conn_push_fl (pkt->conn, RSE_FR, __FILE__, __LINE__,
                                "rad_sign: %s", fr_strerror ());
-  assert (pkt->rpkt);
 #if defined (DEBUG)
   {
     char host[80], serv[80];
@@ -183,11 +192,28 @@ _read_cb (struct bufferevent *bev, void *ctx)
 #endif
       if (!rad_packet_ok (pkt->rpkt, 0) != 0)
        return;
-      if (rad_decode (pkt->rpkt, NULL, pkt->conn->active_peer->secret) != 0)
-        return;
+      assert (pkt->original);
+
+      /* Verify header and message authenticator.  */
+      if (rad_verify (pkt->rpkt, pkt->original->rpkt,
+                     pkt->conn->active_peer->secret))
+       {
+         rs_err_conn_push_fl (pkt->conn, RSE_FR, __FILE__, __LINE__,
+                              "rad_verify: %s", fr_strerror ());
+         return;
+       }
+
+      /* decode and decrypt */
+      if (rad_decode (pkt->rpkt, pkt->original->rpkt,
+                     pkt->conn->active_peer->secret))
+       {
+         rs_err_conn_push_fl (pkt->conn, RSE_FR, __FILE__, __LINE__,
+                              "rad_decode: %s", fr_strerror ());
+         return;
+       }
 
       if (pkt->conn->callbacks.received_cb)
-       pkt->conn->callbacks.received_cb(pkt, pkt->conn->user_data);
+       pkt->conn->callbacks.received_cb (pkt, pkt->conn->user_data);
 
       if (event_base_loopbreak (pkt->conn->evb) < 0)
        abort ();               /* FIXME */
@@ -396,7 +422,9 @@ rs_packet_send (struct rs_packet *pkt, void *user_data)
 }
 
 int
-rs_conn_receive_packet (struct rs_connection *conn, struct rs_packet **pkt_out)
+rs_conn_receive_packet (struct rs_connection *conn,
+                       struct rs_packet *request,
+                       struct rs_packet **pkt_out)
 {
   struct rs_packet *pkt;
 
@@ -406,6 +434,7 @@ rs_conn_receive_packet (struct rs_connection *conn, struct rs_packet **pkt_out)
     return -1;
   pkt = *pkt_out;
   pkt->conn = conn;
+  pkt->original = request;
 
   if (_conn_open (conn, pkt))
     return -1;
@@ -433,6 +462,8 @@ rs_conn_receive_packet (struct rs_connection *conn, struct rs_packet **pkt_out)
 #endif
     }
 
+  pkt->original = NULL;
+
   return RSE_OK;
 }
 
index 85278f3..5cb87bb 100644 (file)
@@ -8,9 +8,6 @@
 #include <radsec/request.h>
 #include <radsec/request-impl.h>
 
-static int
-_rs_decrypt_mppe(struct rs_request *request, VALUE_PAIR *vp);
-
 int
 rs_request_create (struct rs_connection *conn, struct rs_request **req_out)
 {
@@ -55,37 +52,6 @@ static void
 _rs_req_packet_received(const struct rs_packet *pkt, void *user_data)
 {
   struct rs_request *request = (struct rs_request *)user_data;
-  int err;
-  VALUE_PAIR *vp;
-
-  assert (request);
-  assert (request->conn);
-  assert (request->req);
-
-  err = rad_verify(pkt->rpkt, request->req->rpkt,
-                  pkt->conn->active_peer->secret);
-  if (err)
-    return;
-
-  for (vp = pkt->rpkt->vps; vp != NULL; vp = vp->next)
-    {
-      if (VENDOR(vp->attribute) != VENDORPEC_MS)
-       continue;
-
-      switch (vp->attribute & 0xffff)
-       {
-         case PW_MS_MPPE_SEND_KEY:
-         case PW_MS_MPPE_RECV_KEY:
-           err = _rs_decrypt_mppe (request, vp);
-           if (err)
-             return;
-           break;
-         default:
-           break;
-       }
-    }
-
-  request->verified = 1;
 }
 
 static void
@@ -99,7 +65,6 @@ rs_request_send(struct rs_request *request, struct rs_packet *req,
                struct rs_packet **resp)
 {
   int err;
-  VALUE_PAIR *vp;
   struct rs_connection *conn;
 
   assert (request);
@@ -114,104 +79,15 @@ rs_request_send(struct rs_request *request, struct rs_packet *req,
   conn->callbacks.received_cb = _rs_req_packet_received;
   conn->callbacks.sent_cb = _rs_req_packet_sent;
 
-  assert(request->verified == 0);
-
-  vp = paircreate(PW_MESSAGE_AUTHENTICATOR, PW_TYPE_OCTETS);
-  pairadd(&request->req->rpkt->vps, vp);
-
   err = rs_packet_send(request->req, request);
   if (err)
     goto cleanup;
 
-  err = rs_conn_receive_packet(request->conn, resp);
+  err = rs_conn_receive_packet(request->conn, request->req, resp);
   if (err)
     goto cleanup;
 
-  if (!request->verified)
-    {
-      err = rs_err_conn_push_fl (conn, RSE_BADAUTH, __FILE__, __LINE__, NULL);
-      goto cleanup;
-    }
-
 cleanup:
   conn->callbacks = request->saved_cb;
   return err;
 }
-
-/*
- * Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Alternatively, this software may be distributed under the terms of BSD
- * license.
- *
- * See README and COPYING for more details.
- */
-#include <openssl/md5.h>
-
-static int
-_rs_decrypt_mppe(struct rs_request *request, VALUE_PAIR *vp)
-{
-  unsigned char *key = vp->vp_octets;
-  size_t len = vp->length;
-  unsigned char plain[1 + MAX_STRING_LEN], *ppos = plain, *res;
-  const unsigned char *pos;
-  size_t left, plen;
-  unsigned char hash[MD5_DIGEST_LENGTH];
-  int i, first = 1;
-  const unsigned char *addr[3];
-  struct rs_connection *conn;
-
-  assert (request);
-  assert (request->conn);
-  conn = request->conn;
-
-  if (vp->type != PW_TYPE_OCTETS)
-    return rs_err_conn_push_fl (conn, RSE_BADAUTH, __FILE__, __LINE__, NULL);
-
-  pos = key + 2;
-  left = len - 2;
-  if (left % 16)
-    return rs_err_conn_push_fl (conn, RSE_BADAUTH, __FILE__, __LINE__, NULL);
-
-  plen = left;
-  if (plen > MAX_STRING_LEN)
-    return rs_err_conn_push_fl (conn, RSE_BADAUTH, __FILE__, __LINE__, NULL);
-
-  plain[0] = 0;
-
-  while (left)
-    {
-      MD5_CTX md5;
-
-      MD5_Init (&md5);
-      MD5_Update (&md5, conn->active_peer->secret,
-                 strlen (conn->active_peer->secret));
-      if (first)
-       {
-         MD5_Update (&md5, request->req->rpkt->vector, MD5_DIGEST_LENGTH);
-         MD5_Update (&md5, key, 2);
-         first = 0;
-       }
-      else
-       {
-         MD5_Update (&md5, pos - MD5_DIGEST_LENGTH, MD5_DIGEST_LENGTH);
-       }
-      MD5_Final (hash, &md5);
-
-      for (i = 0; i < MD5_DIGEST_LENGTH; i++)
-       *ppos++ = *pos++ ^ hash[i];
-      left -= MD5_DIGEST_LENGTH;
-    }
-
-  if (plain[0] == 0 || plain[0] > plen - 1)
-    return rs_err_conn_push_fl (conn, RSE_NOMEM, __FILE__, __LINE__, NULL);
-
-  memcpy (vp->vp_octets, plain + 1, plain[0]);
-  vp->length = plain[0];
-
-  return RSE_OK;
-}