]> asedeno.scripts.mit.edu Git - 1ts-debian.git/blob - zephyr/lib/ZMkAuth.c
r4254@bucket (orig r244): kcr | 2008-01-20 14:40:42 -0500
[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$
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$";
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
28 ZResetAuthentication(void)
29 {
30     return ZERR_NONE;
31 }
32
33 Code_t
34 ZMakeAuthentication(register ZNotice_t *notice,
35                     char *buffer,
36                     int buffer_len,
37                     int *len)
38 {
39 #if 1
40     return ZMakeZcodeAuthentication(notice, buffer, buffer_len, len/*?XXX*/);
41 #else
42 #if defined(HAVE_KRB4) || defined(HAVE_KRB5)
43     int result;
44     time_t now;
45     KTEXT_ST authent;
46     char *cstart, *cend;
47     ZChecksum_t checksum;
48     CREDENTIALS cred;
49     C_Block *session;
50 #ifdef HAVE_KRB5
51     krb5_creds *creds_out;
52
53     result = ZGetCreds(&creds_out);
54     if (result)
55       return result;
56
57     result = krb5_524_convert_creds(Z_krb5_ctx, creds_out, &cred);
58     /* krb5_free_creds(Z_krb5_ctx, creds_out);*/
59     if (result)
60       return result;
61     /* HOLDING: creds_out */
62
63     if (creds_out->keyblock.enctype != ENCTYPE_DES_CBC_CRC)
64       return (KRB5_BAD_ENCTYPE);
65     session = (C_Block *)creds_out->keyblock.contents;
66
67     result = krb_mk_req_creds(&authent, &cred, 0);
68     if (result != MK_AP_OK)
69       return result + krb_err_base;
70 #endif
71 #ifndef HAVE_KRB5
72     result = krb_mk_req(&authent, SERVER_SERVICE, 
73                         SERVER_INSTANCE, __Zephyr_realm, 0);
74     if (result != MK_AP_OK)
75         return (result+krb_err_base);
76     result = krb_get_cred(SERVER_SERVICE, SERVER_INSTANCE,
77                           __Zephyr_realm, &cred);
78     if (result != KSUCCESS)
79         return (result+krb_err_base);
80
81     session = (C_Block *)cred.session;
82 #endif
83
84     notice->z_auth = 1;
85     notice->z_authent_len = authent.length;
86     notice->z_ascii_authent = (char *)malloc((unsigned)authent.length*3);
87     /* zero length authent is an error, so malloc(0) is not a problem */
88     if (!notice->z_ascii_authent)
89         return (ENOMEM);
90     if ((result = ZMakeAscii(notice->z_ascii_authent, 
91                              authent.length*3, 
92                              authent.dat, 
93                              authent.length)) != ZERR_NONE) {
94         free(notice->z_ascii_authent);
95         return (result);
96     }
97     result = Z_FormatRawHeader(notice, buffer, buffer_len, len, &cstart,
98                                &cend);
99     free(notice->z_ascii_authent);
100     notice->z_authent_len = 0;
101     if (result)
102         return(result);
103
104     /* Compute a checksum over the header and message. */
105     checksum = des_quad_cksum(buffer, NULL, cstart - buffer, 0, session);
106     checksum ^= des_quad_cksum(cend, NULL, buffer + *len - cend, 0,
107                                session);
108     checksum ^= des_quad_cksum(notice->z_message, NULL, notice->z_message_len,
109                                0, session);
110     notice->z_checksum = checksum;
111     ZMakeAscii32(cstart, buffer + buffer_len - cstart, checksum);
112
113     return (ZERR_NONE);
114 #else
115     notice->z_checksum = 0;
116     notice->z_auth = 1;
117     notice->z_authent_len = 0;
118     notice->z_ascii_authent = "";
119     return (Z_FormatRawHeader(notice, buffer, buffer_len, len, NULL, NULL));
120 #endif
121 #endif
122 }
123
124 Code_t
125 ZMakeZcodeAuthentication(register ZNotice_t *notice,
126                          char *buffer,
127                          int buffer_len,
128                          int *phdr_len)
129 {
130     return ZMakeZcodeRealmAuthentication(notice, buffer, buffer_len, phdr_len,
131                                          __Zephyr_realm);
132 }
133
134 Code_t
135 ZMakeZcodeRealmAuthentication(register ZNotice_t *notice,
136                               char *buffer,
137                               int buffer_len,
138                               int *phdr_len, 
139                               char *realm)
140 {
141 #ifdef HAVE_KRB5
142     krb5_error_code result;
143     krb5_creds *creds;
144     krb5_keyblock *keyblock;
145     krb5_enctype enctype;
146     krb5_cksumtype cksumtype;
147     krb5_auth_context authctx;
148     krb5_data *authent;
149     char *svcinst, *x, *y;
150     char *cksum_start, *cstart, *cend, *asn1_data;
151     int i, cksum_len, zcode_len, asn1_len, phdr_adj;
152     
153     result = ZGetCredsRealm(&creds, realm);
154     if (result)
155         return result;
156     /* HOLDING: creds */
157     
158     /* Figure out what checksum type to use */
159     keyblock = Z_credskey(creds);
160     /* HOLDING: creds */
161     
162     /* Create the authenticator */
163     result = krb5_auth_con_init(Z_krb5_ctx, &authctx);
164     if (result) {
165         krb5_free_creds(Z_krb5_ctx, creds);
166         return (result);
167     }
168         
169     authent = (krb5_data *)malloc(sizeof(krb5_data));
170
171     /* HOLDING: creds, authctx */
172     result = krb5_mk_req_extended(Z_krb5_ctx, &authctx, 0 /* options */,
173                                   0 /* in_data */, creds, authent);
174     krb5_auth_con_free(Z_krb5_ctx, authctx);
175     if (result) {
176         krb5_free_creds(Z_krb5_ctx, creds);
177         return (result);
178     }
179     /* HOLDING: creds, authent */
180     
181     /* Encode the authenticator */
182     notice->z_auth = 1;
183     notice->z_authent_len = authent->length;
184     zcode_len = authent->length * 2 + 2; /* 2x growth plus Z and null */
185     notice->z_ascii_authent = (char *)malloc(zcode_len);
186     if (!notice->z_ascii_authent) {
187         krb5_free_data(Z_krb5_ctx, authent);
188         krb5_free_creds(Z_krb5_ctx, creds);
189         return (ENOMEM);
190     }
191     /* HOLDING: creds, authent, notice->z_ascii_authent */
192     result = ZMakeZcode(notice->z_ascii_authent, zcode_len, 
193                         authent->data, authent->length);
194     krb5_free_data(Z_krb5_ctx, authent);
195     if (result) {
196         free(notice->z_ascii_authent);
197         krb5_free_creds(Z_krb5_ctx, creds);
198         return (result);
199     }
200     /* HOLDING: creds, notice->z_ascii_authent */
201     
202     /* format the notice header, with a zero checksum */
203     result = Z_NewFormatRawHeader(notice, buffer, buffer_len, phdr_len,
204                                   &cksum_start, &cksum_len, &cstart, &cend);
205     free(notice->z_ascii_authent);
206     notice->z_authent_len = 0;
207     if (result) {
208         krb5_free_creds(Z_krb5_ctx, creds);
209         return (result);
210     }
211     result = Z_InsertZcodeChecksum(keyblock, notice, buffer, cksum_start,
212                                    cksum_len, cstart, cend, buffer_len,
213                                    &phdr_adj);
214     krb5_free_creds(Z_krb5_ctx, creds);
215     if (result) {
216          return result;
217     }
218     *phdr_len += phdr_adj;
219
220     return (result);
221 #endif /* HAVE_KRB5 */
222 }
223
224 #ifdef HAVE_KRB5
225 int
226 ZGetCreds(krb5_creds **creds_out)
227 {
228   return ZGetCredsRealm(creds_out, __Zephyr_realm);
229 }
230
231 int
232 ZGetCredsRealm(krb5_creds **creds_out,
233                char *realm)
234 {
235   krb5_creds creds_in;
236   krb5_ccache ccache; /* XXX make this a global or static?*/
237   int result;
238   
239   result = krb5_cc_default(Z_krb5_ctx, &ccache);
240   if (result)
241     return result;
242
243   memset((char *)&creds_in, 0, sizeof(creds_in));
244   result = krb5_build_principal(Z_krb5_ctx, &creds_in.server,
245                                 strlen(realm),
246                                 realm,
247                                 SERVER_SERVICE, SERVER_INSTANCE, 0);
248   if (result) {
249     krb5_cc_close(Z_krb5_ctx, ccache);
250     return result;
251   }
252   
253   result = krb5_cc_get_principal(Z_krb5_ctx, ccache, &creds_in.client);
254   if (result) {
255     krb5_free_cred_contents(Z_krb5_ctx, &creds_in); /* I also hope this is ok */
256     krb5_cc_close(Z_krb5_ctx, ccache);
257     return result;
258   }
259  
260 #ifdef HAVE_KRB5_CREDS_KEYBLOCK_ENCTYPE 
261   creds_in.keyblock.enctype = ENCTYPE_DES_CBC_CRC; /* XXX? */
262 #else
263   creds_in.session.keytype = KEYTYPE_DES; /* XXX? */
264 #endif
265   
266   result = krb5_get_credentials(Z_krb5_ctx, 0, ccache, &creds_in, creds_out);
267   krb5_cc_close(Z_krb5_ctx, ccache);
268   krb5_free_cred_contents(Z_krb5_ctx, &creds_in); /* I also hope this is ok */
269
270   return result;
271 }
272 #endif