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