kauth: Fix overflow when writing ticket file
[openafs.git] / src / kauth / kautils.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 #include <afsconfig.h>
11 #include <afs/param.h>
12 #include <afs/stds.h>
13
14 #include <roken.h>
15
16 #include <ctype.h>
17
18 #include <hcrypto/des.h>
19
20 #include <afs/afsutil.h>
21 #include <rx/xdr.h>
22 #include <rx/rx.h>
23 #include <rx/rxkad_convert.h>
24
25 #include "kauth.h"
26 #include "kautils.h"
27
28
29 /* This should match the behavior of ParseLoginName on input so that the output
30  * and input are compatible.  In names "." should show as \056 and in names and
31  * instances "@" should show as \100 */
32
33 void
34 ka_PrintUserID(char *prefix,    /* part to be output before userID */
35                char *name,      /* user name */
36                char *instance,  /* instance, possible null or len=0 */
37                char *postfix)
38 {                               /* for output following userID */
39     unsigned char *c;
40     printf("%s", prefix);
41     for (c = (unsigned char *)name; *c; c++)
42         if (isalnum(*c) || (ispunct(*c) && (*c != '.') && (*c != '@')))
43             printf("%c", *c);
44         else
45             printf("\\%.3o", *c);
46     if (instance && strlen(instance)) {
47         printf(".");
48         for (c = (unsigned char *)instance; *c; c++)
49             if (isalnum(*c) || (ispunct(*c) && (*c != '@')))
50                 printf("%c", *c);
51             else
52                 printf("\\%.3o", *c);
53     }
54     printf("%s", postfix);
55 }
56
57 void
58 ka_PrintBytes(char bs[], int bl)
59 {
60     int i = 0;
61
62     for (i = 0; i < bl; i++) {
63         unsigned char c = bs[i];
64         printf("\\%.3o", c);
65     }
66 }
67
68 /* converts a byte string to ascii.  Return the number of unconverted bytes. */
69
70 int
71 ka_ConvertBytes(char *ascii,    /* output buffer */
72                 int alen,       /* buffer length */
73                 char bs[],      /* byte string */
74                 int bl)
75 {                               /* number of bytes */
76     int i;
77     unsigned char c;
78
79     alen--;                     /* make room for termination */
80     for (i = 0; i < bl; i++) {
81         c = bs[i];
82         if (alen <= 0)
83             return bl - i;
84         if (isalnum(c) || ispunct(c))
85             (*ascii++ = c), alen--;
86         else {
87             if (alen <= 3)
88                 return bl - i;
89             *ascii++ = '\\';
90             *ascii++ = (c >> 6) + '0';
91             *ascii++ = (c >> 3 & 7) + '0';
92             *ascii++ = (c & 7) + '0';
93             alen -= 4;
94         }
95     }
96     *ascii = 0;                 /* terminate string */
97     return 0;                   /* all OK */
98 }
99
100 /* This is the inverse of the above function.  The return value is the number
101    of bytes read.  The blen parameter gived the maximum size of the output
102    buffer (binary). */
103
104 int
105 ka_ReadBytes(char *ascii, char *binary, int blen)
106 {
107     char *cp = ascii;
108     char c;
109     int i = 0;
110     while ((i < blen) && *cp) { /* get byte till null or full */
111         if (*cp == '\\') {      /* get byte in octal */
112             c = (*++cp) - '0';
113             c = (c << 3) + (*++cp) - '0';
114             c = (c << 3) + (*++cp) - '0';
115             cp++;
116         } else
117             c = *cp++;          /* get byte */
118         binary[i++] = c;
119     }
120     return i;
121 }
122
123 int
124 umin(afs_uint32 a, afs_uint32 b)
125 {
126     if (a < b)
127         return a;
128     else
129         return b;
130 }
131
132 /* ka_KeyCheckSum - returns a 32 bit cryptographic checksum of a DES encryption
133  * key.  It encrypts a block of zeros and uses first 4 bytes as cksum. */
134
135 afs_int32
136 ka_KeyCheckSum(char *key, afs_uint32 * cksumP)
137 {
138     DES_key_schedule s;
139     DES_cblock block;
140     afs_uint32 cksum;
141     afs_int32 code;
142
143     *cksumP = 0;
144     memset(block, 0, 8);
145     code = DES_key_sched(charptr_to_cblock(key), &s);
146     if (code)
147         return KABADKEY;
148     DES_ecb_encrypt(&block, &block, &s, ENCRYPT);
149     memcpy(&cksum, &block, sizeof(afs_int32));
150     *cksumP = ntohl(cksum);
151     return 0;
152 }
153
154 /* is the key all zeros? */
155 int
156 ka_KeyIsZero(char *akey, int alen)
157 {
158     int i;
159     for (i = 0; i < alen; i++) {
160         if (*akey++ != 0)
161             return 0;
162     }
163     return 1;
164 }
165
166 void
167 ka_timestr(afs_int32 time, char *tstr, afs_int32 tlen)
168 {
169     char tbuffer[32];           /* need at least 26 bytes */
170     time_t passtime;            /* modern systems have 64 bit time */
171     struct tm tm;
172
173     passtime = time;
174
175     if (time == NEVERDATE)
176         strcpy(tstr, "never");
177     else {
178         if (!time || strftime(tbuffer, sizeof(tbuffer), "%c",
179                               localtime_r(&passtime, &tm)) == 0)
180             strcpy(tstr, "no date");
181         else {
182             strncpy(tstr, tbuffer, tlen);
183         }
184     }
185 }