2 * Copyright (c) 1995, 1996, 1997, 1998 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
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.
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.
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
34 /* ticket_memory.c - Storage for tickets in memory
35 * Author: d93-jka@nada.kth.se - June 1996
38 #define WIN32_LEAN_AND_MEAN
41 #include "ticket_memory.h"
43 RCSID("$Id: ticket_memory.c,v 1.15 1999/12/02 16:58:44 joda Exp $");
45 void msg(char *text, int error);
47 /* Global variables for memory mapping. */
48 HANDLE SharedMemoryHandle;
51 static int CredIndex = -1;
53 void PostUpdateMessage(void);
56 newTktMem(const char *tf_name)
59 SharedMemoryHandle = CreateFileMapping((HANDLE)-1, 0,
62 sizeof(tktmem) & 0xffff,
65 if(!SharedMemoryHandle){
66 msg("Could not create shared memory.", GetLastError());
70 SharedMemory = MapViewOfFile(SharedMemoryHandle,
71 FILE_MAP_WRITE, 0, 0, 0);
73 msg("Unable to alloc shared memory.", GetLastError());
76 if(GetLastError() != ERROR_ALREADY_EXISTS) {
77 memset(SharedMemory, 0, sizeof(*SharedMemory));
79 strlcpy(SharedMemory->tmname,
80 tf_name, sizeof(SharedMemory->tmname));
88 freeTktMem(const char *tf_name)
91 UnmapViewOfFile(SharedMemory);
92 CloseHandle(SharedMemoryHandle);
100 getTktMem(const char *tf_name)
108 if(getTktMem(0)->last_cred_no > 0)
120 last = mem->last_cred_no;
121 if(CredIndex >= 0 && CredIndex < last )
124 return CredIndex = -1;
133 last = mem->last_cred_no;
134 if(CredIndex >= 0 && CredIndex < last)
137 return CredIndex = -1;
143 tktmem *mem = getTktMem(0);
144 if(mem->last_cred_no > CRED_VEC_SZ)
147 return mem->last_cred_no++;
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.
158 in_tkt(char *pname, char *pinst)
160 /* Here goes code to initialize shared memory, to store tickets in. */
161 /* Implemented somewhere else. */
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
171 * The ticket file (TKT_FILE) is defined in "krb.h".
177 memset(getTktMem(0), 0, sizeof(tktmem));
181 /* Short description of routines:
183 * tf_init() opens the ticket file and locks it.
185 * tf_get_pname() returns the principal's name.
187 * tf_put_pname() writes the principal's name to the ticket file.
189 * tf_get_pinst() returns the principal's instance (may be null).
191 * tf_put_pinst() writes the instance.
193 * tf_get_cred() returns the next CREDENTIALS record.
195 * tf_save_cred() appends a new CREDENTIAL record to the ticket file.
197 * tf_close() closes the ticket file and releases the lock.
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().
202 * tf_read() reads a given number of bytes. It's an internal routine
203 * used by tf_get_cred().
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.
211 * Returns KSUCCESS if all went well, otherwise one of the following:
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
219 tf_init(char *tf_name, int rw)
221 if(!getTktMem(tf_name))
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.
234 tf_create(char *tf_name)
236 if(newTktMem(tf_name) != KSUCCESS)
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.
251 tf_get_pname(char *p)
255 if(!(TktStore = getTktMem(0)))
257 if(!TktStore->pname[0])
259 strlcpy(p, TktStore->pname, ANAME_SZ);
264 * tf_put_pname() sets the principal's name in the ticket file. Call
269 tf_put_pname(char *p)
273 if(!(TktStore = getTktMem(0)))
275 strlcpy(TktStore->pname, p, sizeof(TktStore->pname));
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.
290 tf_get_pinst(char *inst)
294 if(!(TktStore = getTktMem(0)))
296 strlcpy(inst, TktStore->pinst, INST_SZ);
301 * tf_put_pinst writes the principal's instance to the ticket file.
302 * Call after tf_create.
306 tf_put_pinst(char *inst)
310 if(!(TktStore = getTktMem(0)))
312 strlcpy(TktStore->pinst, inst, sizeof(TktStore->pinst));
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:
322 * TKT_FIL_INI - tf_init wasn't called first
323 * TKT_FIL_FMT - bad format
324 * EOF - end of file encountered
328 tf_get_cred(CREDENTIALS *c)
334 if(!(TktStore = getTktMem(0)))
336 krb_set_kdc_time_diff(TktStore->kdc_diff);
337 if((index = nextCredIndex()) == -1)
339 if(!(cred = TktStore->cred_vec+index))
343 memcpy(c, cred, sizeof(*c));
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.
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().
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).
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.
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 */
383 tktmem *mem = getTktMem(0);
384 int last = nextFreeIndex();
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;
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));
405 set_time_diff(time_t diff)
407 tktmem *TktStore = getTktMem(0);
410 TktStore->kdc_diff = diff;
415 tf_setup(CREDENTIALS *cred, char *pname, char *pinst)
418 ret = tf_create(tkt_string());
422 if (tf_put_pname(pname) != KSUCCESS ||
423 tf_put_pinst(pinst) != KSUCCESS) {
428 set_time_diff(krb_get_kdc_time_diff());
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);