keytab_any.c revision 256281
168349Sobrien/* 268349Sobrien * Copyright (c) 2001-2002 Kungliga Tekniska H��gskolan 368349Sobrien * (Royal Institute of Technology, Stockholm, Sweden). 468349Sobrien * All rights reserved. 568349Sobrien * 668349Sobrien * Redistribution and use in source and binary forms, with or without 768349Sobrien * modification, are permitted provided that the following conditions 868349Sobrien * are met: 968349Sobrien * 1068349Sobrien * 1. Redistributions of source code must retain the above copyright 1168349Sobrien * notice, this list of conditions and the following disclaimer. 1268349Sobrien * 1368349Sobrien * 2. Redistributions in binary form must reproduce the above copyright 1468349Sobrien * notice, this list of conditions and the following disclaimer in the 1568349Sobrien * documentation and/or other materials provided with the distribution. 16186690Sobrien * 1768349Sobrien * 3. Neither the name of the Institute nor the names of its contributors 18186690Sobrien * may be used to endorse or promote products derived from this software 1968349Sobrien * without specific prior written permission. 20186690Sobrien * 21159764Sobrien * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 2268349Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23159764Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24159764Sobrien * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 25159764Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2668349Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2768349Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2868349Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2968349Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3068349Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3168349Sobrien * SUCH DAMAGE. 32159764Sobrien */ 3368349Sobrien 3468349Sobrien#include "krb5_locl.h" 35159764Sobrien 36159764Sobrienstruct any_data { 37159764Sobrien krb5_keytab kt; 38159764Sobrien char *name; 39159764Sobrien struct any_data *next; 40159764Sobrien}; 41159764Sobrien 42159764Sobrienstatic void 43159764Sobrienfree_list (krb5_context context, struct any_data *a) 44159764Sobrien{ 4568349Sobrien struct any_data *next; 4668349Sobrien 47133359Sobrien for (; a != NULL; a = next) { 48133359Sobrien next = a->next; 49159764Sobrien free (a->name); 50159764Sobrien if(a->kt) 51159764Sobrien krb5_kt_close(context, a->kt); 52159764Sobrien free (a); 53159764Sobrien } 54159764Sobrien} 55159764Sobrien 56159764Sobrienstatic krb5_error_code KRB5_CALLCONV 57159764Sobrienany_resolve(krb5_context context, const char *name, krb5_keytab id) 58159764Sobrien{ 59159764Sobrien struct any_data *a, *a0 = NULL, *prev = NULL; 60159764Sobrien krb5_error_code ret; 61159764Sobrien char buf[256]; 62159764Sobrien 63159764Sobrien while (strsep_copy(&name, ",", buf, sizeof(buf)) != -1) { 64 a = calloc(1, sizeof(*a)); 65 if (a == NULL) { 66 ret = ENOMEM; 67 goto fail; 68 } 69 if (a0 == NULL) { 70 a0 = a; 71 a->name = strdup(buf); 72 if (a->name == NULL) { 73 ret = ENOMEM; 74 krb5_set_error_message(context, ret, N_("malloc: out of memory", "")); 75 goto fail; 76 } 77 } else 78 a->name = NULL; 79 if (prev != NULL) 80 prev->next = a; 81 a->next = NULL; 82 ret = krb5_kt_resolve (context, buf, &a->kt); 83 if (ret) 84 goto fail; 85 prev = a; 86 } 87 if (a0 == NULL) { 88 krb5_set_error_message(context, ENOENT, N_("empty ANY: keytab", "")); 89 return ENOENT; 90 } 91 id->data = a0; 92 return 0; 93 fail: 94 free_list (context, a0); 95 return ret; 96} 97 98static krb5_error_code KRB5_CALLCONV 99any_get_name (krb5_context context, 100 krb5_keytab id, 101 char *name, 102 size_t namesize) 103{ 104 struct any_data *a = id->data; 105 strlcpy(name, a->name, namesize); 106 return 0; 107} 108 109static krb5_error_code KRB5_CALLCONV 110any_close (krb5_context context, 111 krb5_keytab id) 112{ 113 struct any_data *a = id->data; 114 115 free_list (context, a); 116 return 0; 117} 118 119struct any_cursor_extra_data { 120 struct any_data *a; 121 krb5_kt_cursor cursor; 122}; 123 124static krb5_error_code KRB5_CALLCONV 125any_start_seq_get(krb5_context context, 126 krb5_keytab id, 127 krb5_kt_cursor *c) 128{ 129 struct any_data *a = id->data; 130 struct any_cursor_extra_data *ed; 131 krb5_error_code ret; 132 133 c->data = malloc (sizeof(struct any_cursor_extra_data)); 134 if(c->data == NULL){ 135 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); 136 return ENOMEM; 137 } 138 ed = (struct any_cursor_extra_data *)c->data; 139 for (ed->a = a; ed->a != NULL; ed->a = ed->a->next) { 140 ret = krb5_kt_start_seq_get(context, ed->a->kt, &ed->cursor); 141 if (ret == 0) 142 break; 143 } 144 if (ed->a == NULL) { 145 free (c->data); 146 c->data = NULL; 147 krb5_clear_error_message (context); 148 return KRB5_KT_END; 149 } 150 return 0; 151} 152 153static krb5_error_code KRB5_CALLCONV 154any_next_entry (krb5_context context, 155 krb5_keytab id, 156 krb5_keytab_entry *entry, 157 krb5_kt_cursor *cursor) 158{ 159 krb5_error_code ret, ret2; 160 struct any_cursor_extra_data *ed; 161 162 ed = (struct any_cursor_extra_data *)cursor->data; 163 do { 164 ret = krb5_kt_next_entry(context, ed->a->kt, entry, &ed->cursor); 165 if (ret == 0) 166 return 0; 167 else if (ret != KRB5_KT_END) 168 return ret; 169 170 ret2 = krb5_kt_end_seq_get (context, ed->a->kt, &ed->cursor); 171 if (ret2) 172 return ret2; 173 while ((ed->a = ed->a->next) != NULL) { 174 ret2 = krb5_kt_start_seq_get(context, ed->a->kt, &ed->cursor); 175 if (ret2 == 0) 176 break; 177 } 178 if (ed->a == NULL) { 179 krb5_clear_error_message (context); 180 return KRB5_KT_END; 181 } 182 } while (1); 183} 184 185static krb5_error_code KRB5_CALLCONV 186any_end_seq_get(krb5_context context, 187 krb5_keytab id, 188 krb5_kt_cursor *cursor) 189{ 190 krb5_error_code ret = 0; 191 struct any_cursor_extra_data *ed; 192 193 ed = (struct any_cursor_extra_data *)cursor->data; 194 if (ed->a != NULL) 195 ret = krb5_kt_end_seq_get(context, ed->a->kt, &ed->cursor); 196 free (ed); 197 cursor->data = NULL; 198 return ret; 199} 200 201static krb5_error_code KRB5_CALLCONV 202any_add_entry(krb5_context context, 203 krb5_keytab id, 204 krb5_keytab_entry *entry) 205{ 206 struct any_data *a = id->data; 207 krb5_error_code ret; 208 while(a != NULL) { 209 ret = krb5_kt_add_entry(context, a->kt, entry); 210 if(ret != 0 && ret != KRB5_KT_NOWRITE) { 211 krb5_set_error_message(context, ret, 212 N_("failed to add entry to %s", ""), 213 a->name); 214 return ret; 215 } 216 a = a->next; 217 } 218 return 0; 219} 220 221static krb5_error_code KRB5_CALLCONV 222any_remove_entry(krb5_context context, 223 krb5_keytab id, 224 krb5_keytab_entry *entry) 225{ 226 struct any_data *a = id->data; 227 krb5_error_code ret; 228 int found = 0; 229 while(a != NULL) { 230 ret = krb5_kt_remove_entry(context, a->kt, entry); 231 if(ret == 0) 232 found++; 233 else { 234 if(ret != KRB5_KT_NOWRITE && ret != KRB5_KT_NOTFOUND) { 235 krb5_set_error_message(context, ret, 236 N_("Failed to remove keytab " 237 "entry from %s", "keytab name"), 238 a->name); 239 return ret; 240 } 241 } 242 a = a->next; 243 } 244 if(!found) 245 return KRB5_KT_NOTFOUND; 246 return 0; 247} 248 249const krb5_kt_ops krb5_any_ops = { 250 "ANY", 251 any_resolve, 252 any_get_name, 253 any_close, 254 NULL, /* destroy */ 255 NULL, /* get */ 256 any_start_seq_get, 257 any_next_entry, 258 any_end_seq_get, 259 any_add_entry, 260 any_remove_entry 261}; 262