1.\" Copyright 1998 Juniper Networks, Inc. 2.\" Copyright 2009 Alexander Motin <mav@FreeBSD.org>. 3.\" All rights reserved. 4.\" 5.\" Redistribution and use in source and binary forms, with or without 6.\" modification, are permitted provided that the following conditions 7.\" are met: 8.\" 1. Redistributions of source code must retain the above copyright 9.\" notice, this list of conditions and the following disclaimer. 10.\" 2. Redistributions in binary form must reproduce the above copyright 11.\" notice, this list of conditions and the following disclaimer in the 12.\" documentation and/or other materials provided with the distribution. 13.\" 14.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24.\" SUCH DAMAGE. 25.\" 26.\" $FreeBSD$ 27.\" 28.Dd August 5, 2009 29.Dt LIBRADIUS 3 30.Os 31.Sh NAME 32.Nm libradius 33.Nd RADIUS client/server library 34.Sh SYNOPSIS 35.In radlib.h 36.Ft "struct rad_handle *" 37.Fn rad_acct_open "void" 38.Ft int 39.Fn rad_add_server "struct rad_handle *h" "const char *host" "int port" "const char *secret" "int timeout" "int max_tries" 40.Ft "struct rad_handle *" 41.Fn rad_auth_open "void" 42.Ft void 43.Fn rad_close "struct rad_handle *h" 44.Ft int 45.Fn rad_config "struct rad_handle *h" "const char *file" 46.Ft int 47.Fn rad_continue_send_request "struct rad_handle *h" "int selected" "int *fd" "struct timeval *tv" 48.Ft int 49.Fn rad_create_request "struct rad_handle *h" "int code" 50.Ft int 51.Fn rad_create_response "struct rad_handle *h" "int code" 52.Ft "struct in_addr" 53.Fn rad_cvt_addr "const void *data" 54.Ft u_int32_t 55.Fn rad_cvt_int "const void *data" 56.Ft char * 57.Fn rad_cvt_string "const void *data" "size_t len" 58.Ft int 59.Fn rad_get_attr "struct rad_handle *h" "const void **data" "size_t *len" 60.Ft int 61.Fn rad_get_vendor_attr "u_int32_t *vendor" "const void **data" "size_t *len" 62.Ft int 63.Fn rad_init_send_request "struct rad_handle *h" "int *fd" "struct timeval *tv" 64.Ft int 65.Fn rad_put_addr "struct rad_handle *h" "int type" "struct in_addr addr" 66.Ft int 67.Fn rad_put_attr "struct rad_handle *h" "int type" "const void *data" "size_t len" 68.Ft int 69.Fn rad_put_int "struct rad_handle *h" "int type" "u_int32_t value" 70.Ft int 71.Fn rad_put_string "struct rad_handle *h" "int type" "const char *str" 72.Ft int 73.Fn rad_put_message_authentic "struct rad_handle *h" 74.Ft int 75.Fn rad_put_vendor_addr "struct rad_handle *h" "int vendor" "int type" "struct in_addr addr" 76.Ft int 77.Fn rad_put_vendor_attr "struct rad_handle *h" "int vendor" "int type" "const void *data" "size_t len" 78.Ft int 79.Fn rad_put_vendor_int "struct rad_handle *h" "int vendor" "int type" "u_int32_t value" 80.Ft int 81.Fn rad_put_vendor_string "struct rad_handle *h" "int vendor" "int type" "const char *str" 82.Ft ssize_t 83.Fn rad_request_authenticator "struct rad_handle *h" "char *buf" "size_t len" 84.Ft int 85.Fn rad_receive_request "struct rad_handle *h" 86.Ft int 87.Fn rad_send_request "struct rad_handle *h" 88.Ft int 89.Fn rad_send_response "struct rad_handle *h" 90.Ft "struct rad_handle *" 91.Fn rad_server_open "int fd" 92.Ft "const char *" 93.Fn rad_server_secret "struct rad_handle *h" 94.Ft "void" 95.Fn rad_bind_to "struct rad_handle *h" "in_addr_t addr" 96.Ft u_char * 97.Fn rad_demangle "struct rad_handle *h" "const void *mangled" "size_t mlen" 98.Ft u_char * 99.Fn rad_demangle_mppe_key "struct rad_handle *h" "const void *mangled" "size_t mlen" "size_t *len" 100.Ft "const char *" 101.Fn rad_strerror "struct rad_handle *h" 102.Sh DESCRIPTION 103The 104.Nm 105library implements the Remote Authentication Dial In User Service (RADIUS). 106RADIUS, defined in RFCs 2865 and 2866, 107allows clients to perform authentication and accounting by means of 108network requests to remote servers. 109.Ss Initialization 110To use the library, an application must first call 111.Fn rad_auth_open 112, 113.Fn rad_acct_open 114or 115.Fn rad_server_open 116to obtain a 117.Vt "struct rad_handle *" , 118which provides the context for subsequent operations. 119The former function is used for RADIUS authentication and the 120latter is used for RADIUS accounting. 121Calls to 122.Fn rad_auth_open 123, 124.Fn rad_acct_open 125and 126.Fn rad_server_open 127always succeed unless insufficient virtual memory is available. 128If 129the necessary memory cannot be allocated, the functions return 130.Dv NULL . 131For compatibility with earlier versions of this library, 132.Fn rad_open 133is provided as a synonym for 134.Fn rad_auth_open . 135.Pp 136Before issuing any RADIUS requests, the library must be made aware 137of the servers it can contact. 138The easiest way to configure the 139library is to call 140.Fn rad_config . 141.Fn rad_config 142causes the library to read a configuration file whose format is 143described in 144.Xr radius.conf 5 . 145The pathname of the configuration file is passed as the 146.Fa file 147argument to 148.Fn rad_config . 149This argument may also be given as 150.Dv NULL , 151in which case the standard configuration file 152.Pa /etc/radius.conf 153is used. 154.Fn rad_config 155returns 0 on success, or \-1 if an error occurs. 156.Pp 157The library can also be configured programmatically by calls to 158.Fn rad_add_server . 159The 160.Fa host 161parameter specifies the server host, either as a fully qualified 162domain name or as a dotted-quad IP address in text form. 163The 164.Fa port 165parameter specifies the UDP port to contact on the server. 166If 167.Fa port 168is given as 0, the library looks up the 169.Ql radius/udp 170or 171.Ql radacct/udp 172service in the network 173.Xr services 5 174database, and uses the port found 175there. 176If no entry is found, the library uses the standard RADIUS 177ports, 1812 for authentication and 1813 for accounting. 178The shared secret for the server host is passed to the 179.Fa secret 180parameter. 181It may be any 182.Dv NUL Ns -terminated 183string of bytes. 184The RADIUS protocol 185ignores all but the leading 128 bytes of the shared secret. 186The timeout for receiving replies from the server is passed to the 187.Fa timeout 188parameter, in units of seconds. 189The maximum number of repeated 190requests to make before giving up is passed into the 191.Fa max_tries 192parameter. 193.Fn rad_add_server 194returns 0 on success, or \-1 if an error occurs. 195.Pp 196.Fn rad_add_server 197may be called multiple times, and it may be used together with 198.Fn rad_config . 199At most 10 servers may be specified. 200When multiple servers are given, they are tried in round-robin 201fashion until a valid response is received, or until each server's 202.Fa max_tries 203limit has been reached. 204.Ss Creating a RADIUS Request 205A RADIUS request consists of a code specifying the kind of request, 206and zero or more attributes which provide additional information. 207To 208begin constructing a new request, call 209.Fn rad_create_request . 210In addition to the usual 211.Vt "struct rad_handle *" , 212this function takes a 213.Fa code 214parameter which specifies the type of the request. 215Most often this 216will be 217.Dv RAD_ACCESS_REQUEST . 218.Fn rad_create_request 219returns 0 on success, or \-1 on if an error occurs. 220.Pp 221After the request has been created with 222.Fn rad_create_request , 223attributes can be attached to it. 224This is done through calls to 225.Fn rad_put_addr , 226.Fn rad_put_int , 227and 228.Fn rad_put_string . 229Each accepts a 230.Fa type 231parameter identifying the attribute, and a value which may be 232an Internet address, an integer, or a 233.Dv NUL Ns -terminated 234string, 235respectively. 236Alternatively, 237.Fn rad_put_vendor_addr , 238.Fn rad_put_vendor_int 239or 240.Fn rad_put_vendor_string 241may be used to specify vendor specific attributes. 242Vendor specific 243definitions may be found in 244.In radlib_vs.h 245.Pp 246The library also provides a function 247.Fn rad_put_attr 248which can be used to supply a raw, uninterpreted attribute. 249The 250.Fa data 251argument points to an array of bytes, and the 252.Fa len 253argument specifies its length. 254.Pp 255It is possible adding the Message-Authenticator to the request. 256This is an HMAC-MD5 hash of the entire Access-Request packet (see RFC 3579). 257This attribute must be present in any packet that includes an EAP-Message 258attribute. 259It can be added by using the 260.Fn rad_put_message_authentic 261function. 262The 263.Nm 264library 265calculates the HMAC-MD5 hash implicitly before sending the request. 266If the Message-Authenticator was found inside the response packet, 267then the packet is silently dropped, if the validation failed. 268In order to get this feature, the library should be compiled with 269OpenSSL support. 270.Pp 271The 272.Fn rad_put_X 273functions return 0 on success, or \-1 if an error occurs. 274.Ss Sending the Request and Receiving the Response 275After the RADIUS request has been constructed, it is sent either by means of 276.Fn rad_send_request 277or by a combination of calls to 278.Fn rad_init_send_request 279and 280.Fn rad_continue_send_request . 281.Pp 282The 283.Fn rad_send_request 284function sends the request and waits for a valid reply, 285retrying the defined servers in round-robin fashion as necessary. 286If a valid response is received, 287.Fn rad_send_request 288returns the RADIUS code which specifies the type of the response. 289This will typically be 290.Dv RAD_ACCESS_ACCEPT , 291.Dv RAD_ACCESS_REJECT , 292or 293.Dv RAD_ACCESS_CHALLENGE . 294If no valid response is received, 295.Fn rad_send_request 296returns \-1. 297.Pp 298As an alternative, if you do not wish to block waiting for a response, 299.Fn rad_init_send_request 300and 301.Fn rad_continue_send_request 302may be used instead. 303If a reply is received from the RADIUS server or a 304timeout occurs, these functions return a value as described for 305.Fn rad_send_request . 306Otherwise, a value of zero is returned and the values pointed to by 307.Fa fd 308and 309.Fa tv 310are set to the descriptor and timeout that should be passed to 311.Xr select 2 . 312.Pp 313.Fn rad_init_send_request 314must be called first, followed by repeated calls to 315.Fn rad_continue_send_request 316as long as a return value of zero is given. 317Between each call, the application should call 318.Xr select 2 , 319passing 320.Fa *fd 321as a read descriptor and timing out after the interval specified by 322.Fa tv . 323When 324.Xr select 2 325returns, 326.Fn rad_continue_send_request 327should be called with 328.Fa selected 329set to a non-zero value if 330.Xr select 2 331indicated that the descriptor is readable. 332.Pp 333Like RADIUS requests, each response may contain zero or more 334attributes. 335After a response has been received successfully by 336.Fn rad_send_request 337or 338.Fn rad_continue_send_request , 339its attributes can be extracted one by one using 340.Fn rad_get_attr . 341Each time 342.Fn rad_get_attr 343is called, it gets the next attribute from the current response, and 344stores a pointer to the data and the length of the data via the 345reference parameters 346.Fa data 347and 348.Fa len , 349respectively. 350Note that the data resides in the response itself, 351and must not be modified. 352A successful call to 353.Fn rad_get_attr 354returns the RADIUS attribute type. 355If no more attributes remain in the current response, 356.Fn rad_get_attr 357returns 0. 358If an error such as a malformed attribute is detected, \-1 is 359returned. 360.Pp 361If 362.Fn rad_get_attr 363returns 364.Dv RAD_VENDOR_SPECIFIC , 365.Fn rad_get_vendor_attr 366may be called to determine the vendor. 367The vendor specific RADIUS attribute type is returned. 368The reference parameters 369.Fa data 370and 371.Fa len 372(as returned from 373.Fn rad_get_attr ) 374are passed to 375.Fn rad_get_vendor_attr , 376and are adjusted to point to the vendor specific attribute data. 377.Pp 378The common types of attributes can be decoded using 379.Fn rad_cvt_addr , 380.Fn rad_cvt_int , 381and 382.Fn rad_cvt_string . 383These functions accept a pointer to the attribute data, which should 384have been obtained using 385.Fn rad_get_attr 386and optionally 387.Fn rad_get_vendor_attr . 388In the case of 389.Fn rad_cvt_string , 390the length 391.Fa len 392must also be given. 393These functions interpret the attribute as an 394Internet address, an integer, or a string, respectively, and return 395its value. 396.Fn rad_cvt_string 397returns its value as a 398.Dv NUL Ns -terminated 399string in dynamically 400allocated memory. 401The application should free the string using 402.Xr free 3 403when it is no longer needed. 404.Pp 405If insufficient virtual memory is available, 406.Fn rad_cvt_string 407returns 408.Dv NULL . 409.Fn rad_cvt_addr 410and 411.Fn rad_cvt_int 412cannot fail. 413.Pp 414The 415.Fn rad_request_authenticator 416function may be used to obtain the Request-Authenticator attribute value 417associated with the current RADIUS server according to the supplied 418rad_handle. 419The target buffer 420.Fa buf 421of length 422.Fa len 423must be supplied and should be at least 16 bytes. 424The return value is the number of bytes written to 425.Fa buf 426or \-1 to indicate that 427.Fa len 428was not large enough. 429.Pp 430The 431.Fn rad_server_secret 432returns the secret shared with the current RADIUS server according to the 433supplied rad_handle. 434.Pp 435The 436.Fn rad_bind_to 437assigns a source address for all requests to the current RADIUS server. 438.Pp 439The 440.Fn rad_demangle 441function demangles attributes containing passwords and MS-CHAPv1 MPPE-Keys. 442The return value is 443.Dv NULL 444on failure, or the plaintext attribute. 445This value should be freed using 446.Xr free 3 447when it is no longer needed. 448.Pp 449The 450.Fn rad_demangle_mppe_key 451function demangles the send- and recv-keys when using MPPE (see RFC 2548). 452The return value is 453.Dv NULL 454on failure, or the plaintext attribute. 455This value should be freed using 456.Xr free 3 457when it is no longer needed. 458.Ss Obtaining Error Messages 459Those functions which accept a 460.Vt "struct rad_handle *" 461argument record an error message if they fail. 462The error message 463can be retrieved by calling 464.Fn rad_strerror . 465The message text is overwritten on each new error for the given 466.Vt "struct rad_handle *" . 467Thus the message must be copied if it is to be preserved through 468subsequent library calls using the same handle. 469.Ss Cleanup 470To free the resources used by the RADIUS library, call 471.Fn rad_close . 472.Ss Server operation 473Server mode operates much alike to client mode, except packet send and receive 474steps are swapped. To operate as server you should obtain server context with 475.Fn rad_server_open 476function, passing opened and bound UDP socket file descriptor as argument. 477You should define allowed clients and their secrets using 478.Fn rad_add_server 479function. port, timeout and max_tries arguments are ignored in server mode. 480You should call 481.Fn rad_receive_request 482function to receive request from client. If you do not want to block on socket 483read, you are free to use any poll(), select() or non-blocking sockets for 484the socket. 485Received request can be parsed with same parsing functions as for client. 486To respond to the request you should call 487.Fn rad_create_response 488and fill response content with same packet writing functions as for client. 489When packet is ready, it should be sent with 490.Fn rad_send_response 491.Sh RETURN VALUES 492The following functions return a non-negative value on success. 493If 494they detect an error, they return \-1 and record an error message 495which can be retrieved using 496.Fn rad_strerror . 497.Pp 498.Bl -item -offset indent -compact 499.It 500.Fn rad_add_server 501.It 502.Fn rad_config 503.It 504.Fn rad_create_request 505.It 506.Fn rad_create_response 507.It 508.Fn rad_get_attr 509.It 510.Fn rad_put_addr 511.It 512.Fn rad_put_attr 513.It 514.Fn rad_put_int 515.It 516.Fn rad_put_string 517.It 518.Fn rad_put_message_authentic 519.It 520.Fn rad_init_send_request 521.It 522.Fn rad_continue_send_request 523.It 524.Fn rad_send_request 525.It 526.Fn rad_send_response 527.El 528.Pp 529The following functions return a 530.No non- Ns Dv NULL 531pointer on success. 532If they are unable to allocate sufficient 533virtual memory, they return 534.Dv NULL , 535without recording an error message. 536.Pp 537.Bl -item -offset indent -compact 538.It 539.Fn rad_acct_open 540.It 541.Fn rad_auth_open 542.It 543.Fn rad_server_open 544.It 545.Fn rad_cvt_string 546.El 547.Pp 548The following functions return a 549.No non- Ns Dv NULL 550pointer on success. 551If they fail, they return 552.Dv NULL , 553with recording an error message. 554.Pp 555.Bl -item -offset indent -compact 556.It 557.Fn rad_demangle 558.It 559.Fn rad_demangle_mppe_key 560.El 561.Sh FILES 562.Bl -tag -width indent 563.It Pa /etc/radius.conf 564.El 565.Sh SEE ALSO 566.Xr radius.conf 5 567.Rs 568.%A "C. Rigney, et al" 569.%T "Remote Authentication Dial In User Service (RADIUS)" 570.%O "RFC 2865" 571.Re 572.Rs 573.%A "C. Rigney" 574.%T "RADIUS Accounting" 575.%O "RFC 2866" 576.Re 577.Rs 578.%A G. Zorn 579.%T "Microsoft Vendor-specific RADIUS attributes" 580.%O RFC 2548 581.Re 582.Rs 583.%A C. Rigney, et al 584.%T "RADIUS extensions" 585.%O RFC 2869 586.Re 587.Sh AUTHORS 588.An -nosplit 589This software was originally written by 590.An John Polstra , 591and donated to the 592.Fx 593project by Juniper Networks, Inc. 594.An Oleg Semyonov 595subsequently added the ability to perform RADIUS 596accounting. 597Later additions and changes by 598.An Michael Bretterklieber . 599Server mode support was added by 600.An Alexander Motin . 601