mcache.c revision 72445
1/* 2 * Copyright (c) 1997-2000 Kungliga Tekniska H�gskolan 3 * (Royal Institute of Technology, Stockholm, Sweden). 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * 3. Neither the name of the Institute nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34#include "krb5_locl.h" 35 36RCSID("$Id: mcache.c,v 1.12 2000/11/15 02:12:51 assar Exp $"); 37 38typedef struct krb5_mcache { 39 char *name; 40 unsigned int refcnt; 41 krb5_principal primary_principal; 42 struct link { 43 krb5_creds cred; 44 struct link *next; 45 } *creds; 46 struct krb5_mcache *next; 47} krb5_mcache; 48 49static struct krb5_mcache *mcc_head; 50 51#define MCACHE(X) ((krb5_mcache *)(X)->data.data) 52 53#define MISDEAD(X) ((X)->primary_principal == NULL) 54 55#define MCC_CURSOR(C) ((struct link*)(C)) 56 57static char* 58mcc_get_name(krb5_context context, 59 krb5_ccache id) 60{ 61 return MCACHE(id)->name; 62} 63 64static krb5_mcache * 65mcc_alloc(const char *name) 66{ 67 krb5_mcache *m; 68 ALLOC(m, 1); 69 if(m == NULL) 70 return NULL; 71 if(name == NULL) 72 asprintf(&m->name, "%p", m); 73 else 74 m->name = strdup(name); 75 if(m->name == NULL) { 76 free(m); 77 return NULL; 78 } 79 m->refcnt = 1; 80 m->primary_principal = NULL; 81 m->creds = NULL; 82 m->next = mcc_head; 83 mcc_head = m; 84 return m; 85} 86 87static krb5_error_code 88mcc_resolve(krb5_context context, krb5_ccache *id, const char *res) 89{ 90 krb5_mcache *m; 91 92 for (m = mcc_head; m != NULL; m = m->next) 93 if (strcmp(m->name, res) == 0) 94 break; 95 96 if (m != NULL) { 97 m->refcnt++; 98 (*id)->data.data = m; 99 (*id)->data.length = sizeof(*m); 100 return 0; 101 } 102 103 m = mcc_alloc(res); 104 if (m == NULL) 105 return KRB5_CC_NOMEM; 106 107 (*id)->data.data = m; 108 (*id)->data.length = sizeof(*m); 109 110 return 0; 111} 112 113 114static krb5_error_code 115mcc_gen_new(krb5_context context, krb5_ccache *id) 116{ 117 krb5_mcache *m; 118 119 m = mcc_alloc(NULL); 120 121 if (m == NULL) 122 return KRB5_CC_NOMEM; 123 124 (*id)->data.data = m; 125 (*id)->data.length = sizeof(*m); 126 127 return 0; 128} 129 130static krb5_error_code 131mcc_initialize(krb5_context context, 132 krb5_ccache id, 133 krb5_principal primary_principal) 134{ 135 return krb5_copy_principal (context, 136 primary_principal, 137 &MCACHE(id)->primary_principal); 138} 139 140static krb5_error_code 141mcc_close(krb5_context context, 142 krb5_ccache id) 143{ 144 krb5_mcache *m = MCACHE(id); 145 146 if (--m->refcnt != 0) 147 return 0; 148 149 if (MISDEAD(m)) { 150 free (m->name); 151 krb5_data_free(&id->data); 152 } 153 154 return 0; 155} 156 157static krb5_error_code 158mcc_destroy(krb5_context context, 159 krb5_ccache id) 160{ 161 krb5_mcache **n, *m = MCACHE(id); 162 struct link *l; 163 164 if (m->refcnt == 0) 165 krb5_abortx(context, "mcc_destroy: refcnt already 0"); 166 167 if (!MISDEAD(m)) { 168 /* if this is an active mcache, remove it from the linked 169 list, and free all data */ 170 for(n = &mcc_head; n && *n; n = &(*n)->next) { 171 if(m == *n) { 172 *n = m->next; 173 break; 174 } 175 } 176 krb5_free_principal (context, m->primary_principal); 177 m->primary_principal = NULL; 178 179 l = m->creds; 180 while (l != NULL) { 181 struct link *old; 182 183 krb5_free_creds_contents (context, &l->cred); 184 old = l; 185 l = l->next; 186 free (old); 187 } 188 m->creds = NULL; 189 } 190 return 0; 191} 192 193static krb5_error_code 194mcc_store_cred(krb5_context context, 195 krb5_ccache id, 196 krb5_creds *creds) 197{ 198 krb5_mcache *m = MCACHE(id); 199 krb5_error_code ret; 200 struct link *l; 201 202 if (MISDEAD(m)) 203 return ENOENT; 204 205 l = malloc (sizeof(*l)); 206 if (l == NULL) 207 return KRB5_CC_NOMEM; 208 l->next = m->creds; 209 m->creds = l; 210 memset (&l->cred, 0, sizeof(l->cred)); 211 ret = krb5_copy_creds_contents (context, creds, &l->cred); 212 if (ret) { 213 m->creds = l->next; 214 free (l); 215 return ret; 216 } 217 return 0; 218} 219 220static krb5_error_code 221mcc_get_principal(krb5_context context, 222 krb5_ccache id, 223 krb5_principal *principal) 224{ 225 krb5_mcache *m = MCACHE(id); 226 227 if (MISDEAD(m)) 228 return ENOENT; 229 230 return krb5_copy_principal (context, 231 m->primary_principal, 232 principal); 233} 234 235static krb5_error_code 236mcc_get_first (krb5_context context, 237 krb5_ccache id, 238 krb5_cc_cursor *cursor) 239{ 240 krb5_mcache *m = MCACHE(id); 241 242 if (MISDEAD(m)) 243 return ENOENT; 244 245 *cursor = m->creds; 246 return 0; 247} 248 249static krb5_error_code 250mcc_get_next (krb5_context context, 251 krb5_ccache id, 252 krb5_cc_cursor *cursor, 253 krb5_creds *creds) 254{ 255 krb5_mcache *m = MCACHE(id); 256 struct link *l; 257 258 if (MISDEAD(m)) 259 return ENOENT; 260 261 l = *cursor; 262 if (l != NULL) { 263 *cursor = l->next; 264 return krb5_copy_creds_contents (context, 265 &l->cred, 266 creds); 267 } else 268 return KRB5_CC_END; 269} 270 271static krb5_error_code 272mcc_end_get (krb5_context context, 273 krb5_ccache id, 274 krb5_cc_cursor *cursor) 275{ 276 return 0; 277} 278 279static krb5_error_code 280mcc_remove_cred(krb5_context context, 281 krb5_ccache id, 282 krb5_flags which, 283 krb5_creds *mcreds) 284{ 285 krb5_mcache *m = MCACHE(id); 286 struct link **q, *p; 287 for(q = &m->creds, p = *q; p; p = *q) { 288 if(krb5_compare_creds(context, which, mcreds, &p->cred)) { 289 *q = p->next; 290 krb5_free_cred_contents(context, &p->cred); 291 free(p); 292 } else 293 q = &p->next; 294 } 295 return 0; 296} 297 298static krb5_error_code 299mcc_set_flags(krb5_context context, 300 krb5_ccache id, 301 krb5_flags flags) 302{ 303 return 0; /* XXX */ 304} 305 306const krb5_cc_ops krb5_mcc_ops = { 307 "MEMORY", 308 mcc_get_name, 309 mcc_resolve, 310 mcc_gen_new, 311 mcc_initialize, 312 mcc_destroy, 313 mcc_close, 314 mcc_store_cred, 315 NULL, /* mcc_retrieve */ 316 mcc_get_principal, 317 mcc_get_first, 318 mcc_get_next, 319 mcc_end_get, 320 mcc_remove_cred, 321 mcc_set_flags 322}; 323