From owner-svn-src-stable@FreeBSD.ORG Fri Oct 30 12:59:23 2009 Return-Path: Delivered-To: svn-src-stable@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 409B5106568B; Fri, 30 Oct 2009 12:59:23 +0000 (UTC) (envelope-from mav@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 2D8A28FC13; Fri, 30 Oct 2009 12:59:23 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id n9UCxNh4044975; Fri, 30 Oct 2009 12:59:23 GMT (envelope-from mav@svn.freebsd.org) Received: (from mav@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id n9UCxNIs044970; Fri, 30 Oct 2009 12:59:23 GMT (envelope-from mav@svn.freebsd.org) Message-Id: <200910301259.n9UCxNIs044970@svn.freebsd.org> From: Alexander Motin Date: Fri, 30 Oct 2009 12:59:23 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-7@freebsd.org X-SVN-Group: stable-7 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r198673 - stable/7/lib/libradius X-BeenThere: svn-src-stable@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for all the -stable branches of the src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 30 Oct 2009 12:59:23 -0000 Author: mav Date: Fri Oct 30 12:59:22 2009 New Revision: 198673 URL: http://svn.freebsd.org/changeset/base/198673 Log: MFC rev. 197086: 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. Modified: stable/7/lib/libradius/ (props changed) stable/7/lib/libradius/libradius.3 stable/7/lib/libradius/radlib.c stable/7/lib/libradius/radlib.h stable/7/lib/libradius/radlib_private.h Modified: stable/7/lib/libradius/libradius.3 ============================================================================== --- stable/7/lib/libradius/libradius.3 Fri Oct 30 12:57:28 2009 (r198672) +++ stable/7/lib/libradius/libradius.3 Fri Oct 30 12:59:22 2009 (r198673) @@ -1,4 +1,5 @@ .\" Copyright 1998 Juniper Networks, Inc. +.\" Copyright 2009 Alexander Motin . .\" 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: stable/7/lib/libradius/radlib.c ============================================================================== --- stable/7/lib/libradius/radlib.c Fri Oct 30 12:57:28 2009 (r198672) +++ stable/7/lib/libradius/radlib.c Fri Oct 30 12:59:22 2009 (r198673) @@ -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: stable/7/lib/libradius/radlib.h ============================================================================== --- stable/7/lib/libradius/radlib.h Fri Oct 30 12:57:28 2009 (r198672) +++ stable/7/lib/libradius/radlib.h Fri Oct 30 12:59:22 2009 (r198673) @@ -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: stable/7/lib/libradius/radlib_private.h ============================================================================== --- stable/7/lib/libradius/radlib_private.h Fri Oct 30 12:57:28 2009 (r198672) +++ stable/7/lib/libradius/radlib_private.h Fri Oct 30 12:59:22 2009 (r198673) @@ -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 */