1 /* 2 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 3 * Use is subject to license terms. 4 */ 5 6 #pragma ident "%Z%%M% %I% %E% SMI" 7 8 /* 9 * lib/krb5/rcache/rc_base.c 10 * 11 * This file of the Kerberos V5 software is derived from public-domain code 12 * contributed by Daniel J. Bernstein, <brnstnd@acf10.nyu.edu>. 13 */ 14 15 16 /* 17 * Base "glue" functions for the replay cache. 18 */ 19 20 #include "rc_base.h" 21 #include "rc_common.h" 22 #include "rc_mem.h" 23 #include "rc_file.h" 24 #include <k5-thread.h> 25 26 #define FREE_RC(x) ((void) free((char *) (x))) 27 28 struct krb5_rc_typelist 29 { 30 const krb5_rc_ops *ops; 31 struct krb5_rc_typelist *next; 32 }; 33 34 static struct krb5_rc_typelist rc_none_type = { &krb5_rc_none_ops, 0 }; 35 static struct krb5_rc_typelist rc_mem_type = 36 { &krb5_rc_mem_ops, &rc_none_type }; 37 static struct krb5_rc_typelist krb5_rc_typelist_dfl = 38 { &krb5_rc_file_ops, &rc_mem_type }; 39 static struct krb5_rc_typelist *typehead = &krb5_rc_typelist_dfl; 40 static k5_mutex_t rc_typelist_lock = K5_MUTEX_PARTIAL_INITIALIZER; 41 42 int krb5int_rc_finish_init(void) 43 { 44 int retval; 45 46 retval = k5_mutex_finish_init(&grcache.lock); 47 if (retval) 48 return (retval); 49 50 return k5_mutex_finish_init(&rc_typelist_lock); 51 } 52 void krb5int_rc_terminate(void) 53 { 54 struct krb5_rc_typelist *t, *t_next; 55 struct mem_data *tgr = (struct mem_data *)grcache.data; 56 struct authlist *q, *qt; 57 int i; 58 59 k5_mutex_destroy(&grcache.lock); 60 61 if (tgr != NULL) { 62 if (tgr->name) 63 free(tgr->name); 64 for (i = 0; i < tgr->hsize; i++) 65 for (q = tgr->h[i]; q; q = qt) { 66 qt = q->nh; 67 free(q->rep.server); 68 free(q->rep.client); 69 free(q); 70 } 71 if (tgr->h) 72 free(tgr->h); 73 free(tgr); 74 } 75 76 k5_mutex_destroy(&rc_typelist_lock); 77 for (t = typehead; t != &krb5_rc_typelist_dfl; t = t_next) { 78 t_next = t->next; 79 free(t); 80 } 81 } 82 83 /*ARGSUSED*/ 84 krb5_error_code krb5_rc_register_type(krb5_context context, 85 const krb5_rc_ops *ops) 86 { 87 struct krb5_rc_typelist *t; 88 krb5_error_code err; 89 90 err = k5_mutex_lock(&rc_typelist_lock); 91 if (err) 92 return err; 93 94 for (t = typehead;t && strcmp(t->ops->type,ops->type);t = t->next) 95 ; 96 if (t) { 97 k5_mutex_unlock(&rc_typelist_lock); 98 return KRB5_RC_TYPE_EXISTS; 99 } 100 101 t = (struct krb5_rc_typelist *) malloc(sizeof(struct krb5_rc_typelist)); 102 if (t == NULL) { 103 k5_mutex_unlock(&rc_typelist_lock); 104 return KRB5_RC_MALLOC; 105 } 106 t->next = typehead; 107 t->ops = ops; 108 typehead = t; 109 110 k5_mutex_unlock(&rc_typelist_lock); 111 return 0; 112 } 113 114 /*ARGSUSED*/ 115 krb5_error_code krb5_rc_resolve_type(krb5_context context, krb5_rcache *id, 116 char *type) 117 { 118 struct krb5_rc_typelist *t; 119 krb5_error_code err; 120 err = k5_mutex_lock(&rc_typelist_lock); 121 if (err) 122 return err; 123 for (t = typehead;t && strcmp(t->ops->type,type);t = t->next) 124 ; 125 if (!t) { 126 k5_mutex_unlock(&rc_typelist_lock); 127 return KRB5_RC_TYPE_NOTFOUND; 128 } 129 /* allocate *id? nah */ 130 (*id)->ops = t->ops; 131 k5_mutex_unlock(&rc_typelist_lock); 132 return k5_mutex_init(&(*id)->lock); 133 } 134 135 /*ARGSUSED*/ 136 char * krb5_rc_get_type(krb5_context context, krb5_rcache id) 137 { 138 return id->ops->type; 139 } 140 141 char * krb5_rc_default_type(krb5_context context) 142 { 143 /* 144 * Solaris Kerberos/SUNW14resync 145 * MIT's is "dfl" but we now have FILE and MEMORY instead. 146 * And we only support the KRB5RCNAME env var. 147 */ 148 return ("FILE"); 149 } 150 151 /*ARGSUSED*/ 152 char * krb5_rc_default_name(krb5_context context) 153 { 154 char *s; 155 if ((s = getenv("KRB5RCNAME"))) 156 return s; 157 else 158 return (char *) 0; 159 } 160 161 krb5_error_code 162 krb5_rc_default(krb5_context context, krb5_rcache *id) 163 { 164 krb5_error_code retval; 165 166 if (!(*id = (krb5_rcache )malloc(sizeof(**id)))) 167 return KRB5_RC_MALLOC; 168 169 retval = krb5_rc_resolve_type(context, id, krb5_rc_default_type(context)); 170 if (retval != 0) { 171 /* 172 * k5_mutex_destroy() is not called here, because the mutex had 173 * not been successfully initialized by krb5_rc_resolve_type(). 174 */ 175 FREE_RC(*id); 176 return (retval); 177 } 178 retval = krb5_rc_resolve(context, *id, krb5_rc_default_name(context)); 179 if (retval) { 180 k5_mutex_destroy(&(*id)->lock); 181 FREE_RC(*id); 182 return retval; 183 } 184 (*id)->magic = KV5M_RCACHE; 185 return retval; 186 } 187 188 krb5_error_code krb5_rc_resolve_full(krb5_context context, krb5_rcache *id, char *string_name) 189 { 190 char *type; 191 char *residual; 192 krb5_error_code retval; 193 unsigned int diff; 194 195 if (!(residual = strchr(string_name,':'))) 196 return KRB5_RC_PARSE; 197 198 diff = residual - string_name; 199 if (!(type = malloc(diff + 1))) 200 return KRB5_RC_MALLOC; 201 (void) strncpy(type, string_name, diff); 202 type[residual - string_name] = '\0'; 203 204 if (!(*id = (krb5_rcache) malloc(sizeof(**id)))) { 205 FREE_RC(type); 206 return KRB5_RC_MALLOC; 207 } 208 209 retval = krb5_rc_resolve_type(context, id, type); 210 if (retval != 0) { 211 /* 212 * k5_mutex_destroy() is not called here, because the mutex had 213 * not been successfully initialized by krb5_rc_resolve_type(). 214 */ 215 FREE_RC(type); 216 FREE_RC(*id); 217 return retval; 218 } 219 FREE_RC(type); 220 retval = krb5_rc_resolve(context, *id, residual + 1); 221 if (retval) { 222 k5_mutex_destroy(&(*id)->lock); 223 FREE_RC(*id); 224 return retval; 225 } 226 (*id)->magic = KV5M_RCACHE; 227 return retval; 228 } 229