xref: /freebsd/crypto/heimdal/lib/krb5/replay.c (revision 5e9cd1ae3e10592ed70e7575551cba1bbab04d84)
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