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().
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 etype = krb5_keytype_array[creds->keyblock.keytype]->system->proto_enctype;
112 if (!valid_etype(etype))
113 return KRB5_PROG_ETYPE_NOSUPP;
115 request.ap_options = ap_req_options;
116 /* we need a native ticket */
117 if (retval = decode_krb5_ticket(&creds->ticket, &request.ticket))
120 #define cleanup_ticket() krb5_free_ticket(request.ticket)
122 if (retval = krb5_generate_subkey(&creds->keyblock, newkey)) {
127 #define cleanup_key() {if (newkey) krb5_free_keyblock(*newkey);}
128 if (retval = krb5_generate_authenticator(&authent, creds->client, checksum,
129 newkey ? *newkey : 0,
130 sequence, creds->authdata)) {
137 /* Null out these fields, to prevent pointer sharing problems
138 * The caller won't need these fields anyway, since they were
139 * supplied by the caller
141 authentp->client = NULL;
142 authentp->checksum = NULL;
144 /* encode it before encrypting */
145 retval = encode_krb5_authenticator(&authent, &scratch);
152 #define cleanup_scratch() { (void) memset(scratch->data, 0, scratch->length); \
153 krb5_free_data(scratch); }
155 /* put together an eblock for this encryption */
157 krb5_use_cstype(&eblock, etype);
158 request.authenticator.etype = etype;
159 request.authenticator.kvno = 0; /* XXX user set? */
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 */
170 memset(scratch->data + scratch->length, 0,
171 request.authenticator.ciphertext.length - scratch->length);
172 if (!(request.authenticator.ciphertext.data =
173 malloc(request.authenticator.ciphertext.length))) {
178 #define cleanup_encpart() {\
179 (void) memset(request.authenticator.ciphertext.data, 0,\
180 request.authenticator.ciphertext.length); \
181 free(request.authenticator.ciphertext.data); \
182 request.authenticator.ciphertext.length = 0; \
183 request.authenticator.ciphertext.data = 0;}
185 /* do any necessary key pre-processing */
186 if (retval = krb5_process_key(&eblock, &creds->keyblock)) {
190 #define cleanup_prockey() {(void) krb5_finish_key(&eblock);}
192 /* call the encryption routine */
193 if (retval = krb5_encrypt((krb5_pointer) scratch->data,
194 (krb5_pointer) request.authenticator.ciphertext.data,
195 scratch->length, &eblock, 0)) {
199 /* authenticator now assembled-- do some cleanup */
202 if (retval = krb5_finish_key(&eblock)) {
207 if (!(retval = encode_krb5_ap_req(&request, &toutbuf))) {
228 static krb5_error_code
229 krb5_generate_authenticator(authent, client, cksum, key, seq_number, authorization)
230 krb5_authenticator *authent;
231 krb5_principal client;
232 const krb5_checksum *cksum;
234 krb5_int32 seq_number;
235 krb5_authdata **authorization;
237 authent->client = client;
238 authent->checksum = (krb5_checksum *)cksum;
239 authent->subkey = key;
240 authent->seq_number = seq_number;
241 authent->authorization_data = authorization;
243 return(krb5_us_timeofday(&authent->ctime, &authent->cusec));