Import Upstream version 1.8.5
[hcoop/debian/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 }