diff options
-rw-r--r-- | net/sunrpc/auth_gss/svcauth_gss.c | 115 |
1 files changed, 64 insertions, 51 deletions
diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c index 71f57a5d800d..ce8dc0db214e 100644 --- a/net/sunrpc/auth_gss/svcauth_gss.c +++ b/net/sunrpc/auth_gss/svcauth_gss.c | |||
@@ -1072,8 +1072,8 @@ out: | |||
1072 | return ret; | 1072 | return ret; |
1073 | } | 1073 | } |
1074 | 1074 | ||
1075 | static int | 1075 | static inline int |
1076 | svcauth_gss_release(struct svc_rqst *rqstp) | 1076 | svcauth_gss_wrap_resp_integ(struct svc_rqst *rqstp) |
1077 | { | 1077 | { |
1078 | struct gss_svc_data *gsd = (struct gss_svc_data *)rqstp->rq_auth_data; | 1078 | struct gss_svc_data *gsd = (struct gss_svc_data *)rqstp->rq_auth_data; |
1079 | struct rpc_gss_wire_cred *gc = &gsd->clcred; | 1079 | struct rpc_gss_wire_cred *gc = &gsd->clcred; |
@@ -1085,6 +1085,67 @@ svcauth_gss_release(struct svc_rqst *rqstp) | |||
1085 | int integ_offset, integ_len; | 1085 | int integ_offset, integ_len; |
1086 | int stat = -EINVAL; | 1086 | int stat = -EINVAL; |
1087 | 1087 | ||
1088 | p = gsd->body_start; | ||
1089 | gsd->body_start = NULL; | ||
1090 | /* move accept_stat to right place: */ | ||
1091 | memcpy(p, p + 2, 4); | ||
1092 | /* don't wrap in failure case: */ | ||
1093 | /* Note: counting on not getting here if call was not even | ||
1094 | * accepted! */ | ||
1095 | if (*p != rpc_success) { | ||
1096 | resbuf->head[0].iov_len -= 2 * 4; | ||
1097 | goto out; | ||
1098 | } | ||
1099 | p++; | ||
1100 | integ_offset = (u8 *)(p + 1) - (u8 *)resbuf->head[0].iov_base; | ||
1101 | integ_len = resbuf->len - integ_offset; | ||
1102 | BUG_ON(integ_len % 4); | ||
1103 | *p++ = htonl(integ_len); | ||
1104 | *p++ = htonl(gc->gc_seq); | ||
1105 | if (xdr_buf_subsegment(resbuf, &integ_buf, integ_offset, | ||
1106 | integ_len)) | ||
1107 | BUG(); | ||
1108 | if (resbuf->page_len == 0 | ||
1109 | && resbuf->head[0].iov_len + RPC_MAX_AUTH_SIZE | ||
1110 | < PAGE_SIZE) { | ||
1111 | BUG_ON(resbuf->tail[0].iov_len); | ||
1112 | /* Use head for everything */ | ||
1113 | resv = &resbuf->head[0]; | ||
1114 | } else if (resbuf->tail[0].iov_base == NULL) { | ||
1115 | if (resbuf->head[0].iov_len + RPC_MAX_AUTH_SIZE > PAGE_SIZE) | ||
1116 | goto out_err; | ||
1117 | resbuf->tail[0].iov_base = resbuf->head[0].iov_base | ||
1118 | + resbuf->head[0].iov_len; | ||
1119 | resbuf->tail[0].iov_len = 0; | ||
1120 | rqstp->rq_restailpage = 0; | ||
1121 | resv = &resbuf->tail[0]; | ||
1122 | } else { | ||
1123 | resv = &resbuf->tail[0]; | ||
1124 | } | ||
1125 | mic.data = (u8 *)resv->iov_base + resv->iov_len + 4; | ||
1126 | if (gss_get_mic(gsd->rsci->mechctx, &integ_buf, &mic)) | ||
1127 | goto out_err; | ||
1128 | svc_putu32(resv, htonl(mic.len)); | ||
1129 | memset(mic.data + mic.len, 0, | ||
1130 | round_up_to_quad(mic.len) - mic.len); | ||
1131 | resv->iov_len += XDR_QUADLEN(mic.len) << 2; | ||
1132 | /* not strictly required: */ | ||
1133 | resbuf->len += XDR_QUADLEN(mic.len) << 2; | ||
1134 | BUG_ON(resv->iov_len > PAGE_SIZE); | ||
1135 | out: | ||
1136 | stat = 0; | ||
1137 | out_err: | ||
1138 | return stat; | ||
1139 | } | ||
1140 | |||
1141 | static int | ||
1142 | svcauth_gss_release(struct svc_rqst *rqstp) | ||
1143 | { | ||
1144 | struct gss_svc_data *gsd = (struct gss_svc_data *)rqstp->rq_auth_data; | ||
1145 | struct rpc_gss_wire_cred *gc = &gsd->clcred; | ||
1146 | struct xdr_buf *resbuf = &rqstp->rq_res; | ||
1147 | int stat = -EINVAL; | ||
1148 | |||
1088 | if (gc->gc_proc != RPC_GSS_PROC_DATA) | 1149 | if (gc->gc_proc != RPC_GSS_PROC_DATA) |
1089 | goto out; | 1150 | goto out; |
1090 | /* Release can be called twice, but we only wrap once. */ | 1151 | /* Release can be called twice, but we only wrap once. */ |
@@ -1097,55 +1158,7 @@ svcauth_gss_release(struct svc_rqst *rqstp) | |||
1097 | case RPC_GSS_SVC_NONE: | 1158 | case RPC_GSS_SVC_NONE: |
1098 | break; | 1159 | break; |
1099 | case RPC_GSS_SVC_INTEGRITY: | 1160 | case RPC_GSS_SVC_INTEGRITY: |
1100 | p = gsd->body_start; | 1161 | svcauth_gss_wrap_resp_integ(rqstp); |
1101 | gsd->body_start = NULL; | ||
1102 | /* move accept_stat to right place: */ | ||
1103 | memcpy(p, p + 2, 4); | ||
1104 | /* don't wrap in failure case: */ | ||
1105 | /* Note: counting on not getting here if call was not even | ||
1106 | * accepted! */ | ||
1107 | if (*p != rpc_success) { | ||
1108 | resbuf->head[0].iov_len -= 2 * 4; | ||
1109 | goto out; | ||
1110 | } | ||
1111 | p++; | ||
1112 | integ_offset = (u8 *)(p + 1) - (u8 *)resbuf->head[0].iov_base; | ||
1113 | integ_len = resbuf->len - integ_offset; | ||
1114 | BUG_ON(integ_len % 4); | ||
1115 | *p++ = htonl(integ_len); | ||
1116 | *p++ = htonl(gc->gc_seq); | ||
1117 | if (xdr_buf_subsegment(resbuf, &integ_buf, integ_offset, | ||
1118 | integ_len)) | ||
1119 | BUG(); | ||
1120 | if (resbuf->page_len == 0 | ||
1121 | && resbuf->head[0].iov_len + RPC_MAX_AUTH_SIZE | ||
1122 | < PAGE_SIZE) { | ||
1123 | BUG_ON(resbuf->tail[0].iov_len); | ||
1124 | /* Use head for everything */ | ||
1125 | resv = &resbuf->head[0]; | ||
1126 | } else if (resbuf->tail[0].iov_base == NULL) { | ||
1127 | if (resbuf->head[0].iov_len + RPC_MAX_AUTH_SIZE | ||
1128 | > PAGE_SIZE) | ||
1129 | goto out_err; | ||
1130 | resbuf->tail[0].iov_base = | ||
1131 | resbuf->head[0].iov_base | ||
1132 | + resbuf->head[0].iov_len; | ||
1133 | resbuf->tail[0].iov_len = 0; | ||
1134 | rqstp->rq_restailpage = 0; | ||
1135 | resv = &resbuf->tail[0]; | ||
1136 | } else { | ||
1137 | resv = &resbuf->tail[0]; | ||
1138 | } | ||
1139 | mic.data = (u8 *)resv->iov_base + resv->iov_len + 4; | ||
1140 | if (gss_get_mic(gsd->rsci->mechctx, &integ_buf, &mic)) | ||
1141 | goto out_err; | ||
1142 | svc_putu32(resv, htonl(mic.len)); | ||
1143 | memset(mic.data + mic.len, 0, | ||
1144 | round_up_to_quad(mic.len) - mic.len); | ||
1145 | resv->iov_len += XDR_QUADLEN(mic.len) << 2; | ||
1146 | /* not strictly required: */ | ||
1147 | resbuf->len += XDR_QUADLEN(mic.len) << 2; | ||
1148 | BUG_ON(resv->iov_len > PAGE_SIZE); | ||
1149 | break; | 1162 | break; |
1150 | case RPC_GSS_SVC_PRIVACY: | 1163 | case RPC_GSS_SVC_PRIVACY: |
1151 | default: | 1164 | default: |