diff options
| author | J. Bruce Fields <bfields@citi.umich.edu> | 2007-08-09 20:16:22 -0400 |
|---|---|---|
| committer | J. Bruce Fields <bfields@citi.umich.edu> | 2007-10-09 18:31:57 -0400 |
| commit | 21fcd02be34f73bbc94db267b4db6ccd7332923d (patch) | |
| tree | 9adfcbd850a83fe22e809d401e18fdd98586db94 | |
| parent | c175b83c4c4be72535c5c12abc155e29a08323a0 (diff) | |
svcgss: move init code into separate function
We've let svcauth_gss_accept() get much too long and hairy. The
RPC_GSS_PROC_INIT and RPC_GSS_PROC_CONTINUE_INIT cases share very little
with the other cases, so it's very natural to split them off into a
separate function.
This will also nicely isolate the piece of code we need to parametrize
to authenticating gss-protected NFSv4 callbacks on behalf of the NFS
client.
Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
Acked-by: Neil Brown <neilb@suse.de>
| -rw-r--r-- | net/sunrpc/auth_gss/svcauth_gss.c | 144 |
1 files changed, 77 insertions, 67 deletions
diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c index 7da7050f06c3..73940df6c460 100644 --- a/net/sunrpc/auth_gss/svcauth_gss.c +++ b/net/sunrpc/auth_gss/svcauth_gss.c | |||
| @@ -631,7 +631,8 @@ svc_safe_putnetobj(struct kvec *resv, struct xdr_netobj *o) | |||
| 631 | return 0; | 631 | return 0; |
| 632 | } | 632 | } |
| 633 | 633 | ||
| 634 | /* Verify the checksum on the header and return SVC_OK on success. | 634 | /* |
| 635 | * Verify the checksum on the header and return SVC_OK on success. | ||
| 635 | * Otherwise, return SVC_DROP (in the case of a bad sequence number) | 636 | * Otherwise, return SVC_DROP (in the case of a bad sequence number) |
| 636 | * or return SVC_DENIED and indicate error in authp. | 637 | * or return SVC_DENIED and indicate error in authp. |
| 637 | */ | 638 | */ |
| @@ -961,6 +962,78 @@ gss_write_init_verf(struct svc_rqst *rqstp, struct rsi *rsip) | |||
| 961 | } | 962 | } |
| 962 | 963 | ||
| 963 | /* | 964 | /* |
| 965 | * Having read the cred already and found we're in the context | ||
| 966 | * initiation case, read the verifier and initiate (or check the results | ||
| 967 | * of) upcalls to userspace for help with context initiation. If | ||
| 968 | * the upcall results are available, write the verifier and result. | ||
| 969 | * Otherwise, drop the request pending an answer to the upcall. | ||
| 970 | */ | ||
| 971 | static int svcauth_gss_handle_init(struct svc_rqst *rqstp, | ||
| 972 | struct rpc_gss_wire_cred *gc, __be32 *authp) | ||
| 973 | { | ||
| 974 | struct kvec *argv = &rqstp->rq_arg.head[0]; | ||
| 975 | struct kvec *resv = &rqstp->rq_res.head[0]; | ||
| 976 | struct xdr_netobj tmpobj; | ||
| 977 | struct rsi *rsip, rsikey; | ||
| 978 | |||
| 979 | /* Read the verifier; should be NULL: */ | ||
| 980 | *authp = rpc_autherr_badverf; | ||
| 981 | if (argv->iov_len < 2 * 4) | ||
| 982 | return SVC_DENIED; | ||
| 983 | if (svc_getnl(argv) != RPC_AUTH_NULL) | ||
| 984 | return SVC_DENIED; | ||
| 985 | if (svc_getnl(argv) != 0) | ||
| 986 | return SVC_DENIED; | ||
| 987 | |||
| 988 | /* Martial context handle and token for upcall: */ | ||
| 989 | *authp = rpc_autherr_badcred; | ||
| 990 | if (gc->gc_proc == RPC_GSS_PROC_INIT && gc->gc_ctx.len != 0) | ||
| 991 | return SVC_DENIED; | ||
| 992 | memset(&rsikey, 0, sizeof(rsikey)); | ||
| 993 | if (dup_netobj(&rsikey.in_handle, &gc->gc_ctx)) | ||
| 994 | return SVC_DROP; | ||
| 995 | *authp = rpc_autherr_badverf; | ||
| 996 | if (svc_safe_getnetobj(argv, &tmpobj)) { | ||
| 997 | kfree(rsikey.in_handle.data); | ||
| 998 | return SVC_DENIED; | ||
| 999 | } | ||
| 1000 | if (dup_netobj(&rsikey.in_token, &tmpobj)) { | ||
| 1001 | kfree(rsikey.in_handle.data); | ||
| 1002 | return SVC_DROP; | ||
| 1003 | } | ||
| 1004 | |||
| 1005 | /* Perform upcall, or find upcall result: */ | ||
| 1006 | rsip = rsi_lookup(&rsikey); | ||
| 1007 | rsi_free(&rsikey); | ||
| 1008 | if (!rsip) | ||
| 1009 | return SVC_DROP; | ||
| 1010 | switch (cache_check(&rsi_cache, &rsip->h, &rqstp->rq_chandle)) { | ||
| 1011 | case -EAGAIN: | ||
| 1012 | case -ETIMEDOUT: | ||
| 1013 | case -ENOENT: | ||
| 1014 | /* No upcall result: */ | ||
| 1015 | return SVC_DROP; | ||
| 1016 | case 0: | ||
| 1017 | /* Got an answer to the upcall; use it: */ | ||
| 1018 | if (gss_write_init_verf(rqstp, rsip)) | ||
| 1019 | return SVC_DROP; | ||
| 1020 | if (resv->iov_len + 4 > PAGE_SIZE) | ||
| 1021 | return SVC_DROP; | ||
| 1022 | svc_putnl(resv, RPC_SUCCESS); | ||
| 1023 | if (svc_safe_putnetobj(resv, &rsip->out_handle)) | ||
| 1024 | return SVC_DROP; | ||
| 1025 | if (resv->iov_len + 3 * 4 > PAGE_SIZE) | ||
| 1026 | return SVC_DROP; | ||
| 1027 | svc_putnl(resv, rsip->major_status); | ||
| 1028 | svc_putnl(resv, rsip->minor_status); | ||
| 1029 | svc_putnl(resv, GSS_SEQ_WIN); | ||
| 1030 | if (svc_safe_putnetobj(resv, &rsip->out_token)) | ||
| 1031 | return SVC_DROP; | ||
| 1032 | } | ||
| 1033 | return SVC_COMPLETE; | ||
| 1034 | } | ||
| 1035 | |||
| 1036 | /* | ||
| 964 | * Accept an rpcsec packet. | 1037 | * Accept an rpcsec packet. |
| 965 | * If context establishment, punt to user space | 1038 | * If context establishment, punt to user space |
| 966 | * If data exchange, verify/decrypt | 1039 | * If data exchange, verify/decrypt |
| @@ -974,11 +1047,9 @@ svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp) | |||
| 974 | struct kvec *argv = &rqstp->rq_arg.head[0]; | 1047 | struct kvec *argv = &rqstp->rq_arg.head[0]; |
| 975 | struct kvec *resv = &rqstp->rq_res.head[0]; | 1048 | struct kvec *resv = &rqstp->rq_res.head[0]; |
| 976 | u32 crlen; | 1049 | u32 crlen; |
| 977 | struct xdr_netobj tmpobj; | ||
| 978 | struct gss_svc_data *svcdata = rqstp->rq_auth_data; | 1050 | struct gss_svc_data *svcdata = rqstp->rq_auth_data; |
| 979 | struct rpc_gss_wire_cred *gc; | 1051 | struct rpc_gss_wire_cred *gc; |
| 980 | struct rsc *rsci = NULL; | 1052 | struct rsc *rsci = NULL; |
| 981 | struct rsi *rsip, rsikey; | ||
| 982 | __be32 *rpcstart; | 1053 | __be32 *rpcstart; |
| 983 | __be32 *reject_stat = resv->iov_base + resv->iov_len; | 1054 | __be32 *reject_stat = resv->iov_base + resv->iov_len; |
| 984 | int ret; | 1055 | int ret; |
| @@ -1023,30 +1094,14 @@ svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp) | |||
| 1023 | if ((gc->gc_proc != RPC_GSS_PROC_DATA) && (rqstp->rq_proc != 0)) | 1094 | if ((gc->gc_proc != RPC_GSS_PROC_DATA) && (rqstp->rq_proc != 0)) |
| 1024 | goto auth_err; | 1095 | goto auth_err; |
| 1025 | 1096 | ||
| 1026 | /* | ||
| 1027 | * We've successfully parsed the credential. Let's check out the | ||
| 1028 | * verifier. An AUTH_NULL verifier is allowed (and required) for | ||
| 1029 | * INIT and CONTINUE_INIT requests. AUTH_RPCSEC_GSS is required for | ||
| 1030 | * PROC_DATA and PROC_DESTROY. | ||
| 1031 | * | ||
| 1032 | * AUTH_NULL verifier is 0 (AUTH_NULL), 0 (length). | ||
| 1033 | * AUTH_RPCSEC_GSS verifier is: | ||
| 1034 | * 6 (AUTH_RPCSEC_GSS), length, checksum. | ||
| 1035 | * checksum is calculated over rpcheader from xid up to here. | ||
| 1036 | */ | ||
| 1037 | *authp = rpc_autherr_badverf; | 1097 | *authp = rpc_autherr_badverf; |
| 1038 | switch (gc->gc_proc) { | 1098 | switch (gc->gc_proc) { |
| 1039 | case RPC_GSS_PROC_INIT: | 1099 | case RPC_GSS_PROC_INIT: |
| 1040 | case RPC_GSS_PROC_CONTINUE_INIT: | 1100 | case RPC_GSS_PROC_CONTINUE_INIT: |
| 1041 | if (argv->iov_len < 2 * 4) | 1101 | return svcauth_gss_handle_init(rqstp, gc, authp); |
| 1042 | goto auth_err; | ||
| 1043 | if (svc_getnl(argv) != RPC_AUTH_NULL) | ||
| 1044 | goto auth_err; | ||
| 1045 | if (svc_getnl(argv) != 0) | ||
| 1046 | goto auth_err; | ||
| 1047 | break; | ||
| 1048 | case RPC_GSS_PROC_DATA: | 1102 | case RPC_GSS_PROC_DATA: |
| 1049 | case RPC_GSS_PROC_DESTROY: | 1103 | case RPC_GSS_PROC_DESTROY: |
| 1104 | /* Look up the context, and check the verifier: */ | ||
| 1050 | *authp = rpcsec_gsserr_credproblem; | 1105 | *authp = rpcsec_gsserr_credproblem; |
| 1051 | rsci = gss_svc_searchbyctx(&gc->gc_ctx); | 1106 | rsci = gss_svc_searchbyctx(&gc->gc_ctx); |
| 1052 | if (!rsci) | 1107 | if (!rsci) |
| @@ -1067,51 +1122,6 @@ svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp) | |||
| 1067 | 1122 | ||
| 1068 | /* now act upon the command: */ | 1123 | /* now act upon the command: */ |
| 1069 | switch (gc->gc_proc) { | 1124 | switch (gc->gc_proc) { |
| 1070 | case RPC_GSS_PROC_INIT: | ||
| 1071 | case RPC_GSS_PROC_CONTINUE_INIT: | ||
| 1072 | *authp = rpc_autherr_badcred; | ||
| 1073 | if (gc->gc_proc == RPC_GSS_PROC_INIT && gc->gc_ctx.len != 0) | ||
| 1074 | goto auth_err; | ||
| 1075 | memset(&rsikey, 0, sizeof(rsikey)); | ||
| 1076 | if (dup_netobj(&rsikey.in_handle, &gc->gc_ctx)) | ||
| 1077 | goto drop; | ||
| 1078 | *authp = rpc_autherr_badverf; | ||
| 1079 | if (svc_safe_getnetobj(argv, &tmpobj)) { | ||
| 1080 | kfree(rsikey.in_handle.data); | ||
| 1081 | goto auth_err; | ||
| 1082 | } | ||
| 1083 | if (dup_netobj(&rsikey.in_token, &tmpobj)) { | ||
| 1084 | kfree(rsikey.in_handle.data); | ||
| 1085 | goto drop; | ||
| 1086 | } | ||
| 1087 | |||
| 1088 | rsip = rsi_lookup(&rsikey); | ||
| 1089 | rsi_free(&rsikey); | ||
| 1090 | if (!rsip) { | ||
| 1091 | goto drop; | ||
| 1092 | } | ||
| 1093 | switch(cache_check(&rsi_cache, &rsip->h, &rqstp->rq_chandle)) { | ||
| 1094 | case -EAGAIN: | ||
| 1095 | case -ETIMEDOUT: | ||
| 1096 | case -ENOENT: | ||
| 1097 | goto drop; | ||
| 1098 | case 0: | ||
| 1099 | if (gss_write_init_verf(rqstp, rsip)) | ||
| 1100 | goto drop; | ||
| 1101 | if (resv->iov_len + 4 > PAGE_SIZE) | ||
| 1102 | goto drop; | ||
| 1103 | svc_putnl(resv, RPC_SUCCESS); | ||
| 1104 | if (svc_safe_putnetobj(resv, &rsip->out_handle)) | ||
| 1105 | goto drop; | ||
| 1106 | if (resv->iov_len + 3 * 4 > PAGE_SIZE) | ||
| 1107 | goto drop; | ||
| 1108 | svc_putnl(resv, rsip->major_status); | ||
| 1109 | svc_putnl(resv, rsip->minor_status); | ||
| 1110 | svc_putnl(resv, GSS_SEQ_WIN); | ||
| 1111 | if (svc_safe_putnetobj(resv, &rsip->out_token)) | ||
| 1112 | goto drop; | ||
| 1113 | } | ||
| 1114 | goto complete; | ||
| 1115 | case RPC_GSS_PROC_DESTROY: | 1125 | case RPC_GSS_PROC_DESTROY: |
| 1116 | if (gss_write_verf(rqstp, rsci->mechctx, gc->gc_seq)) | 1126 | if (gss_write_verf(rqstp, rsci->mechctx, gc->gc_seq)) |
| 1117 | goto auth_err; | 1127 | goto auth_err; |
| @@ -1158,7 +1168,7 @@ svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp) | |||
| 1158 | goto out; | 1168 | goto out; |
| 1159 | } | 1169 | } |
| 1160 | auth_err: | 1170 | auth_err: |
| 1161 | /* Restore write pointer to original value: */ | 1171 | /* Restore write pointer to its original value: */ |
| 1162 | xdr_ressize_check(rqstp, reject_stat); | 1172 | xdr_ressize_check(rqstp, reject_stat); |
| 1163 | ret = SVC_DENIED; | 1173 | ret = SVC_DENIED; |
| 1164 | goto out; | 1174 | goto out; |
