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: |
