diff options
Diffstat (limited to 'lib/libc')
-rw-r--r-- | lib/libc/rpc/Makefile.inc | 5 | ||||
-rw-r--r-- | lib/libc/rpc/Symbol.map | 4 | ||||
-rw-r--r-- | lib/libc/rpc/clnt_dg.c | 112 | ||||
-rw-r--r-- | lib/libc/rpc/clnt_perror.c | 9 | ||||
-rw-r--r-- | lib/libc/rpc/clnt_vc.c | 49 | ||||
-rw-r--r-- | lib/libc/rpc/rpcsec_gss_stub.c | 48 | ||||
-rw-r--r-- | lib/libc/rpc/svc.c | 58 | ||||
-rw-r--r-- | lib/libc/rpc/svc_auth.c | 24 | ||||
-rw-r--r-- | lib/libc/rpc/svc_dg.c | 34 | ||||
-rw-r--r-- | lib/libc/rpc/svc_raw.c | 38 | ||||
-rw-r--r-- | lib/libc/rpc/svc_vc.c | 45 | ||||
-rw-r--r-- | lib/libc/xdr/xdr_rec.c | 25 |
12 files changed, 360 insertions, 91 deletions
diff --git a/lib/libc/rpc/Makefile.inc b/lib/libc/rpc/Makefile.inc index dceecc7..db0b8ad 100644 --- a/lib/libc/rpc/Makefile.inc +++ b/lib/libc/rpc/Makefile.inc @@ -8,8 +8,9 @@ SRCS+= auth_none.c auth_unix.c authunix_prot.c bindresvport.c clnt_bcast.c \ getrpcport.c mt_misc.c pmap_clnt.c pmap_getmaps.c pmap_getport.c \ pmap_prot.c pmap_prot2.c pmap_rmt.c rpc_prot.c rpc_commondata.c \ rpc_callmsg.c rpc_generic.c rpc_soc.c rpcb_clnt.c rpcb_prot.c \ - rpcb_st_xdr.c svc.c svc_auth.c svc_dg.c svc_auth_unix.c svc_generic.c \ - svc_raw.c svc_run.c svc_simple.c svc_vc.c + rpcb_st_xdr.c rpcsec_gss_stub.c svc.c svc_auth.c svc_dg.c \ + svc_auth_unix.c svc_generic.c svc_raw.c svc_run.c svc_simple.c \ + svc_vc.c # Secure-RPC SRCS+= auth_time.c auth_des.c authdes_prot.c des_crypt.c des_soft.c \ diff --git a/lib/libc/rpc/Symbol.map b/lib/libc/rpc/Symbol.map index e3ac6a6..ccf0bfa 100644 --- a/lib/libc/rpc/Symbol.map +++ b/lib/libc/rpc/Symbol.map @@ -244,4 +244,8 @@ FBSDprivate_1.0 { * Remove this hack if rpcinfo stops building with it. */ __svc_clean_idle; + __rpc_gss_unwrap; + __rpc_gss_unwrap_stub; + __rpc_gss_wrap; + __rpc_gss_wrap_stub; }; diff --git a/lib/libc/rpc/clnt_dg.c b/lib/libc/rpc/clnt_dg.c index 27296ab..3014155 100644 --- a/lib/libc/rpc/clnt_dg.c +++ b/lib/libc/rpc/clnt_dg.c @@ -52,6 +52,7 @@ __FBSDID("$FreeBSD$"); #include <sys/ioctl.h> #include <arpa/inet.h> #include <rpc/rpc.h> +#include <rpc/rpcsec_gss.h> #include <errno.h> #include <stdlib.h> #include <string.h> @@ -113,6 +114,8 @@ static const char mem_err_clnt_dg[] = "clnt_dg_create: out of memory"; /* VARIABLES PROTECTED BY clnt_fd_lock: dg_fd_locks, dg_cv */ +#define MCALL_MSG_SIZE 24 + /* * Private data kept per client handle */ @@ -127,6 +130,7 @@ struct cu_data { XDR cu_outxdrs; u_int cu_xdrpos; u_int cu_sendsz; /* send size */ + char cu_outhdr[MCALL_MSG_SIZE]; char *cu_outbuf; u_int cu_recvsz; /* recv size */ int cu_async; @@ -253,13 +257,16 @@ clnt_dg_create(fd, svcaddr, program, version, sendsz, recvsz) call_msg.rm_xid = __RPC_GETXID(&now); call_msg.rm_call.cb_prog = program; call_msg.rm_call.cb_vers = version; - xdrmem_create(&(cu->cu_outxdrs), cu->cu_outbuf, sendsz, XDR_ENCODE); - if (! xdr_callhdr(&(cu->cu_outxdrs), &call_msg)) { + xdrmem_create(&(cu->cu_outxdrs), cu->cu_outhdr, MCALL_MSG_SIZE, + XDR_ENCODE); + if (! xdr_callhdr(&cu->cu_outxdrs, &call_msg)) { rpc_createerr.cf_stat = RPC_CANTENCODEARGS; /* XXX */ rpc_createerr.cf_error.re_errno = 0; goto err2; } cu->cu_xdrpos = XDR_GETPOS(&(cu->cu_outxdrs)); + XDR_DESTROY(&cu->cu_outxdrs); + xdrmem_create(&cu->cu_outxdrs, cu->cu_outbuf, sendsz, XDR_ENCODE); /* XXX fvdl - do we still want this? */ #if 0 @@ -312,6 +319,7 @@ clnt_dg_call(cl, proc, xargs, argsp, xresults, resultsp, utimeout) XDR reply_xdrs; bool_t ok; int nrefreshes = 2; /* number of times to refresh cred */ + int nretries = 0; /* number of times we retransmitted */ struct timeval timeout; struct timeval retransmit_time; struct timeval next_sendtime, starttime, time_waited, tv; @@ -375,25 +383,37 @@ clnt_dg_call(cl, proc, xargs, argsp, xresults, resultsp, utimeout) kin_len = 1; call_again: - xdrs = &(cu->cu_outxdrs); - if (cu->cu_async == TRUE && xargs == NULL) - goto get_reply; - xdrs->x_op = XDR_ENCODE; - XDR_SETPOS(xdrs, cu->cu_xdrpos); /* * the transaction is the first thing in the out buffer * XXX Yes, and it's in network byte order, so we should to * be careful when we increment it, shouldn't we. */ - xid = ntohl(*(u_int32_t *)(void *)(cu->cu_outbuf)); + xid = ntohl(*(u_int32_t *)(void *)(cu->cu_outhdr)); xid++; - *(u_int32_t *)(void *)(cu->cu_outbuf) = htonl(xid); - - if ((! XDR_PUTINT32(xdrs, &proc)) || - (! AUTH_MARSHALL(cl->cl_auth, xdrs)) || - (! (*xargs)(xdrs, argsp))) { - cu->cu_error.re_status = RPC_CANTENCODEARGS; - goto out; + *(u_int32_t *)(void *)(cu->cu_outhdr) = htonl(xid); +call_again_same_xid: + xdrs = &(cu->cu_outxdrs); + if (cu->cu_async == TRUE && xargs == NULL) + goto get_reply; + xdrs->x_op = XDR_ENCODE; + XDR_SETPOS(xdrs, 0); + + if (cl->cl_auth->ah_cred.oa_flavor != RPCSEC_GSS) { + if ((! XDR_PUTBYTES(xdrs, cu->cu_outhdr, cu->cu_xdrpos)) || + (! XDR_PUTINT32(xdrs, &proc)) || + (! AUTH_MARSHALL(cl->cl_auth, xdrs)) || + (! (*xargs)(xdrs, argsp))) { + cu->cu_error.re_status = RPC_CANTENCODEARGS; + goto out; + } + } else { + *(uint32_t *) &cu->cu_outhdr[cu->cu_xdrpos] = htonl(proc); + if (!__rpc_gss_wrap(cl->cl_auth, cu->cu_outhdr, + cu->cu_xdrpos + sizeof(uint32_t), + xdrs, xargs, argsp)) { + cu->cu_error.re_status = RPC_CANTENCODEARGS; + goto out; + } } outlen = (size_t)XDR_GETPOS(xdrs); @@ -420,8 +440,13 @@ get_reply: * (We assume that this is actually only executed once.) */ reply_msg.acpted_rply.ar_verf = _null_auth; - reply_msg.acpted_rply.ar_results.where = resultsp; - reply_msg.acpted_rply.ar_results.proc = xresults; + if (cl->cl_auth->ah_cred.oa_flavor != RPCSEC_GSS) { + reply_msg.acpted_rply.ar_results.where = resultsp; + reply_msg.acpted_rply.ar_results.proc = xresults; + } else { + reply_msg.acpted_rply.ar_results.where = NULL; + reply_msg.acpted_rply.ar_results.proc = (xdrproc_t)xdr_void; + } for (;;) { /* Decide how long to wait. */ @@ -483,7 +508,17 @@ get_reply: &retransmit_time); timeradd(&next_sendtime, &retransmit_time, &next_sendtime); - goto send_again; + nretries++; + + /* + * When retransmitting a RPCSEC_GSS message, + * we must use a new sequence number (handled + * by __rpc_gss_wrap above). + */ + if (cl->cl_auth->ah_cred.oa_flavor != RPCSEC_GSS) + goto send_again; + else + goto call_again_same_xid; } } inlen = (socklen_t)recvlen; @@ -505,8 +540,37 @@ get_reply: if (cu->cu_error.re_status == RPC_SUCCESS) { if (! AUTH_VALIDATE(cl->cl_auth, &reply_msg.acpted_rply.ar_verf)) { + if (nretries && + cl->cl_auth->ah_cred.oa_flavor + == RPCSEC_GSS) + /* + * If we retransmitted, its + * possible that we will + * receive a reply for one of + * the earlier transmissions + * (which will use an older + * RPCSEC_GSS sequence + * number). In this case, just + * go back and listen for a + * new reply. We could keep a + * record of all the seq + * numbers we have transmitted + * so far so that we could + * accept a reply for any of + * them here. + */ + goto get_reply; cu->cu_error.re_status = RPC_AUTHERROR; cu->cu_error.re_why = AUTH_INVALIDRESP; + } else { + if (cl->cl_auth->ah_cred.oa_flavor + == RPCSEC_GSS) { + if (!__rpc_gss_unwrap(cl->cl_auth, + &reply_xdrs, xresults, + resultsp)) + cu->cu_error.re_status = + RPC_CANTDECODERES; + } } if (reply_msg.acpted_rply.ar_verf.oa_base != NULL) { xdrs->x_op = XDR_FREE; @@ -670,12 +734,12 @@ clnt_dg_control(cl, request, info) * This will get the xid of the PREVIOUS call */ *(u_int32_t *)info = - ntohl(*(u_int32_t *)(void *)cu->cu_outbuf); + ntohl(*(u_int32_t *)(void *)cu->cu_outhdr); break; case CLSET_XID: /* This will set the xid of the NEXT call */ - *(u_int32_t *)(void *)cu->cu_outbuf = + *(u_int32_t *)(void *)cu->cu_outhdr = htonl(*(u_int32_t *)info - 1); /* decrement by 1 as clnt_dg_call() increments once */ break; @@ -688,12 +752,12 @@ clnt_dg_control(cl, request, info) * call_struct is changed */ *(u_int32_t *)info = - ntohl(*(u_int32_t *)(void *)(cu->cu_outbuf + + ntohl(*(u_int32_t *)(void *)(cu->cu_outhdr + 4 * BYTES_PER_XDR_UNIT)); break; case CLSET_VERS: - *(u_int32_t *)(void *)(cu->cu_outbuf + 4 * BYTES_PER_XDR_UNIT) + *(u_int32_t *)(void *)(cu->cu_outhdr + 4 * BYTES_PER_XDR_UNIT) = htonl(*(u_int32_t *)info); break; @@ -705,12 +769,12 @@ clnt_dg_control(cl, request, info) * call_struct is changed */ *(u_int32_t *)info = - ntohl(*(u_int32_t *)(void *)(cu->cu_outbuf + + ntohl(*(u_int32_t *)(void *)(cu->cu_outhdr + 3 * BYTES_PER_XDR_UNIT)); break; case CLSET_PROG: - *(u_int32_t *)(void *)(cu->cu_outbuf + 3 * BYTES_PER_XDR_UNIT) + *(u_int32_t *)(void *)(cu->cu_outhdr + 3 * BYTES_PER_XDR_UNIT) = htonl(*(u_int32_t *)info); break; case CLSET_ASYNC: diff --git a/lib/libc/rpc/clnt_perror.c b/lib/libc/rpc/clnt_perror.c index 4b6d6b1..efe9043 100644 --- a/lib/libc/rpc/clnt_perror.c +++ b/lib/libc/rpc/clnt_perror.c @@ -309,7 +309,14 @@ static const char *const auth_errlist[] = { "Server rejected verifier", /* 4 - AUTH_REJECTEDVERF */ "Client credential too weak", /* 5 - AUTH_TOOWEAK */ "Invalid server verifier", /* 6 - AUTH_INVALIDRESP */ - "Failed (unspecified error)" /* 7 - AUTH_FAILED */ + "Failed (unspecified error)", /* 7 - AUTH_FAILED */ + "Kerberos generic error", /* 8 - AUTH_KERB_GENERIC*/ + "Kerberos credential expired", /* 9 - AUTH_TIMEEXPIRE */ + "Bad kerberos ticket file", /* 10 - AUTH_TKT_FILE */ + "Can't decode kerberos authenticator", /* 11 - AUTH_DECODE */ + "Address wrong in kerberos ticket", /* 12 - AUTH_NET_ADDR */ + "GSS-API crediential problem", /* 13 - RPCSEC_GSS_CREDPROBLEM */ + "GSS-API context problem" /* 14 - RPCSEC_GSS_CTXPROBLEM */ }; static char * diff --git a/lib/libc/rpc/clnt_vc.c b/lib/libc/rpc/clnt_vc.c index 414eb0b..07eff46 100644 --- a/lib/libc/rpc/clnt_vc.c +++ b/lib/libc/rpc/clnt_vc.c @@ -77,6 +77,7 @@ __FBSDID("$FreeBSD$"); #include <signal.h> #include <rpc/rpc.h> +#include <rpc/rpcsec_gss.h> #include "un-namespace.h" #include "rpc_com.h" #include "mt_misc.h" @@ -285,6 +286,7 @@ clnt_vc_create(fd, raddr, prog, vers, sendsz, recvsz) } ct->ct_mpos = XDR_GETPOS(&(ct->ct_xdrs)); XDR_DESTROY(&(ct->ct_xdrs)); + assert(ct->ct_mpos + sizeof(uint32_t) <= MCALL_MSG_SIZE); /* * Create a client handle which uses xdrrec for serialization @@ -331,6 +333,7 @@ clnt_vc_call(cl, proc, xdr_args, args_ptr, xdr_results, results_ptr, timeout) int refreshes = 2; sigset_t mask, newmask; int rpc_lock_value; + bool_t reply_stat; assert(cl != NULL); @@ -360,15 +363,28 @@ call_again: ct->ct_error.re_status = RPC_SUCCESS; x_id = ntohl(--(*msg_x_id)); - if ((! XDR_PUTBYTES(xdrs, ct->ct_u.ct_mcallc, ct->ct_mpos)) || - (! XDR_PUTINT32(xdrs, &proc)) || - (! AUTH_MARSHALL(cl->cl_auth, xdrs)) || - (! (*xdr_args)(xdrs, args_ptr))) { - if (ct->ct_error.re_status == RPC_SUCCESS) - ct->ct_error.re_status = RPC_CANTENCODEARGS; - (void)xdrrec_endofrecord(xdrs, TRUE); - release_fd_lock(ct->ct_fd, mask); - return (ct->ct_error.re_status); + if (cl->cl_auth->ah_cred.oa_flavor != RPCSEC_GSS) { + if ((! XDR_PUTBYTES(xdrs, ct->ct_u.ct_mcallc, ct->ct_mpos)) || + (! XDR_PUTINT32(xdrs, &proc)) || + (! AUTH_MARSHALL(cl->cl_auth, xdrs)) || + (! (*xdr_args)(xdrs, args_ptr))) { + if (ct->ct_error.re_status == RPC_SUCCESS) + ct->ct_error.re_status = RPC_CANTENCODEARGS; + (void)xdrrec_endofrecord(xdrs, TRUE); + release_fd_lock(ct->ct_fd, mask); + return (ct->ct_error.re_status); + } + } else { + *(uint32_t *) &ct->ct_u.ct_mcallc[ct->ct_mpos] = htonl(proc); + if (! __rpc_gss_wrap(cl->cl_auth, ct->ct_u.ct_mcallc, + ct->ct_mpos + sizeof(uint32_t), + xdrs, xdr_args, args_ptr)) { + if (ct->ct_error.re_status == RPC_SUCCESS) + ct->ct_error.re_status = RPC_CANTENCODEARGS; + (void)xdrrec_endofrecord(xdrs, TRUE); + release_fd_lock(ct->ct_fd, mask); + return (ct->ct_error.re_status); + } } if (! xdrrec_endofrecord(xdrs, shipnow)) { release_fd_lock(ct->ct_fd, mask); @@ -419,9 +435,18 @@ call_again: &reply_msg.acpted_rply.ar_verf)) { ct->ct_error.re_status = RPC_AUTHERROR; ct->ct_error.re_why = AUTH_INVALIDRESP; - } else if (! (*xdr_results)(xdrs, results_ptr)) { - if (ct->ct_error.re_status == RPC_SUCCESS) - ct->ct_error.re_status = RPC_CANTDECODERES; + } else { + if (cl->cl_auth->ah_cred.oa_flavor != RPCSEC_GSS) { + reply_stat = (*xdr_results)(xdrs, results_ptr); + } else { + reply_stat = __rpc_gss_unwrap(cl->cl_auth, + xdrs, xdr_results, results_ptr); + } + if (! reply_stat) { + if (ct->ct_error.re_status == RPC_SUCCESS) + ct->ct_error.re_status = + RPC_CANTDECODERES; + } } /* free verifier ... */ if (reply_msg.acpted_rply.ar_verf.oa_base != NULL) { diff --git a/lib/libc/rpc/rpcsec_gss_stub.c b/lib/libc/rpc/rpcsec_gss_stub.c new file mode 100644 index 0000000..55eb106 --- /dev/null +++ b/lib/libc/rpc/rpcsec_gss_stub.c @@ -0,0 +1,48 @@ +/*- + * Copyright (c) 2006 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include <rpc/rpc.h> +#include <rpc/rpcsec_gss.h> + +bool_t +__rpc_gss_wrap_stub(AUTH *auth, void *header, size_t headerlen, XDR* xdrs, + xdrproc_t xdr_args, void *args_ptr) +{ + + return (FALSE); +} + +bool_t +__rpc_gss_unwrap_stub(AUTH *auth, XDR* xdrs, xdrproc_t xdr_args, void *args_ptr) +{ + + return (FALSE); +} + +__weak_reference(__rpc_gss_wrap_stub, __rpc_gss_wrap); +__weak_reference(__rpc_gss_unwrap_stub, __rpc_gss_unwrap); diff --git a/lib/libc/rpc/svc.c b/lib/libc/rpc/svc.c index b924bde..f5654b1 100644 --- a/lib/libc/rpc/svc.c +++ b/lib/libc/rpc/svc.c @@ -67,7 +67,7 @@ __FBSDID("$FreeBSD$"); #define RQCRED_SIZE 400 /* this size is excessive */ #define SVC_VERSQUIET 0x0001 /* keep quiet about vers mismatch */ -#define version_keepquiet(xp) ((u_long)(xp)->xp_p3 & SVC_VERSQUIET) +#define version_keepquiet(xp) (SVC_EXT(xp)->xp_flags & SVC_VERSQUIET) #define max(a, b) (a > b ? a : b) @@ -452,20 +452,16 @@ void __svc_versquiet_on(xprt) SVCXPRT *xprt; { - u_long tmp; - tmp = ((u_long) xprt->xp_p3) | SVC_VERSQUIET; - xprt->xp_p3 = tmp; + SVC_EXT(xprt)->xp_flags |= SVC_VERSQUIET; } void __svc_versquiet_off(xprt) SVCXPRT *xprt; { - u_long tmp; - tmp = ((u_long) xprt->xp_p3) & ~SVC_VERSQUIET; - xprt->xp_p3 = tmp; + SVC_EXT(xprt)->xp_flags &= ~SVC_VERSQUIET; } void @@ -479,7 +475,8 @@ int __svc_versquiet_get(xprt) SVCXPRT *xprt; { - return ((int) xprt->xp_p3) & SVC_VERSQUIET; + + return (SVC_EXT(xprt)->xp_flags & SVC_VERSQUIET); } #endif @@ -555,6 +552,39 @@ svcerr_progvers(xprt, low_vers, high_vers) SVC_REPLY(xprt, &rply); } +/* + * Allocate a new server transport structure. All fields are + * initialized to zero and xp_p3 is initialized to point at an + * extension structure to hold various flags and authentication + * parameters. + */ +SVCXPRT * +svc_xprt_alloc() +{ + SVCXPRT *xprt; + SVCXPRT_EXT *ext; + + xprt = mem_alloc(sizeof(SVCXPRT)); + memset(xprt, 0, sizeof(SVCXPRT)); + ext = mem_alloc(sizeof(SVCXPRT_EXT)); + memset(ext, 0, sizeof(SVCXPRT_EXT)); + xprt->xp_p3 = ext; + + return (xprt); +} + +/* + * Free a server transport structure. + */ +void +svc_xprt_free(xprt) + SVCXPRT *xprt; +{ + + mem_free(xprt->xp_p3, sizeof(SVCXPRT_EXT)); + mem_free(xprt, sizeof(SVCXPRT)); +} + /* ******************* SERVER INPUT STUFF ******************* */ /* @@ -643,7 +673,15 @@ svc_getreq_common(fd) r.rq_cred = msg.rm_call.cb_cred; /* first authenticate the message */ if ((why = _authenticate(&r, &msg)) != AUTH_OK) { - svcerr_auth(xprt, why); + /* + * RPCSEC_GSS uses this return code + * for requests that form part of its + * context establishment protocol and + * should not be dispatched to the + * application. + */ + if (why != RPCSEC_GSS_NODISPATCH) + svcerr_auth(xprt, why); goto call_done; } /* now match message with a registered service*/ @@ -670,7 +708,7 @@ svc_getreq_common(fd) if (prog_found) svcerr_progvers(xprt, low_vers, high_vers); else - svcerr_noprog(xprt); + svcerr_noprog(xprt); /* Fall through to ... */ } /* diff --git a/lib/libc/rpc/svc_auth.c b/lib/libc/rpc/svc_auth.c index eb1a5f2..4e27ccd 100644 --- a/lib/libc/rpc/svc_auth.c +++ b/lib/libc/rpc/svc_auth.c @@ -75,6 +75,8 @@ struct authsvc { }; static struct authsvc *Auths = NULL; +static struct svc_auth_ops svc_auth_null_ops; + /* * The call rpc message, msg has been obtained from the wire. The msg contains * the raw form of credentials and verifiers. authenticate returns AUTH_OK @@ -105,6 +107,8 @@ _authenticate(rqst, msg) /* VARIABLES PROTECTED BY authsvc_lock: asp, Auths */ rqst->rq_cred = msg->rm_call.cb_cred; + SVC_AUTH(rqst->rq_xprt).svc_ah_ops = &svc_auth_null_ops; + SVC_AUTH(rqst->rq_xprt).svc_ah_private = NULL; rqst->rq_xprt->xp_verf.oa_flavor = _null_auth.oa_flavor; rqst->rq_xprt->xp_verf.oa_length = 0; cred_flavor = rqst->rq_cred.oa_flavor; @@ -143,6 +147,26 @@ _authenticate(rqst, msg) return (AUTH_REJECTEDCRED); } +/* + * A set of null auth methods used by any authentication protocols + * that don't need to inspect or modify the message body. + */ +static bool_t +svcauth_null_wrap(auth, xdrs, xdr_func, xdr_ptr) + SVCAUTH *auth; + XDR *xdrs; + xdrproc_t xdr_func; + caddr_t xdr_ptr; +{ + + return (xdr_func(xdrs, xdr_ptr)); +} + +static struct svc_auth_ops svc_auth_null_ops = { + svcauth_null_wrap, + svcauth_null_wrap, +}; + /*ARGSUSED*/ enum auth_stat _svcauth_null(rqst, msg) diff --git a/lib/libc/rpc/svc_dg.c b/lib/libc/rpc/svc_dg.c index 1c602bc..51facd2 100644 --- a/lib/libc/rpc/svc_dg.c +++ b/lib/libc/rpc/svc_dg.c @@ -51,6 +51,7 @@ __FBSDID("$FreeBSD$"); #include <sys/socket.h> #include <rpc/rpc.h> #include <rpc/svc_dg.h> +#include <assert.h> #include <errno.h> #include <unistd.h> #include <stdio.h> @@ -125,10 +126,9 @@ svc_dg_create(fd, sendsize, recvsize) return (NULL); } - xprt = mem_alloc(sizeof (SVCXPRT)); + xprt = svc_xprt_alloc(); if (xprt == NULL) goto freedata; - memset(xprt, 0, sizeof (SVCXPRT)); su = mem_alloc(sizeof (*su)); if (su == NULL) @@ -160,7 +160,7 @@ freedata: if (xprt) { if (su) (void) mem_free(su, sizeof (*su)); - (void) mem_free(xprt, sizeof (SVCXPRT)); + svc_xprt_free(xprt); } return (NULL); } @@ -230,13 +230,28 @@ svc_dg_reply(xprt, msg) { struct svc_dg_data *su = su_data(xprt); XDR *xdrs = &(su->su_xdrs); - bool_t stat = FALSE; + bool_t stat = TRUE; size_t slen; + xdrproc_t xdr_proc; + caddr_t xdr_where; xdrs->x_op = XDR_ENCODE; XDR_SETPOS(xdrs, 0); msg->rm_xid = su->su_xid; - if (xdr_replymsg(xdrs, msg)) { + if (msg->rm_reply.rp_stat == MSG_ACCEPTED && + msg->rm_reply.rp_acpt.ar_stat == SUCCESS) { + xdr_proc = msg->acpted_rply.ar_results.proc; + xdr_where = msg->acpted_rply.ar_results.where; + msg->acpted_rply.ar_results.proc = (xdrproc_t) xdr_void; + msg->acpted_rply.ar_results.where = NULL; + + if (!xdr_replymsg(xdrs, msg) || + !SVCAUTH_WRAP(&SVC_AUTH(xprt), xdrs, xdr_proc, xdr_where)) + stat = FALSE; + } else { + stat = xdr_replymsg(xdrs, msg); + } + if (stat) { slen = XDR_GETPOS(xdrs); if (_sendto(xprt->xp_fd, rpc_buffer(xprt), slen, 0, (struct sockaddr *)xprt->xp_rtaddr.buf, @@ -255,7 +270,12 @@ svc_dg_getargs(xprt, xdr_args, args_ptr) xdrproc_t xdr_args; void *args_ptr; { - return (*xdr_args)(&(su_data(xprt)->su_xdrs), args_ptr); + struct svc_dg_data *su; + + assert(xprt != NULL); + su = su_data(xprt); + return (SVCAUTH_UNWRAP(&SVC_AUTH(xprt), + &su->su_xdrs, xdr_args, args_ptr)); } static bool_t @@ -288,7 +308,7 @@ svc_dg_destroy(xprt) (void) mem_free(xprt->xp_ltaddr.buf, xprt->xp_ltaddr.maxlen); if (xprt->xp_tp) (void) free(xprt->xp_tp); - (void) mem_free(xprt, sizeof (SVCXPRT)); + svc_xprt_free(xprt); } static bool_t diff --git a/lib/libc/rpc/svc_raw.c b/lib/libc/rpc/svc_raw.c index 32d1ff7..7492046 100644 --- a/lib/libc/rpc/svc_raw.c +++ b/lib/libc/rpc/svc_raw.c @@ -66,7 +66,7 @@ __FBSDID("$FreeBSD$"); */ static struct svc_raw_private { char *raw_buf; /* should be shared with the cl handle */ - SVCXPRT server; + SVCXPRT *server; XDR xdr_stream; char verf_body[MAX_AUTH_BYTES]; } *svc_raw_private; @@ -99,17 +99,17 @@ svc_raw_create() if (__rpc_rawcombuf == NULL) __rpc_rawcombuf = calloc(UDPMSGSIZE, sizeof (char)); srp->raw_buf = __rpc_rawcombuf; /* Share it with the client */ + srp->server = svc_xprt_alloc(); svc_raw_private = srp; } - srp->server.xp_fd = FD_SETSIZE; - srp->server.xp_port = 0; - srp->server.xp_p3 = NULL; - svc_raw_ops(&srp->server); - srp->server.xp_verf.oa_base = srp->verf_body; + srp->server->xp_fd = FD_SETSIZE; + srp->server->xp_port = 0; + svc_raw_ops(srp->server); + srp->server->xp_verf.oa_base = srp->verf_body; xdrmem_create(&srp->xdr_stream, srp->raw_buf, UDPMSGSIZE, XDR_DECODE); - xprt_register(&srp->server); + xprt_register(srp->server); mutex_unlock(&svcraw_lock); - return (&srp->server); + return (srp->server); } /*ARGSUSED*/ @@ -154,6 +154,9 @@ svc_raw_reply(xprt, msg) { struct svc_raw_private *srp; XDR *xdrs; + bool_t stat; + xdrproc_t xdr_proc; + caddr_t xdr_where; mutex_lock(&svcraw_lock); srp = svc_raw_private; @@ -166,7 +169,20 @@ svc_raw_reply(xprt, msg) xdrs = &srp->xdr_stream; xdrs->x_op = XDR_ENCODE; (void) XDR_SETPOS(xdrs, 0); - if (! xdr_replymsg(xdrs, msg)) { + if (msg->rm_reply.rp_stat == MSG_ACCEPTED && + msg->rm_reply.rp_acpt.ar_stat == SUCCESS) { + xdr_proc = msg->acpted_rply.ar_results.proc; + xdr_where = msg->acpted_rply.ar_results.where; + msg->acpted_rply.ar_results.proc = (xdrproc_t) xdr_void; + msg->acpted_rply.ar_results.where = NULL; + + if (!xdr_replymsg(xdrs, msg) || + !SVCAUTH_WRAP(&SVC_AUTH(xprt), xdrs, xdr_proc, xdr_where)) + stat = FALSE; + } else { + stat = xdr_replymsg(xdrs, msg); + } + if (!stat) { return (FALSE); } (void) XDR_GETPOS(xdrs); /* called just for overhead */ @@ -189,7 +205,9 @@ svc_raw_getargs(xprt, xdr_args, args_ptr) return (FALSE); } mutex_unlock(&svcraw_lock); - return (*xdr_args)(&srp->xdr_stream, args_ptr); + + return (SVCAUTH_UNWRAP(&SVC_AUTH(xprt), &srp->xdr_stream, + xdr_args, args_ptr)); } /*ARGSUSED*/ diff --git a/lib/libc/rpc/svc_vc.c b/lib/libc/rpc/svc_vc.c index 6370aad..3fd8b7e 100644 --- a/lib/libc/rpc/svc_vc.c +++ b/lib/libc/rpc/svc_vc.c @@ -146,15 +146,12 @@ svc_vc_create(fd, sendsize, recvsize) r->sendsize = __rpc_get_t_size(si.si_af, si.si_proto, (int)sendsize); r->recvsize = __rpc_get_t_size(si.si_af, si.si_proto, (int)recvsize); r->maxrec = __svc_maxrec; - xprt = mem_alloc(sizeof(SVCXPRT)); + xprt = svc_xprt_alloc(); if (xprt == NULL) { warnx("svc_vc_create: out of memory"); goto cleanup_svc_vc_create; } - xprt->xp_tp = NULL; xprt->xp_p1 = r; - xprt->xp_p2 = NULL; - xprt->xp_p3 = NULL; xprt->xp_verf = _null_auth; svc_vc_rendezvous_ops(xprt); xprt->xp_port = (u_short)-1; /* It is the rendezvouser */ @@ -259,16 +256,15 @@ makefd_xprt(fd, sendsize, recvsize) assert(fd != -1); - xprt = mem_alloc(sizeof(SVCXPRT)); + xprt = svc_xprt_alloc(); if (xprt == NULL) { warnx("svc_vc: makefd_xprt: out of memory"); goto done; } - memset(xprt, 0, sizeof *xprt); cd = mem_alloc(sizeof(struct cf_conn)); if (cd == NULL) { warnx("svc_tcp: makefd_xprt: out of memory"); - mem_free(xprt, sizeof(SVCXPRT)); + svc_xprt_free(xprt); xprt = NULL; goto done; } @@ -417,7 +413,7 @@ __svc_vc_dodestroy(xprt) free(xprt->xp_tp); if (xprt->xp_netid) free(xprt->xp_netid); - mem_free(xprt, sizeof(SVCXPRT)); + svc_xprt_free(xprt); } /*ARGSUSED*/ @@ -623,11 +619,12 @@ svc_vc_getargs(xprt, xdr_args, args_ptr) xdrproc_t xdr_args; void *args_ptr; { + struct cf_conn *cd; assert(xprt != NULL); - /* args_ptr may be NULL */ - return ((*xdr_args)(&(((struct cf_conn *)(xprt->xp_p1))->xdrs), - args_ptr)); + cd = (struct cf_conn *)(xprt->xp_p1); + return (SVCAUTH_UNWRAP(&SVC_AUTH(xprt), + &cd->xdrs, xdr_args, args_ptr)); } static bool_t @@ -655,6 +652,9 @@ svc_vc_reply(xprt, msg) struct cf_conn *cd; XDR *xdrs; bool_t rstat; + xdrproc_t xdr_proc; + caddr_t xdr_where; + u_int pos; assert(xprt != NULL); assert(msg != NULL); @@ -664,8 +664,27 @@ svc_vc_reply(xprt, msg) xdrs->x_op = XDR_ENCODE; msg->rm_xid = cd->x_id; - rstat = xdr_replymsg(xdrs, msg); - (void)xdrrec_endofrecord(xdrs, TRUE); + rstat = TRUE; + if (msg->rm_reply.rp_stat == MSG_ACCEPTED && + msg->rm_reply.rp_acpt.ar_stat == SUCCESS) { + xdr_proc = msg->acpted_rply.ar_results.proc; + xdr_where = msg->acpted_rply.ar_results.where; + msg->acpted_rply.ar_results.proc = (xdrproc_t) xdr_void; + msg->acpted_rply.ar_results.where = NULL; + + pos = XDR_GETPOS(xdrs); + if (!xdr_replymsg(xdrs, msg) || + !SVCAUTH_WRAP(&SVC_AUTH(xprt), xdrs, xdr_proc, xdr_where)) { + XDR_SETPOS(xdrs, pos); + rstat = FALSE; + } + } else { + rstat = xdr_replymsg(xdrs, msg); + } + + if (rstat) + (void)xdrrec_endofrecord(xdrs, TRUE); + return (rstat); } diff --git a/lib/libc/xdr/xdr_rec.c b/lib/libc/xdr/xdr_rec.c index 34238ed..dc4aa18 100644 --- a/lib/libc/xdr/xdr_rec.c +++ b/lib/libc/xdr/xdr_rec.c @@ -338,21 +338,22 @@ xdrrec_getpos(xdrs) off_t pos; pos = lseek((int)(u_long)rstrm->tcp_handle, (off_t)0, 1); - if (pos != -1) - switch (xdrs->x_op) { + if (pos == -1) + pos = 0; + switch (xdrs->x_op) { - case XDR_ENCODE: - pos += rstrm->out_finger - rstrm->out_base; - break; + case XDR_ENCODE: + pos += rstrm->out_finger - rstrm->out_base; + break; - case XDR_DECODE: - pos -= rstrm->in_boundry - rstrm->in_finger; - break; + case XDR_DECODE: + pos -= rstrm->in_boundry - rstrm->in_finger; + break; - default: - pos = (off_t) -1; - break; - } + default: + pos = (off_t) -1; + break; + } return ((u_int) pos); } |