1 /* 2 * Copyright (c) 1997-2001 Kungliga Tekniska H�gskolan 3 * (Royal Institute of Technology, Stockholm, Sweden). 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * 3. Neither the name of the Institute nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34 #include "krb5_locl.h" 35 #include <vis.h> 36 37 RCSID("$Id: replay.c,v 1.7 2001/01/29 02:09:00 assar Exp $"); 38 39 struct krb5_rcache_data { 40 char *name; 41 }; 42 43 krb5_error_code 44 krb5_rc_resolve(krb5_context context, 45 krb5_rcache id, 46 const char *name) 47 { 48 id->name = strdup(name); 49 if(id->name == NULL) 50 return KRB5_RC_MALLOC; 51 return 0; 52 } 53 54 krb5_error_code 55 krb5_rc_resolve_type(krb5_context context, 56 krb5_rcache *id, 57 const char *type) 58 { 59 if(strcmp(type, "FILE")) 60 return KRB5_RC_TYPE_NOTFOUND; 61 *id = calloc(1, sizeof(**id)); 62 if(*id == NULL) 63 return KRB5_RC_MALLOC; 64 return 0; 65 } 66 67 krb5_error_code 68 krb5_rc_resolve_full(krb5_context context, 69 krb5_rcache *id, 70 const char *string_name) 71 { 72 krb5_error_code ret; 73 if(strncmp(string_name, "FILE:", 5)) 74 return KRB5_RC_TYPE_NOTFOUND; 75 ret = krb5_rc_resolve_type(context, id, "FILE"); 76 if(ret) 77 return ret; 78 ret = krb5_rc_resolve(context, *id, string_name + 5); 79 return ret; 80 } 81 82 const char * 83 krb5_rc_default_name(krb5_context context) 84 { 85 return "FILE:/var/run/default_rcache"; 86 } 87 88 const char * 89 krb5_rc_default_type(krb5_context context) 90 { 91 return "FILE"; 92 } 93 94 krb5_error_code 95 krb5_rc_default(krb5_context context, 96 krb5_rcache *id) 97 { 98 return krb5_rc_resolve_full(context, id, krb5_rc_default_name(context)); 99 } 100 101 struct rc_entry{ 102 time_t stamp; 103 unsigned char data[16]; 104 }; 105 106 krb5_error_code 107 krb5_rc_initialize(krb5_context context, 108 krb5_rcache id, 109 krb5_deltat auth_lifespan) 110 { 111 FILE *f = fopen(id->name, "w"); 112 struct rc_entry tmp; 113 if(f == NULL) 114 return errno; 115 tmp.stamp = auth_lifespan; 116 fwrite(&tmp, 1, sizeof(tmp), f); 117 fclose(f); 118 return 0; 119 } 120 121 krb5_error_code 122 krb5_rc_recover(krb5_context context, 123 krb5_rcache id) 124 { 125 return 0; 126 } 127 128 krb5_error_code 129 krb5_rc_destroy(krb5_context context, 130 krb5_rcache id) 131 { 132 if(remove(id->name) < 0) 133 return errno; 134 return krb5_rc_close(context, id); 135 } 136 137 krb5_error_code 138 krb5_rc_close(krb5_context context, 139 krb5_rcache id) 140 { 141 free(id->name); 142 free(id); 143 return 0; 144 } 145 146 static void 147 checksum_authenticator(Authenticator *auth, void *data) 148 { 149 MD5_CTX md5; 150 int i; 151 152 MD5_Init (&md5); 153 MD5_Update (&md5, auth->crealm, strlen(auth->crealm)); 154 for(i = 0; i < auth->cname.name_string.len; i++) 155 MD5_Update(&md5, auth->cname.name_string.val[i], 156 strlen(auth->cname.name_string.val[i])); 157 MD5_Update (&md5, &auth->ctime, sizeof(auth->ctime)); 158 MD5_Update (&md5, &auth->cusec, sizeof(auth->cusec)); 159 MD5_Final (data, &md5); 160 } 161 162 krb5_error_code 163 krb5_rc_store(krb5_context context, 164 krb5_rcache id, 165 krb5_donot_replay *rep) 166 { 167 struct rc_entry ent, tmp; 168 time_t t; 169 FILE *f; 170 ent.stamp = time(NULL); 171 checksum_authenticator(rep, ent.data); 172 f = fopen(id->name, "r"); 173 if(f == NULL) 174 return errno; 175 fread(&tmp, sizeof(ent), 1, f); 176 t = ent.stamp - tmp.stamp; 177 while(fread(&tmp, sizeof(ent), 1, f)){ 178 if(tmp.stamp < t) 179 continue; 180 if(memcmp(tmp.data, ent.data, sizeof(ent.data)) == 0){ 181 fclose(f); 182 return KRB5_RC_REPLAY; 183 } 184 } 185 if(ferror(f)){ 186 fclose(f); 187 return errno; 188 } 189 fclose(f); 190 f = fopen(id->name, "a"); 191 if(f == NULL) 192 return KRB5_RC_IO_UNKNOWN; 193 fwrite(&ent, 1, sizeof(ent), f); 194 fclose(f); 195 return 0; 196 } 197 198 krb5_error_code 199 krb5_rc_expunge(krb5_context context, 200 krb5_rcache id) 201 { 202 return 0; 203 } 204 205 krb5_error_code 206 krb5_rc_get_lifespan(krb5_context context, 207 krb5_rcache id, 208 krb5_deltat *auth_lifespan) 209 { 210 FILE *f = fopen(id->name, "r"); 211 int r; 212 struct rc_entry ent; 213 r = fread(&ent, sizeof(ent), 1, f); 214 fclose(f); 215 if(r){ 216 *auth_lifespan = ent.stamp; 217 return 0; 218 } 219 return KRB5_RC_IO_UNKNOWN; 220 } 221 222 const char* 223 krb5_rc_get_name(krb5_context context, 224 krb5_rcache id) 225 { 226 return id->name; 227 } 228 229 const char* 230 krb5_rc_get_type(krb5_context context, 231 krb5_rcache id) 232 { 233 return "FILE"; 234 } 235 236 krb5_error_code 237 krb5_get_server_rcache(krb5_context context, 238 const krb5_data *piece, 239 krb5_rcache *id) 240 { 241 krb5_rcache rcache; 242 krb5_error_code ret; 243 244 char *tmp = malloc(4 * piece->length + 1); 245 char *name; 246 if(tmp == NULL) 247 return ENOMEM; 248 strvisx(tmp, piece->data, piece->length, VIS_WHITE | VIS_OCTAL); 249 #ifdef HAVE_GETEUID 250 asprintf(&name, "FILE:rc_%s_%u", tmp, geteuid()); 251 #else 252 asprintf(&name, "FILE:rc_%s", tmp); 253 #endif 254 free(tmp); 255 if(name == NULL) 256 return ENOMEM; 257 258 ret = krb5_rc_resolve_full(context, &rcache, name); 259 free(name); 260 if(ret) 261 return ret; 262 *id = rcache; 263 return ret; 264 } 265