mcache.c revision 78527
184260Sobrien/* 21573Srgrimes * Copyright (c) 1997-2000 Kungliga Tekniska H�gskolan 351794Smarcel * (Royal Institute of Technology, Stockholm, Sweden). 41573Srgrimes * All rights reserved. 51573Srgrimes * 684260Sobrien * Redistribution and use in source and binary forms, with or without 751794Smarcel * modification, are permitted provided that the following conditions 81573Srgrimes * are met: 926926Smsmith * 1026926Smsmith * 1. Redistributions of source code must retain the above copyright 111573Srgrimes * notice, this list of conditions and the following disclaimer. 1251904Smarcel * 1351904Smarcel * 2. Redistributions in binary form must reproduce the above copyright 143527Sache * notice, this list of conditions and the following disclaimer in the 1574870Sru * documentation and/or other materials provided with the distribution. 1626926Smsmith * 1726926Smsmith * 3. Neither the name of the Institute nor the names of its contributors 1884260Sobrien * may be used to endorse or promote products derived from this software 1926926Smsmith * without specific prior written permission. 2026926Smsmith * 2126926Smsmith * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 2226926Smsmith * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2350088Smdodd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2484260Sobrien * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 2526926Smsmith * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 261573Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 271573Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 281573Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 291573Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 301573Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3126926Smsmith * SUCH DAMAGE. 3284260Sobrien */ 3326926Smsmith 3426926Smsmith#include "krb5_locl.h" 358870Srgrimes 361573SrgrimesRCSID("$Id: mcache.c,v 1.13 2001/05/14 06:14:49 assar Exp $"); 371573Srgrimes 381573Srgrimestypedef struct krb5_mcache { 398870Srgrimes char *name; 401573Srgrimes unsigned int refcnt; 411573Srgrimes krb5_principal primary_principal; 421573Srgrimes struct link { 431573Srgrimes krb5_creds cred; 441573Srgrimes struct link *next; 451573Srgrimes } *creds; 461573Srgrimes struct krb5_mcache *next; 471573Srgrimes} krb5_mcache; 481573Srgrimes 491573Srgrimesstatic struct krb5_mcache *mcc_head; 501573Srgrimes 511573Srgrimes#define MCACHE(X) ((krb5_mcache *)(X)->data.data) 521573Srgrimes 531573Srgrimes#define MISDEAD(X) ((X)->primary_principal == NULL) 541573Srgrimes 551573Srgrimes#define MCC_CURSOR(C) ((struct link*)(C)) 561573Srgrimes 578870Srgrimesstatic char* 581573Srgrimesmcc_get_name(krb5_context context, 591573Srgrimes krb5_ccache id) 601573Srgrimes{ 611573Srgrimes return MCACHE(id)->name; 621573Srgrimes} 6384260Sobrien 6484260Sobrienstatic krb5_mcache * 651573Srgrimesmcc_alloc(const char *name) 6684260Sobrien{ 6784260Sobrien krb5_mcache *m; 6884260Sobrien 691573Srgrimes ALLOC(m, 1); 7084260Sobrien if(m == NULL) 7184260Sobrien return NULL; 722678Srgrimes if(name == NULL) 7317929Speter asprintf(&m->name, "%p", m); 741573Srgrimes else 751573Srgrimes m->name = strdup(name); 76 if(m->name == NULL) { 77 free(m); 78 return NULL; 79 } 80 m->refcnt = 1; 81 m->primary_principal = NULL; 82 m->creds = NULL; 83 m->next = mcc_head; 84 mcc_head = m; 85 return m; 86} 87 88static krb5_error_code 89mcc_resolve(krb5_context context, krb5_ccache *id, const char *res) 90{ 91 krb5_mcache *m; 92 93 for (m = mcc_head; m != NULL; m = m->next) 94 if (strcmp(m->name, res) == 0) 95 break; 96 97 if (m != NULL) { 98 m->refcnt++; 99 (*id)->data.data = m; 100 (*id)->data.length = sizeof(*m); 101 return 0; 102 } 103 104 m = mcc_alloc(res); 105 if (m == NULL) { 106 krb5_set_error_string (context, "malloc: out of memory"); 107 return KRB5_CC_NOMEM; 108 } 109 110 (*id)->data.data = m; 111 (*id)->data.length = sizeof(*m); 112 113 return 0; 114} 115 116 117static krb5_error_code 118mcc_gen_new(krb5_context context, krb5_ccache *id) 119{ 120 krb5_mcache *m; 121 122 m = mcc_alloc(NULL); 123 124 if (m == NULL) { 125 krb5_set_error_string (context, "malloc: out of memory"); 126 return KRB5_CC_NOMEM; 127 } 128 129 (*id)->data.data = m; 130 (*id)->data.length = sizeof(*m); 131 132 return 0; 133} 134 135static krb5_error_code 136mcc_initialize(krb5_context context, 137 krb5_ccache id, 138 krb5_principal primary_principal) 139{ 140 return krb5_copy_principal (context, 141 primary_principal, 142 &MCACHE(id)->primary_principal); 143} 144 145static krb5_error_code 146mcc_close(krb5_context context, 147 krb5_ccache id) 148{ 149 krb5_mcache *m = MCACHE(id); 150 151 if (--m->refcnt != 0) 152 return 0; 153 154 if (MISDEAD(m)) { 155 free (m->name); 156 krb5_data_free(&id->data); 157 } 158 159 return 0; 160} 161 162static krb5_error_code 163mcc_destroy(krb5_context context, 164 krb5_ccache id) 165{ 166 krb5_mcache **n, *m = MCACHE(id); 167 struct link *l; 168 169 if (m->refcnt == 0) 170 krb5_abortx(context, "mcc_destroy: refcnt already 0"); 171 172 if (!MISDEAD(m)) { 173 /* if this is an active mcache, remove it from the linked 174 list, and free all data */ 175 for(n = &mcc_head; n && *n; n = &(*n)->next) { 176 if(m == *n) { 177 *n = m->next; 178 break; 179 } 180 } 181 krb5_free_principal (context, m->primary_principal); 182 m->primary_principal = NULL; 183 184 l = m->creds; 185 while (l != NULL) { 186 struct link *old; 187 188 krb5_free_creds_contents (context, &l->cred); 189 old = l; 190 l = l->next; 191 free (old); 192 } 193 m->creds = NULL; 194 } 195 return 0; 196} 197 198static krb5_error_code 199mcc_store_cred(krb5_context context, 200 krb5_ccache id, 201 krb5_creds *creds) 202{ 203 krb5_mcache *m = MCACHE(id); 204 krb5_error_code ret; 205 struct link *l; 206 207 if (MISDEAD(m)) 208 return ENOENT; 209 210 l = malloc (sizeof(*l)); 211 if (l == NULL) { 212 krb5_set_error_string (context, "malloc: out of memory"); 213 return KRB5_CC_NOMEM; 214 } 215 l->next = m->creds; 216 m->creds = l; 217 memset (&l->cred, 0, sizeof(l->cred)); 218 ret = krb5_copy_creds_contents (context, creds, &l->cred); 219 if (ret) { 220 m->creds = l->next; 221 free (l); 222 return ret; 223 } 224 return 0; 225} 226 227static krb5_error_code 228mcc_get_principal(krb5_context context, 229 krb5_ccache id, 230 krb5_principal *principal) 231{ 232 krb5_mcache *m = MCACHE(id); 233 234 if (MISDEAD(m)) 235 return ENOENT; 236 237 return krb5_copy_principal (context, 238 m->primary_principal, 239 principal); 240} 241 242static krb5_error_code 243mcc_get_first (krb5_context context, 244 krb5_ccache id, 245 krb5_cc_cursor *cursor) 246{ 247 krb5_mcache *m = MCACHE(id); 248 249 if (MISDEAD(m)) 250 return ENOENT; 251 252 *cursor = m->creds; 253 return 0; 254} 255 256static krb5_error_code 257mcc_get_next (krb5_context context, 258 krb5_ccache id, 259 krb5_cc_cursor *cursor, 260 krb5_creds *creds) 261{ 262 krb5_mcache *m = MCACHE(id); 263 struct link *l; 264 265 if (MISDEAD(m)) 266 return ENOENT; 267 268 l = *cursor; 269 if (l != NULL) { 270 *cursor = l->next; 271 return krb5_copy_creds_contents (context, 272 &l->cred, 273 creds); 274 } else 275 return KRB5_CC_END; 276} 277 278static krb5_error_code 279mcc_end_get (krb5_context context, 280 krb5_ccache id, 281 krb5_cc_cursor *cursor) 282{ 283 return 0; 284} 285 286static krb5_error_code 287mcc_remove_cred(krb5_context context, 288 krb5_ccache id, 289 krb5_flags which, 290 krb5_creds *mcreds) 291{ 292 krb5_mcache *m = MCACHE(id); 293 struct link **q, *p; 294 for(q = &m->creds, p = *q; p; p = *q) { 295 if(krb5_compare_creds(context, which, mcreds, &p->cred)) { 296 *q = p->next; 297 krb5_free_cred_contents(context, &p->cred); 298 free(p); 299 } else 300 q = &p->next; 301 } 302 return 0; 303} 304 305static krb5_error_code 306mcc_set_flags(krb5_context context, 307 krb5_ccache id, 308 krb5_flags flags) 309{ 310 return 0; /* XXX */ 311} 312 313const krb5_cc_ops krb5_mcc_ops = { 314 "MEMORY", 315 mcc_get_name, 316 mcc_resolve, 317 mcc_gen_new, 318 mcc_initialize, 319 mcc_destroy, 320 mcc_close, 321 mcc_store_cred, 322 NULL, /* mcc_retrieve */ 323 mcc_get_principal, 324 mcc_get_first, 325 mcc_get_next, 326 mcc_end_get, 327 mcc_remove_cred, 328 mcc_set_flags 329}; 330