1*7934SMark.Phalan@Sun.COM /*
2*7934SMark.Phalan@Sun.COM * COPYRIGHT (C) 2006,2007
3*7934SMark.Phalan@Sun.COM * THE REGENTS OF THE UNIVERSITY OF MICHIGAN
4*7934SMark.Phalan@Sun.COM * ALL RIGHTS RESERVED
5*7934SMark.Phalan@Sun.COM *
6*7934SMark.Phalan@Sun.COM * Permission is granted to use, copy, create derivative works
7*7934SMark.Phalan@Sun.COM * and redistribute this software and such derivative works
8*7934SMark.Phalan@Sun.COM * for any purpose, so long as the name of The University of
9*7934SMark.Phalan@Sun.COM * Michigan is not used in any advertising or publicity
10*7934SMark.Phalan@Sun.COM * pertaining to the use of distribution of this software
11*7934SMark.Phalan@Sun.COM * without specific, written prior authorization. If the
12*7934SMark.Phalan@Sun.COM * above copyright notice or any other identification of the
13*7934SMark.Phalan@Sun.COM * University of Michigan is included in any copy of any
14*7934SMark.Phalan@Sun.COM * portion of this software, then the disclaimer below must
15*7934SMark.Phalan@Sun.COM * also be included.
16*7934SMark.Phalan@Sun.COM *
17*7934SMark.Phalan@Sun.COM * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION
18*7934SMark.Phalan@Sun.COM * FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY
19*7934SMark.Phalan@Sun.COM * PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF
20*7934SMark.Phalan@Sun.COM * MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
21*7934SMark.Phalan@Sun.COM * WITHOUT LIMITATION THE IMPLIED WARRANTIES OF
22*7934SMark.Phalan@Sun.COM * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
23*7934SMark.Phalan@Sun.COM * REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE
24*7934SMark.Phalan@Sun.COM * FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR
25*7934SMark.Phalan@Sun.COM * CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING
26*7934SMark.Phalan@Sun.COM * OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN
27*7934SMark.Phalan@Sun.COM * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF
28*7934SMark.Phalan@Sun.COM * SUCH DAMAGES.
29*7934SMark.Phalan@Sun.COM */
30*7934SMark.Phalan@Sun.COM
31*7934SMark.Phalan@Sun.COM #include <stdio.h>
32*7934SMark.Phalan@Sun.COM #include <stdlib.h>
33*7934SMark.Phalan@Sun.COM #include <errno.h>
34*7934SMark.Phalan@Sun.COM #include <string.h>
35*7934SMark.Phalan@Sun.COM
36*7934SMark.Phalan@Sun.COM #include "pkinit.h"
37*7934SMark.Phalan@Sun.COM
38*7934SMark.Phalan@Sun.COM static krb5_error_code
39*7934SMark.Phalan@Sun.COM pkinit_server_get_edata(krb5_context context,
40*7934SMark.Phalan@Sun.COM krb5_kdc_req * request,
41*7934SMark.Phalan@Sun.COM struct _krb5_db_entry_new * client,
42*7934SMark.Phalan@Sun.COM struct _krb5_db_entry_new * server,
43*7934SMark.Phalan@Sun.COM preauth_get_entry_data_proc server_get_entry_data,
44*7934SMark.Phalan@Sun.COM void *pa_plugin_context,
45*7934SMark.Phalan@Sun.COM krb5_pa_data * data);
46*7934SMark.Phalan@Sun.COM
47*7934SMark.Phalan@Sun.COM static krb5_error_code
48*7934SMark.Phalan@Sun.COM pkinit_server_verify_padata(krb5_context context,
49*7934SMark.Phalan@Sun.COM struct _krb5_db_entry_new * client,
50*7934SMark.Phalan@Sun.COM krb5_data *req_pkt,
51*7934SMark.Phalan@Sun.COM krb5_kdc_req * request,
52*7934SMark.Phalan@Sun.COM krb5_enc_tkt_part * enc_tkt_reply,
53*7934SMark.Phalan@Sun.COM krb5_pa_data * data,
54*7934SMark.Phalan@Sun.COM preauth_get_entry_data_proc server_get_entry_data,
55*7934SMark.Phalan@Sun.COM void *pa_plugin_context,
56*7934SMark.Phalan@Sun.COM void **pa_request_context,
57*7934SMark.Phalan@Sun.COM krb5_data **e_data,
58*7934SMark.Phalan@Sun.COM krb5_authdata ***authz_data);
59*7934SMark.Phalan@Sun.COM
60*7934SMark.Phalan@Sun.COM static krb5_error_code
61*7934SMark.Phalan@Sun.COM pkinit_server_return_padata(krb5_context context,
62*7934SMark.Phalan@Sun.COM krb5_pa_data * padata,
63*7934SMark.Phalan@Sun.COM struct _krb5_db_entry_new * client,
64*7934SMark.Phalan@Sun.COM krb5_data *req_pkt,
65*7934SMark.Phalan@Sun.COM krb5_kdc_req * request,
66*7934SMark.Phalan@Sun.COM krb5_kdc_rep * reply,
67*7934SMark.Phalan@Sun.COM struct _krb5_key_data * client_key,
68*7934SMark.Phalan@Sun.COM krb5_keyblock * encrypting_key,
69*7934SMark.Phalan@Sun.COM krb5_pa_data ** send_pa,
70*7934SMark.Phalan@Sun.COM preauth_get_entry_data_proc server_get_entry_data,
71*7934SMark.Phalan@Sun.COM void *pa_plugin_context,
72*7934SMark.Phalan@Sun.COM void **pa_request_context);
73*7934SMark.Phalan@Sun.COM
74*7934SMark.Phalan@Sun.COM static int pkinit_server_get_flags
75*7934SMark.Phalan@Sun.COM (krb5_context kcontext, krb5_preauthtype patype);
76*7934SMark.Phalan@Sun.COM
77*7934SMark.Phalan@Sun.COM static krb5_error_code pkinit_init_kdc_req_context
78*7934SMark.Phalan@Sun.COM (krb5_context, void **blob);
79*7934SMark.Phalan@Sun.COM
80*7934SMark.Phalan@Sun.COM static void pkinit_fini_kdc_req_context
81*7934SMark.Phalan@Sun.COM (krb5_context context, void *blob);
82*7934SMark.Phalan@Sun.COM
83*7934SMark.Phalan@Sun.COM static int pkinit_server_plugin_init_realm
84*7934SMark.Phalan@Sun.COM (krb5_context context, const char *realmname,
85*7934SMark.Phalan@Sun.COM pkinit_kdc_context *pplgctx);
86*7934SMark.Phalan@Sun.COM
87*7934SMark.Phalan@Sun.COM static void pkinit_server_plugin_fini_realm
88*7934SMark.Phalan@Sun.COM (krb5_context context, pkinit_kdc_context plgctx);
89*7934SMark.Phalan@Sun.COM
90*7934SMark.Phalan@Sun.COM static int pkinit_server_plugin_init
91*7934SMark.Phalan@Sun.COM (krb5_context context, void **blob, const char **realmnames);
92*7934SMark.Phalan@Sun.COM
93*7934SMark.Phalan@Sun.COM static void pkinit_server_plugin_fini
94*7934SMark.Phalan@Sun.COM (krb5_context context, void *blob);
95*7934SMark.Phalan@Sun.COM
96*7934SMark.Phalan@Sun.COM static pkinit_kdc_context pkinit_find_realm_context
97*7934SMark.Phalan@Sun.COM (krb5_context context, void *pa_plugin_context, krb5_principal princ);
98*7934SMark.Phalan@Sun.COM
99*7934SMark.Phalan@Sun.COM static krb5_error_code
pkinit_create_edata(krb5_context context,pkinit_plg_crypto_context plg_cryptoctx,pkinit_req_crypto_context req_cryptoctx,pkinit_identity_crypto_context id_cryptoctx,pkinit_plg_opts * opts,krb5_error_code err_code,krb5_data ** e_data)100*7934SMark.Phalan@Sun.COM pkinit_create_edata(krb5_context context,
101*7934SMark.Phalan@Sun.COM pkinit_plg_crypto_context plg_cryptoctx,
102*7934SMark.Phalan@Sun.COM pkinit_req_crypto_context req_cryptoctx,
103*7934SMark.Phalan@Sun.COM pkinit_identity_crypto_context id_cryptoctx,
104*7934SMark.Phalan@Sun.COM pkinit_plg_opts *opts,
105*7934SMark.Phalan@Sun.COM krb5_error_code err_code,
106*7934SMark.Phalan@Sun.COM krb5_data **e_data)
107*7934SMark.Phalan@Sun.COM {
108*7934SMark.Phalan@Sun.COM krb5_error_code retval = KRB5KRB_ERR_GENERIC;
109*7934SMark.Phalan@Sun.COM
110*7934SMark.Phalan@Sun.COM pkiDebug("pkinit_create_edata: creating edata for error %d (%s)\n",
111*7934SMark.Phalan@Sun.COM err_code, error_message(err_code));
112*7934SMark.Phalan@Sun.COM switch(err_code) {
113*7934SMark.Phalan@Sun.COM case KRB5KDC_ERR_CANT_VERIFY_CERTIFICATE:
114*7934SMark.Phalan@Sun.COM retval = pkinit_create_td_trusted_certifiers(context,
115*7934SMark.Phalan@Sun.COM plg_cryptoctx, req_cryptoctx, id_cryptoctx, e_data);
116*7934SMark.Phalan@Sun.COM break;
117*7934SMark.Phalan@Sun.COM case KRB5KDC_ERR_DH_KEY_PARAMETERS_NOT_ACCEPTED:
118*7934SMark.Phalan@Sun.COM retval = pkinit_create_td_dh_parameters(context, plg_cryptoctx,
119*7934SMark.Phalan@Sun.COM req_cryptoctx, id_cryptoctx, opts, e_data);
120*7934SMark.Phalan@Sun.COM break;
121*7934SMark.Phalan@Sun.COM case KRB5KDC_ERR_INVALID_CERTIFICATE:
122*7934SMark.Phalan@Sun.COM case KRB5KDC_ERR_REVOKED_CERTIFICATE:
123*7934SMark.Phalan@Sun.COM retval = pkinit_create_td_invalid_certificate(context,
124*7934SMark.Phalan@Sun.COM plg_cryptoctx, req_cryptoctx, id_cryptoctx, e_data);
125*7934SMark.Phalan@Sun.COM break;
126*7934SMark.Phalan@Sun.COM default:
127*7934SMark.Phalan@Sun.COM pkiDebug("no edata needed for error %d (%s)\n",
128*7934SMark.Phalan@Sun.COM err_code, error_message(err_code));
129*7934SMark.Phalan@Sun.COM retval = 0;
130*7934SMark.Phalan@Sun.COM goto cleanup;
131*7934SMark.Phalan@Sun.COM }
132*7934SMark.Phalan@Sun.COM
133*7934SMark.Phalan@Sun.COM cleanup:
134*7934SMark.Phalan@Sun.COM
135*7934SMark.Phalan@Sun.COM return retval;
136*7934SMark.Phalan@Sun.COM }
137*7934SMark.Phalan@Sun.COM
138*7934SMark.Phalan@Sun.COM /* ARGSUSED */
139*7934SMark.Phalan@Sun.COM static krb5_error_code
pkinit_server_get_edata(krb5_context context,krb5_kdc_req * request,struct _krb5_db_entry_new * client,struct _krb5_db_entry_new * server,preauth_get_entry_data_proc server_get_entry_data,void * pa_plugin_context,krb5_pa_data * data)140*7934SMark.Phalan@Sun.COM pkinit_server_get_edata(krb5_context context,
141*7934SMark.Phalan@Sun.COM krb5_kdc_req * request,
142*7934SMark.Phalan@Sun.COM struct _krb5_db_entry_new * client,
143*7934SMark.Phalan@Sun.COM struct _krb5_db_entry_new * server,
144*7934SMark.Phalan@Sun.COM preauth_get_entry_data_proc server_get_entry_data,
145*7934SMark.Phalan@Sun.COM void *pa_plugin_context,
146*7934SMark.Phalan@Sun.COM krb5_pa_data * data)
147*7934SMark.Phalan@Sun.COM {
148*7934SMark.Phalan@Sun.COM krb5_error_code retval = 0;
149*7934SMark.Phalan@Sun.COM pkinit_kdc_context plgctx = NULL;
150*7934SMark.Phalan@Sun.COM
151*7934SMark.Phalan@Sun.COM pkiDebug("pkinit_server_get_edata: entered!\n");
152*7934SMark.Phalan@Sun.COM
153*7934SMark.Phalan@Sun.COM /*
154*7934SMark.Phalan@Sun.COM * If we don't have a realm context for the given realm,
155*7934SMark.Phalan@Sun.COM * don't tell the client that we support pkinit!
156*7934SMark.Phalan@Sun.COM */
157*7934SMark.Phalan@Sun.COM plgctx = pkinit_find_realm_context(context, pa_plugin_context,
158*7934SMark.Phalan@Sun.COM request->server);
159*7934SMark.Phalan@Sun.COM if (plgctx == NULL)
160*7934SMark.Phalan@Sun.COM retval = EINVAL;
161*7934SMark.Phalan@Sun.COM
162*7934SMark.Phalan@Sun.COM return retval;
163*7934SMark.Phalan@Sun.COM }
164*7934SMark.Phalan@Sun.COM
165*7934SMark.Phalan@Sun.COM static krb5_error_code
verify_client_san(krb5_context context,pkinit_kdc_context plgctx,pkinit_kdc_req_context reqctx,krb5_principal client,int * valid_san)166*7934SMark.Phalan@Sun.COM verify_client_san(krb5_context context,
167*7934SMark.Phalan@Sun.COM pkinit_kdc_context plgctx,
168*7934SMark.Phalan@Sun.COM pkinit_kdc_req_context reqctx,
169*7934SMark.Phalan@Sun.COM krb5_principal client,
170*7934SMark.Phalan@Sun.COM int *valid_san)
171*7934SMark.Phalan@Sun.COM {
172*7934SMark.Phalan@Sun.COM krb5_error_code retval;
173*7934SMark.Phalan@Sun.COM krb5_principal *princs = NULL;
174*7934SMark.Phalan@Sun.COM krb5_principal *upns = NULL;
175*7934SMark.Phalan@Sun.COM int i;
176*7934SMark.Phalan@Sun.COM #ifdef DEBUG_SAN_INFO
177*7934SMark.Phalan@Sun.COM char *client_string = NULL, *san_string;
178*7934SMark.Phalan@Sun.COM #endif
179*7934SMark.Phalan@Sun.COM
180*7934SMark.Phalan@Sun.COM retval = crypto_retrieve_cert_sans(context, plgctx->cryptoctx,
181*7934SMark.Phalan@Sun.COM reqctx->cryptoctx, plgctx->idctx,
182*7934SMark.Phalan@Sun.COM &princs,
183*7934SMark.Phalan@Sun.COM plgctx->opts->allow_upn ? &upns : NULL,
184*7934SMark.Phalan@Sun.COM NULL);
185*7934SMark.Phalan@Sun.COM if (retval) {
186*7934SMark.Phalan@Sun.COM pkiDebug("%s: error from retrieve_certificate_sans()\n", __FUNCTION__);
187*7934SMark.Phalan@Sun.COM retval = KRB5KDC_ERR_CLIENT_NAME_MISMATCH;
188*7934SMark.Phalan@Sun.COM goto out;
189*7934SMark.Phalan@Sun.COM }
190*7934SMark.Phalan@Sun.COM /* XXX Verify this is consistent with client side XXX */
191*7934SMark.Phalan@Sun.COM #if 0
192*7934SMark.Phalan@Sun.COM retval = call_san_checking_plugins(context, plgctx, reqctx, princs,
193*7934SMark.Phalan@Sun.COM upns, NULL, &plugin_decision, &ignore);
194*7934SMark.Phalan@Sun.COM pkiDebug("%s: call_san_checking_plugins() returned retval %d\n",
195*7934SMark.Phalan@Sun.COM __FUNCTION__);
196*7934SMark.Phalan@Sun.COM if (retval) {
197*7934SMark.Phalan@Sun.COM retval = KRB5KDC_ERR_CLIENT_NAME_MISMATCH;
198*7934SMark.Phalan@Sun.COM goto cleanup;
199*7934SMark.Phalan@Sun.COM }
200*7934SMark.Phalan@Sun.COM pkiDebug("%s: call_san_checking_plugins() returned decision %d\n",
201*7934SMark.Phalan@Sun.COM __FUNCTION__, plugin_decision);
202*7934SMark.Phalan@Sun.COM if (plugin_decision != NO_DECISION) {
203*7934SMark.Phalan@Sun.COM retval = plugin_decision;
204*7934SMark.Phalan@Sun.COM goto out;
205*7934SMark.Phalan@Sun.COM }
206*7934SMark.Phalan@Sun.COM #endif
207*7934SMark.Phalan@Sun.COM
208*7934SMark.Phalan@Sun.COM #ifdef DEBUG_SAN_INFO
209*7934SMark.Phalan@Sun.COM krb5_unparse_name(context, client, &client_string);
210*7934SMark.Phalan@Sun.COM #endif
211*7934SMark.Phalan@Sun.COM pkiDebug("%s: Checking pkinit sans\n", __FUNCTION__);
212*7934SMark.Phalan@Sun.COM for (i = 0; princs != NULL && princs[i] != NULL; i++) {
213*7934SMark.Phalan@Sun.COM #ifdef DEBUG_SAN_INFO
214*7934SMark.Phalan@Sun.COM krb5_unparse_name(context, princs[i], &san_string);
215*7934SMark.Phalan@Sun.COM pkiDebug("%s: Comparing client '%s' to pkinit san value '%s'\n",
216*7934SMark.Phalan@Sun.COM __FUNCTION__, client_string, san_string);
217*7934SMark.Phalan@Sun.COM krb5_free_unparsed_name(context, san_string);
218*7934SMark.Phalan@Sun.COM #endif
219*7934SMark.Phalan@Sun.COM if (krb5_principal_compare(context, princs[i], client)) {
220*7934SMark.Phalan@Sun.COM pkiDebug("%s: pkinit san match found\n", __FUNCTION__);
221*7934SMark.Phalan@Sun.COM *valid_san = 1;
222*7934SMark.Phalan@Sun.COM retval = 0;
223*7934SMark.Phalan@Sun.COM goto out;
224*7934SMark.Phalan@Sun.COM }
225*7934SMark.Phalan@Sun.COM }
226*7934SMark.Phalan@Sun.COM pkiDebug("%s: no pkinit san match found\n", __FUNCTION__);
227*7934SMark.Phalan@Sun.COM /*
228*7934SMark.Phalan@Sun.COM * XXX if cert has names but none match, should we
229*7934SMark.Phalan@Sun.COM * be returning KRB5KDC_ERR_CLIENT_NAME_MISMATCH here?
230*7934SMark.Phalan@Sun.COM */
231*7934SMark.Phalan@Sun.COM
232*7934SMark.Phalan@Sun.COM if (upns == NULL) {
233*7934SMark.Phalan@Sun.COM pkiDebug("%s: no upn sans (or we wouldn't accept them anyway)\n",
234*7934SMark.Phalan@Sun.COM __FUNCTION__);
235*7934SMark.Phalan@Sun.COM retval = KRB5KDC_ERR_CLIENT_NAME_MISMATCH;
236*7934SMark.Phalan@Sun.COM goto out;
237*7934SMark.Phalan@Sun.COM }
238*7934SMark.Phalan@Sun.COM
239*7934SMark.Phalan@Sun.COM pkiDebug("%s: Checking upn sans\n", __FUNCTION__);
240*7934SMark.Phalan@Sun.COM for (i = 0; upns[i] != NULL; i++) {
241*7934SMark.Phalan@Sun.COM #ifdef DEBUG_SAN_INFO
242*7934SMark.Phalan@Sun.COM krb5_unparse_name(context, upns[i], &san_string);
243*7934SMark.Phalan@Sun.COM pkiDebug("%s: Comparing client '%s' to upn san value '%s'\n",
244*7934SMark.Phalan@Sun.COM __FUNCTION__, client_string, san_string);
245*7934SMark.Phalan@Sun.COM krb5_free_unparsed_name(context, san_string);
246*7934SMark.Phalan@Sun.COM #endif
247*7934SMark.Phalan@Sun.COM if (krb5_principal_compare(context, upns[i], client)) {
248*7934SMark.Phalan@Sun.COM pkiDebug("%s: upn san match found\n", __FUNCTION__);
249*7934SMark.Phalan@Sun.COM *valid_san = 1;
250*7934SMark.Phalan@Sun.COM retval = 0;
251*7934SMark.Phalan@Sun.COM goto out;
252*7934SMark.Phalan@Sun.COM }
253*7934SMark.Phalan@Sun.COM }
254*7934SMark.Phalan@Sun.COM pkiDebug("%s: no upn san match found\n", __FUNCTION__);
255*7934SMark.Phalan@Sun.COM
256*7934SMark.Phalan@Sun.COM /* We found no match */
257*7934SMark.Phalan@Sun.COM if (princs != NULL || upns != NULL) {
258*7934SMark.Phalan@Sun.COM *valid_san = 0;
259*7934SMark.Phalan@Sun.COM /* XXX ??? If there was one or more name in the cert, but
260*7934SMark.Phalan@Sun.COM * none matched the client name, then return mismatch? */
261*7934SMark.Phalan@Sun.COM retval = KRB5KDC_ERR_CLIENT_NAME_MISMATCH;
262*7934SMark.Phalan@Sun.COM }
263*7934SMark.Phalan@Sun.COM retval = 0;
264*7934SMark.Phalan@Sun.COM
265*7934SMark.Phalan@Sun.COM out:
266*7934SMark.Phalan@Sun.COM if (princs != NULL) {
267*7934SMark.Phalan@Sun.COM for (i = 0; princs[i] != NULL; i++)
268*7934SMark.Phalan@Sun.COM krb5_free_principal(context, princs[i]);
269*7934SMark.Phalan@Sun.COM free(princs);
270*7934SMark.Phalan@Sun.COM }
271*7934SMark.Phalan@Sun.COM if (upns != NULL) {
272*7934SMark.Phalan@Sun.COM for (i = 0; upns[i] != NULL; i++)
273*7934SMark.Phalan@Sun.COM krb5_free_principal(context, upns[i]);
274*7934SMark.Phalan@Sun.COM free(upns);
275*7934SMark.Phalan@Sun.COM }
276*7934SMark.Phalan@Sun.COM #ifdef DEBUG_SAN_INFO
277*7934SMark.Phalan@Sun.COM if (client_string != NULL)
278*7934SMark.Phalan@Sun.COM krb5_free_unparsed_name(context, client_string);
279*7934SMark.Phalan@Sun.COM #endif
280*7934SMark.Phalan@Sun.COM pkiDebug("%s: returning retval %d, valid_san %d\n",
281*7934SMark.Phalan@Sun.COM __FUNCTION__, retval, *valid_san);
282*7934SMark.Phalan@Sun.COM return retval;
283*7934SMark.Phalan@Sun.COM }
284*7934SMark.Phalan@Sun.COM
285*7934SMark.Phalan@Sun.COM static krb5_error_code
verify_client_eku(krb5_context context,pkinit_kdc_context plgctx,pkinit_kdc_req_context reqctx,int * eku_accepted)286*7934SMark.Phalan@Sun.COM verify_client_eku(krb5_context context,
287*7934SMark.Phalan@Sun.COM pkinit_kdc_context plgctx,
288*7934SMark.Phalan@Sun.COM pkinit_kdc_req_context reqctx,
289*7934SMark.Phalan@Sun.COM int *eku_accepted)
290*7934SMark.Phalan@Sun.COM {
291*7934SMark.Phalan@Sun.COM krb5_error_code retval;
292*7934SMark.Phalan@Sun.COM
293*7934SMark.Phalan@Sun.COM *eku_accepted = 0;
294*7934SMark.Phalan@Sun.COM
295*7934SMark.Phalan@Sun.COM if (plgctx->opts->require_eku == 0) {
296*7934SMark.Phalan@Sun.COM pkiDebug("%s: configuration requests no EKU checking\n", __FUNCTION__);
297*7934SMark.Phalan@Sun.COM *eku_accepted = 1;
298*7934SMark.Phalan@Sun.COM retval = 0;
299*7934SMark.Phalan@Sun.COM goto out;
300*7934SMark.Phalan@Sun.COM }
301*7934SMark.Phalan@Sun.COM
302*7934SMark.Phalan@Sun.COM retval = crypto_check_cert_eku(context, plgctx->cryptoctx,
303*7934SMark.Phalan@Sun.COM reqctx->cryptoctx, plgctx->idctx,
304*7934SMark.Phalan@Sun.COM 0, /* kdc cert */
305*7934SMark.Phalan@Sun.COM plgctx->opts->accept_secondary_eku,
306*7934SMark.Phalan@Sun.COM eku_accepted);
307*7934SMark.Phalan@Sun.COM if (retval) {
308*7934SMark.Phalan@Sun.COM pkiDebug("%s: Error from crypto_check_cert_eku %d (%s)\n",
309*7934SMark.Phalan@Sun.COM __FUNCTION__, retval, error_message(retval));
310*7934SMark.Phalan@Sun.COM goto out;
311*7934SMark.Phalan@Sun.COM }
312*7934SMark.Phalan@Sun.COM
313*7934SMark.Phalan@Sun.COM out:
314*7934SMark.Phalan@Sun.COM pkiDebug("%s: returning retval %d, eku_accepted %d\n",
315*7934SMark.Phalan@Sun.COM __FUNCTION__, retval, *eku_accepted);
316*7934SMark.Phalan@Sun.COM return retval;
317*7934SMark.Phalan@Sun.COM }
318*7934SMark.Phalan@Sun.COM
319*7934SMark.Phalan@Sun.COM /* ARGSUSED */
320*7934SMark.Phalan@Sun.COM static krb5_error_code
pkinit_server_verify_padata(krb5_context context,struct _krb5_db_entry_new * client,krb5_data * req_pkt,krb5_kdc_req * request,krb5_enc_tkt_part * enc_tkt_reply,krb5_pa_data * data,preauth_get_entry_data_proc server_get_entry_data,void * pa_plugin_context,void ** pa_request_context,krb5_data ** e_data,krb5_authdata *** authz_data)321*7934SMark.Phalan@Sun.COM pkinit_server_verify_padata(krb5_context context,
322*7934SMark.Phalan@Sun.COM struct _krb5_db_entry_new * client,
323*7934SMark.Phalan@Sun.COM krb5_data *req_pkt,
324*7934SMark.Phalan@Sun.COM krb5_kdc_req * request,
325*7934SMark.Phalan@Sun.COM krb5_enc_tkt_part * enc_tkt_reply,
326*7934SMark.Phalan@Sun.COM krb5_pa_data * data,
327*7934SMark.Phalan@Sun.COM preauth_get_entry_data_proc server_get_entry_data,
328*7934SMark.Phalan@Sun.COM void *pa_plugin_context,
329*7934SMark.Phalan@Sun.COM void **pa_request_context,
330*7934SMark.Phalan@Sun.COM krb5_data **e_data,
331*7934SMark.Phalan@Sun.COM krb5_authdata ***authz_data)
332*7934SMark.Phalan@Sun.COM {
333*7934SMark.Phalan@Sun.COM krb5_error_code retval = 0;
334*7934SMark.Phalan@Sun.COM krb5_octet_data authp_data = {0, 0, NULL}, krb5_authz = {0, 0, NULL};
335*7934SMark.Phalan@Sun.COM krb5_data *encoded_pkinit_authz_data = NULL;
336*7934SMark.Phalan@Sun.COM krb5_pa_pk_as_req *reqp = NULL;
337*7934SMark.Phalan@Sun.COM krb5_pa_pk_as_req_draft9 *reqp9 = NULL;
338*7934SMark.Phalan@Sun.COM krb5_auth_pack *auth_pack = NULL;
339*7934SMark.Phalan@Sun.COM krb5_auth_pack_draft9 *auth_pack9 = NULL;
340*7934SMark.Phalan@Sun.COM pkinit_kdc_context plgctx = NULL;
341*7934SMark.Phalan@Sun.COM pkinit_kdc_req_context reqctx;
342*7934SMark.Phalan@Sun.COM /* Solaris Kerberos: set but not used */
343*7934SMark.Phalan@Sun.COM #if 0
344*7934SMark.Phalan@Sun.COM krb5_preauthtype pa_type;
345*7934SMark.Phalan@Sun.COM #endif
346*7934SMark.Phalan@Sun.COM krb5_checksum cksum = {0, 0, 0, NULL};
347*7934SMark.Phalan@Sun.COM krb5_data *der_req = NULL;
348*7934SMark.Phalan@Sun.COM int valid_eku = 0, valid_san = 0;
349*7934SMark.Phalan@Sun.COM krb5_authdata **my_authz_data = NULL, *pkinit_authz_data = NULL;
350*7934SMark.Phalan@Sun.COM krb5_kdc_req *tmp_as_req = NULL;
351*7934SMark.Phalan@Sun.COM krb5_data k5data;
352*7934SMark.Phalan@Sun.COM
353*7934SMark.Phalan@Sun.COM pkiDebug("pkinit_verify_padata: entered!\n");
354*7934SMark.Phalan@Sun.COM /* Solaris Kerberos */
355*7934SMark.Phalan@Sun.COM if (data == NULL || data->length == 0 || data->contents == NULL)
356*7934SMark.Phalan@Sun.COM return 0;
357*7934SMark.Phalan@Sun.COM
358*7934SMark.Phalan@Sun.COM if (pa_plugin_context == NULL || e_data == NULL)
359*7934SMark.Phalan@Sun.COM return EINVAL;
360*7934SMark.Phalan@Sun.COM
361*7934SMark.Phalan@Sun.COM plgctx = pkinit_find_realm_context(context, pa_plugin_context,
362*7934SMark.Phalan@Sun.COM request->server);
363*7934SMark.Phalan@Sun.COM if (plgctx == NULL)
364*7934SMark.Phalan@Sun.COM return 0;
365*7934SMark.Phalan@Sun.COM
366*7934SMark.Phalan@Sun.COM #ifdef DEBUG_ASN1
367*7934SMark.Phalan@Sun.COM print_buffer_bin(data->contents, data->length, "/tmp/kdc_as_req");
368*7934SMark.Phalan@Sun.COM #endif
369*7934SMark.Phalan@Sun.COM /* create a per-request context */
370*7934SMark.Phalan@Sun.COM retval = pkinit_init_kdc_req_context(context, (void **)&reqctx);
371*7934SMark.Phalan@Sun.COM if (retval)
372*7934SMark.Phalan@Sun.COM goto cleanup;
373*7934SMark.Phalan@Sun.COM reqctx->pa_type = data->pa_type;
374*7934SMark.Phalan@Sun.COM
375*7934SMark.Phalan@Sun.COM PADATA_TO_KRB5DATA(data, &k5data);
376*7934SMark.Phalan@Sun.COM
377*7934SMark.Phalan@Sun.COM switch ((int)data->pa_type) {
378*7934SMark.Phalan@Sun.COM case KRB5_PADATA_PK_AS_REQ:
379*7934SMark.Phalan@Sun.COM pkiDebug("processing KRB5_PADATA_PK_AS_REQ\n");
380*7934SMark.Phalan@Sun.COM retval = k5int_decode_krb5_pa_pk_as_req(&k5data, &reqp);
381*7934SMark.Phalan@Sun.COM if (retval) {
382*7934SMark.Phalan@Sun.COM pkiDebug("decode_krb5_pa_pk_as_req failed\n");
383*7934SMark.Phalan@Sun.COM goto cleanup;
384*7934SMark.Phalan@Sun.COM }
385*7934SMark.Phalan@Sun.COM #ifdef DEBUG_ASN1
386*7934SMark.Phalan@Sun.COM print_buffer_bin(reqp->signedAuthPack.data,
387*7934SMark.Phalan@Sun.COM reqp->signedAuthPack.length,
388*7934SMark.Phalan@Sun.COM "/tmp/kdc_signed_data");
389*7934SMark.Phalan@Sun.COM #endif
390*7934SMark.Phalan@Sun.COM retval = cms_signeddata_verify(context, plgctx->cryptoctx,
391*7934SMark.Phalan@Sun.COM reqctx->cryptoctx, plgctx->idctx, CMS_SIGN_CLIENT,
392*7934SMark.Phalan@Sun.COM plgctx->opts->require_crl_checking,
393*7934SMark.Phalan@Sun.COM reqp->signedAuthPack.data, reqp->signedAuthPack.length,
394*7934SMark.Phalan@Sun.COM &authp_data.data, &authp_data.length, &krb5_authz.data,
395*7934SMark.Phalan@Sun.COM &krb5_authz.length);
396*7934SMark.Phalan@Sun.COM break;
397*7934SMark.Phalan@Sun.COM case KRB5_PADATA_PK_AS_REP_OLD:
398*7934SMark.Phalan@Sun.COM case KRB5_PADATA_PK_AS_REQ_OLD:
399*7934SMark.Phalan@Sun.COM pkiDebug("processing KRB5_PADATA_PK_AS_REQ_OLD\n");
400*7934SMark.Phalan@Sun.COM retval = k5int_decode_krb5_pa_pk_as_req_draft9(&k5data, &reqp9);
401*7934SMark.Phalan@Sun.COM if (retval) {
402*7934SMark.Phalan@Sun.COM pkiDebug("decode_krb5_pa_pk_as_req_draft9 failed\n");
403*7934SMark.Phalan@Sun.COM goto cleanup;
404*7934SMark.Phalan@Sun.COM }
405*7934SMark.Phalan@Sun.COM #ifdef DEBUG_ASN1
406*7934SMark.Phalan@Sun.COM print_buffer_bin(reqp9->signedAuthPack.data,
407*7934SMark.Phalan@Sun.COM reqp9->signedAuthPack.length,
408*7934SMark.Phalan@Sun.COM "/tmp/kdc_signed_data_draft9");
409*7934SMark.Phalan@Sun.COM #endif
410*7934SMark.Phalan@Sun.COM
411*7934SMark.Phalan@Sun.COM retval = cms_signeddata_verify(context, plgctx->cryptoctx,
412*7934SMark.Phalan@Sun.COM reqctx->cryptoctx, plgctx->idctx, CMS_SIGN_DRAFT9,
413*7934SMark.Phalan@Sun.COM plgctx->opts->require_crl_checking,
414*7934SMark.Phalan@Sun.COM reqp9->signedAuthPack.data, reqp9->signedAuthPack.length,
415*7934SMark.Phalan@Sun.COM &authp_data.data, &authp_data.length, &krb5_authz.data,
416*7934SMark.Phalan@Sun.COM &krb5_authz.length);
417*7934SMark.Phalan@Sun.COM break;
418*7934SMark.Phalan@Sun.COM default:
419*7934SMark.Phalan@Sun.COM pkiDebug("unrecognized pa_type = %d\n", data->pa_type);
420*7934SMark.Phalan@Sun.COM retval = EINVAL;
421*7934SMark.Phalan@Sun.COM goto cleanup;
422*7934SMark.Phalan@Sun.COM }
423*7934SMark.Phalan@Sun.COM if (retval) {
424*7934SMark.Phalan@Sun.COM pkiDebug("pkcs7_signeddata_verify failed\n");
425*7934SMark.Phalan@Sun.COM goto cleanup;
426*7934SMark.Phalan@Sun.COM }
427*7934SMark.Phalan@Sun.COM
428*7934SMark.Phalan@Sun.COM retval = verify_client_san(context, plgctx, reqctx, request->client,
429*7934SMark.Phalan@Sun.COM &valid_san);
430*7934SMark.Phalan@Sun.COM if (retval)
431*7934SMark.Phalan@Sun.COM goto cleanup;
432*7934SMark.Phalan@Sun.COM if (!valid_san) {
433*7934SMark.Phalan@Sun.COM pkiDebug("%s: did not find an acceptable SAN in user certificate\n",
434*7934SMark.Phalan@Sun.COM __FUNCTION__);
435*7934SMark.Phalan@Sun.COM retval = KRB5KDC_ERR_CLIENT_NAME_MISMATCH;
436*7934SMark.Phalan@Sun.COM goto cleanup;
437*7934SMark.Phalan@Sun.COM }
438*7934SMark.Phalan@Sun.COM retval = verify_client_eku(context, plgctx, reqctx, &valid_eku);
439*7934SMark.Phalan@Sun.COM if (retval)
440*7934SMark.Phalan@Sun.COM goto cleanup;
441*7934SMark.Phalan@Sun.COM
442*7934SMark.Phalan@Sun.COM if (!valid_eku) {
443*7934SMark.Phalan@Sun.COM pkiDebug("%s: did not find an acceptable EKU in user certificate\n",
444*7934SMark.Phalan@Sun.COM __FUNCTION__);
445*7934SMark.Phalan@Sun.COM retval = KRB5KDC_ERR_INCONSISTENT_KEY_PURPOSE;
446*7934SMark.Phalan@Sun.COM goto cleanup;
447*7934SMark.Phalan@Sun.COM }
448*7934SMark.Phalan@Sun.COM
449*7934SMark.Phalan@Sun.COM #ifdef DEBUG_ASN1
450*7934SMark.Phalan@Sun.COM print_buffer_bin(authp_data.data, authp_data.length, "/tmp/kdc_auth_pack");
451*7934SMark.Phalan@Sun.COM #endif
452*7934SMark.Phalan@Sun.COM
453*7934SMark.Phalan@Sun.COM OCTETDATA_TO_KRB5DATA(&authp_data, &k5data);
454*7934SMark.Phalan@Sun.COM switch ((int)data->pa_type) {
455*7934SMark.Phalan@Sun.COM case KRB5_PADATA_PK_AS_REQ:
456*7934SMark.Phalan@Sun.COM retval = k5int_decode_krb5_auth_pack(&k5data, &auth_pack);
457*7934SMark.Phalan@Sun.COM if (retval) {
458*7934SMark.Phalan@Sun.COM pkiDebug("failed to decode krb5_auth_pack\n");
459*7934SMark.Phalan@Sun.COM goto cleanup;
460*7934SMark.Phalan@Sun.COM }
461*7934SMark.Phalan@Sun.COM
462*7934SMark.Phalan@Sun.COM /* check dh parameters */
463*7934SMark.Phalan@Sun.COM if (auth_pack->clientPublicValue != NULL) {
464*7934SMark.Phalan@Sun.COM retval = server_check_dh(context, plgctx->cryptoctx,
465*7934SMark.Phalan@Sun.COM reqctx->cryptoctx, plgctx->idctx,
466*7934SMark.Phalan@Sun.COM &auth_pack->clientPublicValue->algorithm.parameters,
467*7934SMark.Phalan@Sun.COM plgctx->opts->dh_min_bits);
468*7934SMark.Phalan@Sun.COM
469*7934SMark.Phalan@Sun.COM if (retval) {
470*7934SMark.Phalan@Sun.COM pkiDebug("bad dh parameters\n");
471*7934SMark.Phalan@Sun.COM goto cleanup;
472*7934SMark.Phalan@Sun.COM }
473*7934SMark.Phalan@Sun.COM }
474*7934SMark.Phalan@Sun.COM /*
475*7934SMark.Phalan@Sun.COM * The KDC may have modified the request after decoding it.
476*7934SMark.Phalan@Sun.COM * We need to compute the checksum on the data that
477*7934SMark.Phalan@Sun.COM * came from the client. Therefore, we use the original
478*7934SMark.Phalan@Sun.COM * packet contents.
479*7934SMark.Phalan@Sun.COM */
480*7934SMark.Phalan@Sun.COM retval = k5int_decode_krb5_as_req(req_pkt, &tmp_as_req);
481*7934SMark.Phalan@Sun.COM if (retval) {
482*7934SMark.Phalan@Sun.COM pkiDebug("decode_krb5_as_req returned %d\n", (int)retval);
483*7934SMark.Phalan@Sun.COM goto cleanup;
484*7934SMark.Phalan@Sun.COM }
485*7934SMark.Phalan@Sun.COM
486*7934SMark.Phalan@Sun.COM retval = k5int_encode_krb5_kdc_req_body(tmp_as_req, &der_req);
487*7934SMark.Phalan@Sun.COM if (retval) {
488*7934SMark.Phalan@Sun.COM pkiDebug("encode_krb5_kdc_req_body returned %d\n", (int) retval);
489*7934SMark.Phalan@Sun.COM goto cleanup;
490*7934SMark.Phalan@Sun.COM }
491*7934SMark.Phalan@Sun.COM retval = krb5_c_make_checksum(context, CKSUMTYPE_NIST_SHA, NULL,
492*7934SMark.Phalan@Sun.COM 0, der_req, &cksum);
493*7934SMark.Phalan@Sun.COM if (retval) {
494*7934SMark.Phalan@Sun.COM pkiDebug("unable to calculate AS REQ checksum\n");
495*7934SMark.Phalan@Sun.COM goto cleanup;
496*7934SMark.Phalan@Sun.COM }
497*7934SMark.Phalan@Sun.COM if (cksum.length != auth_pack->pkAuthenticator.paChecksum.length ||
498*7934SMark.Phalan@Sun.COM memcmp(cksum.contents,
499*7934SMark.Phalan@Sun.COM auth_pack->pkAuthenticator.paChecksum.contents,
500*7934SMark.Phalan@Sun.COM cksum.length)) {
501*7934SMark.Phalan@Sun.COM pkiDebug("failed to match the checksum\n");
502*7934SMark.Phalan@Sun.COM #ifdef DEBUG_CKSUM
503*7934SMark.Phalan@Sun.COM pkiDebug("calculating checksum on buf size (%d)\n",
504*7934SMark.Phalan@Sun.COM req_pkt->length);
505*7934SMark.Phalan@Sun.COM print_buffer(req_pkt->data, req_pkt->length);
506*7934SMark.Phalan@Sun.COM pkiDebug("received checksum type=%d size=%d ",
507*7934SMark.Phalan@Sun.COM auth_pack->pkAuthenticator.paChecksum.checksum_type,
508*7934SMark.Phalan@Sun.COM auth_pack->pkAuthenticator.paChecksum.length);
509*7934SMark.Phalan@Sun.COM print_buffer(auth_pack->pkAuthenticator.paChecksum.contents,
510*7934SMark.Phalan@Sun.COM auth_pack->pkAuthenticator.paChecksum.length);
511*7934SMark.Phalan@Sun.COM pkiDebug("expected checksum type=%d size=%d ",
512*7934SMark.Phalan@Sun.COM cksum.checksum_type, cksum.length);
513*7934SMark.Phalan@Sun.COM print_buffer(cksum.contents, cksum.length);
514*7934SMark.Phalan@Sun.COM #endif
515*7934SMark.Phalan@Sun.COM
516*7934SMark.Phalan@Sun.COM retval = KRB5KDC_ERR_PA_CHECKSUM_MUST_BE_INCLUDED;
517*7934SMark.Phalan@Sun.COM goto cleanup;
518*7934SMark.Phalan@Sun.COM }
519*7934SMark.Phalan@Sun.COM
520*7934SMark.Phalan@Sun.COM /* check if kdcPkId present and match KDC's subjectIdentifier */
521*7934SMark.Phalan@Sun.COM if (reqp->kdcPkId.data != NULL) {
522*7934SMark.Phalan@Sun.COM int valid_kdcPkId = 0;
523*7934SMark.Phalan@Sun.COM retval = pkinit_check_kdc_pkid(context, plgctx->cryptoctx,
524*7934SMark.Phalan@Sun.COM reqctx->cryptoctx, plgctx->idctx,
525*7934SMark.Phalan@Sun.COM reqp->kdcPkId.data, reqp->kdcPkId.length, &valid_kdcPkId);
526*7934SMark.Phalan@Sun.COM if (retval)
527*7934SMark.Phalan@Sun.COM goto cleanup;
528*7934SMark.Phalan@Sun.COM if (!valid_kdcPkId)
529*7934SMark.Phalan@Sun.COM pkiDebug("kdcPkId in AS_REQ does not match KDC's cert"
530*7934SMark.Phalan@Sun.COM "RFC says to ignore and proceed\n");
531*7934SMark.Phalan@Sun.COM
532*7934SMark.Phalan@Sun.COM }
533*7934SMark.Phalan@Sun.COM /* remember the decoded auth_pack for verify_padata routine */
534*7934SMark.Phalan@Sun.COM reqctx->rcv_auth_pack = auth_pack;
535*7934SMark.Phalan@Sun.COM auth_pack = NULL;
536*7934SMark.Phalan@Sun.COM break;
537*7934SMark.Phalan@Sun.COM case KRB5_PADATA_PK_AS_REP_OLD:
538*7934SMark.Phalan@Sun.COM case KRB5_PADATA_PK_AS_REQ_OLD:
539*7934SMark.Phalan@Sun.COM retval = k5int_decode_krb5_auth_pack_draft9(&k5data, &auth_pack9);
540*7934SMark.Phalan@Sun.COM if (retval) {
541*7934SMark.Phalan@Sun.COM pkiDebug("failed to decode krb5_auth_pack_draft9\n");
542*7934SMark.Phalan@Sun.COM goto cleanup;
543*7934SMark.Phalan@Sun.COM }
544*7934SMark.Phalan@Sun.COM if (auth_pack9->clientPublicValue != NULL) {
545*7934SMark.Phalan@Sun.COM retval = server_check_dh(context, plgctx->cryptoctx,
546*7934SMark.Phalan@Sun.COM reqctx->cryptoctx, plgctx->idctx,
547*7934SMark.Phalan@Sun.COM &auth_pack9->clientPublicValue->algorithm.parameters,
548*7934SMark.Phalan@Sun.COM plgctx->opts->dh_min_bits);
549*7934SMark.Phalan@Sun.COM
550*7934SMark.Phalan@Sun.COM if (retval) {
551*7934SMark.Phalan@Sun.COM pkiDebug("bad dh parameters\n");
552*7934SMark.Phalan@Sun.COM goto cleanup;
553*7934SMark.Phalan@Sun.COM }
554*7934SMark.Phalan@Sun.COM }
555*7934SMark.Phalan@Sun.COM /* remember the decoded auth_pack for verify_padata routine */
556*7934SMark.Phalan@Sun.COM reqctx->rcv_auth_pack9 = auth_pack9;
557*7934SMark.Phalan@Sun.COM auth_pack9 = NULL;
558*7934SMark.Phalan@Sun.COM break;
559*7934SMark.Phalan@Sun.COM }
560*7934SMark.Phalan@Sun.COM
561*7934SMark.Phalan@Sun.COM /* return authorization data to be included in the ticket */
562*7934SMark.Phalan@Sun.COM switch ((int)data->pa_type) {
563*7934SMark.Phalan@Sun.COM case KRB5_PADATA_PK_AS_REQ:
564*7934SMark.Phalan@Sun.COM my_authz_data = malloc(2 * sizeof(*my_authz_data));
565*7934SMark.Phalan@Sun.COM if (my_authz_data == NULL) {
566*7934SMark.Phalan@Sun.COM retval = ENOMEM;
567*7934SMark.Phalan@Sun.COM pkiDebug("Couldn't allocate krb5_authdata ptr array\n");
568*7934SMark.Phalan@Sun.COM goto cleanup;
569*7934SMark.Phalan@Sun.COM }
570*7934SMark.Phalan@Sun.COM my_authz_data[1] = NULL;
571*7934SMark.Phalan@Sun.COM my_authz_data[0] = malloc(sizeof(krb5_authdata));
572*7934SMark.Phalan@Sun.COM if (my_authz_data[0] == NULL) {
573*7934SMark.Phalan@Sun.COM retval = ENOMEM;
574*7934SMark.Phalan@Sun.COM pkiDebug("Couldn't allocate krb5_authdata\n");
575*7934SMark.Phalan@Sun.COM free(my_authz_data);
576*7934SMark.Phalan@Sun.COM goto cleanup;
577*7934SMark.Phalan@Sun.COM }
578*7934SMark.Phalan@Sun.COM /* AD-INITIAL-VERIFIED-CAS must be wrapped in AD-IF-RELEVANT */
579*7934SMark.Phalan@Sun.COM my_authz_data[0]->magic = KV5M_AUTHDATA;
580*7934SMark.Phalan@Sun.COM my_authz_data[0]->ad_type = KRB5_AUTHDATA_IF_RELEVANT;
581*7934SMark.Phalan@Sun.COM
582*7934SMark.Phalan@Sun.COM /* create an internal AD-INITIAL-VERIFIED-CAS data */
583*7934SMark.Phalan@Sun.COM pkinit_authz_data = malloc(sizeof(krb5_authdata));
584*7934SMark.Phalan@Sun.COM if (pkinit_authz_data == NULL) {
585*7934SMark.Phalan@Sun.COM retval = ENOMEM;
586*7934SMark.Phalan@Sun.COM pkiDebug("Couldn't allocate krb5_authdata\n");
587*7934SMark.Phalan@Sun.COM free(my_authz_data[0]);
588*7934SMark.Phalan@Sun.COM free(my_authz_data);
589*7934SMark.Phalan@Sun.COM goto cleanup;
590*7934SMark.Phalan@Sun.COM }
591*7934SMark.Phalan@Sun.COM pkinit_authz_data->ad_type = KRB5_AUTHDATA_INITIAL_VERIFIED_CAS;
592*7934SMark.Phalan@Sun.COM /* content of this ad-type contains the certification
593*7934SMark.Phalan@Sun.COM path with which the client certificate was validated
594*7934SMark.Phalan@Sun.COM */
595*7934SMark.Phalan@Sun.COM pkinit_authz_data->contents = krb5_authz.data;
596*7934SMark.Phalan@Sun.COM pkinit_authz_data->length = krb5_authz.length;
597*7934SMark.Phalan@Sun.COM retval = k5int_encode_krb5_authdata_elt(pkinit_authz_data,
598*7934SMark.Phalan@Sun.COM &encoded_pkinit_authz_data);
599*7934SMark.Phalan@Sun.COM #ifdef DEBUG_ASN1
600*7934SMark.Phalan@Sun.COM print_buffer_bin((unsigned char *)encoded_pkinit_authz_data->data,
601*7934SMark.Phalan@Sun.COM encoded_pkinit_authz_data->length,
602*7934SMark.Phalan@Sun.COM "/tmp/kdc_pkinit_authz_data");
603*7934SMark.Phalan@Sun.COM #endif
604*7934SMark.Phalan@Sun.COM free(pkinit_authz_data);
605*7934SMark.Phalan@Sun.COM if (retval) {
606*7934SMark.Phalan@Sun.COM pkiDebug("k5int_encode_krb5_authdata_elt failed\n");
607*7934SMark.Phalan@Sun.COM free(my_authz_data[0]);
608*7934SMark.Phalan@Sun.COM free(my_authz_data);
609*7934SMark.Phalan@Sun.COM goto cleanup;
610*7934SMark.Phalan@Sun.COM }
611*7934SMark.Phalan@Sun.COM
612*7934SMark.Phalan@Sun.COM my_authz_data[0]->contents =
613*7934SMark.Phalan@Sun.COM (krb5_octet *) encoded_pkinit_authz_data->data;
614*7934SMark.Phalan@Sun.COM my_authz_data[0]->length = encoded_pkinit_authz_data->length;
615*7934SMark.Phalan@Sun.COM *authz_data = my_authz_data;
616*7934SMark.Phalan@Sun.COM pkiDebug("Returning %d bytes of authorization data\n",
617*7934SMark.Phalan@Sun.COM krb5_authz.length);
618*7934SMark.Phalan@Sun.COM encoded_pkinit_authz_data->data = NULL; /* Don't free during cleanup*/
619*7934SMark.Phalan@Sun.COM free(encoded_pkinit_authz_data);
620*7934SMark.Phalan@Sun.COM break;
621*7934SMark.Phalan@Sun.COM default:
622*7934SMark.Phalan@Sun.COM *authz_data = NULL;
623*7934SMark.Phalan@Sun.COM }
624*7934SMark.Phalan@Sun.COM /* remember to set the PREAUTH flag in the reply */
625*7934SMark.Phalan@Sun.COM enc_tkt_reply->flags |= TKT_FLG_PRE_AUTH;
626*7934SMark.Phalan@Sun.COM *pa_request_context = reqctx;
627*7934SMark.Phalan@Sun.COM reqctx = NULL;
628*7934SMark.Phalan@Sun.COM
629*7934SMark.Phalan@Sun.COM cleanup:
630*7934SMark.Phalan@Sun.COM if (retval && data->pa_type == KRB5_PADATA_PK_AS_REQ) {
631*7934SMark.Phalan@Sun.COM pkiDebug("pkinit_verify_padata failed: creating e-data\n");
632*7934SMark.Phalan@Sun.COM if (pkinit_create_edata(context, plgctx->cryptoctx, reqctx->cryptoctx,
633*7934SMark.Phalan@Sun.COM plgctx->idctx, plgctx->opts, retval, e_data))
634*7934SMark.Phalan@Sun.COM pkiDebug("pkinit_create_edata failed\n");
635*7934SMark.Phalan@Sun.COM }
636*7934SMark.Phalan@Sun.COM
637*7934SMark.Phalan@Sun.COM switch ((int)data->pa_type) {
638*7934SMark.Phalan@Sun.COM case KRB5_PADATA_PK_AS_REQ:
639*7934SMark.Phalan@Sun.COM free_krb5_pa_pk_as_req(&reqp);
640*7934SMark.Phalan@Sun.COM if (cksum.contents != NULL)
641*7934SMark.Phalan@Sun.COM free(cksum.contents);
642*7934SMark.Phalan@Sun.COM if (der_req != NULL)
643*7934SMark.Phalan@Sun.COM krb5_free_data(context, der_req);
644*7934SMark.Phalan@Sun.COM break;
645*7934SMark.Phalan@Sun.COM case KRB5_PADATA_PK_AS_REP_OLD:
646*7934SMark.Phalan@Sun.COM case KRB5_PADATA_PK_AS_REQ_OLD:
647*7934SMark.Phalan@Sun.COM free_krb5_pa_pk_as_req_draft9(&reqp9);
648*7934SMark.Phalan@Sun.COM }
649*7934SMark.Phalan@Sun.COM if (tmp_as_req != NULL)
650*7934SMark.Phalan@Sun.COM k5int_krb5_free_kdc_req(context, tmp_as_req);
651*7934SMark.Phalan@Sun.COM if (authp_data.data != NULL)
652*7934SMark.Phalan@Sun.COM free(authp_data.data);
653*7934SMark.Phalan@Sun.COM if (krb5_authz.data != NULL)
654*7934SMark.Phalan@Sun.COM free(krb5_authz.data);
655*7934SMark.Phalan@Sun.COM if (reqctx != NULL)
656*7934SMark.Phalan@Sun.COM pkinit_fini_kdc_req_context(context, reqctx);
657*7934SMark.Phalan@Sun.COM if (auth_pack != NULL)
658*7934SMark.Phalan@Sun.COM free_krb5_auth_pack(&auth_pack);
659*7934SMark.Phalan@Sun.COM if (auth_pack9 != NULL)
660*7934SMark.Phalan@Sun.COM free_krb5_auth_pack_draft9(context, &auth_pack9);
661*7934SMark.Phalan@Sun.COM
662*7934SMark.Phalan@Sun.COM return retval;
663*7934SMark.Phalan@Sun.COM }
664*7934SMark.Phalan@Sun.COM
665*7934SMark.Phalan@Sun.COM /* ARGSUSED */
666*7934SMark.Phalan@Sun.COM static krb5_error_code
pkinit_server_return_padata(krb5_context context,krb5_pa_data * padata,struct _krb5_db_entry_new * client,krb5_data * req_pkt,krb5_kdc_req * request,krb5_kdc_rep * reply,struct _krb5_key_data * client_key,krb5_keyblock * encrypting_key,krb5_pa_data ** send_pa,preauth_get_entry_data_proc server_get_entry_data,void * pa_plugin_context,void ** pa_request_context)667*7934SMark.Phalan@Sun.COM pkinit_server_return_padata(krb5_context context,
668*7934SMark.Phalan@Sun.COM krb5_pa_data * padata,
669*7934SMark.Phalan@Sun.COM struct _krb5_db_entry_new * client,
670*7934SMark.Phalan@Sun.COM krb5_data *req_pkt,
671*7934SMark.Phalan@Sun.COM krb5_kdc_req * request,
672*7934SMark.Phalan@Sun.COM krb5_kdc_rep * reply,
673*7934SMark.Phalan@Sun.COM struct _krb5_key_data * client_key,
674*7934SMark.Phalan@Sun.COM krb5_keyblock * encrypting_key,
675*7934SMark.Phalan@Sun.COM krb5_pa_data ** send_pa,
676*7934SMark.Phalan@Sun.COM preauth_get_entry_data_proc server_get_entry_data,
677*7934SMark.Phalan@Sun.COM void *pa_plugin_context,
678*7934SMark.Phalan@Sun.COM void **pa_request_context)
679*7934SMark.Phalan@Sun.COM {
680*7934SMark.Phalan@Sun.COM krb5_error_code retval = 0;
681*7934SMark.Phalan@Sun.COM krb5_data scratch = {0, 0, NULL};
682*7934SMark.Phalan@Sun.COM krb5_pa_pk_as_req *reqp = NULL;
683*7934SMark.Phalan@Sun.COM krb5_pa_pk_as_req_draft9 *reqp9 = NULL;
684*7934SMark.Phalan@Sun.COM int i = 0;
685*7934SMark.Phalan@Sun.COM
686*7934SMark.Phalan@Sun.COM unsigned char *subjectPublicKey = NULL;
687*7934SMark.Phalan@Sun.COM unsigned char *dh_pubkey = NULL, *server_key = NULL;
688*7934SMark.Phalan@Sun.COM unsigned int subjectPublicKey_len = 0;
689*7934SMark.Phalan@Sun.COM unsigned int server_key_len = 0, dh_pubkey_len = 0;
690*7934SMark.Phalan@Sun.COM
691*7934SMark.Phalan@Sun.COM krb5_kdc_dh_key_info dhkey_info;
692*7934SMark.Phalan@Sun.COM krb5_data *encoded_dhkey_info = NULL;
693*7934SMark.Phalan@Sun.COM krb5_pa_pk_as_rep *rep = NULL;
694*7934SMark.Phalan@Sun.COM krb5_pa_pk_as_rep_draft9 *rep9 = NULL;
695*7934SMark.Phalan@Sun.COM krb5_data *out_data = NULL;
696*7934SMark.Phalan@Sun.COM
697*7934SMark.Phalan@Sun.COM krb5_enctype enctype = -1;
698*7934SMark.Phalan@Sun.COM
699*7934SMark.Phalan@Sun.COM krb5_reply_key_pack *key_pack = NULL;
700*7934SMark.Phalan@Sun.COM krb5_reply_key_pack_draft9 *key_pack9 = NULL;
701*7934SMark.Phalan@Sun.COM krb5_data *encoded_key_pack = NULL;
702*7934SMark.Phalan@Sun.COM unsigned int num_types;
703*7934SMark.Phalan@Sun.COM krb5_cksumtype *cksum_types = NULL;
704*7934SMark.Phalan@Sun.COM
705*7934SMark.Phalan@Sun.COM pkinit_kdc_context plgctx;
706*7934SMark.Phalan@Sun.COM pkinit_kdc_req_context reqctx;
707*7934SMark.Phalan@Sun.COM
708*7934SMark.Phalan@Sun.COM int fixed_keypack = 0;
709*7934SMark.Phalan@Sun.COM
710*7934SMark.Phalan@Sun.COM *send_pa = NULL;
711*7934SMark.Phalan@Sun.COM /* Solaris Kerberos */
712*7934SMark.Phalan@Sun.COM if (padata == NULL || padata->length == 0 || padata->contents == NULL)
713*7934SMark.Phalan@Sun.COM return 0;
714*7934SMark.Phalan@Sun.COM
715*7934SMark.Phalan@Sun.COM if (pa_request_context == NULL || *pa_request_context == NULL) {
716*7934SMark.Phalan@Sun.COM pkiDebug("missing request context \n");
717*7934SMark.Phalan@Sun.COM return EINVAL;
718*7934SMark.Phalan@Sun.COM }
719*7934SMark.Phalan@Sun.COM
720*7934SMark.Phalan@Sun.COM plgctx = pkinit_find_realm_context(context, pa_plugin_context,
721*7934SMark.Phalan@Sun.COM request->server);
722*7934SMark.Phalan@Sun.COM if (plgctx == NULL) {
723*7934SMark.Phalan@Sun.COM pkiDebug("Unable to locate correct realm context\n");
724*7934SMark.Phalan@Sun.COM return ENOENT;
725*7934SMark.Phalan@Sun.COM }
726*7934SMark.Phalan@Sun.COM
727*7934SMark.Phalan@Sun.COM pkiDebug("pkinit_return_padata: entered!\n");
728*7934SMark.Phalan@Sun.COM reqctx = (pkinit_kdc_req_context)*pa_request_context;
729*7934SMark.Phalan@Sun.COM
730*7934SMark.Phalan@Sun.COM if (encrypting_key->contents) {
731*7934SMark.Phalan@Sun.COM free(encrypting_key->contents);
732*7934SMark.Phalan@Sun.COM encrypting_key->length = 0;
733*7934SMark.Phalan@Sun.COM encrypting_key->contents = NULL;
734*7934SMark.Phalan@Sun.COM }
735*7934SMark.Phalan@Sun.COM
736*7934SMark.Phalan@Sun.COM for(i = 0; i < request->nktypes; i++) {
737*7934SMark.Phalan@Sun.COM enctype = request->ktype[i];
738*7934SMark.Phalan@Sun.COM if (!krb5_c_valid_enctype(enctype))
739*7934SMark.Phalan@Sun.COM continue;
740*7934SMark.Phalan@Sun.COM else {
741*7934SMark.Phalan@Sun.COM pkiDebug("KDC picked etype = %d\n", enctype);
742*7934SMark.Phalan@Sun.COM break;
743*7934SMark.Phalan@Sun.COM }
744*7934SMark.Phalan@Sun.COM }
745*7934SMark.Phalan@Sun.COM
746*7934SMark.Phalan@Sun.COM if (i == request->nktypes) {
747*7934SMark.Phalan@Sun.COM retval = KRB5KDC_ERR_ETYPE_NOSUPP;
748*7934SMark.Phalan@Sun.COM goto cleanup;
749*7934SMark.Phalan@Sun.COM }
750*7934SMark.Phalan@Sun.COM
751*7934SMark.Phalan@Sun.COM switch((int)reqctx->pa_type) {
752*7934SMark.Phalan@Sun.COM case KRB5_PADATA_PK_AS_REQ:
753*7934SMark.Phalan@Sun.COM init_krb5_pa_pk_as_rep(&rep);
754*7934SMark.Phalan@Sun.COM if (rep == NULL) {
755*7934SMark.Phalan@Sun.COM retval = ENOMEM;
756*7934SMark.Phalan@Sun.COM goto cleanup;
757*7934SMark.Phalan@Sun.COM }
758*7934SMark.Phalan@Sun.COM /* let's assume it's RSA. we'll reset it to DH if needed */
759*7934SMark.Phalan@Sun.COM rep->choice = choice_pa_pk_as_rep_encKeyPack;
760*7934SMark.Phalan@Sun.COM break;
761*7934SMark.Phalan@Sun.COM case KRB5_PADATA_PK_AS_REP_OLD:
762*7934SMark.Phalan@Sun.COM case KRB5_PADATA_PK_AS_REQ_OLD:
763*7934SMark.Phalan@Sun.COM init_krb5_pa_pk_as_rep_draft9(&rep9);
764*7934SMark.Phalan@Sun.COM if (rep9 == NULL) {
765*7934SMark.Phalan@Sun.COM retval = ENOMEM;
766*7934SMark.Phalan@Sun.COM goto cleanup;
767*7934SMark.Phalan@Sun.COM }
768*7934SMark.Phalan@Sun.COM rep9->choice = choice_pa_pk_as_rep_draft9_encKeyPack;
769*7934SMark.Phalan@Sun.COM break;
770*7934SMark.Phalan@Sun.COM default:
771*7934SMark.Phalan@Sun.COM retval = KRB5KDC_ERR_PREAUTH_FAILED;
772*7934SMark.Phalan@Sun.COM goto cleanup;
773*7934SMark.Phalan@Sun.COM }
774*7934SMark.Phalan@Sun.COM
775*7934SMark.Phalan@Sun.COM if (reqctx->rcv_auth_pack != NULL &&
776*7934SMark.Phalan@Sun.COM reqctx->rcv_auth_pack->clientPublicValue != NULL) {
777*7934SMark.Phalan@Sun.COM subjectPublicKey =
778*7934SMark.Phalan@Sun.COM reqctx->rcv_auth_pack->clientPublicValue->subjectPublicKey.data;
779*7934SMark.Phalan@Sun.COM subjectPublicKey_len =
780*7934SMark.Phalan@Sun.COM reqctx->rcv_auth_pack->clientPublicValue->subjectPublicKey.length;
781*7934SMark.Phalan@Sun.COM rep->choice = choice_pa_pk_as_rep_dhInfo;
782*7934SMark.Phalan@Sun.COM } else if (reqctx->rcv_auth_pack9 != NULL &&
783*7934SMark.Phalan@Sun.COM reqctx->rcv_auth_pack9->clientPublicValue != NULL) {
784*7934SMark.Phalan@Sun.COM subjectPublicKey =
785*7934SMark.Phalan@Sun.COM reqctx->rcv_auth_pack9->clientPublicValue->subjectPublicKey.data;
786*7934SMark.Phalan@Sun.COM subjectPublicKey_len =
787*7934SMark.Phalan@Sun.COM reqctx->rcv_auth_pack9->clientPublicValue->subjectPublicKey.length;
788*7934SMark.Phalan@Sun.COM rep9->choice = choice_pa_pk_as_rep_draft9_dhSignedData;
789*7934SMark.Phalan@Sun.COM }
790*7934SMark.Phalan@Sun.COM
791*7934SMark.Phalan@Sun.COM /* if this DH, then process finish computing DH key */
792*7934SMark.Phalan@Sun.COM if (rep != NULL && (rep->choice == choice_pa_pk_as_rep_dhInfo ||
793*7934SMark.Phalan@Sun.COM rep->choice == choice_pa_pk_as_rep_draft9_dhSignedData)) {
794*7934SMark.Phalan@Sun.COM pkiDebug("received DH key delivery AS REQ\n");
795*7934SMark.Phalan@Sun.COM retval = server_process_dh(context, plgctx->cryptoctx,
796*7934SMark.Phalan@Sun.COM reqctx->cryptoctx, plgctx->idctx, subjectPublicKey,
797*7934SMark.Phalan@Sun.COM subjectPublicKey_len, &dh_pubkey, &dh_pubkey_len,
798*7934SMark.Phalan@Sun.COM &server_key, &server_key_len);
799*7934SMark.Phalan@Sun.COM if (retval) {
800*7934SMark.Phalan@Sun.COM pkiDebug("failed to process/create dh paramters\n");
801*7934SMark.Phalan@Sun.COM goto cleanup;
802*7934SMark.Phalan@Sun.COM }
803*7934SMark.Phalan@Sun.COM }
804*7934SMark.Phalan@Sun.COM
805*7934SMark.Phalan@Sun.COM if ((rep9 != NULL &&
806*7934SMark.Phalan@Sun.COM rep9->choice == choice_pa_pk_as_rep_draft9_dhSignedData) ||
807*7934SMark.Phalan@Sun.COM (rep != NULL && rep->choice == choice_pa_pk_as_rep_dhInfo)) {
808*7934SMark.Phalan@Sun.COM retval = pkinit_octetstring2key(context, enctype, server_key,
809*7934SMark.Phalan@Sun.COM server_key_len, encrypting_key);
810*7934SMark.Phalan@Sun.COM if (retval) {
811*7934SMark.Phalan@Sun.COM pkiDebug("pkinit_octetstring2key failed: %s\n",
812*7934SMark.Phalan@Sun.COM error_message(retval));
813*7934SMark.Phalan@Sun.COM goto cleanup;
814*7934SMark.Phalan@Sun.COM }
815*7934SMark.Phalan@Sun.COM
816*7934SMark.Phalan@Sun.COM dhkey_info.subjectPublicKey.length = dh_pubkey_len;
817*7934SMark.Phalan@Sun.COM dhkey_info.subjectPublicKey.data = dh_pubkey;
818*7934SMark.Phalan@Sun.COM dhkey_info.nonce = request->nonce;
819*7934SMark.Phalan@Sun.COM dhkey_info.dhKeyExpiration = 0;
820*7934SMark.Phalan@Sun.COM
821*7934SMark.Phalan@Sun.COM retval = k5int_encode_krb5_kdc_dh_key_info(&dhkey_info,
822*7934SMark.Phalan@Sun.COM &encoded_dhkey_info);
823*7934SMark.Phalan@Sun.COM if (retval) {
824*7934SMark.Phalan@Sun.COM pkiDebug("encode_krb5_kdc_dh_key_info failed\n");
825*7934SMark.Phalan@Sun.COM goto cleanup;
826*7934SMark.Phalan@Sun.COM }
827*7934SMark.Phalan@Sun.COM #ifdef DEBUG_ASN1
828*7934SMark.Phalan@Sun.COM print_buffer_bin((unsigned char *)encoded_dhkey_info->data,
829*7934SMark.Phalan@Sun.COM encoded_dhkey_info->length,
830*7934SMark.Phalan@Sun.COM "/tmp/kdc_dh_key_info");
831*7934SMark.Phalan@Sun.COM #endif
832*7934SMark.Phalan@Sun.COM
833*7934SMark.Phalan@Sun.COM switch ((int)padata->pa_type) {
834*7934SMark.Phalan@Sun.COM case KRB5_PADATA_PK_AS_REQ:
835*7934SMark.Phalan@Sun.COM retval = cms_signeddata_create(context, plgctx->cryptoctx,
836*7934SMark.Phalan@Sun.COM reqctx->cryptoctx, plgctx->idctx, CMS_SIGN_SERVER, 1,
837*7934SMark.Phalan@Sun.COM (unsigned char *)encoded_dhkey_info->data,
838*7934SMark.Phalan@Sun.COM encoded_dhkey_info->length,
839*7934SMark.Phalan@Sun.COM &rep->u.dh_Info.dhSignedData.data,
840*7934SMark.Phalan@Sun.COM &rep->u.dh_Info.dhSignedData.length);
841*7934SMark.Phalan@Sun.COM if (retval) {
842*7934SMark.Phalan@Sun.COM pkiDebug("failed to create pkcs7 signed data\n");
843*7934SMark.Phalan@Sun.COM goto cleanup;
844*7934SMark.Phalan@Sun.COM }
845*7934SMark.Phalan@Sun.COM break;
846*7934SMark.Phalan@Sun.COM case KRB5_PADATA_PK_AS_REP_OLD:
847*7934SMark.Phalan@Sun.COM case KRB5_PADATA_PK_AS_REQ_OLD:
848*7934SMark.Phalan@Sun.COM retval = cms_signeddata_create(context, plgctx->cryptoctx,
849*7934SMark.Phalan@Sun.COM reqctx->cryptoctx, plgctx->idctx, CMS_SIGN_DRAFT9, 1,
850*7934SMark.Phalan@Sun.COM (unsigned char *)encoded_dhkey_info->data,
851*7934SMark.Phalan@Sun.COM encoded_dhkey_info->length,
852*7934SMark.Phalan@Sun.COM &rep9->u.dhSignedData.data,
853*7934SMark.Phalan@Sun.COM &rep9->u.dhSignedData.length);
854*7934SMark.Phalan@Sun.COM if (retval) {
855*7934SMark.Phalan@Sun.COM pkiDebug("failed to create pkcs7 signed data\n");
856*7934SMark.Phalan@Sun.COM goto cleanup;
857*7934SMark.Phalan@Sun.COM }
858*7934SMark.Phalan@Sun.COM break;
859*7934SMark.Phalan@Sun.COM }
860*7934SMark.Phalan@Sun.COM } else {
861*7934SMark.Phalan@Sun.COM pkiDebug("received RSA key delivery AS REQ\n");
862*7934SMark.Phalan@Sun.COM
863*7934SMark.Phalan@Sun.COM retval = krb5_c_make_random_key(context, enctype, encrypting_key);
864*7934SMark.Phalan@Sun.COM if (retval) {
865*7934SMark.Phalan@Sun.COM pkiDebug("unable to make a session key\n");
866*7934SMark.Phalan@Sun.COM goto cleanup;
867*7934SMark.Phalan@Sun.COM }
868*7934SMark.Phalan@Sun.COM
869*7934SMark.Phalan@Sun.COM /* check if PA_TYPE of 132 is present which means the client is
870*7934SMark.Phalan@Sun.COM * requesting that a checksum is send back instead of the nonce
871*7934SMark.Phalan@Sun.COM */
872*7934SMark.Phalan@Sun.COM for (i = 0; request->padata[i] != NULL; i++) {
873*7934SMark.Phalan@Sun.COM pkiDebug("%s: Checking pa_type 0x%08x\n",
874*7934SMark.Phalan@Sun.COM __FUNCTION__, request->padata[i]->pa_type);
875*7934SMark.Phalan@Sun.COM if (request->padata[i]->pa_type == 132)
876*7934SMark.Phalan@Sun.COM fixed_keypack = 1;
877*7934SMark.Phalan@Sun.COM }
878*7934SMark.Phalan@Sun.COM pkiDebug("%s: return checksum instead of nonce = %d\n",
879*7934SMark.Phalan@Sun.COM __FUNCTION__, fixed_keypack);
880*7934SMark.Phalan@Sun.COM
881*7934SMark.Phalan@Sun.COM /* if this is an RFC reply or draft9 client requested a checksum
882*7934SMark.Phalan@Sun.COM * in the reply instead of the nonce, create an RFC-style keypack
883*7934SMark.Phalan@Sun.COM */
884*7934SMark.Phalan@Sun.COM if ((int)padata->pa_type == KRB5_PADATA_PK_AS_REQ || fixed_keypack) {
885*7934SMark.Phalan@Sun.COM init_krb5_reply_key_pack(&key_pack);
886*7934SMark.Phalan@Sun.COM if (key_pack == NULL) {
887*7934SMark.Phalan@Sun.COM retval = ENOMEM;
888*7934SMark.Phalan@Sun.COM goto cleanup;
889*7934SMark.Phalan@Sun.COM }
890*7934SMark.Phalan@Sun.COM /* retrieve checksums for a given enctype of the reply key */
891*7934SMark.Phalan@Sun.COM retval = krb5_c_keyed_checksum_types(context,
892*7934SMark.Phalan@Sun.COM encrypting_key->enctype, &num_types, &cksum_types);
893*7934SMark.Phalan@Sun.COM if (retval)
894*7934SMark.Phalan@Sun.COM goto cleanup;
895*7934SMark.Phalan@Sun.COM
896*7934SMark.Phalan@Sun.COM /* pick the first of acceptable enctypes for the checksum */
897*7934SMark.Phalan@Sun.COM retval = krb5_c_make_checksum(context, cksum_types[0],
898*7934SMark.Phalan@Sun.COM encrypting_key, KRB5_KEYUSAGE_TGS_REQ_AUTH_CKSUM,
899*7934SMark.Phalan@Sun.COM req_pkt, &key_pack->asChecksum);
900*7934SMark.Phalan@Sun.COM if (retval) {
901*7934SMark.Phalan@Sun.COM pkiDebug("unable to calculate AS REQ checksum\n");
902*7934SMark.Phalan@Sun.COM goto cleanup;
903*7934SMark.Phalan@Sun.COM }
904*7934SMark.Phalan@Sun.COM #ifdef DEBUG_CKSUM
905*7934SMark.Phalan@Sun.COM pkiDebug("calculating checksum on buf size = %d\n", req_pkt->length);
906*7934SMark.Phalan@Sun.COM print_buffer(req_pkt->data, req_pkt->length);
907*7934SMark.Phalan@Sun.COM pkiDebug("checksum size = %d\n", key_pack->asChecksum.length);
908*7934SMark.Phalan@Sun.COM print_buffer(key_pack->asChecksum.contents,
909*7934SMark.Phalan@Sun.COM key_pack->asChecksum.length);
910*7934SMark.Phalan@Sun.COM pkiDebug("encrypting key (%d)\n", encrypting_key->length);
911*7934SMark.Phalan@Sun.COM print_buffer(encrypting_key->contents, encrypting_key->length);
912*7934SMark.Phalan@Sun.COM #endif
913*7934SMark.Phalan@Sun.COM
914*7934SMark.Phalan@Sun.COM krb5_copy_keyblock_contents(context, encrypting_key,
915*7934SMark.Phalan@Sun.COM &key_pack->replyKey);
916*7934SMark.Phalan@Sun.COM
917*7934SMark.Phalan@Sun.COM retval = k5int_encode_krb5_reply_key_pack(key_pack,
918*7934SMark.Phalan@Sun.COM &encoded_key_pack);
919*7934SMark.Phalan@Sun.COM if (retval) {
920*7934SMark.Phalan@Sun.COM pkiDebug("failed to encode reply_key_pack\n");
921*7934SMark.Phalan@Sun.COM goto cleanup;
922*7934SMark.Phalan@Sun.COM }
923*7934SMark.Phalan@Sun.COM }
924*7934SMark.Phalan@Sun.COM
925*7934SMark.Phalan@Sun.COM switch ((int)padata->pa_type) {
926*7934SMark.Phalan@Sun.COM case KRB5_PADATA_PK_AS_REQ:
927*7934SMark.Phalan@Sun.COM rep->choice = choice_pa_pk_as_rep_encKeyPack;
928*7934SMark.Phalan@Sun.COM retval = cms_envelopeddata_create(context, plgctx->cryptoctx,
929*7934SMark.Phalan@Sun.COM reqctx->cryptoctx, plgctx->idctx, padata->pa_type, 1,
930*7934SMark.Phalan@Sun.COM (unsigned char *)encoded_key_pack->data,
931*7934SMark.Phalan@Sun.COM encoded_key_pack->length,
932*7934SMark.Phalan@Sun.COM &rep->u.encKeyPack.data, &rep->u.encKeyPack.length);
933*7934SMark.Phalan@Sun.COM break;
934*7934SMark.Phalan@Sun.COM case KRB5_PADATA_PK_AS_REP_OLD:
935*7934SMark.Phalan@Sun.COM case KRB5_PADATA_PK_AS_REQ_OLD:
936*7934SMark.Phalan@Sun.COM /* if the request is from the broken draft9 client that
937*7934SMark.Phalan@Sun.COM * expects back a nonce, create it now
938*7934SMark.Phalan@Sun.COM */
939*7934SMark.Phalan@Sun.COM if (!fixed_keypack) {
940*7934SMark.Phalan@Sun.COM init_krb5_reply_key_pack_draft9(&key_pack9);
941*7934SMark.Phalan@Sun.COM if (key_pack9 == NULL) {
942*7934SMark.Phalan@Sun.COM retval = ENOMEM;
943*7934SMark.Phalan@Sun.COM goto cleanup;
944*7934SMark.Phalan@Sun.COM }
945*7934SMark.Phalan@Sun.COM key_pack9->nonce = reqctx->rcv_auth_pack9->pkAuthenticator.nonce;
946*7934SMark.Phalan@Sun.COM krb5_copy_keyblock_contents(context, encrypting_key,
947*7934SMark.Phalan@Sun.COM &key_pack9->replyKey);
948*7934SMark.Phalan@Sun.COM
949*7934SMark.Phalan@Sun.COM retval = k5int_encode_krb5_reply_key_pack_draft9(key_pack9,
950*7934SMark.Phalan@Sun.COM &encoded_key_pack);
951*7934SMark.Phalan@Sun.COM if (retval) {
952*7934SMark.Phalan@Sun.COM pkiDebug("failed to encode reply_key_pack\n");
953*7934SMark.Phalan@Sun.COM goto cleanup;
954*7934SMark.Phalan@Sun.COM }
955*7934SMark.Phalan@Sun.COM }
956*7934SMark.Phalan@Sun.COM
957*7934SMark.Phalan@Sun.COM rep9->choice = choice_pa_pk_as_rep_draft9_encKeyPack;
958*7934SMark.Phalan@Sun.COM retval = cms_envelopeddata_create(context, plgctx->cryptoctx,
959*7934SMark.Phalan@Sun.COM reqctx->cryptoctx, plgctx->idctx, padata->pa_type, 1,
960*7934SMark.Phalan@Sun.COM (unsigned char *)encoded_key_pack->data,
961*7934SMark.Phalan@Sun.COM encoded_key_pack->length,
962*7934SMark.Phalan@Sun.COM &rep9->u.encKeyPack.data, &rep9->u.encKeyPack.length);
963*7934SMark.Phalan@Sun.COM break;
964*7934SMark.Phalan@Sun.COM }
965*7934SMark.Phalan@Sun.COM if (retval) {
966*7934SMark.Phalan@Sun.COM pkiDebug("failed to create pkcs7 enveloped data: %s\n",
967*7934SMark.Phalan@Sun.COM error_message(retval));
968*7934SMark.Phalan@Sun.COM goto cleanup;
969*7934SMark.Phalan@Sun.COM }
970*7934SMark.Phalan@Sun.COM #ifdef DEBUG_ASN1
971*7934SMark.Phalan@Sun.COM print_buffer_bin((unsigned char *)encoded_key_pack->data,
972*7934SMark.Phalan@Sun.COM encoded_key_pack->length,
973*7934SMark.Phalan@Sun.COM "/tmp/kdc_key_pack");
974*7934SMark.Phalan@Sun.COM switch ((int)padata->pa_type) {
975*7934SMark.Phalan@Sun.COM case KRB5_PADATA_PK_AS_REQ:
976*7934SMark.Phalan@Sun.COM print_buffer_bin(rep->u.encKeyPack.data,
977*7934SMark.Phalan@Sun.COM rep->u.encKeyPack.length,
978*7934SMark.Phalan@Sun.COM "/tmp/kdc_enc_key_pack");
979*7934SMark.Phalan@Sun.COM break;
980*7934SMark.Phalan@Sun.COM case KRB5_PADATA_PK_AS_REP_OLD:
981*7934SMark.Phalan@Sun.COM case KRB5_PADATA_PK_AS_REQ_OLD:
982*7934SMark.Phalan@Sun.COM print_buffer_bin(rep9->u.encKeyPack.data,
983*7934SMark.Phalan@Sun.COM rep9->u.encKeyPack.length,
984*7934SMark.Phalan@Sun.COM "/tmp/kdc_enc_key_pack");
985*7934SMark.Phalan@Sun.COM break;
986*7934SMark.Phalan@Sun.COM }
987*7934SMark.Phalan@Sun.COM #endif
988*7934SMark.Phalan@Sun.COM }
989*7934SMark.Phalan@Sun.COM
990*7934SMark.Phalan@Sun.COM switch ((int)padata->pa_type) {
991*7934SMark.Phalan@Sun.COM case KRB5_PADATA_PK_AS_REQ:
992*7934SMark.Phalan@Sun.COM retval = k5int_encode_krb5_pa_pk_as_rep(rep, &out_data);
993*7934SMark.Phalan@Sun.COM break;
994*7934SMark.Phalan@Sun.COM case KRB5_PADATA_PK_AS_REP_OLD:
995*7934SMark.Phalan@Sun.COM case KRB5_PADATA_PK_AS_REQ_OLD:
996*7934SMark.Phalan@Sun.COM retval = k5int_encode_krb5_pa_pk_as_rep_draft9(rep9, &out_data);
997*7934SMark.Phalan@Sun.COM break;
998*7934SMark.Phalan@Sun.COM }
999*7934SMark.Phalan@Sun.COM if (retval) {
1000*7934SMark.Phalan@Sun.COM pkiDebug("failed to encode AS_REP\n");
1001*7934SMark.Phalan@Sun.COM goto cleanup;
1002*7934SMark.Phalan@Sun.COM }
1003*7934SMark.Phalan@Sun.COM #ifdef DEBUG_ASN1
1004*7934SMark.Phalan@Sun.COM if (out_data != NULL)
1005*7934SMark.Phalan@Sun.COM print_buffer_bin((unsigned char *)out_data->data, out_data->length,
1006*7934SMark.Phalan@Sun.COM "/tmp/kdc_as_rep");
1007*7934SMark.Phalan@Sun.COM #endif
1008*7934SMark.Phalan@Sun.COM
1009*7934SMark.Phalan@Sun.COM *send_pa = (krb5_pa_data *) malloc(sizeof(krb5_pa_data));
1010*7934SMark.Phalan@Sun.COM if (*send_pa == NULL) {
1011*7934SMark.Phalan@Sun.COM retval = ENOMEM;
1012*7934SMark.Phalan@Sun.COM free(out_data->data);
1013*7934SMark.Phalan@Sun.COM free(out_data);
1014*7934SMark.Phalan@Sun.COM out_data = NULL;
1015*7934SMark.Phalan@Sun.COM goto cleanup;
1016*7934SMark.Phalan@Sun.COM }
1017*7934SMark.Phalan@Sun.COM (*send_pa)->magic = KV5M_PA_DATA;
1018*7934SMark.Phalan@Sun.COM switch ((int)padata->pa_type) {
1019*7934SMark.Phalan@Sun.COM case KRB5_PADATA_PK_AS_REQ:
1020*7934SMark.Phalan@Sun.COM (*send_pa)->pa_type = KRB5_PADATA_PK_AS_REP;
1021*7934SMark.Phalan@Sun.COM break;
1022*7934SMark.Phalan@Sun.COM case KRB5_PADATA_PK_AS_REQ_OLD:
1023*7934SMark.Phalan@Sun.COM case KRB5_PADATA_PK_AS_REP_OLD:
1024*7934SMark.Phalan@Sun.COM (*send_pa)->pa_type = KRB5_PADATA_PK_AS_REP_OLD;
1025*7934SMark.Phalan@Sun.COM break;
1026*7934SMark.Phalan@Sun.COM }
1027*7934SMark.Phalan@Sun.COM (*send_pa)->length = out_data->length;
1028*7934SMark.Phalan@Sun.COM (*send_pa)->contents = (krb5_octet *) out_data->data;
1029*7934SMark.Phalan@Sun.COM
1030*7934SMark.Phalan@Sun.COM
1031*7934SMark.Phalan@Sun.COM cleanup:
1032*7934SMark.Phalan@Sun.COM pkinit_fini_kdc_req_context(context, reqctx);
1033*7934SMark.Phalan@Sun.COM if (scratch.data != NULL)
1034*7934SMark.Phalan@Sun.COM free(scratch.data);
1035*7934SMark.Phalan@Sun.COM if (out_data != NULL)
1036*7934SMark.Phalan@Sun.COM free(out_data);
1037*7934SMark.Phalan@Sun.COM if (encoded_dhkey_info != NULL)
1038*7934SMark.Phalan@Sun.COM krb5_free_data(context, encoded_dhkey_info);
1039*7934SMark.Phalan@Sun.COM if (encoded_key_pack != NULL)
1040*7934SMark.Phalan@Sun.COM krb5_free_data(context, encoded_key_pack);
1041*7934SMark.Phalan@Sun.COM if (dh_pubkey != NULL)
1042*7934SMark.Phalan@Sun.COM free(dh_pubkey);
1043*7934SMark.Phalan@Sun.COM if (server_key != NULL)
1044*7934SMark.Phalan@Sun.COM free(server_key);
1045*7934SMark.Phalan@Sun.COM if (cksum_types != NULL)
1046*7934SMark.Phalan@Sun.COM free(cksum_types);
1047*7934SMark.Phalan@Sun.COM
1048*7934SMark.Phalan@Sun.COM switch ((int)padata->pa_type) {
1049*7934SMark.Phalan@Sun.COM case KRB5_PADATA_PK_AS_REQ:
1050*7934SMark.Phalan@Sun.COM free_krb5_pa_pk_as_req(&reqp);
1051*7934SMark.Phalan@Sun.COM free_krb5_pa_pk_as_rep(&rep);
1052*7934SMark.Phalan@Sun.COM free_krb5_reply_key_pack(&key_pack);
1053*7934SMark.Phalan@Sun.COM break;
1054*7934SMark.Phalan@Sun.COM case KRB5_PADATA_PK_AS_REP_OLD:
1055*7934SMark.Phalan@Sun.COM case KRB5_PADATA_PK_AS_REQ_OLD:
1056*7934SMark.Phalan@Sun.COM free_krb5_pa_pk_as_req_draft9(&reqp9);
1057*7934SMark.Phalan@Sun.COM free_krb5_pa_pk_as_rep_draft9(&rep9);
1058*7934SMark.Phalan@Sun.COM if (!fixed_keypack)
1059*7934SMark.Phalan@Sun.COM free_krb5_reply_key_pack_draft9(&key_pack9);
1060*7934SMark.Phalan@Sun.COM else
1061*7934SMark.Phalan@Sun.COM free_krb5_reply_key_pack(&key_pack);
1062*7934SMark.Phalan@Sun.COM break;
1063*7934SMark.Phalan@Sun.COM }
1064*7934SMark.Phalan@Sun.COM
1065*7934SMark.Phalan@Sun.COM if (retval)
1066*7934SMark.Phalan@Sun.COM pkiDebug("pkinit_verify_padata failure");
1067*7934SMark.Phalan@Sun.COM
1068*7934SMark.Phalan@Sun.COM return retval;
1069*7934SMark.Phalan@Sun.COM }
1070*7934SMark.Phalan@Sun.COM
1071*7934SMark.Phalan@Sun.COM /* ARGSUSED */
1072*7934SMark.Phalan@Sun.COM static int
pkinit_server_get_flags(krb5_context kcontext,krb5_preauthtype patype)1073*7934SMark.Phalan@Sun.COM pkinit_server_get_flags(krb5_context kcontext, krb5_preauthtype patype)
1074*7934SMark.Phalan@Sun.COM {
1075*7934SMark.Phalan@Sun.COM return PA_SUFFICIENT | PA_REPLACES_KEY;
1076*7934SMark.Phalan@Sun.COM }
1077*7934SMark.Phalan@Sun.COM
1078*7934SMark.Phalan@Sun.COM static krb5_preauthtype supported_server_pa_types[] = {
1079*7934SMark.Phalan@Sun.COM KRB5_PADATA_PK_AS_REQ,
1080*7934SMark.Phalan@Sun.COM KRB5_PADATA_PK_AS_REQ_OLD,
1081*7934SMark.Phalan@Sun.COM KRB5_PADATA_PK_AS_REP_OLD,
1082*7934SMark.Phalan@Sun.COM 0
1083*7934SMark.Phalan@Sun.COM };
1084*7934SMark.Phalan@Sun.COM
1085*7934SMark.Phalan@Sun.COM /* ARGSUSED */
1086*7934SMark.Phalan@Sun.COM static void
pkinit_fini_kdc_profile(krb5_context context,pkinit_kdc_context plgctx)1087*7934SMark.Phalan@Sun.COM pkinit_fini_kdc_profile(krb5_context context, pkinit_kdc_context plgctx)
1088*7934SMark.Phalan@Sun.COM {
1089*7934SMark.Phalan@Sun.COM /*
1090*7934SMark.Phalan@Sun.COM * There is nothing currently allocated by pkinit_init_kdc_profile()
1091*7934SMark.Phalan@Sun.COM * which needs to be freed here.
1092*7934SMark.Phalan@Sun.COM */
1093*7934SMark.Phalan@Sun.COM }
1094*7934SMark.Phalan@Sun.COM
1095*7934SMark.Phalan@Sun.COM static krb5_error_code
pkinit_init_kdc_profile(krb5_context context,pkinit_kdc_context plgctx)1096*7934SMark.Phalan@Sun.COM pkinit_init_kdc_profile(krb5_context context, pkinit_kdc_context plgctx)
1097*7934SMark.Phalan@Sun.COM {
1098*7934SMark.Phalan@Sun.COM krb5_error_code retval;
1099*7934SMark.Phalan@Sun.COM char *eku_string = NULL;
1100*7934SMark.Phalan@Sun.COM
1101*7934SMark.Phalan@Sun.COM pkiDebug("%s: entered for realm %s\n", __FUNCTION__, plgctx->realmname);
1102*7934SMark.Phalan@Sun.COM retval = pkinit_kdcdefault_string(context, plgctx->realmname,
1103*7934SMark.Phalan@Sun.COM "pkinit_identity",
1104*7934SMark.Phalan@Sun.COM &plgctx->idopts->identity);
1105*7934SMark.Phalan@Sun.COM if (retval != 0 || NULL == plgctx->idopts->identity) {
1106*7934SMark.Phalan@Sun.COM retval = EINVAL;
1107*7934SMark.Phalan@Sun.COM krb5_set_error_message(context, retval,
1108*7934SMark.Phalan@Sun.COM "No pkinit_identity supplied for realm %s",
1109*7934SMark.Phalan@Sun.COM plgctx->realmname);
1110*7934SMark.Phalan@Sun.COM goto errout;
1111*7934SMark.Phalan@Sun.COM }
1112*7934SMark.Phalan@Sun.COM
1113*7934SMark.Phalan@Sun.COM retval = pkinit_kdcdefault_strings(context, plgctx->realmname,
1114*7934SMark.Phalan@Sun.COM "pkinit_anchors",
1115*7934SMark.Phalan@Sun.COM &plgctx->idopts->anchors);
1116*7934SMark.Phalan@Sun.COM if (retval != 0 || NULL == plgctx->idopts->anchors) {
1117*7934SMark.Phalan@Sun.COM retval = EINVAL;
1118*7934SMark.Phalan@Sun.COM krb5_set_error_message(context, retval,
1119*7934SMark.Phalan@Sun.COM "No pkinit_anchors supplied for realm %s",
1120*7934SMark.Phalan@Sun.COM plgctx->realmname);
1121*7934SMark.Phalan@Sun.COM goto errout;
1122*7934SMark.Phalan@Sun.COM }
1123*7934SMark.Phalan@Sun.COM
1124*7934SMark.Phalan@Sun.COM /* Solaris Kerberos */
1125*7934SMark.Phalan@Sun.COM (void) pkinit_kdcdefault_strings(context, plgctx->realmname,
1126*7934SMark.Phalan@Sun.COM "pkinit_pool",
1127*7934SMark.Phalan@Sun.COM &plgctx->idopts->intermediates);
1128*7934SMark.Phalan@Sun.COM
1129*7934SMark.Phalan@Sun.COM (void) pkinit_kdcdefault_strings(context, plgctx->realmname,
1130*7934SMark.Phalan@Sun.COM "pkinit_revoke",
1131*7934SMark.Phalan@Sun.COM &plgctx->idopts->crls);
1132*7934SMark.Phalan@Sun.COM
1133*7934SMark.Phalan@Sun.COM (void) pkinit_kdcdefault_string(context, plgctx->realmname,
1134*7934SMark.Phalan@Sun.COM "pkinit_kdc_ocsp",
1135*7934SMark.Phalan@Sun.COM &plgctx->idopts->ocsp);
1136*7934SMark.Phalan@Sun.COM
1137*7934SMark.Phalan@Sun.COM (void) pkinit_kdcdefault_string(context, plgctx->realmname,
1138*7934SMark.Phalan@Sun.COM "pkinit_mappings_file",
1139*7934SMark.Phalan@Sun.COM &plgctx->idopts->dn_mapping_file);
1140*7934SMark.Phalan@Sun.COM
1141*7934SMark.Phalan@Sun.COM (void) pkinit_kdcdefault_integer(context, plgctx->realmname,
1142*7934SMark.Phalan@Sun.COM "pkinit_dh_min_bits",
1143*7934SMark.Phalan@Sun.COM PKINIT_DEFAULT_DH_MIN_BITS,
1144*7934SMark.Phalan@Sun.COM &plgctx->opts->dh_min_bits);
1145*7934SMark.Phalan@Sun.COM if (plgctx->opts->dh_min_bits < 1024) {
1146*7934SMark.Phalan@Sun.COM pkiDebug("%s: invalid value (%d) for pkinit_dh_min_bits, "
1147*7934SMark.Phalan@Sun.COM "using default value (%d) instead\n", __FUNCTION__,
1148*7934SMark.Phalan@Sun.COM plgctx->opts->dh_min_bits, PKINIT_DEFAULT_DH_MIN_BITS);
1149*7934SMark.Phalan@Sun.COM plgctx->opts->dh_min_bits = PKINIT_DEFAULT_DH_MIN_BITS;
1150*7934SMark.Phalan@Sun.COM }
1151*7934SMark.Phalan@Sun.COM
1152*7934SMark.Phalan@Sun.COM (void) pkinit_kdcdefault_boolean(context, plgctx->realmname,
1153*7934SMark.Phalan@Sun.COM "pkinit_allow_upn",
1154*7934SMark.Phalan@Sun.COM 0, &plgctx->opts->allow_upn);
1155*7934SMark.Phalan@Sun.COM
1156*7934SMark.Phalan@Sun.COM (void) pkinit_kdcdefault_boolean(context, plgctx->realmname,
1157*7934SMark.Phalan@Sun.COM "pkinit_require_crl_checking",
1158*7934SMark.Phalan@Sun.COM 0, &plgctx->opts->require_crl_checking);
1159*7934SMark.Phalan@Sun.COM
1160*7934SMark.Phalan@Sun.COM (void) pkinit_kdcdefault_string(context, plgctx->realmname,
1161*7934SMark.Phalan@Sun.COM "pkinit_eku_checking",
1162*7934SMark.Phalan@Sun.COM &eku_string);
1163*7934SMark.Phalan@Sun.COM if (eku_string != NULL) {
1164*7934SMark.Phalan@Sun.COM if (strcasecmp(eku_string, "kpClientAuth") == 0) {
1165*7934SMark.Phalan@Sun.COM plgctx->opts->require_eku = 1;
1166*7934SMark.Phalan@Sun.COM plgctx->opts->accept_secondary_eku = 0;
1167*7934SMark.Phalan@Sun.COM } else if (strcasecmp(eku_string, "scLogin") == 0) {
1168*7934SMark.Phalan@Sun.COM plgctx->opts->require_eku = 1;
1169*7934SMark.Phalan@Sun.COM plgctx->opts->accept_secondary_eku = 1;
1170*7934SMark.Phalan@Sun.COM } else if (strcasecmp(eku_string, "none") == 0) {
1171*7934SMark.Phalan@Sun.COM plgctx->opts->require_eku = 0;
1172*7934SMark.Phalan@Sun.COM plgctx->opts->accept_secondary_eku = 0;
1173*7934SMark.Phalan@Sun.COM } else {
1174*7934SMark.Phalan@Sun.COM pkiDebug("%s: Invalid value for pkinit_eku_checking: '%s'\n",
1175*7934SMark.Phalan@Sun.COM __FUNCTION__, eku_string);
1176*7934SMark.Phalan@Sun.COM }
1177*7934SMark.Phalan@Sun.COM free(eku_string);
1178*7934SMark.Phalan@Sun.COM }
1179*7934SMark.Phalan@Sun.COM
1180*7934SMark.Phalan@Sun.COM
1181*7934SMark.Phalan@Sun.COM return 0;
1182*7934SMark.Phalan@Sun.COM errout:
1183*7934SMark.Phalan@Sun.COM pkinit_fini_kdc_profile(context, plgctx);
1184*7934SMark.Phalan@Sun.COM return retval;
1185*7934SMark.Phalan@Sun.COM }
1186*7934SMark.Phalan@Sun.COM
1187*7934SMark.Phalan@Sun.COM /* ARGSUSED */
1188*7934SMark.Phalan@Sun.COM static pkinit_kdc_context
pkinit_find_realm_context(krb5_context context,void * pa_plugin_context,krb5_principal princ)1189*7934SMark.Phalan@Sun.COM pkinit_find_realm_context(krb5_context context, void *pa_plugin_context,
1190*7934SMark.Phalan@Sun.COM krb5_principal princ)
1191*7934SMark.Phalan@Sun.COM {
1192*7934SMark.Phalan@Sun.COM int i;
1193*7934SMark.Phalan@Sun.COM pkinit_kdc_context *realm_contexts = pa_plugin_context;
1194*7934SMark.Phalan@Sun.COM
1195*7934SMark.Phalan@Sun.COM if (pa_plugin_context == NULL)
1196*7934SMark.Phalan@Sun.COM return NULL;
1197*7934SMark.Phalan@Sun.COM
1198*7934SMark.Phalan@Sun.COM for (i = 0; realm_contexts[i] != NULL; i++) {
1199*7934SMark.Phalan@Sun.COM pkinit_kdc_context p = realm_contexts[i];
1200*7934SMark.Phalan@Sun.COM
1201*7934SMark.Phalan@Sun.COM if ((p->realmname_len == princ->realm.length) &&
1202*7934SMark.Phalan@Sun.COM (strncmp(p->realmname, princ->realm.data, p->realmname_len) == 0)) {
1203*7934SMark.Phalan@Sun.COM pkiDebug("%s: returning context at %p for realm '%s'\n",
1204*7934SMark.Phalan@Sun.COM __FUNCTION__, p, p->realmname);
1205*7934SMark.Phalan@Sun.COM return p;
1206*7934SMark.Phalan@Sun.COM }
1207*7934SMark.Phalan@Sun.COM }
1208*7934SMark.Phalan@Sun.COM pkiDebug("%s: unable to find realm context for realm '%.*s'\n",
1209*7934SMark.Phalan@Sun.COM __FUNCTION__, princ->realm.length, princ->realm.data);
1210*7934SMark.Phalan@Sun.COM return NULL;
1211*7934SMark.Phalan@Sun.COM }
1212*7934SMark.Phalan@Sun.COM
1213*7934SMark.Phalan@Sun.COM static int
pkinit_server_plugin_init_realm(krb5_context context,const char * realmname,pkinit_kdc_context * pplgctx)1214*7934SMark.Phalan@Sun.COM pkinit_server_plugin_init_realm(krb5_context context, const char *realmname,
1215*7934SMark.Phalan@Sun.COM pkinit_kdc_context *pplgctx)
1216*7934SMark.Phalan@Sun.COM {
1217*7934SMark.Phalan@Sun.COM krb5_error_code retval = ENOMEM;
1218*7934SMark.Phalan@Sun.COM pkinit_kdc_context plgctx = NULL;
1219*7934SMark.Phalan@Sun.COM
1220*7934SMark.Phalan@Sun.COM *pplgctx = NULL;
1221*7934SMark.Phalan@Sun.COM
1222*7934SMark.Phalan@Sun.COM plgctx = (pkinit_kdc_context) calloc(1, sizeof(*plgctx));
1223*7934SMark.Phalan@Sun.COM if (plgctx == NULL)
1224*7934SMark.Phalan@Sun.COM goto errout;
1225*7934SMark.Phalan@Sun.COM
1226*7934SMark.Phalan@Sun.COM pkiDebug("%s: initializing context at %p for realm '%s'\n",
1227*7934SMark.Phalan@Sun.COM __FUNCTION__, plgctx, realmname);
1228*7934SMark.Phalan@Sun.COM (void) memset(plgctx, 0, sizeof(*plgctx));
1229*7934SMark.Phalan@Sun.COM plgctx->magic = PKINIT_CTX_MAGIC;
1230*7934SMark.Phalan@Sun.COM
1231*7934SMark.Phalan@Sun.COM plgctx->realmname = strdup(realmname);
1232*7934SMark.Phalan@Sun.COM if (plgctx->realmname == NULL)
1233*7934SMark.Phalan@Sun.COM goto errout;
1234*7934SMark.Phalan@Sun.COM plgctx->realmname_len = strlen(plgctx->realmname);
1235*7934SMark.Phalan@Sun.COM
1236*7934SMark.Phalan@Sun.COM retval = pkinit_init_plg_crypto(&plgctx->cryptoctx);
1237*7934SMark.Phalan@Sun.COM if (retval)
1238*7934SMark.Phalan@Sun.COM goto errout;
1239*7934SMark.Phalan@Sun.COM
1240*7934SMark.Phalan@Sun.COM retval = pkinit_init_plg_opts(&plgctx->opts);
1241*7934SMark.Phalan@Sun.COM if (retval)
1242*7934SMark.Phalan@Sun.COM goto errout;
1243*7934SMark.Phalan@Sun.COM
1244*7934SMark.Phalan@Sun.COM retval = pkinit_init_identity_crypto(&plgctx->idctx);
1245*7934SMark.Phalan@Sun.COM if (retval)
1246*7934SMark.Phalan@Sun.COM goto errout;
1247*7934SMark.Phalan@Sun.COM
1248*7934SMark.Phalan@Sun.COM retval = pkinit_init_identity_opts(&plgctx->idopts);
1249*7934SMark.Phalan@Sun.COM if (retval)
1250*7934SMark.Phalan@Sun.COM goto errout;
1251*7934SMark.Phalan@Sun.COM
1252*7934SMark.Phalan@Sun.COM retval = pkinit_init_kdc_profile(context, plgctx);
1253*7934SMark.Phalan@Sun.COM if (retval)
1254*7934SMark.Phalan@Sun.COM goto errout;
1255*7934SMark.Phalan@Sun.COM
1256*7934SMark.Phalan@Sun.COM /*
1257*7934SMark.Phalan@Sun.COM * Solaris Kerberos:
1258*7934SMark.Phalan@Sun.COM * Some methods of storing key information (PKCS11, PKCS12,...) may
1259*7934SMark.Phalan@Sun.COM * require interactive prompting.
1260*7934SMark.Phalan@Sun.COM */
1261*7934SMark.Phalan@Sun.COM retval = pkinit_identity_set_prompter(plgctx->idctx, krb5_prompter_posix,
1262*7934SMark.Phalan@Sun.COM NULL);
1263*7934SMark.Phalan@Sun.COM if (retval)
1264*7934SMark.Phalan@Sun.COM goto errout;
1265*7934SMark.Phalan@Sun.COM
1266*7934SMark.Phalan@Sun.COM retval = pkinit_identity_initialize(context, plgctx->cryptoctx, NULL,
1267*7934SMark.Phalan@Sun.COM plgctx->idopts, plgctx->idctx, 0, NULL);
1268*7934SMark.Phalan@Sun.COM if (retval)
1269*7934SMark.Phalan@Sun.COM goto errout;
1270*7934SMark.Phalan@Sun.COM
1271*7934SMark.Phalan@Sun.COM pkiDebug("%s: returning context at %p for realm '%s'\n",
1272*7934SMark.Phalan@Sun.COM __FUNCTION__, plgctx, realmname);
1273*7934SMark.Phalan@Sun.COM *pplgctx = plgctx;
1274*7934SMark.Phalan@Sun.COM retval = 0;
1275*7934SMark.Phalan@Sun.COM
1276*7934SMark.Phalan@Sun.COM errout:
1277*7934SMark.Phalan@Sun.COM if (retval)
1278*7934SMark.Phalan@Sun.COM pkinit_server_plugin_fini_realm(context, plgctx);
1279*7934SMark.Phalan@Sun.COM
1280*7934SMark.Phalan@Sun.COM return retval;
1281*7934SMark.Phalan@Sun.COM }
1282*7934SMark.Phalan@Sun.COM
1283*7934SMark.Phalan@Sun.COM static int
pkinit_server_plugin_init(krb5_context context,void ** blob,const char ** realmnames)1284*7934SMark.Phalan@Sun.COM pkinit_server_plugin_init(krb5_context context, void **blob,
1285*7934SMark.Phalan@Sun.COM const char **realmnames)
1286*7934SMark.Phalan@Sun.COM {
1287*7934SMark.Phalan@Sun.COM krb5_error_code retval = ENOMEM;
1288*7934SMark.Phalan@Sun.COM pkinit_kdc_context plgctx, *realm_contexts = NULL;
1289*7934SMark.Phalan@Sun.COM int i, j;
1290*7934SMark.Phalan@Sun.COM size_t numrealms;
1291*7934SMark.Phalan@Sun.COM
1292*7934SMark.Phalan@Sun.COM retval = pkinit_accessor_init();
1293*7934SMark.Phalan@Sun.COM if (retval)
1294*7934SMark.Phalan@Sun.COM return retval;
1295*7934SMark.Phalan@Sun.COM
1296*7934SMark.Phalan@Sun.COM /* Determine how many realms we may need to support */
1297*7934SMark.Phalan@Sun.COM for (i = 0; realmnames[i] != NULL; i++) {};
1298*7934SMark.Phalan@Sun.COM numrealms = i;
1299*7934SMark.Phalan@Sun.COM
1300*7934SMark.Phalan@Sun.COM realm_contexts = (pkinit_kdc_context *)
1301*7934SMark.Phalan@Sun.COM calloc(numrealms+1, sizeof(pkinit_kdc_context));
1302*7934SMark.Phalan@Sun.COM if (realm_contexts == NULL)
1303*7934SMark.Phalan@Sun.COM return ENOMEM;
1304*7934SMark.Phalan@Sun.COM
1305*7934SMark.Phalan@Sun.COM for (i = 0, j = 0; i < numrealms; i++) {
1306*7934SMark.Phalan@Sun.COM pkiDebug("%s: processing realm '%s'\n", __FUNCTION__, realmnames[i]);
1307*7934SMark.Phalan@Sun.COM retval = pkinit_server_plugin_init_realm(context, realmnames[i], &plgctx);
1308*7934SMark.Phalan@Sun.COM if (retval == 0 && plgctx != NULL)
1309*7934SMark.Phalan@Sun.COM realm_contexts[j++] = plgctx;
1310*7934SMark.Phalan@Sun.COM }
1311*7934SMark.Phalan@Sun.COM
1312*7934SMark.Phalan@Sun.COM if (j == 0) {
1313*7934SMark.Phalan@Sun.COM /*
1314*7934SMark.Phalan@Sun.COM * Solaris Kerberos
1315*7934SMark.Phalan@Sun.COM * Improve error messages for the common case of a single realm
1316*7934SMark.Phalan@Sun.COM */
1317*7934SMark.Phalan@Sun.COM if (numrealms != 1) {
1318*7934SMark.Phalan@Sun.COM retval = EINVAL;
1319*7934SMark.Phalan@Sun.COM krb5_set_error_message(context, retval, "No realms configured "
1320*7934SMark.Phalan@Sun.COM "correctly for pkinit support");
1321*7934SMark.Phalan@Sun.COM }
1322*7934SMark.Phalan@Sun.COM
1323*7934SMark.Phalan@Sun.COM goto errout;
1324*7934SMark.Phalan@Sun.COM }
1325*7934SMark.Phalan@Sun.COM
1326*7934SMark.Phalan@Sun.COM *blob = realm_contexts;
1327*7934SMark.Phalan@Sun.COM retval = 0;
1328*7934SMark.Phalan@Sun.COM pkiDebug("%s: returning context at %p\n", __FUNCTION__, realm_contexts);
1329*7934SMark.Phalan@Sun.COM
1330*7934SMark.Phalan@Sun.COM errout:
1331*7934SMark.Phalan@Sun.COM if (retval)
1332*7934SMark.Phalan@Sun.COM pkinit_server_plugin_fini(context, realm_contexts);
1333*7934SMark.Phalan@Sun.COM
1334*7934SMark.Phalan@Sun.COM return retval;
1335*7934SMark.Phalan@Sun.COM }
1336*7934SMark.Phalan@Sun.COM
1337*7934SMark.Phalan@Sun.COM static void
pkinit_server_plugin_fini_realm(krb5_context context,pkinit_kdc_context plgctx)1338*7934SMark.Phalan@Sun.COM pkinit_server_plugin_fini_realm(krb5_context context, pkinit_kdc_context plgctx)
1339*7934SMark.Phalan@Sun.COM {
1340*7934SMark.Phalan@Sun.COM if (plgctx == NULL)
1341*7934SMark.Phalan@Sun.COM return;
1342*7934SMark.Phalan@Sun.COM
1343*7934SMark.Phalan@Sun.COM pkinit_fini_kdc_profile(context, plgctx);
1344*7934SMark.Phalan@Sun.COM pkinit_fini_identity_opts(plgctx->idopts);
1345*7934SMark.Phalan@Sun.COM pkinit_fini_identity_crypto(plgctx->idctx);
1346*7934SMark.Phalan@Sun.COM pkinit_fini_plg_crypto(plgctx->cryptoctx);
1347*7934SMark.Phalan@Sun.COM pkinit_fini_plg_opts(plgctx->opts);
1348*7934SMark.Phalan@Sun.COM free(plgctx->realmname);
1349*7934SMark.Phalan@Sun.COM free(plgctx);
1350*7934SMark.Phalan@Sun.COM }
1351*7934SMark.Phalan@Sun.COM
1352*7934SMark.Phalan@Sun.COM static void
pkinit_server_plugin_fini(krb5_context context,void * blob)1353*7934SMark.Phalan@Sun.COM pkinit_server_plugin_fini(krb5_context context, void *blob)
1354*7934SMark.Phalan@Sun.COM {
1355*7934SMark.Phalan@Sun.COM pkinit_kdc_context *realm_contexts = blob;
1356*7934SMark.Phalan@Sun.COM int i;
1357*7934SMark.Phalan@Sun.COM
1358*7934SMark.Phalan@Sun.COM if (realm_contexts == NULL)
1359*7934SMark.Phalan@Sun.COM return;
1360*7934SMark.Phalan@Sun.COM
1361*7934SMark.Phalan@Sun.COM for (i = 0; realm_contexts[i] != NULL; i++) {
1362*7934SMark.Phalan@Sun.COM pkinit_server_plugin_fini_realm(context, realm_contexts[i]);
1363*7934SMark.Phalan@Sun.COM }
1364*7934SMark.Phalan@Sun.COM pkiDebug("%s: freeing context at %p\n", __FUNCTION__, realm_contexts);
1365*7934SMark.Phalan@Sun.COM free(realm_contexts);
1366*7934SMark.Phalan@Sun.COM }
1367*7934SMark.Phalan@Sun.COM
1368*7934SMark.Phalan@Sun.COM static krb5_error_code
pkinit_init_kdc_req_context(krb5_context context,void ** ctx)1369*7934SMark.Phalan@Sun.COM pkinit_init_kdc_req_context(krb5_context context, void **ctx)
1370*7934SMark.Phalan@Sun.COM {
1371*7934SMark.Phalan@Sun.COM krb5_error_code retval = ENOMEM;
1372*7934SMark.Phalan@Sun.COM pkinit_kdc_req_context reqctx = NULL;
1373*7934SMark.Phalan@Sun.COM
1374*7934SMark.Phalan@Sun.COM reqctx = (pkinit_kdc_req_context)malloc(sizeof(*reqctx));
1375*7934SMark.Phalan@Sun.COM if (reqctx == NULL)
1376*7934SMark.Phalan@Sun.COM return retval;
1377*7934SMark.Phalan@Sun.COM (void) memset(reqctx, 0, sizeof(*reqctx));
1378*7934SMark.Phalan@Sun.COM reqctx->magic = PKINIT_CTX_MAGIC;
1379*7934SMark.Phalan@Sun.COM
1380*7934SMark.Phalan@Sun.COM retval = pkinit_init_req_crypto(&reqctx->cryptoctx);
1381*7934SMark.Phalan@Sun.COM if (retval)
1382*7934SMark.Phalan@Sun.COM goto cleanup;
1383*7934SMark.Phalan@Sun.COM reqctx->rcv_auth_pack = NULL;
1384*7934SMark.Phalan@Sun.COM reqctx->rcv_auth_pack9 = NULL;
1385*7934SMark.Phalan@Sun.COM
1386*7934SMark.Phalan@Sun.COM pkiDebug("%s: returning reqctx at %p\n", __FUNCTION__, reqctx);
1387*7934SMark.Phalan@Sun.COM *ctx = reqctx;
1388*7934SMark.Phalan@Sun.COM retval = 0;
1389*7934SMark.Phalan@Sun.COM cleanup:
1390*7934SMark.Phalan@Sun.COM if (retval)
1391*7934SMark.Phalan@Sun.COM pkinit_fini_kdc_req_context(context, reqctx);
1392*7934SMark.Phalan@Sun.COM
1393*7934SMark.Phalan@Sun.COM return retval;
1394*7934SMark.Phalan@Sun.COM }
1395*7934SMark.Phalan@Sun.COM
1396*7934SMark.Phalan@Sun.COM static void
pkinit_fini_kdc_req_context(krb5_context context,void * ctx)1397*7934SMark.Phalan@Sun.COM pkinit_fini_kdc_req_context(krb5_context context, void *ctx)
1398*7934SMark.Phalan@Sun.COM {
1399*7934SMark.Phalan@Sun.COM pkinit_kdc_req_context reqctx = (pkinit_kdc_req_context)ctx;
1400*7934SMark.Phalan@Sun.COM
1401*7934SMark.Phalan@Sun.COM if (reqctx == NULL || reqctx->magic != PKINIT_CTX_MAGIC) {
1402*7934SMark.Phalan@Sun.COM pkiDebug("pkinit_fini_kdc_req_context: got bad reqctx (%p)!\n", reqctx);
1403*7934SMark.Phalan@Sun.COM return;
1404*7934SMark.Phalan@Sun.COM }
1405*7934SMark.Phalan@Sun.COM pkiDebug("%s: freeing reqctx at %p\n", __FUNCTION__, reqctx);
1406*7934SMark.Phalan@Sun.COM
1407*7934SMark.Phalan@Sun.COM pkinit_fini_req_crypto(reqctx->cryptoctx);
1408*7934SMark.Phalan@Sun.COM if (reqctx->rcv_auth_pack != NULL)
1409*7934SMark.Phalan@Sun.COM free_krb5_auth_pack(&reqctx->rcv_auth_pack);
1410*7934SMark.Phalan@Sun.COM if (reqctx->rcv_auth_pack9 != NULL)
1411*7934SMark.Phalan@Sun.COM free_krb5_auth_pack_draft9(context, &reqctx->rcv_auth_pack9);
1412*7934SMark.Phalan@Sun.COM
1413*7934SMark.Phalan@Sun.COM free(reqctx);
1414*7934SMark.Phalan@Sun.COM }
1415*7934SMark.Phalan@Sun.COM
1416*7934SMark.Phalan@Sun.COM struct krb5plugin_preauth_server_ftable_v1 preauthentication_server_1 = {
1417*7934SMark.Phalan@Sun.COM "pkinit", /* name */
1418*7934SMark.Phalan@Sun.COM supported_server_pa_types, /* pa_type_list */
1419*7934SMark.Phalan@Sun.COM pkinit_server_plugin_init, /* (*init_proc) */
1420*7934SMark.Phalan@Sun.COM pkinit_server_plugin_fini, /* (*fini_proc) */
1421*7934SMark.Phalan@Sun.COM pkinit_server_get_flags, /* (*flags_proc) */
1422*7934SMark.Phalan@Sun.COM pkinit_server_get_edata, /* (*edata_proc) */
1423*7934SMark.Phalan@Sun.COM pkinit_server_verify_padata,/* (*verify_proc) */
1424*7934SMark.Phalan@Sun.COM pkinit_server_return_padata,/* (*return_proc) */
1425*7934SMark.Phalan@Sun.COM NULL, /* (*freepa_reqcontext_proc) */
1426*7934SMark.Phalan@Sun.COM };
1427