]> asedeno.scripts.mit.edu Git - 1ts-debian.git/blob - zephyr/lib/ZMkAuth.c
bits of krb5 bdump
[1ts-debian.git] / zephyr / lib / ZMkAuth.c
1 /* This file is part of the Project Athena Zephyr Notification System.
2  * It contains source for the ZMakeAuthentication function.
3  *
4  *      Created by:     Robert French
5  *
6  *      $Id: ZMkAuth.c,v 1.20 2002/11/11 18:28:06 ghudson Exp $
7  *
8  *      Copyright (c) 1987 by the Massachusetts Institute of Technology.
9  *      For copying and distribution information, see the file
10  *      "mit-copyright.h". 
11  */
12
13 #include <internal.h>
14
15 #ifndef lint
16 static const char rcsid_ZMakeAuthentication_c[] = "$Id: ZMkAuth.c,v 1.20 2002/11/11 18:28:06 ghudson Exp $";
17 #endif
18
19 #ifdef HAVE_KRB4
20 #include <krb_err.h>
21 #endif
22
23 #if defined(HAVE_KRB5) && !HAVE_KRB5_FREE_DATA
24 #define krb5_free_data(ctx, dat) free((dat)->data)
25 #endif
26
27 Code_t ZResetAuthentication () {
28     return ZERR_NONE;
29 }
30
31 Code_t ZMakeAuthentication(notice, buffer, buffer_len, len)
32     register ZNotice_t *notice;
33     char *buffer;
34     int buffer_len;
35     int *len;
36 {
37 #if 1
38     return ZMakeZcodeAuthentication(notice, buffer, buffer_len, len/*?XXX*/);
39 #else
40 #if defined(HAVE_KRB4) || defined(HAVE_KRB5)
41     int result;
42     time_t now;
43     KTEXT_ST authent;
44     char *cstart, *cend;
45     ZChecksum_t checksum;
46     CREDENTIALS cred;
47     C_Block *session;
48 #ifdef HAVE_KRB5
49     krb5_creds *creds_out;
50
51     result = ZGetCreds(&creds_out);
52     if (result)
53       return result;
54
55     result = krb5_524_convert_creds(Z_krb5_ctx, creds_out, &cred);
56     /* krb5_free_creds(Z_krb5_ctx, creds_out);*/
57     if (result)
58       return result;
59     /* HOLDING: creds_out */
60
61     if (creds_out->keyblock.enctype != ENCTYPE_DES_CBC_CRC)
62       return (KRB5_BAD_ENCTYPE);
63     session = (C_Block *)creds_out->keyblock.contents;
64
65     result = krb_mk_req_creds(&authent, &cred, 0);
66     if (result != MK_AP_OK)
67       return result + krb_err_base;
68 #endif
69 #ifndef HAVE_KRB5
70     result = krb_mk_req(&authent, SERVER_SERVICE, 
71                         SERVER_INSTANCE, __Zephyr_realm, 0);
72     if (result != MK_AP_OK)
73         return (result+krb_err_base);
74     result = krb_get_cred(SERVER_SERVICE, SERVER_INSTANCE,
75                           __Zephyr_realm, &cred);
76     if (result != KSUCCESS)
77         return (result+krb_err_base);
78
79     session = (C_Block *)cred.session;
80 #endif
81
82     notice->z_auth = 1;
83     notice->z_authent_len = authent.length;
84     notice->z_ascii_authent = (char *)malloc((unsigned)authent.length*3);
85     /* zero length authent is an error, so malloc(0) is not a problem */
86     if (!notice->z_ascii_authent)
87         return (ENOMEM);
88     if ((result = ZMakeAscii(notice->z_ascii_authent, 
89                              authent.length*3, 
90                              authent.dat, 
91                              authent.length)) != ZERR_NONE) {
92         free(notice->z_ascii_authent);
93         return (result);
94     }
95     result = Z_FormatRawHeader(notice, buffer, buffer_len, len, &cstart,
96                                &cend);
97     free(notice->z_ascii_authent);
98     notice->z_authent_len = 0;
99     if (result)
100         return(result);
101
102     /* Compute a checksum over the header and message. */
103     checksum = des_quad_cksum(buffer, NULL, cstart - buffer, 0, session);
104     checksum ^= des_quad_cksum(cend, NULL, buffer + *len - cend, 0,
105                                session);
106     checksum ^= des_quad_cksum(notice->z_message, NULL, notice->z_message_len,
107                                0, session);
108     notice->z_checksum = checksum;
109     ZMakeAscii32(cstart, buffer + buffer_len - cstart, checksum);
110
111     return (ZERR_NONE);
112 #else
113     notice->z_checksum = 0;
114     notice->z_auth = 1;
115     notice->z_authent_len = 0;
116     notice->z_ascii_authent = "";
117     return (Z_FormatRawHeader(notice, buffer, buffer_len, len, NULL, NULL));
118 #endif
119 #endif
120 }
121
122 Code_t ZMakeZcodeAuthentication(notice, buffer, buffer_len, phdr_len)
123     register ZNotice_t *notice;
124     char *buffer;
125     int buffer_len;
126     int *phdr_len;
127 {
128     return ZMakeZcodeRealmAuthentication(notice, buffer, buffer_len, phdr_len,
129                                          __Zephyr_realm);
130 }
131
132 Code_t ZMakeZcodeRealmAuthentication(notice, buffer, buffer_len, phdr_len, 
133                                      realm)
134     register ZNotice_t *notice;
135     char *buffer;
136     int buffer_len;
137     int *phdr_len;
138     char *realm;
139 {
140 #ifdef HAVE_KRB5
141     krb5_error_code result;
142     krb5_creds *creds;
143     krb5_keyblock *keyblock;
144     krb5_enctype enctype;
145     krb5_cksumtype cksumtype;
146     krb5_auth_context authctx;
147     krb5_data *authent;
148     krb5_data cksumbuf;
149     char *svcinst, *x, *y;
150     char *cksum_start, *cstart, *cend, *asn1_data;
151     int plain_len;   /* length of part not to be checksummed */
152     int cksum_len;   /* length of part to be checksummed (incl cksum) */
153     int cksum0_len;  /* length of part before checksum */
154     int cksum1_len;  /* length of part after checksum */
155     int i, zcode_len, asn1_len;
156     
157     result = ZGetCredsRealm(&creds, realm);
158     if (result)
159         return result;
160     /* HOLDING: creds */
161     
162     /* Figure out what checksum type to use */
163     keyblock = Z_credskey(creds);
164     result = Z_ExtractEncCksum(keyblock, &enctype, &cksumtype);
165     if (result) {
166         krb5_free_creds(Z_krb5_ctx, creds);
167         return result;
168     }
169     /* HOLDING: creds */
170     
171     /* Create the authenticator */
172     result = krb5_auth_con_init(Z_krb5_ctx, &authctx);
173     if (result) {
174         krb5_free_creds(Z_krb5_ctx, creds);
175         return (result);
176     }
177         
178     authent = (krb5_data *)malloc(sizeof(krb5_data));
179
180     /* HOLDING: creds, authctx */
181     result = krb5_mk_req_extended(Z_krb5_ctx, &authctx, 0 /* options */,
182                                   0 /* in_data */, creds, authent);
183     krb5_auth_con_free(Z_krb5_ctx, authctx);
184     if (result) {
185         krb5_free_creds(Z_krb5_ctx, creds);
186         return (result);
187     }
188     /* HOLDING: creds, authent */
189     
190     /* Encode the authenticator */
191     notice->z_auth = 1;
192     notice->z_authent_len = authent->length;
193     zcode_len = authent->length * 2 + 2; /* 2x growth plus Z and null */
194     notice->z_ascii_authent = (char *)malloc(zcode_len);
195     if (!notice->z_ascii_authent) {
196         krb5_free_data(Z_krb5_ctx, authent);
197         krb5_free_creds(Z_krb5_ctx, creds);
198         return (ENOMEM);
199     }
200     /* HOLDING: creds, authent, notice->z_ascii_authent */
201     result = ZMakeZcode(notice->z_ascii_authent, zcode_len, 
202                         authent->data, authent->length);
203     krb5_free_data(Z_krb5_ctx, authent);
204     if (result) {
205         free(notice->z_ascii_authent);
206         krb5_free_creds(Z_krb5_ctx, creds);
207         return (result);
208     }
209     /* HOLDING: creds, notice->z_ascii_authent */
210     
211     /* format the notice header, with a zero checksum */
212     result = Z_NewFormatRawHeader(notice, buffer, buffer_len, phdr_len,
213                                   &cksum_start, &cksum_len, &cstart, &cend);
214     free(notice->z_ascii_authent);
215     notice->z_authent_len = 0;
216     if (result) {
217         krb5_free_creds(Z_krb5_ctx, creds);
218         return (result);
219     }
220     /* HOLDING: creds */
221     
222     /* Assemble the things to be checksummed */
223     plain_len  = cksum_start - buffer;
224     cksum0_len = cstart - cksum_start;
225     cksum1_len = (cksum_start + cksum_len) - cend;
226     memset(&cksumbuf, 0, sizeof(cksumbuf));
227     cksumbuf.length = cksum0_len + cksum1_len + notice->z_message_len;
228     cksumbuf.data = malloc(cksumbuf.length);
229     if (!cksumbuf.data) {
230         krb5_free_creds(Z_krb5_ctx, creds);
231         return (ENOMEM);
232     }
233     /* HOLDING: creds, cksumbuf.data */
234     memcpy(cksumbuf.data, cksum_start, cksum0_len);
235     memcpy(cksumbuf.data + cksum0_len, cend, cksum1_len);
236     memcpy(cksumbuf.data + cksum0_len + cksum1_len,
237            notice->z_message, notice->z_message_len);
238
239     /* compute the checksum */
240     result = Z_Checksum(&cksumbuf, keyblock, cksumtype, &asn1_data, &asn1_len);
241     krb5_free_creds(Z_krb5_ctx, creds);
242     if (result) {
243         free(cksumbuf.data);
244         return result;
245     }
246     
247     /* 
248      * OK....  we can zcode to a space starting at 'cstart',
249      * with a length of buffer_len - (plain_len + cksum_len).
250      * Then we tack on the end part, which is located at
251      * cksumbuf.data + cksum0_len and has length cksum1_len
252      */
253     result = ZMakeZcode(cstart, buffer_len - (plain_len + cksum_len),
254                         asn1_data, asn1_len);
255     if (!result) {
256         zcode_len = strlen(cstart) + 1;
257         memcpy(cstart + zcode_len, cksumbuf.data + cksum0_len, cksum1_len);
258         *phdr_len -= cksum_len - (cksum0_len + cksum1_len);
259         *phdr_len += zcode_len;
260     }
261     
262     /* free stuff up, and then return the result from the last call */
263
264     free(cksumbuf.data);
265     free(asn1_data);
266
267     return (result);
268 #endif /* HAVE_KRB5 */
269 }
270
271 #ifdef HAVE_KRB5
272 int ZGetCreds(krb5_creds **creds_out) {
273   return ZGetCredsRealm(creds_out, __Zephyr_realm);
274 }
275
276 int ZGetCredsRealm(krb5_creds **creds_out, char *realm) {
277   krb5_creds creds_in;
278   krb5_ccache ccache; /* XXX make this a global or static?*/
279   int result;
280   
281   result = krb5_cc_default(Z_krb5_ctx, &ccache);
282   if (result)
283     return result;
284
285   memset((char *)&creds_in, 0, sizeof(creds_in));
286   result = krb5_build_principal(Z_krb5_ctx, &creds_in.server,
287                                 strlen(realm),
288                                 realm,
289                                 SERVER_SERVICE, SERVER_INSTANCE, 0);
290   if (result) {
291     krb5_cc_close(Z_krb5_ctx, ccache);
292     return result;
293   }
294   
295   result = krb5_cc_get_principal(Z_krb5_ctx, ccache, &creds_in.client);
296   if (result) {
297     krb5_free_cred_contents(Z_krb5_ctx, &creds_in); /* I also hope this is ok */
298     krb5_cc_close(Z_krb5_ctx, ccache);
299     return result;
300   }
301   
302   creds_in.keyblock.enctype = ENCTYPE_DES_CBC_CRC; /* XXX? */
303   
304   result = krb5_get_credentials(Z_krb5_ctx, 0, ccache, &creds_in, creds_out);
305   krb5_cc_close(Z_krb5_ctx, ccache);
306   krb5_free_cred_contents(Z_krb5_ctx, &creds_in); /* I also hope this is ok */
307
308   return result;
309 }
310 #endif