1b528cefcSMark Murray /* 2*ae771770SStanislav Sedov * Copyright (c) 1997 - 2005 Kungliga Tekniska Högskolan 3b528cefcSMark Murray * (Royal Institute of Technology, Stockholm, Sweden). 4b528cefcSMark Murray * All rights reserved. 5b528cefcSMark Murray * 6b528cefcSMark Murray * Redistribution and use in source and binary forms, with or without 7b528cefcSMark Murray * modification, are permitted provided that the following conditions 8b528cefcSMark Murray * are met: 9b528cefcSMark Murray * 10b528cefcSMark Murray * 1. Redistributions of source code must retain the above copyright 11b528cefcSMark Murray * notice, this list of conditions and the following disclaimer. 12b528cefcSMark Murray * 13b528cefcSMark Murray * 2. Redistributions in binary form must reproduce the above copyright 14b528cefcSMark Murray * notice, this list of conditions and the following disclaimer in the 15b528cefcSMark Murray * documentation and/or other materials provided with the distribution. 16b528cefcSMark Murray * 17b528cefcSMark Murray * 3. Neither the name of the Institute nor the names of its contributors 18b528cefcSMark Murray * may be used to endorse or promote products derived from this software 19b528cefcSMark Murray * without specific prior written permission. 20b528cefcSMark Murray * 21b528cefcSMark Murray * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 22b528cefcSMark Murray * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23b528cefcSMark Murray * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24b528cefcSMark Murray * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 25b528cefcSMark Murray * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26b528cefcSMark Murray * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27b528cefcSMark Murray * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28b528cefcSMark Murray * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29b528cefcSMark Murray * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30b528cefcSMark Murray * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31b528cefcSMark Murray * SUCH DAMAGE. 32b528cefcSMark Murray */ 33b528cefcSMark Murray 34b528cefcSMark Murray #include "krb5_locl.h" 35b528cefcSMark Murray 36*ae771770SStanislav Sedov /** 37*ae771770SStanislav Sedov * @page krb5_keytab_intro The keytab handing functions 38*ae771770SStanislav Sedov * @section section_krb5_keytab Kerberos Keytabs 39*ae771770SStanislav Sedov * 40*ae771770SStanislav Sedov * See the library functions here: @ref krb5_keytab 41*ae771770SStanislav Sedov * 42*ae771770SStanislav Sedov * Keytabs are long term key storage for servers, their equvalment of 43*ae771770SStanislav Sedov * password files. 44*ae771770SStanislav Sedov * 45*ae771770SStanislav Sedov * Normally the only function that useful for server are to specify 46*ae771770SStanislav Sedov * what keytab to use to other core functions like krb5_rd_req() 47*ae771770SStanislav Sedov * krb5_kt_resolve(), and krb5_kt_close(). 48*ae771770SStanislav Sedov * 49*ae771770SStanislav Sedov * @subsection krb5_keytab_names Keytab names 50*ae771770SStanislav Sedov * 51*ae771770SStanislav Sedov * A keytab name is on the form type:residual. The residual part is 52*ae771770SStanislav Sedov * specific to each keytab-type. 53*ae771770SStanislav Sedov * 54*ae771770SStanislav Sedov * When a keytab-name is resolved, the type is matched with an internal 55*ae771770SStanislav Sedov * list of keytab types. If there is no matching keytab type, 56*ae771770SStanislav Sedov * the default keytab is used. The current default type is FILE. 57*ae771770SStanislav Sedov * 58*ae771770SStanislav Sedov * The default value can be changed in the configuration file 59*ae771770SStanislav Sedov * /etc/krb5.conf by setting the variable 60*ae771770SStanislav Sedov * [defaults]default_keytab_name. 61*ae771770SStanislav Sedov * 62*ae771770SStanislav Sedov * The keytab types that are implemented in Heimdal are: 63*ae771770SStanislav Sedov * - file 64*ae771770SStanislav Sedov * store the keytab in a file, the type's name is FILE . The 65*ae771770SStanislav Sedov * residual part is a filename. For compatibility with other 66*ae771770SStanislav Sedov * Kerberos implemtation WRFILE and JAVA14 is also accepted. WRFILE 67*ae771770SStanislav Sedov * has the same format as FILE. JAVA14 have a format that is 68*ae771770SStanislav Sedov * compatible with older versions of MIT kerberos and SUN's Java 69*ae771770SStanislav Sedov * based installation. They store a truncted kvno, so when the knvo 70*ae771770SStanislav Sedov * excess 255, they are truncted in this format. 71*ae771770SStanislav Sedov * 72*ae771770SStanislav Sedov * - keytab 73*ae771770SStanislav Sedov * store the keytab in a AFS keyfile (usually /usr/afs/etc/KeyFile ), 74*ae771770SStanislav Sedov * the type's name is AFSKEYFILE. The residual part is a filename. 75*ae771770SStanislav Sedov * 76*ae771770SStanislav Sedov * - memory 77*ae771770SStanislav Sedov * The keytab is stored in a memory segment. This allows sensitive 78*ae771770SStanislav Sedov * and/or temporary data not to be stored on disk. The type's name 79*ae771770SStanislav Sedov * is MEMORY. Each MEMORY keytab is referenced counted by and 80*ae771770SStanislav Sedov * opened by the residual name, so two handles can point to the 81*ae771770SStanislav Sedov * same memory area. When the last user closes using krb5_kt_close() 82*ae771770SStanislav Sedov * the keytab, the keys in they keytab is memset() to zero and freed 83*ae771770SStanislav Sedov * and can no longer be looked up by name. 84*ae771770SStanislav Sedov * 85*ae771770SStanislav Sedov * 86*ae771770SStanislav Sedov * @subsection krb5_keytab_example Keytab example 87*ae771770SStanislav Sedov * 88*ae771770SStanislav Sedov * This is a minimalistic version of ktutil. 89*ae771770SStanislav Sedov * 90*ae771770SStanislav Sedov * @code 91*ae771770SStanislav Sedov int 92*ae771770SStanislav Sedov main (int argc, char **argv) 93*ae771770SStanislav Sedov { 94*ae771770SStanislav Sedov krb5_context context; 95*ae771770SStanislav Sedov krb5_keytab keytab; 96*ae771770SStanislav Sedov krb5_kt_cursor cursor; 97*ae771770SStanislav Sedov krb5_keytab_entry entry; 98*ae771770SStanislav Sedov krb5_error_code ret; 99*ae771770SStanislav Sedov char *principal; 100b528cefcSMark Murray 101*ae771770SStanislav Sedov if (krb5_init_context (&context) != 0) 102*ae771770SStanislav Sedov errx(1, "krb5_context"); 103*ae771770SStanislav Sedov 104*ae771770SStanislav Sedov ret = krb5_kt_default (context, &keytab); 105*ae771770SStanislav Sedov if (ret) 106*ae771770SStanislav Sedov krb5_err(context, 1, ret, "krb5_kt_default"); 107*ae771770SStanislav Sedov 108*ae771770SStanislav Sedov ret = krb5_kt_start_seq_get(context, keytab, &cursor); 109*ae771770SStanislav Sedov if (ret) 110*ae771770SStanislav Sedov krb5_err(context, 1, ret, "krb5_kt_start_seq_get"); 111*ae771770SStanislav Sedov while((ret = krb5_kt_next_entry(context, keytab, &entry, &cursor)) == 0){ 112*ae771770SStanislav Sedov krb5_unparse_name(context, entry.principal, &principal); 113*ae771770SStanislav Sedov printf("principal: %s\n", principal); 114*ae771770SStanislav Sedov free(principal); 115*ae771770SStanislav Sedov krb5_kt_free_entry(context, &entry); 116*ae771770SStanislav Sedov } 117*ae771770SStanislav Sedov ret = krb5_kt_end_seq_get(context, keytab, &cursor); 118*ae771770SStanislav Sedov if (ret) 119*ae771770SStanislav Sedov krb5_err(context, 1, ret, "krb5_kt_end_seq_get"); 120*ae771770SStanislav Sedov ret = krb5_kt_close(context, keytab); 121*ae771770SStanislav Sedov if (ret) 122*ae771770SStanislav Sedov krb5_err(context, 1, ret, "krb5_kt_close"); 123*ae771770SStanislav Sedov krb5_free_context(context); 124*ae771770SStanislav Sedov return 0; 125*ae771770SStanislav Sedov } 126*ae771770SStanislav Sedov * @endcode 127*ae771770SStanislav Sedov * 128b528cefcSMark Murray */ 129b528cefcSMark Murray 130*ae771770SStanislav Sedov 131*ae771770SStanislav Sedov /** 132*ae771770SStanislav Sedov * Register a new keytab backend. 133*ae771770SStanislav Sedov * 134*ae771770SStanislav Sedov * @param context a Keberos context. 135*ae771770SStanislav Sedov * @param ops a backend to register. 136*ae771770SStanislav Sedov * 137*ae771770SStanislav Sedov * @return Return an error code or 0, see krb5_get_error_message(). 138*ae771770SStanislav Sedov * 139*ae771770SStanislav Sedov * @ingroup krb5_keytab 140*ae771770SStanislav Sedov */ 141*ae771770SStanislav Sedov 142*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 143b528cefcSMark Murray krb5_kt_register(krb5_context context, 144b528cefcSMark Murray const krb5_kt_ops *ops) 145b528cefcSMark Murray { 146b528cefcSMark Murray struct krb5_keytab_data *tmp; 147b528cefcSMark Murray 148bbd80c28SJacques Vidrine if (strlen(ops->prefix) > KRB5_KT_PREFIX_MAX_LEN - 1) { 149*ae771770SStanislav Sedov krb5_set_error_message(context, KRB5_KT_BADNAME, 150*ae771770SStanislav Sedov N_("can't register cache type, prefix too long", "")); 151c19800e8SDoug Rabson return KRB5_KT_BADNAME; 152bbd80c28SJacques Vidrine } 153bbd80c28SJacques Vidrine 154b528cefcSMark Murray tmp = realloc(context->kt_types, 155b528cefcSMark Murray (context->num_kt_types + 1) * sizeof(*context->kt_types)); 156adb0ddaeSAssar Westerlund if(tmp == NULL) { 157*ae771770SStanislav Sedov krb5_set_error_message(context, ENOMEM, 158*ae771770SStanislav Sedov N_("malloc: out of memory", "")); 159b528cefcSMark Murray return ENOMEM; 160adb0ddaeSAssar Westerlund } 161b528cefcSMark Murray memcpy(&tmp[context->num_kt_types], ops, 162b528cefcSMark Murray sizeof(tmp[context->num_kt_types])); 163b528cefcSMark Murray context->kt_types = tmp; 164b528cefcSMark Murray context->num_kt_types++; 165b528cefcSMark Murray return 0; 166b528cefcSMark Murray } 167b528cefcSMark Murray 168*ae771770SStanislav Sedov static const char * 169*ae771770SStanislav Sedov keytab_name(const char *name, const char **type, size_t *type_len) 170*ae771770SStanislav Sedov { 171*ae771770SStanislav Sedov const char *residual; 172*ae771770SStanislav Sedov 173*ae771770SStanislav Sedov residual = strchr(name, ':'); 174*ae771770SStanislav Sedov 175*ae771770SStanislav Sedov if (residual == NULL || 176*ae771770SStanislav Sedov name[0] == '/' 177*ae771770SStanislav Sedov #ifdef _WIN32 178*ae771770SStanislav Sedov /* Avoid treating <drive>:<path> as a keytab type 179*ae771770SStanislav Sedov * specification */ 180*ae771770SStanislav Sedov || name + 1 == residual 181*ae771770SStanislav Sedov #endif 182*ae771770SStanislav Sedov ) { 183*ae771770SStanislav Sedov 184*ae771770SStanislav Sedov *type = "FILE"; 185*ae771770SStanislav Sedov *type_len = strlen(*type); 186*ae771770SStanislav Sedov residual = name; 187*ae771770SStanislav Sedov } else { 188*ae771770SStanislav Sedov *type = name; 189*ae771770SStanislav Sedov *type_len = residual - name; 190*ae771770SStanislav Sedov residual++; 191*ae771770SStanislav Sedov } 192*ae771770SStanislav Sedov 193*ae771770SStanislav Sedov return residual; 194*ae771770SStanislav Sedov } 195*ae771770SStanislav Sedov 196*ae771770SStanislav Sedov /** 197b528cefcSMark Murray * Resolve the keytab name (of the form `type:residual') in `name' 198b528cefcSMark Murray * into a keytab in `id'. 199*ae771770SStanislav Sedov * 200*ae771770SStanislav Sedov * @param context a Keberos context. 201*ae771770SStanislav Sedov * @param name name to resolve 202*ae771770SStanislav Sedov * @param id resulting keytab, free with krb5_kt_close(). 203*ae771770SStanislav Sedov * 204*ae771770SStanislav Sedov * @return Return an error code or 0, see krb5_get_error_message(). 205*ae771770SStanislav Sedov * 206*ae771770SStanislav Sedov * @ingroup krb5_keytab 207b528cefcSMark Murray */ 208b528cefcSMark Murray 209*ae771770SStanislav Sedov 210*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 211b528cefcSMark Murray krb5_kt_resolve(krb5_context context, 212b528cefcSMark Murray const char *name, 213b528cefcSMark Murray krb5_keytab *id) 214b528cefcSMark Murray { 215b528cefcSMark Murray krb5_keytab k; 216b528cefcSMark Murray int i; 217b528cefcSMark Murray const char *type, *residual; 218b528cefcSMark Murray size_t type_len; 219b528cefcSMark Murray krb5_error_code ret; 220b528cefcSMark Murray 221*ae771770SStanislav Sedov residual = keytab_name(name, &type, &type_len); 222b528cefcSMark Murray 223b528cefcSMark Murray for(i = 0; i < context->num_kt_types; i++) { 2244137ff4cSJacques Vidrine if(strncasecmp(type, context->kt_types[i].prefix, type_len) == 0) 225b528cefcSMark Murray break; 226b528cefcSMark Murray } 227adb0ddaeSAssar Westerlund if(i == context->num_kt_types) { 228*ae771770SStanislav Sedov krb5_set_error_message(context, KRB5_KT_UNKNOWN_TYPE, 229*ae771770SStanislav Sedov N_("unknown keytab type %.*s", "type"), 230adb0ddaeSAssar Westerlund (int)type_len, type); 231b528cefcSMark Murray return KRB5_KT_UNKNOWN_TYPE; 232adb0ddaeSAssar Westerlund } 233b528cefcSMark Murray 234b528cefcSMark Murray k = malloc (sizeof(*k)); 235adb0ddaeSAssar Westerlund if (k == NULL) { 236*ae771770SStanislav Sedov krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); 237b528cefcSMark Murray return ENOMEM; 238adb0ddaeSAssar Westerlund } 239b528cefcSMark Murray memcpy(k, &context->kt_types[i], sizeof(*k)); 240b528cefcSMark Murray k->data = NULL; 241b528cefcSMark Murray ret = (*k->resolve)(context, residual, k); 242b528cefcSMark Murray if(ret) { 243b528cefcSMark Murray free(k); 244b528cefcSMark Murray k = NULL; 245b528cefcSMark Murray } 246b528cefcSMark Murray *id = k; 247b528cefcSMark Murray return ret; 248b528cefcSMark Murray } 249b528cefcSMark Murray 250*ae771770SStanislav Sedov /** 251b528cefcSMark Murray * copy the name of the default keytab into `name'. 252*ae771770SStanislav Sedov * 253*ae771770SStanislav Sedov * @param context a Keberos context. 254*ae771770SStanislav Sedov * @param name buffer where the name will be written 255*ae771770SStanislav Sedov * @param namesize length of name 256*ae771770SStanislav Sedov * 257*ae771770SStanislav Sedov * @return Return an error code or 0, see krb5_get_error_message(). 258*ae771770SStanislav Sedov * 259*ae771770SStanislav Sedov * @ingroup krb5_keytab 260b528cefcSMark Murray */ 261b528cefcSMark Murray 262*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 263b528cefcSMark Murray krb5_kt_default_name(krb5_context context, char *name, size_t namesize) 264b528cefcSMark Murray { 265adb0ddaeSAssar Westerlund if (strlcpy (name, context->default_keytab, namesize) >= namesize) { 266*ae771770SStanislav Sedov krb5_clear_error_message (context); 267b528cefcSMark Murray return KRB5_CONFIG_NOTENUFSPACE; 268adb0ddaeSAssar Westerlund } 269adb0ddaeSAssar Westerlund return 0; 270adb0ddaeSAssar Westerlund } 271adb0ddaeSAssar Westerlund 272*ae771770SStanislav Sedov /** 273*ae771770SStanislav Sedov * Copy the name of the default modify keytab into `name'. 274*ae771770SStanislav Sedov * 275*ae771770SStanislav Sedov * @param context a Keberos context. 276*ae771770SStanislav Sedov * @param name buffer where the name will be written 277*ae771770SStanislav Sedov * @param namesize length of name 278*ae771770SStanislav Sedov * 279*ae771770SStanislav Sedov * @return Return an error code or 0, see krb5_get_error_message(). 280*ae771770SStanislav Sedov * 281*ae771770SStanislav Sedov * @ingroup krb5_keytab 282adb0ddaeSAssar Westerlund */ 283adb0ddaeSAssar Westerlund 284*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 285adb0ddaeSAssar Westerlund krb5_kt_default_modify_name(krb5_context context, char *name, size_t namesize) 286adb0ddaeSAssar Westerlund { 2874137ff4cSJacques Vidrine const char *kt = NULL; 2884137ff4cSJacques Vidrine if(context->default_keytab_modify == NULL) { 2894137ff4cSJacques Vidrine if(strncasecmp(context->default_keytab, "ANY:", 4) != 0) 2904137ff4cSJacques Vidrine kt = context->default_keytab; 2914137ff4cSJacques Vidrine else { 2924137ff4cSJacques Vidrine size_t len = strcspn(context->default_keytab + 4, ","); 2934137ff4cSJacques Vidrine if(len >= namesize) { 294*ae771770SStanislav Sedov krb5_clear_error_message(context); 2954137ff4cSJacques Vidrine return KRB5_CONFIG_NOTENUFSPACE; 2964137ff4cSJacques Vidrine } 2974137ff4cSJacques Vidrine strlcpy(name, context->default_keytab + 4, namesize); 2984137ff4cSJacques Vidrine name[len] = '\0'; 2994137ff4cSJacques Vidrine return 0; 3004137ff4cSJacques Vidrine } 3014137ff4cSJacques Vidrine } else 3024137ff4cSJacques Vidrine kt = context->default_keytab_modify; 3034137ff4cSJacques Vidrine if (strlcpy (name, kt, namesize) >= namesize) { 304*ae771770SStanislav Sedov krb5_clear_error_message (context); 305adb0ddaeSAssar Westerlund return KRB5_CONFIG_NOTENUFSPACE; 306adb0ddaeSAssar Westerlund } 307b528cefcSMark Murray return 0; 308b528cefcSMark Murray } 309b528cefcSMark Murray 310*ae771770SStanislav Sedov /** 311b528cefcSMark Murray * Set `id' to the default keytab. 312*ae771770SStanislav Sedov * 313*ae771770SStanislav Sedov * @param context a Keberos context. 314*ae771770SStanislav Sedov * @param id the new default keytab. 315*ae771770SStanislav Sedov * 316*ae771770SStanislav Sedov * @return Return an error code or 0, see krb5_get_error_message(). 317*ae771770SStanislav Sedov * 318*ae771770SStanislav Sedov * @ingroup krb5_keytab 319b528cefcSMark Murray */ 320b528cefcSMark Murray 321*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 322b528cefcSMark Murray krb5_kt_default(krb5_context context, krb5_keytab *id) 323b528cefcSMark Murray { 324b528cefcSMark Murray return krb5_kt_resolve (context, context->default_keytab, id); 325b528cefcSMark Murray } 326b528cefcSMark Murray 327*ae771770SStanislav Sedov /** 328b528cefcSMark Murray * Read the key identified by `(principal, vno, enctype)' from the 329b528cefcSMark Murray * keytab in `keyprocarg' (the default if == NULL) into `*key'. 330*ae771770SStanislav Sedov * 331*ae771770SStanislav Sedov * @param context a Keberos context. 332*ae771770SStanislav Sedov * @param keyprocarg 333*ae771770SStanislav Sedov * @param principal 334*ae771770SStanislav Sedov * @param vno 335*ae771770SStanislav Sedov * @param enctype 336*ae771770SStanislav Sedov * @param key 337*ae771770SStanislav Sedov * 338*ae771770SStanislav Sedov * @return Return an error code or 0, see krb5_get_error_message(). 339*ae771770SStanislav Sedov * 340*ae771770SStanislav Sedov * @ingroup krb5_keytab 341b528cefcSMark Murray */ 342b528cefcSMark Murray 343*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 344b528cefcSMark Murray krb5_kt_read_service_key(krb5_context context, 345b528cefcSMark Murray krb5_pointer keyprocarg, 346b528cefcSMark Murray krb5_principal principal, 347b528cefcSMark Murray krb5_kvno vno, 348b528cefcSMark Murray krb5_enctype enctype, 349b528cefcSMark Murray krb5_keyblock **key) 350b528cefcSMark Murray { 351b528cefcSMark Murray krb5_keytab keytab; 352b528cefcSMark Murray krb5_keytab_entry entry; 353b528cefcSMark Murray krb5_error_code ret; 354b528cefcSMark Murray 355b528cefcSMark Murray if (keyprocarg) 356b528cefcSMark Murray ret = krb5_kt_resolve (context, keyprocarg, &keytab); 357b528cefcSMark Murray else 358b528cefcSMark Murray ret = krb5_kt_default (context, &keytab); 359b528cefcSMark Murray 360b528cefcSMark Murray if (ret) 361b528cefcSMark Murray return ret; 362b528cefcSMark Murray 363b528cefcSMark Murray ret = krb5_kt_get_entry (context, keytab, principal, vno, enctype, &entry); 364b528cefcSMark Murray krb5_kt_close (context, keytab); 365b528cefcSMark Murray if (ret) 366b528cefcSMark Murray return ret; 367b528cefcSMark Murray ret = krb5_copy_keyblock (context, &entry.keyblock, key); 368b528cefcSMark Murray krb5_kt_free_entry(context, &entry); 369b528cefcSMark Murray return ret; 370b528cefcSMark Murray } 371b528cefcSMark Murray 372*ae771770SStanislav Sedov /** 373bbd80c28SJacques Vidrine * Return the type of the `keytab' in the string `prefix of length 374bbd80c28SJacques Vidrine * `prefixsize'. 375*ae771770SStanislav Sedov * 376*ae771770SStanislav Sedov * @param context a Keberos context. 377*ae771770SStanislav Sedov * @param keytab the keytab to get the prefix for 378*ae771770SStanislav Sedov * @param prefix prefix buffer 379*ae771770SStanislav Sedov * @param prefixsize length of prefix buffer 380*ae771770SStanislav Sedov * 381*ae771770SStanislav Sedov * @return Return an error code or 0, see krb5_get_error_message(). 382*ae771770SStanislav Sedov * 383*ae771770SStanislav Sedov * @ingroup krb5_keytab 384bbd80c28SJacques Vidrine */ 385bbd80c28SJacques Vidrine 386*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 387bbd80c28SJacques Vidrine krb5_kt_get_type(krb5_context context, 388bbd80c28SJacques Vidrine krb5_keytab keytab, 389bbd80c28SJacques Vidrine char *prefix, 390bbd80c28SJacques Vidrine size_t prefixsize) 391bbd80c28SJacques Vidrine { 392bbd80c28SJacques Vidrine strlcpy(prefix, keytab->prefix, prefixsize); 393bbd80c28SJacques Vidrine return 0; 394bbd80c28SJacques Vidrine } 395bbd80c28SJacques Vidrine 396*ae771770SStanislav Sedov /** 397b528cefcSMark Murray * Retrieve the name of the keytab `keytab' into `name', `namesize' 398*ae771770SStanislav Sedov * 399*ae771770SStanislav Sedov * @param context a Keberos context. 400*ae771770SStanislav Sedov * @param keytab the keytab to get the name for. 401*ae771770SStanislav Sedov * @param name name buffer. 402*ae771770SStanislav Sedov * @param namesize size of name buffer. 403*ae771770SStanislav Sedov * 404*ae771770SStanislav Sedov * @return Return an error code or 0, see krb5_get_error_message(). 405*ae771770SStanislav Sedov * 406*ae771770SStanislav Sedov * @ingroup krb5_keytab 407b528cefcSMark Murray */ 408b528cefcSMark Murray 409*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 410b528cefcSMark Murray krb5_kt_get_name(krb5_context context, 411b528cefcSMark Murray krb5_keytab keytab, 412b528cefcSMark Murray char *name, 413b528cefcSMark Murray size_t namesize) 414b528cefcSMark Murray { 415b528cefcSMark Murray return (*keytab->get_name)(context, keytab, name, namesize); 416b528cefcSMark Murray } 417b528cefcSMark Murray 418*ae771770SStanislav Sedov /** 419c19800e8SDoug Rabson * Retrieve the full name of the keytab `keytab' and store the name in 420*ae771770SStanislav Sedov * `str'. 421*ae771770SStanislav Sedov * 422*ae771770SStanislav Sedov * @param context a Keberos context. 423*ae771770SStanislav Sedov * @param keytab keytab to get name for. 424*ae771770SStanislav Sedov * @param str the name of the keytab name, usee krb5_xfree() to free 425*ae771770SStanislav Sedov * the string. On error, *str is set to NULL. 426*ae771770SStanislav Sedov * 427*ae771770SStanislav Sedov * @return Return an error code or 0, see krb5_get_error_message(). 428*ae771770SStanislav Sedov * 429*ae771770SStanislav Sedov * @ingroup krb5_keytab 430b528cefcSMark Murray */ 431b528cefcSMark Murray 432*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 433c19800e8SDoug Rabson krb5_kt_get_full_name(krb5_context context, 434c19800e8SDoug Rabson krb5_keytab keytab, 435c19800e8SDoug Rabson char **str) 436c19800e8SDoug Rabson { 437c19800e8SDoug Rabson char type[KRB5_KT_PREFIX_MAX_LEN]; 438c19800e8SDoug Rabson char name[MAXPATHLEN]; 439c19800e8SDoug Rabson krb5_error_code ret; 440c19800e8SDoug Rabson 441c19800e8SDoug Rabson *str = NULL; 442c19800e8SDoug Rabson 443c19800e8SDoug Rabson ret = krb5_kt_get_type(context, keytab, type, sizeof(type)); 444c19800e8SDoug Rabson if (ret) 445c19800e8SDoug Rabson return ret; 446c19800e8SDoug Rabson 447c19800e8SDoug Rabson ret = krb5_kt_get_name(context, keytab, name, sizeof(name)); 448c19800e8SDoug Rabson if (ret) 449c19800e8SDoug Rabson return ret; 450c19800e8SDoug Rabson 451c19800e8SDoug Rabson if (asprintf(str, "%s:%s", type, name) == -1) { 452*ae771770SStanislav Sedov krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); 453c19800e8SDoug Rabson *str = NULL; 454c19800e8SDoug Rabson return ENOMEM; 455c19800e8SDoug Rabson } 456c19800e8SDoug Rabson 457c19800e8SDoug Rabson return 0; 458c19800e8SDoug Rabson } 459c19800e8SDoug Rabson 460*ae771770SStanislav Sedov /** 461c19800e8SDoug Rabson * Finish using the keytab in `id'. All resources will be released, 462*ae771770SStanislav Sedov * even on errors. 463*ae771770SStanislav Sedov * 464*ae771770SStanislav Sedov * @param context a Keberos context. 465*ae771770SStanislav Sedov * @param id keytab to close. 466*ae771770SStanislav Sedov * 467*ae771770SStanislav Sedov * @return Return an error code or 0, see krb5_get_error_message(). 468*ae771770SStanislav Sedov * 469*ae771770SStanislav Sedov * @ingroup krb5_keytab 470c19800e8SDoug Rabson */ 471c19800e8SDoug Rabson 472*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 473b528cefcSMark Murray krb5_kt_close(krb5_context context, 474b528cefcSMark Murray krb5_keytab id) 475b528cefcSMark Murray { 476b528cefcSMark Murray krb5_error_code ret; 477b528cefcSMark Murray 478b528cefcSMark Murray ret = (*id->close)(context, id); 479c19800e8SDoug Rabson memset(id, 0, sizeof(*id)); 480b528cefcSMark Murray free(id); 481b528cefcSMark Murray return ret; 482b528cefcSMark Murray } 483b528cefcSMark Murray 484*ae771770SStanislav Sedov /** 485*ae771770SStanislav Sedov * Destroy (remove) the keytab in `id'. All resources will be released, 486*ae771770SStanislav Sedov * even on errors, does the equvalment of krb5_kt_close() on the resources. 487*ae771770SStanislav Sedov * 488*ae771770SStanislav Sedov * @param context a Keberos context. 489*ae771770SStanislav Sedov * @param id keytab to destroy. 490*ae771770SStanislav Sedov * 491*ae771770SStanislav Sedov * @return Return an error code or 0, see krb5_get_error_message(). 492*ae771770SStanislav Sedov * 493*ae771770SStanislav Sedov * @ingroup krb5_keytab 494*ae771770SStanislav Sedov */ 495*ae771770SStanislav Sedov 496*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 497*ae771770SStanislav Sedov krb5_kt_destroy(krb5_context context, 498*ae771770SStanislav Sedov krb5_keytab id) 499*ae771770SStanislav Sedov { 500*ae771770SStanislav Sedov krb5_error_code ret; 501*ae771770SStanislav Sedov 502*ae771770SStanislav Sedov ret = (*id->destroy)(context, id); 503*ae771770SStanislav Sedov krb5_kt_close(context, id); 504*ae771770SStanislav Sedov return ret; 505*ae771770SStanislav Sedov } 506*ae771770SStanislav Sedov 507b528cefcSMark Murray /* 508*ae771770SStanislav Sedov * Match any aliases in keytab `entry' with `principal'. 509*ae771770SStanislav Sedov */ 510*ae771770SStanislav Sedov 511*ae771770SStanislav Sedov static krb5_boolean 512*ae771770SStanislav Sedov compare_aliseses(krb5_context context, 513*ae771770SStanislav Sedov krb5_keytab_entry *entry, 514*ae771770SStanislav Sedov krb5_const_principal principal) 515*ae771770SStanislav Sedov { 516*ae771770SStanislav Sedov unsigned int i; 517*ae771770SStanislav Sedov if (entry->aliases == NULL) 518*ae771770SStanislav Sedov return FALSE; 519*ae771770SStanislav Sedov for (i = 0; i < entry->aliases->len; i++) 520*ae771770SStanislav Sedov if (krb5_principal_compare(context, &entry->aliases->val[i], principal)) 521*ae771770SStanislav Sedov return TRUE; 522*ae771770SStanislav Sedov return FALSE; 523*ae771770SStanislav Sedov } 524*ae771770SStanislav Sedov 525*ae771770SStanislav Sedov /** 526b528cefcSMark Murray * Compare `entry' against `principal, vno, enctype'. 527b528cefcSMark Murray * Any of `principal, vno, enctype' might be 0 which acts as a wildcard. 528b528cefcSMark Murray * Return TRUE if they compare the same, FALSE otherwise. 529*ae771770SStanislav Sedov * 530*ae771770SStanislav Sedov * @param context a Keberos context. 531*ae771770SStanislav Sedov * @param entry an entry to match with. 532*ae771770SStanislav Sedov * @param principal principal to match, NULL matches all principals. 533*ae771770SStanislav Sedov * @param vno key version to match, 0 matches all key version numbers. 534*ae771770SStanislav Sedov * @param enctype encryption type to match, 0 matches all encryption types. 535*ae771770SStanislav Sedov * 536*ae771770SStanislav Sedov * @return Return TRUE or match, FALSE if not matched. 537*ae771770SStanislav Sedov * 538*ae771770SStanislav Sedov * @ingroup krb5_keytab 539b528cefcSMark Murray */ 540b528cefcSMark Murray 541*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL 542b528cefcSMark Murray krb5_kt_compare(krb5_context context, 543b528cefcSMark Murray krb5_keytab_entry *entry, 544b528cefcSMark Murray krb5_const_principal principal, 545b528cefcSMark Murray krb5_kvno vno, 546b528cefcSMark Murray krb5_enctype enctype) 547b528cefcSMark Murray { 548b528cefcSMark Murray if(principal != NULL && 549*ae771770SStanislav Sedov !(krb5_principal_compare(context, entry->principal, principal) || 550*ae771770SStanislav Sedov compare_aliseses(context, entry, principal))) 551b528cefcSMark Murray return FALSE; 552b528cefcSMark Murray if(vno && vno != entry->vno) 553b528cefcSMark Murray return FALSE; 554b528cefcSMark Murray if(enctype && enctype != entry->keyblock.keytype) 555b528cefcSMark Murray return FALSE; 556b528cefcSMark Murray return TRUE; 557b528cefcSMark Murray } 558b528cefcSMark Murray 559*ae771770SStanislav Sedov krb5_error_code 560*ae771770SStanislav Sedov _krb5_kt_principal_not_found(krb5_context context, 561*ae771770SStanislav Sedov krb5_error_code ret, 562*ae771770SStanislav Sedov krb5_keytab id, 563*ae771770SStanislav Sedov krb5_const_principal principal, 564*ae771770SStanislav Sedov krb5_enctype enctype, 565*ae771770SStanislav Sedov int kvno) 566*ae771770SStanislav Sedov { 567*ae771770SStanislav Sedov char princ[256], kvno_str[25], *kt_name; 568*ae771770SStanislav Sedov char *enctype_str = NULL; 569*ae771770SStanislav Sedov 570*ae771770SStanislav Sedov krb5_unparse_name_fixed (context, principal, princ, sizeof(princ)); 571*ae771770SStanislav Sedov krb5_kt_get_full_name (context, id, &kt_name); 572*ae771770SStanislav Sedov krb5_enctype_to_string(context, enctype, &enctype_str); 573*ae771770SStanislav Sedov 574*ae771770SStanislav Sedov if (kvno) 575*ae771770SStanislav Sedov snprintf(kvno_str, sizeof(kvno_str), "(kvno %d)", kvno); 576*ae771770SStanislav Sedov else 577*ae771770SStanislav Sedov kvno_str[0] = '\0'; 578*ae771770SStanislav Sedov 579*ae771770SStanislav Sedov krb5_set_error_message (context, ret, 580*ae771770SStanislav Sedov N_("Failed to find %s%s in keytab %s (%s)", 581*ae771770SStanislav Sedov "principal, kvno, keytab file, enctype"), 582*ae771770SStanislav Sedov princ, 583*ae771770SStanislav Sedov kvno_str, 584*ae771770SStanislav Sedov kt_name ? kt_name : "unknown keytab", 585*ae771770SStanislav Sedov enctype_str ? enctype_str : "unknown enctype"); 586*ae771770SStanislav Sedov free(kt_name); 587*ae771770SStanislav Sedov free(enctype_str); 588*ae771770SStanislav Sedov return ret; 589*ae771770SStanislav Sedov } 590*ae771770SStanislav Sedov 591*ae771770SStanislav Sedov 592*ae771770SStanislav Sedov /** 593b528cefcSMark Murray * Retrieve the keytab entry for `principal, kvno, enctype' into `entry' 594*ae771770SStanislav Sedov * from the keytab `id'. Matching is done like krb5_kt_compare(). 595*ae771770SStanislav Sedov * 596*ae771770SStanislav Sedov * @param context a Keberos context. 597*ae771770SStanislav Sedov * @param id a keytab. 598*ae771770SStanislav Sedov * @param principal principal to match, NULL matches all principals. 599*ae771770SStanislav Sedov * @param kvno key version to match, 0 matches all key version numbers. 600*ae771770SStanislav Sedov * @param enctype encryption type to match, 0 matches all encryption types. 601*ae771770SStanislav Sedov * @param entry the returned entry, free with krb5_kt_free_entry(). 602*ae771770SStanislav Sedov * 603*ae771770SStanislav Sedov * @return Return an error code or 0, see krb5_get_error_message(). 604*ae771770SStanislav Sedov * 605*ae771770SStanislav Sedov * @ingroup krb5_keytab 606b528cefcSMark Murray */ 607b528cefcSMark Murray 608*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 609b528cefcSMark Murray krb5_kt_get_entry(krb5_context context, 610b528cefcSMark Murray krb5_keytab id, 611b528cefcSMark Murray krb5_const_principal principal, 612b528cefcSMark Murray krb5_kvno kvno, 613b528cefcSMark Murray krb5_enctype enctype, 614b528cefcSMark Murray krb5_keytab_entry *entry) 615b528cefcSMark Murray { 616b528cefcSMark Murray krb5_keytab_entry tmp; 617b528cefcSMark Murray krb5_error_code ret; 618b528cefcSMark Murray krb5_kt_cursor cursor; 619b528cefcSMark Murray 620b528cefcSMark Murray if(id->get) 621b528cefcSMark Murray return (*id->get)(context, id, principal, kvno, enctype, entry); 622b528cefcSMark Murray 623b528cefcSMark Murray ret = krb5_kt_start_seq_get (context, id, &cursor); 624c19800e8SDoug Rabson if (ret) { 625*ae771770SStanislav Sedov /* This is needed for krb5_verify_init_creds, but keep error 626*ae771770SStanislav Sedov * string from previous error for the human. */ 627*ae771770SStanislav Sedov context->error_code = KRB5_KT_NOTFOUND; 628*ae771770SStanislav Sedov return KRB5_KT_NOTFOUND; 629c19800e8SDoug Rabson } 630b528cefcSMark Murray 631b528cefcSMark Murray entry->vno = 0; 632b528cefcSMark Murray while (krb5_kt_next_entry(context, id, &tmp, &cursor) == 0) { 633b528cefcSMark Murray if (krb5_kt_compare(context, &tmp, principal, 0, enctype)) { 6348373020dSJacques Vidrine /* the file keytab might only store the lower 8 bits of 6358373020dSJacques Vidrine the kvno, so only compare those bits */ 6368373020dSJacques Vidrine if (kvno == tmp.vno 6378373020dSJacques Vidrine || (tmp.vno < 256 && kvno % 256 == tmp.vno)) { 638b528cefcSMark Murray krb5_kt_copy_entry_contents (context, &tmp, entry); 639b528cefcSMark Murray krb5_kt_free_entry (context, &tmp); 640b528cefcSMark Murray krb5_kt_end_seq_get(context, id, &cursor); 641b528cefcSMark Murray return 0; 642b528cefcSMark Murray } else if (kvno == 0 && tmp.vno > entry->vno) { 643b528cefcSMark Murray if (entry->vno) 644b528cefcSMark Murray krb5_kt_free_entry (context, entry); 645b528cefcSMark Murray krb5_kt_copy_entry_contents (context, &tmp, entry); 646b528cefcSMark Murray } 647b528cefcSMark Murray } 648b528cefcSMark Murray krb5_kt_free_entry(context, &tmp); 649b528cefcSMark Murray } 650b528cefcSMark Murray krb5_kt_end_seq_get (context, id, &cursor); 651*ae771770SStanislav Sedov if (entry->vno == 0) 652*ae771770SStanislav Sedov return _krb5_kt_principal_not_found(context, KRB5_KT_NOTFOUND, 653*ae771770SStanislav Sedov id, principal, enctype, kvno); 654b528cefcSMark Murray return 0; 655adb0ddaeSAssar Westerlund } 656b528cefcSMark Murray 657*ae771770SStanislav Sedov /** 658b528cefcSMark Murray * Copy the contents of `in' into `out'. 659*ae771770SStanislav Sedov * 660*ae771770SStanislav Sedov * @param context a Keberos context. 661*ae771770SStanislav Sedov * @param in the keytab entry to copy. 662*ae771770SStanislav Sedov * @param out the copy of the keytab entry, free with krb5_kt_free_entry(). 663*ae771770SStanislav Sedov * 664*ae771770SStanislav Sedov * @return Return an error code or 0, see krb5_get_error_message(). 665*ae771770SStanislav Sedov * 666*ae771770SStanislav Sedov * @ingroup krb5_keytab 667*ae771770SStanislav Sedov */ 668b528cefcSMark Murray 669*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 670b528cefcSMark Murray krb5_kt_copy_entry_contents(krb5_context context, 671b528cefcSMark Murray const krb5_keytab_entry *in, 672b528cefcSMark Murray krb5_keytab_entry *out) 673b528cefcSMark Murray { 674b528cefcSMark Murray krb5_error_code ret; 675b528cefcSMark Murray 676b528cefcSMark Murray memset(out, 0, sizeof(*out)); 677b528cefcSMark Murray out->vno = in->vno; 678b528cefcSMark Murray 679b528cefcSMark Murray ret = krb5_copy_principal (context, in->principal, &out->principal); 680b528cefcSMark Murray if (ret) 681b528cefcSMark Murray goto fail; 682b528cefcSMark Murray ret = krb5_copy_keyblock_contents (context, 683b528cefcSMark Murray &in->keyblock, 684b528cefcSMark Murray &out->keyblock); 685b528cefcSMark Murray if (ret) 686b528cefcSMark Murray goto fail; 687b528cefcSMark Murray out->timestamp = in->timestamp; 688b528cefcSMark Murray return 0; 689b528cefcSMark Murray fail: 690b528cefcSMark Murray krb5_kt_free_entry (context, out); 691b528cefcSMark Murray return ret; 692b528cefcSMark Murray } 693b528cefcSMark Murray 694*ae771770SStanislav Sedov /** 695b528cefcSMark Murray * Free the contents of `entry'. 696*ae771770SStanislav Sedov * 697*ae771770SStanislav Sedov * @param context a Keberos context. 698*ae771770SStanislav Sedov * @param entry the entry to free 699*ae771770SStanislav Sedov * 700*ae771770SStanislav Sedov * @return Return an error code or 0, see krb5_get_error_message(). 701*ae771770SStanislav Sedov * 702*ae771770SStanislav Sedov * @ingroup krb5_keytab 703b528cefcSMark Murray */ 704b528cefcSMark Murray 705*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 706b528cefcSMark Murray krb5_kt_free_entry(krb5_context context, 707b528cefcSMark Murray krb5_keytab_entry *entry) 708b528cefcSMark Murray { 709b528cefcSMark Murray krb5_free_principal (context, entry->principal); 710b528cefcSMark Murray krb5_free_keyblock_contents (context, &entry->keyblock); 711c19800e8SDoug Rabson memset(entry, 0, sizeof(*entry)); 712b528cefcSMark Murray return 0; 713b528cefcSMark Murray } 714b528cefcSMark Murray 715*ae771770SStanislav Sedov /** 716b528cefcSMark Murray * Set `cursor' to point at the beginning of `id'. 717*ae771770SStanislav Sedov * 718*ae771770SStanislav Sedov * @param context a Keberos context. 719*ae771770SStanislav Sedov * @param id a keytab. 720*ae771770SStanislav Sedov * @param cursor a newly allocated cursor, free with krb5_kt_end_seq_get(). 721*ae771770SStanislav Sedov * 722*ae771770SStanislav Sedov * @return Return an error code or 0, see krb5_get_error_message(). 723*ae771770SStanislav Sedov * 724*ae771770SStanislav Sedov * @ingroup krb5_keytab 725b528cefcSMark Murray */ 726b528cefcSMark Murray 727*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 728b528cefcSMark Murray krb5_kt_start_seq_get(krb5_context context, 729b528cefcSMark Murray krb5_keytab id, 730b528cefcSMark Murray krb5_kt_cursor *cursor) 731b528cefcSMark Murray { 732adb0ddaeSAssar Westerlund if(id->start_seq_get == NULL) { 733*ae771770SStanislav Sedov krb5_set_error_message(context, HEIM_ERR_OPNOTSUPP, 734*ae771770SStanislav Sedov N_("start_seq_get is not supported " 735*ae771770SStanislav Sedov "in the %s keytab type", ""), 736*ae771770SStanislav Sedov id->prefix); 737b528cefcSMark Murray return HEIM_ERR_OPNOTSUPP; 738adb0ddaeSAssar Westerlund } 739b528cefcSMark Murray return (*id->start_seq_get)(context, id, cursor); 740b528cefcSMark Murray } 741b528cefcSMark Murray 742*ae771770SStanislav Sedov /** 743*ae771770SStanislav Sedov * Get the next entry from keytab, advance the cursor. On last entry 744*ae771770SStanislav Sedov * the function will return KRB5_KT_END. 745*ae771770SStanislav Sedov * 746*ae771770SStanislav Sedov * @param context a Keberos context. 747*ae771770SStanislav Sedov * @param id a keytab. 748*ae771770SStanislav Sedov * @param entry the returned entry, free with krb5_kt_free_entry(). 749*ae771770SStanislav Sedov * @param cursor the cursor of the iteration. 750*ae771770SStanislav Sedov * 751*ae771770SStanislav Sedov * @return Return an error code or 0, see krb5_get_error_message(). 752*ae771770SStanislav Sedov * 753*ae771770SStanislav Sedov * @ingroup krb5_keytab 754b528cefcSMark Murray */ 755b528cefcSMark Murray 756*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 757b528cefcSMark Murray krb5_kt_next_entry(krb5_context context, 758b528cefcSMark Murray krb5_keytab id, 759b528cefcSMark Murray krb5_keytab_entry *entry, 760b528cefcSMark Murray krb5_kt_cursor *cursor) 761b528cefcSMark Murray { 762adb0ddaeSAssar Westerlund if(id->next_entry == NULL) { 763*ae771770SStanislav Sedov krb5_set_error_message(context, HEIM_ERR_OPNOTSUPP, 764*ae771770SStanislav Sedov N_("next_entry is not supported in the %s " 765*ae771770SStanislav Sedov " keytab", ""), 766*ae771770SStanislav Sedov id->prefix); 767b528cefcSMark Murray return HEIM_ERR_OPNOTSUPP; 768adb0ddaeSAssar Westerlund } 769b528cefcSMark Murray return (*id->next_entry)(context, id, entry, cursor); 770b528cefcSMark Murray } 771b528cefcSMark Murray 772*ae771770SStanislav Sedov /** 773b528cefcSMark Murray * Release all resources associated with `cursor'. 774*ae771770SStanislav Sedov * 775*ae771770SStanislav Sedov * @param context a Keberos context. 776*ae771770SStanislav Sedov * @param id a keytab. 777*ae771770SStanislav Sedov * @param cursor the cursor to free. 778*ae771770SStanislav Sedov * 779*ae771770SStanislav Sedov * @return Return an error code or 0, see krb5_get_error_message(). 780*ae771770SStanislav Sedov * 781*ae771770SStanislav Sedov * @ingroup krb5_keytab 782b528cefcSMark Murray */ 783b528cefcSMark Murray 784*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 785b528cefcSMark Murray krb5_kt_end_seq_get(krb5_context context, 786b528cefcSMark Murray krb5_keytab id, 787b528cefcSMark Murray krb5_kt_cursor *cursor) 788b528cefcSMark Murray { 789adb0ddaeSAssar Westerlund if(id->end_seq_get == NULL) { 790*ae771770SStanislav Sedov krb5_set_error_message(context, HEIM_ERR_OPNOTSUPP, 791adb0ddaeSAssar Westerlund "end_seq_get is not supported in the %s " 792adb0ddaeSAssar Westerlund " keytab", id->prefix); 793b528cefcSMark Murray return HEIM_ERR_OPNOTSUPP; 794adb0ddaeSAssar Westerlund } 795b528cefcSMark Murray return (*id->end_seq_get)(context, id, cursor); 796b528cefcSMark Murray } 797b528cefcSMark Murray 798*ae771770SStanislav Sedov /** 799b528cefcSMark Murray * Add the entry in `entry' to the keytab `id'. 800*ae771770SStanislav Sedov * 801*ae771770SStanislav Sedov * @param context a Keberos context. 802*ae771770SStanislav Sedov * @param id a keytab. 803*ae771770SStanislav Sedov * @param entry the entry to add 804*ae771770SStanislav Sedov * 805*ae771770SStanislav Sedov * @return Return an error code or 0, see krb5_get_error_message(). 806*ae771770SStanislav Sedov * 807*ae771770SStanislav Sedov * @ingroup krb5_keytab 808b528cefcSMark Murray */ 809b528cefcSMark Murray 810*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 811b528cefcSMark Murray krb5_kt_add_entry(krb5_context context, 812b528cefcSMark Murray krb5_keytab id, 813b528cefcSMark Murray krb5_keytab_entry *entry) 814b528cefcSMark Murray { 815adb0ddaeSAssar Westerlund if(id->add == NULL) { 816*ae771770SStanislav Sedov krb5_set_error_message(context, KRB5_KT_NOWRITE, 817*ae771770SStanislav Sedov N_("Add is not supported in the %s keytab", ""), 818adb0ddaeSAssar Westerlund id->prefix); 819b528cefcSMark Murray return KRB5_KT_NOWRITE; 820adb0ddaeSAssar Westerlund } 82113e3f4d6SMark Murray entry->timestamp = time(NULL); 822b528cefcSMark Murray return (*id->add)(context, id,entry); 823b528cefcSMark Murray } 824b528cefcSMark Murray 825*ae771770SStanislav Sedov /** 826*ae771770SStanislav Sedov * Remove an entry from the keytab, matching is done using 827*ae771770SStanislav Sedov * krb5_kt_compare(). 828*ae771770SStanislav Sedov 829*ae771770SStanislav Sedov * @param context a Keberos context. 830*ae771770SStanislav Sedov * @param id a keytab. 831*ae771770SStanislav Sedov * @param entry the entry to remove 832*ae771770SStanislav Sedov * 833*ae771770SStanislav Sedov * @return Return an error code or 0, see krb5_get_error_message(). 834*ae771770SStanislav Sedov * 835*ae771770SStanislav Sedov * @ingroup krb5_keytab 836b528cefcSMark Murray */ 837b528cefcSMark Murray 838*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 839b528cefcSMark Murray krb5_kt_remove_entry(krb5_context context, 840b528cefcSMark Murray krb5_keytab id, 841b528cefcSMark Murray krb5_keytab_entry *entry) 842b528cefcSMark Murray { 843adb0ddaeSAssar Westerlund if(id->remove == NULL) { 844*ae771770SStanislav Sedov krb5_set_error_message(context, KRB5_KT_NOWRITE, 845*ae771770SStanislav Sedov N_("Remove is not supported in the %s keytab", ""), 846adb0ddaeSAssar Westerlund id->prefix); 847b528cefcSMark Murray return KRB5_KT_NOWRITE; 848adb0ddaeSAssar Westerlund } 849b528cefcSMark Murray return (*id->remove)(context, id, entry); 850b528cefcSMark Murray } 851*ae771770SStanislav Sedov 852*ae771770SStanislav Sedov /** 853*ae771770SStanislav Sedov * Return true if the keytab exists and have entries 854*ae771770SStanislav Sedov * 855*ae771770SStanislav Sedov * @param context a Keberos context. 856*ae771770SStanislav Sedov * @param id a keytab. 857*ae771770SStanislav Sedov * 858*ae771770SStanislav Sedov * @return Return an error code or 0, see krb5_get_error_message(). 859*ae771770SStanislav Sedov * 860*ae771770SStanislav Sedov * @ingroup krb5_keytab 861*ae771770SStanislav Sedov */ 862*ae771770SStanislav Sedov 863*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL 864*ae771770SStanislav Sedov krb5_kt_have_content(krb5_context context, 865*ae771770SStanislav Sedov krb5_keytab id) 866*ae771770SStanislav Sedov { 867*ae771770SStanislav Sedov krb5_keytab_entry entry; 868*ae771770SStanislav Sedov krb5_kt_cursor cursor; 869*ae771770SStanislav Sedov krb5_error_code ret; 870*ae771770SStanislav Sedov char *name; 871*ae771770SStanislav Sedov 872*ae771770SStanislav Sedov ret = krb5_kt_start_seq_get(context, id, &cursor); 873*ae771770SStanislav Sedov if (ret) 874*ae771770SStanislav Sedov goto notfound; 875*ae771770SStanislav Sedov 876*ae771770SStanislav Sedov ret = krb5_kt_next_entry(context, id, &entry, &cursor); 877*ae771770SStanislav Sedov krb5_kt_end_seq_get(context, id, &cursor); 878*ae771770SStanislav Sedov if (ret) 879*ae771770SStanislav Sedov goto notfound; 880*ae771770SStanislav Sedov 881*ae771770SStanislav Sedov krb5_kt_free_entry(context, &entry); 882*ae771770SStanislav Sedov 883*ae771770SStanislav Sedov return 0; 884*ae771770SStanislav Sedov 885*ae771770SStanislav Sedov notfound: 886*ae771770SStanislav Sedov ret = krb5_kt_get_full_name(context, id, &name); 887*ae771770SStanislav Sedov if (ret == 0) { 888*ae771770SStanislav Sedov krb5_set_error_message(context, KRB5_KT_NOTFOUND, 889*ae771770SStanislav Sedov N_("No entry in keytab: %s", ""), name); 890*ae771770SStanislav Sedov free(name); 891*ae771770SStanislav Sedov } 892*ae771770SStanislav Sedov return KRB5_KT_NOTFOUND; 893*ae771770SStanislav Sedov } 894