Change __signed to signed.
[dragonfly.git] / crypto / kerberosIV / lib / krb / ticket_memory.c
1 /*
2  * Copyright (c) 1995, 1996, 1997, 1998 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 /* ticket_memory.c - Storage for tickets in memory
35  * Author: d93-jka@nada.kth.se - June 1996
36  */
37
38 #define WIN32_LEAN_AND_MEAN
39 #include <Windows.h>
40 #include "krb_locl.h"
41 #include "ticket_memory.h"
42
43 RCSID("$Id: ticket_memory.c,v 1.15 1999/12/02 16:58:44 joda Exp $");
44
45 void msg(char *text, int error);
46
47 /* Global variables for memory mapping. */
48 HANDLE  SharedMemoryHandle;
49 tktmem  *SharedMemory;
50
51 static int CredIndex = -1;
52
53 void PostUpdateMessage(void);
54
55 int
56 newTktMem(const char *tf_name)
57 {
58     if(!SharedMemory){
59         SharedMemoryHandle = CreateFileMapping((HANDLE)-1, 0,
60                                                PAGE_READWRITE,
61                                                sizeof(tktmem) >> 16,
62                                                sizeof(tktmem) & 0xffff,
63                                                "krb_memory");
64         
65         if(!SharedMemoryHandle){
66             msg("Could not create shared memory.", GetLastError());
67             return KFAILURE;
68         }
69                 
70         SharedMemory = MapViewOfFile(SharedMemoryHandle,
71                                      FILE_MAP_WRITE, 0, 0, 0);
72         if(!SharedMemory){
73             msg("Unable to alloc shared memory.", GetLastError());
74             return KFAILURE;
75         }
76         if(GetLastError() != ERROR_ALREADY_EXISTS) {
77             memset(SharedMemory, 0, sizeof(*SharedMemory));
78             if(tf_name)
79                 strlcpy(SharedMemory->tmname,
80                                 tf_name, sizeof(SharedMemory->tmname));
81         }
82     }
83     CredIndex = 0;
84     return KSUCCESS;
85 }
86
87 int
88 freeTktMem(const char *tf_name)
89 {
90     if(SharedMemory) {
91         UnmapViewOfFile(SharedMemory);
92         CloseHandle(SharedMemoryHandle);
93     }
94     return KSUCCESS;
95 }
96
97
98
99 tktmem *
100 getTktMem(const char *tf_name)
101 {
102     return SharedMemory;
103 }
104
105 void
106 firstCred(void)
107 {
108     if(getTktMem(0)->last_cred_no > 0)
109         CredIndex = 0;
110     else
111         CredIndex = -1;
112 }
113         
114 int
115 nextCredIndex(void)
116 {
117     const tktmem *mem;
118     int last;
119     mem = getTktMem(0);
120     last = mem->last_cred_no;
121     if(CredIndex >= 0 && CredIndex < last )
122         return CredIndex++;
123     else
124         return CredIndex = -1;
125 }
126
127 int
128 currCredIndex(void)
129 {
130     const tktmem *mem;
131     int last;
132     mem = getTktMem(0);
133     last = mem->last_cred_no;
134     if(CredIndex >= 0 && CredIndex < last)
135         return CredIndex;
136     else
137         return CredIndex = -1;
138 }
139
140 int
141 nextFreeIndex(void)
142 {
143     tktmem *mem = getTktMem(0);
144     if(mem->last_cred_no > CRED_VEC_SZ)
145         return -1;
146     else
147         return mem->last_cred_no++;
148 }
149
150 /*
151  * in_tkt() is used to initialize the ticket store.  It creates the
152  * file to contain the tickets and writes the given user's name "pname"
153  * and instance "pinst" in the file.  in_tkt() returns KSUCCESS on
154  * success, or KFAILURE if something goes wrong.
155  */
156
157 int
158 in_tkt(char *pname, char *pinst)
159 {
160     /* Here goes code to initialize shared memory, to store tickets in. */
161     /* Implemented somewhere else. */
162     return KFAILURE;
163 }
164
165 /*
166  * dest_tkt() is used to destroy the ticket store upon logout.
167  * If the ticket file does not exist, dest_tkt() returns RET_TKFIL.
168  * Otherwise the function returns RET_OK on success, KFAILURE on
169  * failure.
170  *
171  * The ticket file (TKT_FILE) is defined in "krb.h".
172  */
173
174 int
175 dest_tkt(void)
176 {
177     memset(getTktMem(0), 0, sizeof(tktmem));
178     return 0;
179 }
180
181 /* Short description of routines:
182  *
183  * tf_init() opens the ticket file and locks it.
184  *
185  * tf_get_pname() returns the principal's name.
186  *
187  * tf_put_pname() writes the principal's name to the ticket file.
188  *
189  * tf_get_pinst() returns the principal's instance (may be null).
190  *
191  * tf_put_pinst() writes the instance.
192  *
193  * tf_get_cred() returns the next CREDENTIALS record.
194  *
195  * tf_save_cred() appends a new CREDENTIAL record to the ticket file.
196  *
197  * tf_close() closes the ticket file and releases the lock.
198  *
199  * tf_gets() returns the next null-terminated string.  It's an internal
200  * routine used by tf_get_pname(), tf_get_pinst(), and tf_get_cred().
201  *
202  * tf_read() reads a given number of bytes.  It's an internal routine
203  * used by tf_get_cred().
204  */
205
206 /*
207  * tf_init() should be called before the other ticket file routines.
208  * It takes the name of the ticket file to use, "tf_name", and a
209  * read/write flag "rw" as arguments. 
210  *
211  * Returns KSUCCESS if all went well, otherwise one of the following: 
212  *
213  * NO_TKT_FIL   - file wasn't there
214  * TKT_FIL_ACC  - file was in wrong mode, etc.
215  * TKT_FIL_LCK  - couldn't lock the file, even after a retry
216  */
217
218 int
219 tf_init(char *tf_name, int rw)
220 {
221     if(!getTktMem(tf_name))
222         return NO_TKT_FIL;
223     firstCred();
224     return KSUCCESS;
225 }
226
227 /*
228  * tf_create() should be called when creating a new ticket file.
229  * The only argument is the name of the ticket file.
230  * After calling this, it should be possible to use other tf_* functions.
231  */
232
233 int
234 tf_create(char *tf_name)
235 {
236     if(newTktMem(tf_name) != KSUCCESS)
237         return NO_TKT_FIL;
238     return KSUCCESS;
239 }
240
241 /*
242  * tf_get_pname() reads the principal's name from the ticket file. It
243  * should only be called after tf_init() has been called.  The
244  * principal's name is filled into the "p" parameter.  If all goes well,
245  * KSUCCESS is returned.  If tf_init() wasn't called, TKT_FIL_INI is
246  * returned.  If the name was null, or EOF was encountered, or the name
247  * was longer than ANAME_SZ, TKT_FIL_FMT is returned. 
248  */
249
250 int
251 tf_get_pname(char *p)
252 {
253     tktmem *TktStore;
254
255     if(!(TktStore =  getTktMem(0)))
256         return KFAILURE;
257     if(!TktStore->pname[0])
258         return KFAILURE;
259     strlcpy(p, TktStore->pname, ANAME_SZ);
260     return KSUCCESS;
261 }
262
263 /*
264  * tf_put_pname() sets the principal's name in the ticket file. Call
265  * after tf_create().
266  */
267
268 int
269 tf_put_pname(char *p)
270 {
271     tktmem *TktStore;
272
273     if(!(TktStore =  getTktMem(0)))
274         return KFAILURE;
275     strlcpy(TktStore->pname, p, sizeof(TktStore->pname));
276     return KSUCCESS;
277 }
278
279 /*
280  * tf_get_pinst() reads the principal's instance from a ticket file.
281  * It should only be called after tf_init() and tf_get_pname() have been
282  * called.  The instance is filled into the "inst" parameter.  If all
283  * goes well, KSUCCESS is returned.  If tf_init() wasn't called,
284  * TKT_FIL_INI is returned.  If EOF was encountered, or the instance
285  * was longer than ANAME_SZ, TKT_FIL_FMT is returned.  Note that the
286  * instance may be null. 
287  */
288
289 int
290 tf_get_pinst(char *inst)
291 {
292     tktmem *TktStore;
293
294     if(!(TktStore =  getTktMem(0)))
295         return KFAILURE;
296     strlcpy(inst, TktStore->pinst, INST_SZ);
297     return KSUCCESS;
298 }
299
300 /*
301  * tf_put_pinst writes the principal's instance to the ticket file.
302  * Call after tf_create.
303  */
304
305 int
306 tf_put_pinst(char *inst)
307 {
308     tktmem *TktStore;
309
310     if(!(TktStore =  getTktMem(0)))
311         return KFAILURE;
312     strlcpy(TktStore->pinst, inst, sizeof(TktStore->pinst));
313     return KSUCCESS;
314 }
315
316 /*
317  * tf_get_cred() reads a CREDENTIALS record from a ticket file and fills
318  * in the given structure "c".  It should only be called after tf_init(),
319  * tf_get_pname(), and tf_get_pinst() have been called. If all goes well,
320  * KSUCCESS is returned.  Possible error codes are: 
321  *
322  * TKT_FIL_INI  - tf_init wasn't called first
323  * TKT_FIL_FMT  - bad format
324  * EOF          - end of file encountered
325  */
326
327 int
328 tf_get_cred(CREDENTIALS *c)
329 {
330     int index;
331     CREDENTIALS *cred;
332     tktmem *TktStore;
333
334     if(!(TktStore =  getTktMem(0)))
335         return KFAILURE;
336     krb_set_kdc_time_diff(TktStore->kdc_diff);
337     if((index = nextCredIndex()) == -1)
338         return EOF;
339     if(!(cred = TktStore->cred_vec+index))
340         return KFAILURE;
341     if(!c)
342         return KFAILURE;
343     memcpy(c, cred, sizeof(*c));
344     return KSUCCESS;
345 }
346
347 /*
348  * tf_close() closes the ticket file and sets "fd" to -1. If "fd" is
349  * not a valid file descriptor, it just returns.  It also clears the
350  * buffer used to read tickets.
351  */
352
353 void
354 tf_close(void)
355 {
356 }
357
358 /*
359  * tf_save_cred() appends an incoming ticket to the end of the ticket
360  * file.  You must call tf_init() before calling tf_save_cred().
361  *
362  * The "service", "instance", and "realm" arguments specify the
363  * server's name; "session" contains the session key to be used with
364  * the ticket; "kvno" is the server key version number in which the
365  * ticket is encrypted, "ticket" contains the actual ticket, and
366  * "issue_date" is the time the ticket was requested (local host's time).
367  *
368  * Returns KSUCCESS if all goes well, TKT_FIL_INI if tf_init() wasn't
369  * called previously, and KFAILURE for anything else that went wrong.
370  */
371  
372 int
373 tf_save_cred(char *service,     /* Service name */
374              char *instance,    /* Instance */
375              char *realm,       /* Auth domain */
376              unsigned char *session, /* Session key */
377              int lifetime,      /* Lifetime */
378              int kvno,          /* Key version number */
379              KTEXT ticket,      /* The ticket itself */
380              u_int32_t issue_date) /* The issue time */
381 {
382     CREDENTIALS *cred;
383     tktmem *mem =  getTktMem(0);
384     int last = nextFreeIndex();
385
386     if(last == -1)
387         return KFAILURE;
388     cred = mem->cred_vec+last;
389     strlcpy(cred->service, service, sizeof(cred->service));
390     strlcpy(cred->instance, instance, sizeof(cred->instance));
391     strlcpy(cred->realm, realm, sizeof(cred->realm));
392     memcpy(cred->session, session, sizeof(cred->session));
393     cred->lifetime = lifetime;
394     cred->kvno = kvno;
395     memcpy(&(cred->ticket_st), ticket, sizeof(*ticket));
396     cred->issue_date = issue_date;
397     strlcpy(cred->pname, mem->pname, sizeof(cred->pname));
398     strlcpy(cred->pinst, mem->pinst, sizeof(cred->pinst));
399     PostUpdateMessage();
400     return KSUCCESS;
401 }
402
403
404 static void
405 set_time_diff(time_t diff)
406 {
407     tktmem *TktStore = getTktMem(0);
408     if(TktStore == NULL)
409         return;
410     TktStore->kdc_diff = diff;
411 }
412
413
414 int
415 tf_setup(CREDENTIALS *cred, char *pname, char *pinst)
416 {
417     int ret;
418     ret = tf_create(tkt_string());
419     if (ret != KSUCCESS)
420         return ret;
421
422     if (tf_put_pname(pname) != KSUCCESS ||
423         tf_put_pinst(pinst) != KSUCCESS) {
424         tf_close();
425         return INTK_ERR;
426     }
427
428     set_time_diff(krb_get_kdc_time_diff());
429
430     ret = tf_save_cred(cred->service, cred->instance, cred->realm, 
431                        cred->session, cred->lifetime, cred->kvno,
432                        &cred->ticket_st, cred->issue_date);
433     tf_close();
434     return ret;
435 }