aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/sunrpc/auth_gss/svcauth_gss.c115
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
1075static int 1075static inline int
1076svcauth_gss_release(struct svc_rqst *rqstp) 1076svcauth_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);
1135out:
1136 stat = 0;
1137out_err:
1138 return stat;
1139}
1140
1141static int
1142svcauth_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: