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