bool_t xdr_rpc_gss_data(XDR *xdrs, xdrproc_t xdr_func, caddr_t xdr_ptr, gss_ctx_id_t ctx, gss_qop_t qop, rpc_gss_svc_t svc, u_int seq) { switch (xdrs->x_op) { case XDR_ENCODE: return (xdr_rpc_gss_wrap_data(xdrs, xdr_func, xdr_ptr, ctx, qop, svc, seq)); case XDR_DECODE: return (xdr_rpc_gss_unwrap_data(xdrs, xdr_func, xdr_ptr, ctx, qop,svc, seq)); case XDR_FREE: return (TRUE); } return (FALSE); }
bool_t __rpc_gss_wrap(AUTH *auth, void *header, size_t headerlen, XDR* xdrs, xdrproc_t xdr_args, void *args_ptr) { XDR tmpxdrs; char credbuf[MAX_AUTH_BYTES]; char tmpheader[MAX_AUTH_BYTES]; struct opaque_auth creds, verf; struct rpc_gss_data *gd; gss_buffer_desc rpcbuf, checksum; OM_uint32 maj_stat, min_stat; bool_t xdr_stat; log_debug("in rpc_gss_wrap()"); gd = AUTH_PRIVATE(auth); if (gd->gd_state == RPCSEC_GSS_ESTABLISHED) gd->gd_cred.gc_seq++; /* * We need to encode our creds and then put the header and * creds together in a buffer so that we can create a checksum * for the verf. */ xdrmem_create(&tmpxdrs, credbuf, sizeof(credbuf), XDR_ENCODE); if (!xdr_rpc_gss_cred(&tmpxdrs, &gd->gd_cred)) { XDR_DESTROY(&tmpxdrs); _rpc_gss_set_error(RPC_GSS_ER_SYSTEMERROR, ENOMEM); return (FALSE); } creds.oa_flavor = RPCSEC_GSS; creds.oa_base = credbuf; creds.oa_length = XDR_GETPOS(&tmpxdrs); XDR_DESTROY(&tmpxdrs); xdrmem_create(&tmpxdrs, tmpheader, sizeof(tmpheader), XDR_ENCODE); if (!XDR_PUTBYTES(&tmpxdrs, header, headerlen) || !xdr_opaque_auth(&tmpxdrs, &creds)) { XDR_DESTROY(&tmpxdrs); _rpc_gss_set_error(RPC_GSS_ER_SYSTEMERROR, ENOMEM); return (FALSE); } headerlen = XDR_GETPOS(&tmpxdrs); XDR_DESTROY(&tmpxdrs); if (!XDR_PUTBYTES(xdrs, tmpheader, headerlen)) { _rpc_gss_set_error(RPC_GSS_ER_SYSTEMERROR, ENOMEM); return (FALSE); } if (gd->gd_cred.gc_proc == RPCSEC_GSS_INIT || gd->gd_cred.gc_proc == RPCSEC_GSS_CONTINUE_INIT) { if (!xdr_opaque_auth(xdrs, &_null_auth)) { _rpc_gss_set_error(RPC_GSS_ER_SYSTEMERROR, ENOMEM); return (FALSE); } } else { /* * Checksum serialized RPC header, up to and including * credential. */ rpcbuf.length = headerlen; rpcbuf.value = tmpheader; maj_stat = gss_get_mic(&min_stat, gd->gd_ctx, gd->gd_qop, &rpcbuf, &checksum); if (maj_stat != GSS_S_COMPLETE) { log_status("gss_get_mic", gd->gd_mech, maj_stat, min_stat); if (maj_stat == GSS_S_CONTEXT_EXPIRED) { rpc_gss_destroy_context(auth, TRUE); } _rpc_gss_set_error(RPC_GSS_ER_SYSTEMERROR, EPERM); return (FALSE); } verf.oa_flavor = RPCSEC_GSS; verf.oa_base = checksum.value; verf.oa_length = checksum.length; xdr_stat = xdr_opaque_auth(xdrs, &verf); gss_release_buffer(&min_stat, &checksum); if (!xdr_stat) { _rpc_gss_set_error(RPC_GSS_ER_SYSTEMERROR, ENOMEM); return (FALSE); } } if (gd->gd_state != RPCSEC_GSS_ESTABLISHED || gd->gd_cred.gc_svc == rpc_gss_svc_none) { return (xdr_args(xdrs, args_ptr)); } return (xdr_rpc_gss_wrap_data(xdrs, xdr_args, args_ptr, gd->gd_ctx, gd->gd_qop, gd->gd_cred.gc_svc, gd->gd_cred.gc_seq)); }