xref: /onnv-gate/usr/src/lib/krb5/plugins/preauth/pkinit/pkinit_srv.c (revision 7934:6aeeafc994de)
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