1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ 2 /* 3 * Copyright (c) 2006 Red Hat, Inc. 4 * Portions copyright (c) 2006, 2011 Massachusetts Institute of Technology 5 * All Rights Reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions are met: 9 * 10 * * Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * * Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in 14 * the documentation and/or other materials provided with the 15 * distribution. 16 * * Neither the name of Red Hat, Inc., nor the names of its 17 * contributors may be used to endorse or promote products derived 18 * from this software without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 21 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 23 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 24 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 27 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 28 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 29 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 /* 34 * Declarations for kdcpreauth plugin module implementors. 35 * 36 * The kdcpreauth interface has a single supported major version, which is 1. 37 * Major version 1 has a current minor version of 2. kdcpreauth modules should 38 * define a function named kdcpreauth_<modulename>_initvt, matching the 39 * signature: 40 * 41 * krb5_error_code 42 * kdcpreauth_modname_initvt(krb5_context context, int maj_ver, int min_ver, 43 * krb5_plugin_vtable vtable); 44 * 45 * The initvt function should: 46 * 47 * - Check that the supplied maj_ver number is supported by the module, or 48 * return KRB5_PLUGIN_VER_NOTSUPP if it is not. 49 * 50 * - Cast the vtable pointer as appropriate for the interface and maj_ver: 51 * kdcpreauth, maj_ver == 1: Cast to krb5_kdcpreauth_vtable 52 * 53 * - Initialize the methods of the vtable, stopping as appropriate for the 54 * supplied min_ver. Optional methods may be left uninitialized. 55 * 56 * Memory for the vtable is allocated by the caller, not by the module. 57 */ 58 59 #ifndef KRB5_KDCPREAUTH_PLUGIN_H 60 #define KRB5_KDCPREAUTH_PLUGIN_H 61 62 #include <krb5/krb5.h> 63 #include <krb5/plugin.h> 64 65 /* kdcpreauth mechanism property flags */ 66 67 /* 68 * Causes the KDC to include this mechanism in a list of supported preauth 69 * types if the user's DB entry flags the user as requiring hardware-based 70 * preauthentication. 71 */ 72 #define PA_HARDWARE 0x00000004 73 74 /* 75 * Causes the KDC to include this mechanism in a list of supported preauth 76 * types if the user's DB entry flags the user as requiring preauthentication, 77 * and to fail preauthentication if we can't verify the client data. The 78 * flipside of PA_SUFFICIENT. 79 */ 80 #define PA_REQUIRED 0x00000008 81 82 /* 83 * Causes the KDC to include this mechanism in a list of supported preauth 84 * types if the user's DB entry flags the user as requiring preauthentication, 85 * and to mark preauthentication as successful if we can verify the client 86 * data. The flipside of PA_REQUIRED. 87 */ 88 #define PA_SUFFICIENT 0x00000010 89 90 /* 91 * Marks this preauthentication mechanism as one which changes the key which is 92 * used for encrypting the response to the client. Modules which have this 93 * flag have their server_return_fn called before modules which do not, and are 94 * passed over if a previously-called module has modified the encrypting key. 95 */ 96 #define PA_REPLACES_KEY 0x00000020 97 98 /* 99 * Not really a padata type, so don't include it in any list of preauth types 100 * which gets sent over the wire. 101 */ 102 #define PA_PSEUDO 0x00000080 103 104 /* 105 * Indicates that e_data in non-FAST errors should be encoded as typed data 106 * instead of padata. 107 */ 108 #define PA_TYPED_E_DATA 0x00000100 109 110 /* Abstract type for a KDC callback data handle. */ 111 typedef struct krb5_kdcpreauth_rock_st *krb5_kdcpreauth_rock; 112 113 /* Abstract type for module data and per-request module data. */ 114 typedef struct krb5_kdcpreauth_moddata_st *krb5_kdcpreauth_moddata; 115 typedef struct krb5_kdcpreauth_modreq_st *krb5_kdcpreauth_modreq; 116 117 /* The verto context structure type (typedef is in verto.h; we want to avoid a 118 * header dependency for the moment). */ 119 struct verto_ctx; 120 121 /* Before using a callback after version 1, modules must check the vers 122 * field of the callback structure. */ 123 typedef struct krb5_kdcpreauth_callbacks_st { 124 int vers; 125 126 krb5_deltat (*max_time_skew)(krb5_context context, 127 krb5_kdcpreauth_rock rock); 128 129 /* 130 * Get an array of krb5_keyblock structures containing the client keys 131 * matching the request enctypes, terminated by an entry with key type = 0. 132 * Returns ENOENT if no keys are available for the request enctypes. Free 133 * the resulting object with the free_keys callback. 134 */ 135 krb5_error_code (*client_keys)(krb5_context context, 136 krb5_kdcpreauth_rock rock, 137 krb5_keyblock **keys_out); 138 139 /* Free the result of client_keys. */ 140 void (*free_keys)(krb5_context context, krb5_kdcpreauth_rock rock, 141 krb5_keyblock *keys); 142 143 /* 144 * Get the encoded request body, which is sometimes needed for checksums. 145 * For a FAST request this is the encoded inner request body. The returned 146 * pointer is an alias and should not be freed. 147 */ 148 krb5_data *(*request_body)(krb5_context context, 149 krb5_kdcpreauth_rock rock); 150 151 /* Get a pointer to the FAST armor key, or NULL if the request did not use 152 * FAST. The returned pointer is an alias and should not be freed. */ 153 krb5_keyblock *(*fast_armor)(krb5_context context, 154 krb5_kdcpreauth_rock rock); 155 156 /* Retrieve a string attribute from the client DB entry, or NULL if no such 157 * attribute is set. Free the result with the free_string callback. */ 158 krb5_error_code (*get_string)(krb5_context context, 159 krb5_kdcpreauth_rock rock, const char *key, 160 char **value_out); 161 162 /* Free the result of get_string. */ 163 void (*free_string)(krb5_context context, krb5_kdcpreauth_rock rock, 164 char *string); 165 166 /* Get a pointer to the client DB entry (returned as a void pointer to 167 * avoid a dependency on a libkdb5 type). */ 168 void *(*client_entry)(krb5_context context, krb5_kdcpreauth_rock rock); 169 170 /* Get a pointer to the verto context which should be used by an 171 * asynchronous edata or verify method. */ 172 struct verto_ctx *(*event_context)(krb5_context context, 173 krb5_kdcpreauth_rock rock); 174 175 /* End of version 1 kdcpreauth callbacks. */ 176 177 /* Return true if the client DB entry contains any keys matching the 178 * request enctypes. */ 179 krb5_boolean (*have_client_keys)(krb5_context context, 180 krb5_kdcpreauth_rock rock); 181 182 /* End of version 2 kdcpreauth callbacks. */ 183 184 /* 185 * Get the decrypted client long-term key chosen according to the request 186 * enctype list, or NULL if no matching key was found. The returned 187 * pointer is an alias and should not be freed. If invoked from 188 * return_padata, the result will be the same as the encrypting_key 189 * parameter if it is not NULL, and will therefore reflect the modified 190 * reply key if a return_padata handler has replaced the reply key. 191 */ 192 const krb5_keyblock *(*client_keyblock)(krb5_context context, 193 krb5_kdcpreauth_rock rock); 194 195 /* Assert an authentication indicator in the AS-REP authdata. Duplicate 196 * indicators will be ignored. */ 197 krb5_error_code (*add_auth_indicator)(krb5_context context, 198 krb5_kdcpreauth_rock rock, 199 const char *indicator); 200 201 /* 202 * Read a data value for pa_type from the request cookie, placing it in 203 * *out. The value placed there is an alias and must not be freed. 204 * Returns true if a value for pa_type was retrieved, false if not. 205 */ 206 krb5_boolean (*get_cookie)(krb5_context context, krb5_kdcpreauth_rock rock, 207 krb5_preauthtype pa_type, krb5_data *out); 208 209 /* 210 * Set a data value for pa_type to be sent in a secure cookie in the next 211 * error response. If pa_type is already present, the value is ignored. 212 * If the preauth mechanism has different preauth types for requests and 213 * responses, use the request type. Secure cookies are encrypted in a key 214 * known only to the KDCs, but can be replayed within a short time window 215 * for requests using the same client principal. 216 */ 217 krb5_error_code (*set_cookie)(krb5_context context, 218 krb5_kdcpreauth_rock rock, 219 krb5_preauthtype pa_type, 220 const krb5_data *data); 221 222 /* End of version 3 kdcpreauth callbacks. */ 223 224 /* 225 * Return true if princ matches the principal named in the request or the 226 * client principal (possibly canonicalized). If princ does not match, 227 * attempt a database lookup of princ with aliases allowed and compare the 228 * result to the client principal, returning true if it matches. 229 * Otherwise, return false. 230 */ 231 krb5_boolean (*match_client)(krb5_context context, 232 krb5_kdcpreauth_rock rock, 233 krb5_principal princ); 234 235 /* 236 * Get an alias to the client DB entry principal (possibly canonicalized). 237 */ 238 krb5_principal (*client_name)(krb5_context context, 239 krb5_kdcpreauth_rock rock); 240 241 /* End of version 4 kdcpreauth callbacks. */ 242 243 /* 244 * Instruct the KDC to send a freshness token in the method data 245 * accompanying a PREAUTH_REQUIRED or PREAUTH_FAILED error, if the client 246 * indicated support for freshness tokens. This callback should only be 247 * invoked from the edata method. 248 */ 249 void (*send_freshness_token)(krb5_context context, 250 krb5_kdcpreauth_rock rock); 251 252 /* Validate a freshness token sent by the client. Return 0 on success, 253 * KRB5KDC_ERR_PREAUTH_EXPIRED on error. */ 254 krb5_error_code (*check_freshness_token)(krb5_context context, 255 krb5_kdcpreauth_rock rock, 256 const krb5_data *token); 257 258 /* End of version 5 kdcpreauth callbacks. */ 259 260 } *krb5_kdcpreauth_callbacks; 261 262 /* Optional: preauth plugin initialization function. */ 263 typedef krb5_error_code 264 (*krb5_kdcpreauth_init_fn)(krb5_context context, 265 krb5_kdcpreauth_moddata *moddata_out, 266 const char **realmnames); 267 268 /* Optional: preauth plugin cleanup function. */ 269 typedef void 270 (*krb5_kdcpreauth_fini_fn)(krb5_context context, 271 krb5_kdcpreauth_moddata moddata); 272 273 /* 274 * Optional: return the flags which the KDC should use for this module. This 275 * is a callback instead of a static value because the module may or may not 276 * wish to count itself as a hardware preauthentication module (in other words, 277 * the flags may be affected by the configuration, for example if a site 278 * administrator can force a particular preauthentication type to be supported 279 * using only hardware). This function is called for each entry entry in the 280 * server_pa_type_list. 281 */ 282 typedef int 283 (*krb5_kdcpreauth_flags_fn)(krb5_context context, krb5_preauthtype pa_type); 284 285 /* 286 * Responder for krb5_kdcpreauth_edata_fn. If invoked with a non-zero code, pa 287 * will be ignored and the padata type will not be included in the hint list. 288 * If invoked with a zero code and a null pa value, the padata type will be 289 * included in the list with an empty value. If invoked with a zero code and a 290 * non-null pa value, pa will be included in the hint list and will later be 291 * freed by the KDC. 292 */ 293 typedef void 294 (*krb5_kdcpreauth_edata_respond_fn)(void *arg, krb5_error_code code, 295 krb5_pa_data *pa); 296 297 /* 298 * Optional: provide pa_data to send to the client as part of the "you need to 299 * use preauthentication" error. The implementation must invoke the respond 300 * when complete, whether successful or not, either before returning or 301 * asynchronously using the verto context returned by cb->event_context(). 302 * 303 * This function is not allowed to create a modreq object because we have no 304 * guarantee that the client will ever make a follow-up request, or that it 305 * will hit this KDC if it does. 306 */ 307 typedef void 308 (*krb5_kdcpreauth_edata_fn)(krb5_context context, krb5_kdc_req *request, 309 krb5_kdcpreauth_callbacks cb, 310 krb5_kdcpreauth_rock rock, 311 krb5_kdcpreauth_moddata moddata, 312 krb5_preauthtype pa_type, 313 krb5_kdcpreauth_edata_respond_fn respond, 314 void *arg); 315 316 /* 317 * Responder for krb5_kdcpreauth_verify_fn. Invoke with the arg parameter 318 * supplied to verify, the error code (0 for success), an optional module 319 * request state object to be consumed by return_fn or free_modreq_fn, optional 320 * e_data to be passed to the caller if code is nonzero, and optional 321 * authorization data to be included in the ticket. In non-FAST replies, 322 * e_data will be encoded as typed-data if the module sets the PA_TYPED_E_DATA 323 * flag, and as pa-data otherwise. e_data and authz_data will be freed by the 324 * KDC. 325 */ 326 typedef void 327 (*krb5_kdcpreauth_verify_respond_fn)(void *arg, krb5_error_code code, 328 krb5_kdcpreauth_modreq modreq, 329 krb5_pa_data **e_data, 330 krb5_authdata **authz_data); 331 332 /* 333 * Optional: verify preauthentication data sent by the client, setting the 334 * TKT_FLG_PRE_AUTH or TKT_FLG_HW_AUTH flag in the enc_tkt_reply's "flags" 335 * field as appropriate. The implementation must invoke the respond function 336 * when complete, whether successful or not, either before returning or 337 * asynchronously using the verto context returned by cb->event_context(). 338 */ 339 typedef void 340 (*krb5_kdcpreauth_verify_fn)(krb5_context context, 341 krb5_data *req_pkt, krb5_kdc_req *request, 342 krb5_enc_tkt_part *enc_tkt_reply, 343 krb5_pa_data *data, 344 krb5_kdcpreauth_callbacks cb, 345 krb5_kdcpreauth_rock rock, 346 krb5_kdcpreauth_moddata moddata, 347 krb5_kdcpreauth_verify_respond_fn respond, 348 void *arg); 349 350 /* 351 * Optional: generate preauthentication response data to send to the client as 352 * part of the AS-REP. If it needs to override the key which is used to 353 * encrypt the response, it can do so. 354 */ 355 typedef krb5_error_code 356 (*krb5_kdcpreauth_return_fn)(krb5_context context, 357 krb5_pa_data *padata, 358 krb5_data *req_pkt, 359 krb5_kdc_req *request, 360 krb5_kdc_rep *reply, 361 krb5_keyblock *encrypting_key, 362 krb5_pa_data **send_pa_out, 363 krb5_kdcpreauth_callbacks cb, 364 krb5_kdcpreauth_rock rock, 365 krb5_kdcpreauth_moddata moddata, 366 krb5_kdcpreauth_modreq modreq); 367 368 /* Optional: free a per-request context. */ 369 typedef void 370 (*krb5_kdcpreauth_free_modreq_fn)(krb5_context, 371 krb5_kdcpreauth_moddata moddata, 372 krb5_kdcpreauth_modreq modreq); 373 374 /* Optional: invoked after init_fn to provide the module with a pointer to the 375 * verto main loop. */ 376 typedef krb5_error_code 377 (*krb5_kdcpreauth_loop_fn)(krb5_context context, 378 krb5_kdcpreauth_moddata moddata, 379 struct verto_ctx *ctx); 380 381 typedef struct krb5_kdcpreauth_vtable_st { 382 /* Mandatory: name of module. */ 383 char *name; 384 385 /* Mandatory: pointer to zero-terminated list of pa_types which this module 386 * can provide services for. */ 387 krb5_preauthtype *pa_type_list; 388 389 krb5_kdcpreauth_init_fn init; 390 krb5_kdcpreauth_fini_fn fini; 391 krb5_kdcpreauth_flags_fn flags; 392 krb5_kdcpreauth_edata_fn edata; 393 krb5_kdcpreauth_verify_fn verify; 394 krb5_kdcpreauth_return_fn return_padata; 395 krb5_kdcpreauth_free_modreq_fn free_modreq; 396 /* Minor 1 ends here. */ 397 398 krb5_kdcpreauth_loop_fn loop; 399 /* Minor 2 ends here. */ 400 } *krb5_kdcpreauth_vtable; 401 402 #endif /* KRB5_KDCPREAUTH_PLUGIN_H */ 403