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 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 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 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 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 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 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 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 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 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 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 * 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 */ 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 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 */ 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 */ 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