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