mcache.c revision 72445
155682Smarkm/* 272445Sassar * Copyright (c) 1997-2000 Kungliga Tekniska H�gskolan 355682Smarkm * (Royal Institute of Technology, Stockholm, Sweden). 455682Smarkm * All rights reserved. 555682Smarkm * 655682Smarkm * Redistribution and use in source and binary forms, with or without 755682Smarkm * modification, are permitted provided that the following conditions 855682Smarkm * are met: 955682Smarkm * 1055682Smarkm * 1. Redistributions of source code must retain the above copyright 1155682Smarkm * notice, this list of conditions and the following disclaimer. 1255682Smarkm * 1355682Smarkm * 2. Redistributions in binary form must reproduce the above copyright 1455682Smarkm * notice, this list of conditions and the following disclaimer in the 1555682Smarkm * documentation and/or other materials provided with the distribution. 1655682Smarkm * 1755682Smarkm * 3. Neither the name of the Institute nor the names of its contributors 1855682Smarkm * may be used to endorse or promote products derived from this software 1955682Smarkm * without specific prior written permission. 2055682Smarkm * 2155682Smarkm * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 2255682Smarkm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2355682Smarkm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2455682Smarkm * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 2555682Smarkm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2655682Smarkm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2755682Smarkm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2855682Smarkm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2955682Smarkm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3055682Smarkm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3155682Smarkm * SUCH DAMAGE. 3255682Smarkm */ 3355682Smarkm 3455682Smarkm#include "krb5_locl.h" 3555682Smarkm 3672445SassarRCSID("$Id: mcache.c,v 1.12 2000/11/15 02:12:51 assar Exp $"); 3755682Smarkm 3855682Smarkmtypedef struct krb5_mcache { 3972445Sassar char *name; 4072445Sassar unsigned int refcnt; 4155682Smarkm krb5_principal primary_principal; 4255682Smarkm struct link { 4355682Smarkm krb5_creds cred; 4455682Smarkm struct link *next; 4555682Smarkm } *creds; 4672445Sassar struct krb5_mcache *next; 4755682Smarkm} krb5_mcache; 4855682Smarkm 4972445Sassarstatic struct krb5_mcache *mcc_head; 5072445Sassar 5172445Sassar#define MCACHE(X) ((krb5_mcache *)(X)->data.data) 5272445Sassar 5372445Sassar#define MISDEAD(X) ((X)->primary_principal == NULL) 5472445Sassar 5555682Smarkm#define MCC_CURSOR(C) ((struct link*)(C)) 5655682Smarkm 5755682Smarkmstatic char* 5855682Smarkmmcc_get_name(krb5_context context, 5955682Smarkm krb5_ccache id) 6055682Smarkm{ 6172445Sassar return MCACHE(id)->name; 6255682Smarkm} 6355682Smarkm 6472445Sassarstatic krb5_mcache * 6572445Sassarmcc_alloc(const char *name) 6672445Sassar{ 6772445Sassar krb5_mcache *m; 6872445Sassar ALLOC(m, 1); 6972445Sassar if(m == NULL) 7072445Sassar return NULL; 7172445Sassar if(name == NULL) 7272445Sassar asprintf(&m->name, "%p", m); 7372445Sassar else 7472445Sassar m->name = strdup(name); 7572445Sassar if(m->name == NULL) { 7672445Sassar free(m); 7772445Sassar return NULL; 7872445Sassar } 7972445Sassar m->refcnt = 1; 8072445Sassar m->primary_principal = NULL; 8172445Sassar m->creds = NULL; 8272445Sassar m->next = mcc_head; 8372445Sassar mcc_head = m; 8472445Sassar return m; 8572445Sassar} 8672445Sassar 8755682Smarkmstatic krb5_error_code 8855682Smarkmmcc_resolve(krb5_context context, krb5_ccache *id, const char *res) 8955682Smarkm{ 9072445Sassar krb5_mcache *m; 9172445Sassar 9272445Sassar for (m = mcc_head; m != NULL; m = m->next) 9372445Sassar if (strcmp(m->name, res) == 0) 9472445Sassar break; 9572445Sassar 9672445Sassar if (m != NULL) { 9772445Sassar m->refcnt++; 9872445Sassar (*id)->data.data = m; 9972445Sassar (*id)->data.length = sizeof(*m); 10072445Sassar return 0; 10172445Sassar } 10272445Sassar 10372445Sassar m = mcc_alloc(res); 10472445Sassar if (m == NULL) 10572445Sassar return KRB5_CC_NOMEM; 10672445Sassar 10772445Sassar (*id)->data.data = m; 10872445Sassar (*id)->data.length = sizeof(*m); 10972445Sassar 11072445Sassar return 0; 11155682Smarkm} 11255682Smarkm 11372445Sassar 11455682Smarkmstatic krb5_error_code 11555682Smarkmmcc_gen_new(krb5_context context, krb5_ccache *id) 11655682Smarkm{ 11755682Smarkm krb5_mcache *m; 11855682Smarkm 11972445Sassar m = mcc_alloc(NULL); 12072445Sassar 12155682Smarkm if (m == NULL) 12255682Smarkm return KRB5_CC_NOMEM; 12372445Sassar 12455682Smarkm (*id)->data.data = m; 12555682Smarkm (*id)->data.length = sizeof(*m); 12672445Sassar 12755682Smarkm return 0; 12855682Smarkm} 12955682Smarkm 13055682Smarkmstatic krb5_error_code 13155682Smarkmmcc_initialize(krb5_context context, 13255682Smarkm krb5_ccache id, 13355682Smarkm krb5_principal primary_principal) 13455682Smarkm{ 13572445Sassar return krb5_copy_principal (context, 13672445Sassar primary_principal, 13772445Sassar &MCACHE(id)->primary_principal); 13855682Smarkm} 13955682Smarkm 14055682Smarkmstatic krb5_error_code 14155682Smarkmmcc_close(krb5_context context, 14255682Smarkm krb5_ccache id) 14355682Smarkm{ 14472445Sassar krb5_mcache *m = MCACHE(id); 14555682Smarkm 14672445Sassar if (--m->refcnt != 0) 14772445Sassar return 0; 14855682Smarkm 14972445Sassar if (MISDEAD(m)) { 15072445Sassar free (m->name); 15172445Sassar krb5_data_free(&id->data); 15255682Smarkm } 15372445Sassar 15455682Smarkm return 0; 15555682Smarkm} 15655682Smarkm 15755682Smarkmstatic krb5_error_code 15855682Smarkmmcc_destroy(krb5_context context, 15955682Smarkm krb5_ccache id) 16055682Smarkm{ 16172445Sassar krb5_mcache **n, *m = MCACHE(id); 16272445Sassar struct link *l; 16372445Sassar 16472445Sassar if (m->refcnt == 0) 16572445Sassar krb5_abortx(context, "mcc_destroy: refcnt already 0"); 16672445Sassar 16772445Sassar if (!MISDEAD(m)) { 16872445Sassar /* if this is an active mcache, remove it from the linked 16972445Sassar list, and free all data */ 17072445Sassar for(n = &mcc_head; n && *n; n = &(*n)->next) { 17172445Sassar if(m == *n) { 17272445Sassar *n = m->next; 17372445Sassar break; 17472445Sassar } 17572445Sassar } 17672445Sassar krb5_free_principal (context, m->primary_principal); 17772445Sassar m->primary_principal = NULL; 17872445Sassar 17972445Sassar l = m->creds; 18072445Sassar while (l != NULL) { 18172445Sassar struct link *old; 18272445Sassar 18372445Sassar krb5_free_creds_contents (context, &l->cred); 18472445Sassar old = l; 18572445Sassar l = l->next; 18672445Sassar free (old); 18772445Sassar } 18872445Sassar m->creds = NULL; 18972445Sassar } 19055682Smarkm return 0; 19155682Smarkm} 19255682Smarkm 19355682Smarkmstatic krb5_error_code 19455682Smarkmmcc_store_cred(krb5_context context, 19555682Smarkm krb5_ccache id, 19655682Smarkm krb5_creds *creds) 19755682Smarkm{ 19872445Sassar krb5_mcache *m = MCACHE(id); 19955682Smarkm krb5_error_code ret; 20055682Smarkm struct link *l; 20155682Smarkm 20272445Sassar if (MISDEAD(m)) 20372445Sassar return ENOENT; 20472445Sassar 20555682Smarkm l = malloc (sizeof(*l)); 20655682Smarkm if (l == NULL) 20755682Smarkm return KRB5_CC_NOMEM; 20855682Smarkm l->next = m->creds; 20955682Smarkm m->creds = l; 21055682Smarkm memset (&l->cred, 0, sizeof(l->cred)); 21155682Smarkm ret = krb5_copy_creds_contents (context, creds, &l->cred); 21255682Smarkm if (ret) { 21355682Smarkm m->creds = l->next; 21455682Smarkm free (l); 21555682Smarkm return ret; 21655682Smarkm } 21755682Smarkm return 0; 21855682Smarkm} 21955682Smarkm 22055682Smarkmstatic krb5_error_code 22155682Smarkmmcc_get_principal(krb5_context context, 22255682Smarkm krb5_ccache id, 22355682Smarkm krb5_principal *principal) 22455682Smarkm{ 22572445Sassar krb5_mcache *m = MCACHE(id); 22655682Smarkm 22772445Sassar if (MISDEAD(m)) 22872445Sassar return ENOENT; 22972445Sassar 23055682Smarkm return krb5_copy_principal (context, 23155682Smarkm m->primary_principal, 23255682Smarkm principal); 23355682Smarkm} 23455682Smarkm 23555682Smarkmstatic krb5_error_code 23655682Smarkmmcc_get_first (krb5_context context, 23755682Smarkm krb5_ccache id, 23855682Smarkm krb5_cc_cursor *cursor) 23955682Smarkm{ 24072445Sassar krb5_mcache *m = MCACHE(id); 24172445Sassar 24272445Sassar if (MISDEAD(m)) 24372445Sassar return ENOENT; 24472445Sassar 24555682Smarkm *cursor = m->creds; 24655682Smarkm return 0; 24755682Smarkm} 24855682Smarkm 24955682Smarkmstatic krb5_error_code 25055682Smarkmmcc_get_next (krb5_context context, 25155682Smarkm krb5_ccache id, 25255682Smarkm krb5_cc_cursor *cursor, 25355682Smarkm krb5_creds *creds) 25455682Smarkm{ 25572445Sassar krb5_mcache *m = MCACHE(id); 25655682Smarkm struct link *l; 25755682Smarkm 25872445Sassar if (MISDEAD(m)) 25972445Sassar return ENOENT; 26072445Sassar 26155682Smarkm l = *cursor; 26255682Smarkm if (l != NULL) { 26355682Smarkm *cursor = l->next; 26455682Smarkm return krb5_copy_creds_contents (context, 26555682Smarkm &l->cred, 26655682Smarkm creds); 26755682Smarkm } else 26855682Smarkm return KRB5_CC_END; 26955682Smarkm} 27055682Smarkm 27155682Smarkmstatic krb5_error_code 27255682Smarkmmcc_end_get (krb5_context context, 27355682Smarkm krb5_ccache id, 27455682Smarkm krb5_cc_cursor *cursor) 27555682Smarkm{ 27655682Smarkm return 0; 27755682Smarkm} 27855682Smarkm 27955682Smarkmstatic krb5_error_code 28055682Smarkmmcc_remove_cred(krb5_context context, 28155682Smarkm krb5_ccache id, 28255682Smarkm krb5_flags which, 28372445Sassar krb5_creds *mcreds) 28455682Smarkm{ 28572445Sassar krb5_mcache *m = MCACHE(id); 28672445Sassar struct link **q, *p; 28772445Sassar for(q = &m->creds, p = *q; p; p = *q) { 28872445Sassar if(krb5_compare_creds(context, which, mcreds, &p->cred)) { 28972445Sassar *q = p->next; 29072445Sassar krb5_free_cred_contents(context, &p->cred); 29172445Sassar free(p); 29272445Sassar } else 29372445Sassar q = &p->next; 29472445Sassar } 29572445Sassar return 0; 29655682Smarkm} 29755682Smarkm 29855682Smarkmstatic krb5_error_code 29955682Smarkmmcc_set_flags(krb5_context context, 30055682Smarkm krb5_ccache id, 30155682Smarkm krb5_flags flags) 30255682Smarkm{ 30355682Smarkm return 0; /* XXX */ 30455682Smarkm} 30555682Smarkm 30655682Smarkmconst krb5_cc_ops krb5_mcc_ops = { 30755682Smarkm "MEMORY", 30855682Smarkm mcc_get_name, 30955682Smarkm mcc_resolve, 31055682Smarkm mcc_gen_new, 31155682Smarkm mcc_initialize, 31255682Smarkm mcc_destroy, 31355682Smarkm mcc_close, 31455682Smarkm mcc_store_cred, 31555682Smarkm NULL, /* mcc_retrieve */ 31655682Smarkm mcc_get_principal, 31755682Smarkm mcc_get_first, 31855682Smarkm mcc_get_next, 31955682Smarkm mcc_end_get, 32055682Smarkm mcc_remove_cred, 32155682Smarkm mcc_set_flags 32255682Smarkm}; 323