|
@@ -964,16 +964,17 @@ svcauth_gss_set_client(struct svc_rqst *rqstp)
|
|
}
|
|
}
|
|
|
|
|
|
static inline int
|
|
static inline int
|
|
-gss_write_init_verf(struct cache_detail *cd, struct svc_rqst *rqstp, struct rsi *rsip)
|
|
|
|
|
|
+gss_write_init_verf(struct cache_detail *cd, struct svc_rqst *rqstp,
|
|
|
|
+ struct xdr_netobj *out_handle, int *major_status)
|
|
{
|
|
{
|
|
struct rsc *rsci;
|
|
struct rsc *rsci;
|
|
int rc;
|
|
int rc;
|
|
|
|
|
|
- if (rsip->major_status != GSS_S_COMPLETE)
|
|
|
|
|
|
+ if (*major_status != GSS_S_COMPLETE)
|
|
return gss_write_null_verf(rqstp);
|
|
return gss_write_null_verf(rqstp);
|
|
- rsci = gss_svc_searchbyctx(cd, &rsip->out_handle);
|
|
|
|
|
|
+ rsci = gss_svc_searchbyctx(cd, out_handle);
|
|
if (rsci == NULL) {
|
|
if (rsci == NULL) {
|
|
- rsip->major_status = GSS_S_NO_CONTEXT;
|
|
|
|
|
|
+ *major_status = GSS_S_NO_CONTEXT;
|
|
return gss_write_null_verf(rqstp);
|
|
return gss_write_null_verf(rqstp);
|
|
}
|
|
}
|
|
rc = gss_write_verf(rqstp, rsci->mechctx, GSS_SEQ_WIN);
|
|
rc = gss_write_verf(rqstp, rsci->mechctx, GSS_SEQ_WIN);
|
|
@@ -981,22 +982,13 @@ gss_write_init_verf(struct cache_detail *cd, struct svc_rqst *rqstp, struct rsi
|
|
return rc;
|
|
return rc;
|
|
}
|
|
}
|
|
|
|
|
|
-/*
|
|
|
|
- * Having read the cred already and found we're in the context
|
|
|
|
- * initiation case, read the verifier and initiate (or check the results
|
|
|
|
- * of) upcalls to userspace for help with context initiation. If
|
|
|
|
- * the upcall results are available, write the verifier and result.
|
|
|
|
- * Otherwise, drop the request pending an answer to the upcall.
|
|
|
|
- */
|
|
|
|
-static int svcauth_gss_handle_init(struct svc_rqst *rqstp,
|
|
|
|
- struct rpc_gss_wire_cred *gc, __be32 *authp)
|
|
|
|
|
|
+static inline int
|
|
|
|
+gss_read_verf(struct rpc_gss_wire_cred *gc,
|
|
|
|
+ struct kvec *argv, __be32 *authp,
|
|
|
|
+ struct xdr_netobj *in_handle,
|
|
|
|
+ struct xdr_netobj *in_token)
|
|
{
|
|
{
|
|
- struct kvec *argv = &rqstp->rq_arg.head[0];
|
|
|
|
- struct kvec *resv = &rqstp->rq_res.head[0];
|
|
|
|
struct xdr_netobj tmpobj;
|
|
struct xdr_netobj tmpobj;
|
|
- struct rsi *rsip, rsikey;
|
|
|
|
- int ret;
|
|
|
|
- struct sunrpc_net *sn = net_generic(rqstp->rq_xprt->xpt_net, sunrpc_net_id);
|
|
|
|
|
|
|
|
/* Read the verifier; should be NULL: */
|
|
/* Read the verifier; should be NULL: */
|
|
*authp = rpc_autherr_badverf;
|
|
*authp = rpc_autherr_badverf;
|
|
@@ -1006,24 +998,67 @@ static int svcauth_gss_handle_init(struct svc_rqst *rqstp,
|
|
return SVC_DENIED;
|
|
return SVC_DENIED;
|
|
if (svc_getnl(argv) != 0)
|
|
if (svc_getnl(argv) != 0)
|
|
return SVC_DENIED;
|
|
return SVC_DENIED;
|
|
-
|
|
|
|
/* Martial context handle and token for upcall: */
|
|
/* Martial context handle and token for upcall: */
|
|
*authp = rpc_autherr_badcred;
|
|
*authp = rpc_autherr_badcred;
|
|
if (gc->gc_proc == RPC_GSS_PROC_INIT && gc->gc_ctx.len != 0)
|
|
if (gc->gc_proc == RPC_GSS_PROC_INIT && gc->gc_ctx.len != 0)
|
|
return SVC_DENIED;
|
|
return SVC_DENIED;
|
|
- memset(&rsikey, 0, sizeof(rsikey));
|
|
|
|
- if (dup_netobj(&rsikey.in_handle, &gc->gc_ctx))
|
|
|
|
|
|
+ if (dup_netobj(in_handle, &gc->gc_ctx))
|
|
return SVC_CLOSE;
|
|
return SVC_CLOSE;
|
|
*authp = rpc_autherr_badverf;
|
|
*authp = rpc_autherr_badverf;
|
|
if (svc_safe_getnetobj(argv, &tmpobj)) {
|
|
if (svc_safe_getnetobj(argv, &tmpobj)) {
|
|
- kfree(rsikey.in_handle.data);
|
|
|
|
|
|
+ kfree(in_handle->data);
|
|
return SVC_DENIED;
|
|
return SVC_DENIED;
|
|
}
|
|
}
|
|
- if (dup_netobj(&rsikey.in_token, &tmpobj)) {
|
|
|
|
- kfree(rsikey.in_handle.data);
|
|
|
|
|
|
+ if (dup_netobj(in_token, &tmpobj)) {
|
|
|
|
+ kfree(in_handle->data);
|
|
return SVC_CLOSE;
|
|
return SVC_CLOSE;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static inline int
|
|
|
|
+gss_write_resv(struct kvec *resv, size_t size_limit,
|
|
|
|
+ struct xdr_netobj *out_handle, struct xdr_netobj *out_token,
|
|
|
|
+ int major_status, int minor_status)
|
|
|
|
+{
|
|
|
|
+ if (resv->iov_len + 4 > size_limit)
|
|
|
|
+ return -1;
|
|
|
|
+ svc_putnl(resv, RPC_SUCCESS);
|
|
|
|
+ if (svc_safe_putnetobj(resv, out_handle))
|
|
|
|
+ return -1;
|
|
|
|
+ if (resv->iov_len + 3 * 4 > size_limit)
|
|
|
|
+ return -1;
|
|
|
|
+ svc_putnl(resv, major_status);
|
|
|
|
+ svc_putnl(resv, minor_status);
|
|
|
|
+ svc_putnl(resv, GSS_SEQ_WIN);
|
|
|
|
+ if (svc_safe_putnetobj(resv, out_token))
|
|
|
|
+ return -1;
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/*
|
|
|
|
+ * Having read the cred already and found we're in the context
|
|
|
|
+ * initiation case, read the verifier and initiate (or check the results
|
|
|
|
+ * of) upcalls to userspace for help with context initiation. If
|
|
|
|
+ * the upcall results are available, write the verifier and result.
|
|
|
|
+ * Otherwise, drop the request pending an answer to the upcall.
|
|
|
|
+ */
|
|
|
|
+static int svcauth_gss_handle_init(struct svc_rqst *rqstp,
|
|
|
|
+ struct rpc_gss_wire_cred *gc, __be32 *authp)
|
|
|
|
+{
|
|
|
|
+ struct kvec *argv = &rqstp->rq_arg.head[0];
|
|
|
|
+ struct kvec *resv = &rqstp->rq_res.head[0];
|
|
|
|
+ struct rsi *rsip, rsikey;
|
|
|
|
+ int ret;
|
|
|
|
+ struct sunrpc_net *sn = net_generic(rqstp->rq_xprt->xpt_net, sunrpc_net_id);
|
|
|
|
+
|
|
|
|
+ memset(&rsikey, 0, sizeof(rsikey));
|
|
|
|
+ ret = gss_read_verf(gc, argv, authp,
|
|
|
|
+ &rsikey.in_handle, &rsikey.in_token);
|
|
|
|
+ if (ret)
|
|
|
|
+ return ret;
|
|
|
|
+
|
|
/* Perform upcall, or find upcall result: */
|
|
/* Perform upcall, or find upcall result: */
|
|
rsip = rsi_lookup(sn->rsi_cache, &rsikey);
|
|
rsip = rsi_lookup(sn->rsi_cache, &rsikey);
|
|
rsi_free(&rsikey);
|
|
rsi_free(&rsikey);
|
|
@@ -1035,19 +1070,12 @@ static int svcauth_gss_handle_init(struct svc_rqst *rqstp,
|
|
|
|
|
|
ret = SVC_CLOSE;
|
|
ret = SVC_CLOSE;
|
|
/* Got an answer to the upcall; use it: */
|
|
/* Got an answer to the upcall; use it: */
|
|
- if (gss_write_init_verf(sn->rsc_cache, rqstp, rsip))
|
|
|
|
|
|
+ if (gss_write_init_verf(sn->rsc_cache, rqstp,
|
|
|
|
+ &rsip->out_handle, &rsip->major_status))
|
|
goto out;
|
|
goto out;
|
|
- if (resv->iov_len + 4 > PAGE_SIZE)
|
|
|
|
- goto out;
|
|
|
|
- svc_putnl(resv, RPC_SUCCESS);
|
|
|
|
- if (svc_safe_putnetobj(resv, &rsip->out_handle))
|
|
|
|
- goto out;
|
|
|
|
- if (resv->iov_len + 3 * 4 > PAGE_SIZE)
|
|
|
|
- goto out;
|
|
|
|
- svc_putnl(resv, rsip->major_status);
|
|
|
|
- svc_putnl(resv, rsip->minor_status);
|
|
|
|
- svc_putnl(resv, GSS_SEQ_WIN);
|
|
|
|
- if (svc_safe_putnetobj(resv, &rsip->out_token))
|
|
|
|
|
|
+ if (gss_write_resv(resv, PAGE_SIZE,
|
|
|
|
+ &rsip->out_handle, &rsip->out_token,
|
|
|
|
+ rsip->major_status, rsip->minor_status))
|
|
goto out;
|
|
goto out;
|
|
|
|
|
|
ret = SVC_COMPLETE;
|
|
ret = SVC_COMPLETE;
|