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 /net | |
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>
Diffstat (limited to 'net')
-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; |