1 /* 2 * Copyright 2006 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 static struct krb5_rc_typelist rc_mem_type = { &krb5_rc_mem_ops, 0 }; 34 static struct krb5_rc_typelist krb5_rc_typelist_dfl = 35 { &krb5_rc_file_ops, &rc_mem_type }; 36 static struct krb5_rc_typelist *typehead = &krb5_rc_typelist_dfl; 37 static k5_mutex_t rc_typelist_lock = K5_MUTEX_PARTIAL_INITIALIZER; 38 39 int krb5int_rc_finish_init(void) 40 { 41 int retval; 42 43 retval = k5_mutex_finish_init(&grcache.lock); 44 if (retval) 45 return (retval); 46 47 return k5_mutex_finish_init(&rc_typelist_lock); 48 } 49 void krb5int_rc_terminate(void) 50 { 51 struct krb5_rc_typelist *t, *t_next; 52 struct mem_data *tgr = (struct mem_data *)grcache.data; 53 struct authlist *q, *qt; 54 int i; 55 56 k5_mutex_destroy(&grcache.lock); 57 58 if (tgr != NULL) { 59 if (tgr->name) 60 free(tgr->name); 61 for (i = 0; i < tgr->hsize; i++) 62 for (q = tgr->h[i]; q; q = qt) { 63 qt = q->nh; 64 free(q->rep.server); 65 free(q->rep.client); 66 free(q); 67 } 68 if (tgr->h) 69 free(tgr->h); 70 free(tgr); 71 } 72 73 k5_mutex_destroy(&rc_typelist_lock); 74 for (t = typehead; t != &krb5_rc_typelist_dfl; t = t_next) { 75 t_next = t->next; 76 free(t); 77 } 78 } 79 80 /*ARGSUSED*/ 81 krb5_error_code krb5_rc_register_type(krb5_context context, 82 const krb5_rc_ops *ops) 83 { 84 struct krb5_rc_typelist *t; 85 krb5_error_code err; 86 87 err = k5_mutex_lock(&rc_typelist_lock); 88 if (err) 89 return err; 90 91 for (t = typehead;t && strcmp(t->ops->type,ops->type);t = t->next) 92 ; 93 if (t) { 94 k5_mutex_unlock(&rc_typelist_lock); 95 return KRB5_RC_TYPE_EXISTS; 96 } 97 98 t = (struct krb5_rc_typelist *) malloc(sizeof(struct krb5_rc_typelist)); 99 if (t == NULL) { 100 k5_mutex_unlock(&rc_typelist_lock); 101 return KRB5_RC_MALLOC; 102 } 103 t->next = typehead; 104 t->ops = ops; 105 typehead = t; 106 107 k5_mutex_unlock(&rc_typelist_lock); 108 return 0; 109 } 110 111 /*ARGSUSED*/ 112 krb5_error_code krb5_rc_resolve_type(krb5_context context, krb5_rcache *id, 113 char *type) 114 { 115 struct krb5_rc_typelist *t; 116 krb5_error_code err; 117 err = k5_mutex_lock(&rc_typelist_lock); 118 if (err) 119 return err; 120 for (t = typehead;t && strcmp(t->ops->type,type);t = t->next) 121 ; 122 if (!t) { 123 k5_mutex_unlock(&rc_typelist_lock); 124 return KRB5_RC_TYPE_NOTFOUND; 125 } 126 /* allocate *id? nah */ 127 (*id)->ops = t->ops; 128 k5_mutex_unlock(&rc_typelist_lock); 129 return k5_mutex_init(&(*id)->lock); 130 } 131 132 /*ARGSUSED*/ 133 char * krb5_rc_get_type(krb5_context context, krb5_rcache id) 134 { 135 return id->ops->type; 136 } 137 138 char * krb5_rc_default_type(krb5_context context) 139 { 140 /* 141 * Solaris Kerberos/SUNW14resync 142 * MIT's is "dfl" but we now have FILE and MEMORY instead. 143 * And we only support the KRB5RCNAME env var. 144 */ 145 return ("FILE"); 146 } 147 148 /*ARGSUSED*/ 149 char * krb5_rc_default_name(krb5_context context) 150 { 151 char *s; 152 if ((s = getenv("KRB5RCNAME"))) 153 return s; 154 else 155 return (char *) 0; 156 } 157 158 krb5_error_code 159 krb5_rc_default(krb5_context context, krb5_rcache *id) 160 { 161 krb5_error_code retval; 162 163 if (!(*id = (krb5_rcache )malloc(sizeof(**id)))) 164 return KRB5_RC_MALLOC; 165 166 retval = krb5_rc_resolve_type(context, id, krb5_rc_default_type(context)); 167 if (retval != 0) { 168 /* 169 * k5_mutex_destroy() is not called here, because the mutex had 170 * not been successfully initialized by krb5_rc_resolve_type(). 171 */ 172 FREE_RC(*id); 173 return (retval); 174 } 175 retval = krb5_rc_resolve(context, *id, krb5_rc_default_name(context)); 176 if (retval) { 177 k5_mutex_destroy(&(*id)->lock); 178 FREE_RC(*id); 179 return retval; 180 } 181 (*id)->magic = KV5M_RCACHE; 182 return retval; 183 } 184 185 krb5_error_code krb5_rc_resolve_full(krb5_context context, krb5_rcache *id, char *string_name) 186 { 187 char *type; 188 char *residual; 189 krb5_error_code retval; 190 unsigned int diff; 191 192 if (!(residual = strchr(string_name,':'))) 193 return KRB5_RC_PARSE; 194 195 diff = residual - string_name; 196 if (!(type = malloc(diff + 1))) 197 return KRB5_RC_MALLOC; 198 (void) strncpy(type, string_name, diff); 199 type[residual - string_name] = '\0'; 200 201 if (!(*id = (krb5_rcache) malloc(sizeof(**id)))) { 202 FREE_RC(type); 203 return KRB5_RC_MALLOC; 204 } 205 206 retval = krb5_rc_resolve_type(context, id, type); 207 if (retval != 0) { 208 /* 209 * k5_mutex_destroy() is not called here, because the mutex had 210 * not been successfully initialized by krb5_rc_resolve_type(). 211 */ 212 FREE_RC(type); 213 FREE_RC(*id); 214 return retval; 215 } 216 FREE_RC(type); 217 retval = krb5_rc_resolve(context, *id, residual + 1); 218 if (retval) { 219 k5_mutex_destroy(&(*id)->lock); 220 FREE_RC(*id); 221 return retval; 222 } 223 (*id)->magic = KV5M_RCACHE; 224 return retval; 225 } 226