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 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 . 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_bind_to 435assigns a source address for all requests to the current RADIUS server. 436.Pp 437The 438.Fn rad_demangle 439function demangles attributes containing passwords and MS-CHAPv1 MPPE-Keys. 440The return value is 441.Dv NULL 442on failure, or the plaintext attribute. 443This value should be freed using 444.Xr free 3 445when it is no longer needed. 446.Pp 447The 448.Fn rad_demangle_mppe_key 449function demangles the send- and recv-keys when using MPPE (see RFC 2548). 450The return value is 451.Dv NULL 452on failure, or the plaintext attribute. 453This value should be freed using 454.Xr free 3 455when it is no longer needed. 456.Ss Obtaining Error Messages 457Those functions which accept a 458.Vt "struct rad_handle *" 459argument record an error message if they fail. 460The error message 461can be retrieved by calling 462.Fn rad_strerror . 463The message text is overwritten on each new error for the given 464.Vt "struct rad_handle *" . 465Thus the message must be copied if it is to be preserved through 466subsequent library calls using the same handle. 467.Ss Cleanup 468To free the resources used by the RADIUS library, call 469.Fn rad_close . 470.Ss Server operation 471Server mode operates much alike to client mode, except packet send and receive 472steps are swapped. To operate as server you should obtain server context with 473.Fn rad_server_open 474function, passing opened and bound UDP socket file descriptor as argument. 475You should define allowed clients and their secrets using 476.Fn rad_add_server 477function. port, timeout and max_tries arguments are ignored in server mode. 478You should call 479.Fn rad_receive_request 480function to receive request from client. If you do not want to block on socket 481read, you are free to use any poll(), select() or non-blocking sockets for 482the socket. 483Received request can be parsed with same parsing functions as for client. 484To respond to the request you should call 485.Fn rad_create_response 486and fill response content with same packet writing functions as for client. 487When packet is ready, it should be sent with 488.Fn rad_send_response . 489.Sh RETURN VALUES 490The following functions return a non-negative value on success. 491If 492they detect an error, they return \-1 and record an error message 493which can be retrieved using 494.Fn rad_strerror . 495.Pp 496.Bl -item -offset indent -compact 497.It 498.Fn rad_add_server 499.It 500.Fn rad_config 501.It 502.Fn rad_create_request 503.It 504.Fn rad_create_response 505.It 506.Fn rad_get_attr 507.It 508.Fn rad_put_addr 509.It 510.Fn rad_put_attr 511.It 512.Fn rad_put_int 513.It 514.Fn rad_put_string 515.It 516.Fn rad_put_message_authentic 517.It 518.Fn rad_init_send_request 519.It 520.Fn rad_continue_send_request 521.It 522.Fn rad_send_request 523.It 524.Fn rad_send_response 525.El 526.Pp 527The following functions return a 528.No non- Ns Dv NULL 529pointer on success. 530If they are unable to allocate sufficient 531virtual memory, they return 532.Dv NULL , 533without recording an error message. 534.Pp 535.Bl -item -offset indent -compact 536.It 537.Fn rad_acct_open 538.It 539.Fn rad_auth_open 540.It 541.Fn rad_server_open 542.It 543.Fn rad_cvt_string 544.El 545.Pp 546The following functions return a 547.No non- Ns Dv NULL 548pointer on success. 549If they fail, they return 550.Dv NULL , 551with recording an error message. 552.Pp 553.Bl -item -offset indent -compact 554.It 555.Fn rad_demangle 556.It 557.Fn rad_demangle_mppe_key 558.El 559.Sh FILES 560.Bl -tag -width indent 561.It Pa /etc/radius.conf 562.El 563.Sh SEE ALSO 564.Xr radius.conf 5 565.Rs 566.%A "C. Rigney, et al" 567.%T "Remote Authentication Dial In User Service (RADIUS)" 568.%O "RFC 2865" 569.Re 570.Rs 571.%A "C. Rigney" 572.%T "RADIUS Accounting" 573.%O "RFC 2866" 574.Re 575.Rs 576.%A G. Zorn 577.%T "Microsoft Vendor-specific RADIUS attributes" 578.%O RFC 2548 579.Re 580.Rs 581.%A C. Rigney, et al 582.%T "RADIUS extensions" 583.%O RFC 2869 584.Re 585.Sh AUTHORS 586.An -nosplit 587This software was originally written by 588.An John Polstra , 589and donated to the 590.Fx 591project by Juniper Networks, Inc. 592.An Oleg Semyonov 593subsequently added the ability to perform RADIUS 594accounting. 595Later additions and changes by 596.An Michael Bretterklieber . 597Server mode support was added by 598.An Alexander Motin . 599