5 * Copyright 1990,1991 by the Massachusetts Institute of Technology.
8 * Export of this software from the United States of America may
9 * require a specific license from the United States Government.
10 * It is the responsibility of any person or organization contemplating
11 * export to obtain such a license before exporting.
13 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
14 * distribute this software and its documentation for any purpose and
15 * without fee is hereby granted, provided that the above copyright
16 * notice appear in all copies and that both that copyright notice and
17 * this permission notice appear in supporting documentation, and that
18 * the name of M.I.T. not be used in advertising or publicity pertaining
19 * to distribution of the software without specific, written prior
20 * permission. M.I.T. makes no representations about the suitability of
21 * this software for any purpose. It is provided "as is" without express
22 * or implied warranty.
25 * krb5_mk_req_extended()
28 #if !defined(lint) && !defined(SABER)
29 static char rcsid_mk_req_ext_c[] =
31 #endif /* !lint & !SABER */
33 #include <krb5/krb5.h>
34 #include <krb5/asn1.h>
36 #include <krb5/libos.h>
37 #include <krb5/los-proto.h>
39 #include <krb5/ext-proto.h>
42 Formats a KRB_AP_REQ message into outbuf, with more complete options than
45 outbuf, ap_req_options, checksum, and ccache are used in the
46 same fashion as for krb5_mk_req.
48 creds is used to supply the credentials (ticket and session key) needed
51 if creds->ticket has no data (length == 0), then a ticket is obtained
52 from either the cache or the TGS, passing creds to krb5_get_credentials().
53 kdc_options specifies the options requested for the ticket to be used.
54 If a ticket with appropriate flags is not found in the cache, then these
55 options are passed on in a request to an appropriate KDC.
57 ap_req_options specifies the KRB_AP_REQ options desired.
59 if ap_req_options specifies AP_OPTS_USE_SESSION_KEY, then creds->ticket
60 must contain the appropriate ENC-TKT-IN-SKEY ticket.
62 checksum specifies the checksum to be used in the authenticator.
64 The outbuf buffer storage is allocated, and should be freed by the
67 On an error return, the credentials pointed to by creds might have been
68 augmented with additional fields from the obtained credentials; the entire
69 credentials should be released by calling krb5_free_creds().
73 static krb5_error_code generate_authenticator PROTOTYPE((krb5_authenticator *,
75 const krb5_checksum *,
80 krb5_mk_req_extended(ap_req_options, checksum, kdc_options,
81 sequence, newkey, ccache, creds, authentp, outbuf)
82 const krb5_flags ap_req_options;
83 const krb5_checksum *checksum;
84 const krb5_flags kdc_options;
86 krb5_keyblock **newkey;
89 krb5_authenticator *authentp;
92 krb5_error_code retval;
94 krb5_authenticator authent;
97 krb5_encrypt_block eblock;
100 if ((ap_req_options & AP_OPTS_USE_SESSION_KEY) &&
101 !creds->ticket.length)
102 return(KRB5_NO_TKT_SUPPLIED);
104 if (!creds->ticket.length) {
106 if (retval = krb5_get_credentials(kdc_options,
111 /* verify a valid etype is available */
112 if (!valid_keytype(creds->keyblock.keytype))
113 return KRB5_PROG_KEYTYPE_NOSUPP;
115 etype = krb5_keytype_array[creds->keyblock.keytype]->system->proto_enctype;
117 if (!valid_etype(etype))
118 return KRB5_PROG_ETYPE_NOSUPP;
120 request.ap_options = ap_req_options;
121 /* we need a native ticket */
122 if (retval = decode_krb5_ticket(&creds->ticket, &request.ticket))
125 #define cleanup_ticket() krb5_free_ticket(request.ticket)
127 if (retval = krb5_generate_subkey(&creds->keyblock, newkey)) {
132 #define cleanup_key() {if (newkey) krb5_free_keyblock(*newkey);}
133 if (retval = generate_authenticator(&authent, creds, checksum,
134 newkey ? *newkey : 0,
142 /* Null out these fields, to prevent pointer sharing problems
143 * The caller won't need these fields anyway, since they were
144 * supplied by the caller
146 authentp->client = NULL;
147 authentp->checksum = NULL;
149 /* encode it before encrypting */
150 retval = encode_krb5_authenticator(&authent, &scratch);
157 #define cleanup_scratch() { (void) memset(scratch->data, 0, scratch->length); \
158 krb5_free_data(scratch); }
160 /* put together an eblock for this encryption */
162 krb5_use_cstype(&eblock, etype);
163 request.authenticator.etype = etype;
164 request.authenticator.kvno = 0; /* XXX user set? */
165 request.authenticator.ciphertext.length =
166 krb5_encrypt_size(scratch->length, eblock.crypto_entry);
167 /* add padding area, and zero it */
168 if (!(scratch->data = realloc(scratch->data,
169 request.authenticator.ciphertext.length))) {
170 /* may destroy scratch->data */
175 memset(scratch->data + scratch->length, 0,
176 request.authenticator.ciphertext.length - scratch->length);
177 if (!(request.authenticator.ciphertext.data =
178 malloc(request.authenticator.ciphertext.length))) {
183 #define cleanup_encpart() {\
184 (void) memset(request.authenticator.ciphertext.data, 0,\
185 request.authenticator.ciphertext.length); \
186 free(request.authenticator.ciphertext.data); \
187 request.authenticator.ciphertext.length = 0; \
188 request.authenticator.ciphertext.data = 0;}
190 /* do any necessary key pre-processing */
191 if (retval = krb5_process_key(&eblock, &creds->keyblock)) {
195 #define cleanup_prockey() {(void) krb5_finish_key(&eblock);}
197 /* call the encryption routine */
198 if (retval = krb5_encrypt((krb5_pointer) scratch->data,
199 (krb5_pointer) request.authenticator.ciphertext.data,
200 scratch->length, &eblock, 0)) {
204 /* authenticator now assembled-- do some cleanup */
207 if (retval = krb5_finish_key(&eblock)) {
212 if (!(retval = encode_krb5_ap_req(&request, &toutbuf))) {
233 static krb5_error_code
234 generate_authenticator(authent, creds, cksum, key, seq_number)
235 krb5_authenticator *authent;
236 const krb5_creds *creds;
237 const krb5_checksum *cksum;
239 krb5_int32 seq_number;
241 authent->client = creds->client;
242 authent->checksum = (krb5_checksum *)cksum;
243 authent->subkey = key;
244 authent->seq_number = seq_number;
246 return(krb5_us_timeofday(&authent->ctime, &authent->cusec));