X-Git-Url: http://www.project-moonshot.org/gitweb/?a=blobdiff_plain;f=lib%2Fpacket.c;h=a0b3eb2e9ae496f61988e942477e1ae2ee2f21a3;hb=fed9094cd8cda69605d0c103acd14308379b6eb0;hp=68adf2b269069d36d4cd126060e1766d5a98c8a2;hpb=e981fbcf3909fbaba462c7b578f29fa67b3bc74b;p=radsecproxy.git diff --git a/lib/packet.c b/lib/packet.c index 68adf2b..a0b3eb2 100644 --- a/lib/packet.c +++ b/lib/packet.c @@ -1,33 +1,156 @@ -#include +/* Copyright 2010-2013 NORDUnet A/S. All rights reserved. + See LICENSE for licensing information. */ + +#if defined HAVE_CONFIG_H +#include +#endif + +#include #include -#include -#include "libradsec.h" -#include "libradsec-impl.h" -#if defined DEBUG +#include +#include +#include +#include +#include "conn.h" #include "debug.h" +#include "packet.h" + +#if defined (DEBUG) +#include +#include +#include #endif int -_packet_create (struct rs_connection *conn, struct rs_packet **pkt_out, - int code) +packet_verify_response (struct rs_connection *conn, + struct rs_packet *response, + struct rs_packet *request) +{ + int err; + + assert (conn); + assert (conn->active_peer); + assert (conn->active_peer->secret); + assert (response); + assert (response->rpkt); + assert (request); + assert (request->rpkt); + + response->rpkt->secret = conn->active_peer->secret; + response->rpkt->sizeof_secret = strlen (conn->active_peer->secret); + + /* Verify header and message authenticator. */ + err = nr_packet_verify (response->rpkt, request->rpkt); + if (err) + { + if (conn->is_connected) + rs_conn_disconnect(conn); + return rs_err_conn_push_fl (conn, -err, __FILE__, __LINE__, + "nr_packet_verify"); + } + + /* Decode and decrypt. */ + err = nr_packet_decode (response->rpkt, request->rpkt); + if (err) + { + if (conn->is_connected) + rs_conn_disconnect(conn); + return rs_err_conn_push_fl (conn, -err, __FILE__, __LINE__, + "nr_packet_decode"); + } + + return RSE_OK; +} + + +/* Badly named function for preparing a RADIUS message and queue it. + FIXME: Rename. */ +int +packet_do_send (struct rs_packet *pkt) +{ + int err; + + assert (pkt); + assert (pkt->conn); + assert (pkt->conn->active_peer); + assert (pkt->conn->active_peer->secret); + assert (pkt->rpkt); + + pkt->rpkt->secret = pkt->conn->active_peer->secret; + pkt->rpkt->sizeof_secret = strlen (pkt->rpkt->secret); + + /* Encode message. */ + err = nr_packet_encode (pkt->rpkt, NULL); + if (err < 0) + return rs_err_conn_push_fl (pkt->conn, -err, __FILE__, __LINE__, + "nr_packet_encode"); + /* Sign message. */ + err = nr_packet_sign (pkt->rpkt, NULL); + if (err < 0) + return rs_err_conn_push_fl (pkt->conn, -err, __FILE__, __LINE__, + "nr_packet_sign"); +#if defined (DEBUG) + { + char host[80], serv[80]; + + getnameinfo (pkt->conn->active_peer->addr_cache->ai_addr, + pkt->conn->active_peer->addr_cache->ai_addrlen, + host, sizeof(host), serv, sizeof(serv), + 0 /* NI_NUMERICHOST|NI_NUMERICSERV*/); + rs_debug (("%s: about to send this to %s:%s:\n", __func__, host, serv)); + rs_dump_packet (pkt); + } +#endif + + /* Put message in output buffer. */ + if (pkt->conn->bev) /* TCP. */ + { + int err = bufferevent_write (pkt->conn->bev, pkt->rpkt->data, + pkt->rpkt->length); + if (err < 0) + return rs_err_conn_push_fl (pkt->conn, RSE_EVENT, __FILE__, __LINE__, + "bufferevent_write: %s", + evutil_gai_strerror (err)); + } + else /* UDP. */ + { + struct rs_packet **pp = &pkt->conn->out_queue; + + while (*pp && (*pp)->next) + *pp = (*pp)->next; + *pp = pkt; + } + + return RSE_OK; +} + +/* Public functions. */ +int +rs_packet_create (struct rs_connection *conn, struct rs_packet **pkt_out) { struct rs_packet *p; RADIUS_PACKET *rpkt; + int err; *pkt_out = NULL; - rpkt = rad_alloc (1); - if (!rpkt) - return rs_conn_err_push (conn, RSE_NOMEM, __func__); - rpkt->id = -1; - rpkt->code = code; + rpkt = rs_malloc (conn->ctx, sizeof(*rpkt) + RS_MAX_PACKET_LEN); + if (rpkt == NULL) + return rs_err_conn_push (conn, RSE_NOMEM, __func__); - p = (struct rs_packet *) malloc (sizeof (struct rs_packet)); - if (!p) { - rad_free (&rpkt); - return rs_conn_err_push (conn, RSE_NOMEM, __func__); - } - memset (p, 0, sizeof (struct rs_packet)); + err = nr_packet_init (rpkt, NULL, NULL, + PW_ACCESS_REQUEST, + rpkt + 1, RS_MAX_PACKET_LEN); + if (err < 0) + return rs_err_conn_push (conn, -err, __func__); + + p = (struct rs_packet *) rs_calloc (conn->ctx, 1, sizeof (*p)); + if (p == NULL) + { + rs_free (conn->ctx, rpkt); + return rs_err_conn_push (conn, RSE_NOMEM, __func__); + } + p->conn = conn; p->rpkt = rpkt; *pkt_out = p; @@ -35,58 +158,96 @@ _packet_create (struct rs_connection *conn, struct rs_packet **pkt_out, } int -rs_packet_create_acc_request (struct rs_connection *conn, - struct rs_packet **pkt_out, - const char *user_name, const char *user_pw) +rs_packet_create_authn_request (struct rs_connection *conn, + struct rs_packet **pkt_out, + const char *user_name, const char *user_pw) { struct rs_packet *pkt; - struct rs_attr *attr; + int err; - if (_packet_create (conn, pkt_out, PW_AUTHENTICATION_REQUEST)) + if (rs_packet_create (conn, pkt_out)) return -1; + pkt = *pkt_out; + pkt->rpkt->code = PW_ACCESS_REQUEST; - if (rs_attr_create (conn, &attr, "User-Name", user_name)) - return -1; - rs_packet_add_attr (pkt, attr); + if (user_name) + { + err = rs_packet_append_avp (pkt, PW_USER_NAME, 0, user_name, 0); + if (err) + return err; + } - if (rs_attr_create (conn, &attr, "User-Password", user_name)) - return -1; - /* FIXME: need this too? rad_pwencode(user_pw, &pwlen, SECRET, reqauth) */ - rs_packet_add_attr (pkt, attr); + if (user_pw) + { + err = rs_packet_append_avp (pkt, PW_USER_PASSWORD, 0, user_pw, 0); + if (err) + return err; + } return RSE_OK; } +void +rs_packet_destroy (struct rs_packet *pkt) +{ + assert (pkt); + assert (pkt->conn); + assert (pkt->conn->ctx); + + rs_avp_free (&pkt->rpkt->vps); + rs_free (pkt->conn->ctx, pkt->rpkt); + rs_free (pkt->conn->ctx, pkt); +} + int -rs_packet_send (struct rs_connection *conn, const struct rs_packet *pkt, - void *user_data) +rs_packet_append_avp (struct rs_packet *pkt, + unsigned int attr, unsigned int vendor, + const void *data, size_t data_len) { - assert (pkt->rpkt); + const DICT_ATTR *da; + int err; - if (!conn->active_peer) - { - int err = rs_conn_open (conn); - if (err) - return err; - } - rad_encode (pkt->rpkt, NULL, conn->active_peer->secret); -#if defined (DEBUG) - fprintf (stderr, "%s: about to send this to %s", __func__, "fixme"); - rs_dump_packet (pkt); -#endif + assert (pkt); + + da = nr_dict_attr_byvalue (attr, vendor); + if (da == NULL) + return rs_err_conn_push (pkt->conn, RSE_ATTR_TYPE_UNKNOWN, __func__); - return RSE_NOSYS; + err = nr_packet_attr_append (pkt->rpkt, NULL, da, data, data_len); + if (err < 0) + return rs_err_conn_push (pkt->conn, -err, __func__); + + return RSE_OK; } -int rs_packet_receive(struct rs_connection *conn, struct rs_packet **pkt) +void +rs_packet_avps (struct rs_packet *pkt, rs_avp ***vps) { - return RSE_NOSYS; + assert (pkt); + *vps = &pkt->rpkt->vps; } -void -rs_packet_add_attr(struct rs_packet *pkt, struct rs_attr *attr) +unsigned int +rs_packet_code (struct rs_packet *pkt) { - pairadd (&pkt->rpkt->vps, attr->vp); - attr->pkt = pkt; + assert (pkt); + return pkt->rpkt->code; +} + +rs_const_avp * +rs_packet_find_avp (struct rs_packet *pkt, unsigned int attr, unsigned int vendor) +{ + assert (pkt); + return rs_avp_find_const (pkt->rpkt->vps, attr, vendor); +} + +int +rs_packet_set_id (struct rs_packet *pkt, int id) +{ + int old = pkt->rpkt->id; + + pkt->rpkt->id = id; + + return old; }