Author: mav
Date: Fri Sep 11 11:42:56 2009
New Revision: 197086
URL: http://svn.freebsd.org/changeset/base/197086

Log:
  Add simple embedded RADIUS server support to libradius, by extending existing
  API, keeping backward compatibility.
  
  First consumer for this functionality is going to become forthcoming MPD-5.4,
  supporting CoA and DR of RFC 3576: Dynamic Authorization Extensions to RADIUS.
  
  MFC after:    1 month

Modified:
  head/lib/libradius/libradius.3
  head/lib/libradius/radlib.c
  head/lib/libradius/radlib.h
  head/lib/libradius/radlib_private.h

Modified: head/lib/libradius/libradius.3
==============================================================================
--- head/lib/libradius/libradius.3      Fri Sep 11 02:07:24 2009        
(r197085)
+++ head/lib/libradius/libradius.3      Fri Sep 11 11:42:56 2009        
(r197086)
@@ -1,4 +1,5 @@
 .\" Copyright 1998 Juniper Networks, Inc.
+.\" Copyright 2009 Alexander Motin <m...@freebsd.org>.
 .\" All rights reserved.
 .\"
 .\" Redistribution and use in source and binary forms, with or without
@@ -24,12 +25,12 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd April 27, 2004
+.Dd August 5, 2009
 .Dt LIBRADIUS 3
 .Os
 .Sh NAME
 .Nm libradius
-.Nd RADIUS client library
+.Nd RADIUS client/server library
 .Sh SYNOPSIS
 .In radlib.h
 .Ft "struct rad_handle *"
@@ -46,6 +47,8 @@
 .Fn rad_continue_send_request "struct rad_handle *h" "int selected" "int *fd" 
"struct timeval *tv"
 .Ft int
 .Fn rad_create_request "struct rad_handle *h" "int code"
+.Ft int
+.Fn rad_create_response "struct rad_handle *h" "int code"
 .Ft "struct in_addr"
 .Fn rad_cvt_addr "const void *data"
 .Ft u_int32_t
@@ -79,7 +82,13 @@
 .Ft ssize_t
 .Fn rad_request_authenticator "struct rad_handle *h" "char *buf" "size_t len"
 .Ft int
+.Fn rad_receive_request "struct rad_handle *h"
+.Ft int
 .Fn rad_send_request "struct rad_handle *h"
+.Ft int
+.Fn rad_send_response "struct rad_handle *h"
+.Ft "struct rad_handle *"
+.Fn rad_server_open "int fd"
 .Ft "const char *"
 .Fn rad_server_secret "struct rad_handle *h"
 .Ft u_char *
@@ -91,16 +100,17 @@
 .Sh DESCRIPTION
 The
 .Nm
-library implements the client side of the Remote Authentication Dial
-In User Service (RADIUS).
+library implements the Remote Authentication Dial In User Service (RADIUS).
 RADIUS, defined in RFCs 2865 and 2866,
 allows clients to perform authentication and accounting by means of
 network requests to remote servers.
 .Ss Initialization
 To use the library, an application must first call
 .Fn rad_auth_open
-or
+,
 .Fn rad_acct_open
+or
+.Fn rad_server_open
 to obtain a
 .Vt "struct rad_handle *" ,
 which provides the context for subsequent operations.
@@ -108,8 +118,10 @@ The former function is used for RADIUS a
 latter is used for RADIUS accounting.
 Calls to
 .Fn rad_auth_open
-and
+,
 .Fn rad_acct_open
+and
+.Fn rad_server_open
 always succeed unless insufficient virtual memory is available.
 If
 the necessary memory cannot be allocated, the functions return
@@ -451,6 +463,25 @@ subsequent library calls using the same 
 .Ss Cleanup
 To free the resources used by the RADIUS library, call
 .Fn rad_close .
+.Ss Server operation
+Server mode operates much alike to client mode, except packet send and receieve
+steps are swapped. To operate as server you should obtain server context with
+.Fn rad_server_open
+function, passing opened and bound UDP socket file descriptor as argument.
+You should define allowed clients and their secrets using
+.Fn rad_add_server
+function. port, timeout and max_tries arguments are ignored in server mode.
+You should call
+.Fn rad_receive_request
+function to receive request from client. If you do not want to block on socket
+read, you are free to use any poll(), select() or non-blocking sockets for
+the socket.
+Received request can be parsed with same parsing functions as for client.
+To respond to the request you should call
+.Fn rad_create_response
+and fill response content with same packet writing functions as for client.
+When packet is ready, it should be sent with
+.Fn rad_send_response
 .Sh RETURN VALUES
 The following functions return a non-negative value on success.
 If
@@ -466,6 +497,8 @@ which can be retrieved using
 .It
 .Fn rad_create_request
 .It
+.Fn rad_create_response
+.It
 .Fn rad_get_attr
 .It
 .Fn rad_put_addr
@@ -483,6 +516,8 @@ which can be retrieved using
 .Fn rad_continue_send_request
 .It
 .Fn rad_send_request
+.It
+.Fn rad_send_response
 .El
 .Pp
 The following functions return a
@@ -499,6 +534,8 @@ without recording an error message.
 .It
 .Fn rad_auth_open
 .It
+.Fn rad_server_open
+.It
 .Fn rad_cvt_string
 .El
 .Pp
@@ -553,3 +590,5 @@ subsequently added the ability to perfor
 accounting.
 Later additions and changes by
 .An Michael Bretterklieber .
+Server mode support was added by
+.An Alexander Motin .

Modified: head/lib/libradius/radlib.c
==============================================================================
--- head/lib/libradius/radlib.c Fri Sep 11 02:07:24 2009        (r197085)
+++ head/lib/libradius/radlib.c Fri Sep 11 11:42:56 2009        (r197086)
@@ -103,7 +103,7 @@ insert_scrambled_password(struct rad_han
        srvp = &h->servers[srv];
        padded_len = h->pass_len == 0 ? 16 : (h->pass_len+15) & ~0xf;
 
-       memcpy(md5, &h->request[POS_AUTH], LEN_AUTH);
+       memcpy(md5, &h->out[POS_AUTH], LEN_AUTH);
        for (pos = 0;  pos < padded_len;  pos += 16) {
                int i;
 
@@ -120,49 +120,55 @@ insert_scrambled_password(struct rad_han
                 * in calculating the scrambler for next time.
                 */
                for (i = 0;  i < 16;  i++)
-                       h->request[h->pass_pos + pos + i] =
+                       h->out[h->pass_pos + pos + i] =
                            md5[i] ^= h->pass[pos + i];
        }
 }
 
 static void
-insert_request_authenticator(struct rad_handle *h, int srv)
+insert_request_authenticator(struct rad_handle *h, int resp)
 {
        MD5_CTX ctx;
        const struct rad_server *srvp;
 
-       srvp = &h->servers[srv];
+       srvp = &h->servers[h->srv];
 
        /* Create the request authenticator */
        MD5Init(&ctx);
-       MD5Update(&ctx, &h->request[POS_CODE], POS_AUTH - POS_CODE);
-       MD5Update(&ctx, memset(&h->request[POS_AUTH], 0, LEN_AUTH), LEN_AUTH);
-       MD5Update(&ctx, &h->request[POS_ATTRS], h->req_len - POS_ATTRS);
+       MD5Update(&ctx, &h->out[POS_CODE], POS_AUTH - POS_CODE);
+       if (resp)
+           MD5Update(&ctx, &h->in[POS_AUTH], LEN_AUTH);
+       else
+           MD5Update(&ctx, &h->out[POS_AUTH], LEN_AUTH);
+       MD5Update(&ctx, &h->out[POS_ATTRS], h->out_len - POS_ATTRS);
        MD5Update(&ctx, srvp->secret, strlen(srvp->secret));
-       MD5Final(&h->request[POS_AUTH], &ctx);
+       MD5Final(&h->out[POS_AUTH], &ctx);
 }
 
 static void
-insert_message_authenticator(struct rad_handle *h, int srv)
+insert_message_authenticator(struct rad_handle *h, int resp)
 {
 #ifdef WITH_SSL
        u_char md[EVP_MAX_MD_SIZE];
        u_int md_len;
        const struct rad_server *srvp;
        HMAC_CTX ctx;
-       srvp = &h->servers[srv];
+       srvp = &h->servers[h->srv];
 
        if (h->authentic_pos != 0) {
                HMAC_CTX_init(&ctx);
                HMAC_Init(&ctx, srvp->secret, strlen(srvp->secret), EVP_md5());
-               HMAC_Update(&ctx, &h->request[POS_CODE], POS_AUTH - POS_CODE);
-               HMAC_Update(&ctx, &h->request[POS_AUTH], LEN_AUTH);
-               HMAC_Update(&ctx, &h->request[POS_ATTRS],
-                   h->req_len - POS_ATTRS);
+               HMAC_Update(&ctx, &h->out[POS_CODE], POS_AUTH - POS_CODE);
+               if (resp)
+                   HMAC_Update(&ctx, &h->in[POS_AUTH], LEN_AUTH);
+               else
+                   HMAC_Update(&ctx, &h->out[POS_AUTH], LEN_AUTH);
+               HMAC_Update(&ctx, &h->out[POS_ATTRS],
+                   h->out_len - POS_ATTRS);
                HMAC_Final(&ctx, md, &md_len);
                HMAC_CTX_cleanup(&ctx);
                HMAC_cleanup(&ctx);
-               memcpy(&h->request[h->authentic_pos + 2], md, md_len);
+               memcpy(&h->out[h->authentic_pos + 2], md, md_len);
        }
 #endif
 }
@@ -195,20 +201,20 @@ is_valid_response(struct rad_handle *h, 
                return 0;
 
        /* Check the message length */
-       if (h->resp_len < POS_ATTRS)
+       if (h->in_len < POS_ATTRS)
                return 0;
-       len = h->response[POS_LENGTH] << 8 | h->response[POS_LENGTH+1];
-       if (len > h->resp_len)
+       len = h->in[POS_LENGTH] << 8 | h->in[POS_LENGTH+1];
+       if (len > h->in_len)
                return 0;
 
        /* Check the response authenticator */
        MD5Init(&ctx);
-       MD5Update(&ctx, &h->response[POS_CODE], POS_AUTH - POS_CODE);
-       MD5Update(&ctx, &h->request[POS_AUTH], LEN_AUTH);
-       MD5Update(&ctx, &h->response[POS_ATTRS], len - POS_ATTRS);
+       MD5Update(&ctx, &h->in[POS_CODE], POS_AUTH - POS_CODE);
+       MD5Update(&ctx, &h->out[POS_AUTH], LEN_AUTH);
+       MD5Update(&ctx, &h->in[POS_ATTRS], len - POS_ATTRS);
        MD5Update(&ctx, srvp->secret, strlen(srvp->secret));
        MD5Final(md5, &ctx);
-       if (memcmp(&h->response[POS_AUTH], md5, sizeof md5) != 0)
+       if (memcmp(&h->in[POS_AUTH], md5, sizeof md5) != 0)
                return 0;
 
 #ifdef WITH_SSL
@@ -216,42 +222,111 @@ is_valid_response(struct rad_handle *h, 
         * For non accounting responses check the message authenticator,
         * if any.
         */
-       if (h->response[POS_CODE] != RAD_ACCOUNTING_RESPONSE) {
+       if (h->in[POS_CODE] != RAD_ACCOUNTING_RESPONSE) {
 
-               memcpy(resp, h->response, MSGSIZE);
+               memcpy(resp, h->in, MSGSIZE);
                pos = POS_ATTRS;
 
                /* Search and verify the Message-Authenticator */
                while (pos < len - 2) {
 
-                       if (h->response[pos] == RAD_MESSAGE_AUTHENTIC) {
+                       if (h->in[pos] == RAD_MESSAGE_AUTHENTIC) {
                                /* zero fill the Message-Authenticator */
                                memset(&resp[pos + 2], 0, MD5_DIGEST_LENGTH);
 
                                HMAC_CTX_init(&hctx);
                                HMAC_Init(&hctx, srvp->secret,
                                    strlen(srvp->secret), EVP_md5());
-                               HMAC_Update(&hctx, &h->response[POS_CODE],
+                               HMAC_Update(&hctx, &h->in[POS_CODE],
                                    POS_AUTH - POS_CODE);
-                               HMAC_Update(&hctx, &h->request[POS_AUTH],
+                               HMAC_Update(&hctx, &h->out[POS_AUTH],
                                    LEN_AUTH);
                                HMAC_Update(&hctx, &resp[POS_ATTRS],
-                                   h->resp_len - POS_ATTRS);
+                                   h->in_len - POS_ATTRS);
                                HMAC_Final(&hctx, md, &md_len);
                                HMAC_CTX_cleanup(&hctx);
                                HMAC_cleanup(&hctx);
-                               if (memcmp(md, &h->response[pos + 2],
+                               if (memcmp(md, &h->in[pos + 2],
                                    MD5_DIGEST_LENGTH) != 0)
                                        return 0;
                                break;
                        }
-                       pos += h->response[pos + 1];
+                       pos += h->in[pos + 1];
                }
        }
 #endif
        return 1;
 }
 
+/*
+ * Return true if the current request is valid for the specified server.
+ */
+static int
+is_valid_request(struct rad_handle *h)
+{
+       MD5_CTX ctx;
+       unsigned char md5[MD5_DIGEST_LENGTH];
+       const struct rad_server *srvp;
+       int len;
+#ifdef WITH_SSL
+       HMAC_CTX hctx;
+       u_char resp[MSGSIZE], md[EVP_MAX_MD_SIZE];
+       u_int md_len;
+       int pos;
+#endif
+
+       srvp = &h->servers[h->srv];
+
+       /* Check the message length */
+       if (h->in_len < POS_ATTRS)
+               return (0);
+       len = h->in[POS_LENGTH] << 8 | h->in[POS_LENGTH+1];
+       if (len > h->in_len)
+               return (0);
+
+       if (h->in[POS_CODE] != RAD_ACCESS_REQUEST) {
+               uint32_t zeroes[4] = { 0, 0, 0, 0 };
+               /* Check the request authenticator */
+               MD5Init(&ctx);
+               MD5Update(&ctx, &h->in[POS_CODE], POS_AUTH - POS_CODE);
+               MD5Update(&ctx, zeroes, LEN_AUTH);
+               MD5Update(&ctx, &h->in[POS_ATTRS], len - POS_ATTRS);
+               MD5Update(&ctx, srvp->secret, strlen(srvp->secret));
+               MD5Final(md5, &ctx);
+               if (memcmp(&h->in[POS_AUTH], md5, sizeof md5) != 0)
+                       return (0);
+       }
+
+#ifdef WITH_SSL
+       /* Search and verify the Message-Authenticator */
+       pos = POS_ATTRS;
+       while (pos < len - 2) {
+               if (h->in[pos] == RAD_MESSAGE_AUTHENTIC) {
+                       memcpy(resp, h->in, MSGSIZE);
+                       /* zero fill the Request-Authenticator */
+                       if (h->in[POS_CODE] != RAD_ACCESS_REQUEST)
+                               memset(&resp[POS_AUTH], 0, LEN_AUTH);
+                       /* zero fill the Message-Authenticator */
+                       memset(&resp[pos + 2], 0, MD5_DIGEST_LENGTH);
+
+                       HMAC_CTX_init(&hctx);
+                       HMAC_Init(&hctx, srvp->secret,
+                           strlen(srvp->secret), EVP_md5());
+                       HMAC_Update(&hctx, resp, h->in_len);
+                       HMAC_Final(&hctx, md, &md_len);
+                       HMAC_CTX_cleanup(&hctx);
+                       HMAC_cleanup(&hctx);
+                       if (memcmp(md, &h->in[pos + 2],
+                           MD5_DIGEST_LENGTH) != 0)
+                               return (0);
+                       break;
+               }
+               pos += h->in[pos + 1];
+       }
+#endif
+       return (1);
+}
+
 static int
 put_password_attr(struct rad_handle *h, int type, const void *value, size_t 
len)
 {
@@ -273,7 +348,7 @@ put_password_attr(struct rad_handle *h, 
         */
        clear_password(h);
        put_raw_attr(h, type, h->pass, padded_len);
-       h->pass_pos = h->req_len - padded_len;
+       h->pass_pos = h->out_len - padded_len;
 
        /* Save the cleartext password, padded as necessary */
        memcpy(h->pass, value, len);
@@ -289,14 +364,14 @@ put_raw_attr(struct rad_handle *h, int t
                generr(h, "Attribute too long");
                return -1;
        }
-       if (h->req_len + 2 + len > MSGSIZE) {
+       if (h->out_len + 2 + len > MSGSIZE) {
                generr(h, "Maximum message length exceeded");
                return -1;
        }
-       h->request[h->req_len++] = type;
-       h->request[h->req_len++] = len + 2;
-       memcpy(&h->request[h->req_len], value, len);
-       h->req_len += len;
+       h->out[h->out_len++] = type;
+       h->out[h->out_len++] = len + 2;
+       memcpy(&h->out[h->out_len], value, len);
+       h->out_len += len;
        return 0;
 }
 
@@ -523,22 +598,26 @@ rad_continue_send_request(struct rad_han
 {
        int n;
 
+       if (h->type == RADIUS_SERVER) {
+               generr(h, "denied function call");
+               return (-1);
+       }
        if (selected) {
                struct sockaddr_in from;
                socklen_t fromlen;
 
                fromlen = sizeof from;
-               h->resp_len = recvfrom(h->fd, h->response,
+               h->in_len = recvfrom(h->fd, h->in,
                    MSGSIZE, MSG_WAITALL, (struct sockaddr *)&from, &fromlen);
-               if (h->resp_len == -1) {
+               if (h->in_len == -1) {
                        generr(h, "recvfrom: %s", strerror(errno));
                        return -1;
                }
                if (is_valid_response(h, h->srv, &from)) {
-                       h->resp_len = h->response[POS_LENGTH] << 8 |
-                           h->response[POS_LENGTH+1];
-                       h->resp_pos = POS_ATTRS;
-                       return h->response[POS_CODE];
+                       h->in_len = h->in[POS_LENGTH] << 8 |
+                           h->in[POS_LENGTH+1];
+                       h->in_pos = POS_ATTRS;
+                       return h->in[POS_CODE];
                }
        }
 
@@ -556,21 +635,22 @@ rad_continue_send_request(struct rad_han
                if (++h->srv >= h->num_servers)
                        h->srv = 0;
 
-       if (h->request[POS_CODE] == RAD_ACCOUNTING_REQUEST)
-               /* Insert the request authenticator into the request */
-               insert_request_authenticator(h, h->srv);
-       else
+       if (h->out[POS_CODE] == RAD_ACCESS_REQUEST) {
                /* Insert the scrambled password into the request */
                if (h->pass_pos != 0)
                        insert_scrambled_password(h, h->srv);
-
-       insert_message_authenticator(h, h->srv);
+       }
+       insert_message_authenticator(h, 0);
+       if (h->out[POS_CODE] != RAD_ACCESS_REQUEST) {
+               /* Insert the request authenticator into the request */
+               insert_request_authenticator(h, h->srv);
+       }
 
        /* Send the request */
-       n = sendto(h->fd, h->request, h->req_len, 0,
+       n = sendto(h->fd, h->out, h->out_len, 0,
            (const struct sockaddr *)&h->servers[h->srv].addr,
            sizeof h->servers[h->srv].addr);
-       if (n != h->req_len) {
+       if (n != h->out_len) {
                if (n == -1)
                        generr(h, "sendto: %s", strerror(errno));
                else
@@ -588,22 +668,117 @@ rad_continue_send_request(struct rad_han
 }
 
 int
+rad_receive_request(struct rad_handle *h)
+{
+       struct sockaddr_in from;
+       socklen_t fromlen;
+       int n;
+
+       if (h->type != RADIUS_SERVER) {
+               generr(h, "denied function call");
+               return (-1);
+       }
+       h->srv = -1;
+       fromlen = sizeof(from);
+       h->in_len = recvfrom(h->fd, h->in,
+           MSGSIZE, MSG_WAITALL, (struct sockaddr *)&from, &fromlen);
+       if (h->in_len == -1) {
+               generr(h, "recvfrom: %s", strerror(errno));
+               return (-1);
+       }
+       for (n = 0; n < h->num_servers; n++) {
+               if (h->servers[n].addr.sin_addr.s_addr == from.sin_addr.s_addr) 
{
+                       h->servers[n].addr.sin_port = from.sin_port;
+                       h->srv = n;
+                       break;
+               }
+       }
+       if (h->srv == -1)
+               return (-2);
+       if (is_valid_request(h)) {
+               h->in_len = h->in[POS_LENGTH] << 8 |
+                   h->in[POS_LENGTH+1];
+               h->in_pos = POS_ATTRS;
+               return (h->in[POS_CODE]);
+       }
+       return (-3);
+}
+
+int
+rad_send_response(struct rad_handle *h)
+{
+       int n;
+
+       if (h->type != RADIUS_SERVER) {
+               generr(h, "denied function call");
+               return (-1);
+       }
+       /* Fill in the length field in the message */
+       h->out[POS_LENGTH] = h->out_len >> 8;
+       h->out[POS_LENGTH+1] = h->out_len;
+
+       insert_message_authenticator(h,
+           (h->in[POS_CODE] == RAD_ACCESS_REQUEST) ? 1 : 0);
+       insert_request_authenticator(h, 1);
+
+       /* Send the request */
+       n = sendto(h->fd, h->out, h->out_len, 0,
+           (const struct sockaddr *)&h->servers[h->srv].addr,
+           sizeof h->servers[h->srv].addr);
+       if (n != h->out_len) {
+               if (n == -1)
+                       generr(h, "sendto: %s", strerror(errno));
+               else
+                       generr(h, "sendto: short write");
+               return -1;
+       }
+
+       return 0;
+}
+
+int
 rad_create_request(struct rad_handle *h, int code)
 {
        int i;
 
-       h->request[POS_CODE] = code;
-       h->request[POS_IDENT] = ++h->ident;
-       /* Create a random authenticator */
-       for (i = 0;  i < LEN_AUTH;  i += 2) {
-               long r;
-               r = random();
-               h->request[POS_AUTH+i] = (u_char)r;
-               h->request[POS_AUTH+i+1] = (u_char)(r >> 8);
+       if (h->type == RADIUS_SERVER) {
+               generr(h, "denied function call");
+               return (-1);
+       }
+       h->out[POS_CODE] = code;
+       h->out[POS_IDENT] = ++h->ident;
+       if (code == RAD_ACCESS_REQUEST) {
+               /* Create a random authenticator */
+               for (i = 0;  i < LEN_AUTH;  i += 2) {
+                       long r;
+                       r = random();
+                       h->out[POS_AUTH+i] = (u_char)r;
+                       h->out[POS_AUTH+i+1] = (u_char)(r >> 8);
+               }
+       } else
+               memset(&h->out[POS_AUTH], 0, LEN_AUTH);
+       h->out_len = POS_ATTRS;
+       clear_password(h);
+       h->authentic_pos = 0;
+       h->out_created = 1;
+       return 0;
+}
+
+int
+rad_create_response(struct rad_handle *h, int code)
+{
+
+       if (h->type != RADIUS_SERVER) {
+               generr(h, "denied function call");
+               return (-1);
        }
-       h->req_len = POS_ATTRS;
+       h->out[POS_CODE] = code;
+       h->out[POS_IDENT] = h->in[POS_IDENT];
+       memset(&h->out[POS_AUTH], 0, LEN_AUTH);
+       h->out_len = POS_ATTRS;
        clear_password(h);
-       h->request_created = 1;
+       h->authentic_pos = 0;
+       h->out_created = 1;
        return 0;
 }
 
@@ -647,20 +822,20 @@ rad_get_attr(struct rad_handle *h, const
 {
        int type;
 
-       if (h->resp_pos >= h->resp_len)
+       if (h->in_pos >= h->in_len)
                return 0;
-       if (h->resp_pos + 2 > h->resp_len) {
+       if (h->in_pos + 2 > h->in_len) {
                generr(h, "Malformed attribute in response");
                return -1;
        }
-       type = h->response[h->resp_pos++];
-       *len = h->response[h->resp_pos++] - 2;
-       if (h->resp_pos + (int)*len > h->resp_len) {
+       type = h->in[h->in_pos++];
+       *len = h->in[h->in_pos++] - 2;
+       if (h->in_pos + (int)*len > h->in_len) {
                generr(h, "Malformed attribute in response");
                return -1;
        }
-       *value = &h->response[h->resp_pos];
-       h->resp_pos += *len;
+       *value = &h->in[h->in_pos];
+       h->in_pos += *len;
        return type;
 }
 
@@ -672,6 +847,10 @@ rad_init_send_request(struct rad_handle 
 {
        int srv;
 
+       if (h->type == RADIUS_SERVER) {
+               generr(h, "denied function call");
+               return (-1);
+       }
        /* Make sure we have a socket to use */
        if (h->fd == -1) {
                struct sockaddr_in sin;
@@ -694,7 +873,7 @@ rad_init_send_request(struct rad_handle 
                }
        }
 
-       if (h->request[POS_CODE] == RAD_ACCOUNTING_REQUEST) {
+       if (h->out[POS_CODE] != RAD_ACCESS_REQUEST) {
                /* Make sure no password given */
                if (h->pass_pos || h->chap_pass) {
                        generr(h, "User or Chap Password"
@@ -718,8 +897,8 @@ rad_init_send_request(struct rad_handle 
        }
 
        /* Fill in the length field in the message */
-       h->request[POS_LENGTH] = h->req_len >> 8;
-       h->request[POS_LENGTH+1] = h->req_len;
+       h->out[POS_LENGTH] = h->out_len >> 8;
+       h->out[POS_LENGTH+1] = h->out_len;
 
        /*
         * Count the total number of tries we will make, and zero the
@@ -763,7 +942,7 @@ rad_auth_open(void)
                h->chap_pass = 0;
                h->authentic_pos = 0;
                h->type = RADIUS_AUTH;
-               h->request_created = 0;
+               h->out_created = 0;
                h->eap_msg = 0;
        }
        return h;
@@ -781,6 +960,19 @@ rad_acct_open(void)
 }
 
 struct rad_handle *
+rad_server_open(int fd)
+{
+       struct rad_handle *h;
+
+       h = rad_open();
+       if (h != NULL) {
+               h->type = RADIUS_SERVER;
+               h->fd = fd;
+       }
+       return h;
+}
+
+struct rad_handle *
 rad_open(void)
 {
     return rad_auth_open();
@@ -797,13 +989,13 @@ rad_put_attr(struct rad_handle *h, int t
 {
        int result;
 
-       if (!h->request_created) {
+       if (!h->out_created) {
                generr(h, "Please call rad_create_request()"
                    " before putting attributes");
                return -1;
        }
 
-       if (h->request[POS_CODE] == RAD_ACCOUNTING_REQUEST) {
+       if (h->out[POS_CODE] == RAD_ACCOUNTING_REQUEST) {
                if (type == RAD_EAP_MESSAGE) {
                        generr(h, "EAP-Message attribute is not valid"
                            " in accounting requests");
@@ -858,14 +1050,14 @@ rad_put_message_authentic(struct rad_han
 #ifdef WITH_SSL
        u_char md_zero[MD5_DIGEST_LENGTH];
 
-       if (h->request[POS_CODE] == RAD_ACCOUNTING_REQUEST) {
+       if (h->out[POS_CODE] == RAD_ACCOUNTING_REQUEST) {
                generr(h, "Message-Authenticator is not valid"
                    " in accounting requests");
                return -1;
        }
 
        if (h->authentic_pos == 0) {
-               h->authentic_pos = h->req_len;
+               h->authentic_pos = h->out_len;
                memset(md_zero, 0, sizeof(md_zero));
                return (put_raw_attr(h, RAD_MESSAGE_AUTHENTIC, md_zero,
                    sizeof(md_zero)));
@@ -1041,7 +1233,7 @@ rad_put_vendor_attr(struct rad_handle *h
        struct vendor_attribute *attr;
        int res;
 
-       if (!h->request_created) {
+       if (!h->out_created) {
                generr(h, "Please call rad_create_request()"
                    " before putting attributes");
                return -1;
@@ -1088,7 +1280,7 @@ rad_request_authenticator(struct rad_han
 {
        if (len < LEN_AUTH)
                return (-1);
-       memcpy(buf, h->request + POS_AUTH, LEN_AUTH);
+       memcpy(buf, h->out + POS_AUTH, LEN_AUTH);
        if (len > LEN_AUTH)
                buf[LEN_AUTH] = '\0';
        return (LEN_AUTH);

Modified: head/lib/libradius/radlib.h
==============================================================================
--- head/lib/libradius/radlib.h Fri Sep 11 02:07:24 2009        (r197085)
+++ head/lib/libradius/radlib.h Fri Sep 11 11:42:56 2009        (r197086)
@@ -42,6 +42,12 @@
 #define RAD_ACCOUNTING_REQUEST         4
 #define RAD_ACCOUNTING_RESPONSE                5
 #define RAD_ACCESS_CHALLENGE           11
+#define RAD_DISCONNECT_REQUEST         40
+#define RAD_DISCONNECT_ACK             41
+#define RAD_DISCONNECT_NAK             42
+#define RAD_COA_REQUEST                        43
+#define RAD_COA_ACK                    44
+#define RAD_COA_NAK                    45
 
 /* Attribute types and values */
 #define RAD_USER_NAME                  1       /* String */
@@ -179,6 +185,8 @@
 #define        RAD_ACCT_MULTI_SESSION_ID       50      /* String */
 #define        RAD_ACCT_LINK_COUNT             51      /* Integer */
 
+#define        RAD_ERROR_CAUSE                 101     /* Integer */
+
 struct rad_handle;
 struct timeval;
 
@@ -192,6 +200,7 @@ int                  rad_config(struct rad_handle *, c
 int                     rad_continue_send_request(struct rad_handle *, int,
                            int *, struct timeval *);
 int                     rad_create_request(struct rad_handle *, int);
+int                     rad_create_response(struct rad_handle *, int);
 struct in_addr          rad_cvt_addr(const void *);
 u_int32_t               rad_cvt_int(const void *);
 char                   *rad_cvt_string(const void *, size_t);
@@ -209,7 +218,10 @@ int                         rad_put_string(struct 
rad_handle 
 int                     rad_put_message_authentic(struct rad_handle *);
 ssize_t                         rad_request_authenticator(struct rad_handle *, 
char *,
                            size_t);
+int                     rad_receive_request(struct rad_handle *);
 int                     rad_send_request(struct rad_handle *);
+int                     rad_send_response(struct rad_handle *);
+struct rad_handle      *rad_server_open(int fd);
 const char             *rad_server_secret(struct rad_handle *);
 const char             *rad_strerror(struct rad_handle *);
 u_char                 *rad_demangle(struct rad_handle *, const void *,

Modified: head/lib/libradius/radlib_private.h
==============================================================================
--- head/lib/libradius/radlib_private.h Fri Sep 11 02:07:24 2009        
(r197085)
+++ head/lib/libradius/radlib_private.h Fri Sep 11 11:42:56 2009        
(r197086)
@@ -38,6 +38,7 @@
 /* Handle types */
 #define RADIUS_AUTH            0   /* RADIUS authentication, default */
 #define RADIUS_ACCT            1   /* RADIUS accounting */
+#define RADIUS_SERVER          2   /* RADIUS server */
 
 /* Defaults */
 #define MAXTRIES               3
@@ -75,18 +76,18 @@ struct rad_handle {
        int              num_servers;   /* Number of valid server entries */
        int              ident;         /* Current identifier value */
        char             errmsg[ERRSIZE];       /* Most recent error message */
-       unsigned char    request[MSGSIZE];      /* Request to send */
-       char             request_created; /* rad_create_request() called? */
-       int              req_len;       /* Length of request */
+       unsigned char    out[MSGSIZE];  /* Request to send */
+       char             out_created;   /* rad_create_request() called? */
+       int              out_len;       /* Length of request */
        char             pass[PASSSIZE];        /* Cleartext password */
        int              pass_len;      /* Length of cleartext password */
        int              pass_pos;      /* Position of scrambled password */
-       char             chap_pass;     /* Have we got a CHAP_PASSWORD ? */
+       char             chap_pass;     /* Have we got a CHAP_PASSWORD ? */
        int              authentic_pos; /* Position of message authenticator */
        char             eap_msg;       /* Are we an EAP Proxy? */
-       unsigned char    response[MSGSIZE];     /* Response received */
-       int              resp_len;      /* Length of response */
-       int              resp_pos;      /* Current position scanning attrs */
+       unsigned char    in[MSGSIZE];   /* Response received */
+       int              in_len;        /* Length of response */
+       int              in_pos;        /* Current position scanning attrs */
        int              total_tries;   /* How many requests we'll send */
        int              try;           /* How many requests we've sent */
        int              srv;           /* Server number we did last */
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to