diff options
author | Tom Yu <tlyu@mit.edu> | 2004-06-16 01:26:55 +0000 |
---|---|---|
committer | Tom Yu <tlyu@mit.edu> | 2004-06-16 01:26:55 +0000 |
commit | 9720ec5793d204cf6d59ec021ff33e80c9b0b7cf (patch) | |
tree | 5ce587f11d5bca6958bb03270d0e2bb09e65d114 | |
parent | 330c08794f9d305778cc40d8407b9170eaa96db6 (diff) | |
download | krb5-9720ec5793d204cf6d59ec021ff33e80c9b0b7cf.zip krb5-9720ec5793d204cf6d59ec021ff33e80c9b0b7cf.tar.gz krb5-9720ec5793d204cf6d59ec021ff33e80c9b0b7cf.tar.bz2 |
fix lots of memory leaks and memory corruption
ticket: 2578
status: open
git-svn-id: svn://anonsvn.mit.edu/krb5/branches/tlyu-umich-rpc@16456 dc483132-0cff-0310-8789-dd5450dbe970
-rw-r--r-- | src/lib/rpc/ChangeLog | 53 | ||||
-rw-r--r-- | src/lib/rpc/auth_gss.c | 45 | ||||
-rw-r--r-- | src/lib/rpc/auth_gssapi.h | 7 | ||||
-rw-r--r-- | src/lib/rpc/authgss_prot.c | 29 | ||||
-rw-r--r-- | src/lib/rpc/svc.c | 3 | ||||
-rw-r--r-- | src/lib/rpc/svc.h | 3 | ||||
-rw-r--r-- | src/lib/rpc/svc_auth_gss.c | 178 | ||||
-rw-r--r-- | src/lib/rpc/svc_auth_gssapi.c | 17 | ||||
-rw-r--r-- | src/lib/rpc/svc_tcp.c | 6 | ||||
-rw-r--r-- | src/lib/rpc/svc_udp.c | 9 | ||||
-rw-r--r-- | src/lib/rpc/xdr_rec.c | 34 |
11 files changed, 256 insertions, 128 deletions
diff --git a/src/lib/rpc/ChangeLog b/src/lib/rpc/ChangeLog index c5f91c8..753edfb 100644 --- a/src/lib/rpc/ChangeLog +++ b/src/lib/rpc/ChangeLog @@ -1,3 +1,56 @@ +2004-06-15 Tom Yu <tlyu@mit.edu> + + * auth_gss.c (print_rpc_gss_sec): Use gss_oid_to_str(). + (rpc_gss_data): Add field "established" to indicate whether + context establishment is in progress; this prevents recursive + failures when auth_refresh() calls clnt_call(). If clnt_call() + called from auth_refresh() gets an error condition, the + clnt_call() logic will attempt a refresh, which can cause the + cl_auth to get destroyed multiple times, corrupting memory. + (authgss_validate, authgss_refresh): Use gd->established. + (authgss_refresh): Release gd->gc_wire_verf. + (authgss_destroy_context): Log clnt_call() failures. + + * auth_gssapi.h: Add prototypes for svcauth_gss_set_log_*_func. + + * authgss_prot.c (log_status): Correctly reset msg_ctx between + different types of calls to gss_display_status(). + + * svc.c: Don't reset xp_auth prior to authenticating message. + + * svc.h (svc_req): Remove rq_svcname; application can get it from + rq_svccred anyway. + + * svc_auth_gss.c: Include auth_gssapi.h to get typedefs for + logging callback functions. Enable logging callbacks. Replace + SVCAUTH_PRIVATE_LVALUE() kludge. Fix up namespace somewhat to not + use reserved names. + (svcauth_gss_accept_sec_context): Free rpc_gss_init_args to avoid + leak. Release gr->gr_token on error conditions. + (svcauth_gss_nextverf, svcauth_gss_accept_sec_context): + (gssrpc__svcauth_gss): Use gd->checksum. + (gssrpc__svcauth_gss): Use macro ret_freegc() to ensure freeing of + gc. On destroy, set *no_dispatch=TRUE and explicitly send reply + to avoid application sending a NULLPROC reply with an invalid + verifier. + + * svc_auth_gssapi.c (gssrpc__svcauth_gssapi): Set xp_auth to NULL + upon destroy. + (svc_auth_gssapi_destroy): New function so SVCAUTH_DESTROY() will + work. + + * svc_tcp.c (svctcp_create, makefd_xprt): Initialize xp_auth to + NULL. + (svctcp_destroy): Call SVCAUTH_DESTROY() if appropriate. + + * svc_udp.c (svcudp_bufcreate, svcudp_destroy): Initialize xp_auth + to NULL. + (svcudp_destroy): Only close xp_sock if it's not -1. Call + SVCAUTH_DESTROY() if appropriate. + + * xdr_rec.c (xdrrec_getpos): Add CITI's fix to return position for + non-flushed buffers. + 2004-05-27 Tom Yu <tlyu@mit.edu> * auth_any.c, svc_auth_any.c: Removed. diff --git a/src/lib/rpc/auth_gss.c b/src/lib/rpc/auth_gss.c index 5da8556..846cf36 100644 --- a/src/lib/rpc/auth_gss.c +++ b/src/lib/rpc/auth_gss.c @@ -96,8 +96,9 @@ static struct auth_ops authgss_ops = { void print_rpc_gss_sec(struct rpc_gss_sec *ptr) { -int i; -char *p; +#if HAVE_HEIMDAL + int i; + char *p; log_debug("rpc_gss_sec:\n"); if(ptr->mech == NULL) @@ -113,6 +114,23 @@ char *p; } log_debug(" qop: %d\n",ptr->qop); log_debug(" service: %d\n",ptr->svc); +#else + OM_uint32 min_stat; + gss_buffer_desc msg; + + if (ptr->mech == NULL) + log_debug("rpc_gss_sec: mech NULL, qop %d, svc %d", + ptr->qop, ptr->svc); + else { + gss_oid_to_str(&min_stat, ptr->mech, &msg); + + log_debug("rpc_gss_sec: mech %.*s, qop %d, svc %d", + msg.length, (char *)msg.value, + ptr->qop, ptr->svc); + + gss_release_buffer(&min_stat, &msg); + } +#endif } #endif /*DEBUG*/ @@ -140,6 +158,7 @@ static gss_OID_desc spkm3oid = struct rpc_gss_data { bool_t established; /* context established */ + bool_t inprogress; gss_buffer_desc gc_wire_verf; /* save GSS_S_COMPLETE NULL RPC verfier * to process at end of context negotiation*/ CLIENT *clnt; /* client handle */ @@ -364,7 +383,7 @@ authgss_refresh(AUTH *auth, struct rpc_msg *msg) gd = AUTH_PRIVATE(auth); - if (gd->established) + if (gd->established || gd->inprogress) return (TRUE); /* GSS context establishment loop. */ @@ -384,6 +403,7 @@ authgss_refresh(AUTH *auth, struct rpc_msg *msg) #endif /*SPKM*/ for (;;) { + gd->inprogress = TRUE; maj_stat = gss_init_sec_context(&min_stat, GSS_C_NO_CREDENTIAL, &gd->ctx, @@ -418,7 +438,9 @@ authgss_refresh(AUTH *auth, struct rpc_msg *msg) (caddr_t)&gr, AUTH_TIMEOUT); gss_release_buffer(&min_stat, &send_token); - + + log_debug("authgss_refresh: call_stat=%d", call_stat); + log_debug("%s", clnt_sperror(gd->clnt, "authgss_refresh")); if (call_stat != RPC_SUCCESS || (gr.gr_major != GSS_S_COMPLETE && gr.gr_major != GSS_S_CONTINUE_NEEDED)) @@ -458,13 +480,16 @@ authgss_refresh(AUTH *auth, struct rpc_msg *msg) if (maj_stat != GSS_S_COMPLETE || qop_state != gd->sec.qop) { log_status("gss_verify_mic", maj_stat, min_stat); + gss_release_buffer(&min_stat, &gd->gc_wire_verf); if (maj_stat == GSS_S_CONTEXT_EXPIRED) { gd->established = FALSE; authgss_destroy_context(auth); } return (FALSE); } + gss_release_buffer(&min_stat, &gd->gc_wire_verf); gd->established = TRUE; + gd->inprogress = FALSE; gd->gc.gc_proc = RPCSEC_GSS_DATA; gd->gc.gc_seq = 0; gd->win = gr.gr_win; @@ -510,6 +535,7 @@ authgss_destroy_context(AUTH *auth) { struct rpc_gss_data *gd; OM_uint32 min_stat; + enum clnt_stat callstat; log_debug("in authgss_destroy_context()"); @@ -518,8 +544,13 @@ authgss_destroy_context(AUTH *auth) if (gd->gc.gc_ctx.length != 0) { if (gd->established) { gd->gc.gc_proc = RPCSEC_GSS_DESTROY; - clnt_call(gd->clnt, NULLPROC, xdr_void, NULL, - xdr_void, NULL, AUTH_TIMEOUT); + callstat = clnt_call(gd->clnt, NULLPROC, + xdr_void, NULL, + xdr_void, NULL, + AUTH_TIMEOUT); + log_debug("%s", + clnt_sperror(gd->clnt, + "authgss_destroy_context")); } gss_release_buffer(&min_stat, &gd->gc.gc_ctx); /* XXX ANDROS check size of context - should be 8 */ @@ -530,6 +561,8 @@ authgss_destroy_context(AUTH *auth) gd->ctx = GSS_C_NO_CONTEXT; } gd->established = FALSE; + + log_debug("finished authgss_destroy_context()"); } static void diff --git a/src/lib/rpc/auth_gssapi.h b/src/lib/rpc/auth_gssapi.h index 5384b06..73a2f0b 100644 --- a/src/lib/rpc/auth_gssapi.h +++ b/src/lib/rpc/auth_gssapi.h @@ -128,6 +128,13 @@ void svcauth_gssapi_set_log_miscerr_func (auth_gssapi_log_miscerr_func func, caddr_t data); +void svcauth_gss_set_log_badauth_func(auth_gssapi_log_badauth_func, + caddr_t); +void svcauth_gss_set_log_badverf_func(auth_gssapi_log_badverf_func, + caddr_t); +void svcauth_gss_set_log_miscerr_func(auth_gssapi_log_miscerr_func, + caddr_t data); + #define GSS_COPY_BUFFER(dest, src) { \ (dest).length = (src).length; \ (dest).value = (src).value; } diff --git a/src/lib/rpc/authgss_prot.c b/src/lib/rpc/authgss_prot.c index fc5fa03..6d91b8b 100644 --- a/src/lib/rpc/authgss_prot.c +++ b/src/lib/rpc/authgss_prot.c @@ -39,10 +39,6 @@ #include <stdlib.h> #include <stdarg.h> #include <string.h> -#include <gssrpc/types.h> -#include <gssrpc/xdr.h> -#include <gssrpc/auth.h> -#include <gssrpc/auth_gss.h> #include <gssrpc/rpc.h> #ifdef HAVE_HEIMDAL #include <gssapi.h> @@ -289,21 +285,22 @@ log_debug(const char *fmt, ...) void log_status(char *m, OM_uint32 maj_stat, OM_uint32 min_stat) { - OM_uint32 min; - gss_buffer_desc msg; - int msg_ctx = 0; + OM_uint32 min, msg_ctx; + gss_buffer_desc msgg, msgm; - fprintf(stderr, "rpcsec_gss: %s: ", m); - + msg_ctx = 0; gss_display_status(&min, maj_stat, GSS_C_GSS_CODE, GSS_C_NULL_OID, - &msg_ctx, &msg); - fprintf(stderr, "%s - ", (char *)msg.value); - gss_release_buffer(&min, &msg); - + &msg_ctx, &msgg); + msg_ctx = 0; gss_display_status(&min, min_stat, GSS_C_MECH_CODE, GSS_C_NULL_OID, - &msg_ctx, &msg); - fprintf(stderr, "%s\n", (char *)msg.value); - gss_release_buffer(&min, &msg); + &msg_ctx, &msgm); + + log_debug("%s: %.*s - %.*s\n", m, + msgg.length, (char *)msgg.value, + msgm.length, (char *)msgm.value); + + gss_release_buffer(&min, &msgg); + gss_release_buffer(&min, &msgm); } void diff --git a/src/lib/rpc/svc.c b/src/lib/rpc/svc.c index 39aa73e..e35c80c 100644 --- a/src/lib/rpc/svc.c +++ b/src/lib/rpc/svc.c @@ -451,9 +451,6 @@ svc_getreqset(readfds) r.rq_proc = msg.rm_call.cb_proc; r.rq_cred = msg.rm_call.cb_cred; - /* in case _authenticate has been replaced - with an old-style version */ - r.rq_xprt->xp_auth = &svc_auth_none; no_dispatch = FALSE; /* first authenticate the message */ diff --git a/src/lib/rpc/svc.h b/src/lib/rpc/svc.h index ce39cef..360e5cb 100644 --- a/src/lib/rpc/svc.h +++ b/src/lib/rpc/svc.h @@ -164,9 +164,8 @@ struct svc_req { rpcproc_t rq_proc; /* the desired procedure */ struct opaque_auth rq_cred; /* raw creds from the wire */ void * rq_clntcred; /* read only cooked client cred */ - void * rq_svccred; /* read only cooked svc cred */ + void * rq_svccred; /* read only svc cred/context */ void * rq_clntname; /* read only client name */ - void * rq_svcname; /* read only cooked service cred */ SVCXPRT *rq_xprt; /* associated transport */ /* The request's auth flavor *should* be here, but the svc_req */ /* isn't passed around everywhere it is necessary. The */ diff --git a/src/lib/rpc/svc_auth_gss.c b/src/lib/rpc/svc_auth_gss.c index d8a5db2..8751251 100644 --- a/src/lib/rpc/svc_auth_gss.c +++ b/src/lib/rpc/svc_auth_gss.c @@ -39,6 +39,7 @@ #include <stdlib.h> #include <string.h> #include <gssrpc/rpc.h> +#include <gssrpc/auth_gssapi.h> #ifdef HAVE_HEIMDAL #include <gssapi.h> #define gss_nt_service_name GSS_C_NT_HOSTBASED_SERVICE @@ -77,7 +78,6 @@ typedef struct gss_union_ctx_id_t { } gss_union_ctx_id_desc, *gss_union_ctx_id_t; -#ifdef MIT_RPC_ADDITIONS static auth_gssapi_log_badauth_func log_badauth = NULL; static caddr_t log_badauth_data = NULL; static auth_gssapi_log_badverf_func log_badverf = NULL; @@ -87,7 +87,6 @@ static caddr_t log_miscerr_data = NULL; #define LOG_MISCERR(arg) if (log_miscerr) \ (*log_miscerr)(rqst, msg, arg, log_miscerr_data) -#endif /* MIT_RPC_ADDITIONS */ static bool_t svcauth_gss_destroy(SVCAUTH *); static bool_t svcauth_gss_wrap(SVCAUTH *, XDR *, xdrproc_t, caddr_t); @@ -111,17 +110,15 @@ struct svc_rpc_gss_data { u_int seqlast; /* last sequence number */ uint32_t seqmask; /* bitmask of seqnums */ gss_name_t client_name; /* unparsed name string */ + gss_buffer_desc checksum; /* so we can free it */ }; #define SVCAUTH_PRIVATE(auth) \ - ((struct svc_rpc_gss_data *)(auth)->svc_ah_private) -/* AIX compiler doesn't like having the cast in an lvalue */ -#define SVCAUTH_PRIVATE_LVALUE(auth) \ - ((auth)->svc_ah_private) + (*(struct svc_rpc_gss_data **)&(auth)->svc_ah_private) /* Global server credentials. */ -gss_cred_id_t _svcauth_gss_creds; -static gss_name_t _svcauth_gss_name = NULL; +gss_cred_id_t svcauth_gss_creds; +static gss_name_t svcauth_gss_name = NULL; bool_t svcauth_gss_set_svc_name(gss_name_t name) @@ -130,16 +127,19 @@ svcauth_gss_set_svc_name(gss_name_t name) log_debug("in svcauth_gss_set_svc_name()"); - if (_svcauth_gss_name != NULL) { - maj_stat = gss_release_name(&min_stat, &_svcauth_gss_name); + if (svcauth_gss_name != NULL) { + maj_stat = gss_release_name(&min_stat, &svcauth_gss_name); if (maj_stat != GSS_S_COMPLETE) { log_status("gss_release_name", maj_stat, min_stat); return (FALSE); } - _svcauth_gss_name = NULL; + svcauth_gss_name = NULL; } - maj_stat = gss_duplicate_name(&min_stat, name, &_svcauth_gss_name); + if (svcauth_gss_name == GSS_C_NO_NAME) + return (TRUE); + + maj_stat = gss_duplicate_name(&min_stat, name, &svcauth_gss_name); if (maj_stat != GSS_S_COMPLETE) { log_status("gss_duplicate_name", maj_stat, min_stat); @@ -182,9 +182,9 @@ svcauth_gss_acquire_cred(void) log_debug("in svcauth_gss_acquire_cred()"); - maj_stat = gss_acquire_cred(&min_stat, _svcauth_gss_name, 0, + maj_stat = gss_acquire_cred(&min_stat, svcauth_gss_name, 0, GSS_C_NULL_OID_SET, GSS_C_ACCEPT, - &_svcauth_gss_creds, NULL, NULL); + &svcauth_gss_creds, NULL, NULL); if (maj_stat != GSS_S_COMPLETE) { log_status("gss_acquire_cred", maj_stat, min_stat); @@ -200,14 +200,14 @@ svcauth_gss_release_cred(void) log_debug("in svcauth_gss_release_cred()"); - maj_stat = gss_release_cred(&min_stat, &_svcauth_gss_creds); + maj_stat = gss_release_cred(&min_stat, &svcauth_gss_creds); if (maj_stat != GSS_S_COMPLETE) { log_status("gss_release_cred", maj_stat, min_stat); return (FALSE); } - _svcauth_gss_creds = NULL; + svcauth_gss_creds = NULL; return (TRUE); } @@ -218,7 +218,7 @@ svcauth_gss_accept_sec_context(struct svc_req *rqst, { struct svc_rpc_gss_data *gd; struct rpc_gss_cred *gc; - gss_buffer_desc recv_tok, seqbuf, checksum; + gss_buffer_desc recv_tok, seqbuf; gss_OID mech; OM_uint32 maj_stat = 0, min_stat = 0, ret_flags, seq; @@ -237,7 +237,7 @@ svcauth_gss_accept_sec_context(struct svc_req *rqst, gr->gr_major = gss_accept_sec_context(&gr->gr_minor, &gd->ctx, - _svcauth_gss_creds, + svcauth_gss_creds, &recv_tok, GSS_C_NO_CHANNEL_BINDINGS, &gd->client_name, @@ -246,20 +246,20 @@ svcauth_gss_accept_sec_context(struct svc_req *rqst, &ret_flags, NULL, NULL); - + + svc_freeargs(rqst->rq_xprt, xdr_rpc_gss_init_args, (caddr_t)&recv_tok); + + log_status("accept_sec_context", gr->gr_major, gr->gr_minor); if (gr->gr_major != GSS_S_COMPLETE && gr->gr_major != GSS_S_CONTINUE_NEEDED) { - log_status("accept_sec_context", gr->gr_major, gr->gr_minor); -#ifdef MIT_RPC_ADDITIONS - if (log_badauth != NULL) + if (log_badauth != NULL) { (*log_badauth)(gr->gr_major, gr->gr_minor, &rqst->rq_xprt->xp_raddr, log_badauth_data); -#endif + } gd->ctx = GSS_C_NO_CONTEXT; - gss_release_buffer(&min_stat, &gr->gr_token); - return (FALSE); + goto errout; } /* * ANDROS: krb5 mechglue returns ctx of size 8 - two pointers, @@ -267,7 +267,7 @@ svcauth_gss_accept_sec_context(struct svc_req *rqst, */ if ((gr->gr_ctx.value = mem_alloc(sizeof(gss_union_ctx_id_desc))) == NULL) { fprintf(stderr, "svcauth_gss_accept_context: out of memory\n"); - return (FALSE); + goto errout; } memcpy(gr->gr_ctx.value, gd->ctx, sizeof(gss_union_ctx_id_desc)); gr->gr_ctx.length = sizeof(gss_union_ctx_id_desc); @@ -294,7 +294,7 @@ svcauth_gss_accept_sec_context(struct svc_req *rqst, #endif if (maj_stat != GSS_S_COMPLETE) { log_status("display_name", maj_stat, min_stat); - return (FALSE); + goto errout; } #ifdef DEBUG #ifdef HAVE_HEIMDAL @@ -322,17 +322,23 @@ svcauth_gss_accept_sec_context(struct svc_req *rqst, seqbuf.value = &seq; seqbuf.length = sizeof(seq); + gss_release_buffer(&min_stat, &gd->checksum); maj_stat = gss_sign(&min_stat, gd->ctx, GSS_C_QOP_DEFAULT, - &seqbuf, &checksum); + &seqbuf, &gd->checksum); - if (maj_stat != GSS_S_COMPLETE) - return (FALSE); + if (maj_stat != GSS_S_COMPLETE) { + goto errout; + } + rqst->rq_xprt->xp_verf.oa_flavor = RPCSEC_GSS; - rqst->rq_xprt->xp_verf.oa_base = checksum.value; - rqst->rq_xprt->xp_verf.oa_length = checksum.length; + rqst->rq_xprt->xp_verf.oa_base = gd->checksum.value; + rqst->rq_xprt->xp_verf.oa_length = gd->checksum.length; } return (TRUE); +errout: + gss_release_buffer(&min_stat, &gr->gr_token); + return (FALSE); } static bool_t @@ -374,12 +380,10 @@ svcauth_gss_validate(struct svc_req *rqst, struct svc_rpc_gss_data *gd, struct r if (maj_stat != GSS_S_COMPLETE) { log_status("gss_verify_mic", maj_stat, min_stat); -#ifdef MIT_RPC_ADDITIONS if (log_badverf != NULL) (*log_badverf)(gd->client_name, - _svcauth_gss_name, + svcauth_gss_name, rqst, msg, log_badverf_data); -#endif return (FALSE); } return (TRUE); @@ -389,7 +393,7 @@ static bool_t svcauth_gss_nextverf(struct svc_req *rqst, u_int num) { struct svc_rpc_gss_data *gd; - gss_buffer_desc signbuf, checksum; + gss_buffer_desc signbuf; OM_uint32 maj_stat, min_stat; log_debug("in svcauth_gss_nextverf()"); @@ -398,20 +402,22 @@ svcauth_gss_nextverf(struct svc_req *rqst, u_int num) return (FALSE); gd = SVCAUTH_PRIVATE(rqst->rq_xprt->xp_auth); - + + gss_release_buffer(&min_stat, &gd->checksum); + signbuf.value = # signbuf.length = sizeof(num); maj_stat = gss_get_mic(&min_stat, gd->ctx, gd->sec.qop, - &signbuf, &checksum); + &signbuf, &gd->checksum); if (maj_stat != GSS_S_COMPLETE) { log_status("gss_get_mic", maj_stat, min_stat); return (FALSE); } rqst->rq_xprt->xp_verf.oa_flavor = RPCSEC_GSS; - rqst->rq_xprt->xp_verf.oa_base = (caddr_t)checksum.value; - rqst->rq_xprt->xp_verf.oa_length = (u_int)checksum.length; + rqst->rq_xprt->xp_verf.oa_base = (caddr_t)gd->checksum.value; + rqst->rq_xprt->xp_verf.oa_length = (u_int)gd->checksum.length; return (TRUE); } @@ -420,12 +426,14 @@ enum auth_stat gssrpc__svcauth_gss(struct svc_req *rqst, struct rpc_msg *msg, bool_t *no_dispatch) { + enum auth_stat retstat; XDR xdrs; SVCAUTH *auth; struct svc_rpc_gss_data *gd; struct rpc_gss_cred *gc; struct rpc_gss_init_res gr; int call_stat, offset; + OM_uint32 min_stat; log_debug("in svcauth_gss()"); @@ -444,11 +452,13 @@ gssrpc__svcauth_gss(struct svc_req *rqst, struct rpc_msg *msg, return (AUTH_FAILED); } auth->svc_ah_ops = &svc_auth_gss_ops; - SVCAUTH_PRIVATE_LVALUE(auth) = (caddr_t) gd; + SVCAUTH_PRIVATE(auth) = gd; rqst->rq_xprt->xp_auth = auth; } else gd = SVCAUTH_PRIVATE(rqst->rq_xprt->xp_auth); - + + log_debug("xp_auth=%p, gd=%p", rqst->rq_xprt->xp_auth, gd); + /* Deserialize client credentials. */ if (rqst->rq_cred.oa_length <= 0) return (AUTH_BADCRED); @@ -465,20 +475,24 @@ gssrpc__svcauth_gss(struct svc_req *rqst, struct rpc_msg *msg, } XDR_DESTROY(&xdrs); + retstat = AUTH_FAILED; + +#define ret_freegc(code) do { retstat = code; goto freegc; } while (0) + /* Check version. */ if (gc->gc_v != RPCSEC_GSS_VERSION) - return (AUTH_BADCRED); + ret_freegc (AUTH_BADCRED); /* Check RPCSEC_GSS service. */ if (gc->gc_svc != RPCSEC_GSS_SVC_NONE && gc->gc_svc != RPCSEC_GSS_SVC_INTEGRITY && gc->gc_svc != RPCSEC_GSS_SVC_PRIVACY) - return (AUTH_BADCRED); + ret_freegc (AUTH_BADCRED); /* Check sequence number. */ if (gd->established) { if (gc->gc_seq > MAXSEQ) - return (RPCSEC_GSS_CTXPROBLEM); + ret_freegc (RPCSEC_GSS_CTXPROBLEM); if ((offset = gd->seqlast - gc->gc_seq) < 0) { gd->seqlast = gc->gc_seq; @@ -488,7 +502,7 @@ gssrpc__svcauth_gss(struct svc_req *rqst, struct rpc_msg *msg, } else if (offset >= gd->win || (gd->seqmask & (1 << offset))) { *no_dispatch = 1; - return (RPCSEC_GSS_CTXPROBLEM); + ret_freegc (RPCSEC_GSS_CTXPROBLEM); } gd->seq = gc->gc_seq; gd->seqmask |= (1 << offset); @@ -496,7 +510,7 @@ gssrpc__svcauth_gss(struct svc_req *rqst, struct rpc_msg *msg, if (gd->established) { rqst->rq_clntname = (char *)gd->client_name; - rqst->rq_svcname = (char *)gd->ctx; + rqst->rq_svccred = (char *)gd->ctx; } /* Handle RPCSEC_GSS control procedure. */ @@ -505,29 +519,30 @@ gssrpc__svcauth_gss(struct svc_req *rqst, struct rpc_msg *msg, case RPCSEC_GSS_INIT: case RPCSEC_GSS_CONTINUE_INIT: if (rqst->rq_proc != NULLPROC) - return (AUTH_FAILED); /* XXX ? */ - - if (_svcauth_gss_name == NULL) { - if (!svcauth_gss_import_name("nfs")) - return (AUTH_FAILED); - } + ret_freegc (AUTH_FAILED); /* XXX ? */ if (!svcauth_gss_acquire_cred()) - return (AUTH_FAILED); + ret_freegc (AUTH_FAILED); if (!svcauth_gss_accept_sec_context(rqst, &gr)) - return (AUTH_REJECTEDCRED); + ret_freegc (AUTH_REJECTEDCRED); - if (!svcauth_gss_nextverf(rqst, htonl(gr.gr_win))) - return (AUTH_FAILED); - + if (!svcauth_gss_nextverf(rqst, htonl(gr.gr_win))) { + gss_release_buffer(&min_stat, &gr.gr_token); + mem_free(gr.gr_ctx.value, + sizeof(gss_union_ctx_id_desc)); + ret_freegc (AUTH_FAILED); + } *no_dispatch = TRUE; call_stat = svc_sendreply(rqst->rq_xprt, xdr_rpc_gss_init_res, (caddr_t)&gr); + gss_release_buffer(&min_stat, &gr.gr_token); + gss_release_buffer(&min_stat, &gd->checksum); + mem_free(gr.gr_ctx.value, sizeof(gss_union_ctx_id_desc)); if (!call_stat) - return (AUTH_FAILED); + ret_freegc (AUTH_FAILED); if (gr.gr_major == GSS_S_COMPLETE) gd->established = TRUE; @@ -536,24 +551,31 @@ gssrpc__svcauth_gss(struct svc_req *rqst, struct rpc_msg *msg, case RPCSEC_GSS_DATA: if (!svcauth_gss_validate(rqst, gd, msg)) - return (RPCSEC_GSS_CREDPROBLEM); + ret_freegc (RPCSEC_GSS_CREDPROBLEM); if (!svcauth_gss_nextverf(rqst, htonl(gc->gc_seq))) - return (AUTH_FAILED); + ret_freegc (AUTH_FAILED); break; case RPCSEC_GSS_DESTROY: if (rqst->rq_proc != NULLPROC) - return (AUTH_FAILED); /* XXX ? */ - + ret_freegc (AUTH_FAILED); /* XXX ? */ + if (!svcauth_gss_validate(rqst, gd, msg)) - return (RPCSEC_GSS_CREDPROBLEM); + ret_freegc (RPCSEC_GSS_CREDPROBLEM); if (!svcauth_gss_nextverf(rqst, htonl(gc->gc_seq))) - return (AUTH_FAILED); + ret_freegc (AUTH_FAILED); + + *no_dispatch = TRUE; + + call_stat = svc_sendreply(rqst->rq_xprt, + xdr_void, (caddr_t)NULL); + + log_debug("sendreply in destroy: %d", call_stat); if (!svcauth_gss_release_cred()) - return (AUTH_FAILED); + ret_freegc (AUTH_FAILED); SVCAUTH_DESTROY(rqst->rq_xprt->xp_auth); rqst->rq_xprt->xp_auth = &svc_auth_none; @@ -561,10 +583,13 @@ gssrpc__svcauth_gss(struct svc_req *rqst, struct rpc_msg *msg, break; default: - return (AUTH_REJECTEDCRED); + ret_freegc (AUTH_REJECTEDCRED); break; } - return (AUTH_OK); + retstat = AUTH_OK; +freegc: + xdr_free(xdr_rpc_gss_cred, gc); + return (retstat); } static bool_t @@ -579,6 +604,7 @@ svcauth_gss_destroy(SVCAUTH *auth) gss_delete_sec_context(&min_stat, &gd->ctx, GSS_C_NO_BUFFER); gss_release_buffer(&min_stat, &gd->cname); + gss_release_buffer(&min_stat, &gd->checksum); if (gd->client_name) gss_release_name(&min_stat, &gd->client_name); @@ -643,17 +669,15 @@ svcauth_gss_get_principal(SVCAUTH *auth) return (pname); } -#ifdef MIT_RPC_ADDITIONS - /* - * Function: _svcauth_gssapi_set_log_badauth_func + * Function: svcauth_gss_set_log_badauth_func * * Purpose: sets the logging function called when an invalid RPC call * arrives * * See functional specifications. */ -void _svcauth_gssapi_set_log_badauth_func +void svcauth_gss_set_log_badauth_func (func, data) auth_gssapi_log_badauth_func func; caddr_t data; @@ -663,14 +687,14 @@ void _svcauth_gssapi_set_log_badauth_func } /* - * Function: _svcauth_gssapi_set_log_badverf_func + * Function: svcauth_gss_set_log_badverf_func * * Purpose: sets the logging function called when an invalid RPC call * arrives * * See functional specifications. */ -void _svcauth_gssapi_set_log_badverf_func +void svcauth_gss_set_log_badverf_func (func, data) auth_gssapi_log_badverf_func func; caddr_t data; @@ -680,14 +704,14 @@ void _svcauth_gssapi_set_log_badverf_func } /* - * Function: _svcauth_gssapi_set_log_miscerr_func + * Function: svcauth_gss_set_log_miscerr_func * * Purpose: sets the logging function called when a miscellaneous * AUTH_GSSAPI error occurs * * See functional specifications. */ -void _svcauth_gssapi_set_log_miscerr_func +void svcauth_gss_set_log_miscerr_func (func, data) auth_gssapi_log_miscerr_func func; caddr_t data; @@ -695,5 +719,3 @@ void _svcauth_gssapi_set_log_miscerr_func log_miscerr = func; log_miscerr_data = data; } - -#endif /* MIT_RPC_ADDITIONS */ diff --git a/src/lib/rpc/svc_auth_gssapi.c b/src/lib/rpc/svc_auth_gssapi.c index 94ccc7b..f9bde17 100644 --- a/src/lib/rpc/svc_auth_gssapi.c +++ b/src/lib/rpc/svc_auth_gssapi.c @@ -76,6 +76,8 @@ typedef struct _svc_auth_gssapi_data { static bool_t svc_auth_gssapi_wrap(SVCAUTH *, XDR *, xdrproc_t, caddr_t); static bool_t svc_auth_gssapi_unwrap(SVCAUTH *, XDR *, xdrproc_t, caddr_t); +static bool_t svc_auth_gssapi_destroy(SVCAUTH *); + static svc_auth_gssapi_data *create_client(void); static svc_auth_gssapi_data *get_client (gss_buffer_t client_handle); @@ -89,6 +91,7 @@ static void dump_db (char *msg); struct svc_auth_ops svc_auth_gssapi_ops = { svc_auth_gssapi_wrap, svc_auth_gssapi_unwrap, + svc_auth_gssapi_destroy }; /* @@ -581,6 +584,7 @@ enum auth_stat gssrpc__svcauth_gssapi(rqst, msg, no_dispatch) *no_dispatch = TRUE; destroy_client(client_data); + rqst->rq_xprt->xp_auth = NULL; break; default: @@ -924,7 +928,9 @@ bool_t svcauth_gssapi_set_names(names, num) for (i = 0; i < num; i++) { in_buf.value = names[i].name; in_buf.length = strlen(in_buf.value) + 1; - + + PRINTF(("svcauth_gssapi_set_names: importing %s\n", in_buf.value)); + gssstat = gss_import_name(&minor_stat, &in_buf, names[i].type, &server_name_list[i]); @@ -1084,3 +1090,12 @@ static bool_t svc_auth_gssapi_unwrap(auth, in_xdrs, xdr_func, xdr_ptr) } else return TRUE; } + +static bool_t svc_auth_gssapi_destroy(auth) + SVCAUTH *auth; +{ + svc_auth_gssapi_data *client_data = SVCAUTH_PRIVATE(auth); + + destroy_client(client_data); + return TRUE; +} diff --git a/src/lib/rpc/svc_tcp.c b/src/lib/rpc/svc_tcp.c index 1614d98..841bcc6 100644 --- a/src/lib/rpc/svc_tcp.c +++ b/src/lib/rpc/svc_tcp.c @@ -176,6 +176,7 @@ svctcp_create(sock, sendsize, recvsize) } xprt->xp_p2 = NULL; xprt->xp_p1 = (caddr_t)r; + xprt->xp_auth = NULL; xprt->xp_verf = gssrpc__null_auth; xprt->xp_ops = &svctcp_rendezvous_op; xprt->xp_port = ntohs(addr.sin_port); @@ -225,6 +226,7 @@ makefd_xprt(fd, sendsize, recvsize) (caddr_t)xprt, readtcp, writetcp); xprt->xp_p2 = NULL; xprt->xp_p1 = (caddr_t)cd; + xprt->xp_auth = NULL; xprt->xp_verf.oa_base = cd->verf_body; xprt->xp_addrlen = 0; xprt->xp_laddrlen = 0; @@ -292,6 +294,10 @@ svctcp_destroy(xprt) /* an actual connection socket */ XDR_DESTROY(&(cd->xdrs)); } + if (xprt->xp_auth != NULL) { + SVCAUTH_DESTROY(xprt->xp_auth); + xprt->xp_auth = NULL; + } mem_free((caddr_t)cd, sizeof(struct tcp_conn)); mem_free((caddr_t)xprt, sizeof(SVCXPRT)); } diff --git a/src/lib/rpc/svc_udp.c b/src/lib/rpc/svc_udp.c index 3f8cd4a..4630500 100644 --- a/src/lib/rpc/svc_udp.c +++ b/src/lib/rpc/svc_udp.c @@ -149,6 +149,7 @@ svcudp_bufcreate(sock, sendsz, recvsz) &(su->su_xdrs), rpc_buffer(xprt), su->su_iosz, XDR_DECODE); su->su_cache = NULL; xprt->xp_p2 = (caddr_t)su; + xprt->xp_auth = NULL; xprt->xp_verf.oa_base = su->su_verfbody; xprt->xp_ops = &svcudp_op; xprt->xp_port = ntohs(addr.sin_port); @@ -300,7 +301,13 @@ svcudp_destroy(xprt) register struct svcudp_data *su = su_data(xprt); xprt_unregister(xprt); - (void)close(xprt->xp_sock); + if (xprt->xp_sock != -1) + (void)close(xprt->xp_sock); + xprt->xp_sock = -1; + if (xprt->xp_auth != NULL) { + SVCAUTH_DESTROY(xprt->xp_auth); + xprt->xp_auth = NULL; + } XDR_DESTROY(&(su->su_xdrs)); mem_free(rpc_buffer(xprt), su->su_iosz); mem_free((caddr_t)su, sizeof(struct svcudp_data)); diff --git a/src/lib/rpc/xdr_rec.c b/src/lib/rpc/xdr_rec.c index 5aef7c7..ae79627 100644 --- a/src/lib/rpc/xdr_rec.c +++ b/src/lib/rpc/xdr_rec.c @@ -303,30 +303,22 @@ xdrrec_getpos(xdrs) register RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private; register int pos; -/* 11/5/95 JRG HELP! lseek() can't take a pointer as the first arg - * This code must have always failed, and the failure let the arithmetic - * calculations proceed - */ -#ifdef __osf__ - pos = -1; -#else - pos = lseek((int)rstrm->tcp_handle, (off_t) 0, 1); -#endif - if (pos != -1) - switch (xdrs->x_op) { + 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 + - BYTES_PER_XDR_UNIT; + break; - case XDR_DECODE: - pos -= rstrm->in_boundry - rstrm->in_finger; - break; + case XDR_DECODE: + pos = rstrm->in_boundry - rstrm->in_finger + - BYTES_PER_XDR_UNIT; + break; - default: - pos = (u_int) -1; - break; - } + default: + pos = -1; + break; + } return ((u_int) pos); } |