1*bf6873c5SCy Schubert /* 2*bf6873c5SCy Schubert * Portability wrapper around krb5.h. 3*bf6873c5SCy Schubert * 4*bf6873c5SCy Schubert * This header includes krb5.h and then adjusts for various portability 5*bf6873c5SCy Schubert * issues, primarily between MIT Kerberos and Heimdal, so that code can be 6*bf6873c5SCy Schubert * written to a consistent API. 7*bf6873c5SCy Schubert * 8*bf6873c5SCy Schubert * Unfortunately, due to the nature of the differences between MIT Kerberos 9*bf6873c5SCy Schubert * and Heimdal, it's not possible to write code to either one of the APIs and 10*bf6873c5SCy Schubert * adjust for the other one. In general, this header tries to make available 11*bf6873c5SCy Schubert * the Heimdal API and fix it for MIT Kerberos, but there are places where MIT 12*bf6873c5SCy Schubert * Kerberos requires a more specific call. For those cases, it provides the 13*bf6873c5SCy Schubert * most specific interface. 14*bf6873c5SCy Schubert * 15*bf6873c5SCy Schubert * For example, MIT Kerberos has krb5_free_unparsed_name() whereas Heimdal 16*bf6873c5SCy Schubert * prefers the generic krb5_xfree(). In this case, this header provides 17*bf6873c5SCy Schubert * krb5_free_unparsed_name() for both APIs since it's the most specific call. 18*bf6873c5SCy Schubert * 19*bf6873c5SCy Schubert * The canonical version of this file is maintained in the rra-c-util package, 20*bf6873c5SCy Schubert * which can be found at <https://www.eyrie.org/~eagle/software/rra-c-util/>. 21*bf6873c5SCy Schubert * 22*bf6873c5SCy Schubert * Written by Russ Allbery <eagle@eyrie.org> 23*bf6873c5SCy Schubert * Copyright 2015, 2017, 2020 Russ Allbery <eagle@eyrie.org> 24*bf6873c5SCy Schubert * Copyright 2010-2014 25*bf6873c5SCy Schubert * The Board of Trustees of the Leland Stanford Junior University 26*bf6873c5SCy Schubert * 27*bf6873c5SCy Schubert * Copying and distribution of this file, with or without modification, are 28*bf6873c5SCy Schubert * permitted in any medium without royalty provided the copyright notice and 29*bf6873c5SCy Schubert * this notice are preserved. This file is offered as-is, without any 30*bf6873c5SCy Schubert * warranty. 31*bf6873c5SCy Schubert * 32*bf6873c5SCy Schubert * SPDX-License-Identifier: FSFAP 33*bf6873c5SCy Schubert */ 34*bf6873c5SCy Schubert 35*bf6873c5SCy Schubert #ifndef PORTABLE_KRB5_H 36*bf6873c5SCy Schubert #define PORTABLE_KRB5_H 1 37*bf6873c5SCy Schubert 38*bf6873c5SCy Schubert /* 39*bf6873c5SCy Schubert * Allow inclusion of config.h to be skipped, since sometimes we have to use a 40*bf6873c5SCy Schubert * stripped-down version of config.h with a different name. 41*bf6873c5SCy Schubert */ 42*bf6873c5SCy Schubert #ifndef CONFIG_H_INCLUDED 43*bf6873c5SCy Schubert # include <config.h> 44*bf6873c5SCy Schubert #endif 45*bf6873c5SCy Schubert #include <portable/macros.h> 46*bf6873c5SCy Schubert 47*bf6873c5SCy Schubert #if defined(HAVE_KRB5_H) 48*bf6873c5SCy Schubert # include <krb5.h> 49*bf6873c5SCy Schubert #elif defined(HAVE_KERBEROSV5_KRB5_H) 50*bf6873c5SCy Schubert # include <kerberosv5/krb5.h> 51*bf6873c5SCy Schubert #else 52*bf6873c5SCy Schubert # include <krb5/krb5.h> 53*bf6873c5SCy Schubert #endif 54*bf6873c5SCy Schubert #include <stdlib.h> 55*bf6873c5SCy Schubert 56*bf6873c5SCy Schubert /* Heimdal: KRB5_WELLKNOWN_NAME, MIT: KRB5_WELLKNOWN_NAMESTR. */ 57*bf6873c5SCy Schubert #ifndef KRB5_WELLKNOWN_NAME 58*bf6873c5SCy Schubert # ifdef KRB5_WELLKNOWN_NAMESTR 59*bf6873c5SCy Schubert # define KRB5_WELLKNOWN_NAME KRB5_WELLKNOWN_NAMESTR 60*bf6873c5SCy Schubert # else 61*bf6873c5SCy Schubert # define KRB5_WELLKNOWN_NAME "WELLKNOWN" 62*bf6873c5SCy Schubert # endif 63*bf6873c5SCy Schubert #endif 64*bf6873c5SCy Schubert 65*bf6873c5SCy Schubert /* Heimdal: KRB5_ANON_NAME, MIT: KRB5_ANONYMOUS_PRINCSTR. */ 66*bf6873c5SCy Schubert #ifndef KRB5_ANON_NAME 67*bf6873c5SCy Schubert # ifdef KRB5_ANONYMOUS_PRINCSTR 68*bf6873c5SCy Schubert # define KRB5_ANON_NAME KRB5_ANONYMOUS_PRINCSTR 69*bf6873c5SCy Schubert # else 70*bf6873c5SCy Schubert # define KRB5_ANON_NAME "ANONYMOUS" 71*bf6873c5SCy Schubert # endif 72*bf6873c5SCy Schubert #endif 73*bf6873c5SCy Schubert 74*bf6873c5SCy Schubert /* Heimdal: KRB5_ANON_REALM, MIT: KRB5_ANONYMOUS_REALMSTR. */ 75*bf6873c5SCy Schubert #ifndef KRB5_ANON_REALM 76*bf6873c5SCy Schubert # ifdef KRB5_ANONYMOUS_REALMSTR 77*bf6873c5SCy Schubert # define KRB5_ANON_REALM KRB5_ANONYMOUS_REALMSTR 78*bf6873c5SCy Schubert # else 79*bf6873c5SCy Schubert # define KRB5_ANON_REALM "WELLKNOWN:ANONYMOUS" 80*bf6873c5SCy Schubert # endif 81*bf6873c5SCy Schubert #endif 82*bf6873c5SCy Schubert 83*bf6873c5SCy Schubert BEGIN_DECLS 84*bf6873c5SCy Schubert 85*bf6873c5SCy Schubert /* Default to a hidden visibility for all portability functions. */ 86*bf6873c5SCy Schubert #pragma GCC visibility push(hidden) 87*bf6873c5SCy Schubert 88*bf6873c5SCy Schubert /* 89*bf6873c5SCy Schubert * AIX included Kerberos includes the profile library but not the 90*bf6873c5SCy Schubert * krb5_appdefault functions, so we provide replacements that we have to 91*bf6873c5SCy Schubert * prototype. 92*bf6873c5SCy Schubert */ 93*bf6873c5SCy Schubert #ifndef HAVE_KRB5_APPDEFAULT_STRING 94*bf6873c5SCy Schubert void krb5_appdefault_boolean(krb5_context, const char *, const krb5_data *, 95*bf6873c5SCy Schubert const char *, int, int *); 96*bf6873c5SCy Schubert void krb5_appdefault_string(krb5_context, const char *, const krb5_data *, 97*bf6873c5SCy Schubert const char *, const char *, char **); 98*bf6873c5SCy Schubert #endif 99*bf6873c5SCy Schubert 100*bf6873c5SCy Schubert /* 101*bf6873c5SCy Schubert * Now present in both Heimdal and MIT, but very new in MIT and not present in 102*bf6873c5SCy Schubert * older Heimdal. 103*bf6873c5SCy Schubert */ 104*bf6873c5SCy Schubert #ifndef HAVE_KRB5_CC_GET_FULL_NAME 105*bf6873c5SCy Schubert krb5_error_code krb5_cc_get_full_name(krb5_context, krb5_ccache, char **); 106*bf6873c5SCy Schubert #endif 107*bf6873c5SCy Schubert 108*bf6873c5SCy Schubert /* Heimdal: krb5_data_free, MIT: krb5_free_data_contents. */ 109*bf6873c5SCy Schubert #ifdef HAVE_KRB5_DATA_FREE 110*bf6873c5SCy Schubert # define krb5_free_data_contents(c, d) krb5_data_free(d) 111*bf6873c5SCy Schubert #endif 112*bf6873c5SCy Schubert 113*bf6873c5SCy Schubert /* 114*bf6873c5SCy Schubert * MIT-specific. The Heimdal documentation says to use free(), but that 115*bf6873c5SCy Schubert * doesn't actually make sense since the memory is allocated inside the 116*bf6873c5SCy Schubert * Kerberos library. Use krb5_xfree instead. 117*bf6873c5SCy Schubert */ 118*bf6873c5SCy Schubert #ifndef HAVE_KRB5_FREE_DEFAULT_REALM 119*bf6873c5SCy Schubert # define krb5_free_default_realm(c, r) krb5_xfree(r) 120*bf6873c5SCy Schubert #endif 121*bf6873c5SCy Schubert 122*bf6873c5SCy Schubert /* 123*bf6873c5SCy Schubert * Heimdal: krb5_xfree, MIT: krb5_free_string, older MIT uses free(). Note 124*bf6873c5SCy Schubert * that we can incorrectly allocate in the library and call free() if 125*bf6873c5SCy Schubert * krb5_free_string is not available but something we use that API for is 126*bf6873c5SCy Schubert * available, such as krb5_appdefaults_*, but there isn't anything we can 127*bf6873c5SCy Schubert * really do about it. 128*bf6873c5SCy Schubert */ 129*bf6873c5SCy Schubert #ifndef HAVE_KRB5_FREE_STRING 130*bf6873c5SCy Schubert # ifdef HAVE_KRB5_XFREE 131*bf6873c5SCy Schubert # define krb5_free_string(c, s) krb5_xfree(s) 132*bf6873c5SCy Schubert # else 133*bf6873c5SCy Schubert # define krb5_free_string(c, s) free(s) 134*bf6873c5SCy Schubert # endif 135*bf6873c5SCy Schubert #endif 136*bf6873c5SCy Schubert 137*bf6873c5SCy Schubert /* Heimdal: krb5_xfree, MIT: krb5_free_unparsed_name. */ 138*bf6873c5SCy Schubert #ifdef HAVE_KRB5_XFREE 139*bf6873c5SCy Schubert # define krb5_free_unparsed_name(c, p) krb5_xfree(p) 140*bf6873c5SCy Schubert #endif 141*bf6873c5SCy Schubert 142*bf6873c5SCy Schubert /* 143*bf6873c5SCy Schubert * krb5_{get,free}_error_message are the preferred APIs for both current MIT 144*bf6873c5SCy Schubert * and current Heimdal, but there are tons of older APIs we may have to fall 145*bf6873c5SCy Schubert * back on for earlier versions. 146*bf6873c5SCy Schubert * 147*bf6873c5SCy Schubert * This function should be called immediately after the corresponding error 148*bf6873c5SCy Schubert * without any intervening Kerberos calls. Otherwise, the correct error 149*bf6873c5SCy Schubert * message and supporting information may not be returned. 150*bf6873c5SCy Schubert */ 151*bf6873c5SCy Schubert #ifndef HAVE_KRB5_GET_ERROR_MESSAGE 152*bf6873c5SCy Schubert const char *krb5_get_error_message(krb5_context, krb5_error_code); 153*bf6873c5SCy Schubert #endif 154*bf6873c5SCy Schubert #ifndef HAVE_KRB5_FREE_ERROR_MESSAGE 155*bf6873c5SCy Schubert void krb5_free_error_message(krb5_context, const char *); 156*bf6873c5SCy Schubert #endif 157*bf6873c5SCy Schubert 158*bf6873c5SCy Schubert /* 159*bf6873c5SCy Schubert * Both current MIT and current Heimdal prefer _opt_alloc and _opt_free, but 160*bf6873c5SCy Schubert * older versions of both require allocating your own struct and calling 161*bf6873c5SCy Schubert * _opt_init. 162*bf6873c5SCy Schubert */ 163*bf6873c5SCy Schubert #ifndef HAVE_KRB5_GET_INIT_CREDS_OPT_ALLOC 164*bf6873c5SCy Schubert krb5_error_code krb5_get_init_creds_opt_alloc(krb5_context, 165*bf6873c5SCy Schubert krb5_get_init_creds_opt **); 166*bf6873c5SCy Schubert #endif 167*bf6873c5SCy Schubert #ifdef HAVE_KRB5_GET_INIT_CREDS_OPT_FREE 168*bf6873c5SCy Schubert # ifndef HAVE_KRB5_GET_INIT_CREDS_OPT_FREE_2_ARGS 169*bf6873c5SCy Schubert # define krb5_get_init_creds_opt_free(c, o) \ 170*bf6873c5SCy Schubert krb5_get_init_creds_opt_free(o) 171*bf6873c5SCy Schubert # endif 172*bf6873c5SCy Schubert #else 173*bf6873c5SCy Schubert # define krb5_get_init_creds_opt_free(c, o) free(o) 174*bf6873c5SCy Schubert #endif 175*bf6873c5SCy Schubert 176*bf6873c5SCy Schubert /* Not available in versions of Heimdal prior to 7.0.1. */ 177*bf6873c5SCy Schubert #ifndef HAVE_KRB5_GET_INIT_CREDS_OPT_SET_CHANGE_PASSWORD_PROMPT 178*bf6873c5SCy Schubert # define krb5_get_init_creds_opt_set_change_password_prompt(o, f) /* */ 179*bf6873c5SCy Schubert #endif 180*bf6873c5SCy Schubert 181*bf6873c5SCy Schubert /* Heimdal-specific. */ 182*bf6873c5SCy Schubert #ifndef HAVE_KRB5_GET_INIT_CREDS_OPT_SET_DEFAULT_FLAGS 183*bf6873c5SCy Schubert # define krb5_get_init_creds_opt_set_default_flags(c, p, r, o) /* empty */ 184*bf6873c5SCy Schubert #endif 185*bf6873c5SCy Schubert 186*bf6873c5SCy Schubert /* 187*bf6873c5SCy Schubert * Old versions of Heimdal (0.7 and earlier) take only nine arguments to the 188*bf6873c5SCy Schubert * krb5_get_init_creds_opt_set_pkinit instead of the 11 arguments that current 189*bf6873c5SCy Schubert * versions take. Adjust if needed. This function is Heimdal-specific. 190*bf6873c5SCy Schubert */ 191*bf6873c5SCy Schubert #ifdef HAVE_KRB5_GET_INIT_CREDS_OPT_SET_PKINIT 192*bf6873c5SCy Schubert # ifdef HAVE_KRB5_GET_INIT_CREDS_OPT_SET_PKINIT_9_ARGS 193*bf6873c5SCy Schubert # define krb5_get_init_creds_opt_set_pkinit(c, o, p, u, a, l, r, f, m, \ 194*bf6873c5SCy Schubert d, s) \ 195*bf6873c5SCy Schubert krb5_get_init_creds_opt_set_pkinit((c), (o), (p), (u), (a), (f), \ 196*bf6873c5SCy Schubert (m), (d), (s)); 197*bf6873c5SCy Schubert # endif 198*bf6873c5SCy Schubert #endif 199*bf6873c5SCy Schubert 200*bf6873c5SCy Schubert /* 201*bf6873c5SCy Schubert * MIT-specific. Heimdal automatically ignores environment variables if 202*bf6873c5SCy Schubert * called in a setuid context. 203*bf6873c5SCy Schubert */ 204*bf6873c5SCy Schubert #ifndef HAVE_KRB5_INIT_SECURE_CONTEXT 205*bf6873c5SCy Schubert # define krb5_init_secure_context(c) krb5_init_context(c) 206*bf6873c5SCy Schubert #endif 207*bf6873c5SCy Schubert 208*bf6873c5SCy Schubert /* 209*bf6873c5SCy Schubert * Heimdal: krb5_kt_free_entry, MIT: krb5_free_keytab_entry_contents. We 210*bf6873c5SCy Schubert * check for the declaration rather than the function since the function is 211*bf6873c5SCy Schubert * present in older MIT Kerberos libraries but not prototyped. 212*bf6873c5SCy Schubert */ 213*bf6873c5SCy Schubert #if !HAVE_DECL_KRB5_KT_FREE_ENTRY 214*bf6873c5SCy Schubert # define krb5_kt_free_entry(c, e) krb5_free_keytab_entry_contents((c), (e)) 215*bf6873c5SCy Schubert #endif 216*bf6873c5SCy Schubert 217*bf6873c5SCy Schubert /* 218*bf6873c5SCy Schubert * Heimdal provides a nice function that just returns a const char *. On MIT, 219*bf6873c5SCy Schubert * there's an accessor macro that returns the krb5_data pointer, which 220*bf6873c5SCy Schubert * requires more work to get at the underlying char *. 221*bf6873c5SCy Schubert */ 222*bf6873c5SCy Schubert #ifndef HAVE_KRB5_PRINCIPAL_GET_REALM 223*bf6873c5SCy Schubert const char *krb5_principal_get_realm(krb5_context, krb5_const_principal); 224*bf6873c5SCy Schubert #endif 225*bf6873c5SCy Schubert 226*bf6873c5SCy Schubert /* 227*bf6873c5SCy Schubert * krb5_change_password is deprecated in favor of krb5_set_password in current 228*bf6873c5SCy Schubert * Heimdal. Current MIT provides both. 229*bf6873c5SCy Schubert */ 230*bf6873c5SCy Schubert #ifndef HAVE_KRB5_SET_PASSWORD 231*bf6873c5SCy Schubert # define krb5_set_password(c, cr, pw, p, rc, rcs, rs) \ 232*bf6873c5SCy Schubert krb5_change_password((c), (cr), (pw), (rc), (rcs), (rs)) 233*bf6873c5SCy Schubert #endif 234*bf6873c5SCy Schubert 235*bf6873c5SCy Schubert /* 236*bf6873c5SCy Schubert * AIX's NAS Kerberos implementation mysteriously provides the struct and the 237*bf6873c5SCy Schubert * krb5_verify_init_creds function but not this function. 238*bf6873c5SCy Schubert */ 239*bf6873c5SCy Schubert #ifndef HAVE_KRB5_VERIFY_INIT_CREDS_OPT_INIT 240*bf6873c5SCy Schubert void krb5_verify_init_creds_opt_init(krb5_verify_init_creds_opt *opt); 241*bf6873c5SCy Schubert #endif 242*bf6873c5SCy Schubert 243*bf6873c5SCy Schubert /* Undo default visibility change. */ 244*bf6873c5SCy Schubert #pragma GCC visibility pop 245*bf6873c5SCy Schubert 246*bf6873c5SCy Schubert END_DECLS 247*bf6873c5SCy Schubert 248*bf6873c5SCy Schubert #endif /* !PORTABLE_KRB5_H */ 249