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