aboutsummaryrefslogtreecommitdiffstats
path: root/net/sunrpc/auth_gss/svcauth_gss.c
diff options
context:
space:
mode:
authorSimo Sorce <simo@redhat.com>2012-04-17 09:39:06 -0400
committerJ. Bruce Fields <bfields@redhat.com>2012-04-25 14:29:32 -0400
commitfc2952a2a9f724f7d200c69a2b059ec331a80363 (patch)
treec615c18469c1052024e5f487d490db071bb1b776 /net/sunrpc/auth_gss/svcauth_gss.c
parentf69adb2fe2553f0536ad3603828c835239d5ec3e (diff)
SUNRPC: split upcall function to extract reusable parts
This is needed to share code between the current server upcall mechanism and the new gssproxy upcall mechanism introduced in a following patch. Signed-off-by: Simo Sorce <simo@redhat.com> Signed-off-by: J. Bruce Fields <bfields@redhat.com>
Diffstat (limited to 'net/sunrpc/auth_gss/svcauth_gss.c')
-rw-r--r--net/sunrpc/auth_gss/svcauth_gss.c100
1 files changed, 64 insertions, 36 deletions
diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c
index 1600cfb1618c..f0a0cd4470b7 100644
--- a/net/sunrpc/auth_gss/svcauth_gss.c
+++ b/net/sunrpc/auth_gss/svcauth_gss.c
@@ -964,16 +964,17 @@ svcauth_gss_set_client(struct svc_rqst *rqstp)
964} 964}
965 965
966static inline int 966static inline int
967gss_write_init_verf(struct cache_detail *cd, struct svc_rqst *rqstp, struct rsi *rsip) 967gss_write_init_verf(struct cache_detail *cd, struct svc_rqst *rqstp,
968 struct xdr_netobj *out_handle, int *major_status)
968{ 969{
969 struct rsc *rsci; 970 struct rsc *rsci;
970 int rc; 971 int rc;
971 972
972 if (rsip->major_status != GSS_S_COMPLETE) 973 if (*major_status != GSS_S_COMPLETE)
973 return gss_write_null_verf(rqstp); 974 return gss_write_null_verf(rqstp);
974 rsci = gss_svc_searchbyctx(cd, &rsip->out_handle); 975 rsci = gss_svc_searchbyctx(cd, out_handle);
975 if (rsci == NULL) { 976 if (rsci == NULL) {
976 rsip->major_status = GSS_S_NO_CONTEXT; 977 *major_status = GSS_S_NO_CONTEXT;
977 return gss_write_null_verf(rqstp); 978 return gss_write_null_verf(rqstp);
978 } 979 }
979 rc = gss_write_verf(rqstp, rsci->mechctx, GSS_SEQ_WIN); 980 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
981 return rc; 982 return rc;
982} 983}
983 984
984/* 985static inline int
985 * Having read the cred already and found we're in the context 986gss_read_verf(struct rpc_gss_wire_cred *gc,
986 * initiation case, read the verifier and initiate (or check the results 987 struct kvec *argv, __be32 *authp,
987 * of) upcalls to userspace for help with context initiation. If 988 struct xdr_netobj *in_handle,
988 * the upcall results are available, write the verifier and result. 989 struct xdr_netobj *in_token)
989 * Otherwise, drop the request pending an answer to the upcall.
990 */
991static int svcauth_gss_handle_init(struct svc_rqst *rqstp,
992 struct rpc_gss_wire_cred *gc, __be32 *authp)
993{ 990{
994 struct kvec *argv = &rqstp->rq_arg.head[0];
995 struct kvec *resv = &rqstp->rq_res.head[0];
996 struct xdr_netobj tmpobj; 991 struct xdr_netobj tmpobj;
997 struct rsi *rsip, rsikey;
998 int ret;
999 struct sunrpc_net *sn = net_generic(rqstp->rq_xprt->xpt_net, sunrpc_net_id);
1000 992
1001 /* Read the verifier; should be NULL: */ 993 /* Read the verifier; should be NULL: */
1002 *authp = rpc_autherr_badverf; 994 *authp = rpc_autherr_badverf;
@@ -1006,24 +998,67 @@ static int svcauth_gss_handle_init(struct svc_rqst *rqstp,
1006 return SVC_DENIED; 998 return SVC_DENIED;
1007 if (svc_getnl(argv) != 0) 999 if (svc_getnl(argv) != 0)
1008 return SVC_DENIED; 1000 return SVC_DENIED;
1009
1010 /* Martial context handle and token for upcall: */ 1001 /* Martial context handle and token for upcall: */
1011 *authp = rpc_autherr_badcred; 1002 *authp = rpc_autherr_badcred;
1012 if (gc->gc_proc == RPC_GSS_PROC_INIT && gc->gc_ctx.len != 0) 1003 if (gc->gc_proc == RPC_GSS_PROC_INIT && gc->gc_ctx.len != 0)
1013 return SVC_DENIED; 1004 return SVC_DENIED;
1014 memset(&rsikey, 0, sizeof(rsikey)); 1005 if (dup_netobj(in_handle, &gc->gc_ctx))
1015 if (dup_netobj(&rsikey.in_handle, &gc->gc_ctx))
1016 return SVC_CLOSE; 1006 return SVC_CLOSE;
1017 *authp = rpc_autherr_badverf; 1007 *authp = rpc_autherr_badverf;
1018 if (svc_safe_getnetobj(argv, &tmpobj)) { 1008 if (svc_safe_getnetobj(argv, &tmpobj)) {
1019 kfree(rsikey.in_handle.data); 1009 kfree(in_handle->data);
1020 return SVC_DENIED; 1010 return SVC_DENIED;
1021 } 1011 }
1022 if (dup_netobj(&rsikey.in_token, &tmpobj)) { 1012 if (dup_netobj(in_token, &tmpobj)) {
1023 kfree(rsikey.in_handle.data); 1013 kfree(in_handle->data);
1024 return SVC_CLOSE; 1014 return SVC_CLOSE;
1025 } 1015 }
1026 1016
1017 return 0;
1018}
1019
1020static inline int
1021gss_write_resv(struct kvec *resv, size_t size_limit,
1022 struct xdr_netobj *out_handle, struct xdr_netobj *out_token,
1023 int major_status, int minor_status)
1024{
1025 if (resv->iov_len + 4 > size_limit)
1026 return -1;
1027 svc_putnl(resv, RPC_SUCCESS);
1028 if (svc_safe_putnetobj(resv, out_handle))
1029 return -1;
1030 if (resv->iov_len + 3 * 4 > size_limit)
1031 return -1;
1032 svc_putnl(resv, major_status);
1033 svc_putnl(resv, minor_status);
1034 svc_putnl(resv, GSS_SEQ_WIN);
1035 if (svc_safe_putnetobj(resv, out_token))
1036 return -1;
1037 return 0;
1038}
1039
1040/*
1041 * Having read the cred already and found we're in the context
1042 * initiation case, read the verifier and initiate (or check the results
1043 * of) upcalls to userspace for help with context initiation. If
1044 * the upcall results are available, write the verifier and result.
1045 * Otherwise, drop the request pending an answer to the upcall.
1046 */
1047static int svcauth_gss_handle_init(struct svc_rqst *rqstp,
1048 struct rpc_gss_wire_cred *gc, __be32 *authp)
1049{
1050 struct kvec *argv = &rqstp->rq_arg.head[0];
1051 struct kvec *resv = &rqstp->rq_res.head[0];
1052 struct rsi *rsip, rsikey;
1053 int ret;
1054 struct sunrpc_net *sn = net_generic(rqstp->rq_xprt->xpt_net, sunrpc_net_id);
1055
1056 memset(&rsikey, 0, sizeof(rsikey));
1057 ret = gss_read_verf(gc, argv, authp,
1058 &rsikey.in_handle, &rsikey.in_token);
1059 if (ret)
1060 return ret;
1061
1027 /* Perform upcall, or find upcall result: */ 1062 /* Perform upcall, or find upcall result: */
1028 rsip = rsi_lookup(sn->rsi_cache, &rsikey); 1063 rsip = rsi_lookup(sn->rsi_cache, &rsikey);
1029 rsi_free(&rsikey); 1064 rsi_free(&rsikey);
@@ -1035,19 +1070,12 @@ static int svcauth_gss_handle_init(struct svc_rqst *rqstp,
1035 1070
1036 ret = SVC_CLOSE; 1071 ret = SVC_CLOSE;
1037 /* Got an answer to the upcall; use it: */ 1072 /* Got an answer to the upcall; use it: */
1038 if (gss_write_init_verf(sn->rsc_cache, rqstp, rsip)) 1073 if (gss_write_init_verf(sn->rsc_cache, rqstp,
1074 &rsip->out_handle, &rsip->major_status))
1039 goto out; 1075 goto out;
1040 if (resv->iov_len + 4 > PAGE_SIZE) 1076 if (gss_write_resv(resv, PAGE_SIZE,
1041 goto out; 1077 &rsip->out_handle, &rsip->out_token,
1042 svc_putnl(resv, RPC_SUCCESS); 1078 rsip->major_status, rsip->minor_status))
1043 if (svc_safe_putnetobj(resv, &rsip->out_handle))
1044 goto out;
1045 if (resv->iov_len + 3 * 4 > PAGE_SIZE)
1046 goto out;
1047 svc_putnl(resv, rsip->major_status);
1048 svc_putnl(resv, rsip->minor_status);
1049 svc_putnl(resv, GSS_SEQ_WIN);
1050 if (svc_safe_putnetobj(resv, &rsip->out_token))
1051 goto out; 1079 goto out;
1052 1080
1053 ret = SVC_COMPLETE; 1081 ret = SVC_COMPLETE;