155682Smarkm/* 2233294Sstas * Copyright (c) 1997-2001 Kungliga Tekniska H��gskolan 3233294Sstas * (Royal Institute of Technology, Stockholm, Sweden). 4233294Sstas * All rights reserved. 555682Smarkm * 6233294Sstas * Redistribution and use in source and binary forms, with or without 7233294Sstas * modification, are permitted provided that the following conditions 8233294Sstas * are met: 955682Smarkm * 10233294Sstas * 1. Redistributions of source code must retain the above copyright 11233294Sstas * notice, this list of conditions and the following disclaimer. 1255682Smarkm * 13233294Sstas * 2. Redistributions in binary form must reproduce the above copyright 14233294Sstas * notice, this list of conditions and the following disclaimer in the 15233294Sstas * documentation and/or other materials provided with the distribution. 1655682Smarkm * 17233294Sstas * 3. Neither the name of the Institute nor the names of its contributors 18233294Sstas * may be used to endorse or promote products derived from this software 19233294Sstas * without specific prior written permission. 2055682Smarkm * 21233294Sstas * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 22233294Sstas * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23233294Sstas * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24233294Sstas * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 25233294Sstas * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26233294Sstas * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27233294Sstas * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28233294Sstas * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29233294Sstas * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30233294Sstas * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31233294Sstas * SUCH DAMAGE. 3255682Smarkm */ 3355682Smarkm 3455682Smarkm#include "krb5_locl.h" 3572445Sassar#include <vis.h> 3655682Smarkm 3755682Smarkmstruct krb5_rcache_data { 3855682Smarkm char *name; 3955682Smarkm}; 4055682Smarkm 41233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 4255682Smarkmkrb5_rc_resolve(krb5_context context, 4355682Smarkm krb5_rcache id, 4455682Smarkm const char *name) 4555682Smarkm{ 4655682Smarkm id->name = strdup(name); 4778527Sassar if(id->name == NULL) { 48233294Sstas krb5_set_error_message(context, KRB5_RC_MALLOC, 49233294Sstas N_("malloc: out of memory", "")); 5055682Smarkm return KRB5_RC_MALLOC; 5178527Sassar } 5255682Smarkm return 0; 5355682Smarkm} 5455682Smarkm 55233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 5655682Smarkmkrb5_rc_resolve_type(krb5_context context, 5755682Smarkm krb5_rcache *id, 5855682Smarkm const char *type) 5955682Smarkm{ 60178825Sdfr *id = NULL; 6178527Sassar if(strcmp(type, "FILE")) { 62233294Sstas krb5_set_error_message (context, KRB5_RC_TYPE_NOTFOUND, 63233294Sstas N_("replay cache type %s not supported", ""), 64233294Sstas type); 6555682Smarkm return KRB5_RC_TYPE_NOTFOUND; 6678527Sassar } 6755682Smarkm *id = calloc(1, sizeof(**id)); 6878527Sassar if(*id == NULL) { 69233294Sstas krb5_set_error_message(context, KRB5_RC_MALLOC, 70233294Sstas N_("malloc: out of memory", "")); 7155682Smarkm return KRB5_RC_MALLOC; 7278527Sassar } 7355682Smarkm return 0; 7455682Smarkm} 7555682Smarkm 76233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 7755682Smarkmkrb5_rc_resolve_full(krb5_context context, 7855682Smarkm krb5_rcache *id, 7955682Smarkm const char *string_name) 8055682Smarkm{ 8155682Smarkm krb5_error_code ret; 82178825Sdfr 83178825Sdfr *id = NULL; 84178825Sdfr 8578527Sassar if(strncmp(string_name, "FILE:", 5)) { 86233294Sstas krb5_set_error_message(context, KRB5_RC_TYPE_NOTFOUND, 87233294Sstas N_("replay cache type %s not supported", ""), 8878527Sassar string_name); 8955682Smarkm return KRB5_RC_TYPE_NOTFOUND; 9078527Sassar } 9155682Smarkm ret = krb5_rc_resolve_type(context, id, "FILE"); 9255682Smarkm if(ret) 9355682Smarkm return ret; 9455682Smarkm ret = krb5_rc_resolve(context, *id, string_name + 5); 95178825Sdfr if (ret) { 96178825Sdfr krb5_rc_close(context, *id); 97178825Sdfr *id = NULL; 98178825Sdfr } 9955682Smarkm return ret; 10055682Smarkm} 10155682Smarkm 102233294SstasKRB5_LIB_FUNCTION const char* KRB5_LIB_CALL 10355682Smarkmkrb5_rc_default_name(krb5_context context) 10455682Smarkm{ 10555682Smarkm return "FILE:/var/run/default_rcache"; 10655682Smarkm} 10755682Smarkm 108233294SstasKRB5_LIB_FUNCTION const char* KRB5_LIB_CALL 10972445Sassarkrb5_rc_default_type(krb5_context context) 11072445Sassar{ 11172445Sassar return "FILE"; 11272445Sassar} 11372445Sassar 114233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 11555682Smarkmkrb5_rc_default(krb5_context context, 11655682Smarkm krb5_rcache *id) 11755682Smarkm{ 11855682Smarkm return krb5_rc_resolve_full(context, id, krb5_rc_default_name(context)); 11955682Smarkm} 12055682Smarkm 12155682Smarkmstruct rc_entry{ 12255682Smarkm time_t stamp; 12355682Smarkm unsigned char data[16]; 12455682Smarkm}; 12555682Smarkm 126233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 12755682Smarkmkrb5_rc_initialize(krb5_context context, 12855682Smarkm krb5_rcache id, 12955682Smarkm krb5_deltat auth_lifespan) 13055682Smarkm{ 13155682Smarkm FILE *f = fopen(id->name, "w"); 13255682Smarkm struct rc_entry tmp; 13378527Sassar int ret; 13478527Sassar 13578527Sassar if(f == NULL) { 136233294Sstas char buf[128]; 13778527Sassar ret = errno; 138233294Sstas rk_strerror_r(ret, buf, sizeof(buf)); 139233294Sstas krb5_set_error_message(context, ret, "open(%s): %s", id->name, buf); 14078527Sassar return ret; 14178527Sassar } 14255682Smarkm tmp.stamp = auth_lifespan; 14355682Smarkm fwrite(&tmp, 1, sizeof(tmp), f); 14455682Smarkm fclose(f); 14555682Smarkm return 0; 14655682Smarkm} 14755682Smarkm 148233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 14955682Smarkmkrb5_rc_recover(krb5_context context, 15055682Smarkm krb5_rcache id) 15155682Smarkm{ 15255682Smarkm return 0; 15355682Smarkm} 15455682Smarkm 155233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 15655682Smarkmkrb5_rc_destroy(krb5_context context, 15755682Smarkm krb5_rcache id) 15855682Smarkm{ 15978527Sassar int ret; 16078527Sassar 16178527Sassar if(remove(id->name) < 0) { 162233294Sstas char buf[128]; 16378527Sassar ret = errno; 164233294Sstas rk_strerror_r(ret, buf, sizeof(buf)); 165233294Sstas krb5_set_error_message(context, ret, "remove(%s): %s", id->name, buf); 16678527Sassar return ret; 16778527Sassar } 16855682Smarkm return krb5_rc_close(context, id); 16955682Smarkm} 17055682Smarkm 171233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 17255682Smarkmkrb5_rc_close(krb5_context context, 17355682Smarkm krb5_rcache id) 17455682Smarkm{ 17555682Smarkm free(id->name); 17655682Smarkm free(id); 17755682Smarkm return 0; 17855682Smarkm} 17955682Smarkm 18055682Smarkmstatic void 18155682Smarkmchecksum_authenticator(Authenticator *auth, void *data) 18255682Smarkm{ 183233294Sstas EVP_MD_CTX *m = EVP_MD_CTX_create(); 184233294Sstas unsigned i; 18557416Smarkm 186233294Sstas EVP_DigestInit_ex(m, EVP_md5(), NULL); 187233294Sstas 188233294Sstas EVP_DigestUpdate(m, auth->crealm, strlen(auth->crealm)); 18955682Smarkm for(i = 0; i < auth->cname.name_string.len; i++) 190233294Sstas EVP_DigestUpdate(m, auth->cname.name_string.val[i], 19172445Sassar strlen(auth->cname.name_string.val[i])); 192233294Sstas EVP_DigestUpdate(m, &auth->ctime, sizeof(auth->ctime)); 193233294Sstas EVP_DigestUpdate(m, &auth->cusec, sizeof(auth->cusec)); 194233294Sstas 195233294Sstas EVP_DigestFinal_ex(m, data, NULL); 196233294Sstas EVP_MD_CTX_destroy(m); 19755682Smarkm} 19855682Smarkm 199233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 20055682Smarkmkrb5_rc_store(krb5_context context, 20155682Smarkm krb5_rcache id, 20272445Sassar krb5_donot_replay *rep) 20355682Smarkm{ 20455682Smarkm struct rc_entry ent, tmp; 20555682Smarkm time_t t; 20655682Smarkm FILE *f; 20778527Sassar int ret; 20878527Sassar 20955682Smarkm ent.stamp = time(NULL); 21055682Smarkm checksum_authenticator(rep, ent.data); 21155682Smarkm f = fopen(id->name, "r"); 21278527Sassar if(f == NULL) { 213233294Sstas char buf[128]; 21478527Sassar ret = errno; 215233294Sstas rk_strerror_r(ret, buf, sizeof(buf)); 216233294Sstas krb5_set_error_message(context, ret, "open(%s): %s", id->name, buf); 21778527Sassar return ret; 21878527Sassar } 219233294Sstas rk_cloexec_file(f); 22055682Smarkm fread(&tmp, sizeof(ent), 1, f); 22155682Smarkm t = ent.stamp - tmp.stamp; 22255682Smarkm while(fread(&tmp, sizeof(ent), 1, f)){ 22355682Smarkm if(tmp.stamp < t) 22455682Smarkm continue; 22555682Smarkm if(memcmp(tmp.data, ent.data, sizeof(ent.data)) == 0){ 22655682Smarkm fclose(f); 227233294Sstas krb5_clear_error_message (context); 22855682Smarkm return KRB5_RC_REPLAY; 22955682Smarkm } 23055682Smarkm } 23155682Smarkm if(ferror(f)){ 232233294Sstas char buf[128]; 23378527Sassar ret = errno; 23455682Smarkm fclose(f); 235233294Sstas rk_strerror_r(ret, buf, sizeof(buf)); 236233294Sstas krb5_set_error_message(context, ret, "%s: %s", 237233294Sstas id->name, buf); 23878527Sassar return ret; 23955682Smarkm } 24055682Smarkm fclose(f); 24155682Smarkm f = fopen(id->name, "a"); 24278527Sassar if(f == NULL) { 243233294Sstas char buf[128]; 244233294Sstas rk_strerror_r(errno, buf, sizeof(buf)); 245233294Sstas krb5_set_error_message(context, KRB5_RC_IO_UNKNOWN, 246233294Sstas "open(%s): %s", id->name, buf); 24755682Smarkm return KRB5_RC_IO_UNKNOWN; 24878527Sassar } 24955682Smarkm fwrite(&ent, 1, sizeof(ent), f); 25055682Smarkm fclose(f); 25155682Smarkm return 0; 25255682Smarkm} 25355682Smarkm 254233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 25555682Smarkmkrb5_rc_expunge(krb5_context context, 25655682Smarkm krb5_rcache id) 25755682Smarkm{ 25855682Smarkm return 0; 25955682Smarkm} 26055682Smarkm 261233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 26255682Smarkmkrb5_rc_get_lifespan(krb5_context context, 26355682Smarkm krb5_rcache id, 26455682Smarkm krb5_deltat *auth_lifespan) 26555682Smarkm{ 26655682Smarkm FILE *f = fopen(id->name, "r"); 26755682Smarkm int r; 26855682Smarkm struct rc_entry ent; 26955682Smarkm r = fread(&ent, sizeof(ent), 1, f); 27055682Smarkm fclose(f); 27155682Smarkm if(r){ 27255682Smarkm *auth_lifespan = ent.stamp; 27355682Smarkm return 0; 27455682Smarkm } 275233294Sstas krb5_clear_error_message (context); 27655682Smarkm return KRB5_RC_IO_UNKNOWN; 27755682Smarkm} 27872445Sassar 279233294SstasKRB5_LIB_FUNCTION const char* KRB5_LIB_CALL 28055682Smarkmkrb5_rc_get_name(krb5_context context, 28155682Smarkm krb5_rcache id) 28255682Smarkm{ 28355682Smarkm return id->name; 28455682Smarkm} 285233294Sstas 286233294SstasKRB5_LIB_FUNCTION const char* KRB5_LIB_CALL 28755682Smarkmkrb5_rc_get_type(krb5_context context, 28855682Smarkm krb5_rcache id) 28955682Smarkm{ 29055682Smarkm return "FILE"; 29155682Smarkm} 292233294Sstas 293233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 294233294Sstaskrb5_get_server_rcache(krb5_context context, 295233294Sstas const krb5_data *piece, 29672445Sassar krb5_rcache *id) 29772445Sassar{ 29872445Sassar krb5_rcache rcache; 29972445Sassar krb5_error_code ret; 30072445Sassar 30172445Sassar char *tmp = malloc(4 * piece->length + 1); 30272445Sassar char *name; 30378527Sassar 30478527Sassar if(tmp == NULL) { 305233294Sstas krb5_set_error_message(context, ENOMEM, 306233294Sstas N_("malloc: out of memory", "")); 30772445Sassar return ENOMEM; 30878527Sassar } 30972445Sassar strvisx(tmp, piece->data, piece->length, VIS_WHITE | VIS_OCTAL); 31072445Sassar#ifdef HAVE_GETEUID 311233294Sstas ret = asprintf(&name, "FILE:rc_%s_%u", tmp, (unsigned)geteuid()); 31272445Sassar#else 313233294Sstas ret = asprintf(&name, "FILE:rc_%s", tmp); 31472445Sassar#endif 31572445Sassar free(tmp); 316233294Sstas if(ret < 0 || name == NULL) { 317233294Sstas krb5_set_error_message(context, ENOMEM, 318233294Sstas N_("malloc: out of memory", "")); 31972445Sassar return ENOMEM; 32078527Sassar } 32172445Sassar 32272445Sassar ret = krb5_rc_resolve_full(context, &rcache, name); 32372445Sassar free(name); 32472445Sassar if(ret) 32572445Sassar return ret; 32672445Sassar *id = rcache; 32772445Sassar return ret; 32872445Sassar} 329