155682Smarkm/* 272445Sassar * Copyright (c) 1997-2001 Kungliga Tekniska H�gskolan 355682Smarkm * (Royal Institute of Technology, Stockholm, Sweden). 455682Smarkm * All rights reserved. 555682Smarkm * 655682Smarkm * Redistribution and use in source and binary forms, with or without 755682Smarkm * modification, are permitted provided that the following conditions 855682Smarkm * are met: 955682Smarkm * 1055682Smarkm * 1. Redistributions of source code must retain the above copyright 1155682Smarkm * notice, this list of conditions and the following disclaimer. 1255682Smarkm * 1355682Smarkm * 2. Redistributions in binary form must reproduce the above copyright 1455682Smarkm * notice, this list of conditions and the following disclaimer in the 1555682Smarkm * documentation and/or other materials provided with the distribution. 1655682Smarkm * 1755682Smarkm * 3. Neither the name of the Institute nor the names of its contributors 1855682Smarkm * may be used to endorse or promote products derived from this software 1955682Smarkm * without specific prior written permission. 2055682Smarkm * 2155682Smarkm * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 2255682Smarkm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2355682Smarkm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2455682Smarkm * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 2555682Smarkm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2655682Smarkm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2755682Smarkm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2855682Smarkm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2955682Smarkm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3055682Smarkm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3155682Smarkm * SUCH DAMAGE. 3255682Smarkm */ 3355682Smarkm 3455682Smarkm#include "krb5_locl.h" 3572445Sassar#include <vis.h> 3655682Smarkm 37178825SdfrRCSID("$Id: replay.c 17047 2006-04-10 17:13:49Z lha $"); 3872445Sassar 3955682Smarkmstruct krb5_rcache_data { 4055682Smarkm char *name; 4155682Smarkm}; 4255682Smarkm 43178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION 4455682Smarkmkrb5_rc_resolve(krb5_context context, 4555682Smarkm krb5_rcache id, 4655682Smarkm const char *name) 4755682Smarkm{ 4855682Smarkm id->name = strdup(name); 4978527Sassar if(id->name == NULL) { 5078527Sassar krb5_set_error_string (context, "malloc: out of memory"); 5155682Smarkm return KRB5_RC_MALLOC; 5278527Sassar } 5355682Smarkm return 0; 5455682Smarkm} 5555682Smarkm 56178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION 5755682Smarkmkrb5_rc_resolve_type(krb5_context context, 5855682Smarkm krb5_rcache *id, 5955682Smarkm const char *type) 6055682Smarkm{ 61178825Sdfr *id = NULL; 6278527Sassar if(strcmp(type, "FILE")) { 6378527Sassar krb5_set_error_string (context, "replay cache type %s not supported", 6478527Sassar type); 6555682Smarkm return KRB5_RC_TYPE_NOTFOUND; 6678527Sassar } 6755682Smarkm *id = calloc(1, sizeof(**id)); 6878527Sassar if(*id == NULL) { 6978527Sassar krb5_set_error_string (context, "malloc: out of memory"); 7055682Smarkm return KRB5_RC_MALLOC; 7178527Sassar } 7255682Smarkm return 0; 7355682Smarkm} 7455682Smarkm 75178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION 7655682Smarkmkrb5_rc_resolve_full(krb5_context context, 7755682Smarkm krb5_rcache *id, 7855682Smarkm const char *string_name) 7955682Smarkm{ 8055682Smarkm krb5_error_code ret; 81178825Sdfr 82178825Sdfr *id = NULL; 83178825Sdfr 8478527Sassar if(strncmp(string_name, "FILE:", 5)) { 8578527Sassar krb5_set_error_string (context, "replay cache type %s not supported", 8678527Sassar string_name); 8755682Smarkm return KRB5_RC_TYPE_NOTFOUND; 8878527Sassar } 8955682Smarkm ret = krb5_rc_resolve_type(context, id, "FILE"); 9055682Smarkm if(ret) 9155682Smarkm return ret; 9255682Smarkm ret = krb5_rc_resolve(context, *id, string_name + 5); 93178825Sdfr if (ret) { 94178825Sdfr krb5_rc_close(context, *id); 95178825Sdfr *id = NULL; 96178825Sdfr } 9755682Smarkm return ret; 9855682Smarkm} 9955682Smarkm 100178825Sdfrconst char* KRB5_LIB_FUNCTION 10155682Smarkmkrb5_rc_default_name(krb5_context context) 10255682Smarkm{ 10355682Smarkm return "FILE:/var/run/default_rcache"; 10455682Smarkm} 10555682Smarkm 106178825Sdfrconst char* KRB5_LIB_FUNCTION 10772445Sassarkrb5_rc_default_type(krb5_context context) 10872445Sassar{ 10972445Sassar return "FILE"; 11072445Sassar} 11172445Sassar 112178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION 11355682Smarkmkrb5_rc_default(krb5_context context, 11455682Smarkm krb5_rcache *id) 11555682Smarkm{ 11655682Smarkm return krb5_rc_resolve_full(context, id, krb5_rc_default_name(context)); 11755682Smarkm} 11855682Smarkm 11955682Smarkmstruct rc_entry{ 12055682Smarkm time_t stamp; 12155682Smarkm unsigned char data[16]; 12255682Smarkm}; 12355682Smarkm 124178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION 12555682Smarkmkrb5_rc_initialize(krb5_context context, 12655682Smarkm krb5_rcache id, 12755682Smarkm krb5_deltat auth_lifespan) 12855682Smarkm{ 12955682Smarkm FILE *f = fopen(id->name, "w"); 13055682Smarkm struct rc_entry tmp; 13178527Sassar int ret; 13278527Sassar 13378527Sassar if(f == NULL) { 13478527Sassar ret = errno; 13578527Sassar krb5_set_error_string (context, "open(%s): %s", id->name, 13678527Sassar strerror(ret)); 13778527Sassar return ret; 13878527Sassar } 13955682Smarkm tmp.stamp = auth_lifespan; 14055682Smarkm fwrite(&tmp, 1, sizeof(tmp), f); 14155682Smarkm fclose(f); 14255682Smarkm return 0; 14355682Smarkm} 14455682Smarkm 145178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION 14655682Smarkmkrb5_rc_recover(krb5_context context, 14755682Smarkm krb5_rcache id) 14855682Smarkm{ 14955682Smarkm return 0; 15055682Smarkm} 15155682Smarkm 152178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION 15355682Smarkmkrb5_rc_destroy(krb5_context context, 15455682Smarkm krb5_rcache id) 15555682Smarkm{ 15678527Sassar int ret; 15778527Sassar 15878527Sassar if(remove(id->name) < 0) { 15978527Sassar ret = errno; 16078527Sassar krb5_set_error_string (context, "remove(%s): %s", id->name, 16178527Sassar strerror(ret)); 16278527Sassar return ret; 16378527Sassar } 16455682Smarkm return krb5_rc_close(context, id); 16555682Smarkm} 16655682Smarkm 167178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION 16855682Smarkmkrb5_rc_close(krb5_context context, 16955682Smarkm krb5_rcache id) 17055682Smarkm{ 17155682Smarkm free(id->name); 17255682Smarkm free(id); 17355682Smarkm return 0; 17455682Smarkm} 17555682Smarkm 17655682Smarkmstatic void 17755682Smarkmchecksum_authenticator(Authenticator *auth, void *data) 17855682Smarkm{ 17957416Smarkm MD5_CTX md5; 18055682Smarkm int i; 18157416Smarkm 18272445Sassar MD5_Init (&md5); 18372445Sassar MD5_Update (&md5, auth->crealm, strlen(auth->crealm)); 18455682Smarkm for(i = 0; i < auth->cname.name_string.len; i++) 18572445Sassar MD5_Update(&md5, auth->cname.name_string.val[i], 18672445Sassar strlen(auth->cname.name_string.val[i])); 18772445Sassar MD5_Update (&md5, &auth->ctime, sizeof(auth->ctime)); 18872445Sassar MD5_Update (&md5, &auth->cusec, sizeof(auth->cusec)); 18972445Sassar MD5_Final (data, &md5); 19055682Smarkm} 19155682Smarkm 192178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION 19355682Smarkmkrb5_rc_store(krb5_context context, 19455682Smarkm krb5_rcache id, 19572445Sassar krb5_donot_replay *rep) 19655682Smarkm{ 19755682Smarkm struct rc_entry ent, tmp; 19855682Smarkm time_t t; 19955682Smarkm FILE *f; 20078527Sassar int ret; 20178527Sassar 20255682Smarkm ent.stamp = time(NULL); 20355682Smarkm checksum_authenticator(rep, ent.data); 20455682Smarkm f = fopen(id->name, "r"); 20578527Sassar if(f == NULL) { 20678527Sassar ret = errno; 20778527Sassar krb5_set_error_string (context, "open(%s): %s", id->name, 20878527Sassar strerror(ret)); 20978527Sassar return ret; 21078527Sassar } 21155682Smarkm fread(&tmp, sizeof(ent), 1, f); 21255682Smarkm t = ent.stamp - tmp.stamp; 21355682Smarkm while(fread(&tmp, sizeof(ent), 1, f)){ 21455682Smarkm if(tmp.stamp < t) 21555682Smarkm continue; 21655682Smarkm if(memcmp(tmp.data, ent.data, sizeof(ent.data)) == 0){ 21755682Smarkm fclose(f); 21878527Sassar krb5_clear_error_string (context); 21955682Smarkm return KRB5_RC_REPLAY; 22055682Smarkm } 22155682Smarkm } 22255682Smarkm if(ferror(f)){ 22378527Sassar ret = errno; 22455682Smarkm fclose(f); 22578527Sassar krb5_set_error_string (context, "%s: %s", id->name, strerror(ret)); 22678527Sassar return ret; 22755682Smarkm } 22855682Smarkm fclose(f); 22955682Smarkm f = fopen(id->name, "a"); 23078527Sassar if(f == NULL) { 23178527Sassar krb5_set_error_string (context, "open(%s): %s", id->name, 23278527Sassar strerror(errno)); 23355682Smarkm return KRB5_RC_IO_UNKNOWN; 23478527Sassar } 23555682Smarkm fwrite(&ent, 1, sizeof(ent), f); 23655682Smarkm fclose(f); 23755682Smarkm return 0; 23855682Smarkm} 23955682Smarkm 240178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION 24155682Smarkmkrb5_rc_expunge(krb5_context context, 24255682Smarkm krb5_rcache id) 24355682Smarkm{ 24455682Smarkm return 0; 24555682Smarkm} 24655682Smarkm 247178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION 24855682Smarkmkrb5_rc_get_lifespan(krb5_context context, 24955682Smarkm krb5_rcache id, 25055682Smarkm krb5_deltat *auth_lifespan) 25155682Smarkm{ 25255682Smarkm FILE *f = fopen(id->name, "r"); 25355682Smarkm int r; 25455682Smarkm struct rc_entry ent; 25555682Smarkm r = fread(&ent, sizeof(ent), 1, f); 25655682Smarkm fclose(f); 25755682Smarkm if(r){ 25855682Smarkm *auth_lifespan = ent.stamp; 25955682Smarkm return 0; 26055682Smarkm } 26178527Sassar krb5_clear_error_string (context); 26255682Smarkm return KRB5_RC_IO_UNKNOWN; 26355682Smarkm} 26472445Sassar 265178825Sdfrconst char* KRB5_LIB_FUNCTION 26655682Smarkmkrb5_rc_get_name(krb5_context context, 26755682Smarkm krb5_rcache id) 26855682Smarkm{ 26955682Smarkm return id->name; 27055682Smarkm} 27155682Smarkm 272178825Sdfrconst char* KRB5_LIB_FUNCTION 27355682Smarkmkrb5_rc_get_type(krb5_context context, 27455682Smarkm krb5_rcache id) 27555682Smarkm{ 27655682Smarkm return "FILE"; 27755682Smarkm} 27855682Smarkm 279178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION 28072445Sassarkrb5_get_server_rcache(krb5_context context, 28172445Sassar const krb5_data *piece, 28272445Sassar krb5_rcache *id) 28372445Sassar{ 28472445Sassar krb5_rcache rcache; 28572445Sassar krb5_error_code ret; 28672445Sassar 28772445Sassar char *tmp = malloc(4 * piece->length + 1); 28872445Sassar char *name; 28978527Sassar 29078527Sassar if(tmp == NULL) { 29178527Sassar krb5_set_error_string (context, "malloc: out of memory"); 29272445Sassar return ENOMEM; 29378527Sassar } 29472445Sassar strvisx(tmp, piece->data, piece->length, VIS_WHITE | VIS_OCTAL); 29572445Sassar#ifdef HAVE_GETEUID 29690926Snectar asprintf(&name, "FILE:rc_%s_%u", tmp, (unsigned)geteuid()); 29772445Sassar#else 29872445Sassar asprintf(&name, "FILE:rc_%s", tmp); 29972445Sassar#endif 30072445Sassar free(tmp); 30178527Sassar if(name == NULL) { 30278527Sassar krb5_set_error_string (context, "malloc: out of memory"); 30372445Sassar return ENOMEM; 30478527Sassar } 30572445Sassar 30672445Sassar ret = krb5_rc_resolve_full(context, &rcache, name); 30772445Sassar free(name); 30872445Sassar if(ret) 30972445Sassar return ret; 31072445Sassar *id = rcache; 31172445Sassar return ret; 31272445Sassar} 313