From 6383fae17388f5cd7b4674995d13beed1e7fa087 Mon Sep 17 00:00:00 2001 From: "Matthew N. Dodd" Date: Mon, 20 Jun 2011 13:34:56 -0400 Subject: SVCAUTH_WRAP/SVCAUTH_UNWRAP Server code lacks support for authenticator wrapping/unwrapping, which is particularly useful when using GSS. Verified for both tcp & udp using a trivial RPC server against an MIT Krb5 client. Signed-off-by: Frank Filz Signed-off-by: Steve Dickson --- src/svc.c | 11 +++-------- src/svc_auth_unix.c | 5 +++++ src/svc_dg.c | 31 +++++++++++++++++++++++++++++-- src/svc_vc.c | 37 ++++++++++++++++++++++++++++++++++--- tirpc/rpc/svc_auth.h | 18 ++++++++++++------ 5 files changed, 83 insertions(+), 19 deletions(-) diff --git a/src/svc.c b/src/svc.c index b4a63d0..08cd6c9 100644 --- a/src/svc.c +++ b/src/svc.c @@ -77,9 +77,6 @@ static struct svc_callout extern rwlock_t svc_lock; extern rwlock_t svc_fd_lock; -#ifdef HAVE_LIBGSSAPI -extern struct svc_auth_ops svc_auth_gss_ops; -#endif static struct svc_callout *svc_find (rpcprog_t, rpcvers_t, struct svc_callout **, char *); @@ -717,11 +714,9 @@ svc_getreq_common (fd) SVC_DESTROY (xprt); break; } - else if ((xprt->xp_auth != NULL) -#ifdef HAVE_LIBGSSAPI - && (xprt->xp_auth->svc_ah_ops != &svc_auth_gss_ops) -#endif - ) { + else if ((xprt->xp_auth != NULL) && + (xprt->xp_auth->svc_ah_private == NULL)) + { xprt->xp_auth = NULL; } } diff --git a/src/svc_auth_unix.c b/src/svc_auth_unix.c index ce83859..9585069 100644 --- a/src/svc_auth_unix.c +++ b/src/svc_auth_unix.c @@ -43,6 +43,8 @@ #include +extern SVCAUTH svc_auth_none; + /* * Unix longhand authenticator */ @@ -67,6 +69,8 @@ _svcauth_unix(rqst, msg) assert(rqst != NULL); assert(msg != NULL); + rqst->rq_xprt->xp_auth = &svc_auth_none; + area = (struct area *) rqst->rq_clntcred; aup = &area->area_aup; aup->aup_machname = area->area_machname; @@ -142,5 +146,6 @@ _svcauth_short(rqst, msg) struct svc_req *rqst; struct rpc_msg *msg; { + rqst->rq_xprt->xp_auth = &svc_auth_none; return (AUTH_REJECTEDCRED); } diff --git a/src/svc_dg.c b/src/svc_dg.c index 66a56ee..5ef9df2 100644 --- a/src/svc_dg.c +++ b/src/svc_dg.c @@ -134,6 +134,7 @@ svc_dg_create(fd, sendsize, recvsize) su->su_cache = NULL; xprt->xp_fd = fd; xprt->xp_p2 = su; + xprt->xp_auth = NULL; xprt->xp_verf.oa_base = su->su_verfbody; svc_dg_ops(xprt); xprt->xp_rtaddr.maxlen = sizeof (struct sockaddr_storage); @@ -234,10 +235,27 @@ svc_dg_reply(xprt, msg) bool_t stat = FALSE; size_t slen; + xdrproc_t xdr_results; + caddr_t xdr_location; + bool_t has_args; + + if (msg->rm_reply.rp_stat == MSG_ACCEPTED && + msg->rm_reply.rp_acpt.ar_stat == SUCCESS) { + has_args = TRUE; + xdr_results = msg->acpted_rply.ar_results.proc; + xdr_location = msg->acpted_rply.ar_results.where; + + msg->acpted_rply.ar_results.proc = (xdrproc_t)xdr_void; + msg->acpted_rply.ar_results.where = NULL; + } else + has_args = FALSE; + xdrs->x_op = XDR_ENCODE; XDR_SETPOS(xdrs, 0); msg->rm_xid = su->su_xid; - if (xdr_replymsg(xdrs, msg)) { + if (xdr_replymsg(xdrs, msg) && + (!has_args || + (SVCAUTH_WRAP(xprt->xp_auth, xdrs, xdr_results, xdr_location)))) { struct msghdr *msg = &su->su_msghdr; struct iovec iov; @@ -264,7 +282,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); + if (! SVCAUTH_UNWRAP(xprt->xp_auth, &(su_data(xprt)->su_xdrs), + xdr_args, args_ptr)) { + (void)svc_freeargs(xprt, xdr_args, args_ptr); + return FALSE; + } + return TRUE; } static bool_t @@ -288,6 +311,10 @@ svc_dg_destroy(xprt) xprt_unregister(xprt); if (xprt->xp_fd != -1) (void)close(xprt->xp_fd); + if (xprt->xp_auth != NULL) { + SVCAUTH_DESTROY(xprt->xp_auth); + xprt->xp_auth = NULL; + } XDR_DESTROY(&(su->su_xdrs)); (void) mem_free(rpc_buffer(xprt), su->su_iosz); (void) mem_free(su, sizeof (*su)); diff --git a/src/svc_vc.c b/src/svc_vc.c index 87406f1..74632e2 100644 --- a/src/svc_vc.c +++ b/src/svc_vc.c @@ -172,6 +172,7 @@ svc_vc_create(fd, sendsize, recvsize) xprt->xp_p1 = r; xprt->xp_p2 = NULL; xprt->xp_p3 = NULL; + xprt->xp_auth = NULL; xprt->xp_verf = _null_auth; svc_vc_rendezvous_ops(xprt); xprt->xp_port = (u_short)-1; /* It is the rendezvouser */ @@ -283,6 +284,7 @@ makefd_xprt(fd, sendsize, recvsize) xdrrec_create(&(cd->xdrs), sendsize, recvsize, xprt, read_vc, write_vc); xprt->xp_p1 = cd; + xprt->xp_auth = NULL; xprt->xp_verf.oa_base = cd->verf_body; svc_vc_ops(xprt); /* truely deals with calls */ xprt->xp_port = 0; /* this is a connection, not a rendezvouser */ @@ -412,6 +414,10 @@ __svc_vc_dodestroy(xprt) XDR_DESTROY(&(cd->xdrs)); mem_free(cd, sizeof(struct cf_conn)); } + if (xprt->xp_auth != NULL) { + SVCAUTH_DESTROY(xprt->xp_auth); + xprt->xp_auth = NULL; + } if (xprt->xp_rtaddr.buf) mem_free(xprt->xp_rtaddr.buf, xprt->xp_rtaddr.maxlen); if (xprt->xp_ltaddr.buf) @@ -632,8 +638,13 @@ svc_vc_getargs(xprt, xdr_args, args_ptr) assert(xprt != NULL); /* args_ptr may be NULL */ - return ((*xdr_args)(&(((struct cf_conn *)(xprt->xp_p1))->xdrs), - args_ptr)); + + if (! SVCAUTH_UNWRAP(xprt->xp_auth, + &(((struct cf_conn *)(xprt->xp_p1))->xdrs), + xdr_args, args_ptr)) { + return FALSE; + } + return TRUE; } static bool_t @@ -662,15 +673,35 @@ svc_vc_reply(xprt, msg) XDR *xdrs; bool_t rstat; + xdrproc_t xdr_results; + caddr_t xdr_location; + bool_t has_args; + assert(xprt != NULL); assert(msg != NULL); cd = (struct cf_conn *)(xprt->xp_p1); xdrs = &(cd->xdrs); + if (msg->rm_reply.rp_stat == MSG_ACCEPTED && + msg->rm_reply.rp_acpt.ar_stat == SUCCESS) { + has_args = TRUE; + xdr_results = msg->acpted_rply.ar_results.proc; + xdr_location = msg->acpted_rply.ar_results.where; + + msg->acpted_rply.ar_results.proc = (xdrproc_t)xdr_void; + msg->acpted_rply.ar_results.where = NULL; + } else + has_args = FALSE; + xdrs->x_op = XDR_ENCODE; msg->rm_xid = cd->x_id; - rstat = xdr_replymsg(xdrs, msg); + rstat = FALSE; + if (xdr_replymsg(xdrs, msg) && + (!has_args || + (SVCAUTH_WRAP(xprt->xp_auth, xdrs, xdr_results, xdr_location)))) { + rstat = TRUE; + } (void)xdrrec_endofrecord(xdrs, TRUE); return (rstat); } diff --git a/tirpc/rpc/svc_auth.h b/tirpc/rpc/svc_auth.h index 659e90c..14269d1 100644 --- a/tirpc/rpc/svc_auth.h +++ b/tirpc/rpc/svc_auth.h @@ -44,17 +44,23 @@ /* * Interface to server-side authentication flavors. */ -typedef struct { +typedef struct SVCAUTH { struct svc_auth_ops { - int (*svc_ah_wrap)(void); - int (*svc_ah_unwrap)(void); - int (*svc_ah_destroy)(void); + int (*svc_ah_wrap)(struct SVCAUTH *, XDR *, xdrproc_t, + caddr_t); + int (*svc_ah_unwrap)(struct SVCAUTH *, XDR *, xdrproc_t, + caddr_t); + int (*svc_ah_destroy)(struct SVCAUTH *); } *svc_ah_ops; caddr_t svc_ah_private; } SVCAUTH; -#define SVCAUTH_DESTROY(cred) ((*(cred)->svc_ah_ops->svc_ah_destroy)()) -#define svcauth_destroy(cred) ((*(cred)->svc_ah_ops->svc_ah_destroy)()) +#define SVCAUTH_WRAP(auth, xdrs, xfunc, xwhere) \ + ((*((auth)->svc_ah_ops->svc_ah_wrap))(auth, xdrs, xfunc, xwhere)) +#define SVCAUTH_UNWRAP(auth, xdrs, xfunc, xwhere) \ + ((*((auth)->svc_ah_ops->svc_ah_unwrap))(auth, xdrs, xfunc, xwhere)) +#define SVCAUTH_DESTROY(auth) \ + ((*((auth)->svc_ah_ops->svc_ah_destroy))(auth)) /* * Server side authenticator -- cgit v1.2.1