1 /* 2 * Copyright (c) 1999 Kungliga Tekniska H�gskolan 3 * (Royal Institute of Technology, Stockholm, Sweden). 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * 3. Neither the name of the Institute nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34 #include "hdb_locl.h" 35 36 /* keytab backend for HDB databases */ 37 38 RCSID("$Id: keytab.c,v 1.2 1999/08/26 13:24:05 joda Exp $"); 39 40 struct hdb_data { 41 char *dbname; 42 char *mkey; 43 HDB *db; 44 }; 45 46 static krb5_error_code 47 hdb_resolve(krb5_context context, const char *name, krb5_keytab id) 48 { 49 krb5_error_code ret; 50 struct hdb_data *d; 51 const char *db, *mkey; 52 d = malloc(sizeof(*d)); 53 if(d == NULL) 54 return ENOMEM; 55 db = name; 56 mkey = strchr(name, ':'); 57 if(mkey == NULL || mkey[1] == '\0') { 58 if(*name == '\0') 59 d->dbname = NULL; 60 else { 61 d->dbname = strdup(name); 62 if(d->dbname == NULL) { 63 free(d); 64 return ENOMEM; 65 } 66 } 67 d->mkey = NULL; 68 } else { 69 if((mkey - db) == 0) { 70 d->dbname = NULL; 71 } else { 72 d->dbname = malloc(mkey - db); 73 if(d->dbname == NULL) { 74 free(d); 75 return ENOMEM; 76 } 77 strncpy(d->dbname, db, mkey - db); 78 d->dbname[mkey - db] = '\0'; 79 } 80 d->mkey = strdup(mkey + 1); 81 if(d->mkey == NULL) { 82 free(d->dbname); 83 free(d); 84 return ENOMEM; 85 } 86 } 87 ret = hdb_create(context, &d->db, d->dbname); 88 if(ret) { 89 free(d->dbname); 90 free(d->mkey); 91 free(d); 92 return ret; 93 } 94 ret = hdb_set_master_keyfile (context, d->db, d->mkey); 95 if(ret) { 96 (*d->db->destroy)(context, d->db); 97 free(d->dbname); 98 free(d->mkey); 99 free(d); 100 return ret; 101 } 102 id->data = d; 103 return 0; 104 } 105 106 static krb5_error_code 107 hdb_close(krb5_context context, krb5_keytab id) 108 { 109 struct hdb_data *d = id->data; 110 (*d->db->destroy)(context, d->db); 111 free(d); 112 return 0; 113 } 114 115 static krb5_error_code 116 hdb_get_name(krb5_context context, 117 krb5_keytab id, 118 char *name, 119 size_t namesize) 120 { 121 struct hdb_data *d = id->data; 122 snprintf(name, namesize, "%s%s%s", 123 d->dbname ? d->dbname : "", 124 (d->dbname || d->mkey) ? ":" : "", 125 d->mkey ? d->mkey : ""); 126 return 0; 127 } 128 129 static krb5_error_code 130 hdb_get_entry(krb5_context context, 131 krb5_keytab id, 132 krb5_const_principal principal, 133 krb5_kvno kvno, 134 krb5_enctype enctype, 135 krb5_keytab_entry *entry) 136 { 137 hdb_entry ent; 138 krb5_error_code ret; 139 struct hdb_data *d = id->data; 140 int i; 141 142 ret = (*d->db->open)(context, d->db, O_RDONLY, 0); 143 if (ret) 144 return ret; 145 ent.principal = (krb5_principal)principal; 146 ret = (*d->db->fetch)(context, d->db, HDB_F_DECRYPT, &ent); 147 (*d->db->close)(context, d->db); 148 if(ret == HDB_ERR_NOENTRY) 149 return KRB5_KT_NOTFOUND; 150 else if(ret) 151 return ret; 152 if(kvno && ent.kvno != kvno) { 153 hdb_free_entry(context, &ent); 154 return KRB5_KT_NOTFOUND; 155 } 156 if(enctype == 0) 157 if(ent.keys.len > 0) 158 enctype = ent.keys.val[0].key.keytype; 159 ret = KRB5_KT_NOTFOUND; 160 for(i = 0; i < ent.keys.len; i++) { 161 if(ent.keys.val[i].key.keytype == enctype) { 162 krb5_copy_principal(context, principal, &entry->principal); 163 entry->vno = ent.kvno; 164 krb5_copy_keyblock_contents(context, 165 &ent.keys.val[i].key, 166 &entry->keyblock); 167 ret = 0; 168 break; 169 } 170 } 171 hdb_free_entry(context, &ent); 172 return ret; 173 } 174 175 krb5_kt_ops hdb_kt_ops = { 176 "HDB", 177 hdb_resolve, 178 hdb_get_name, 179 hdb_close, 180 hdb_get_entry, 181 NULL, /* start_seq_get */ 182 NULL, /* next_entry */ 183 NULL, /* end_seq_get */ 184 NULL, /* add */ 185 NULL /* remove */ 186 }; 187 188