kauth: Fix overflow when writing ticket file
[openafs.git] / src / kauth / krb_tf.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  *
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 /*
11  * ALL RIGHTS RESERVED
12  */
13
14 /* This modified from the code in kerberos/src/lib/krb/tf_util.c. */
15
16 /*
17  * This file contains routines for manipulating the ticket cache file.
18  *
19  * The ticket file is in the following format:
20  *
21  *      principal's name        (null-terminated string)
22  *      principal's instance    (null-terminated string)
23  *      CREDENTIAL_1
24  *      CREDENTIAL_2
25  *      ...
26  *      CREDENTIAL_n
27  *      EOF
28  *
29  *      Where "CREDENTIAL_x" consists of the following fixed-length
30  *      fields from the CREDENTIALS structure (see "krb.h"):
31  *
32  *              char            service[ANAME_SZ]
33  *              char            instance[INST_SZ]
34  *              char            realm[REALM_SZ]
35  *              C_Block         session
36  *              int             lifetime
37  *              int             kvno
38  *              KTEXT_ST        ticket_st
39  *              afs_int32            issue_date
40  *
41  * . . .
42  */
43
44 /* Inspite of what the above comment suggests the fields are not fixed length
45    but null terminated as you might figure, except for the ticket which is
46    preceded by a 4 byte length.  All fields in host order. 890306 */
47 #include <afsconfig.h>
48 #include <afs/param.h>
49
50 #include <roken.h>
51 #include <afs/opr.h>
52
53 #include <rx/xdr.h>
54 #include <afs/auth.h>
55
56 #include "kauth.h"
57 #include "kautils.h"
58 #include "kauth_internal.h"
59
60 afs_int32
61 krb_write_ticket_file(char *realm)
62 {
63     int fd;
64     int count;
65     afs_int32 code;
66     int lifetime, kvno;
67     char *tf_name;
68     struct ktc_principal client, server;
69     struct ktc_token token;
70
71     if ((strlen(realm) >= sizeof(client.cell)))
72         return KABADNAME;
73     strcpy(server.name, KA_TGS_NAME);
74     strcpy(server.instance, realm);
75     lcstring(server.cell, realm, sizeof(server.cell));
76
77     code = ktc_GetToken(&server, &token, sizeof(struct ktc_token), &client);
78     if (code)
79         return code;
80
81     /* Use the KRBTKFILE environment variable if it exists, otherwise fall
82      * back upon /tmp/tkt(uid}.
83      */
84     if ((tf_name = (char *)getenv("KRBTKFILE")))
85         fd = open(tf_name, O_WRONLY | O_CREAT | O_TRUNC, 0700);
86     else {
87         asprintf(&tf_name, "%s/tkt%d", gettmpdir(), getuid());
88         if (tf_name == NULL)
89             return ENOMEM;
90         fd = open(tf_name, O_WRONLY | O_CREAT | O_TRUNC, 0700);
91         free(tf_name);
92     }
93
94     if (fd <= 0)
95         return errno;
96
97     /* write client name as file header */
98
99     count = strlen(client.name) + 1;
100     if (write(fd, client.name, count) != count)
101         goto bad;
102
103     count = strlen(client.instance) + 1;
104     if (write(fd, client.instance, count) != count)
105         goto bad;
106
107     /* Write the ticket and associated data */
108     /* Service */
109     count = strlen(server.name) + 1;
110     if (write(fd, server.name, count) != count)
111         goto bad;
112     /* Instance */
113     count = strlen(server.instance) + 1;
114     if (write(fd, server.instance, count) != count)
115         goto bad;
116     /* Realm */
117     ucstring(server.cell, server.cell, sizeof(server.cell));
118     count = strlen(server.cell) + 1;
119     if (write(fd, server.cell, count) != count)
120         goto bad;
121     /* Session key */
122     if (write(fd, (char *)&token.sessionKey, 8) != 8)
123         goto bad;
124     /* Lifetime */
125     lifetime = time_to_life(token.startTime, token.endTime);
126     if (write(fd, (char *)&lifetime, sizeof(int)) != sizeof(int))
127         goto bad;
128     /* Key vno */
129     kvno = token.kvno;
130     if (write(fd, (char *)&kvno, sizeof(int)) != sizeof(int))
131         goto bad;
132     /* Tkt length */
133     if (write(fd, (char *)&(token.ticketLen), sizeof(int)) != sizeof(int))
134         goto bad;
135     /* Ticket */
136     count = token.ticketLen;
137     if (write(fd, (char *)(token.ticket), count) != count)
138         goto bad;
139     /* Issue date */
140     if (write(fd, (char *)&(token.startTime), sizeof(afs_int32))
141         != sizeof(afs_int32))
142         goto bad;
143     close(fd);
144     return 0;
145
146   bad:
147     close(fd);
148     return -1;
149 }