nfs-ganesha 1.4
|
00001 /* 00002 Copyright (c) 2000 The Regents of the University of Michigan. 00003 All rights reserved. 00004 00005 Copyright (c) 2000 Dug Song <dugsong@UMICH.EDU>. 00006 All rights reserved, all wrongs reversed. 00007 00008 Redistribution and use in source and binary forms, with or without 00009 modification, are permitted provided that the following conditions 00010 are met: 00011 00012 1. Redistributions of source code must retain the above copyright 00013 notice, this list of conditions and the following disclaimer. 00014 2. Redistributions in binary form must reproduce the above copyright 00015 notice, this list of conditions and the following disclaimer in the 00016 documentation and/or other materials provided with the distribution. 00017 3. Neither the name of the University nor the names of its 00018 contributors may be used to endorse or promote products derived 00019 from this software without specific prior written permission. 00020 00021 THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED 00022 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 00023 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 00024 DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 00025 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 00026 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 00027 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 00028 BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 00029 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00030 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00031 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00032 00033 Id: svc_auth_gss.c,v 1.28 2002/10/15 21:29:36 kwc Exp 00034 */ 00035 #ifdef HAVE_CONFIG_H 00036 #include "config.h" 00037 #endif 00038 00039 #ifdef _SOLARIS 00040 #include "solaris_port.h" 00041 #endif 00042 00043 #include <stdio.h> 00044 #include <stdlib.h> 00045 #include <string.h> 00046 #include "ganesha_rpc.h" 00047 #include "rpcal.h" 00048 #ifdef HAVE_HEIMDAL 00049 #include <gssapi.h> 00050 #define gss_nt_service_name GSS_C_NT_HOSTBASED_SERVICE 00051 #else 00052 #include <gssapi/gssapi.h> 00053 #include <gssapi/gssapi_generic.h> 00054 #endif 00055 00056 #include "nfs_core.h" 00057 #include "log.h" 00058 00059 #ifdef SPKM 00060 00061 #ifndef OID_EQ 00062 #define g_OID_equal(o1,o2) \ 00063 (((o1)->length == (o2)->length) && \ 00064 ((o1)->elements != 0) && ((o2)->elements != 0) && \ 00065 (memcmp((o1)->elements,(o2)->elements,(int) (o1)->length) == 0)) 00066 #define OID_EQ 1 00067 #endif /* OID_EQ */ 00068 00069 extern const gss_OID_desc *const gss_mech_spkm3; 00070 00071 #endif /* SPKM */ 00072 00073 #ifndef SVCAUTH_DESTROY 00074 #define SVCAUTH_DESTROY(auth) \ 00075 ((*((auth)->svc_ah_ops->svc_ah_destroy))(auth)) 00076 #endif 00077 00078 extern SVCAUTH Svc_auth_none; 00079 00080 #ifdef _USE_TIRPC 00081 static bool_t Svcauth_gss_destroy(); 00082 static bool_t Svcauth_gss_destroy_copy(); 00083 static bool_t Svcauth_gss_wrap(); 00084 static bool_t Svcauth_gss_unwrap(); 00085 #else 00086 static bool_t Svcauth_gss_destroy(SVCAUTH *); 00087 static bool_t Svcauth_gss_destroy_copy(SVCAUTH *); 00088 static bool_t Svcauth_gss_wrap(SVCAUTH *, XDR *, xdrproc_t, caddr_t); 00089 static bool_t Svcauth_gss_unwrap(SVCAUTH *, XDR *, xdrproc_t, caddr_t); 00090 #endif 00091 00092 static bool_t Svcauth_gss_nextverf(struct svc_req *, u_int); 00093 00094 struct svc_auth_ops Svc_auth_gss_ops = { 00095 Svcauth_gss_wrap, 00096 Svcauth_gss_unwrap, 00097 Svcauth_gss_destroy 00098 }; 00099 00100 struct svc_auth_ops Svc_auth_gss_copy_ops = { 00101 Svcauth_gss_wrap, 00102 Svcauth_gss_unwrap, 00103 Svcauth_gss_destroy_copy 00104 }; 00105 00106 const char *str_gc_proc(rpc_gss_proc_t gc_proc) 00107 { 00108 switch(gc_proc) 00109 { 00110 case RPCSEC_GSS_DATA: return "RPCSEC_GSS_DATA"; 00111 case RPCSEC_GSS_INIT: return "RPCSEC_GSS_INIT"; 00112 case RPCSEC_GSS_CONTINUE_INIT: return "RPCSEC_GSS_CONTINUE_INIT"; 00113 case RPCSEC_GSS_DESTROY: return "RPCSEC_GSS_DESTROY"; 00114 } 00115 00116 return "unknown"; 00117 } 00118 00131 void log_sperror_gss(char *outmsg, OM_uint32 maj_stat, OM_uint32 min_stat) 00132 { 00133 OM_uint32 smin; 00134 gss_buffer_desc msg; 00135 gss_buffer_desc msg2; 00136 int msg_ctx = 0; 00137 00138 if(gss_display_status(&smin, 00139 maj_stat, 00140 GSS_C_GSS_CODE, GSS_C_NULL_OID, &msg_ctx, &msg) != GSS_S_COMPLETE) 00141 { 00142 sprintf(outmsg, "untranslatable error"); 00143 return; 00144 } 00145 00146 if(gss_display_status(&smin, 00147 min_stat, 00148 GSS_C_MECH_CODE, 00149 GSS_C_NULL_OID, &msg_ctx, &msg2) != GSS_S_COMPLETE) 00150 { 00151 gss_release_buffer(&smin, &msg); 00152 sprintf(outmsg, "%s : untranslatable error", (char *)msg.value); 00153 return; 00154 } 00155 00156 sprintf(outmsg, "%s : %s ", (char *)msg.value, (char *)msg2.value); 00157 00158 gss_release_buffer(&smin, &msg); 00159 gss_release_buffer(&smin, &msg2); 00160 } /* log_sperror_gss */ 00161 00162 /* Global server credentials. */ 00163 gss_cred_id_t svcauth_gss_creds; 00164 static gss_name_t svcauth_gss_name = NULL; 00165 00166 bool_t Svcauth_gss_set_svc_name(gss_name_t name) 00167 { 00168 OM_uint32 maj_stat, min_stat; 00169 00170 if(svcauth_gss_name != NULL) 00171 { 00172 maj_stat = gss_release_name(&min_stat, &svcauth_gss_name); 00173 00174 if(maj_stat != GSS_S_COMPLETE) 00175 { 00176 return (FALSE); 00177 } 00178 svcauth_gss_name = NULL; 00179 } 00180 00181 if(svcauth_gss_name == GSS_C_NO_NAME) 00182 return (TRUE); 00183 00184 maj_stat = gss_duplicate_name(&min_stat, name, &svcauth_gss_name); 00185 00186 if(maj_stat != GSS_S_COMPLETE) 00187 { 00188 return (FALSE); 00189 } 00190 00191 return (TRUE); 00192 } 00193 00194 bool_t Svcauth_gss_import_name(char *service) 00195 { 00196 gss_name_t name; 00197 gss_buffer_desc namebuf; 00198 OM_uint32 maj_stat, min_stat; 00199 00200 namebuf.value = service; 00201 namebuf.length = strlen(service); 00202 00203 maj_stat = gss_import_name(&min_stat, &namebuf, (gss_OID) gss_nt_service_name, &name); 00204 00205 if(maj_stat != GSS_S_COMPLETE) 00206 { 00207 return (FALSE); 00208 } 00209 if(Svcauth_gss_set_svc_name(name) != TRUE) 00210 { 00211 gss_release_name(&min_stat, &name); 00212 return (FALSE); 00213 } 00214 00215 /* set_svc_name() creates a duplicate, we don't need this copy */ 00216 gss_release_name(&min_stat, &name); 00217 00218 return (TRUE); 00219 } 00220 00221 bool_t Svcauth_gss_acquire_cred(void) 00222 { 00223 OM_uint32 maj_stat, min_stat; 00224 00225 maj_stat = gss_acquire_cred(&min_stat, svcauth_gss_name, 0, 00226 GSS_C_NULL_OID_SET, GSS_C_ACCEPT, 00227 &svcauth_gss_creds, NULL, NULL); 00228 00229 if(maj_stat != GSS_S_COMPLETE) 00230 { 00231 return (FALSE); 00232 } 00233 return (TRUE); 00234 } 00235 00236 static bool_t Svcauth_gss_release_cred(void) 00237 { 00238 OM_uint32 maj_stat, min_stat; 00239 00240 maj_stat = gss_release_cred(&min_stat, &svcauth_gss_creds); 00241 00242 if(maj_stat != GSS_S_COMPLETE) 00243 { 00244 return (FALSE); 00245 } 00246 00247 svcauth_gss_creds = NULL; 00248 00249 return (TRUE); 00250 } 00251 00252 static bool_t 00253 Svcauth_gss_accept_sec_context(struct svc_req *rqst, struct rpc_gss_init_res *gr) 00254 { 00255 struct svc_rpc_gss_data *gd; 00256 struct rpc_gss_cred *gc; 00257 gss_buffer_desc recv_tok, seqbuf; 00258 gss_OID mech; 00259 OM_uint32 maj_stat = 0, min_stat = 0, ret_flags, seq; 00260 00261 gd = SVCAUTH_PRIVATE(rqst->rq_xprt->xp_auth); 00262 gc = (struct rpc_gss_cred *)rqst->rq_clntcred; 00263 memset(gr, 0, sizeof(*gr)); 00264 00265 /* Deserialize arguments. */ 00266 memset(&recv_tok, 0, sizeof(recv_tok)); 00267 00268 if(!svc_getargs(rqst->rq_xprt, (xdrproc_t)xdr_rpc_gss_init_args, (caddr_t) & recv_tok)) 00269 return (FALSE); 00270 00271 gr->gr_major = gss_accept_sec_context(&gr->gr_minor, 00272 &gd->ctx, 00273 svcauth_gss_creds, 00274 &recv_tok, 00275 GSS_C_NO_CHANNEL_BINDINGS, 00276 &gd->client_name, 00277 &mech, &gr->gr_token, &ret_flags, NULL, NULL); 00278 00279 svc_freeargs(rqst->rq_xprt, (xdrproc_t)xdr_rpc_gss_init_args, (caddr_t) & recv_tok); 00280 00281 if(gr->gr_major != GSS_S_COMPLETE && gr->gr_major != GSS_S_CONTINUE_NEEDED) 00282 { 00283 sockaddr_t addr; 00284 char ipstring[SOCK_NAME_MAX]; 00285 copy_xprt_addr(&addr, rqst->rq_xprt); 00286 sprint_sockaddr(&addr, ipstring, sizeof(ipstring)); 00287 00288 LogWarn(COMPONENT_RPCSEC_GSS, 00289 "Bad authentication major=%u minor=%u addr=%s", 00290 gr->gr_major, gr->gr_minor, ipstring); 00291 gd->ctx = GSS_C_NO_CONTEXT; 00292 goto errout; 00293 } 00294 /* 00295 * ANDROS: krb5 mechglue returns ctx of size 8 - two pointers, 00296 * one to the mechanism oid, one to the internal_ctx_id 00297 */ 00298 if((gr->gr_ctx.value = gsh_malloc(sizeof(gss_union_ctx_id_desc))) == NULL) 00299 { 00300 LogCrit(COMPONENT_RPCSEC_GSS, 00301 "svcauth_gss_accept_context: out of memory"); 00302 goto errout; 00303 } 00304 memcpy(gr->gr_ctx.value, gd->ctx, sizeof(gss_union_ctx_id_desc)); 00305 gr->gr_ctx.length = sizeof(gss_union_ctx_id_desc); 00306 00307 /* gr->gr_win = 0x00000005; ANDROS: for debugging linux kernel version... */ 00308 gr->gr_win = sizeof(gd->seqmask) * 8; 00309 00310 /* Save client info. */ 00311 gd->sec.mech = mech; 00312 gd->sec.qop = GSS_C_QOP_DEFAULT; 00313 gd->sec.svc = gc->gc_svc; 00314 gd->seq = gc->gc_seq; 00315 gd->win = gr->gr_win; 00316 00317 if(gr->gr_major == GSS_S_COMPLETE) 00318 { 00319 #ifdef SPKM 00320 /* spkm3: no src_name (anonymous) */ 00321 if(!g_OID_equal(gss_mech_spkm3, mech)) 00322 { 00323 #endif 00324 maj_stat = gss_display_name(&min_stat, gd->client_name, 00325 &gd->cname, &gd->sec.mech); 00326 LogFullDebug(COMPONENT_RPCSEC_GSS, 00327 "cname.val: %s cname.len: %d", 00328 (char *)gd->cname.value, (int)gd->cname.length); 00329 #ifdef SPKM 00330 } 00331 #endif 00332 if(maj_stat != GSS_S_COMPLETE) 00333 { 00334 } 00335 #ifdef HAVE_HEIMDAL 00336 #else 00337 if(isFullDebug(COMPONENT_RPCSEC_GSS)) 00338 { 00339 gss_buffer_desc mechname; 00340 00341 gss_oid_to_str(&min_stat, mech, &mechname); 00342 00343 gss_release_buffer(&min_stat, &mechname); 00344 } 00345 #endif 00346 seq = htonl(gr->gr_win); 00347 seqbuf.value = &seq; 00348 seqbuf.length = sizeof(seq); 00349 00350 gss_release_buffer(&min_stat, &gd->checksum); 00351 LogFullDebug(COMPONENT_RPCSEC_GSS, 00352 "gss_sign in sec_accept_context"); 00353 maj_stat = gss_sign(&min_stat, gd->ctx, GSS_C_QOP_DEFAULT, &seqbuf, &gd->checksum); 00354 00355 if(maj_stat != GSS_S_COMPLETE) 00356 { 00357 goto errout; 00358 } 00359 00360 rqst->rq_xprt->xp_verf.oa_flavor = RPCSEC_GSS; 00361 rqst->rq_xprt->xp_verf.oa_base = gd->checksum.value; 00362 rqst->rq_xprt->xp_verf.oa_length = gd->checksum.length; 00363 } 00364 return (TRUE); 00365 errout: 00366 gss_release_buffer(&min_stat, &gr->gr_token); 00367 return (FALSE); 00368 } 00369 00370 int sprint_ctx(char *buff, unsigned char *ctx, int len) 00371 { 00372 int i; 00373 00374 if(ctx == NULL) 00375 return sprintf(buff, "<null>"); 00376 00377 LogFullDebug(COMPONENT_RPCSEC_GSS, 00378 "sprint_ctx len=%d", len); 00379 00380 if (len > 16) 00381 len = 16; 00382 00383 for(i = 0; i < len; i++) 00384 sprintf(buff + i * 2, "%02x", ctx[i]); 00385 00386 return len * 2; 00387 } 00388 00389 static bool_t 00390 Svcauth_gss_validate(struct svc_req *rqst, struct svc_rpc_gss_data *gd, 00391 struct rpc_msg *msg) 00392 { 00393 struct opaque_auth *oa; 00394 gss_buffer_desc rpcbuf, checksum; 00395 OM_uint32 maj_stat, min_stat, qop_state; 00396 u_char rpchdr[128]; 00397 int32_t *buf; 00398 char GssError[256]; 00399 00400 memset(rpchdr, 0, sizeof(rpchdr)); 00401 00402 /* XXX - Reconstruct RPC header for signing (from xdr_callmsg). */ 00403 oa = &msg->rm_call.cb_cred; 00404 00405 LogFullDebug(COMPONENT_RPCSEC_GSS, 00406 "Call to Svcauth_gss_validate --> xid=%u dir=%u rpcvers=%u " 00407 "prog=%u vers=%u proc=%u flavor=%u len=%u base=%p ckeck.len=%u " 00408 "check.val=%p", 00409 msg->rm_xid, 00410 msg->rm_direction, 00411 msg->rm_call.cb_rpcvers, 00412 msg->rm_call.cb_prog, 00413 msg->rm_call.cb_vers, 00414 msg->rm_call.cb_proc, 00415 oa->oa_flavor, 00416 oa->oa_length, 00417 oa->oa_base, 00418 msg->rm_call.cb_verf.oa_length, 00419 msg->rm_call.cb_verf.oa_base); 00420 00421 if(oa->oa_length > MAX_AUTH_BYTES) 00422 { 00423 LogCrit(COMPONENT_RPCSEC_GSS, 00424 "Svcauth_gss_validate oa->oa_length (%u) > MAX_AUTH_BYTES (%u)", 00425 oa->oa_length, MAX_AUTH_BYTES); 00426 return (FALSE); 00427 } 00428 00429 /* 8 XDR units from the IXDR macro calls. */ 00430 if(sizeof(rpchdr) < (8 * BYTES_PER_XDR_UNIT + 00431 RNDUP(oa->oa_length))) 00432 { 00433 LogCrit(COMPONENT_RPCSEC_GSS, 00434 "Svcauth_gss_validate sizeof(rpchdr) (%d) < " 00435 "(8 * BYTES_PER_XDR_UNIT (%d) + RNDUP(oa->oa_length (%u))) (%d)", 00436 (int) sizeof(rpchdr), 00437 (int) (8 * BYTES_PER_XDR_UNIT), 00438 oa->oa_length, 00439 (int) (8 * BYTES_PER_XDR_UNIT + RNDUP(oa->oa_length))); 00440 return (FALSE); 00441 } 00442 00443 buf = (int32_t *) (void *)rpchdr; 00444 IXDR_PUT_LONG(buf, msg->rm_xid); 00445 IXDR_PUT_ENUM(buf, msg->rm_direction); 00446 IXDR_PUT_LONG(buf, msg->rm_call.cb_rpcvers); 00447 IXDR_PUT_LONG(buf, msg->rm_call.cb_prog); 00448 IXDR_PUT_LONG(buf, msg->rm_call.cb_vers); 00449 IXDR_PUT_LONG(buf, msg->rm_call.cb_proc); 00450 IXDR_PUT_ENUM(buf, oa->oa_flavor); 00451 IXDR_PUT_LONG(buf, oa->oa_length); 00452 if(oa->oa_length) 00453 { 00454 memcpy((caddr_t) buf, oa->oa_base, oa->oa_length); 00455 buf += RNDUP(oa->oa_length) / sizeof(int32_t); 00456 } 00457 rpcbuf.value = rpchdr; 00458 rpcbuf.length = (u_char *) buf - rpchdr; 00459 00460 checksum.value = msg->rm_call.cb_verf.oa_base; 00461 checksum.length = msg->rm_call.cb_verf.oa_length; 00462 00463 if(isFullDebug(COMPONENT_RPCSEC_GSS)) 00464 { 00465 char ctx_str[64]; 00466 sprint_ctx(ctx_str, (unsigned char *)gd->ctx, 00467 sizeof(gss_union_ctx_id_desc)); 00468 LogFullDebug(COMPONENT_RPCSEC_GSS, 00469 "Svcauth_gss_validate context %s rpcbuf=%p:%u " 00470 "checksum=%p:$%u)", 00471 ctx_str, rpcbuf.value, (unsigned int) rpcbuf.length, 00472 checksum.value, (unsigned int) checksum.length); 00473 } 00474 00475 maj_stat = gss_verify_mic(&min_stat, gd->ctx, &rpcbuf, &checksum, &qop_state); 00476 00477 if(maj_stat != GSS_S_COMPLETE) 00478 { 00479 log_sperror_gss(GssError, maj_stat, min_stat); 00480 LogCrit(COMPONENT_RPCSEC_GSS, "Error in gss_verify_mic: %s", GssError); 00481 return (FALSE); 00482 } 00483 return (TRUE); 00484 } 00485 00486 static bool_t Svcauth_gss_nextverf(struct svc_req *rqst, u_int num) 00487 { 00488 struct svc_rpc_gss_data *gd; 00489 gss_buffer_desc signbuf; 00490 OM_uint32 maj_stat, min_stat; 00491 00492 if(rqst->rq_xprt->xp_auth == NULL) 00493 return (FALSE); 00494 00495 gd = SVCAUTH_PRIVATE(rqst->rq_xprt->xp_auth); 00496 00497 gss_release_buffer(&min_stat, &gd->checksum); 00498 00499 signbuf.value = # 00500 signbuf.length = sizeof(num); 00501 00502 maj_stat = gss_get_mic(&min_stat, gd->ctx, gd->sec.qop, &signbuf, 00503 &gd->checksum); 00504 00505 if(maj_stat != GSS_S_COMPLETE) 00506 { 00507 return (FALSE); 00508 } 00509 rqst->rq_xprt->xp_verf.oa_flavor = RPCSEC_GSS; 00510 rqst->rq_xprt->xp_verf.oa_base = (caddr_t) gd->checksum.value; 00511 rqst->rq_xprt->xp_verf.oa_length = (u_int) gd->checksum.length; 00512 00513 return (TRUE); 00514 } 00515 00516 #define ret_freegc(code) do { retstat = code; goto freegc; } while (0) 00517 00518 enum auth_stat 00519 Gssrpc__svcauth_gss(struct svc_req *rqst, struct rpc_msg *msg, 00520 bool_t *no_dispatch) 00521 { 00522 enum auth_stat retstat; 00523 XDR xdrs; 00524 SVCAUTH *auth; 00525 struct svc_rpc_gss_data *gd; 00526 struct rpc_gss_cred *gc; 00527 struct rpc_gss_init_res gr; 00528 int call_stat, offset; 00529 OM_uint32 min_stat; 00530 gss_union_ctx_id_desc *gss_ctx_data; 00531 char ctx_str[64]; 00532 00533 /* Used to update the hashtable entries. 00534 * These should not be used for purposes other than updating 00535 * hashtable entries. */ 00536 bool_t *p_established = NULL; 00537 u_int *p_seqlast = NULL; 00538 uint32_t *p_seqmask = NULL; 00539 00540 /* Initialize reply. */ 00541 LogFullDebug(COMPONENT_RPCSEC_GSS, "Gssrpc__svcauth_gss called"); 00542 00543 /* Allocate and set up server auth handle. */ 00544 if ((rqst->rq_xprt->xp_auth == NULL) || 00545 (rqst->rq_xprt->xp_auth == &Svc_auth_none)) 00546 { 00547 if((auth = gsh_calloc(1, sizeof(*auth))) == NULL) 00548 { 00549 LogCrit(COMPONENT_RPCSEC_GSS, "svcauth_gss: out_of_memory"); 00550 return (AUTH_FAILED); 00551 } 00552 if((gd = gsh_calloc(1, sizeof(*gd))) == NULL) 00553 { 00554 LogCrit(COMPONENT_RPCSEC_GSS, "svcauth_gss: out_of_memory"); 00555 gsh_free(auth); 00556 return (AUTH_FAILED); 00557 } 00558 auth->svc_ah_ops = &Svc_auth_gss_ops; 00559 auth->svc_ah_private = (void *)gd; 00560 rqst->rq_xprt->xp_auth = auth; 00561 } 00562 else 00563 gd = SVCAUTH_PRIVATE(rqst->rq_xprt->xp_auth); 00564 00565 /* Deserialize client credentials. */ 00566 if(rqst->rq_cred.oa_length <= 0) 00567 return (AUTH_BADCRED); 00568 00569 gc = (struct rpc_gss_cred *)rqst->rq_clntcred; 00570 memset(gc, 0, sizeof(*gc)); 00571 00572 xdrmem_create(&xdrs, rqst->rq_cred.oa_base, rqst->rq_cred.oa_length, 00573 XDR_DECODE); 00574 00575 if(!xdr_rpc_gss_cred(&xdrs, gc)) 00576 { 00577 XDR_DESTROY(&xdrs); 00578 return (AUTH_BADCRED); 00579 } 00580 XDR_DESTROY(&xdrs); 00581 00582 if(gc->gc_ctx.length != 0) 00583 gss_ctx_data = (gss_union_ctx_id_desc *)(gc->gc_ctx.value); 00584 else 00585 gss_ctx_data = NULL; 00586 00587 if(isFullDebug(COMPONENT_RPCSEC_GSS)) 00588 { 00589 sprint_ctx(ctx_str, (char *)gc->gc_ctx.value, gc->gc_ctx.length); 00590 LogFullDebug(COMPONENT_RPCSEC_GSS, 00591 "Gssrpc__svcauth_gss gc_proc (%u) %s context %s", 00592 gc->gc_proc, str_gc_proc(gc->gc_proc), ctx_str); 00593 } 00594 00595 /* If we do not retrieve gss data from the cache, then this important 00596 * variables could not possibly be meaningful. */ 00597 gd->seqlast = 0; 00598 gd->seqmask = 0; 00599 gd->established = 0; 00600 00602 /* if( gd->established == 0 && gc->gc_proc == RPCSEC_GSS_DATA )*/ 00603 if(gc->gc_proc == RPCSEC_GSS_DATA || gc->gc_proc == RPCSEC_GSS_DESTROY) 00604 { 00605 if(isFullDebug(COMPONENT_RPCSEC_GSS)) 00606 { 00607 LogFullDebug(COMPONENT_RPCSEC_GSS, 00608 "Dump context hash table"); 00609 Gss_ctx_Hash_Print(); 00610 } 00611 00612 LogFullDebug(COMPONENT_RPCSEC_GSS, "Getting gss data struct from " 00613 "hashtable."); 00614 00615 /* Fill in svc_rpc_gss_data from cache */ 00616 if(!Gss_ctx_Hash_Get(gss_ctx_data, 00617 gd, 00618 &p_established, 00619 &p_seqlast, 00620 &p_seqmask)) 00621 { 00622 LogCrit(COMPONENT_RPCSEC_GSS, "Could not find gss context "); 00623 ret_freegc(AUTH_REJECTEDCRED); 00624 } 00625 else 00626 { 00627 /* If you 'mount -o sec=krb5i' you will have gc->gc_proc > 00628 * RPCSEC_GSS_SVN_NONE, but the negociation will have been made as 00629 * if option was -o sec=krb5, the value of sec.svc has to be updated 00630 * id the stored gd that we got fromn the hash */ 00631 if(gc->gc_svc != gd->sec.svc) 00632 gd->sec.svc = gc->gc_svc; 00633 } 00634 } 00635 00636 if(isFullDebug(COMPONENT_RPCSEC_GSS)) 00637 { 00638 char ctx_str_2[64]; 00639 00640 sprint_ctx(ctx_str_2, (unsigned char *)gd->ctx, sizeof(gss_ctx_data)); 00641 sprint_ctx(ctx_str, (unsigned char *)gc->gc_ctx.value, gc->gc_ctx.length); 00642 00643 LogFullDebug(COMPONENT_RPCSEC_GSS, 00644 "Call to Gssrpc__svcauth_gss ----> Client=%s length=%lu " 00645 "(GD: established=%u ctx=%s) (RQ:sock=%u) " 00646 "(GC: Proc=%u Svc=%u ctx=%s)", 00647 (char *)gd->cname.value, 00648 (long unsigned int)gd->cname.length, 00649 gd->established, 00650 ctx_str_2, 00651 rqst->rq_xprt->xp_fd, 00652 gc->gc_proc, 00653 gc->gc_svc, 00654 ctx_str); 00655 } 00656 00657 retstat = AUTH_FAILED; 00658 00659 /* Check version. */ 00660 if(gc->gc_v != RPCSEC_GSS_VERSION) 00661 { 00662 LogDebug(COMPONENT_RPCSEC_GSS, 00663 "BAD AUTH: bad GSS version."); 00664 ret_freegc(AUTH_BADCRED); 00665 } 00666 00667 /* Check RPCSEC_GSS service. */ 00668 if((gc->gc_svc != RPCSEC_GSS_SVC_NONE) && 00669 (gc->gc_svc != RPCSEC_GSS_SVC_INTEGRITY) && 00670 (gc->gc_svc != RPCSEC_GSS_SVC_PRIVACY)) 00671 { 00672 LogDebug(COMPONENT_RPCSEC_GSS, 00673 "BAD AUTH: bad GSS service (krb5, krb5i, krb5p)"); 00674 ret_freegc(AUTH_BADCRED); 00675 } 00676 00677 /* Check sequence number. */ 00678 if(gd->established) 00679 { 00680 /* Sequence should be less than the max sequence number */ 00681 if(gc->gc_seq > MAXSEQ) 00682 { 00683 LogDebug(COMPONENT_RPCSEC_GSS, 00684 "BAD AUTH: max sequence number exceeded."); 00685 ret_freegc(RPCSEC_GSS_CTXPROBLEM); 00686 } 00687 00688 /* Check the difference between the current sequence number 00689 * and the last sequence number. */ 00690 LogFullDebug(COMPONENT_RPCSEC_GSS, 00691 "seqlast: %d seqnum: %d offset: %d seqwin: %d seqmask: %x", 00692 gd->seqlast, gc->gc_seq, gd->seqlast - gc->gc_seq, gd->win, 00693 gd->seqmask); 00694 00695 if((offset = gd->seqlast - gc->gc_seq) < 0) 00696 { 00697 gd->seqlast = gc->gc_seq; 00698 offset = 0 - offset; 00699 gd->seqmask <<= offset; 00700 offset = 0; 00701 } 00702 else if((unsigned int)offset >= gd->win 00703 || (gd->seqmask & (1 << (unsigned int)offset))) 00704 { 00705 if ((unsigned int)offset >= gd->win) 00706 LogDebug(COMPONENT_RPCSEC_GSS, 00707 "BAD AUTH: the current seqnum is lower " 00708 "than seqlast by %d and out of the seq window of size %d.", offset, gd->win); 00709 else 00710 LogDebug(COMPONENT_RPCSEC_GSS, 00711 "BAD AUTH: the current seqnum has already been used."); 00712 00713 *no_dispatch = TRUE; 00714 ret_freegc(RPCSEC_GSS_CTXPROBLEM); 00715 } 00716 gd->seq = gc->gc_seq; 00717 gd->seqmask |= (1 << offset); 00718 } 00719 00720 if(gd->established) 00721 { 00722 rqst->rq_clntname = (char *)gd->client_name; 00723 #ifndef _USE_TIRPC 00724 rqst->rq_svccred = (char *)gd->ctx; 00725 #else 00726 rqst->rq_svcname = (char *)gd->ctx; 00727 #endif 00728 } 00729 00730 /* Handle RPCSEC_GSS control procedure. */ 00731 switch (gc->gc_proc) 00732 { 00733 00734 case RPCSEC_GSS_INIT: 00735 LogFullDebug(COMPONENT_RPCSEC_GSS, "Reached RPCSEC_GSS_INIT:"); 00736 case RPCSEC_GSS_CONTINUE_INIT: 00737 LogFullDebug(COMPONENT_RPCSEC_GSS, "Reached RPCSEC_GSS_CONTINUE_INIT:"); 00738 if(rqst->rq_proc != NULLPROC) 00739 { 00740 LogFullDebug(COMPONENT_RPCSEC_GSS, "BAD AUTH: request proc != NULL " 00741 "during INIT request"); 00742 ret_freegc(AUTH_FAILED); /* XXX ? */ 00743 } 00744 00745 if(!Svcauth_gss_acquire_cred()) 00746 { 00747 LogFullDebug(COMPONENT_RPCSEC_GSS, "BAD AUTH: Can't acquire " 00748 "credentials from RPC request."); 00749 ret_freegc(AUTH_FAILED); 00750 } 00751 00752 if(!Svcauth_gss_accept_sec_context(rqst, &gr)) 00753 { 00754 LogFullDebug(COMPONENT_RPCSEC_GSS, "BAD AUTH: Can't accept the " 00755 "security context."); 00756 ret_freegc(AUTH_REJECTEDCRED); 00757 } 00758 00759 if(!Svcauth_gss_nextverf(rqst, htonl(gr.gr_win))) 00760 { 00761 gss_release_buffer(&min_stat, &gr.gr_token); 00762 gsh_free(gr.gr_ctx.value); 00763 LogFullDebug(COMPONENT_RPCSEC_GSS, "BAD AUTH: Checksum verification " 00764 "failed"); 00765 ret_freegc(AUTH_FAILED); 00766 } 00767 *no_dispatch = TRUE; 00768 00769 if(isFullDebug(COMPONENT_RPCSEC_GSS)) 00770 { 00771 sprint_ctx(ctx_str, (unsigned char *)gr.gr_ctx.value, 00772 gr.gr_ctx.length); 00773 LogFullDebug(COMPONENT_RPCSEC_GSS, 00774 "Call to Gssrpc__svcauth_gss ----> Client=%s " 00775 "length=%lu (GD: established=%u) (RQ:sock=%u) " 00776 "(GR: maj=%u min=%u ctx=%s)", 00777 (char *)gd->cname.value, 00778 (long unsigned int)gd->cname.length, 00779 gd->established, 00780 rqst->rq_xprt->xp_fd, 00781 gr.gr_major, 00782 gr.gr_minor, 00783 ctx_str); 00784 } 00785 00786 call_stat = svc_sendreply2(rqst->rq_xprt, rqst, 00787 (xdrproc_t)xdr_rpc_gss_init_res, 00788 (caddr_t) & gr); 00789 00790 gss_release_buffer(&min_stat, &gr.gr_token); 00791 gss_release_buffer(&min_stat, &gd->checksum); 00792 gsh_free(gr.gr_ctx.value); 00793 00794 if(!call_stat) 00795 { 00796 LogFullDebug(COMPONENT_RPCSEC_GSS, "BAD AUTH: svc_sendreply failed."); 00797 ret_freegc(AUTH_FAILED); 00798 } 00799 00800 if(gr.gr_major == GSS_S_COMPLETE) 00801 { 00802 gss_union_ctx_id_desc *gss_ctx_data2 = 00803 (gss_union_ctx_id_desc *)gd->ctx; 00804 00805 gd->established = TRUE; 00806 00807 /* Keep the gss context in a hash, gr.gr_ctx.value is used as key */ 00808 (void) Gss_ctx_Hash_Set(gss_ctx_data2, gd); 00809 } 00810 00811 break; 00812 00813 case RPCSEC_GSS_DATA: 00814 LogFullDebug(COMPONENT_RPCSEC_GSS, "Reached RPCSEC_GSS_DATA:"); 00815 if(!Svcauth_gss_validate(rqst, gd, msg)) 00816 { 00817 LogFullDebug(COMPONENT_RPCSEC_GSS, "BAD AUTH: Couldn't validate " 00818 "request."); 00819 ret_freegc(RPCSEC_GSS_CREDPROBLEM); 00820 } 00821 00822 if(!Svcauth_gss_nextverf(rqst, htonl(gc->gc_seq))) 00823 { 00824 LogFullDebug(COMPONENT_RPCSEC_GSS, "BAD AUTH: Checksum verification " 00825 "failed."); 00826 ret_freegc(AUTH_FAILED); 00827 } 00828 00829 /* Update a few important values in the hashtable entry */ 00830 if ( p_established != NULL) 00831 *p_established = gd->established; 00832 if ( p_seqlast != NULL) 00833 *p_seqlast = gd->seqlast; 00834 if (p_seqmask != NULL) 00835 *p_seqmask = gd->seqmask; 00836 00837 break; 00838 00839 case RPCSEC_GSS_DESTROY: 00840 LogFullDebug(COMPONENT_RPCSEC_GSS, "Reached RPCSEC_GSS_DESTROY:"); 00841 if(rqst->rq_proc != NULLPROC) 00842 ret_freegc(AUTH_FAILED); /* XXX ? */ 00843 00844 if(!Svcauth_gss_validate(rqst, gd, msg)) 00845 ret_freegc(RPCSEC_GSS_CREDPROBLEM); 00846 00847 if(!Svcauth_gss_nextverf(rqst, htonl(gc->gc_seq))) 00848 { 00849 LogFullDebug(COMPONENT_RPCSEC_GSS, "BAD AUTH: Checksum verification " 00850 "failed."); 00851 ret_freegc(AUTH_FAILED); 00852 } 00853 00854 *no_dispatch = TRUE; 00855 00856 call_stat = svc_sendreply2(rqst->rq_xprt, rqst, 00857 (xdrproc_t)xdr_void, 00858 (caddr_t) NULL); 00859 00860 if(!Gss_ctx_Hash_Del(gss_ctx_data)) 00861 { 00862 LogCrit(COMPONENT_RPCSEC_GSS, 00863 "Could not delete Gss Context from hash"); 00864 } 00865 else 00866 LogFullDebug(COMPONENT_RPCSEC_GSS, "Gss_ctx_Hash_Del OK"); 00867 00868 if(!Svcauth_gss_release_cred()) 00869 { 00870 LogFullDebug(COMPONENT_RPCSEC_GSS, "BAD AUTH: Failed to release " 00871 "credentials."); 00872 ret_freegc(AUTH_FAILED); 00873 } 00874 00875 if(rqst->rq_xprt->xp_auth) 00876 SVCAUTH_DESTROY(rqst->rq_xprt->xp_auth); 00877 rqst->rq_xprt->xp_auth = &Svc_auth_none; 00878 00879 break; 00880 00881 default: 00882 LogFullDebug(COMPONENT_RPCSEC_GSS, "BAD AUTH: Request is not INIT, " 00883 "INIT_CONTINUE, DATA, OR DESTROY."); 00884 ret_freegc(AUTH_REJECTEDCRED); 00885 break; 00886 } 00887 00888 LogFullDebug(COMPONENT_RPCSEC_GSS, 00889 "Call to Gssrpc__svcauth_gss - OK ---> (RQ:sock=%u)", 00890 rqst->rq_xprt->xp_fd); 00891 00892 retstat = AUTH_OK; 00893 freegc: 00894 if(retstat != AUTH_OK) 00895 LogCrit(COMPONENT_RPCSEC_GSS, 00896 "Call to Gssrpc__svcauth_gss - FAILED ---> (RQ:sock=%u)", 00897 rqst->rq_xprt->xp_fd); 00898 00899 xdr_free((xdrproc_t)xdr_rpc_gss_cred, gc); 00900 return (retstat); 00901 } 00902 00903 static bool_t Svcauth_gss_destroy(SVCAUTH * auth) 00904 { 00905 struct svc_rpc_gss_data *gd; 00906 OM_uint32 min_stat; 00907 00908 gd = SVCAUTH_PRIVATE(auth); 00909 00910 gss_delete_sec_context(&min_stat, &gd->ctx, GSS_C_NO_BUFFER); 00911 00912 gss_release_buffer(&min_stat, &gd->cname); 00913 gss_release_buffer(&min_stat, &gd->checksum); 00914 00915 if(gd->client_name) 00916 gss_release_name(&min_stat, &gd->client_name); 00917 00918 gsh_free(gd); 00919 gsh_free(auth); 00920 00921 return (TRUE); 00922 } 00923 00924 static bool_t Svcauth_gss_destroy_copy(SVCAUTH * auth) 00925 { 00926 /* svc_ah_private aka gd points to the same gd as the original, so no need 00927 * to free or destroy. 00928 * Just free the auth structure (pointer to ops and pointer to gd). 00929 */ 00930 gsh_free(auth); 00931 00932 return (TRUE); 00933 } 00934 00935 #ifndef DONT_USE_WRAPUNWRAP 00936 #define RPC_SLACK_SPACE 1024 00937 00938 bool_t 00939 Xdr_rpc_gss_buf(XDR *xdrs, gss_buffer_t buf, u_int maxsize) 00940 { 00941 bool_t xdr_stat; 00942 u_int tmplen; 00943 00944 if (xdrs->x_op != XDR_DECODE) { 00945 if (buf->length > UINT_MAX) 00946 return FALSE; 00947 else 00948 tmplen = buf->length; 00949 } 00950 xdr_stat = xdr_bytes(xdrs, (char **)&buf->value, &tmplen, maxsize); 00951 00952 if (xdr_stat && xdrs->x_op == XDR_DECODE) 00953 buf->length = tmplen; 00954 00955 LogFullDebug(COMPONENT_RPCSEC_GSS, 00956 "Xdr_rpc_gss_buf: %s %s (%p:%d)", 00957 (xdrs->x_op == XDR_ENCODE) ? "encode" : "decode", 00958 (xdr_stat == TRUE) ? "success" : "failure", 00959 buf->value, (int)buf->length); 00960 00961 return xdr_stat; 00962 } 00963 00964 bool_t 00965 Xdr_rpc_gss_wrap_data(XDR *xdrs, xdrproc_t xdr_func, caddr_t xdr_ptr, 00966 gss_ctx_id_t ctx, gss_qop_t qop, 00967 rpc_gss_svc_t svc, u_int seq) 00968 { 00969 gss_buffer_desc databuf, wrapbuf; 00970 OM_uint32 maj_stat, min_stat; 00971 int start, end, conf_state; 00972 bool_t xdr_stat = FALSE; 00973 u_int databuflen, maxwrapsz; 00974 00975 /* Skip databody length. */ 00976 start = XDR_GETPOS(xdrs); 00977 XDR_SETPOS(xdrs, start + 4); 00978 00979 memset(&databuf, 0, sizeof(databuf)); 00980 memset(&wrapbuf, 0, sizeof(wrapbuf)); 00981 00982 /* Marshal rpc_gss_data_t (sequence number + arguments). */ 00983 if (!xdr_u_int(xdrs, &seq) || !(*xdr_func)(xdrs, xdr_ptr)) 00984 return (FALSE); 00985 end = XDR_GETPOS(xdrs); 00986 00987 /* Set databuf to marshalled rpc_gss_data_t. */ 00988 databuflen = end - start - 4; 00989 XDR_SETPOS(xdrs, start + 4); 00990 databuf.value = XDR_INLINE(xdrs, databuflen); 00991 databuf.length = databuflen; 00992 00993 xdr_stat = FALSE; 00994 00995 if (svc == RPCSEC_GSS_SVC_INTEGRITY) { 00996 /* Marshal databody_integ length. */ 00997 XDR_SETPOS(xdrs, start); 00998 if (!xdr_u_int(xdrs, (u_int *)&databuflen)) 00999 return (FALSE); 01000 01001 /* Checksum rpc_gss_data_t. */ 01002 maj_stat = gss_get_mic(&min_stat, ctx, qop, 01003 &databuf, &wrapbuf); 01004 if (maj_stat != GSS_S_COMPLETE) { 01005 LogFullDebug(COMPONENT_RPCSEC_GSS,"gss_get_mic failed"); 01006 return (FALSE); 01007 } 01008 /* Marshal checksum. */ 01009 XDR_SETPOS(xdrs, end); 01010 maxwrapsz = (u_int)(wrapbuf.length + RPC_SLACK_SPACE); 01011 xdr_stat = Xdr_rpc_gss_buf(xdrs, &wrapbuf, maxwrapsz); 01012 gss_release_buffer(&min_stat, &wrapbuf); 01013 } 01014 else if (svc == RPCSEC_GSS_SVC_PRIVACY) { 01015 /* Encrypt rpc_gss_data_t. */ 01016 maj_stat = gss_wrap(&min_stat, ctx, TRUE, qop, &databuf, 01017 &conf_state, &wrapbuf); 01018 if (maj_stat != GSS_S_COMPLETE) { 01019 LogFullDebug(COMPONENT_RPCSEC_GSS,"gss_wrap %d %d", 01020 maj_stat, min_stat); 01021 return (FALSE); 01022 } 01023 /* Marshal databody_priv. */ 01024 XDR_SETPOS(xdrs, start); 01025 maxwrapsz = (u_int)(wrapbuf.length + RPC_SLACK_SPACE); 01026 xdr_stat = Xdr_rpc_gss_buf(xdrs, &wrapbuf, maxwrapsz); 01027 gss_release_buffer(&min_stat, &wrapbuf); 01028 } 01029 return (xdr_stat); 01030 } 01031 01032 bool_t 01033 Xdr_rpc_gss_unwrap_data(XDR *xdrs, xdrproc_t xdr_func, caddr_t xdr_ptr, 01034 gss_ctx_id_t ctx, gss_qop_t qop, 01035 rpc_gss_svc_t svc, u_int seq) 01036 { 01037 XDR tmpxdrs; 01038 gss_buffer_desc databuf, wrapbuf; 01039 OM_uint32 maj_stat, min_stat; 01040 u_int seq_num, qop_state; 01041 int conf_state; 01042 bool_t xdr_stat; 01043 01044 if (xdr_func == (xdrproc_t)xdr_void || xdr_ptr == NULL) 01045 return (TRUE); 01046 01047 memset(&databuf, 0, sizeof(databuf)); 01048 memset(&wrapbuf, 0, sizeof(wrapbuf)); 01049 01050 if (svc == RPCSEC_GSS_SVC_INTEGRITY) { 01051 /* Decode databody_integ. */ 01052 if (!Xdr_rpc_gss_buf(xdrs, &databuf, (u_int)-1)) { 01053 LogFullDebug(COMPONENT_RPCSEC_GSS,"xdr decode " 01054 "databody_integ failed"); 01055 return (FALSE); 01056 } 01057 /* Decode checksum. */ 01058 if (!Xdr_rpc_gss_buf(xdrs, &wrapbuf, (u_int)-1)) { 01059 #if 0 01060 gss_release_buffer(&min_stat, &databuf); 01061 #else 01062 gsh_free(databuf.value); 01063 #endif 01064 LogFullDebug(COMPONENT_RPCSEC_GSS, 01065 "xdr decode checksum failed"); 01066 return (FALSE); 01067 } 01068 /* Verify checksum and QOP. */ 01069 maj_stat = gss_verify_mic(&min_stat, ctx, &databuf, 01070 &wrapbuf, &qop_state); 01071 #if 0 01072 gss_release_buffer(&min_stat, &wrapbuf); 01073 #else 01074 gsh_free(wrapbuf.value); 01075 #endif 01076 01077 if (maj_stat != GSS_S_COMPLETE || qop_state != qop) { 01078 #if 0 01079 gss_release_buffer(&min_stat, &databuf); 01080 #else 01081 gsh_free(databuf.value); 01082 #endif 01083 LogFullDebug(COMPONENT_RPCSEC_GSS, 01084 "gss_verify_mic %d %d", maj_stat, 01085 min_stat); 01086 return (FALSE); 01087 } 01088 } 01089 else if (svc == RPCSEC_GSS_SVC_PRIVACY) { 01090 /* Decode databody_priv. */ 01091 if (!Xdr_rpc_gss_buf(xdrs, &wrapbuf, (u_int)-1)) { 01092 LogFullDebug(COMPONENT_RPCSEC_GSS, 01093 "xdr decode databody_priv failed"); 01094 return (FALSE); 01095 } 01096 /* Decrypt databody. */ 01097 maj_stat = gss_unwrap(&min_stat, ctx, &wrapbuf, &databuf, 01098 &conf_state, &qop_state); 01099 01100 gss_release_buffer(&min_stat, &wrapbuf); 01101 01102 /* Verify encryption and QOP. */ 01103 if (maj_stat != GSS_S_COMPLETE || qop_state != qop || 01104 conf_state != TRUE) { 01105 gss_release_buffer(&min_stat, &databuf); 01106 LogFullDebug(COMPONENT_RPCSEC_GSS, 01107 "gss_unwrap %d %d", maj_stat, min_stat); 01108 return (FALSE); 01109 } 01110 } 01111 /* Decode rpc_gss_data_t (sequence number + arguments). */ 01112 xdrmem_create(&tmpxdrs, databuf.value, databuf.length, XDR_DECODE); 01113 xdr_stat = (xdr_u_int(&tmpxdrs, &seq_num) && 01114 (*xdr_func)(&tmpxdrs, xdr_ptr)); 01115 XDR_DESTROY(&tmpxdrs); 01116 #if 0 01117 gss_release_buffer(&min_stat, &databuf); 01118 #else 01119 gsh_free(databuf.value); 01120 #endif 01121 01122 /* Verify sequence number. */ 01123 if (xdr_stat == TRUE && seq_num != seq) { 01124 LogFullDebug(COMPONENT_RPCSEC_GSS, 01125 "wrong sequence number in databody"); 01126 return (FALSE); 01127 } 01128 return (xdr_stat); 01129 } 01130 01131 bool_t 01132 Xdr_rpc_gss_data(XDR *xdrs, xdrproc_t xdr_func, caddr_t xdr_ptr, 01133 gss_ctx_id_t ctx, gss_qop_t qop, 01134 rpc_gss_svc_t svc, u_int seq) 01135 { 01136 bool_t rc; 01137 switch (xdrs->x_op) { 01138 01139 case XDR_ENCODE: 01140 rc = (Xdr_rpc_gss_wrap_data(xdrs, xdr_func, xdr_ptr, 01141 ctx, qop, svc, seq)); 01142 LogFullDebug(COMPONENT_RPCSEC_GSS, 01143 "Xdr_rpc_gss_data ENCODE returns %d", 01144 rc); 01145 return rc; 01146 case XDR_DECODE: 01147 rc = (Xdr_rpc_gss_unwrap_data(xdrs, xdr_func, xdr_ptr, 01148 ctx, qop,svc, seq)); 01149 LogFullDebug(COMPONENT_RPCSEC_GSS, 01150 "Xdr_rpc_gss_data DECODE returns %d", 01151 rc); 01152 return rc; 01153 case XDR_FREE: 01154 return (TRUE); 01155 } 01156 return (FALSE); 01157 } 01158 #endif 01159 01160 static bool_t 01161 Svcauth_gss_wrap(SVCAUTH * auth, XDR * xdrs, xdrproc_t xdr_func, 01162 caddr_t xdr_ptr) 01163 { 01164 struct svc_rpc_gss_data *gd; 01165 01166 gd = SVCAUTH_PRIVATE(auth); 01167 01168 if(!gd->established || gd->sec.svc == RPCSEC_GSS_SVC_NONE) 01169 { 01170 return ((*xdr_func) (xdrs, xdr_ptr)); 01171 } 01172 #ifndef DONT_USE_WRAPUNWRAP 01173 return (Xdr_rpc_gss_data(xdrs, xdr_func, xdr_ptr, 01174 gd->ctx, gd->sec.qop, gd->sec.svc, gd->seq)); 01175 #else 01176 return (xdr_rpc_gss_data(xdrs, xdr_func, xdr_ptr, 01177 gd->ctx, gd->sec.qop, gd->sec.svc, gd->seq)); 01178 #endif 01179 } 01180 01181 static bool_t 01182 Svcauth_gss_unwrap(SVCAUTH * auth, XDR * xdrs, xdrproc_t xdr_func, 01183 caddr_t xdr_ptr) 01184 { 01185 struct svc_rpc_gss_data *gd; 01186 01187 gd = SVCAUTH_PRIVATE(auth); 01188 01189 if(!gd->established || gd->sec.svc == RPCSEC_GSS_SVC_NONE) 01190 { 01191 return ((*xdr_func) (xdrs, xdr_ptr)); 01192 } 01193 #ifndef DONT_USE_WRAPUNWRAP 01194 return (Xdr_rpc_gss_data(xdrs, xdr_func, xdr_ptr, 01195 gd->ctx, gd->sec.qop, gd->sec.svc, gd->seq)); 01196 #else 01197 return (xdr_rpc_gss_data(xdrs, xdr_func, xdr_ptr, 01198 gd->ctx, gd->sec.qop, gd->sec.svc, gd->seq)); 01199 #endif 01200 } 01201 01202 int copy_svc_authgss(SVCXPRT *xprt_copy, SVCXPRT *xprt_orig) 01203 { 01204 if(xprt_orig->xp_auth) 01205 { 01206 if(xprt_orig->xp_auth->svc_ah_ops == &Svc_auth_gss_ops || 01207 xprt_orig->xp_auth->svc_ah_ops == &Svc_auth_gss_copy_ops) 01208 { 01209 /* Copy GSS auth */ 01210 struct svc_rpc_gss_data *gd_o, *gd_c; 01211 01212 gd_o = SVCAUTH_PRIVATE(xprt_orig->xp_auth); 01213 xprt_copy->xp_auth = gsh_malloc(sizeof(SVCAUTH)); 01214 if(xprt_copy->xp_auth == NULL) 01215 return 0; 01216 gd_c = gsh_malloc(sizeof(*gd_c)); 01217 if(gd_c == NULL) 01218 { 01219 gsh_free(xprt_copy->xp_auth); 01220 xprt_copy->xp_auth = NULL; 01221 return 0; 01222 } 01223 01224 /* Copy everything over */ 01225 memcpy(gd_c, gd_o, sizeof(*gd_c)); 01226 01227 /* Leave the original without the various pointed to things */ 01228 gd_o->checksum.length = 0; 01229 gd_o->checksum.value = NULL; 01230 gd_o->cname.length = 0; 01231 gd_o->cname.value = NULL; 01232 gd_o->client_name = NULL; 01233 gd_o->ctx = NULL; 01234 01235 /* fill in xp_auth */ 01236 xprt_copy->xp_auth->svc_ah_private = (void *)gd_c; 01237 xprt_copy->xp_auth->svc_ah_ops = &Svc_auth_gss_ops; 01238 } 01239 else 01240 { 01241 /* Should be Svc_auth_none */ 01242 if(xprt_orig->xp_auth != &Svc_auth_none) 01243 LogFullDebug(COMPONENT_RPCSEC_GSS, 01244 "copy_svc_authgss copying unknown xp_auth"); 01245 xprt_copy->xp_auth = xprt_orig->xp_auth; 01246 } 01247 } 01248 else 01249 xprt_copy->xp_auth = NULL; 01250 return 1; 01251 } 01252