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_authenticator *, krb5_principal,
71 const krb5_checksum *, krb5_keyblock *,
72 krb5_int32, krb5_authdata ** ));
75 krb5_mk_req_extended(ap_req_options, checksum, kdc_options,
76 sequence, newkey, ccache, creds, authentp, outbuf)
77 const krb5_flags ap_req_options;
78 const krb5_checksum *checksum;
79 const krb5_flags kdc_options;
81 krb5_keyblock **newkey;
84 krb5_authenticator *authentp;
87 krb5_error_code retval;
89 krb5_authenticator authent;
92 krb5_encrypt_block eblock;
95 if ((ap_req_options & AP_OPTS_USE_SESSION_KEY) &&
96 !creds->ticket.length)
97 return(KRB5_NO_TKT_SUPPLIED);
99 if (!creds->ticket.length) {
101 if (retval = krb5_get_credentials(kdc_options,
106 /* verify a valid etype is available */
107 if (!valid_keytype(creds->keyblock.keytype))
108 return KRB5_PROG_KEYTYPE_NOSUPP;
110 if (creds->keyblock.etype == ETYPE_UNKNOWN)
111 etype = krb5_keytype_array[creds->keyblock.keytype]->system->proto_enctype;
113 etype = creds->keyblock.etype;
115 if (!valid_etype(etype))
116 return KRB5_PROG_ETYPE_NOSUPP;
118 request.ap_options = ap_req_options;
119 /* we need a native ticket */
120 if (retval = decode_krb5_ticket(&creds->ticket, &request.ticket))
123 #define cleanup_ticket() krb5_free_ticket(request.ticket)
125 if (retval = krb5_generate_subkey(&creds->keyblock, newkey)) {
130 #define cleanup_key() {if (newkey) krb5_free_keyblock(*newkey);}
131 if (retval = krb5_generate_authenticator(&authent, creds->client, checksum,
132 newkey ? *newkey : 0,
133 sequence, creds->authdata)) {
139 /* encode the authenticator */
140 retval = encode_krb5_authenticator(&authent, &scratch);
147 /* Null out these fields, to prevent pointer sharing problems;
148 * they were supplied by the caller
150 authent.client = NULL;
151 authent.checksum = NULL;
152 authent.authorization_data = NULL;
156 krb5_free_authenticator_contents(&authent);
158 #define cleanup_scratch() { (void) memset(scratch->data, 0, scratch->length); \
159 krb5_free_data(scratch); }
161 /* put together an eblock for this encryption */
163 krb5_use_cstype(&eblock, etype);
164 request.authenticator.etype = etype;
165 request.authenticator.kvno = 0; /* XXX user set? */
166 request.authenticator.ciphertext.length =
167 krb5_encrypt_size(scratch->length, eblock.crypto_entry);
168 /* add padding area, and zero it */
169 if (!(scratch->data = realloc(scratch->data,
170 request.authenticator.ciphertext.length))) {
171 /* may destroy scratch->data */
176 memset(scratch->data + scratch->length, 0,
177 request.authenticator.ciphertext.length - scratch->length);
178 if (!(request.authenticator.ciphertext.data =
179 malloc(request.authenticator.ciphertext.length))) {
184 #define cleanup_encpart() {\
185 (void) memset(request.authenticator.ciphertext.data, 0,\
186 request.authenticator.ciphertext.length); \
187 free(request.authenticator.ciphertext.data); \
188 request.authenticator.ciphertext.length = 0; \
189 request.authenticator.ciphertext.data = 0;}
191 /* do any necessary key pre-processing */
192 if (retval = krb5_process_key(&eblock, &creds->keyblock)) {
196 #define cleanup_prockey() {(void) krb5_finish_key(&eblock);}
198 /* call the encryption routine */
199 if (retval = krb5_encrypt((krb5_pointer) scratch->data,
200 (krb5_pointer) request.authenticator.ciphertext.data,
201 scratch->length, &eblock, 0)) {
205 /* authenticator now assembled-- do some cleanup */
208 if (retval = krb5_finish_key(&eblock)) {
213 if (!(retval = encode_krb5_ap_req(&request, &toutbuf))) {
234 static krb5_error_code
235 krb5_generate_authenticator(authent, client, cksum, key, seq_number, authorization)
236 krb5_authenticator *authent;
237 krb5_principal client;
238 const krb5_checksum *cksum;
240 krb5_int32 seq_number;
241 krb5_authdata **authorization;
243 krb5_error_code retval;
245 authent->client = client;
246 authent->checksum = (krb5_checksum *)cksum;
248 retval = krb5_copy_keyblock(key, &authent->subkey);
253 authent->subkey = key;
254 authent->seq_number = seq_number;
255 authent->authorization_data = authorization;
257 return(krb5_us_timeofday(&authent->ctime, &authent->cusec));