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