aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Yu <tlyu@mit.edu>2004-06-16 01:26:55 +0000
committerTom Yu <tlyu@mit.edu>2004-06-16 01:26:55 +0000
commit9720ec5793d204cf6d59ec021ff33e80c9b0b7cf (patch)
tree5ce587f11d5bca6958bb03270d0e2bb09e65d114
parent330c08794f9d305778cc40d8407b9170eaa96db6 (diff)
downloadkrb5-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/ChangeLog53
-rw-r--r--src/lib/rpc/auth_gss.c45
-rw-r--r--src/lib/rpc/auth_gssapi.h7
-rw-r--r--src/lib/rpc/authgss_prot.c29
-rw-r--r--src/lib/rpc/svc.c3
-rw-r--r--src/lib/rpc/svc.h3
-rw-r--r--src/lib/rpc/svc_auth_gss.c178
-rw-r--r--src/lib/rpc/svc_auth_gssapi.c17
-rw-r--r--src/lib/rpc/svc_tcp.c6
-rw-r--r--src/lib/rpc/svc_udp.c9
-rw-r--r--src/lib/rpc/xdr_rec.c34
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 = &num;
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);
}