From 06936d1f263c456017e20ea6c74d2756e1e30fcc Mon Sep 17 00:00:00 2001 From: Luke Howard Date: Sat, 9 Oct 2010 11:54:37 +0200 Subject: [PATCH] Have rad_decode() verify responses. --- lib/examples/client-blocking.c | 14 +++-- lib/include/radsec/radsec-impl.h | 1 + lib/include/radsec/radsec.h | 1 + lib/include/radsec/request-impl.h | 6 -- lib/packet.c | 41 +++++++++++-- lib/request.c | 126 +------------------------------------- 6 files changed, 49 insertions(+), 140 deletions(-) diff --git a/lib/examples/client-blocking.c b/lib/examples/client-blocking.c index 66f4859..365b3b0 100644 --- a/lib/examples/client-blocking.c +++ b/lib/examples/client-blocking.c @@ -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; diff --git a/lib/include/radsec/radsec-impl.h b/lib/include/radsec/radsec-impl.h index 3ce01d0..6e5ee83 100644 --- a/lib/include/radsec/radsec-impl.h +++ b/lib/include/radsec/radsec-impl.h @@ -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 { diff --git a/lib/include/radsec/radsec.h b/lib/include/radsec/radsec.h index db1e1a7..dd784cc 100644 --- a/lib/include/radsec/radsec.h +++ b/lib/include/radsec/radsec.h @@ -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); diff --git a/lib/include/radsec/request-impl.h b/lib/include/radsec/request-impl.h index 4fa0ca9..339dfea 100644 --- a/lib/include/radsec/request-impl.h +++ b/lib/include/radsec/request-impl.h @@ -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 diff --git a/lib/packet.c b/lib/packet.c index 9abd698..7872a5a 100644 --- a/lib/packet.c +++ b/lib/packet.c @@ -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; } diff --git a/lib/request.c b/lib/request.c index 85278f3..5cb87bb 100644 --- a/lib/request.c +++ b/lib/request.c @@ -8,9 +8,6 @@ #include #include -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 - * - * 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 - -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; -} -- 2.1.4