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