1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ 2 /* 3 * Copyright 2013 Red Hat, Inc. 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 are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in 13 * the documentation and/or other materials provided with the 14 * distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 17 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 19 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 20 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 21 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 23 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 24 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 25 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 26 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 /* 30 * This API is not considered as stable as the main krb5 API. 31 * 32 * - We may make arbitrary incompatible changes between feature releases 33 * (e.g. from 1.12 to 1.13). 34 * - We will make some effort to avoid making incompatible changes for 35 * bugfix releases, but will make them if necessary. 36 */ 37 38 #ifndef KRAD_H_ 39 #define KRAD_H_ 40 41 #include <krb5.h> 42 #include <verto.h> 43 #include <stddef.h> 44 #include <stdio.h> 45 46 #define KRAD_PACKET_SIZE_MAX 4096 47 48 #define KRAD_SERVICE_TYPE_LOGIN 1 49 #define KRAD_SERVICE_TYPE_FRAMED 2 50 #define KRAD_SERVICE_TYPE_CALLBACK_LOGIN 3 51 #define KRAD_SERVICE_TYPE_CALLBACK_FRAMED 4 52 #define KRAD_SERVICE_TYPE_OUTBOUND 5 53 #define KRAD_SERVICE_TYPE_ADMINISTRATIVE 6 54 #define KRAD_SERVICE_TYPE_NAS_PROMPT 7 55 #define KRAD_SERVICE_TYPE_AUTHENTICATE_ONLY 8 56 #define KRAD_SERVICE_TYPE_CALLBACK_NAS_PROMPT 9 57 #define KRAD_SERVICE_TYPE_CALL_CHECK 10 58 #define KRAD_SERVICE_TYPE_CALLBACK_ADMINISTRATIVE 11 59 60 #define KRAD_ATTR_USER_NAME 1 61 #define KRAD_ATTR_USER_PASSWORD 2 62 #define KRAD_ATTR_SERVICE_TYPE 6 63 #define KRAD_ATTR_NAS_IDENTIFIER 32 64 #define KRAD_ATTR_PROXY_STATE 33 65 #define KRAD_ATTR_MESSAGE_AUTHENTICATOR 80 66 67 #define KRAD_CODE_ACCESS_REQUEST 1 68 #define KRAD_CODE_ACCESS_ACCEPT 2 69 #define KRAD_CODE_ACCESS_REJECT 3 70 #define KRAD_CODE_ACCESS_CHALLENGE 11 71 72 typedef struct krad_attrset_st krad_attrset; 73 typedef struct krad_packet_st krad_packet; 74 typedef struct krad_client_st krad_client; 75 typedef unsigned char krad_code; 76 typedef unsigned char krad_attr; 77 78 /* Called when a response is received or the request times out. */ 79 typedef void 80 (*krad_cb)(krb5_error_code retval, const krad_packet *request, 81 const krad_packet *response, void *data); 82 83 /* 84 * Called to iterate over a set of requests. Either the callback will be 85 * called until it returns NULL, or it will be called with cancel = TRUE to 86 * terminate in the middle of an iteration. 87 */ 88 typedef const krad_packet * 89 (*krad_packet_iter_cb)(void *data, krb5_boolean cancel); 90 91 /* 92 * Code 93 */ 94 95 /* Convert a code name to its number. Only works for codes defined 96 * by RFC 2875 or 2882. Returns 0 if the name was not found. */ 97 krad_code 98 krad_code_name2num(const char *name); 99 100 /* Convert a code number to its name. Only works for attributes defined 101 * by RFC 2865 or 2882. Returns NULL if the name was not found. */ 102 const char * 103 krad_code_num2name(krad_code code); 104 105 /* 106 * Attribute 107 */ 108 109 /* Convert an attribute name to its number. Only works for attributes defined 110 * by RFC 2865. Returns 0 if the name was not found. */ 111 krad_attr 112 krad_attr_name2num(const char *name); 113 114 /* Convert an attribute number to its name. Only works for attributes defined 115 * by RFC 2865. Returns NULL if the name was not found. */ 116 const char * 117 krad_attr_num2name(krad_attr type); 118 119 /* 120 * Attribute set 121 */ 122 123 /* Create a new attribute set. */ 124 krb5_error_code 125 krad_attrset_new(krb5_context ctx, krad_attrset **set); 126 127 /* Create a deep copy of an attribute set. */ 128 krb5_error_code 129 krad_attrset_copy(const krad_attrset *set, krad_attrset **copy); 130 131 /* Free an attribute set. */ 132 void 133 krad_attrset_free(krad_attrset *set); 134 135 /* Add an attribute to a set. */ 136 krb5_error_code 137 krad_attrset_add(krad_attrset *set, krad_attr type, const krb5_data *data); 138 139 /* Add a four-octet unsigned number attribute to the given set. */ 140 krb5_error_code 141 krad_attrset_add_number(krad_attrset *set, krad_attr type, krb5_ui_4 num); 142 143 /* Delete the specified attribute. */ 144 void 145 krad_attrset_del(krad_attrset *set, krad_attr type, size_t indx); 146 147 /* Get the specified attribute. */ 148 const krb5_data * 149 krad_attrset_get(const krad_attrset *set, krad_attr type, size_t indx); 150 151 /* 152 * Packet 153 */ 154 155 /* Determine the bytes needed from the socket to get the whole packet. Don't 156 * cache the return value as it can change! Returns -1 on EBADMSG. */ 157 ssize_t 158 krad_packet_bytes_needed(const krb5_data *buffer); 159 160 /* Free a packet. */ 161 void 162 krad_packet_free(krad_packet *pkt); 163 164 /* 165 * Create a new request packet. 166 * 167 * This function takes the attributes specified in set and converts them into a 168 * radius packet. The packet will have a randomized id. If cb is not NULL, it 169 * will be called passing data as the argument to iterate over a set of 170 * outstanding requests. In this case, the id will be both random and unique 171 * across the set of requests. 172 */ 173 krb5_error_code 174 krad_packet_new_request(krb5_context ctx, const char *secret, krad_code code, 175 const krad_attrset *set, krad_packet_iter_cb cb, 176 void *data, krad_packet **request); 177 178 /* 179 * Create a new response packet. 180 * 181 * This function is similar to krad_packet_new_requst() except that it crafts a 182 * packet in response to a request packet. This new packet will borrow values 183 * from the request such as the id and the authenticator. 184 */ 185 krb5_error_code 186 krad_packet_new_response(krb5_context ctx, const char *secret, krad_code code, 187 const krad_attrset *set, const krad_packet *request, 188 krad_packet **response); 189 190 /* 191 * Decode a request radius packet from krb5_data. 192 * 193 * The resulting decoded packet will be a request packet stored in *reqpkt. 194 * 195 * If cb is NULL, *duppkt will always be NULL. 196 * 197 * If cb is not NULL, it will be called (with the data argument) to iterate 198 * over a set of requests currently being processed. In this case, if the 199 * packet is a duplicate of an already received request, the original request 200 * will be set in *duppkt. 201 */ 202 krb5_error_code 203 krad_packet_decode_request(krb5_context ctx, const char *secret, 204 const krb5_data *buffer, krad_packet_iter_cb cb, 205 void *data, const krad_packet **duppkt, 206 krad_packet **reqpkt); 207 208 /* 209 * Decode a response radius packet from krb5_data. 210 * 211 * The resulting decoded packet will be a response packet stored in *rsppkt. 212 * 213 * If cb is NULL, *reqpkt will always be NULL. 214 * 215 * If cb is not NULL, it will be called (with the data argument) to iterate 216 * over a set of requests awaiting responses. In this case, if the response 217 * packet matches one of these requests, the original request will be set in 218 * *reqpkt. 219 */ 220 krb5_error_code 221 krad_packet_decode_response(krb5_context ctx, const char *secret, 222 const krb5_data *buffer, krad_packet_iter_cb cb, 223 void *data, const krad_packet **reqpkt, 224 krad_packet **rsppkt); 225 226 /* Encode packet. */ 227 const krb5_data * 228 krad_packet_encode(const krad_packet *pkt); 229 230 /* Get the code for the given packet. */ 231 krad_code 232 krad_packet_get_code(const krad_packet *pkt); 233 234 /* Get the specified attribute. */ 235 const krb5_data * 236 krad_packet_get_attr(const krad_packet *pkt, krad_attr type, size_t indx); 237 238 /* 239 * Client 240 */ 241 242 /* Create a new client. */ 243 krb5_error_code 244 krad_client_new(krb5_context kctx, verto_ctx *vctx, krad_client **client); 245 246 /* Free the client. */ 247 void 248 krad_client_free(krad_client *client); 249 250 /* 251 * Send a request to a radius server. 252 * 253 * The remote host may be specified by one of the following formats: 254 * - /path/to/unix.socket 255 * - IPv4 256 * - IPv4:port 257 * - IPv4:service 258 * - [IPv6] 259 * - [IPv6]:port 260 * - [IPv6]:service 261 * - hostname 262 * - hostname:port 263 * - hostname:service 264 * 265 * The timeout parameter (milliseconds) is the total timeout across all remote 266 * hosts (when DNS returns multiple entries) and all retries. For stream 267 * sockets, the retries parameter is ignored and no retries are performed. 268 * 269 * The cb function will be called with the data argument when either a response 270 * is received or the request times out on all possible remote hosts. 271 */ 272 krb5_error_code 273 krad_client_send(krad_client *rc, krad_code code, const krad_attrset *attrs, 274 const char *remote, const char *secret, int timeout, 275 size_t retries, krad_cb cb, void *data); 276 277 #endif /* KRAD_H_ */ 278