144743Smarkm/* 244743Smarkm * Copyright (c) 2001-2002 Kungliga Tekniska H��gskolan 344743Smarkm * (Royal Institute of Technology, Stockholm, Sweden). 444743Smarkm * All rights reserved. 544743Smarkm * 644743Smarkm * Redistribution and use in source and binary forms, with or without 744743Smarkm * modification, are permitted provided that the following conditions 844743Smarkm * are met: 944743Smarkm * 1044743Smarkm * 1. Redistributions of source code must retain the above copyright 1144743Smarkm * notice, this list of conditions and the following disclaimer. 1244743Smarkm * 1344743Smarkm * 2. Redistributions in binary form must reproduce the above copyright 1444743Smarkm * notice, this list of conditions and the following disclaimer in the 1544743Smarkm * documentation and/or other materials provided with the distribution. 1656977Sshin * 1756977Sshin * 3. Neither the name of the Institute nor the names of its contributors 1844743Smarkm * may be used to endorse or promote products derived from this software 1944743Smarkm * without specific prior written permission. 2044743Smarkm * 2144743Smarkm * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 2244743Smarkm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2344743Smarkm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2444743Smarkm * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 2544743Smarkm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2644743Smarkm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2744743Smarkm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2844743Smarkm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2944743Smarkm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3044743Smarkm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3144743Smarkm * SUCH DAMAGE. 3244743Smarkm */ 3344743Smarkm 3444743Smarkm#include "krb5_locl.h" 35146187Sume 3663158Sumestruct any_data { 3756977Sshin krb5_keytab kt; 3856977Sshin char *name; 3944743Smarkm struct any_data *next; 4044743Smarkm}; 4144743Smarkm 4244743Smarkmstatic void 4344743Smarkmfree_list (krb5_context context, struct any_data *a) 4444743Smarkm{ 4544743Smarkm struct any_data *next; 4644743Smarkm 4744743Smarkm for (; a != NULL; a = next) { 4844743Smarkm next = a->next; 4944743Smarkm free (a->name); 5044743Smarkm if(a->kt) 5144743Smarkm krb5_kt_close(context, a->kt); 5244743Smarkm free (a); 5344743Smarkm } 5444743Smarkm} 5544743Smarkm 5644743Smarkmstatic krb5_error_code KRB5_CALLCONV 5744743Smarkmany_resolve(krb5_context context, const char *name, krb5_keytab id) 5844743Smarkm{ 5944743Smarkm struct any_data *a, *a0 = NULL, *prev = NULL; 6044743Smarkm krb5_error_code ret; 6144743Smarkm char buf[256]; 6244743Smarkm 6344743Smarkm while (strsep_copy(&name, ",", buf, sizeof(buf)) != -1) { 6444743Smarkm a = calloc(1, sizeof(*a)); 6544743Smarkm if (a == NULL) { 6644743Smarkm ret = ENOMEM; 6744743Smarkm goto fail; 6844743Smarkm } 6944743Smarkm if (a0 == NULL) { 7044743Smarkm a0 = a; 7144743Smarkm a->name = strdup(buf); 7244743Smarkm if (a->name == NULL) { 7344743Smarkm ret = ENOMEM; 7444743Smarkm krb5_set_error_message(context, ret, N_("malloc: out of memory", "")); 7544743Smarkm goto fail; 7644743Smarkm } 7744743Smarkm } else 7844743Smarkm a->name = NULL; 7944743Smarkm if (prev != NULL) 8044743Smarkm prev->next = a; 8156977Sshin a->next = NULL; 8256977Sshin ret = krb5_kt_resolve (context, buf, &a->kt); 8356977Sshin if (ret) 8456977Sshin goto fail; 8544743Smarkm prev = a; 8644743Smarkm } 8756977Sshin if (a0 == NULL) { 8844743Smarkm krb5_set_error_message(context, ENOENT, N_("empty ANY: keytab", "")); 8944743Smarkm return ENOENT; 9044743Smarkm } 9144743Smarkm id->data = a0; 9244743Smarkm return 0; 9344743Smarkm fail: 9444743Smarkm free_list (context, a0); 9544743Smarkm return ret; 9644743Smarkm} 9744743Smarkm 9844743Smarkmstatic krb5_error_code KRB5_CALLCONV 9944743Smarkmany_get_name (krb5_context context, 10044743Smarkm krb5_keytab id, 10144743Smarkm char *name, 10244743Smarkm size_t namesize) 10344743Smarkm{ 10444743Smarkm struct any_data *a = id->data; 10544743Smarkm strlcpy(name, a->name, namesize); 10644743Smarkm return 0; 10744743Smarkm} 10844743Smarkm 10944743Smarkmstatic krb5_error_code KRB5_CALLCONV 11044743Smarkmany_close (krb5_context context, 11144743Smarkm krb5_keytab id) 11244743Smarkm{ 113123895Sceri struct any_data *a = id->data; 11444743Smarkm 11544743Smarkm free_list (context, a); 11656977Sshin return 0; 11756977Sshin} 11856977Sshin 11944743Smarkmstruct any_cursor_extra_data { 12056977Sshin struct any_data *a; 12144743Smarkm krb5_kt_cursor cursor; 12244743Smarkm}; 12344743Smarkm 12444743Smarkmstatic krb5_error_code KRB5_CALLCONV 12544743Smarkmany_start_seq_get(krb5_context context, 12644743Smarkm krb5_keytab id, 12744743Smarkm krb5_kt_cursor *c) 12844743Smarkm{ 12944743Smarkm struct any_data *a = id->data; 13044743Smarkm struct any_cursor_extra_data *ed; 13144743Smarkm krb5_error_code ret; 13244743Smarkm 13356977Sshin c->data = malloc (sizeof(struct any_cursor_extra_data)); 13456977Sshin if(c->data == NULL){ 13556977Sshin krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); 13644743Smarkm return ENOMEM; 13756977Sshin } 13844743Smarkm ed = (struct any_cursor_extra_data *)c->data; 13944743Smarkm for (ed->a = a; ed->a != NULL; ed->a = ed->a->next) { 14044743Smarkm ret = krb5_kt_start_seq_get(context, ed->a->kt, &ed->cursor); 14144743Smarkm if (ret == 0) 14244743Smarkm break; 14344743Smarkm } 14444743Smarkm if (ed->a == NULL) { 14556977Sshin free (c->data); 14656977Sshin c->data = NULL; 14763158Sume krb5_clear_error_message (context); 14856977Sshin return KRB5_KT_END; 14956977Sshin } 15056977Sshin return 0; 15163158Sume} 15263158Sume 15356977Sshinstatic krb5_error_code KRB5_CALLCONV 15463158Sumeany_next_entry (krb5_context context, 15563158Sume krb5_keytab id, 15663158Sume krb5_keytab_entry *entry, 15763158Sume krb5_kt_cursor *cursor) 158146187Sume{ 15963158Sume krb5_error_code ret, ret2; 16044743Smarkm struct any_cursor_extra_data *ed; 16144743Smarkm 16244743Smarkm ed = (struct any_cursor_extra_data *)cursor->data; 16344743Smarkm do { 16456977Sshin ret = krb5_kt_next_entry(context, ed->a->kt, entry, &ed->cursor); 16544743Smarkm if (ret == 0) 16644743Smarkm return 0; 16744743Smarkm else if (ret != KRB5_KT_END) 16844743Smarkm return ret; 16944743Smarkm 17044743Smarkm ret2 = krb5_kt_end_seq_get (context, ed->a->kt, &ed->cursor); 17144743Smarkm if (ret2) 17256977Sshin return ret2; 17356977Sshin while ((ed->a = ed->a->next) != NULL) { 17463158Sume ret2 = krb5_kt_start_seq_get(context, ed->a->kt, &ed->cursor); 17563158Sume if (ret2 == 0) 17663158Sume break; 17763158Sume } 17863158Sume if (ed->a == NULL) { 17963158Sume krb5_clear_error_message (context); 18063158Sume return KRB5_KT_END; 18163158Sume } 18263158Sume } while (1); 18363158Sume} 18463158Sume 18563158Sumestatic krb5_error_code KRB5_CALLCONV 18663158Sumeany_end_seq_get(krb5_context context, 18756977Sshin krb5_keytab id, 18863158Sume krb5_kt_cursor *cursor) 18963158Sume{ 19063158Sume krb5_error_code ret = 0; 19163158Sume struct any_cursor_extra_data *ed; 19263158Sume 19363158Sume ed = (struct any_cursor_extra_data *)cursor->data; 19463158Sume if (ed->a != NULL) 19563158Sume ret = krb5_kt_end_seq_get(context, ed->a->kt, &ed->cursor); 19663158Sume free (ed); 19763158Sume cursor->data = NULL; 19863158Sume return ret; 19963158Sume} 20063158Sume 20163158Sumestatic krb5_error_code KRB5_CALLCONV 20263158Sumeany_add_entry(krb5_context context, 20363158Sume krb5_keytab id, 20463158Sume krb5_keytab_entry *entry) 20563158Sume{ 20663158Sume struct any_data *a = id->data; 20763158Sume krb5_error_code ret; 20863158Sume while(a != NULL) { 20963158Sume ret = krb5_kt_add_entry(context, a->kt, entry); 210146187Sume if(ret != 0 && ret != KRB5_KT_NOWRITE) { 21163158Sume krb5_set_error_message(context, ret, 21263158Sume N_("failed to add entry to %s", ""), 21363158Sume a->name); 21463158Sume return ret; 21563158Sume } 21666329Sume a = a->next; 21766329Sume } 21866329Sume return 0; 21966329Sume} 22066329Sume 22179249Skrisstatic krb5_error_code KRB5_CALLCONV 22266329Sumeany_remove_entry(krb5_context context, 22366329Sume krb5_keytab id, 22466329Sume krb5_keytab_entry *entry) 22566329Sume{ 22666329Sume struct any_data *a = id->data; 22766329Sume krb5_error_code ret; 22866329Sume int found = 0; 22966329Sume while(a != NULL) { 23066329Sume ret = krb5_kt_remove_entry(context, a->kt, entry); 23166329Sume if(ret == 0) 23266329Sume found++; 23363158Sume else { 23463158Sume if(ret != KRB5_KT_NOWRITE && ret != KRB5_KT_NOTFOUND) { 23563158Sume krb5_set_error_message(context, ret, 23663158Sume N_("Failed to remove keytab " 23763158Sume "entry from %s", "keytab name"), 23863158Sume a->name); 23963158Sume return ret; 24063158Sume } 24163158Sume } 24263158Sume a = a->next; 24363158Sume } 24463158Sume if(!found) 24563158Sume return KRB5_KT_NOTFOUND; 24663158Sume return 0; 24763158Sume} 24863158Sume 24963158Sumeconst krb5_kt_ops krb5_any_ops = { 25063158Sume "ANY", 25163158Sume any_resolve, 25263158Sume any_get_name, 25363158Sume any_close, 25463158Sume NULL, /* destroy */ 25563158Sume NULL, /* get */ 25663158Sume any_start_seq_get, 25763158Sume any_next_entry, 25863158Sume any_end_seq_get, 25963158Sume any_add_entry, 26063158Sume any_remove_entry 26166297Sume}; 26266297Sume