1 /* This file is part of the Project Athena Zephyr Notification System.
2 * It contains source for the ZMakeAuthentication function.
4 * Created by: Robert French
8 * Copyright (c) 1987 by the Massachusetts Institute of Technology.
9 * For copying and distribution information, see the file
16 static const char rcsid_ZMakeAuthentication_c[] = "$Id$";
23 #if defined(HAVE_KRB5) && !HAVE_KRB5_FREE_DATA
24 #define krb5_free_data(ctx, dat) free((dat)->data)
28 ZResetAuthentication(void)
34 ZMakeAuthentication(register ZNotice_t *notice,
40 return ZMakeZcodeAuthentication(notice, buffer, buffer_len, len/*?XXX*/);
42 #if defined(HAVE_KRB4) || defined(HAVE_KRB5)
51 krb5_creds *creds_out;
53 result = ZGetCreds(&creds_out);
57 result = krb5_524_convert_creds(Z_krb5_ctx, creds_out, &cred);
58 /* krb5_free_creds(Z_krb5_ctx, creds_out);*/
61 /* HOLDING: creds_out */
63 if (creds_out->keyblock.enctype != ENCTYPE_DES_CBC_CRC)
64 return (KRB5_BAD_ENCTYPE);
65 session = (C_Block *)creds_out->keyblock.contents;
67 result = krb_mk_req_creds(&authent, &cred, 0);
68 if (result != MK_AP_OK)
69 return result + krb_err_base;
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);
81 session = (C_Block *)cred.session;
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)
90 if ((result = ZMakeAscii(notice->z_ascii_authent,
93 authent.length)) != ZERR_NONE) {
94 free(notice->z_ascii_authent);
97 result = Z_FormatRawHeader(notice, buffer, buffer_len, len, &cstart,
99 free(notice->z_ascii_authent);
100 notice->z_authent_len = 0;
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,
108 checksum ^= des_quad_cksum(notice->z_message, NULL, notice->z_message_len,
110 notice->z_checksum = checksum;
111 ZMakeAscii32(cstart, buffer + buffer_len - cstart, checksum);
115 notice->z_checksum = 0;
117 notice->z_authent_len = 0;
118 notice->z_ascii_authent = "";
119 return (Z_FormatRawHeader(notice, buffer, buffer_len, len, NULL, NULL));
125 ZMakeZcodeAuthentication(register ZNotice_t *notice,
130 return ZMakeZcodeRealmAuthentication(notice, buffer, buffer_len, phdr_len,
135 ZMakeZcodeRealmAuthentication(register ZNotice_t *notice,
142 krb5_error_code result;
144 krb5_keyblock *keyblock;
145 krb5_enctype enctype;
146 krb5_cksumtype cksumtype;
147 krb5_auth_context authctx;
149 char *svcinst, *x, *y;
150 char *cksum_start, *cstart, *cend, *asn1_data;
151 int i, cksum_len, zcode_len, asn1_len, phdr_adj;
153 result = ZGetCredsRealm(&creds, realm);
158 /* Figure out what checksum type to use */
159 keyblock = Z_credskey(creds);
162 /* Create the authenticator */
163 result = krb5_auth_con_init(Z_krb5_ctx, &authctx);
165 krb5_free_creds(Z_krb5_ctx, creds);
169 authent = (krb5_data *)malloc(sizeof(krb5_data));
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);
176 krb5_free_creds(Z_krb5_ctx, creds);
179 /* HOLDING: creds, authent */
181 /* Encode the authenticator */
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);
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);
196 free(notice->z_ascii_authent);
197 krb5_free_creds(Z_krb5_ctx, creds);
200 /* HOLDING: creds, notice->z_ascii_authent */
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;
208 krb5_free_creds(Z_krb5_ctx, creds);
211 result = Z_InsertZcodeChecksum(keyblock, notice, buffer, cksum_start,
212 cksum_len, cstart, cend, buffer_len,
214 krb5_free_creds(Z_krb5_ctx, creds);
218 *phdr_len += phdr_adj;
221 #endif /* HAVE_KRB5 */
226 ZGetCreds(krb5_creds **creds_out)
228 return ZGetCredsRealm(creds_out, __Zephyr_realm);
232 ZGetCredsRealm(krb5_creds **creds_out,
236 krb5_ccache ccache; /* XXX make this a global or static?*/
239 result = krb5_cc_default(Z_krb5_ctx, &ccache);
243 memset((char *)&creds_in, 0, sizeof(creds_in));
244 result = krb5_build_principal(Z_krb5_ctx, &creds_in.server,
247 SERVER_SERVICE, SERVER_INSTANCE, 0);
249 krb5_cc_close(Z_krb5_ctx, ccache);
253 result = krb5_cc_get_principal(Z_krb5_ctx, ccache, &creds_in.client);
255 krb5_free_cred_contents(Z_krb5_ctx, &creds_in); /* I also hope this is ok */
256 krb5_cc_close(Z_krb5_ctx, ccache);
260 #ifdef HAVE_KRB5_CREDS_KEYBLOCK_ENCTYPE
261 creds_in.keyblock.enctype = ENCTYPE_DES_CBC_CRC; /* XXX? */
263 creds_in.session.keytype = KEYTYPE_DES; /* XXX? */
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 */