summaryrefslogtreecommitdiffstats
path: root/crypto/kerberosIV/lib/krb/ticket_memory.c
blob: f694190df65144d15e5a1ccaec970b45659c50bb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
/*
 * Copyright (c) 1995, 1996, 1997, 1998 Kungliga Tekniska Högskolan
 * (Royal Institute of Technology, Stockholm, Sweden).
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 
 * 3. Neither the name of the Institute nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

/* ticket_memory.c - Storage for tickets in memory
 * Author: d93-jka@nada.kth.se - June 1996
 */

#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include "krb_locl.h"
#include "ticket_memory.h"

RCSID("$Id: ticket_memory.c,v 1.15 1999/12/02 16:58:44 joda Exp $");

void msg(char *text, int error);

/* Global variables for memory mapping. */
HANDLE	SharedMemoryHandle;
tktmem	*SharedMemory;

static int CredIndex = -1;

void PostUpdateMessage(void);

int
newTktMem(const char *tf_name)
{
    if(!SharedMemory){
	SharedMemoryHandle = CreateFileMapping((HANDLE)-1, 0,
					       PAGE_READWRITE,
					       sizeof(tktmem) >> 16,
					       sizeof(tktmem) & 0xffff,
					       "krb_memory");
	
	if(!SharedMemoryHandle){
	    msg("Could not create shared memory.", GetLastError());
	    return KFAILURE;
	}
		
	SharedMemory = MapViewOfFile(SharedMemoryHandle,
				     FILE_MAP_WRITE, 0, 0, 0);
	if(!SharedMemory){
	    msg("Unable to alloc shared memory.", GetLastError());
	    return KFAILURE;
	}
	if(GetLastError() != ERROR_ALREADY_EXISTS) {
            memset(SharedMemory, 0, sizeof(*SharedMemory));
	    if(tf_name)
		strlcpy(SharedMemory->tmname,
				tf_name, sizeof(SharedMemory->tmname));
	}
    }
    CredIndex = 0;
    return KSUCCESS;
}

int
freeTktMem(const char *tf_name)
{
    if(SharedMemory) {
	UnmapViewOfFile(SharedMemory);
	CloseHandle(SharedMemoryHandle);
    }
    return KSUCCESS;
}



tktmem *
getTktMem(const char *tf_name)
{
    return SharedMemory;
}

void
firstCred(void)
{
    if(getTktMem(0)->last_cred_no > 0)
	CredIndex = 0;
    else
	CredIndex = -1;
}
	
int
nextCredIndex(void)
{
    const tktmem *mem;
    int last;
    mem = getTktMem(0);
    last = mem->last_cred_no;
    if(CredIndex >= 0 && CredIndex < last )
	return CredIndex++;
    else
	return CredIndex = -1;
}

int
currCredIndex(void)
{
    const tktmem *mem;
    int last;
    mem = getTktMem(0);
    last = mem->last_cred_no;
    if(CredIndex >= 0 && CredIndex < last)
	return CredIndex;
    else
	return CredIndex = -1;
}

int
nextFreeIndex(void)
{
    tktmem *mem = getTktMem(0);
    if(mem->last_cred_no > CRED_VEC_SZ)
	return -1;
    else
	return mem->last_cred_no++;
}

/*
 * in_tkt() is used to initialize the ticket store.  It creates the
 * file to contain the tickets and writes the given user's name "pname"
 * and instance "pinst" in the file.  in_tkt() returns KSUCCESS on
 * success, or KFAILURE if something goes wrong.
 */

int
in_tkt(char *pname, char *pinst)
{
    /* Here goes code to initialize shared memory, to store tickets in. */
    /* Implemented somewhere else. */
    return KFAILURE;
}

/*
 * dest_tkt() is used to destroy the ticket store upon logout.
 * If the ticket file does not exist, dest_tkt() returns RET_TKFIL.
 * Otherwise the function returns RET_OK on success, KFAILURE on
 * failure.
 *
 * The ticket file (TKT_FILE) is defined in "krb.h".
 */

int
dest_tkt(void)
{
    memset(getTktMem(0), 0, sizeof(tktmem));
    return 0;
}

/* Short description of routines:
 *
 * tf_init() opens the ticket file and locks it.
 *
 * tf_get_pname() returns the principal's name.
 *
 * tf_put_pname() writes the principal's name to the ticket file.
 *
 * tf_get_pinst() returns the principal's instance (may be null).
 *
 * tf_put_pinst() writes the instance.
 *
 * tf_get_cred() returns the next CREDENTIALS record.
 *
 * tf_save_cred() appends a new CREDENTIAL record to the ticket file.
 *
 * tf_close() closes the ticket file and releases the lock.
 *
 * tf_gets() returns the next null-terminated string.  It's an internal
 * routine used by tf_get_pname(), tf_get_pinst(), and tf_get_cred().
 *
 * tf_read() reads a given number of bytes.  It's an internal routine
 * used by tf_get_cred().
 */

/*
 * tf_init() should be called before the other ticket file routines.
 * It takes the name of the ticket file to use, "tf_name", and a
 * read/write flag "rw" as arguments. 
 *
 * Returns KSUCCESS if all went well, otherwise one of the following: 
 *
 * NO_TKT_FIL   - file wasn't there
 * TKT_FIL_ACC  - file was in wrong mode, etc.
 * TKT_FIL_LCK  - couldn't lock the file, even after a retry
 */

int
tf_init(char *tf_name, int rw)
{
    if(!getTktMem(tf_name))
	return NO_TKT_FIL;
    firstCred();
    return KSUCCESS;
}

/*
 * tf_create() should be called when creating a new ticket file.
 * The only argument is the name of the ticket file.
 * After calling this, it should be possible to use other tf_* functions.
 */

int
tf_create(char *tf_name)
{
    if(newTktMem(tf_name) != KSUCCESS)
	return NO_TKT_FIL;
    return KSUCCESS;
}

/*
 * tf_get_pname() reads the principal's name from the ticket file. It
 * should only be called after tf_init() has been called.  The
 * principal's name is filled into the "p" parameter.  If all goes well,
 * KSUCCESS is returned.  If tf_init() wasn't called, TKT_FIL_INI is
 * returned.  If the name was null, or EOF was encountered, or the name
 * was longer than ANAME_SZ, TKT_FIL_FMT is returned. 
 */

int
tf_get_pname(char *p)
{
    tktmem *TktStore;

    if(!(TktStore =  getTktMem(0)))
	return KFAILURE;
    if(!TktStore->pname[0])
	return KFAILURE;
    strlcpy(p, TktStore->pname, ANAME_SZ);
    return KSUCCESS;
}

/*
 * tf_put_pname() sets the principal's name in the ticket file. Call
 * after tf_create().
 */

int
tf_put_pname(char *p)
{
    tktmem *TktStore;

    if(!(TktStore =  getTktMem(0)))
	return KFAILURE;
    strlcpy(TktStore->pname, p, sizeof(TktStore->pname));
    return KSUCCESS;
}

/*
 * tf_get_pinst() reads the principal's instance from a ticket file.
 * It should only be called after tf_init() and tf_get_pname() have been
 * called.  The instance is filled into the "inst" parameter.  If all
 * goes well, KSUCCESS is returned.  If tf_init() wasn't called,
 * TKT_FIL_INI is returned.  If EOF was encountered, or the instance
 * was longer than ANAME_SZ, TKT_FIL_FMT is returned.  Note that the
 * instance may be null. 
 */

int
tf_get_pinst(char *inst)
{
    tktmem *TktStore;

    if(!(TktStore =  getTktMem(0)))
	return KFAILURE;
    strlcpy(inst, TktStore->pinst, INST_SZ);
    return KSUCCESS;
}

/*
 * tf_put_pinst writes the principal's instance to the ticket file.
 * Call after tf_create.
 */

int
tf_put_pinst(char *inst)
{
    tktmem *TktStore;

    if(!(TktStore =  getTktMem(0)))
	return KFAILURE;
    strlcpy(TktStore->pinst, inst, sizeof(TktStore->pinst));
    return KSUCCESS;
}

/*
 * tf_get_cred() reads a CREDENTIALS record from a ticket file and fills
 * in the given structure "c".  It should only be called after tf_init(),
 * tf_get_pname(), and tf_get_pinst() have been called. If all goes well,
 * KSUCCESS is returned.  Possible error codes are: 
 *
 * TKT_FIL_INI  - tf_init wasn't called first
 * TKT_FIL_FMT  - bad format
 * EOF          - end of file encountered
 */

int
tf_get_cred(CREDENTIALS *c)
{
    int index;
    CREDENTIALS *cred;
    tktmem *TktStore;

    if(!(TktStore =  getTktMem(0)))
	return KFAILURE;
    krb_set_kdc_time_diff(TktStore->kdc_diff);
    if((index = nextCredIndex()) == -1)
	return EOF;
    if(!(cred = TktStore->cred_vec+index))
	return KFAILURE;
    if(!c)
	return KFAILURE;
    memcpy(c, cred, sizeof(*c));
    return KSUCCESS;
}

/*
 * tf_close() closes the ticket file and sets "fd" to -1. If "fd" is
 * not a valid file descriptor, it just returns.  It also clears the
 * buffer used to read tickets.
 */

void
tf_close(void)
{
}

/*
 * tf_save_cred() appends an incoming ticket to the end of the ticket
 * file.  You must call tf_init() before calling tf_save_cred().
 *
 * The "service", "instance", and "realm" arguments specify the
 * server's name; "session" contains the session key to be used with
 * the ticket; "kvno" is the server key version number in which the
 * ticket is encrypted, "ticket" contains the actual ticket, and
 * "issue_date" is the time the ticket was requested (local host's time).
 *
 * Returns KSUCCESS if all goes well, TKT_FIL_INI if tf_init() wasn't
 * called previously, and KFAILURE for anything else that went wrong.
 */
 
int
tf_save_cred(char *service,	/* Service name */
	     char *instance,	/* Instance */
	     char *realm,	/* Auth domain */
	     unsigned char *session, /* Session key */
	     int lifetime,	/* Lifetime */
	     int kvno,		/* Key version number */
	     KTEXT ticket,	/* The ticket itself */
	     u_int32_t issue_date) /* The issue time */
{
    CREDENTIALS *cred;
    tktmem *mem =  getTktMem(0);
    int last = nextFreeIndex();

    if(last == -1)
	return KFAILURE;
    cred = mem->cred_vec+last;
    strlcpy(cred->service, service, sizeof(cred->service));
    strlcpy(cred->instance, instance, sizeof(cred->instance));
    strlcpy(cred->realm, realm, sizeof(cred->realm));
    memcpy(cred->session, session, sizeof(cred->session));
    cred->lifetime = lifetime;
    cred->kvno = kvno;
    memcpy(&(cred->ticket_st), ticket, sizeof(*ticket));
    cred->issue_date = issue_date;
    strlcpy(cred->pname, mem->pname, sizeof(cred->pname));
    strlcpy(cred->pinst, mem->pinst, sizeof(cred->pinst));
    PostUpdateMessage();
    return KSUCCESS;
}


static void
set_time_diff(time_t diff)
{
    tktmem *TktStore = getTktMem(0);
    if(TktStore == NULL)
	return;
    TktStore->kdc_diff = diff;
}


int
tf_setup(CREDENTIALS *cred, char *pname, char *pinst)
{
    int ret;
    ret = tf_create(tkt_string());
    if (ret != KSUCCESS)
	return ret;

    if (tf_put_pname(pname) != KSUCCESS ||
	tf_put_pinst(pinst) != KSUCCESS) {
	tf_close();
	return INTK_ERR;
    }

    set_time_diff(krb_get_kdc_time_diff());

    ret = tf_save_cred(cred->service, cred->instance, cred->realm, 
		       cred->session, cred->lifetime, cred->kvno,
		       &cred->ticket_st, cred->issue_date);
    tf_close();
    return ret;
}
OpenPOWER on IntegriCloud