2 * lib/krb5/krb/mk_req_ext.c
4 * Copyright 1990,1991 by the Massachusetts Institute of Technology.
7 * Export of this software from the United States of America may
8 * require a specific license from the United States Government.
9 * It is the responsibility of any person or organization contemplating
10 * export to obtain such a license before exporting.
12 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
13 * distribute this software and its documentation for any purpose and
14 * without fee is hereby granted, provided that the above copyright
15 * notice appear in all copies and that both that copyright notice and
16 * this permission notice appear in supporting documentation, and that
17 * the name of M.I.T. not be used in advertising or publicity pertaining
18 * to distribution of the software without specific, written prior
19 * permission. M.I.T. makes no representations about the suitability of
20 * this software for any purpose. It is provided "as is" without express
21 * or implied warranty.
24 * krb5_mk_req_extended()
28 #include <krb5/krb5.h>
29 #include <krb5/asn1.h>
31 #include <krb5/libos.h>
32 #include <krb5/los-proto.h>
34 #include <krb5/ext-proto.h>
37 Formats a KRB_AP_REQ message into outbuf, with more complete options than
40 outbuf, ap_req_options, checksum, and ccache are used in the
41 same fashion as for krb5_mk_req.
43 creds is used to supply the credentials (ticket and session key) needed
46 if creds->ticket has no data (length == 0), then a ticket is obtained
47 from either the cache or the TGS, passing creds to krb5_get_credentials().
48 kdc_options specifies the options requested for the ticket to be used.
49 If a ticket with appropriate flags is not found in the cache, then these
50 options are passed on in a request to an appropriate KDC.
52 ap_req_options specifies the KRB_AP_REQ options desired.
54 if ap_req_options specifies AP_OPTS_USE_SESSION_KEY, then creds->ticket
55 must contain the appropriate ENC-TKT-IN-SKEY ticket.
57 checksum specifies the checksum to be used in the authenticator.
59 The outbuf buffer storage is allocated, and should be freed by the
62 On an error return, the credentials pointed to by creds might have been
63 augmented with additional fields from the obtained credentials; the entire
64 credentials should be released by calling krb5_free_creds().
69 static krb5_error_code
70 krb5_generate_authenticator PROTOTYPE((krb5_context,
71 krb5_authenticator *, krb5_principal,
72 const krb5_checksum *, krb5_keyblock *,
73 krb5_int32, krb5_authdata ** ));
76 krb5_mk_req_extended(context, ap_req_options, checksum, kdc_options,
77 sequence, newkey, ccache, creds, authentp, outbuf)
79 const krb5_flags ap_req_options;
80 const krb5_checksum *checksum;
81 const krb5_flags kdc_options;
83 krb5_keyblock **newkey;
86 krb5_authenticator *authentp;
89 krb5_error_code retval;
91 krb5_authenticator authent;
94 krb5_encrypt_block eblock;
99 request.authenticator.ciphertext.data = 0;
104 if ((ap_req_options & AP_OPTS_USE_SESSION_KEY) &&
105 !creds->ticket.length)
106 return(KRB5_NO_TKT_SUPPLIED);
108 if (!creds->ticket.length) {
110 if (retval = krb5_get_credentials(context, kdc_options,
116 /* we need a native ticket */
117 if (retval = decode_krb5_ticket(&creds->ticket, &request.ticket))
120 /* verify a valid etype is available */
121 etype = request.ticket->enc_part.etype;
123 if (!valid_etype(etype)) {
124 retval = KRB5_PROG_ETYPE_NOSUPP;
128 request.ap_options = ap_req_options;
130 if (retval = krb5_generate_subkey(context, &creds->keyblock, newkey))
134 if (retval = krb5_generate_authenticator(context, &authent, creds->client, checksum,
135 newkey ? *newkey : 0,
136 sequence, creds->authdata))
139 /* encode the authenticator */
140 retval = encode_krb5_authenticator(&authent, &scratch);
144 /* Null out these fields, to prevent pointer sharing problems;
145 * they were supplied by the caller
147 authent.client = NULL;
148 authent.checksum = NULL;
149 authent.authorization_data = NULL;
153 krb5_free_authenticator_contents(context, &authent);
155 /* put together an eblock for this encryption */
157 krb5_use_cstype(context, &eblock, etype);
158 request.authenticator.etype = etype;
159 request.authenticator.kvno = 0;
160 request.authenticator.ciphertext.length =
161 krb5_encrypt_size(scratch->length, eblock.crypto_entry);
162 /* add padding area, and zero it */
163 if (!(scratch->data = realloc(scratch->data,
164 request.authenticator.ciphertext.length))) {
165 /* may destroy scratch->data */
169 memset(scratch->data + scratch->length, 0,
170 request.authenticator.ciphertext.length - scratch->length);
171 if (!(request.authenticator.ciphertext.data =
172 malloc(request.authenticator.ciphertext.length))) {
177 /* do any necessary key pre-processing */
178 if (retval = krb5_process_key(context, &eblock, &creds->keyblock))
183 /* call the encryption routine */
184 if (retval = krb5_encrypt(context, (krb5_pointer) scratch->data,
185 (krb5_pointer) request.authenticator.ciphertext.data,
186 scratch->length, &eblock, 0))
189 if (retval = krb5_finish_key(context, &eblock))
193 retval = encode_krb5_ap_req(&request, &toutbuf);
202 krb5_free_ticket(context, request.ticket);
203 if (request.authenticator.ciphertext.data) {
204 (void) memset(request.authenticator.ciphertext.data, 0,
205 request.authenticator.ciphertext.length);
206 free(request.authenticator.ciphertext.data);
208 if (retval && newkey && *newkey)
209 krb5_free_keyblock(context, *newkey);
211 memset(scratch->data, 0, scratch->length);
212 krb5_xfree(scratch->data);
216 krb5_finish_key(context, &eblock);
221 static krb5_error_code
222 krb5_generate_authenticator(context, authent, client, cksum, key, seq_number, authorization)
223 krb5_context context;
224 krb5_authenticator *authent;
225 krb5_principal client;
226 const krb5_checksum *cksum;
228 krb5_int32 seq_number;
229 krb5_authdata **authorization;
231 krb5_error_code retval;
233 authent->client = client;
234 authent->checksum = (krb5_checksum *)cksum;
236 retval = krb5_copy_keyblock(context, key, &authent->subkey);
241 authent->subkey = key;
242 authent->seq_number = seq_number;
243 authent->authorization_data = authorization;
245 return(krb5_us_timeofday(context, &authent->ctime, &authent->cusec));