mcache.c revision 78527
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 3678527SassarRCSID("$Id: mcache.c,v 1.13 2001/05/14 06:14:49 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; 6878527Sassar 6972445Sassar ALLOC(m, 1); 7072445Sassar if(m == NULL) 7172445Sassar return NULL; 7272445Sassar if(name == NULL) 7372445Sassar asprintf(&m->name, "%p", m); 7472445Sassar else 7572445Sassar m->name = strdup(name); 7672445Sassar if(m->name == NULL) { 7772445Sassar free(m); 7872445Sassar return NULL; 7972445Sassar } 8072445Sassar m->refcnt = 1; 8172445Sassar m->primary_principal = NULL; 8272445Sassar m->creds = NULL; 8372445Sassar m->next = mcc_head; 8472445Sassar mcc_head = m; 8572445Sassar return m; 8672445Sassar} 8772445Sassar 8855682Smarkmstatic krb5_error_code 8955682Smarkmmcc_resolve(krb5_context context, krb5_ccache *id, const char *res) 9055682Smarkm{ 9172445Sassar krb5_mcache *m; 9272445Sassar 9372445Sassar for (m = mcc_head; m != NULL; m = m->next) 9472445Sassar if (strcmp(m->name, res) == 0) 9572445Sassar break; 9672445Sassar 9772445Sassar if (m != NULL) { 9872445Sassar m->refcnt++; 9972445Sassar (*id)->data.data = m; 10072445Sassar (*id)->data.length = sizeof(*m); 10172445Sassar return 0; 10272445Sassar } 10372445Sassar 10472445Sassar m = mcc_alloc(res); 10578527Sassar if (m == NULL) { 10678527Sassar krb5_set_error_string (context, "malloc: out of memory"); 10772445Sassar return KRB5_CC_NOMEM; 10878527Sassar } 10972445Sassar 11072445Sassar (*id)->data.data = m; 11172445Sassar (*id)->data.length = sizeof(*m); 11272445Sassar 11372445Sassar return 0; 11455682Smarkm} 11555682Smarkm 11672445Sassar 11755682Smarkmstatic krb5_error_code 11855682Smarkmmcc_gen_new(krb5_context context, krb5_ccache *id) 11955682Smarkm{ 12055682Smarkm krb5_mcache *m; 12155682Smarkm 12272445Sassar m = mcc_alloc(NULL); 12372445Sassar 12478527Sassar if (m == NULL) { 12578527Sassar krb5_set_error_string (context, "malloc: out of memory"); 12655682Smarkm return KRB5_CC_NOMEM; 12778527Sassar } 12872445Sassar 12955682Smarkm (*id)->data.data = m; 13055682Smarkm (*id)->data.length = sizeof(*m); 13172445Sassar 13255682Smarkm return 0; 13355682Smarkm} 13455682Smarkm 13555682Smarkmstatic krb5_error_code 13655682Smarkmmcc_initialize(krb5_context context, 13755682Smarkm krb5_ccache id, 13855682Smarkm krb5_principal primary_principal) 13955682Smarkm{ 14072445Sassar return krb5_copy_principal (context, 14172445Sassar primary_principal, 14272445Sassar &MCACHE(id)->primary_principal); 14355682Smarkm} 14455682Smarkm 14555682Smarkmstatic krb5_error_code 14655682Smarkmmcc_close(krb5_context context, 14755682Smarkm krb5_ccache id) 14855682Smarkm{ 14972445Sassar krb5_mcache *m = MCACHE(id); 15055682Smarkm 15172445Sassar if (--m->refcnt != 0) 15272445Sassar return 0; 15355682Smarkm 15472445Sassar if (MISDEAD(m)) { 15572445Sassar free (m->name); 15672445Sassar krb5_data_free(&id->data); 15755682Smarkm } 15872445Sassar 15955682Smarkm return 0; 16055682Smarkm} 16155682Smarkm 16255682Smarkmstatic krb5_error_code 16355682Smarkmmcc_destroy(krb5_context context, 16455682Smarkm krb5_ccache id) 16555682Smarkm{ 16672445Sassar krb5_mcache **n, *m = MCACHE(id); 16772445Sassar struct link *l; 16872445Sassar 16972445Sassar if (m->refcnt == 0) 17072445Sassar krb5_abortx(context, "mcc_destroy: refcnt already 0"); 17172445Sassar 17272445Sassar if (!MISDEAD(m)) { 17372445Sassar /* if this is an active mcache, remove it from the linked 17472445Sassar list, and free all data */ 17572445Sassar for(n = &mcc_head; n && *n; n = &(*n)->next) { 17672445Sassar if(m == *n) { 17772445Sassar *n = m->next; 17872445Sassar break; 17972445Sassar } 18072445Sassar } 18172445Sassar krb5_free_principal (context, m->primary_principal); 18272445Sassar m->primary_principal = NULL; 18372445Sassar 18472445Sassar l = m->creds; 18572445Sassar while (l != NULL) { 18672445Sassar struct link *old; 18772445Sassar 18872445Sassar krb5_free_creds_contents (context, &l->cred); 18972445Sassar old = l; 19072445Sassar l = l->next; 19172445Sassar free (old); 19272445Sassar } 19372445Sassar m->creds = NULL; 19472445Sassar } 19555682Smarkm return 0; 19655682Smarkm} 19755682Smarkm 19855682Smarkmstatic krb5_error_code 19955682Smarkmmcc_store_cred(krb5_context context, 20055682Smarkm krb5_ccache id, 20155682Smarkm krb5_creds *creds) 20255682Smarkm{ 20372445Sassar krb5_mcache *m = MCACHE(id); 20455682Smarkm krb5_error_code ret; 20555682Smarkm struct link *l; 20655682Smarkm 20772445Sassar if (MISDEAD(m)) 20872445Sassar return ENOENT; 20972445Sassar 21055682Smarkm l = malloc (sizeof(*l)); 21178527Sassar if (l == NULL) { 21278527Sassar krb5_set_error_string (context, "malloc: out of memory"); 21355682Smarkm return KRB5_CC_NOMEM; 21478527Sassar } 21555682Smarkm l->next = m->creds; 21655682Smarkm m->creds = l; 21755682Smarkm memset (&l->cred, 0, sizeof(l->cred)); 21855682Smarkm ret = krb5_copy_creds_contents (context, creds, &l->cred); 21955682Smarkm if (ret) { 22055682Smarkm m->creds = l->next; 22155682Smarkm free (l); 22255682Smarkm return ret; 22355682Smarkm } 22455682Smarkm return 0; 22555682Smarkm} 22655682Smarkm 22755682Smarkmstatic krb5_error_code 22855682Smarkmmcc_get_principal(krb5_context context, 22955682Smarkm krb5_ccache id, 23055682Smarkm krb5_principal *principal) 23155682Smarkm{ 23272445Sassar krb5_mcache *m = MCACHE(id); 23355682Smarkm 23472445Sassar if (MISDEAD(m)) 23572445Sassar return ENOENT; 23672445Sassar 23755682Smarkm return krb5_copy_principal (context, 23855682Smarkm m->primary_principal, 23955682Smarkm principal); 24055682Smarkm} 24155682Smarkm 24255682Smarkmstatic krb5_error_code 24355682Smarkmmcc_get_first (krb5_context context, 24455682Smarkm krb5_ccache id, 24555682Smarkm krb5_cc_cursor *cursor) 24655682Smarkm{ 24772445Sassar krb5_mcache *m = MCACHE(id); 24872445Sassar 24972445Sassar if (MISDEAD(m)) 25072445Sassar return ENOENT; 25172445Sassar 25255682Smarkm *cursor = m->creds; 25355682Smarkm return 0; 25455682Smarkm} 25555682Smarkm 25655682Smarkmstatic krb5_error_code 25755682Smarkmmcc_get_next (krb5_context context, 25855682Smarkm krb5_ccache id, 25955682Smarkm krb5_cc_cursor *cursor, 26055682Smarkm krb5_creds *creds) 26155682Smarkm{ 26272445Sassar krb5_mcache *m = MCACHE(id); 26355682Smarkm struct link *l; 26455682Smarkm 26572445Sassar if (MISDEAD(m)) 26672445Sassar return ENOENT; 26772445Sassar 26855682Smarkm l = *cursor; 26955682Smarkm if (l != NULL) { 27055682Smarkm *cursor = l->next; 27155682Smarkm return krb5_copy_creds_contents (context, 27255682Smarkm &l->cred, 27355682Smarkm creds); 27455682Smarkm } else 27555682Smarkm return KRB5_CC_END; 27655682Smarkm} 27755682Smarkm 27855682Smarkmstatic krb5_error_code 27955682Smarkmmcc_end_get (krb5_context context, 28055682Smarkm krb5_ccache id, 28155682Smarkm krb5_cc_cursor *cursor) 28255682Smarkm{ 28355682Smarkm return 0; 28455682Smarkm} 28555682Smarkm 28655682Smarkmstatic krb5_error_code 28755682Smarkmmcc_remove_cred(krb5_context context, 28855682Smarkm krb5_ccache id, 28955682Smarkm krb5_flags which, 29072445Sassar krb5_creds *mcreds) 29155682Smarkm{ 29272445Sassar krb5_mcache *m = MCACHE(id); 29372445Sassar struct link **q, *p; 29472445Sassar for(q = &m->creds, p = *q; p; p = *q) { 29572445Sassar if(krb5_compare_creds(context, which, mcreds, &p->cred)) { 29672445Sassar *q = p->next; 29772445Sassar krb5_free_cred_contents(context, &p->cred); 29872445Sassar free(p); 29972445Sassar } else 30072445Sassar q = &p->next; 30172445Sassar } 30272445Sassar return 0; 30355682Smarkm} 30455682Smarkm 30555682Smarkmstatic krb5_error_code 30655682Smarkmmcc_set_flags(krb5_context context, 30755682Smarkm krb5_ccache id, 30855682Smarkm krb5_flags flags) 30955682Smarkm{ 31055682Smarkm return 0; /* XXX */ 31155682Smarkm} 31255682Smarkm 31355682Smarkmconst krb5_cc_ops krb5_mcc_ops = { 31455682Smarkm "MEMORY", 31555682Smarkm mcc_get_name, 31655682Smarkm mcc_resolve, 31755682Smarkm mcc_gen_new, 31855682Smarkm mcc_initialize, 31955682Smarkm mcc_destroy, 32055682Smarkm mcc_close, 32155682Smarkm mcc_store_cred, 32255682Smarkm NULL, /* mcc_retrieve */ 32355682Smarkm mcc_get_principal, 32455682Smarkm mcc_get_first, 32555682Smarkm mcc_get_next, 32655682Smarkm mcc_end_get, 32755682Smarkm mcc_remove_cred, 32855682Smarkm mcc_set_flags 32955682Smarkm}; 330