_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__,
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];
#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 */
}
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;
return -1;
pkt = *pkt_out;
pkt->conn = conn;
+ pkt->original = request;
if (_conn_open (conn, pkt))
return -1;
#endif
}
+ pkt->original = NULL;
+
return RSE_OK;
}
#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)
{
_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
struct rs_packet **resp)
{
int err;
- VALUE_PAIR *vp;
struct rs_connection *conn;
assert (request);
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;
-}