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