xref: /freebsd/crypto/krb5/src/lib/rpc/svc_auth_gss.c (revision 7f2fe78b9dd5f51c821d771b63d2e096f6fd49e9)
1*7f2fe78bSCy Schubert /* lib/rpc/svc_auth_gss.c */
2*7f2fe78bSCy Schubert /*
3*7f2fe78bSCy Schubert   Copyright (c) 2000 The Regents of the University of Michigan.
4*7f2fe78bSCy Schubert   All rights reserved.
5*7f2fe78bSCy Schubert 
6*7f2fe78bSCy Schubert   Copyright (c) 2000 Dug Song <dugsong@UMICH.EDU>.
7*7f2fe78bSCy Schubert   All rights reserved, all wrongs reversed.
8*7f2fe78bSCy Schubert 
9*7f2fe78bSCy Schubert   Redistribution and use in source and binary forms, with or without
10*7f2fe78bSCy Schubert   modification, are permitted provided that the following conditions
11*7f2fe78bSCy Schubert   are met:
12*7f2fe78bSCy Schubert 
13*7f2fe78bSCy Schubert   1. Redistributions of source code must retain the above copyright
14*7f2fe78bSCy Schubert      notice, this list of conditions and the following disclaimer.
15*7f2fe78bSCy Schubert   2. Redistributions in binary form must reproduce the above copyright
16*7f2fe78bSCy Schubert      notice, this list of conditions and the following disclaimer in the
17*7f2fe78bSCy Schubert      documentation and/or other materials provided with the distribution.
18*7f2fe78bSCy Schubert   3. Neither the name of the University nor the names of its
19*7f2fe78bSCy Schubert      contributors may be used to endorse or promote products derived
20*7f2fe78bSCy Schubert      from this software without specific prior written permission.
21*7f2fe78bSCy Schubert 
22*7f2fe78bSCy Schubert   THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
23*7f2fe78bSCy Schubert   WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
24*7f2fe78bSCy Schubert   MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
25*7f2fe78bSCy Schubert   DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26*7f2fe78bSCy Schubert   FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27*7f2fe78bSCy Schubert   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28*7f2fe78bSCy Schubert   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
29*7f2fe78bSCy Schubert   BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
30*7f2fe78bSCy Schubert   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
31*7f2fe78bSCy Schubert   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32*7f2fe78bSCy Schubert   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33*7f2fe78bSCy Schubert 
34*7f2fe78bSCy Schubert   Id: svc_auth_gss.c,v 1.28 2002/10/15 21:29:36 kwc Exp
35*7f2fe78bSCy Schubert  */
36*7f2fe78bSCy Schubert 
37*7f2fe78bSCy Schubert #include "k5-platform.h"
38*7f2fe78bSCy Schubert #include <gssrpc/rpc.h>
39*7f2fe78bSCy Schubert #include <gssrpc/auth_gssapi.h>
40*7f2fe78bSCy Schubert #ifdef HAVE_HEIMDAL
41*7f2fe78bSCy Schubert #include <gssapi.h>
42*7f2fe78bSCy Schubert #define gss_nt_service_name GSS_C_NT_HOSTBASED_SERVICE
43*7f2fe78bSCy Schubert #else
44*7f2fe78bSCy Schubert #include <gssapi/gssapi.h>
45*7f2fe78bSCy Schubert #include <gssapi/gssapi_generic.h>
46*7f2fe78bSCy Schubert #endif
47*7f2fe78bSCy Schubert 
48*7f2fe78bSCy Schubert #ifdef DEBUG_GSSAPI
49*7f2fe78bSCy Schubert int svc_debug_gss = DEBUG_GSSAPI;
50*7f2fe78bSCy Schubert #endif
51*7f2fe78bSCy Schubert 
52*7f2fe78bSCy Schubert #ifdef SPKM
53*7f2fe78bSCy Schubert 
54*7f2fe78bSCy Schubert #ifndef OID_EQ
55*7f2fe78bSCy Schubert #define g_OID_equal(o1,o2) \
56*7f2fe78bSCy Schubert    (((o1)->length == (o2)->length) && \
57*7f2fe78bSCy Schubert     ((o1)->elements != 0) && ((o2)->elements != 0) && \
58*7f2fe78bSCy Schubert     (memcmp((o1)->elements,(o2)->elements,(int) (o1)->length) == 0))
59*7f2fe78bSCy Schubert #define OID_EQ 1
60*7f2fe78bSCy Schubert #endif /* OID_EQ */
61*7f2fe78bSCy Schubert 
62*7f2fe78bSCy Schubert extern const gss_OID_desc * const gss_mech_spkm3;
63*7f2fe78bSCy Schubert 
64*7f2fe78bSCy Schubert #endif /* SPKM */
65*7f2fe78bSCy Schubert 
66*7f2fe78bSCy Schubert extern SVCAUTH svc_auth_none;
67*7f2fe78bSCy Schubert 
68*7f2fe78bSCy Schubert static auth_gssapi_log_badauth_func log_badauth = NULL;
69*7f2fe78bSCy Schubert static caddr_t log_badauth_data = NULL;
70*7f2fe78bSCy Schubert static auth_gssapi_log_badauth2_func log_badauth2 = NULL;
71*7f2fe78bSCy Schubert static caddr_t log_badauth2_data = NULL;
72*7f2fe78bSCy Schubert static auth_gssapi_log_badverf_func log_badverf = NULL;
73*7f2fe78bSCy Schubert static caddr_t log_badverf_data = NULL;
74*7f2fe78bSCy Schubert static auth_gssapi_log_miscerr_func log_miscerr = NULL;
75*7f2fe78bSCy Schubert static caddr_t log_miscerr_data = NULL;
76*7f2fe78bSCy Schubert 
77*7f2fe78bSCy Schubert #define LOG_MISCERR(arg) if (log_miscerr) \
78*7f2fe78bSCy Schubert         (*log_miscerr)(rqst, msg, arg, log_miscerr_data)
79*7f2fe78bSCy Schubert 
80*7f2fe78bSCy Schubert static bool_t	svcauth_gss_destroy(SVCAUTH *);
81*7f2fe78bSCy Schubert static bool_t   svcauth_gss_wrap(SVCAUTH *, XDR *, xdrproc_t, caddr_t);
82*7f2fe78bSCy Schubert static bool_t   svcauth_gss_unwrap(SVCAUTH *, XDR *, xdrproc_t, caddr_t);
83*7f2fe78bSCy Schubert 
84*7f2fe78bSCy Schubert static bool_t	svcauth_gss_nextverf(struct svc_req *, u_int);
85*7f2fe78bSCy Schubert 
86*7f2fe78bSCy Schubert struct svc_auth_ops svc_auth_gss_ops = {
87*7f2fe78bSCy Schubert 	svcauth_gss_wrap,
88*7f2fe78bSCy Schubert 	svcauth_gss_unwrap,
89*7f2fe78bSCy Schubert 	svcauth_gss_destroy
90*7f2fe78bSCy Schubert };
91*7f2fe78bSCy Schubert 
92*7f2fe78bSCy Schubert struct svc_rpc_gss_data {
93*7f2fe78bSCy Schubert 	bool_t			established;	/* context established */
94*7f2fe78bSCy Schubert 	gss_cred_id_t		cred;		/* credential */
95*7f2fe78bSCy Schubert 	gss_ctx_id_t		ctx;		/* context id */
96*7f2fe78bSCy Schubert 	struct rpc_gss_sec	sec;		/* security triple */
97*7f2fe78bSCy Schubert 	gss_buffer_desc		cname;		/* GSS client name */
98*7f2fe78bSCy Schubert 	u_int			seq;		/* sequence number */
99*7f2fe78bSCy Schubert 	u_int			win;		/* sequence window */
100*7f2fe78bSCy Schubert 	u_int			seqlast;	/* last sequence number */
101*7f2fe78bSCy Schubert 	uint32_t		seqmask;	/* bitmask of seqnums */
102*7f2fe78bSCy Schubert 	gss_name_t		client_name;	/* unparsed name string */
103*7f2fe78bSCy Schubert 	gss_buffer_desc		checksum;	/* so we can free it */
104*7f2fe78bSCy Schubert };
105*7f2fe78bSCy Schubert 
106*7f2fe78bSCy Schubert #define SVCAUTH_PRIVATE(auth) \
107*7f2fe78bSCy Schubert 	(*(struct svc_rpc_gss_data **)&(auth)->svc_ah_private)
108*7f2fe78bSCy Schubert 
109*7f2fe78bSCy Schubert /* Global server credentials. */
110*7f2fe78bSCy Schubert static gss_name_t	svcauth_gss_name = NULL;
111*7f2fe78bSCy Schubert 
112*7f2fe78bSCy Schubert bool_t
svcauth_gss_set_svc_name(gss_name_t name)113*7f2fe78bSCy Schubert svcauth_gss_set_svc_name(gss_name_t name)
114*7f2fe78bSCy Schubert {
115*7f2fe78bSCy Schubert 	OM_uint32	maj_stat, min_stat;
116*7f2fe78bSCy Schubert 
117*7f2fe78bSCy Schubert 	log_debug("in svcauth_gss_set_svc_name()");
118*7f2fe78bSCy Schubert 
119*7f2fe78bSCy Schubert 	if (svcauth_gss_name != NULL) {
120*7f2fe78bSCy Schubert 		maj_stat = gss_release_name(&min_stat, &svcauth_gss_name);
121*7f2fe78bSCy Schubert 
122*7f2fe78bSCy Schubert 		if (maj_stat != GSS_S_COMPLETE) {
123*7f2fe78bSCy Schubert 			log_status("gss_release_name", maj_stat, min_stat);
124*7f2fe78bSCy Schubert 			return (FALSE);
125*7f2fe78bSCy Schubert 		}
126*7f2fe78bSCy Schubert 		svcauth_gss_name = NULL;
127*7f2fe78bSCy Schubert 	}
128*7f2fe78bSCy Schubert 	if (svcauth_gss_name == GSS_C_NO_NAME)
129*7f2fe78bSCy Schubert 		return (TRUE);
130*7f2fe78bSCy Schubert 
131*7f2fe78bSCy Schubert 	maj_stat = gss_duplicate_name(&min_stat, name, &svcauth_gss_name);
132*7f2fe78bSCy Schubert 
133*7f2fe78bSCy Schubert 	if (maj_stat != GSS_S_COMPLETE) {
134*7f2fe78bSCy Schubert 		log_status("gss_duplicate_name", maj_stat, min_stat);
135*7f2fe78bSCy Schubert 		return (FALSE);
136*7f2fe78bSCy Schubert 	}
137*7f2fe78bSCy Schubert 
138*7f2fe78bSCy Schubert 	return (TRUE);
139*7f2fe78bSCy Schubert }
140*7f2fe78bSCy Schubert 
141*7f2fe78bSCy Schubert static bool_t
svcauth_gss_acquire_cred(struct svc_rpc_gss_data * gd)142*7f2fe78bSCy Schubert svcauth_gss_acquire_cred(struct svc_rpc_gss_data *gd)
143*7f2fe78bSCy Schubert {
144*7f2fe78bSCy Schubert 	OM_uint32	maj_stat, min_stat;
145*7f2fe78bSCy Schubert 
146*7f2fe78bSCy Schubert 	log_debug("in svcauth_gss_acquire_cred()");
147*7f2fe78bSCy Schubert 
148*7f2fe78bSCy Schubert 	/* We don't need to acquire a credential if using the default name. */
149*7f2fe78bSCy Schubert 	if (svcauth_gss_name == GSS_C_NO_NAME)
150*7f2fe78bSCy Schubert 		return (TRUE);
151*7f2fe78bSCy Schubert 
152*7f2fe78bSCy Schubert 	/* Only acquire a credential once per authentication. */
153*7f2fe78bSCy Schubert 	if (gd->cred != GSS_C_NO_CREDENTIAL)
154*7f2fe78bSCy Schubert 		return (TRUE);
155*7f2fe78bSCy Schubert 
156*7f2fe78bSCy Schubert 	maj_stat = gss_acquire_cred(&min_stat, svcauth_gss_name, 0,
157*7f2fe78bSCy Schubert 				    GSS_C_NULL_OID_SET, GSS_C_ACCEPT,
158*7f2fe78bSCy Schubert 				    &gd->cred, NULL, NULL);
159*7f2fe78bSCy Schubert 
160*7f2fe78bSCy Schubert 	if (maj_stat != GSS_S_COMPLETE) {
161*7f2fe78bSCy Schubert 		log_status("gss_acquire_cred", maj_stat, min_stat);
162*7f2fe78bSCy Schubert 		return (FALSE);
163*7f2fe78bSCy Schubert 	}
164*7f2fe78bSCy Schubert 	return (TRUE);
165*7f2fe78bSCy Schubert }
166*7f2fe78bSCy Schubert 
167*7f2fe78bSCy Schubert /* Invoke log_badauth callbacks for an authentication failure. */
168*7f2fe78bSCy Schubert static void
badauth(OM_uint32 maj,OM_uint32 minor,SVCXPRT * xprt)169*7f2fe78bSCy Schubert badauth(OM_uint32 maj, OM_uint32 minor, SVCXPRT *xprt)
170*7f2fe78bSCy Schubert {
171*7f2fe78bSCy Schubert 	if (log_badauth != NULL)
172*7f2fe78bSCy Schubert 		(*log_badauth)(maj, minor, &xprt->xp_raddr, log_badauth_data);
173*7f2fe78bSCy Schubert 	if (log_badauth2 != NULL)
174*7f2fe78bSCy Schubert 		(*log_badauth2)(maj, minor, xprt, log_badauth2_data);
175*7f2fe78bSCy Schubert }
176*7f2fe78bSCy Schubert 
177*7f2fe78bSCy Schubert static bool_t
svcauth_gss_accept_sec_context(struct svc_req * rqst,struct rpc_gss_init_res * gr)178*7f2fe78bSCy Schubert svcauth_gss_accept_sec_context(struct svc_req *rqst,
179*7f2fe78bSCy Schubert 			       struct rpc_gss_init_res *gr)
180*7f2fe78bSCy Schubert {
181*7f2fe78bSCy Schubert 	struct svc_rpc_gss_data	*gd;
182*7f2fe78bSCy Schubert 	struct rpc_gss_cred	*gc;
183*7f2fe78bSCy Schubert 	gss_buffer_desc		 recv_tok, seqbuf;
184*7f2fe78bSCy Schubert 	gss_OID			 mech;
185*7f2fe78bSCy Schubert 	OM_uint32		 maj_stat = 0, min_stat = 0, ret_flags, seq;
186*7f2fe78bSCy Schubert 
187*7f2fe78bSCy Schubert 	log_debug("in svcauth_gss_accept_context()");
188*7f2fe78bSCy Schubert 
189*7f2fe78bSCy Schubert 	gd = SVCAUTH_PRIVATE(rqst->rq_xprt->xp_auth);
190*7f2fe78bSCy Schubert 	gc = (struct rpc_gss_cred *)rqst->rq_clntcred;
191*7f2fe78bSCy Schubert 	memset(gr, 0, sizeof(*gr));
192*7f2fe78bSCy Schubert 
193*7f2fe78bSCy Schubert 	/* Deserialize arguments. */
194*7f2fe78bSCy Schubert 	memset(&recv_tok, 0, sizeof(recv_tok));
195*7f2fe78bSCy Schubert 
196*7f2fe78bSCy Schubert 	if (!svc_getargs(rqst->rq_xprt, xdr_rpc_gss_init_args,
197*7f2fe78bSCy Schubert 			 (caddr_t)&recv_tok))
198*7f2fe78bSCy Schubert 		return (FALSE);
199*7f2fe78bSCy Schubert 
200*7f2fe78bSCy Schubert 	gr->gr_major = gss_accept_sec_context(&gr->gr_minor,
201*7f2fe78bSCy Schubert 					      &gd->ctx,
202*7f2fe78bSCy Schubert 					      gd->cred,
203*7f2fe78bSCy Schubert 					      &recv_tok,
204*7f2fe78bSCy Schubert 					      GSS_C_NO_CHANNEL_BINDINGS,
205*7f2fe78bSCy Schubert 					      &gd->client_name,
206*7f2fe78bSCy Schubert 					      &mech,
207*7f2fe78bSCy Schubert 					      &gr->gr_token,
208*7f2fe78bSCy Schubert 					      &ret_flags,
209*7f2fe78bSCy Schubert 					      NULL,
210*7f2fe78bSCy Schubert 					      NULL);
211*7f2fe78bSCy Schubert 
212*7f2fe78bSCy Schubert 	svc_freeargs(rqst->rq_xprt, xdr_rpc_gss_init_args, (caddr_t)&recv_tok);
213*7f2fe78bSCy Schubert 
214*7f2fe78bSCy Schubert 	log_status("accept_sec_context", gr->gr_major, gr->gr_minor);
215*7f2fe78bSCy Schubert 	if (gr->gr_major != GSS_S_COMPLETE &&
216*7f2fe78bSCy Schubert 	    gr->gr_major != GSS_S_CONTINUE_NEEDED) {
217*7f2fe78bSCy Schubert 		badauth(gr->gr_major, gr->gr_minor, rqst->rq_xprt);
218*7f2fe78bSCy Schubert 		gd->ctx = GSS_C_NO_CONTEXT;
219*7f2fe78bSCy Schubert 		goto errout;
220*7f2fe78bSCy Schubert 	}
221*7f2fe78bSCy Schubert 	gr->gr_ctx.value = "xxxx";
222*7f2fe78bSCy Schubert 	gr->gr_ctx.length = 4;
223*7f2fe78bSCy Schubert 
224*7f2fe78bSCy Schubert 	/* gr->gr_win = 0x00000005; ANDROS: for debugging linux kernel version...  */
225*7f2fe78bSCy Schubert 	gr->gr_win = sizeof(gd->seqmask) * 8;
226*7f2fe78bSCy Schubert 
227*7f2fe78bSCy Schubert 	/* Save client info. */
228*7f2fe78bSCy Schubert 	gd->sec.mech = mech;
229*7f2fe78bSCy Schubert 	gd->sec.qop = GSS_C_QOP_DEFAULT;
230*7f2fe78bSCy Schubert 	gd->sec.svc = gc->gc_svc;
231*7f2fe78bSCy Schubert 	gd->seq = gc->gc_seq;
232*7f2fe78bSCy Schubert 	gd->win = gr->gr_win;
233*7f2fe78bSCy Schubert 
234*7f2fe78bSCy Schubert 	if (gr->gr_major == GSS_S_COMPLETE) {
235*7f2fe78bSCy Schubert #ifdef SPKM
236*7f2fe78bSCy Schubert 		/* spkm3: no src_name (anonymous) */
237*7f2fe78bSCy Schubert 		if(!g_OID_equal(gss_mech_spkm3, mech)) {
238*7f2fe78bSCy Schubert #endif
239*7f2fe78bSCy Schubert 		    maj_stat = gss_display_name(&min_stat, gd->client_name,
240*7f2fe78bSCy Schubert 					    &gd->cname, &gd->sec.mech);
241*7f2fe78bSCy Schubert #ifdef SPKM
242*7f2fe78bSCy Schubert 		}
243*7f2fe78bSCy Schubert #endif
244*7f2fe78bSCy Schubert 		if (maj_stat != GSS_S_COMPLETE) {
245*7f2fe78bSCy Schubert 			log_status("display_name", maj_stat, min_stat);
246*7f2fe78bSCy Schubert 			goto errout;
247*7f2fe78bSCy Schubert 		}
248*7f2fe78bSCy Schubert #ifdef DEBUG
249*7f2fe78bSCy Schubert #ifdef HAVE_HEIMDAL
250*7f2fe78bSCy Schubert 		log_debug("accepted context for %.*s with "
251*7f2fe78bSCy Schubert 			  "<mech {}, qop %d, svc %d>",
252*7f2fe78bSCy Schubert 			  gd->cname.length, (char *)gd->cname.value,
253*7f2fe78bSCy Schubert 			  gd->sec.qop, gd->sec.svc);
254*7f2fe78bSCy Schubert #else
255*7f2fe78bSCy Schubert 		{
256*7f2fe78bSCy Schubert 			gss_buffer_desc mechname;
257*7f2fe78bSCy Schubert 
258*7f2fe78bSCy Schubert 			gss_oid_to_str(&min_stat, mech, &mechname);
259*7f2fe78bSCy Schubert 
260*7f2fe78bSCy Schubert 			log_debug("accepted context for %.*s with "
261*7f2fe78bSCy Schubert 				  "<mech %.*s, qop %d, svc %d>",
262*7f2fe78bSCy Schubert 				  gd->cname.length, (char *)gd->cname.value,
263*7f2fe78bSCy Schubert 				  mechname.length, (char *)mechname.value,
264*7f2fe78bSCy Schubert 				  gd->sec.qop, gd->sec.svc);
265*7f2fe78bSCy Schubert 
266*7f2fe78bSCy Schubert 			gss_release_buffer(&min_stat, &mechname);
267*7f2fe78bSCy Schubert 		}
268*7f2fe78bSCy Schubert #endif
269*7f2fe78bSCy Schubert #endif /* DEBUG */
270*7f2fe78bSCy Schubert 		seq = htonl(gr->gr_win);
271*7f2fe78bSCy Schubert 		seqbuf.value = &seq;
272*7f2fe78bSCy Schubert 		seqbuf.length = sizeof(seq);
273*7f2fe78bSCy Schubert 
274*7f2fe78bSCy Schubert 		gss_release_buffer(&min_stat, &gd->checksum);
275*7f2fe78bSCy Schubert 		maj_stat = gss_sign(&min_stat, gd->ctx, GSS_C_QOP_DEFAULT,
276*7f2fe78bSCy Schubert 				    &seqbuf, &gd->checksum);
277*7f2fe78bSCy Schubert 
278*7f2fe78bSCy Schubert 		if (maj_stat != GSS_S_COMPLETE) {
279*7f2fe78bSCy Schubert 			goto errout;
280*7f2fe78bSCy Schubert 		}
281*7f2fe78bSCy Schubert 
282*7f2fe78bSCy Schubert 
283*7f2fe78bSCy Schubert 		rqst->rq_xprt->xp_verf.oa_flavor = RPCSEC_GSS;
284*7f2fe78bSCy Schubert 		rqst->rq_xprt->xp_verf.oa_base = gd->checksum.value;
285*7f2fe78bSCy Schubert 		rqst->rq_xprt->xp_verf.oa_length = gd->checksum.length;
286*7f2fe78bSCy Schubert 	}
287*7f2fe78bSCy Schubert 	return (TRUE);
288*7f2fe78bSCy Schubert errout:
289*7f2fe78bSCy Schubert 	gss_release_buffer(&min_stat, &gr->gr_token);
290*7f2fe78bSCy Schubert 	return (FALSE);
291*7f2fe78bSCy Schubert }
292*7f2fe78bSCy Schubert 
293*7f2fe78bSCy Schubert static bool_t
svcauth_gss_validate(struct svc_req * rqst,struct svc_rpc_gss_data * gd,struct rpc_msg * msg)294*7f2fe78bSCy Schubert svcauth_gss_validate(struct svc_req *rqst, struct svc_rpc_gss_data *gd, struct rpc_msg *msg)
295*7f2fe78bSCy Schubert {
296*7f2fe78bSCy Schubert 	struct opaque_auth	*oa;
297*7f2fe78bSCy Schubert 	gss_buffer_desc		 rpcbuf, checksum;
298*7f2fe78bSCy Schubert 	OM_uint32		 maj_stat, min_stat, qop_state;
299*7f2fe78bSCy Schubert 	u_char			 rpchdr[128];
300*7f2fe78bSCy Schubert 	int32_t			*buf;
301*7f2fe78bSCy Schubert 
302*7f2fe78bSCy Schubert 	log_debug("in svcauth_gss_validate()");
303*7f2fe78bSCy Schubert 
304*7f2fe78bSCy Schubert 	memset(rpchdr, 0, sizeof(rpchdr));
305*7f2fe78bSCy Schubert 
306*7f2fe78bSCy Schubert 	/* XXX - Reconstruct RPC header for signing (from xdr_callmsg). */
307*7f2fe78bSCy Schubert 	oa = &msg->rm_call.cb_cred;
308*7f2fe78bSCy Schubert 	if (oa->oa_length > MAX_AUTH_BYTES)
309*7f2fe78bSCy Schubert 		return (FALSE);
310*7f2fe78bSCy Schubert 
311*7f2fe78bSCy Schubert 	/* 8 XDR units from the IXDR macro calls. */
312*7f2fe78bSCy Schubert 	if (sizeof(rpchdr) < (8 * BYTES_PER_XDR_UNIT +
313*7f2fe78bSCy Schubert 			      RNDUP(oa->oa_length)))
314*7f2fe78bSCy Schubert 		return (FALSE);
315*7f2fe78bSCy Schubert 
316*7f2fe78bSCy Schubert 	buf = (int32_t *)(void *)rpchdr;
317*7f2fe78bSCy Schubert 	IXDR_PUT_LONG(buf, msg->rm_xid);
318*7f2fe78bSCy Schubert 	IXDR_PUT_ENUM(buf, msg->rm_direction);
319*7f2fe78bSCy Schubert 	IXDR_PUT_LONG(buf, msg->rm_call.cb_rpcvers);
320*7f2fe78bSCy Schubert 	IXDR_PUT_LONG(buf, msg->rm_call.cb_prog);
321*7f2fe78bSCy Schubert 	IXDR_PUT_LONG(buf, msg->rm_call.cb_vers);
322*7f2fe78bSCy Schubert 	IXDR_PUT_LONG(buf, msg->rm_call.cb_proc);
323*7f2fe78bSCy Schubert 	IXDR_PUT_ENUM(buf, oa->oa_flavor);
324*7f2fe78bSCy Schubert 	IXDR_PUT_LONG(buf, oa->oa_length);
325*7f2fe78bSCy Schubert 	if (oa->oa_length) {
326*7f2fe78bSCy Schubert 		memcpy((caddr_t)buf, oa->oa_base, oa->oa_length);
327*7f2fe78bSCy Schubert 		buf += RNDUP(oa->oa_length) / sizeof(int32_t);
328*7f2fe78bSCy Schubert 	}
329*7f2fe78bSCy Schubert 	rpcbuf.value = rpchdr;
330*7f2fe78bSCy Schubert 	rpcbuf.length = (u_char *)buf - rpchdr;
331*7f2fe78bSCy Schubert 
332*7f2fe78bSCy Schubert 	checksum.value = msg->rm_call.cb_verf.oa_base;
333*7f2fe78bSCy Schubert 	checksum.length = msg->rm_call.cb_verf.oa_length;
334*7f2fe78bSCy Schubert 
335*7f2fe78bSCy Schubert 	maj_stat = gss_verify_mic(&min_stat, gd->ctx, &rpcbuf, &checksum,
336*7f2fe78bSCy Schubert 				  &qop_state);
337*7f2fe78bSCy Schubert 
338*7f2fe78bSCy Schubert 	if (maj_stat != GSS_S_COMPLETE) {
339*7f2fe78bSCy Schubert 		log_status("gss_verify_mic", maj_stat, min_stat);
340*7f2fe78bSCy Schubert 		if (log_badverf != NULL)
341*7f2fe78bSCy Schubert 			(*log_badverf)(gd->client_name,
342*7f2fe78bSCy Schubert 			       svcauth_gss_name,
343*7f2fe78bSCy Schubert 			       rqst, msg, log_badverf_data);
344*7f2fe78bSCy Schubert 		return (FALSE);
345*7f2fe78bSCy Schubert 	}
346*7f2fe78bSCy Schubert 	return (TRUE);
347*7f2fe78bSCy Schubert }
348*7f2fe78bSCy Schubert 
349*7f2fe78bSCy Schubert static bool_t
svcauth_gss_nextverf(struct svc_req * rqst,u_int num)350*7f2fe78bSCy Schubert svcauth_gss_nextverf(struct svc_req *rqst, u_int num)
351*7f2fe78bSCy Schubert {
352*7f2fe78bSCy Schubert 	struct svc_rpc_gss_data	*gd;
353*7f2fe78bSCy Schubert 	gss_buffer_desc		 signbuf;
354*7f2fe78bSCy Schubert 	OM_uint32		 maj_stat, min_stat;
355*7f2fe78bSCy Schubert 
356*7f2fe78bSCy Schubert 	log_debug("in svcauth_gss_nextverf()");
357*7f2fe78bSCy Schubert 
358*7f2fe78bSCy Schubert 	if (rqst->rq_xprt->xp_auth == NULL)
359*7f2fe78bSCy Schubert 		return (FALSE);
360*7f2fe78bSCy Schubert 
361*7f2fe78bSCy Schubert 	gd = SVCAUTH_PRIVATE(rqst->rq_xprt->xp_auth);
362*7f2fe78bSCy Schubert 
363*7f2fe78bSCy Schubert 	gss_release_buffer(&min_stat, &gd->checksum);
364*7f2fe78bSCy Schubert 
365*7f2fe78bSCy Schubert 	signbuf.value = &num;
366*7f2fe78bSCy Schubert 	signbuf.length = sizeof(num);
367*7f2fe78bSCy Schubert 
368*7f2fe78bSCy Schubert 	maj_stat = gss_get_mic(&min_stat, gd->ctx, gd->sec.qop,
369*7f2fe78bSCy Schubert 			       &signbuf, &gd->checksum);
370*7f2fe78bSCy Schubert 
371*7f2fe78bSCy Schubert 	if (maj_stat != GSS_S_COMPLETE) {
372*7f2fe78bSCy Schubert 		log_status("gss_get_mic", maj_stat, min_stat);
373*7f2fe78bSCy Schubert 		return (FALSE);
374*7f2fe78bSCy Schubert 	}
375*7f2fe78bSCy Schubert 	rqst->rq_xprt->xp_verf.oa_flavor = RPCSEC_GSS;
376*7f2fe78bSCy Schubert 	rqst->rq_xprt->xp_verf.oa_base = (caddr_t)gd->checksum.value;
377*7f2fe78bSCy Schubert 	rqst->rq_xprt->xp_verf.oa_length = (u_int)gd->checksum.length;
378*7f2fe78bSCy Schubert 
379*7f2fe78bSCy Schubert 	return (TRUE);
380*7f2fe78bSCy Schubert }
381*7f2fe78bSCy Schubert 
382*7f2fe78bSCy Schubert enum auth_stat
gssrpc__svcauth_gss(struct svc_req * rqst,struct rpc_msg * msg,bool_t * no_dispatch)383*7f2fe78bSCy Schubert gssrpc__svcauth_gss(struct svc_req *rqst, struct rpc_msg *msg,
384*7f2fe78bSCy Schubert 	bool_t *no_dispatch)
385*7f2fe78bSCy Schubert {
386*7f2fe78bSCy Schubert 	enum auth_stat		 retstat;
387*7f2fe78bSCy Schubert 	XDR	 		 xdrs;
388*7f2fe78bSCy Schubert 	SVCAUTH			*auth;
389*7f2fe78bSCy Schubert 	struct svc_rpc_gss_data	*gd;
390*7f2fe78bSCy Schubert 	struct rpc_gss_cred	*gc;
391*7f2fe78bSCy Schubert 	struct rpc_gss_init_res	 gr;
392*7f2fe78bSCy Schubert 	int			 call_stat, offset;
393*7f2fe78bSCy Schubert 	OM_uint32		 min_stat;
394*7f2fe78bSCy Schubert 
395*7f2fe78bSCy Schubert 	log_debug("in svcauth_gss()");
396*7f2fe78bSCy Schubert 
397*7f2fe78bSCy Schubert 	/* Initialize reply. */
398*7f2fe78bSCy Schubert 	rqst->rq_xprt->xp_verf = gssrpc__null_auth;
399*7f2fe78bSCy Schubert 
400*7f2fe78bSCy Schubert 	/* Allocate and set up server auth handle. */
401*7f2fe78bSCy Schubert 	if (rqst->rq_xprt->xp_auth == NULL ||
402*7f2fe78bSCy Schubert 	    rqst->rq_xprt->xp_auth == &svc_auth_none) {
403*7f2fe78bSCy Schubert 		if ((auth = calloc(sizeof(*auth), 1)) == NULL) {
404*7f2fe78bSCy Schubert 			fprintf(stderr, "svcauth_gss: out_of_memory\n");
405*7f2fe78bSCy Schubert 			return (AUTH_FAILED);
406*7f2fe78bSCy Schubert 		}
407*7f2fe78bSCy Schubert 		if ((gd = calloc(sizeof(*gd), 1)) == NULL) {
408*7f2fe78bSCy Schubert 			fprintf(stderr, "svcauth_gss: out_of_memory\n");
409*7f2fe78bSCy Schubert 			return (AUTH_FAILED);
410*7f2fe78bSCy Schubert 		}
411*7f2fe78bSCy Schubert 		auth->svc_ah_ops = &svc_auth_gss_ops;
412*7f2fe78bSCy Schubert 		SVCAUTH_PRIVATE(auth) = gd;
413*7f2fe78bSCy Schubert 		rqst->rq_xprt->xp_auth = auth;
414*7f2fe78bSCy Schubert 	}
415*7f2fe78bSCy Schubert 	else gd = SVCAUTH_PRIVATE(rqst->rq_xprt->xp_auth);
416*7f2fe78bSCy Schubert 
417*7f2fe78bSCy Schubert 	log_debug("xp_auth=%p, gd=%p", rqst->rq_xprt->xp_auth, gd);
418*7f2fe78bSCy Schubert 
419*7f2fe78bSCy Schubert 	/* Deserialize client credentials. */
420*7f2fe78bSCy Schubert 	if (rqst->rq_cred.oa_length <= 0)
421*7f2fe78bSCy Schubert 		return (AUTH_BADCRED);
422*7f2fe78bSCy Schubert 
423*7f2fe78bSCy Schubert 	gc = (struct rpc_gss_cred *)rqst->rq_clntcred;
424*7f2fe78bSCy Schubert 	memset(gc, 0, sizeof(*gc));
425*7f2fe78bSCy Schubert 
426*7f2fe78bSCy Schubert 	log_debug("calling xdrmem_create()");
427*7f2fe78bSCy Schubert 	log_debug("oa_base=%p, oa_length=%u", rqst->rq_cred.oa_base,
428*7f2fe78bSCy Schubert 		  rqst->rq_cred.oa_length);
429*7f2fe78bSCy Schubert 	xdrmem_create(&xdrs, rqst->rq_cred.oa_base,
430*7f2fe78bSCy Schubert 		      rqst->rq_cred.oa_length, XDR_DECODE);
431*7f2fe78bSCy Schubert 	log_debug("xdrmem_create() returned");
432*7f2fe78bSCy Schubert 
433*7f2fe78bSCy Schubert 	if (!xdr_rpc_gss_cred(&xdrs, gc)) {
434*7f2fe78bSCy Schubert 		log_debug("xdr_rpc_gss_cred() failed");
435*7f2fe78bSCy Schubert 		XDR_DESTROY(&xdrs);
436*7f2fe78bSCy Schubert 		return (AUTH_BADCRED);
437*7f2fe78bSCy Schubert 	}
438*7f2fe78bSCy Schubert 	XDR_DESTROY(&xdrs);
439*7f2fe78bSCy Schubert 
440*7f2fe78bSCy Schubert 	retstat = AUTH_FAILED;
441*7f2fe78bSCy Schubert 
442*7f2fe78bSCy Schubert #define ret_freegc(code) do { retstat = code; goto freegc; } while (0)
443*7f2fe78bSCy Schubert 
444*7f2fe78bSCy Schubert 	/* Check version. */
445*7f2fe78bSCy Schubert 	if (gc->gc_v != RPCSEC_GSS_VERSION)
446*7f2fe78bSCy Schubert 		ret_freegc (AUTH_BADCRED);
447*7f2fe78bSCy Schubert 
448*7f2fe78bSCy Schubert 	/* Check RPCSEC_GSS service. */
449*7f2fe78bSCy Schubert 	if (gc->gc_svc != RPCSEC_GSS_SVC_NONE &&
450*7f2fe78bSCy Schubert 	    gc->gc_svc != RPCSEC_GSS_SVC_INTEGRITY &&
451*7f2fe78bSCy Schubert 	    gc->gc_svc != RPCSEC_GSS_SVC_PRIVACY)
452*7f2fe78bSCy Schubert 		ret_freegc (AUTH_BADCRED);
453*7f2fe78bSCy Schubert 
454*7f2fe78bSCy Schubert 	/* Check sequence number. */
455*7f2fe78bSCy Schubert 	if (gd->established) {
456*7f2fe78bSCy Schubert 		if (gc->gc_seq > MAXSEQ)
457*7f2fe78bSCy Schubert 			ret_freegc (RPCSEC_GSS_CTXPROBLEM);
458*7f2fe78bSCy Schubert 
459*7f2fe78bSCy Schubert 		if ((offset = gd->seqlast - gc->gc_seq) < 0) {
460*7f2fe78bSCy Schubert 			gd->seqlast = gc->gc_seq;
461*7f2fe78bSCy Schubert 			offset = 0 - offset;
462*7f2fe78bSCy Schubert 			gd->seqmask <<= offset;
463*7f2fe78bSCy Schubert 			offset = 0;
464*7f2fe78bSCy Schubert 		} else if ((u_int)offset >= gd->win ||
465*7f2fe78bSCy Schubert 			   (gd->seqmask & (1 << offset))) {
466*7f2fe78bSCy Schubert 			*no_dispatch = 1;
467*7f2fe78bSCy Schubert 			ret_freegc (RPCSEC_GSS_CTXPROBLEM);
468*7f2fe78bSCy Schubert 		}
469*7f2fe78bSCy Schubert 		gd->seq = gc->gc_seq;
470*7f2fe78bSCy Schubert 		gd->seqmask |= (1 << offset);
471*7f2fe78bSCy Schubert 	}
472*7f2fe78bSCy Schubert 
473*7f2fe78bSCy Schubert 	if (gd->established) {
474*7f2fe78bSCy Schubert 		rqst->rq_clntname = (char *)gd->client_name;
475*7f2fe78bSCy Schubert 		rqst->rq_svccred = (char *)gd->ctx;
476*7f2fe78bSCy Schubert 	}
477*7f2fe78bSCy Schubert 
478*7f2fe78bSCy Schubert 	/* Handle RPCSEC_GSS control procedure. */
479*7f2fe78bSCy Schubert 	switch (gc->gc_proc) {
480*7f2fe78bSCy Schubert 
481*7f2fe78bSCy Schubert 	case RPCSEC_GSS_INIT:
482*7f2fe78bSCy Schubert 	case RPCSEC_GSS_CONTINUE_INIT:
483*7f2fe78bSCy Schubert 		if (rqst->rq_proc != NULLPROC)
484*7f2fe78bSCy Schubert 			ret_freegc (AUTH_FAILED);		/* XXX ? */
485*7f2fe78bSCy Schubert 
486*7f2fe78bSCy Schubert 		if (!svcauth_gss_acquire_cred(gd))
487*7f2fe78bSCy Schubert 			ret_freegc (AUTH_FAILED);
488*7f2fe78bSCy Schubert 
489*7f2fe78bSCy Schubert 		if (!svcauth_gss_accept_sec_context(rqst, &gr))
490*7f2fe78bSCy Schubert 			ret_freegc (AUTH_REJECTEDCRED);
491*7f2fe78bSCy Schubert 
492*7f2fe78bSCy Schubert 		if (!svcauth_gss_nextverf(rqst, htonl(gr.gr_win))) {
493*7f2fe78bSCy Schubert 			gss_release_buffer(&min_stat, &gr.gr_token);
494*7f2fe78bSCy Schubert 			ret_freegc (AUTH_FAILED);
495*7f2fe78bSCy Schubert 		}
496*7f2fe78bSCy Schubert 		*no_dispatch = TRUE;
497*7f2fe78bSCy Schubert 
498*7f2fe78bSCy Schubert 		call_stat = svc_sendreply(rqst->rq_xprt, xdr_rpc_gss_init_res,
499*7f2fe78bSCy Schubert 					  (caddr_t)&gr);
500*7f2fe78bSCy Schubert 
501*7f2fe78bSCy Schubert 		gss_release_buffer(&min_stat, &gr.gr_token);
502*7f2fe78bSCy Schubert 		gss_release_buffer(&min_stat, &gd->checksum);
503*7f2fe78bSCy Schubert 		if (!call_stat)
504*7f2fe78bSCy Schubert 			ret_freegc (AUTH_FAILED);
505*7f2fe78bSCy Schubert 
506*7f2fe78bSCy Schubert 		if (gr.gr_major == GSS_S_COMPLETE)
507*7f2fe78bSCy Schubert 			gd->established = TRUE;
508*7f2fe78bSCy Schubert 
509*7f2fe78bSCy Schubert 		break;
510*7f2fe78bSCy Schubert 
511*7f2fe78bSCy Schubert 	case RPCSEC_GSS_DATA:
512*7f2fe78bSCy Schubert 		if (!svcauth_gss_validate(rqst, gd, msg))
513*7f2fe78bSCy Schubert 			ret_freegc (RPCSEC_GSS_CREDPROBLEM);
514*7f2fe78bSCy Schubert 
515*7f2fe78bSCy Schubert 		if (!svcauth_gss_nextverf(rqst, htonl(gc->gc_seq)))
516*7f2fe78bSCy Schubert  			ret_freegc (AUTH_FAILED);
517*7f2fe78bSCy Schubert 		break;
518*7f2fe78bSCy Schubert 
519*7f2fe78bSCy Schubert 	case RPCSEC_GSS_DESTROY:
520*7f2fe78bSCy Schubert 		if (rqst->rq_proc != NULLPROC)
521*7f2fe78bSCy Schubert 			ret_freegc (AUTH_FAILED);		/* XXX ? */
522*7f2fe78bSCy Schubert 
523*7f2fe78bSCy Schubert 		if (!svcauth_gss_validate(rqst, gd, msg))
524*7f2fe78bSCy Schubert 			ret_freegc (RPCSEC_GSS_CREDPROBLEM);
525*7f2fe78bSCy Schubert 
526*7f2fe78bSCy Schubert 		if (!svcauth_gss_nextverf(rqst, htonl(gc->gc_seq)))
527*7f2fe78bSCy Schubert 			ret_freegc (AUTH_FAILED);
528*7f2fe78bSCy Schubert 
529*7f2fe78bSCy Schubert 		*no_dispatch = TRUE;
530*7f2fe78bSCy Schubert 
531*7f2fe78bSCy Schubert 		call_stat = svc_sendreply(rqst->rq_xprt,
532*7f2fe78bSCy Schubert 					  xdr_void, (caddr_t)NULL);
533*7f2fe78bSCy Schubert 
534*7f2fe78bSCy Schubert 		log_debug("sendreply in destroy: %d", call_stat);
535*7f2fe78bSCy Schubert 
536*7f2fe78bSCy Schubert 		SVCAUTH_DESTROY(rqst->rq_xprt->xp_auth);
537*7f2fe78bSCy Schubert 		rqst->rq_xprt->xp_auth = &svc_auth_none;
538*7f2fe78bSCy Schubert 
539*7f2fe78bSCy Schubert 		break;
540*7f2fe78bSCy Schubert 
541*7f2fe78bSCy Schubert 	default:
542*7f2fe78bSCy Schubert 		ret_freegc (AUTH_REJECTEDCRED);
543*7f2fe78bSCy Schubert 		break;
544*7f2fe78bSCy Schubert 	}
545*7f2fe78bSCy Schubert 	retstat = AUTH_OK;
546*7f2fe78bSCy Schubert freegc:
547*7f2fe78bSCy Schubert 	xdr_free(xdr_rpc_gss_cred, gc);
548*7f2fe78bSCy Schubert 	log_debug("returning %d from svcauth_gss()", retstat);
549*7f2fe78bSCy Schubert 	return (retstat);
550*7f2fe78bSCy Schubert }
551*7f2fe78bSCy Schubert 
552*7f2fe78bSCy Schubert static bool_t
svcauth_gss_destroy(SVCAUTH * auth)553*7f2fe78bSCy Schubert svcauth_gss_destroy(SVCAUTH *auth)
554*7f2fe78bSCy Schubert {
555*7f2fe78bSCy Schubert 	struct svc_rpc_gss_data	*gd;
556*7f2fe78bSCy Schubert 	OM_uint32		 min_stat;
557*7f2fe78bSCy Schubert 
558*7f2fe78bSCy Schubert 	log_debug("in svcauth_gss_destroy()");
559*7f2fe78bSCy Schubert 
560*7f2fe78bSCy Schubert 	gd = SVCAUTH_PRIVATE(auth);
561*7f2fe78bSCy Schubert 
562*7f2fe78bSCy Schubert 	gss_delete_sec_context(&min_stat, &gd->ctx, GSS_C_NO_BUFFER);
563*7f2fe78bSCy Schubert 	gss_release_cred(&min_stat, &gd->cred);
564*7f2fe78bSCy Schubert 	gss_release_buffer(&min_stat, &gd->cname);
565*7f2fe78bSCy Schubert 	gss_release_buffer(&min_stat, &gd->checksum);
566*7f2fe78bSCy Schubert 
567*7f2fe78bSCy Schubert 	if (gd->client_name)
568*7f2fe78bSCy Schubert 		gss_release_name(&min_stat, &gd->client_name);
569*7f2fe78bSCy Schubert 
570*7f2fe78bSCy Schubert 	mem_free(gd, sizeof(*gd));
571*7f2fe78bSCy Schubert 	mem_free(auth, sizeof(*auth));
572*7f2fe78bSCy Schubert 
573*7f2fe78bSCy Schubert 	return (TRUE);
574*7f2fe78bSCy Schubert }
575*7f2fe78bSCy Schubert 
576*7f2fe78bSCy Schubert static bool_t
svcauth_gss_wrap(SVCAUTH * auth,XDR * xdrs,xdrproc_t xdr_func,caddr_t xdr_ptr)577*7f2fe78bSCy Schubert svcauth_gss_wrap(SVCAUTH *auth, XDR *xdrs, xdrproc_t xdr_func, caddr_t xdr_ptr)
578*7f2fe78bSCy Schubert {
579*7f2fe78bSCy Schubert 	struct svc_rpc_gss_data	*gd;
580*7f2fe78bSCy Schubert 
581*7f2fe78bSCy Schubert 	log_debug("in svcauth_gss_wrap()");
582*7f2fe78bSCy Schubert 
583*7f2fe78bSCy Schubert 	gd = SVCAUTH_PRIVATE(auth);
584*7f2fe78bSCy Schubert 
585*7f2fe78bSCy Schubert 	if (!gd->established || gd->sec.svc == RPCSEC_GSS_SVC_NONE) {
586*7f2fe78bSCy Schubert 		return ((*xdr_func)(xdrs, xdr_ptr));
587*7f2fe78bSCy Schubert 	}
588*7f2fe78bSCy Schubert 	return (xdr_rpc_gss_data(xdrs, xdr_func, xdr_ptr,
589*7f2fe78bSCy Schubert 				 gd->ctx, gd->sec.qop,
590*7f2fe78bSCy Schubert 				 gd->sec.svc, gd->seq));
591*7f2fe78bSCy Schubert }
592*7f2fe78bSCy Schubert 
593*7f2fe78bSCy Schubert static bool_t
svcauth_gss_unwrap(SVCAUTH * auth,XDR * xdrs,xdrproc_t xdr_func,caddr_t xdr_ptr)594*7f2fe78bSCy Schubert svcauth_gss_unwrap(SVCAUTH *auth, XDR *xdrs, xdrproc_t xdr_func, caddr_t xdr_ptr)
595*7f2fe78bSCy Schubert {
596*7f2fe78bSCy Schubert 	struct svc_rpc_gss_data	*gd;
597*7f2fe78bSCy Schubert 
598*7f2fe78bSCy Schubert 	log_debug("in svcauth_gss_unwrap()");
599*7f2fe78bSCy Schubert 
600*7f2fe78bSCy Schubert 	gd = SVCAUTH_PRIVATE(auth);
601*7f2fe78bSCy Schubert 
602*7f2fe78bSCy Schubert 	if (!gd->established || gd->sec.svc == RPCSEC_GSS_SVC_NONE) {
603*7f2fe78bSCy Schubert 		return ((*xdr_func)(xdrs, xdr_ptr));
604*7f2fe78bSCy Schubert 	}
605*7f2fe78bSCy Schubert 	return (xdr_rpc_gss_data(xdrs, xdr_func, xdr_ptr,
606*7f2fe78bSCy Schubert 				 gd->ctx, gd->sec.qop,
607*7f2fe78bSCy Schubert 				 gd->sec.svc, gd->seq));
608*7f2fe78bSCy Schubert }
609*7f2fe78bSCy Schubert 
610*7f2fe78bSCy Schubert char *
svcauth_gss_get_principal(SVCAUTH * auth)611*7f2fe78bSCy Schubert svcauth_gss_get_principal(SVCAUTH *auth)
612*7f2fe78bSCy Schubert {
613*7f2fe78bSCy Schubert 	struct svc_rpc_gss_data *gd;
614*7f2fe78bSCy Schubert 	char *pname;
615*7f2fe78bSCy Schubert 
616*7f2fe78bSCy Schubert 	gd = SVCAUTH_PRIVATE(auth);
617*7f2fe78bSCy Schubert 
618*7f2fe78bSCy Schubert 	if (gd->cname.length == 0 || gd->cname.length >= SIZE_MAX)
619*7f2fe78bSCy Schubert 		return (NULL);
620*7f2fe78bSCy Schubert 
621*7f2fe78bSCy Schubert 	if ((pname = malloc(gd->cname.length + 1)) == NULL)
622*7f2fe78bSCy Schubert 		return (NULL);
623*7f2fe78bSCy Schubert 
624*7f2fe78bSCy Schubert 	memcpy(pname, gd->cname.value, gd->cname.length);
625*7f2fe78bSCy Schubert 	pname[gd->cname.length] = '\0';
626*7f2fe78bSCy Schubert 
627*7f2fe78bSCy Schubert 	return (pname);
628*7f2fe78bSCy Schubert }
629*7f2fe78bSCy Schubert 
630*7f2fe78bSCy Schubert /*
631*7f2fe78bSCy Schubert  * Function: svcauth_gss_set_log_badauth_func
632*7f2fe78bSCy Schubert  *
633*7f2fe78bSCy Schubert  * Purpose: sets the logging function called when an invalid RPC call
634*7f2fe78bSCy Schubert  * arrives
635*7f2fe78bSCy Schubert  *
636*7f2fe78bSCy Schubert  * See functional specifications.
637*7f2fe78bSCy Schubert  */
svcauth_gss_set_log_badauth_func(auth_gssapi_log_badauth_func func,caddr_t data)638*7f2fe78bSCy Schubert void svcauth_gss_set_log_badauth_func(
639*7f2fe78bSCy Schubert 	auth_gssapi_log_badauth_func func,
640*7f2fe78bSCy Schubert 	caddr_t data)
641*7f2fe78bSCy Schubert {
642*7f2fe78bSCy Schubert 	log_badauth = func;
643*7f2fe78bSCy Schubert 	log_badauth_data = data;
644*7f2fe78bSCy Schubert }
645*7f2fe78bSCy Schubert 
646*7f2fe78bSCy Schubert void
svcauth_gss_set_log_badauth2_func(auth_gssapi_log_badauth2_func func,caddr_t data)647*7f2fe78bSCy Schubert svcauth_gss_set_log_badauth2_func(auth_gssapi_log_badauth2_func func,
648*7f2fe78bSCy Schubert 				  caddr_t data)
649*7f2fe78bSCy Schubert {
650*7f2fe78bSCy Schubert 	log_badauth2 = func;
651*7f2fe78bSCy Schubert 	log_badauth2_data = data;
652*7f2fe78bSCy Schubert }
653*7f2fe78bSCy Schubert 
654*7f2fe78bSCy Schubert /*
655*7f2fe78bSCy Schubert  * Function: svcauth_gss_set_log_badverf_func
656*7f2fe78bSCy Schubert  *
657*7f2fe78bSCy Schubert  * Purpose: sets the logging function called when an invalid RPC call
658*7f2fe78bSCy Schubert  * arrives
659*7f2fe78bSCy Schubert  *
660*7f2fe78bSCy Schubert  * See functional specifications.
661*7f2fe78bSCy Schubert  */
svcauth_gss_set_log_badverf_func(auth_gssapi_log_badverf_func func,caddr_t data)662*7f2fe78bSCy Schubert void svcauth_gss_set_log_badverf_func(
663*7f2fe78bSCy Schubert 	auth_gssapi_log_badverf_func func,
664*7f2fe78bSCy Schubert 	caddr_t data)
665*7f2fe78bSCy Schubert {
666*7f2fe78bSCy Schubert 	log_badverf = func;
667*7f2fe78bSCy Schubert 	log_badverf_data = data;
668*7f2fe78bSCy Schubert }
669*7f2fe78bSCy Schubert 
670*7f2fe78bSCy Schubert /*
671*7f2fe78bSCy Schubert  * Function: svcauth_gss_set_log_miscerr_func
672*7f2fe78bSCy Schubert  *
673*7f2fe78bSCy Schubert  * Purpose: sets the logging function called when a miscellaneous
674*7f2fe78bSCy Schubert  * AUTH_GSSAPI error occurs
675*7f2fe78bSCy Schubert  *
676*7f2fe78bSCy Schubert  * See functional specifications.
677*7f2fe78bSCy Schubert  */
svcauth_gss_set_log_miscerr_func(auth_gssapi_log_miscerr_func func,caddr_t data)678*7f2fe78bSCy Schubert void svcauth_gss_set_log_miscerr_func(
679*7f2fe78bSCy Schubert 	auth_gssapi_log_miscerr_func func,
680*7f2fe78bSCy Schubert 	caddr_t data)
681*7f2fe78bSCy Schubert {
682*7f2fe78bSCy Schubert 	log_miscerr = func;
683*7f2fe78bSCy Schubert 	log_miscerr_data = data;
684*7f2fe78bSCy Schubert }
685