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