1*7f2fe78bSCy Schubert /*
2*7f2fe78bSCy Schubert * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved.
3*7f2fe78bSCy Schubert *
4*7f2fe78bSCy Schubert * $Id$
5*7f2fe78bSCy Schubert *
6*7f2fe78bSCy Schubert */
7*7f2fe78bSCy Schubert
8*7f2fe78bSCy Schubert /*
9*7f2fe78bSCy Schubert * svc_auth_gssapi.c
10*7f2fe78bSCy Schubert * Handles the GSS-API flavor authentication parameters on the service
11*7f2fe78bSCy Schubert * side of RPC.
12*7f2fe78bSCy Schubert */
13*7f2fe78bSCy Schubert
14*7f2fe78bSCy Schubert #include <stdio.h>
15*7f2fe78bSCy Schubert #include <errno.h>
16*7f2fe78bSCy Schubert #include <string.h>
17*7f2fe78bSCy Schubert #include <gssrpc/rpc.h>
18*7f2fe78bSCy Schubert #include <sys/stat.h>
19*7f2fe78bSCy Schubert
20*7f2fe78bSCy Schubert #include <gssapi/gssapi_generic.h>
21*7f2fe78bSCy Schubert #include <gssrpc/auth_gssapi.h>
22*7f2fe78bSCy Schubert
23*7f2fe78bSCy Schubert #ifdef GSS_BACKWARD_HACK
24*7f2fe78bSCy Schubert #include <gssapi/gssapi_krb5.h>
25*7f2fe78bSCy Schubert #endif
26*7f2fe78bSCy Schubert
27*7f2fe78bSCy Schubert #include "gssrpcint.h"
28*7f2fe78bSCy Schubert
29*7f2fe78bSCy Schubert #ifdef GSSAPI_KRB5
30*7f2fe78bSCy Schubert /* This is here for the krb5_error_code typedef and the
31*7f2fe78bSCy Schubert * KRB5KRB_AP_ERR_NOT_US #define.*/
32*7f2fe78bSCy Schubert #include <krb5.h>
33*7f2fe78bSCy Schubert #endif
34*7f2fe78bSCy Schubert
35*7f2fe78bSCy Schubert #include <sys/file.h>
36*7f2fe78bSCy Schubert #include <fcntl.h>
37*7f2fe78bSCy Schubert #include <time.h>
38*7f2fe78bSCy Schubert
39*7f2fe78bSCy Schubert #define INITIATION_TIMEOUT 60*15 /* seconds until partially created */
40*7f2fe78bSCy Schubert /* context is destroed */
41*7f2fe78bSCy Schubert #define INDEF_EXPIRE 60*60*24 /* seconds until an context with no */
42*7f2fe78bSCy Schubert /* expiration time is expired */
43*7f2fe78bSCy Schubert
44*7f2fe78bSCy Schubert #ifdef __CODECENTER__
45*7f2fe78bSCy Schubert #define DEBUG_GSSAPI 1
46*7f2fe78bSCy Schubert #endif
47*7f2fe78bSCy Schubert
48*7f2fe78bSCy Schubert #ifdef DEBUG_GSSAPI
49*7f2fe78bSCy Schubert int svc_debug_gssapi = DEBUG_GSSAPI;
gssrpcint_printf(const char * format,...)50*7f2fe78bSCy Schubert void gssrpcint_printf(const char *format, ...)
51*7f2fe78bSCy Schubert {
52*7f2fe78bSCy Schubert va_list ap;
53*7f2fe78bSCy Schubert va_start(ap, format);
54*7f2fe78bSCy Schubert #if 1
55*7f2fe78bSCy Schubert vprintf(format, ap);
56*7f2fe78bSCy Schubert #else
57*7f2fe78bSCy Schubert {
58*7f2fe78bSCy Schubert static FILE *f;
59*7f2fe78bSCy Schubert if (f == NULL)
60*7f2fe78bSCy Schubert f = fopen("/dev/pts/4", "a");
61*7f2fe78bSCy Schubert if (f) {
62*7f2fe78bSCy Schubert vfprintf(f, format, ap);
63*7f2fe78bSCy Schubert fflush(f);
64*7f2fe78bSCy Schubert }
65*7f2fe78bSCy Schubert }
66*7f2fe78bSCy Schubert #endif
67*7f2fe78bSCy Schubert va_end(ap);
68*7f2fe78bSCy Schubert }
69*7f2fe78bSCy Schubert #define L_PRINTF(l,args) if (svc_debug_gssapi >= l) gssrpcint_printf args
70*7f2fe78bSCy Schubert #define PRINTF(args) L_PRINTF(99, args)
71*7f2fe78bSCy Schubert #define AUTH_GSSAPI_DISPLAY_STATUS(args) \
72*7f2fe78bSCy Schubert if (svc_debug_gssapi) auth_gssapi_display_status args
73*7f2fe78bSCy Schubert #else
74*7f2fe78bSCy Schubert #define PRINTF(args)
75*7f2fe78bSCy Schubert #define L_PRINTF(l, args)
76*7f2fe78bSCy Schubert #define AUTH_GSSAPI_DISPLAY_STATUS(args)
77*7f2fe78bSCy Schubert #endif
78*7f2fe78bSCy Schubert
79*7f2fe78bSCy Schubert typedef struct _svc_auth_gssapi_data {
80*7f2fe78bSCy Schubert bool_t established;
81*7f2fe78bSCy Schubert
82*7f2fe78bSCy Schubert gss_ctx_id_t context;
83*7f2fe78bSCy Schubert gss_name_t client_name, server_name;
84*7f2fe78bSCy Schubert gss_cred_id_t server_creds;
85*7f2fe78bSCy Schubert
86*7f2fe78bSCy Schubert uint32_t expiration;
87*7f2fe78bSCy Schubert uint32_t seq_num;
88*7f2fe78bSCy Schubert uint32_t key;
89*7f2fe78bSCy Schubert
90*7f2fe78bSCy Schubert SVCAUTH svcauth;
91*7f2fe78bSCy Schubert
92*7f2fe78bSCy Schubert /* kludge to free verifiers on next call */
93*7f2fe78bSCy Schubert gss_buffer_desc prev_verf;
94*7f2fe78bSCy Schubert } svc_auth_gssapi_data;
95*7f2fe78bSCy Schubert
96*7f2fe78bSCy Schubert #define SVCAUTH_PRIVATE(auth) \
97*7f2fe78bSCy Schubert ((svc_auth_gssapi_data *)(auth)->svc_ah_private)
98*7f2fe78bSCy Schubert
99*7f2fe78bSCy Schubert static bool_t svc_auth_gssapi_wrap(SVCAUTH *, XDR *, xdrproc_t, caddr_t);
100*7f2fe78bSCy Schubert static bool_t svc_auth_gssapi_unwrap(SVCAUTH *, XDR *, xdrproc_t, caddr_t);
101*7f2fe78bSCy Schubert static bool_t svc_auth_gssapi_destroy(SVCAUTH *);
102*7f2fe78bSCy Schubert
103*7f2fe78bSCy Schubert static svc_auth_gssapi_data *create_client(void);
104*7f2fe78bSCy Schubert static svc_auth_gssapi_data *get_client
105*7f2fe78bSCy Schubert (gss_buffer_t client_handle);
106*7f2fe78bSCy Schubert static void destroy_client
107*7f2fe78bSCy Schubert (svc_auth_gssapi_data *client_data);
108*7f2fe78bSCy Schubert static void clean_client(void), cleanup(void);
109*7f2fe78bSCy Schubert static void client_expire
110*7f2fe78bSCy Schubert (svc_auth_gssapi_data *client_data, uint32_t exp);
111*7f2fe78bSCy Schubert static void dump_db (char *msg);
112*7f2fe78bSCy Schubert
113*7f2fe78bSCy Schubert struct svc_auth_ops svc_auth_gssapi_ops = {
114*7f2fe78bSCy Schubert svc_auth_gssapi_wrap,
115*7f2fe78bSCy Schubert svc_auth_gssapi_unwrap,
116*7f2fe78bSCy Schubert svc_auth_gssapi_destroy
117*7f2fe78bSCy Schubert };
118*7f2fe78bSCy Schubert
119*7f2fe78bSCy Schubert /*
120*7f2fe78bSCy Schubert * Globals! Eeek! Run for the hills!
121*7f2fe78bSCy Schubert */
122*7f2fe78bSCy Schubert static gss_cred_id_t *server_creds_list = NULL;
123*7f2fe78bSCy Schubert static gss_name_t *server_name_list = NULL;
124*7f2fe78bSCy Schubert static int server_creds_count = 0;
125*7f2fe78bSCy Schubert
126*7f2fe78bSCy Schubert static auth_gssapi_log_badauth_func log_badauth = NULL;
127*7f2fe78bSCy Schubert static caddr_t log_badauth_data = NULL;
128*7f2fe78bSCy Schubert static auth_gssapi_log_badauth2_func log_badauth2 = NULL;
129*7f2fe78bSCy Schubert static caddr_t log_badauth2_data = NULL;
130*7f2fe78bSCy Schubert static auth_gssapi_log_badverf_func log_badverf = NULL;
131*7f2fe78bSCy Schubert static caddr_t log_badverf_data = NULL;
132*7f2fe78bSCy Schubert static auth_gssapi_log_miscerr_func log_miscerr = NULL;
133*7f2fe78bSCy Schubert static caddr_t log_miscerr_data = NULL;
134*7f2fe78bSCy Schubert
135*7f2fe78bSCy Schubert #define LOG_MISCERR(arg) if (log_miscerr) \
136*7f2fe78bSCy Schubert (*log_miscerr)(rqst, msg, arg, log_miscerr_data)
137*7f2fe78bSCy Schubert
138*7f2fe78bSCy Schubert typedef struct _client_list {
139*7f2fe78bSCy Schubert svc_auth_gssapi_data *client;
140*7f2fe78bSCy Schubert struct _client_list *next;
141*7f2fe78bSCy Schubert } client_list;
142*7f2fe78bSCy Schubert
143*7f2fe78bSCy Schubert static client_list *clients = NULL;
144*7f2fe78bSCy Schubert
145*7f2fe78bSCy Schubert
146*7f2fe78bSCy Schubert /* Invoke log_badauth callbacks for an authentication failure. */
147*7f2fe78bSCy Schubert static void
badauth(OM_uint32 maj,OM_uint32 minor,SVCXPRT * xprt)148*7f2fe78bSCy Schubert badauth(OM_uint32 maj, OM_uint32 minor, SVCXPRT *xprt)
149*7f2fe78bSCy Schubert {
150*7f2fe78bSCy Schubert if (log_badauth != NULL)
151*7f2fe78bSCy Schubert (*log_badauth)(maj, minor, &xprt->xp_raddr, log_badauth_data);
152*7f2fe78bSCy Schubert if (log_badauth2 != NULL)
153*7f2fe78bSCy Schubert (*log_badauth2)(maj, minor, xprt, log_badauth2_data);
154*7f2fe78bSCy Schubert }
155*7f2fe78bSCy Schubert
gssrpc__svcauth_gssapi(struct svc_req * rqst,struct rpc_msg * msg,bool_t * no_dispatch)156*7f2fe78bSCy Schubert enum auth_stat gssrpc__svcauth_gssapi(
157*7f2fe78bSCy Schubert struct svc_req *rqst,
158*7f2fe78bSCy Schubert struct rpc_msg *msg,
159*7f2fe78bSCy Schubert bool_t *no_dispatch)
160*7f2fe78bSCy Schubert {
161*7f2fe78bSCy Schubert XDR xdrs;
162*7f2fe78bSCy Schubert auth_gssapi_creds creds;
163*7f2fe78bSCy Schubert auth_gssapi_init_arg call_arg;
164*7f2fe78bSCy Schubert auth_gssapi_init_res call_res;
165*7f2fe78bSCy Schubert gss_buffer_desc output_token, in_buf, out_buf;
166*7f2fe78bSCy Schubert gss_cred_id_t server_creds;
167*7f2fe78bSCy Schubert struct gss_channel_bindings_struct bindings, *bindp;
168*7f2fe78bSCy Schubert OM_uint32 gssstat, minor_stat, time_rec;
169*7f2fe78bSCy Schubert struct opaque_auth *cred, *verf;
170*7f2fe78bSCy Schubert svc_auth_gssapi_data *client_data;
171*7f2fe78bSCy Schubert int i;
172*7f2fe78bSCy Schubert enum auth_stat ret;
173*7f2fe78bSCy Schubert OM_uint32 ret_flags;
174*7f2fe78bSCy Schubert uint32_t seq_num;
175*7f2fe78bSCy Schubert
176*7f2fe78bSCy Schubert PRINTF(("svcauth_gssapi: starting\n"));
177*7f2fe78bSCy Schubert
178*7f2fe78bSCy Schubert /* clean up expired entries */
179*7f2fe78bSCy Schubert clean_client();
180*7f2fe78bSCy Schubert
181*7f2fe78bSCy Schubert /* use AUTH_NONE until there is a client_handle */
182*7f2fe78bSCy Schubert rqst->rq_xprt->xp_auth = &svc_auth_none;
183*7f2fe78bSCy Schubert
184*7f2fe78bSCy Schubert memset(&call_res, 0, sizeof(call_res));
185*7f2fe78bSCy Schubert creds.client_handle.length = 0;
186*7f2fe78bSCy Schubert creds.client_handle.value = NULL;
187*7f2fe78bSCy Schubert
188*7f2fe78bSCy Schubert cred = &msg->rm_call.cb_cred;
189*7f2fe78bSCy Schubert verf = &msg->rm_call.cb_verf;
190*7f2fe78bSCy Schubert
191*7f2fe78bSCy Schubert if (cred->oa_length == 0) {
192*7f2fe78bSCy Schubert PRINTF(("svcauth_gssapi: empty creds, failing\n"));
193*7f2fe78bSCy Schubert LOG_MISCERR("empty client credentials");
194*7f2fe78bSCy Schubert ret = AUTH_BADCRED;
195*7f2fe78bSCy Schubert goto error;
196*7f2fe78bSCy Schubert }
197*7f2fe78bSCy Schubert
198*7f2fe78bSCy Schubert PRINTF(("svcauth_gssapi: decoding credentials\n"));
199*7f2fe78bSCy Schubert xdrmem_create(&xdrs, cred->oa_base, cred->oa_length, XDR_DECODE);
200*7f2fe78bSCy Schubert memset(&creds, 0, sizeof(creds));
201*7f2fe78bSCy Schubert if (! xdr_authgssapi_creds(&xdrs, &creds)) {
202*7f2fe78bSCy Schubert PRINTF(("svcauth_gssapi: failed decoding creds\n"));
203*7f2fe78bSCy Schubert LOG_MISCERR("protocol error in client credentials");
204*7f2fe78bSCy Schubert xdr_free(xdr_authgssapi_creds, &creds);
205*7f2fe78bSCy Schubert XDR_DESTROY(&xdrs);
206*7f2fe78bSCy Schubert ret = AUTH_BADCRED;
207*7f2fe78bSCy Schubert goto error;
208*7f2fe78bSCy Schubert }
209*7f2fe78bSCy Schubert XDR_DESTROY(&xdrs);
210*7f2fe78bSCy Schubert
211*7f2fe78bSCy Schubert PRINTF(("svcauth_gssapi: got credentials, version %d, client_handle len %d\n",
212*7f2fe78bSCy Schubert creds.version, (int) creds.client_handle.length));
213*7f2fe78bSCy Schubert
214*7f2fe78bSCy Schubert if (creds.version != 2) {
215*7f2fe78bSCy Schubert PRINTF(("svcauth_gssapi: bad credential version\n"));
216*7f2fe78bSCy Schubert LOG_MISCERR("unsupported client credentials version");
217*7f2fe78bSCy Schubert ret = AUTH_BADCRED;
218*7f2fe78bSCy Schubert goto error;
219*7f2fe78bSCy Schubert }
220*7f2fe78bSCy Schubert
221*7f2fe78bSCy Schubert #ifdef DEBUG_GSSAPI
222*7f2fe78bSCy Schubert if (svc_debug_gssapi) {
223*7f2fe78bSCy Schubert if (creds.auth_msg && rqst->rq_proc == AUTH_GSSAPI_EXIT) {
224*7f2fe78bSCy Schubert PRINTF(("svcauth_gssapi: GSSAPI_EXIT, cleaning up\n"));
225*7f2fe78bSCy Schubert svc_sendreply(rqst->rq_xprt, xdr_void, NULL);
226*7f2fe78bSCy Schubert xdr_free(xdr_authgssapi_creds, &creds);
227*7f2fe78bSCy Schubert cleanup();
228*7f2fe78bSCy Schubert exit(0);
229*7f2fe78bSCy Schubert }
230*7f2fe78bSCy Schubert }
231*7f2fe78bSCy Schubert #endif
232*7f2fe78bSCy Schubert
233*7f2fe78bSCy Schubert /*
234*7f2fe78bSCy Schubert * If this is an auth_msg and proc is GSSAPI_INIT, then create a
235*7f2fe78bSCy Schubert * client handle for this client. Otherwise, look up the
236*7f2fe78bSCy Schubert * existing handle.
237*7f2fe78bSCy Schubert */
238*7f2fe78bSCy Schubert if (creds.auth_msg && rqst->rq_proc == AUTH_GSSAPI_INIT) {
239*7f2fe78bSCy Schubert if (creds.client_handle.length != 0) {
240*7f2fe78bSCy Schubert PRINTF(("svcauth_gssapi: non-empty handle on GSSAPI_INIT\n"));
241*7f2fe78bSCy Schubert LOG_MISCERR("protocol error in client handle");
242*7f2fe78bSCy Schubert ret = AUTH_FAILED;
243*7f2fe78bSCy Schubert goto error;
244*7f2fe78bSCy Schubert }
245*7f2fe78bSCy Schubert
246*7f2fe78bSCy Schubert PRINTF(("svcauth_gssapi: GSSAPI_INIT, creating client.\n"));
247*7f2fe78bSCy Schubert
248*7f2fe78bSCy Schubert client_data = create_client();
249*7f2fe78bSCy Schubert if (client_data == NULL) {
250*7f2fe78bSCy Schubert PRINTF(("svcauth_gssapi: create_client failed\n"));
251*7f2fe78bSCy Schubert LOG_MISCERR("internal error creating client record");
252*7f2fe78bSCy Schubert ret = AUTH_FAILED;
253*7f2fe78bSCy Schubert goto error;
254*7f2fe78bSCy Schubert }
255*7f2fe78bSCy Schubert } else {
256*7f2fe78bSCy Schubert if (creds.client_handle.length == 0) {
257*7f2fe78bSCy Schubert PRINTF(("svcauth_gssapi: expected non-empty creds\n"));
258*7f2fe78bSCy Schubert LOG_MISCERR("protocol error in client credentials");
259*7f2fe78bSCy Schubert ret = AUTH_FAILED;
260*7f2fe78bSCy Schubert goto error;
261*7f2fe78bSCy Schubert }
262*7f2fe78bSCy Schubert
263*7f2fe78bSCy Schubert PRINTF(("svcauth_gssapi: incoming client_handle %d, len %d\n",
264*7f2fe78bSCy Schubert *((uint32_t *) creds.client_handle.value),
265*7f2fe78bSCy Schubert (int) creds.client_handle.length));
266*7f2fe78bSCy Schubert
267*7f2fe78bSCy Schubert client_data = get_client(&creds.client_handle);
268*7f2fe78bSCy Schubert if (client_data == NULL) {
269*7f2fe78bSCy Schubert PRINTF(("svcauth_gssapi: client_handle lookup failed\n"));
270*7f2fe78bSCy Schubert LOG_MISCERR("invalid client handle received");
271*7f2fe78bSCy Schubert ret = AUTH_BADCRED;
272*7f2fe78bSCy Schubert goto error;
273*7f2fe78bSCy Schubert }
274*7f2fe78bSCy Schubert PRINTF(("svcauth_gssapi: client_handle lookup succeeded\n"));
275*7f2fe78bSCy Schubert }
276*7f2fe78bSCy Schubert
277*7f2fe78bSCy Schubert /* any response we send will use client_handle, so set it now */
278*7f2fe78bSCy Schubert call_res.client_handle.length = sizeof(client_data->key);
279*7f2fe78bSCy Schubert call_res.client_handle.value = (char *) &client_data->key;
280*7f2fe78bSCy Schubert
281*7f2fe78bSCy Schubert /* mark this call as using AUTH_GSSAPI via client_data's SVCAUTH */
282*7f2fe78bSCy Schubert rqst->rq_xprt->xp_auth = &client_data->svcauth;
283*7f2fe78bSCy Schubert
284*7f2fe78bSCy Schubert if (client_data->established == FALSE) {
285*7f2fe78bSCy Schubert PRINTF(("svcauth_gssapi: context is not established\n"));
286*7f2fe78bSCy Schubert
287*7f2fe78bSCy Schubert if (creds.auth_msg == FALSE) {
288*7f2fe78bSCy Schubert PRINTF(("svcauth_gssapi: expected auth_msg TRUE\n"));
289*7f2fe78bSCy Schubert LOG_MISCERR("protocol error on incomplete connection");
290*7f2fe78bSCy Schubert ret = AUTH_REJECTEDCRED;
291*7f2fe78bSCy Schubert goto error;
292*7f2fe78bSCy Schubert }
293*7f2fe78bSCy Schubert
294*7f2fe78bSCy Schubert /*
295*7f2fe78bSCy Schubert * If the context is not established, then only GSSAPI_INIT
296*7f2fe78bSCy Schubert * and _CONTINUE requests are valid.
297*7f2fe78bSCy Schubert */
298*7f2fe78bSCy Schubert if (rqst->rq_proc != AUTH_GSSAPI_INIT && rqst->rq_proc !=
299*7f2fe78bSCy Schubert AUTH_GSSAPI_CONTINUE_INIT) {
300*7f2fe78bSCy Schubert PRINTF(("svcauth_gssapi: unacceptable procedure %d\n",
301*7f2fe78bSCy Schubert rqst->rq_proc));
302*7f2fe78bSCy Schubert LOG_MISCERR("protocol error on incomplete connection");
303*7f2fe78bSCy Schubert ret = AUTH_FAILED;
304*7f2fe78bSCy Schubert goto error;
305*7f2fe78bSCy Schubert }
306*7f2fe78bSCy Schubert
307*7f2fe78bSCy Schubert /* call is for us, deserialize arguments */
308*7f2fe78bSCy Schubert memset(&call_arg, 0, sizeof(call_arg));
309*7f2fe78bSCy Schubert if (! svc_getargs(rqst->rq_xprt, xdr_authgssapi_init_arg,
310*7f2fe78bSCy Schubert &call_arg)) {
311*7f2fe78bSCy Schubert PRINTF(("svcauth_gssapi: cannot decode args\n"));
312*7f2fe78bSCy Schubert LOG_MISCERR("protocol error in procedure arguments");
313*7f2fe78bSCy Schubert ret = AUTH_BADCRED;
314*7f2fe78bSCy Schubert goto error;
315*7f2fe78bSCy Schubert }
316*7f2fe78bSCy Schubert
317*7f2fe78bSCy Schubert /*
318*7f2fe78bSCy Schubert * Process the call arg version number.
319*7f2fe78bSCy Schubert *
320*7f2fe78bSCy Schubert * Set the krb5_gss backwards-compatibility mode based on client
321*7f2fe78bSCy Schubert * version. This controls whether the AP_REP message is
322*7f2fe78bSCy Schubert * encrypted with the session key (version 2+, correct) or the
323*7f2fe78bSCy Schubert * session subkey (version 1, incorrect). This function can
324*7f2fe78bSCy Schubert * never fail, so we don't bother checking its return value.
325*7f2fe78bSCy Schubert */
326*7f2fe78bSCy Schubert switch (call_arg.version) {
327*7f2fe78bSCy Schubert case 1:
328*7f2fe78bSCy Schubert case 2:
329*7f2fe78bSCy Schubert LOG_MISCERR("Warning: Accepted old RPC protocol request");
330*7f2fe78bSCy Schubert call_res.version = 1;
331*7f2fe78bSCy Schubert break;
332*7f2fe78bSCy Schubert case 3:
333*7f2fe78bSCy Schubert case 4:
334*7f2fe78bSCy Schubert /* 3 and 4 are essentially the same, don't bother warning */
335*7f2fe78bSCy Schubert call_res.version = call_arg.version;
336*7f2fe78bSCy Schubert break;
337*7f2fe78bSCy Schubert default:
338*7f2fe78bSCy Schubert PRINTF(("svcauth_gssapi: bad GSSAPI_INIT version\n"));
339*7f2fe78bSCy Schubert LOG_MISCERR("unsupported GSSAPI_INIT version");
340*7f2fe78bSCy Schubert ret = AUTH_BADCRED;
341*7f2fe78bSCy Schubert goto error;
342*7f2fe78bSCy Schubert }
343*7f2fe78bSCy Schubert
344*7f2fe78bSCy Schubert #ifdef GSS_BACKWARD_HACK
345*7f2fe78bSCy Schubert krb5_gss_set_backward_mode(&minor_stat, call_arg.version == 1);
346*7f2fe78bSCy Schubert #endif
347*7f2fe78bSCy Schubert
348*7f2fe78bSCy Schubert if (call_arg.version >= 3) {
349*7f2fe78bSCy Schubert memset(&bindings, 0, sizeof(bindings));
350*7f2fe78bSCy Schubert bindings.application_data.length = 0;
351*7f2fe78bSCy Schubert bindings.initiator_addrtype = GSS_C_AF_INET;
352*7f2fe78bSCy Schubert bindings.initiator_address.length = 4;
353*7f2fe78bSCy Schubert bindings.initiator_address.value =
354*7f2fe78bSCy Schubert &svc_getcaller(rqst->rq_xprt)->sin_addr.s_addr;
355*7f2fe78bSCy Schubert
356*7f2fe78bSCy Schubert if (rqst->rq_xprt->xp_laddrlen > 0) {
357*7f2fe78bSCy Schubert bindings.acceptor_addrtype = GSS_C_AF_INET;
358*7f2fe78bSCy Schubert bindings.acceptor_address.length = 4;
359*7f2fe78bSCy Schubert bindings.acceptor_address.value =
360*7f2fe78bSCy Schubert &rqst->rq_xprt->xp_laddr.sin_addr.s_addr;
361*7f2fe78bSCy Schubert } else {
362*7f2fe78bSCy Schubert LOG_MISCERR("cannot get local address");
363*7f2fe78bSCy Schubert ret = AUTH_FAILED;
364*7f2fe78bSCy Schubert goto error;
365*7f2fe78bSCy Schubert }
366*7f2fe78bSCy Schubert
367*7f2fe78bSCy Schubert
368*7f2fe78bSCy Schubert bindp = &bindings;
369*7f2fe78bSCy Schubert } else {
370*7f2fe78bSCy Schubert bindp = GSS_C_NO_CHANNEL_BINDINGS;
371*7f2fe78bSCy Schubert }
372*7f2fe78bSCy Schubert
373*7f2fe78bSCy Schubert /*
374*7f2fe78bSCy Schubert * If the client's server_creds is already set, use it.
375*7f2fe78bSCy Schubert * Otherwise, try each credential in server_creds_list until
376*7f2fe78bSCy Schubert * one of them succeeds, then set the client server_creds
377*7f2fe78bSCy Schubert * to that. If all fail, the client's server_creds isn't
378*7f2fe78bSCy Schubert * set (which is fine, because the client will be gc'ed
379*7f2fe78bSCy Schubert * anyway).
380*7f2fe78bSCy Schubert *
381*7f2fe78bSCy Schubert * If accept_sec_context returns something other than
382*7f2fe78bSCy Schubert * success and GSS_S_FAILURE, then assume different
383*7f2fe78bSCy Schubert * credentials won't help and stop looping.
384*7f2fe78bSCy Schubert *
385*7f2fe78bSCy Schubert * Note that there are really two cases here: (1) the client
386*7f2fe78bSCy Schubert * has a server_creds already, and (2) it does not. They
387*7f2fe78bSCy Schubert * are both written in the same loop so that there is only
388*7f2fe78bSCy Schubert * one textual call to gss_accept_sec_context; in fact, in
389*7f2fe78bSCy Schubert * case (1), the loop is executed exactly once.
390*7f2fe78bSCy Schubert */
391*7f2fe78bSCy Schubert for (i = 0; i < server_creds_count; i++) {
392*7f2fe78bSCy Schubert if (client_data->server_creds != NULL) {
393*7f2fe78bSCy Schubert PRINTF(("svcauth_gssapi: using's clients server_creds\n"));
394*7f2fe78bSCy Schubert server_creds = client_data->server_creds;
395*7f2fe78bSCy Schubert } else {
396*7f2fe78bSCy Schubert PRINTF(("svcauth_gssapi: trying creds %d\n", i));
397*7f2fe78bSCy Schubert server_creds = server_creds_list[i];
398*7f2fe78bSCy Schubert }
399*7f2fe78bSCy Schubert
400*7f2fe78bSCy Schubert /* Free previous output_token from loop */
401*7f2fe78bSCy Schubert if(i != 0) gss_release_buffer(&minor_stat, &output_token);
402*7f2fe78bSCy Schubert
403*7f2fe78bSCy Schubert call_res.gss_major =
404*7f2fe78bSCy Schubert gss_accept_sec_context(&call_res.gss_minor,
405*7f2fe78bSCy Schubert &client_data->context,
406*7f2fe78bSCy Schubert server_creds,
407*7f2fe78bSCy Schubert &call_arg.token,
408*7f2fe78bSCy Schubert bindp,
409*7f2fe78bSCy Schubert &client_data->client_name,
410*7f2fe78bSCy Schubert NULL,
411*7f2fe78bSCy Schubert &output_token,
412*7f2fe78bSCy Schubert &ret_flags,
413*7f2fe78bSCy Schubert &time_rec,
414*7f2fe78bSCy Schubert NULL);
415*7f2fe78bSCy Schubert
416*7f2fe78bSCy Schubert if (server_creds == client_data->server_creds)
417*7f2fe78bSCy Schubert break;
418*7f2fe78bSCy Schubert
419*7f2fe78bSCy Schubert PRINTF(("accept_sec_context returned 0x%x 0x%x not-us=%#x\n",
420*7f2fe78bSCy Schubert call_res.gss_major, call_res.gss_minor,
421*7f2fe78bSCy Schubert (int) KRB5KRB_AP_ERR_NOT_US));
422*7f2fe78bSCy Schubert if (call_res.gss_major == GSS_S_COMPLETE ||
423*7f2fe78bSCy Schubert call_res.gss_major == GSS_S_CONTINUE_NEEDED) {
424*7f2fe78bSCy Schubert /* server_creds was right, set it! */
425*7f2fe78bSCy Schubert PRINTF(("svcauth_gssapi: creds are correct, storing\n"));
426*7f2fe78bSCy Schubert client_data->server_creds = server_creds;
427*7f2fe78bSCy Schubert client_data->server_name = server_name_list[i];
428*7f2fe78bSCy Schubert break;
429*7f2fe78bSCy Schubert } else if (call_res.gss_major != GSS_S_FAILURE
430*7f2fe78bSCy Schubert #ifdef GSSAPI_KRB5
431*7f2fe78bSCy Schubert /*
432*7f2fe78bSCy Schubert * hard-coded because there is no other way
433*7f2fe78bSCy Schubert * to prevent all GSS_S_FAILURES from
434*7f2fe78bSCy Schubert * returning a "wrong principal in request"
435*7f2fe78bSCy Schubert * error
436*7f2fe78bSCy Schubert */
437*7f2fe78bSCy Schubert || ((krb5_error_code) call_res.gss_minor !=
438*7f2fe78bSCy Schubert (krb5_error_code) KRB5KRB_AP_ERR_NOT_US)
439*7f2fe78bSCy Schubert #endif
440*7f2fe78bSCy Schubert ) {
441*7f2fe78bSCy Schubert break;
442*7f2fe78bSCy Schubert }
443*7f2fe78bSCy Schubert }
444*7f2fe78bSCy Schubert
445*7f2fe78bSCy Schubert gssstat = call_res.gss_major;
446*7f2fe78bSCy Schubert minor_stat = call_res.gss_minor;
447*7f2fe78bSCy Schubert
448*7f2fe78bSCy Schubert /* done with call args */
449*7f2fe78bSCy Schubert xdr_free(xdr_authgssapi_init_arg, &call_arg);
450*7f2fe78bSCy Schubert
451*7f2fe78bSCy Schubert PRINTF(("svcauth_gssapi: accept_sec_context returned %#x %#x\n",
452*7f2fe78bSCy Schubert call_res.gss_major, call_res.gss_minor));
453*7f2fe78bSCy Schubert if (call_res.gss_major != GSS_S_COMPLETE &&
454*7f2fe78bSCy Schubert call_res.gss_major != GSS_S_CONTINUE_NEEDED) {
455*7f2fe78bSCy Schubert AUTH_GSSAPI_DISPLAY_STATUS(("accepting context",
456*7f2fe78bSCy Schubert call_res.gss_major,
457*7f2fe78bSCy Schubert call_res.gss_minor));
458*7f2fe78bSCy Schubert
459*7f2fe78bSCy Schubert badauth(call_res.gss_major, call_res.gss_minor, rqst->rq_xprt);
460*7f2fe78bSCy Schubert
461*7f2fe78bSCy Schubert gss_release_buffer(&minor_stat, &output_token);
462*7f2fe78bSCy Schubert svc_sendreply(rqst->rq_xprt, xdr_authgssapi_init_res,
463*7f2fe78bSCy Schubert (caddr_t) &call_res);
464*7f2fe78bSCy Schubert *no_dispatch = TRUE;
465*7f2fe78bSCy Schubert ret = AUTH_OK;
466*7f2fe78bSCy Schubert goto error;
467*7f2fe78bSCy Schubert }
468*7f2fe78bSCy Schubert
469*7f2fe78bSCy Schubert if (output_token.length != 0) {
470*7f2fe78bSCy Schubert PRINTF(("svcauth_gssapi: got new output token\n"));
471*7f2fe78bSCy Schubert GSS_COPY_BUFFER(call_res.token, output_token);
472*7f2fe78bSCy Schubert }
473*7f2fe78bSCy Schubert
474*7f2fe78bSCy Schubert if (gssstat == GSS_S_COMPLETE) {
475*7f2fe78bSCy Schubert client_data->seq_num = rand();
476*7f2fe78bSCy Schubert client_expire(client_data,
477*7f2fe78bSCy Schubert (time_rec == GSS_C_INDEFINITE ?
478*7f2fe78bSCy Schubert INDEF_EXPIRE : time_rec) + time(0));
479*7f2fe78bSCy Schubert
480*7f2fe78bSCy Schubert PRINTF(("svcauth_gssapi: context established, isn %d\n",
481*7f2fe78bSCy Schubert client_data->seq_num));
482*7f2fe78bSCy Schubert
483*7f2fe78bSCy Schubert if (auth_gssapi_seal_seq(client_data->context,
484*7f2fe78bSCy Schubert client_data->seq_num,
485*7f2fe78bSCy Schubert &call_res.signed_isn) ==
486*7f2fe78bSCy Schubert FALSE) {
487*7f2fe78bSCy Schubert ret = AUTH_FAILED;
488*7f2fe78bSCy Schubert LOG_MISCERR("internal error sealing sequence number");
489*7f2fe78bSCy Schubert gss_release_buffer(&minor_stat, &output_token);
490*7f2fe78bSCy Schubert goto error;
491*7f2fe78bSCy Schubert }
492*7f2fe78bSCy Schubert }
493*7f2fe78bSCy Schubert
494*7f2fe78bSCy Schubert PRINTF(("svcauth_gssapi: sending reply\n"));
495*7f2fe78bSCy Schubert svc_sendreply(rqst->rq_xprt, xdr_authgssapi_init_res,
496*7f2fe78bSCy Schubert (caddr_t) &call_res);
497*7f2fe78bSCy Schubert *no_dispatch = TRUE;
498*7f2fe78bSCy Schubert
499*7f2fe78bSCy Schubert /*
500*7f2fe78bSCy Schubert * If appropriate, set established to TRUE *after* sending
501*7f2fe78bSCy Schubert * response (otherwise, the client will receive the final
502*7f2fe78bSCy Schubert * token encrypted)
503*7f2fe78bSCy Schubert */
504*7f2fe78bSCy Schubert if (gssstat == GSS_S_COMPLETE) {
505*7f2fe78bSCy Schubert gss_release_buffer(&minor_stat, &call_res.signed_isn);
506*7f2fe78bSCy Schubert client_data->established = TRUE;
507*7f2fe78bSCy Schubert }
508*7f2fe78bSCy Schubert gss_release_buffer(&minor_stat, &output_token);
509*7f2fe78bSCy Schubert } else {
510*7f2fe78bSCy Schubert PRINTF(("svcauth_gssapi: context is established\n"));
511*7f2fe78bSCy Schubert
512*7f2fe78bSCy Schubert /* check the verifier */
513*7f2fe78bSCy Schubert PRINTF(("svcauth_gssapi: checking verifier, len %d\n",
514*7f2fe78bSCy Schubert verf->oa_length));
515*7f2fe78bSCy Schubert
516*7f2fe78bSCy Schubert in_buf.length = verf->oa_length;
517*7f2fe78bSCy Schubert in_buf.value = verf->oa_base;
518*7f2fe78bSCy Schubert
519*7f2fe78bSCy Schubert if (auth_gssapi_unseal_seq(client_data->context, &in_buf,
520*7f2fe78bSCy Schubert &seq_num) == FALSE) {
521*7f2fe78bSCy Schubert ret = AUTH_BADVERF;
522*7f2fe78bSCy Schubert LOG_MISCERR("internal error unsealing sequence number");
523*7f2fe78bSCy Schubert goto error;
524*7f2fe78bSCy Schubert }
525*7f2fe78bSCy Schubert
526*7f2fe78bSCy Schubert if (seq_num != client_data->seq_num + 1) {
527*7f2fe78bSCy Schubert PRINTF(("svcauth_gssapi: expected isn %d, got %d\n",
528*7f2fe78bSCy Schubert client_data->seq_num + 1, seq_num));
529*7f2fe78bSCy Schubert if (log_badverf != NULL)
530*7f2fe78bSCy Schubert (*log_badverf)(client_data->client_name,
531*7f2fe78bSCy Schubert client_data->server_name,
532*7f2fe78bSCy Schubert rqst, msg, log_badverf_data);
533*7f2fe78bSCy Schubert
534*7f2fe78bSCy Schubert ret = AUTH_REJECTEDVERF;
535*7f2fe78bSCy Schubert goto error;
536*7f2fe78bSCy Schubert }
537*7f2fe78bSCy Schubert client_data->seq_num++;
538*7f2fe78bSCy Schubert
539*7f2fe78bSCy Schubert PRINTF(("svcauth_gssapi: seq_num %d okay\n", seq_num));
540*7f2fe78bSCy Schubert
541*7f2fe78bSCy Schubert /* free previous response verifier, if any */
542*7f2fe78bSCy Schubert if (client_data->prev_verf.length != 0) {
543*7f2fe78bSCy Schubert gss_release_buffer(&minor_stat, &client_data->prev_verf);
544*7f2fe78bSCy Schubert client_data->prev_verf.length = 0;
545*7f2fe78bSCy Schubert }
546*7f2fe78bSCy Schubert
547*7f2fe78bSCy Schubert /* prepare response verifier */
548*7f2fe78bSCy Schubert seq_num = client_data->seq_num + 1;
549*7f2fe78bSCy Schubert if (auth_gssapi_seal_seq(client_data->context, seq_num,
550*7f2fe78bSCy Schubert &out_buf) == FALSE) {
551*7f2fe78bSCy Schubert ret = AUTH_FAILED;
552*7f2fe78bSCy Schubert LOG_MISCERR("internal error sealing sequence number");
553*7f2fe78bSCy Schubert goto error;
554*7f2fe78bSCy Schubert }
555*7f2fe78bSCy Schubert
556*7f2fe78bSCy Schubert client_data->seq_num++;
557*7f2fe78bSCy Schubert
558*7f2fe78bSCy Schubert PRINTF(("svcauth_gssapi; response seq_num %d\n", seq_num));
559*7f2fe78bSCy Schubert
560*7f2fe78bSCy Schubert rqst->rq_xprt->xp_verf.oa_flavor = AUTH_GSSAPI;
561*7f2fe78bSCy Schubert rqst->rq_xprt->xp_verf.oa_base = out_buf.value;
562*7f2fe78bSCy Schubert rqst->rq_xprt->xp_verf.oa_length = out_buf.length;
563*7f2fe78bSCy Schubert
564*7f2fe78bSCy Schubert /* save verifier so it can be freed next time */
565*7f2fe78bSCy Schubert client_data->prev_verf.value = out_buf.value;
566*7f2fe78bSCy Schubert client_data->prev_verf.length = out_buf.length;
567*7f2fe78bSCy Schubert
568*7f2fe78bSCy Schubert /*
569*7f2fe78bSCy Schubert * Message is authentic. If auth_msg if true, process the
570*7f2fe78bSCy Schubert * call; otherwise, return AUTH_OK so it will be dispatched
571*7f2fe78bSCy Schubert * to the application server.
572*7f2fe78bSCy Schubert */
573*7f2fe78bSCy Schubert
574*7f2fe78bSCy Schubert if (creds.auth_msg == TRUE) {
575*7f2fe78bSCy Schubert /*
576*7f2fe78bSCy Schubert * If process_token fails, then the token probably came
577*7f2fe78bSCy Schubert * from an attacker. No response (error or otherwise)
578*7f2fe78bSCy Schubert * should be returned to the client, since it won't be
579*7f2fe78bSCy Schubert * accepting one.
580*7f2fe78bSCy Schubert */
581*7f2fe78bSCy Schubert
582*7f2fe78bSCy Schubert switch (rqst->rq_proc) {
583*7f2fe78bSCy Schubert case AUTH_GSSAPI_MSG:
584*7f2fe78bSCy Schubert PRINTF(("svcauth_gssapi: GSSAPI_MSG, getting args\n"));
585*7f2fe78bSCy Schubert memset(&call_arg, 0, sizeof(call_arg));
586*7f2fe78bSCy Schubert if (! svc_getargs(rqst->rq_xprt, xdr_authgssapi_init_arg,
587*7f2fe78bSCy Schubert &call_arg)) {
588*7f2fe78bSCy Schubert PRINTF(("svcauth_gssapi: cannot decode args\n"));
589*7f2fe78bSCy Schubert LOG_MISCERR("protocol error in call arguments");
590*7f2fe78bSCy Schubert xdr_free(xdr_authgssapi_init_arg, &call_arg);
591*7f2fe78bSCy Schubert ret = AUTH_BADCRED;
592*7f2fe78bSCy Schubert goto error;
593*7f2fe78bSCy Schubert }
594*7f2fe78bSCy Schubert
595*7f2fe78bSCy Schubert PRINTF(("svcauth_gssapi: processing token\n"));
596*7f2fe78bSCy Schubert gssstat = gss_process_context_token(&minor_stat,
597*7f2fe78bSCy Schubert client_data->context,
598*7f2fe78bSCy Schubert &call_arg.token);
599*7f2fe78bSCy Schubert
600*7f2fe78bSCy Schubert /* done with call args */
601*7f2fe78bSCy Schubert xdr_free(xdr_authgssapi_init_arg, &call_arg);
602*7f2fe78bSCy Schubert
603*7f2fe78bSCy Schubert if (gssstat != GSS_S_COMPLETE) {
604*7f2fe78bSCy Schubert AUTH_GSSAPI_DISPLAY_STATUS(("processing token",
605*7f2fe78bSCy Schubert gssstat, minor_stat));
606*7f2fe78bSCy Schubert ret = AUTH_FAILED;
607*7f2fe78bSCy Schubert goto error;
608*7f2fe78bSCy Schubert }
609*7f2fe78bSCy Schubert
610*7f2fe78bSCy Schubert svc_sendreply(rqst->rq_xprt, xdr_void, NULL);
611*7f2fe78bSCy Schubert *no_dispatch = TRUE;
612*7f2fe78bSCy Schubert break;
613*7f2fe78bSCy Schubert
614*7f2fe78bSCy Schubert case AUTH_GSSAPI_DESTROY:
615*7f2fe78bSCy Schubert PRINTF(("svcauth_gssapi: GSSAPI_DESTROY\n"));
616*7f2fe78bSCy Schubert
617*7f2fe78bSCy Schubert PRINTF(("svcauth_gssapi: sending reply\n"));
618*7f2fe78bSCy Schubert svc_sendreply(rqst->rq_xprt, xdr_void, NULL);
619*7f2fe78bSCy Schubert *no_dispatch = TRUE;
620*7f2fe78bSCy Schubert
621*7f2fe78bSCy Schubert destroy_client(client_data);
622*7f2fe78bSCy Schubert rqst->rq_xprt->xp_auth = NULL;
623*7f2fe78bSCy Schubert break;
624*7f2fe78bSCy Schubert
625*7f2fe78bSCy Schubert default:
626*7f2fe78bSCy Schubert PRINTF(("svcauth_gssapi: unacceptable procedure %d\n",
627*7f2fe78bSCy Schubert rqst->rq_proc));
628*7f2fe78bSCy Schubert LOG_MISCERR("invalid call procedure number");
629*7f2fe78bSCy Schubert ret = AUTH_FAILED;
630*7f2fe78bSCy Schubert goto error;
631*7f2fe78bSCy Schubert }
632*7f2fe78bSCy Schubert } else {
633*7f2fe78bSCy Schubert /* set credentials for app server; comment in svc.c */
634*7f2fe78bSCy Schubert /* seems to imply this is incorrect, but I don't see */
635*7f2fe78bSCy Schubert /* any problem with it... */
636*7f2fe78bSCy Schubert rqst->rq_clntcred = (char *)client_data->client_name;
637*7f2fe78bSCy Schubert rqst->rq_svccred = (char *)client_data->context;
638*7f2fe78bSCy Schubert }
639*7f2fe78bSCy Schubert }
640*7f2fe78bSCy Schubert
641*7f2fe78bSCy Schubert if (creds.client_handle.length != 0) {
642*7f2fe78bSCy Schubert PRINTF(("svcauth_gssapi: freeing client_handle len %d\n",
643*7f2fe78bSCy Schubert (int) creds.client_handle.length));
644*7f2fe78bSCy Schubert xdr_free(xdr_authgssapi_creds, &creds);
645*7f2fe78bSCy Schubert }
646*7f2fe78bSCy Schubert
647*7f2fe78bSCy Schubert PRINTF(("\n"));
648*7f2fe78bSCy Schubert return AUTH_OK;
649*7f2fe78bSCy Schubert
650*7f2fe78bSCy Schubert error:
651*7f2fe78bSCy Schubert if (creds.client_handle.length != 0) {
652*7f2fe78bSCy Schubert PRINTF(("svcauth_gssapi: freeing client_handle len %d\n",
653*7f2fe78bSCy Schubert (int) creds.client_handle.length));
654*7f2fe78bSCy Schubert xdr_free(xdr_authgssapi_creds, &creds);
655*7f2fe78bSCy Schubert }
656*7f2fe78bSCy Schubert
657*7f2fe78bSCy Schubert PRINTF(("\n"));
658*7f2fe78bSCy Schubert return ret;
659*7f2fe78bSCy Schubert }
660*7f2fe78bSCy Schubert
cleanup(void)661*7f2fe78bSCy Schubert static void cleanup(void)
662*7f2fe78bSCy Schubert {
663*7f2fe78bSCy Schubert client_list *c, *c2;
664*7f2fe78bSCy Schubert
665*7f2fe78bSCy Schubert PRINTF(("cleanup_and_exit: starting\n"));
666*7f2fe78bSCy Schubert
667*7f2fe78bSCy Schubert c = clients;
668*7f2fe78bSCy Schubert while (c) {
669*7f2fe78bSCy Schubert c2 = c;
670*7f2fe78bSCy Schubert c = c->next;
671*7f2fe78bSCy Schubert destroy_client(c2->client);
672*7f2fe78bSCy Schubert free(c2);
673*7f2fe78bSCy Schubert }
674*7f2fe78bSCy Schubert
675*7f2fe78bSCy Schubert exit(0);
676*7f2fe78bSCy Schubert }
677*7f2fe78bSCy Schubert
678*7f2fe78bSCy Schubert /*
679*7f2fe78bSCy Schubert * Function: create_client
680*7f2fe78bSCy Schubert *
681*7f2fe78bSCy Schubert * Purpose: Creates an new client_data structure and stores it in the
682*7f2fe78bSCy Schubert * database.
683*7f2fe78bSCy Schubert *
684*7f2fe78bSCy Schubert * Returns: the new client_data structure, or NULL on failure.
685*7f2fe78bSCy Schubert *
686*7f2fe78bSCy Schubert * Effects:
687*7f2fe78bSCy Schubert *
688*7f2fe78bSCy Schubert * A new client_data is created and stored in the hash table and
689*7f2fe78bSCy Schubert * b-tree. A new key that is unique in the current database is
690*7f2fe78bSCy Schubert * chosen; this key should be used as the client's client_handle.
691*7f2fe78bSCy Schubert */
create_client(void)692*7f2fe78bSCy Schubert static svc_auth_gssapi_data *create_client(void)
693*7f2fe78bSCy Schubert {
694*7f2fe78bSCy Schubert client_list *c;
695*7f2fe78bSCy Schubert svc_auth_gssapi_data *client_data;
696*7f2fe78bSCy Schubert static int client_key = 1;
697*7f2fe78bSCy Schubert
698*7f2fe78bSCy Schubert PRINTF(("svcauth_gssapi: empty creds, creating\n"));
699*7f2fe78bSCy Schubert
700*7f2fe78bSCy Schubert client_data = (svc_auth_gssapi_data *) malloc(sizeof(*client_data));
701*7f2fe78bSCy Schubert if (client_data == NULL)
702*7f2fe78bSCy Schubert return NULL;
703*7f2fe78bSCy Schubert memset(client_data, 0, sizeof(*client_data));
704*7f2fe78bSCy Schubert L_PRINTF(2, ("create_client: new client_data = %p\n",
705*7f2fe78bSCy Schubert (void *) client_data));
706*7f2fe78bSCy Schubert
707*7f2fe78bSCy Schubert /* set up client data structure */
708*7f2fe78bSCy Schubert client_data->established = 0;
709*7f2fe78bSCy Schubert client_data->context = GSS_C_NO_CONTEXT;
710*7f2fe78bSCy Schubert client_data->expiration = time(0) + INITIATION_TIMEOUT;
711*7f2fe78bSCy Schubert
712*7f2fe78bSCy Schubert /* set up psycho-recursive SVCAUTH hack */
713*7f2fe78bSCy Schubert client_data->svcauth.svc_ah_ops = &svc_auth_gssapi_ops;
714*7f2fe78bSCy Schubert client_data->svcauth.svc_ah_private = (caddr_t) client_data;
715*7f2fe78bSCy Schubert
716*7f2fe78bSCy Schubert client_data->key = client_key++;
717*7f2fe78bSCy Schubert
718*7f2fe78bSCy Schubert c = (client_list *) malloc(sizeof(client_list));
719*7f2fe78bSCy Schubert if (c == NULL)
720*7f2fe78bSCy Schubert return NULL;
721*7f2fe78bSCy Schubert c->client = client_data;
722*7f2fe78bSCy Schubert c->next = NULL;
723*7f2fe78bSCy Schubert
724*7f2fe78bSCy Schubert
725*7f2fe78bSCy Schubert if (clients == NULL)
726*7f2fe78bSCy Schubert clients = c;
727*7f2fe78bSCy Schubert else {
728*7f2fe78bSCy Schubert c->next = clients;
729*7f2fe78bSCy Schubert clients = c;
730*7f2fe78bSCy Schubert }
731*7f2fe78bSCy Schubert
732*7f2fe78bSCy Schubert PRINTF(("svcauth_gssapi: new handle %d\n", client_data->key));
733*7f2fe78bSCy Schubert L_PRINTF(2, ("create_client: done\n"));
734*7f2fe78bSCy Schubert
735*7f2fe78bSCy Schubert return client_data;
736*7f2fe78bSCy Schubert }
737*7f2fe78bSCy Schubert
738*7f2fe78bSCy Schubert /*
739*7f2fe78bSCy Schubert * Function: client_expire
740*7f2fe78bSCy Schubert *
741*7f2fe78bSCy Schubert * Purpose: change the expiration time of a client in the database
742*7f2fe78bSCy Schubert *
743*7f2fe78bSCy Schubert * Arguments:
744*7f2fe78bSCy Schubert *
745*7f2fe78bSCy Schubert * client_data (r) the client_data to expire
746*7f2fe78bSCy Schubert * exp (r) the new expiration time
747*7f2fe78bSCy Schubert *
748*7f2fe78bSCy Schubert * Effects:
749*7f2fe78bSCy Schubert *
750*7f2fe78bSCy Schubert * client_data->expiration = exp
751*7f2fe78bSCy Schubert *
752*7f2fe78bSCy Schubert * This function used to remove client_data from the database, change
753*7f2fe78bSCy Schubert * its expiration time, and re-add it, which was necessary because the
754*7f2fe78bSCy Schubert * database was sorted by expiration time so a simple modification
755*7f2fe78bSCy Schubert * would break the rep invariant. Now the database is an unsorted
756*7f2fe78bSCy Schubert * linked list, so it doesn't matter.
757*7f2fe78bSCy Schubert */
client_expire(svc_auth_gssapi_data * client_data,uint32_t exp)758*7f2fe78bSCy Schubert static void client_expire(
759*7f2fe78bSCy Schubert svc_auth_gssapi_data *client_data,
760*7f2fe78bSCy Schubert uint32_t exp)
761*7f2fe78bSCy Schubert {
762*7f2fe78bSCy Schubert client_data->expiration = exp;
763*7f2fe78bSCy Schubert }
764*7f2fe78bSCy Schubert
765*7f2fe78bSCy Schubert /*
766*7f2fe78bSCy Schubert * Function get_client
767*7f2fe78bSCy Schubert *
768*7f2fe78bSCy Schubert * Purpose: retrieve a client_data structure from the database based
769*7f2fe78bSCy Schubert * on its client handle (key)
770*7f2fe78bSCy Schubert *
771*7f2fe78bSCy Schubert * Arguments:
772*7f2fe78bSCy Schubert *
773*7f2fe78bSCy Schubert * client_handle (r) the handle (key) to retrieve
774*7f2fe78bSCy Schubert *
775*7f2fe78bSCy Schubert * Effects:
776*7f2fe78bSCy Schubert *
777*7f2fe78bSCy Schubert * Searches the list and returns the client_data whose key field
778*7f2fe78bSCy Schubert * matches the contents of client_handle, or returns NULL if none was
779*7f2fe78bSCy Schubert * found.
780*7f2fe78bSCy Schubert */
get_client(gss_buffer_t client_handle)781*7f2fe78bSCy Schubert static svc_auth_gssapi_data *get_client(gss_buffer_t client_handle)
782*7f2fe78bSCy Schubert {
783*7f2fe78bSCy Schubert client_list *c;
784*7f2fe78bSCy Schubert uint32_t handle;
785*7f2fe78bSCy Schubert
786*7f2fe78bSCy Schubert memcpy(&handle, client_handle->value, 4);
787*7f2fe78bSCy Schubert
788*7f2fe78bSCy Schubert L_PRINTF(2, ("get_client: looking for client %d\n", handle));
789*7f2fe78bSCy Schubert
790*7f2fe78bSCy Schubert c = clients;
791*7f2fe78bSCy Schubert while (c) {
792*7f2fe78bSCy Schubert if (c->client->key == handle)
793*7f2fe78bSCy Schubert return c->client;
794*7f2fe78bSCy Schubert c = c->next;
795*7f2fe78bSCy Schubert }
796*7f2fe78bSCy Schubert
797*7f2fe78bSCy Schubert L_PRINTF(2, ("get_client: client_handle lookup failed\n"));
798*7f2fe78bSCy Schubert return NULL;
799*7f2fe78bSCy Schubert }
800*7f2fe78bSCy Schubert
801*7f2fe78bSCy Schubert /*
802*7f2fe78bSCy Schubert * Function: destroy_client
803*7f2fe78bSCy Schubert *
804*7f2fe78bSCy Schubert * Purpose: destroys a client entry and removes it from the database
805*7f2fe78bSCy Schubert *
806*7f2fe78bSCy Schubert * Arguments:
807*7f2fe78bSCy Schubert *
808*7f2fe78bSCy Schubert * client_data (r) the client to be destroyed
809*7f2fe78bSCy Schubert *
810*7f2fe78bSCy Schubert * Effects:
811*7f2fe78bSCy Schubert *
812*7f2fe78bSCy Schubert * client_data->context is deleted with gss_delete_sec_context.
813*7f2fe78bSCy Schubert * client_data's entry in the database is destroyed. client_data is
814*7f2fe78bSCy Schubert * freed.
815*7f2fe78bSCy Schubert */
destroy_client(svc_auth_gssapi_data * client_data)816*7f2fe78bSCy Schubert static void destroy_client(svc_auth_gssapi_data *client_data)
817*7f2fe78bSCy Schubert {
818*7f2fe78bSCy Schubert OM_uint32 gssstat, minor_stat;
819*7f2fe78bSCy Schubert gss_buffer_desc out_buf;
820*7f2fe78bSCy Schubert client_list *c, *c2;
821*7f2fe78bSCy Schubert
822*7f2fe78bSCy Schubert PRINTF(("destroy_client: destroying client_data\n"));
823*7f2fe78bSCy Schubert L_PRINTF(2, ("destroy_client: client_data = %p\n", (void *) client_data));
824*7f2fe78bSCy Schubert
825*7f2fe78bSCy Schubert #ifdef DEBUG_GSSAPI
826*7f2fe78bSCy Schubert if (svc_debug_gssapi >= 3)
827*7f2fe78bSCy Schubert dump_db("before frees");
828*7f2fe78bSCy Schubert #endif
829*7f2fe78bSCy Schubert
830*7f2fe78bSCy Schubert /* destroy client struct even if error occurs */
831*7f2fe78bSCy Schubert
832*7f2fe78bSCy Schubert gssstat = gss_delete_sec_context(&minor_stat, &client_data->context,
833*7f2fe78bSCy Schubert &out_buf);
834*7f2fe78bSCy Schubert if (gssstat != GSS_S_COMPLETE)
835*7f2fe78bSCy Schubert AUTH_GSSAPI_DISPLAY_STATUS(("deleting context", gssstat,
836*7f2fe78bSCy Schubert minor_stat));
837*7f2fe78bSCy Schubert
838*7f2fe78bSCy Schubert gss_release_buffer(&minor_stat, &out_buf);
839*7f2fe78bSCy Schubert gss_release_name(&minor_stat, &client_data->client_name);
840*7f2fe78bSCy Schubert if (client_data->prev_verf.length != 0)
841*7f2fe78bSCy Schubert gss_release_buffer(&minor_stat, &client_data->prev_verf);
842*7f2fe78bSCy Schubert
843*7f2fe78bSCy Schubert if (clients == NULL) {
844*7f2fe78bSCy Schubert PRINTF(("destroy_client: called on empty database\n"));
845*7f2fe78bSCy Schubert abort();
846*7f2fe78bSCy Schubert } else if (clients->client == client_data) {
847*7f2fe78bSCy Schubert c = clients;
848*7f2fe78bSCy Schubert clients = clients->next;
849*7f2fe78bSCy Schubert free(c);
850*7f2fe78bSCy Schubert } else {
851*7f2fe78bSCy Schubert c2 = clients;
852*7f2fe78bSCy Schubert c = clients->next;
853*7f2fe78bSCy Schubert while (c) {
854*7f2fe78bSCy Schubert if (c->client == client_data) {
855*7f2fe78bSCy Schubert c2->next = c->next;
856*7f2fe78bSCy Schubert free(c);
857*7f2fe78bSCy Schubert goto done;
858*7f2fe78bSCy Schubert } else {
859*7f2fe78bSCy Schubert c2 = c;
860*7f2fe78bSCy Schubert c = c->next;
861*7f2fe78bSCy Schubert }
862*7f2fe78bSCy Schubert }
863*7f2fe78bSCy Schubert PRINTF(("destroy_client: client_handle delete failed\n"));
864*7f2fe78bSCy Schubert abort();
865*7f2fe78bSCy Schubert }
866*7f2fe78bSCy Schubert
867*7f2fe78bSCy Schubert done:
868*7f2fe78bSCy Schubert
869*7f2fe78bSCy Schubert L_PRINTF(2, ("destroy_client: client %d destroyed\n", client_data->key));
870*7f2fe78bSCy Schubert
871*7f2fe78bSCy Schubert free(client_data);
872*7f2fe78bSCy Schubert }
873*7f2fe78bSCy Schubert
dump_db(char * msg)874*7f2fe78bSCy Schubert static void dump_db(char *msg)
875*7f2fe78bSCy Schubert {
876*7f2fe78bSCy Schubert svc_auth_gssapi_data *client_data;
877*7f2fe78bSCy Schubert client_list *c;
878*7f2fe78bSCy Schubert
879*7f2fe78bSCy Schubert L_PRINTF(3, ("dump_db: %s:\n", msg));
880*7f2fe78bSCy Schubert
881*7f2fe78bSCy Schubert c = clients;
882*7f2fe78bSCy Schubert while (c) {
883*7f2fe78bSCy Schubert client_data = c->client;
884*7f2fe78bSCy Schubert L_PRINTF(3, ("\tclient_data = %p, exp = %d\n",
885*7f2fe78bSCy Schubert (void *) client_data, client_data->expiration));
886*7f2fe78bSCy Schubert c = c->next;
887*7f2fe78bSCy Schubert }
888*7f2fe78bSCy Schubert
889*7f2fe78bSCy Schubert L_PRINTF(3, ("\n"));
890*7f2fe78bSCy Schubert }
891*7f2fe78bSCy Schubert
clean_client(void)892*7f2fe78bSCy Schubert static void clean_client(void)
893*7f2fe78bSCy Schubert {
894*7f2fe78bSCy Schubert svc_auth_gssapi_data *client_data;
895*7f2fe78bSCy Schubert client_list *c;
896*7f2fe78bSCy Schubert
897*7f2fe78bSCy Schubert PRINTF(("clean_client: starting\n"));
898*7f2fe78bSCy Schubert
899*7f2fe78bSCy Schubert c = clients;
900*7f2fe78bSCy Schubert while (c) {
901*7f2fe78bSCy Schubert client_data = c->client;
902*7f2fe78bSCy Schubert
903*7f2fe78bSCy Schubert L_PRINTF(2, ("clean_client: client_data = %p\n",
904*7f2fe78bSCy Schubert (void *) client_data));
905*7f2fe78bSCy Schubert
906*7f2fe78bSCy Schubert if (client_data->expiration < time(0)) {
907*7f2fe78bSCy Schubert PRINTF(("clean_client: client %d expired\n",
908*7f2fe78bSCy Schubert client_data->key));
909*7f2fe78bSCy Schubert destroy_client(client_data);
910*7f2fe78bSCy Schubert c = clients; /* start over, just to be safe */
911*7f2fe78bSCy Schubert } else {
912*7f2fe78bSCy Schubert c = c->next;
913*7f2fe78bSCy Schubert }
914*7f2fe78bSCy Schubert }
915*7f2fe78bSCy Schubert
916*7f2fe78bSCy Schubert PRINTF(("clean_client: done\n"));
917*7f2fe78bSCy Schubert }
918*7f2fe78bSCy Schubert
919*7f2fe78bSCy Schubert /*
920*7f2fe78bSCy Schubert * Function: svcauth_gssapi_set_names
921*7f2fe78bSCy Schubert *
922*7f2fe78bSCy Schubert * Purpose: Sets the list of service names for which incoming
923*7f2fe78bSCy Schubert * authentication requests should be honored.
924*7f2fe78bSCy Schubert *
925*7f2fe78bSCy Schubert * See functional specifications.
926*7f2fe78bSCy Schubert */
svcauth_gssapi_set_names(auth_gssapi_name * names,int num)927*7f2fe78bSCy Schubert bool_t svcauth_gssapi_set_names(
928*7f2fe78bSCy Schubert auth_gssapi_name *names,
929*7f2fe78bSCy Schubert int num)
930*7f2fe78bSCy Schubert {
931*7f2fe78bSCy Schubert OM_uint32 gssstat, minor_stat;
932*7f2fe78bSCy Schubert gss_buffer_desc in_buf;
933*7f2fe78bSCy Schubert int i;
934*7f2fe78bSCy Schubert
935*7f2fe78bSCy Schubert if (num == 0)
936*7f2fe78bSCy Schubert for (; names[num].name != NULL; num++)
937*7f2fe78bSCy Schubert ;
938*7f2fe78bSCy Schubert
939*7f2fe78bSCy Schubert server_creds_list = NULL;
940*7f2fe78bSCy Schubert server_name_list = NULL;
941*7f2fe78bSCy Schubert
942*7f2fe78bSCy Schubert server_creds_list = (gss_cred_id_t *) malloc(num*sizeof(gss_cred_id_t));
943*7f2fe78bSCy Schubert if (server_creds_list == NULL)
944*7f2fe78bSCy Schubert goto fail;
945*7f2fe78bSCy Schubert server_name_list = (gss_name_t *) malloc(num*sizeof(gss_name_t));
946*7f2fe78bSCy Schubert if (server_name_list == NULL)
947*7f2fe78bSCy Schubert goto fail;
948*7f2fe78bSCy Schubert
949*7f2fe78bSCy Schubert for (i = 0; i < num; i++) {
950*7f2fe78bSCy Schubert server_name_list[i] = 0;
951*7f2fe78bSCy Schubert server_creds_list[i] = 0;
952*7f2fe78bSCy Schubert }
953*7f2fe78bSCy Schubert
954*7f2fe78bSCy Schubert server_creds_count = num;
955*7f2fe78bSCy Schubert
956*7f2fe78bSCy Schubert for (i = 0; i < num; i++) {
957*7f2fe78bSCy Schubert in_buf.value = names[i].name;
958*7f2fe78bSCy Schubert in_buf.length = strlen(in_buf.value) + 1;
959*7f2fe78bSCy Schubert
960*7f2fe78bSCy Schubert PRINTF(("svcauth_gssapi_set_names: importing %s\n", names[i].name));
961*7f2fe78bSCy Schubert
962*7f2fe78bSCy Schubert gssstat = gss_import_name(&minor_stat, &in_buf, names[i].type,
963*7f2fe78bSCy Schubert &server_name_list[i]);
964*7f2fe78bSCy Schubert
965*7f2fe78bSCy Schubert if (gssstat != GSS_S_COMPLETE) {
966*7f2fe78bSCy Schubert AUTH_GSSAPI_DISPLAY_STATUS(("importing name", gssstat,
967*7f2fe78bSCy Schubert minor_stat));
968*7f2fe78bSCy Schubert goto fail;
969*7f2fe78bSCy Schubert }
970*7f2fe78bSCy Schubert
971*7f2fe78bSCy Schubert gssstat = gss_acquire_cred(&minor_stat, server_name_list[i], 0,
972*7f2fe78bSCy Schubert GSS_C_NULL_OID_SET, GSS_C_ACCEPT,
973*7f2fe78bSCy Schubert &server_creds_list[i], NULL, NULL);
974*7f2fe78bSCy Schubert if (gssstat != GSS_S_COMPLETE) {
975*7f2fe78bSCy Schubert AUTH_GSSAPI_DISPLAY_STATUS(("acquiring credentials",
976*7f2fe78bSCy Schubert gssstat, minor_stat));
977*7f2fe78bSCy Schubert goto fail;
978*7f2fe78bSCy Schubert }
979*7f2fe78bSCy Schubert }
980*7f2fe78bSCy Schubert
981*7f2fe78bSCy Schubert return TRUE;
982*7f2fe78bSCy Schubert
983*7f2fe78bSCy Schubert fail:
984*7f2fe78bSCy Schubert svcauth_gssapi_unset_names();
985*7f2fe78bSCy Schubert
986*7f2fe78bSCy Schubert return FALSE;
987*7f2fe78bSCy Schubert }
988*7f2fe78bSCy Schubert
989*7f2fe78bSCy Schubert /* Function: svcauth_gssapi_unset_names
990*7f2fe78bSCy Schubert *
991*7f2fe78bSCy Schubert * Purpose: releases the names and credentials allocated by
992*7f2fe78bSCy Schubert * svcauth_gssapi_set_names
993*7f2fe78bSCy Schubert */
994*7f2fe78bSCy Schubert
svcauth_gssapi_unset_names(void)995*7f2fe78bSCy Schubert void svcauth_gssapi_unset_names(void)
996*7f2fe78bSCy Schubert {
997*7f2fe78bSCy Schubert int i;
998*7f2fe78bSCy Schubert OM_uint32 minor_stat;
999*7f2fe78bSCy Schubert
1000*7f2fe78bSCy Schubert if (server_creds_list) {
1001*7f2fe78bSCy Schubert for (i = 0; i < server_creds_count; i++)
1002*7f2fe78bSCy Schubert if (server_creds_list[i])
1003*7f2fe78bSCy Schubert gss_release_cred(&minor_stat, &server_creds_list[i]);
1004*7f2fe78bSCy Schubert free(server_creds_list);
1005*7f2fe78bSCy Schubert server_creds_list = NULL;
1006*7f2fe78bSCy Schubert }
1007*7f2fe78bSCy Schubert
1008*7f2fe78bSCy Schubert if (server_name_list) {
1009*7f2fe78bSCy Schubert for (i = 0; i < server_creds_count; i++)
1010*7f2fe78bSCy Schubert if (server_name_list[i])
1011*7f2fe78bSCy Schubert gss_release_name(&minor_stat, &server_name_list[i]);
1012*7f2fe78bSCy Schubert free(server_name_list);
1013*7f2fe78bSCy Schubert server_name_list = NULL;
1014*7f2fe78bSCy Schubert }
1015*7f2fe78bSCy Schubert server_creds_count = 0;
1016*7f2fe78bSCy Schubert }
1017*7f2fe78bSCy Schubert
1018*7f2fe78bSCy Schubert
1019*7f2fe78bSCy Schubert /*
1020*7f2fe78bSCy Schubert * Function: svcauth_gssapi_set_log_badauth_func
1021*7f2fe78bSCy Schubert *
1022*7f2fe78bSCy Schubert * Purpose: sets the logging function called when an invalid RPC call
1023*7f2fe78bSCy Schubert * arrives
1024*7f2fe78bSCy Schubert *
1025*7f2fe78bSCy Schubert * See functional specifications.
1026*7f2fe78bSCy Schubert */
svcauth_gssapi_set_log_badauth_func(auth_gssapi_log_badauth_func func,caddr_t data)1027*7f2fe78bSCy Schubert void svcauth_gssapi_set_log_badauth_func(
1028*7f2fe78bSCy Schubert auth_gssapi_log_badauth_func func,
1029*7f2fe78bSCy Schubert caddr_t data)
1030*7f2fe78bSCy Schubert {
1031*7f2fe78bSCy Schubert log_badauth = func;
1032*7f2fe78bSCy Schubert log_badauth_data = data;
1033*7f2fe78bSCy Schubert }
1034*7f2fe78bSCy Schubert
1035*7f2fe78bSCy Schubert void
svcauth_gssapi_set_log_badauth2_func(auth_gssapi_log_badauth2_func func,caddr_t data)1036*7f2fe78bSCy Schubert svcauth_gssapi_set_log_badauth2_func(auth_gssapi_log_badauth2_func func,
1037*7f2fe78bSCy Schubert caddr_t data)
1038*7f2fe78bSCy Schubert {
1039*7f2fe78bSCy Schubert log_badauth2 = func;
1040*7f2fe78bSCy Schubert log_badauth2_data = data;
1041*7f2fe78bSCy Schubert }
1042*7f2fe78bSCy Schubert
1043*7f2fe78bSCy Schubert /*
1044*7f2fe78bSCy Schubert * Function: svcauth_gssapi_set_log_badverf_func
1045*7f2fe78bSCy Schubert *
1046*7f2fe78bSCy Schubert * Purpose: sets the logging function called when an invalid RPC call
1047*7f2fe78bSCy Schubert * arrives
1048*7f2fe78bSCy Schubert *
1049*7f2fe78bSCy Schubert * See functional specifications.
1050*7f2fe78bSCy Schubert */
svcauth_gssapi_set_log_badverf_func(auth_gssapi_log_badverf_func func,caddr_t data)1051*7f2fe78bSCy Schubert void svcauth_gssapi_set_log_badverf_func(
1052*7f2fe78bSCy Schubert auth_gssapi_log_badverf_func func,
1053*7f2fe78bSCy Schubert caddr_t data)
1054*7f2fe78bSCy Schubert {
1055*7f2fe78bSCy Schubert log_badverf = func;
1056*7f2fe78bSCy Schubert log_badverf_data = data;
1057*7f2fe78bSCy Schubert }
1058*7f2fe78bSCy Schubert
1059*7f2fe78bSCy Schubert /*
1060*7f2fe78bSCy Schubert * Function: svcauth_gssapi_set_log_miscerr_func
1061*7f2fe78bSCy Schubert *
1062*7f2fe78bSCy Schubert * Purpose: sets the logging function called when a miscellaneous
1063*7f2fe78bSCy Schubert * AUTH_GSSAPI error occurs
1064*7f2fe78bSCy Schubert *
1065*7f2fe78bSCy Schubert * See functional specifications.
1066*7f2fe78bSCy Schubert */
svcauth_gssapi_set_log_miscerr_func(auth_gssapi_log_miscerr_func func,caddr_t data)1067*7f2fe78bSCy Schubert void svcauth_gssapi_set_log_miscerr_func(
1068*7f2fe78bSCy Schubert auth_gssapi_log_miscerr_func func,
1069*7f2fe78bSCy Schubert caddr_t data)
1070*7f2fe78bSCy Schubert {
1071*7f2fe78bSCy Schubert log_miscerr = func;
1072*7f2fe78bSCy Schubert log_miscerr_data = data;
1073*7f2fe78bSCy Schubert }
1074*7f2fe78bSCy Schubert
1075*7f2fe78bSCy Schubert /*
1076*7f2fe78bSCy Schubert * Encrypt the serialized arguments from xdr_func applied to xdr_ptr
1077*7f2fe78bSCy Schubert * and write the result to xdrs.
1078*7f2fe78bSCy Schubert */
svc_auth_gssapi_wrap(SVCAUTH * auth,XDR * out_xdrs,bool_t (* xdr_func)(),caddr_t xdr_ptr)1079*7f2fe78bSCy Schubert static bool_t svc_auth_gssapi_wrap(
1080*7f2fe78bSCy Schubert SVCAUTH *auth,
1081*7f2fe78bSCy Schubert XDR *out_xdrs,
1082*7f2fe78bSCy Schubert bool_t (*xdr_func)(),
1083*7f2fe78bSCy Schubert caddr_t xdr_ptr)
1084*7f2fe78bSCy Schubert {
1085*7f2fe78bSCy Schubert OM_uint32 gssstat, minor_stat;
1086*7f2fe78bSCy Schubert
1087*7f2fe78bSCy Schubert if (! SVCAUTH_PRIVATE(auth)->established) {
1088*7f2fe78bSCy Schubert PRINTF(("svc_gssapi_wrap: not established, noop\n"));
1089*7f2fe78bSCy Schubert return (*xdr_func)(out_xdrs, xdr_ptr);
1090*7f2fe78bSCy Schubert } else if (! auth_gssapi_wrap_data(&gssstat, &minor_stat,
1091*7f2fe78bSCy Schubert SVCAUTH_PRIVATE(auth)->context,
1092*7f2fe78bSCy Schubert SVCAUTH_PRIVATE(auth)->seq_num,
1093*7f2fe78bSCy Schubert out_xdrs, xdr_func, xdr_ptr)) {
1094*7f2fe78bSCy Schubert if (gssstat != GSS_S_COMPLETE)
1095*7f2fe78bSCy Schubert AUTH_GSSAPI_DISPLAY_STATUS(("encrypting function arguments",
1096*7f2fe78bSCy Schubert gssstat, minor_stat));
1097*7f2fe78bSCy Schubert return FALSE;
1098*7f2fe78bSCy Schubert } else
1099*7f2fe78bSCy Schubert return TRUE;
1100*7f2fe78bSCy Schubert }
1101*7f2fe78bSCy Schubert
svc_auth_gssapi_unwrap(SVCAUTH * auth,XDR * in_xdrs,bool_t (* xdr_func)(),caddr_t xdr_ptr)1102*7f2fe78bSCy Schubert static bool_t svc_auth_gssapi_unwrap(
1103*7f2fe78bSCy Schubert SVCAUTH *auth,
1104*7f2fe78bSCy Schubert XDR *in_xdrs,
1105*7f2fe78bSCy Schubert bool_t (*xdr_func)(),
1106*7f2fe78bSCy Schubert caddr_t xdr_ptr)
1107*7f2fe78bSCy Schubert {
1108*7f2fe78bSCy Schubert svc_auth_gssapi_data *client_data = SVCAUTH_PRIVATE(auth);
1109*7f2fe78bSCy Schubert OM_uint32 gssstat, minor_stat;
1110*7f2fe78bSCy Schubert
1111*7f2fe78bSCy Schubert if (! client_data->established) {
1112*7f2fe78bSCy Schubert PRINTF(("svc_gssapi_unwrap: not established, noop\n"));
1113*7f2fe78bSCy Schubert return (*xdr_func)(in_xdrs, (auth_gssapi_init_arg *)(void *) xdr_ptr);
1114*7f2fe78bSCy Schubert } else if (! auth_gssapi_unwrap_data(&gssstat, &minor_stat,
1115*7f2fe78bSCy Schubert client_data->context,
1116*7f2fe78bSCy Schubert client_data->seq_num-1,
1117*7f2fe78bSCy Schubert in_xdrs, xdr_func, xdr_ptr)) {
1118*7f2fe78bSCy Schubert if (gssstat != GSS_S_COMPLETE)
1119*7f2fe78bSCy Schubert AUTH_GSSAPI_DISPLAY_STATUS(("decrypting function arguments",
1120*7f2fe78bSCy Schubert gssstat, minor_stat));
1121*7f2fe78bSCy Schubert return FALSE;
1122*7f2fe78bSCy Schubert } else
1123*7f2fe78bSCy Schubert return TRUE;
1124*7f2fe78bSCy Schubert }
1125*7f2fe78bSCy Schubert
svc_auth_gssapi_destroy(SVCAUTH * auth)1126*7f2fe78bSCy Schubert static bool_t svc_auth_gssapi_destroy(SVCAUTH *auth)
1127*7f2fe78bSCy Schubert {
1128*7f2fe78bSCy Schubert svc_auth_gssapi_data *client_data = SVCAUTH_PRIVATE(auth);
1129*7f2fe78bSCy Schubert
1130*7f2fe78bSCy Schubert destroy_client(client_data);
1131*7f2fe78bSCy Schubert return TRUE;
1132*7f2fe78bSCy Schubert }
1133