1 /* 2 * Copyright 2005 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 k5_mutex_destroy(&(*id)->lock); 142 FREE_RC(*id); 143 return (retval); 144 } 145 retval = krb5_rc_resolve(context, *id, krb5_rc_default_name(context)); 146 if (retval) { 147 k5_mutex_destroy(&(*id)->lock); 148 FREE_RC(*id); 149 return retval; 150 } 151 (*id)->magic = KV5M_RCACHE; 152 return retval; 153 } 154 155 krb5_error_code krb5_rc_resolve_full(krb5_context context, krb5_rcache *id, char *string_name) 156 { 157 char *type; 158 char *residual; 159 krb5_error_code retval; 160 unsigned int diff; 161 162 if (!(residual = strchr(string_name,':'))) 163 return KRB5_RC_PARSE; 164 165 diff = residual - string_name; 166 if (!(type = malloc(diff + 1))) 167 return KRB5_RC_MALLOC; 168 (void) strncpy(type, string_name, diff); 169 type[residual - string_name] = '\0'; 170 171 if (!(*id = (krb5_rcache) malloc(sizeof(**id)))) { 172 FREE_RC(type); 173 return KRB5_RC_MALLOC; 174 } 175 176 if ((retval = krb5_rc_resolve_type(context, id,type))) { 177 FREE_RC(type); 178 k5_mutex_destroy(&(*id)->lock); 179 FREE_RC(*id); 180 return retval; 181 } 182 FREE_RC(type); 183 retval = krb5_rc_resolve(context, *id, residual + 1); 184 if (retval) { 185 k5_mutex_destroy(&(*id)->lock); 186 FREE_RC(*id); 187 return retval; 188 } 189 (*id)->magic = KV5M_RCACHE; 190 return retval; 191 } 192