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