diff options
author | J.Bruce Fields <bfields@fieldses.org> | 2006-10-04 05:16:07 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-10-04 10:55:19 -0400 |
commit | 5b304bc5bfccc82b856e876e829c260df8e67ff2 (patch) | |
tree | 1ef7b419ff3d0a43ea745b375a8aa8209b59d28e | |
parent | 3c15a486643a103eaf068e5fb3b7f9d720d579a7 (diff) |
[PATCH] knfsd: svcrpc: gss: fix failure on SVC_DENIED in integrity case
If the request is denied after gss_accept was called, we shouldn't try to wrap
the reply. We were checking the accept_stat but not the reply_stat.
To check the reply_stat in _release, we need a pointer to before (rather than
after) the verifier, so modify body_start appropriately.
Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
Signed-off-by: Neil Brown <neilb@suse.de>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r-- | net/sunrpc/auth_gss/svcauth_gss.c | 30 |
1 files changed, 18 insertions, 12 deletions
diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c index eeb1cce96649..447d9aef4605 100644 --- a/net/sunrpc/auth_gss/svcauth_gss.c +++ b/net/sunrpc/auth_gss/svcauth_gss.c | |||
@@ -903,9 +903,9 @@ out_seq: | |||
903 | struct gss_svc_data { | 903 | struct gss_svc_data { |
904 | /* decoded gss client cred: */ | 904 | /* decoded gss client cred: */ |
905 | struct rpc_gss_wire_cred clcred; | 905 | struct rpc_gss_wire_cred clcred; |
906 | /* pointer to the beginning of the procedure-specific results, | 906 | /* save a pointer to the beginning of the encoded verifier, |
907 | * which may be encrypted/checksummed in svcauth_gss_release: */ | 907 | * for use in encryption/checksumming in svcauth_gss_release: */ |
908 | __be32 *body_start; | 908 | __be32 *verf_start; |
909 | struct rsc *rsci; | 909 | struct rsc *rsci; |
910 | }; | 910 | }; |
911 | 911 | ||
@@ -968,7 +968,7 @@ svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp) | |||
968 | if (!svcdata) | 968 | if (!svcdata) |
969 | goto auth_err; | 969 | goto auth_err; |
970 | rqstp->rq_auth_data = svcdata; | 970 | rqstp->rq_auth_data = svcdata; |
971 | svcdata->body_start = NULL; | 971 | svcdata->verf_start = NULL; |
972 | svcdata->rsci = NULL; | 972 | svcdata->rsci = NULL; |
973 | gc = &svcdata->clcred; | 973 | gc = &svcdata->clcred; |
974 | 974 | ||
@@ -1097,6 +1097,7 @@ svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp) | |||
1097 | goto complete; | 1097 | goto complete; |
1098 | case RPC_GSS_PROC_DATA: | 1098 | case RPC_GSS_PROC_DATA: |
1099 | *authp = rpcsec_gsserr_ctxproblem; | 1099 | *authp = rpcsec_gsserr_ctxproblem; |
1100 | svcdata->verf_start = resv->iov_base + resv->iov_len; | ||
1100 | if (gss_write_verf(rqstp, rsci->mechctx, gc->gc_seq)) | 1101 | if (gss_write_verf(rqstp, rsci->mechctx, gc->gc_seq)) |
1101 | goto auth_err; | 1102 | goto auth_err; |
1102 | rqstp->rq_cred = rsci->cred; | 1103 | rqstp->rq_cred = rsci->cred; |
@@ -1110,7 +1111,6 @@ svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp) | |||
1110 | gc->gc_seq, rsci->mechctx)) | 1111 | gc->gc_seq, rsci->mechctx)) |
1111 | goto auth_err; | 1112 | goto auth_err; |
1112 | /* placeholders for length and seq. number: */ | 1113 | /* placeholders for length and seq. number: */ |
1113 | svcdata->body_start = resv->iov_base + resv->iov_len; | ||
1114 | svc_putnl(resv, 0); | 1114 | svc_putnl(resv, 0); |
1115 | svc_putnl(resv, 0); | 1115 | svc_putnl(resv, 0); |
1116 | break; | 1116 | break; |
@@ -1119,7 +1119,6 @@ svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp) | |||
1119 | gc->gc_seq, rsci->mechctx)) | 1119 | gc->gc_seq, rsci->mechctx)) |
1120 | goto auth_err; | 1120 | goto auth_err; |
1121 | /* placeholders for length and seq. number: */ | 1121 | /* placeholders for length and seq. number: */ |
1122 | svcdata->body_start = resv->iov_base + resv->iov_len; | ||
1123 | svc_putnl(resv, 0); | 1122 | svc_putnl(resv, 0); |
1124 | svc_putnl(resv, 0); | 1123 | svc_putnl(resv, 0); |
1125 | break; | 1124 | break; |
@@ -1150,14 +1149,21 @@ out: | |||
1150 | u32 * | 1149 | u32 * |
1151 | svcauth_gss_prepare_to_wrap(struct xdr_buf *resbuf, struct gss_svc_data *gsd) | 1150 | svcauth_gss_prepare_to_wrap(struct xdr_buf *resbuf, struct gss_svc_data *gsd) |
1152 | { | 1151 | { |
1153 | u32 *p; | 1152 | u32 *p, verf_len; |
1154 | 1153 | ||
1155 | p = gsd->body_start; | 1154 | p = gsd->verf_start; |
1156 | gsd->body_start = NULL; | 1155 | gsd->verf_start = NULL; |
1156 | |||
1157 | /* If the reply stat is nonzero, don't wrap: */ | ||
1158 | if (*(p-1) != rpc_success) | ||
1159 | return NULL; | ||
1160 | /* Skip the verifier: */ | ||
1161 | p += 1; | ||
1162 | verf_len = ntohl(*p++); | ||
1163 | p += XDR_QUADLEN(verf_len); | ||
1157 | /* move accept_stat to right place: */ | 1164 | /* move accept_stat to right place: */ |
1158 | memcpy(p, p + 2, 4); | 1165 | memcpy(p, p + 2, 4); |
1159 | /* Don't wrap in failure case: */ | 1166 | /* Also don't wrap if the accept stat is nonzero: */ |
1160 | /* Counting on not getting here if call was not even accepted! */ | ||
1161 | if (*p != rpc_success) { | 1167 | if (*p != rpc_success) { |
1162 | resbuf->head[0].iov_len -= 2 * 4; | 1168 | resbuf->head[0].iov_len -= 2 * 4; |
1163 | return NULL; | 1169 | return NULL; |
@@ -1283,7 +1289,7 @@ svcauth_gss_release(struct svc_rqst *rqstp) | |||
1283 | if (gc->gc_proc != RPC_GSS_PROC_DATA) | 1289 | if (gc->gc_proc != RPC_GSS_PROC_DATA) |
1284 | goto out; | 1290 | goto out; |
1285 | /* Release can be called twice, but we only wrap once. */ | 1291 | /* Release can be called twice, but we only wrap once. */ |
1286 | if (gsd->body_start == NULL) | 1292 | if (gsd->verf_start == NULL) |
1287 | goto out; | 1293 | goto out; |
1288 | /* normally not set till svc_send, but we need it here: */ | 1294 | /* normally not set till svc_send, but we need it here: */ |
1289 | /* XXX: what for? Do we mess it up the moment we call svc_putu32 | 1295 | /* XXX: what for? Do we mess it up the moment we call svc_putu32 |