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. Furthermore if you modify this software you must label
20 * your software as modified software and not distribute it in such a
21 * fashion that it might be confused with the original M.I.T. software.
22 * M.I.T. makes no representations about the suitability of
23 * this software for any purpose. It is provided "as is" without express
24 * or implied warranty.
27 * krb5_mk_req_extended()
35 Formats a KRB_AP_REQ message into outbuf, with more complete options than
38 outbuf, ap_req_options, checksum, and ccache are used in the
39 same fashion as for krb5_mk_req.
41 creds is used to supply the credentials (ticket and session key) needed
44 if creds->ticket has no data (length == 0), then a ticket is obtained
45 from either the cache or the TGS, passing creds to krb5_get_credentials().
46 kdc_options specifies the options requested for the ticket to be used.
47 If a ticket with appropriate flags is not found in the cache, then these
48 options are passed on in a request to an appropriate KDC.
50 ap_req_options specifies the KRB_AP_REQ options desired.
52 if ap_req_options specifies AP_OPTS_USE_SESSION_KEY, then creds->ticket
53 must contain the appropriate ENC-TKT-IN-SKEY ticket.
55 checksum specifies the checksum to be used in the authenticator.
57 The outbuf buffer storage is allocated, and should be freed by the
60 On an error return, the credentials pointed to by creds might have been
61 augmented with additional fields from the obtained credentials; the entire
62 credentials should be released by calling krb5_free_creds().
67 static krb5_error_code
68 krb5_generate_authenticator PROTOTYPE((krb5_context,
69 krb5_authenticator *, krb5_principal,
70 const krb5_checksum *, krb5_keyblock *,
71 krb5_int32, krb5_authdata ** ));
73 KRB5_DLLIMP krb5_error_code KRB5_CALLCONV
74 krb5_mk_req_extended(context, auth_context, ap_req_options, in_data, in_creds,
77 krb5_auth_context FAR * auth_context;
78 const krb5_flags ap_req_options;
79 krb5_data FAR * in_data;
80 krb5_creds FAR * in_creds;
81 krb5_data FAR * outbuf;
83 krb5_error_code retval;
84 krb5_checksum checksum;
85 krb5_checksum *checksump = 0;
86 krb5_auth_context new_auth_context;
89 krb5_data *scratch = 0;
92 request.ap_options = ap_req_options & AP_OPTS_WIRE_MASK;
93 request.authenticator.ciphertext.data = 0;
96 if (!in_creds->ticket.length)
97 return(KRB5_NO_TKT_SUPPLIED);
99 /* we need a native ticket */
100 if ((retval = decode_krb5_ticket(&(in_creds)->ticket, &request.ticket)))
103 /* verify that the ticket is not expired */
104 if ((retval = krb5_validate_times(context, &in_creds->times)) != 0)
107 /* generate auth_context if needed */
108 if (*auth_context == NULL) {
109 if ((retval = krb5_auth_con_init(context, &new_auth_context)))
111 *auth_context = new_auth_context;
114 /* set auth context keyblock */
115 if ((retval = krb5_copy_keyblock(context, &in_creds->keyblock,
116 &((*auth_context)->keyblock))))
119 /* generate seq number if needed */
120 if ((((*auth_context)->auth_context_flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE)
121 || ((*auth_context)->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE))
122 && ((*auth_context)->local_seq_number == 0))
123 if ((retval = krb5_generate_seq_number(context, &in_creds->keyblock,
124 &(*auth_context)->local_seq_number)))
128 /* generate subkey if needed */
129 if ((ap_req_options & AP_OPTS_USE_SUBKEY)&&(!(*auth_context)->local_subkey))
130 if ((retval = krb5_generate_subkey(context, &(in_creds)->keyblock,
131 &(*auth_context)->local_subkey)))
135 if ((*auth_context)->req_cksumtype == 0x8003) {
136 /* XXX Special hack for GSSAPI */
137 checksum.checksum_type = 0x8003;
138 checksum.length = in_data->length;
139 checksum.contents = (krb5_octet *) in_data->data;
141 if ((retval = krb5_c_make_checksum(context,
142 (*auth_context)->req_cksumtype,
143 (*auth_context)->keyblock,
144 KRB5_KEYUSAGE_AP_REQ_AUTH_CKSUM,
145 in_data, &checksum)))
148 checksump = &checksum;
151 /* Generate authenticator */
152 if (((*auth_context)->authentp = (krb5_authenticator *)malloc(sizeof(
153 krb5_authenticator))) == NULL) {
158 if ((retval = krb5_generate_authenticator(context,
159 (*auth_context)->authentp,
160 (in_creds)->client, checksump,
161 (*auth_context)->local_subkey,
162 (*auth_context)->local_seq_number,
163 (in_creds)->authdata)))
166 /* encode the authenticator */
167 if ((retval = encode_krb5_authenticator((*auth_context)->authentp,
171 /* Null out these fields, to prevent pointer sharing problems;
172 * they were supplied by the caller
174 (*auth_context)->authentp->client = NULL;
175 (*auth_context)->authentp->checksum = NULL;
176 (*auth_context)->authentp->authorization_data = NULL;
178 /* call the encryption routine */
179 if ((retval = krb5_encrypt_helper(context, &in_creds->keyblock,
180 KRB5_KEYUSAGE_AP_REQ_AUTH,
181 scratch, &request.authenticator)))
184 if ((retval = encode_krb5_ap_req(&request, &toutbuf)))
186 #ifdef HAVE_C_STRUCTURE_ASSIGNMENT
189 memcpy(outbuf, toutbuf, sizeof(krb5_data));
195 if (checksump && checksump->checksum_type != 0x8003)
196 free(checksump->contents);
200 krb5_free_ticket(context, request.ticket);
201 if (request.authenticator.ciphertext.data) {
202 (void) memset(request.authenticator.ciphertext.data, 0,
203 request.authenticator.ciphertext.length);
204 free(request.authenticator.ciphertext.data);
207 memset(scratch->data, 0, scratch->length);
208 krb5_xfree(scratch->data);
214 static krb5_error_code
215 krb5_generate_authenticator(context, authent, client, cksum, key, seq_number, authorization)
216 krb5_context context;
217 krb5_authenticator *authent;
218 krb5_principal client;
219 const krb5_checksum *cksum;
221 krb5_int32 seq_number;
222 krb5_authdata **authorization;
224 krb5_error_code retval;
226 authent->client = client;
227 authent->checksum = (krb5_checksum *)cksum;
229 retval = krb5_copy_keyblock(context, key, &authent->subkey);
234 authent->seq_number = seq_number;
235 authent->authorization_data = authorization;
237 return(krb5_us_timeofday(context, &authent->ctime, &authent->cusec));