diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/sunrpc/auth_gss/gss_krb5_wrap.c | 2 | ||||
-rw-r--r-- | net/sunrpc/auth_gss/svcauth_gss.c | 10 | ||||
-rw-r--r-- | net/sunrpc/xdr.c | 41 |
3 files changed, 51 insertions, 2 deletions
diff --git a/net/sunrpc/auth_gss/gss_krb5_wrap.c b/net/sunrpc/auth_gss/gss_krb5_wrap.c index 107c4528654f..88edec929d73 100644 --- a/net/sunrpc/auth_gss/gss_krb5_wrap.c +++ b/net/sunrpc/auth_gss/gss_krb5_wrap.c | |||
@@ -574,6 +574,8 @@ gss_unwrap_kerberos_v2(struct krb5_ctx *kctx, int offset, struct xdr_buf *buf) | |||
574 | buf->head[0].iov_len -= GSS_KRB5_TOK_HDR_LEN + headskip; | 574 | buf->head[0].iov_len -= GSS_KRB5_TOK_HDR_LEN + headskip; |
575 | buf->len -= GSS_KRB5_TOK_HDR_LEN + headskip; | 575 | buf->len -= GSS_KRB5_TOK_HDR_LEN + headskip; |
576 | 576 | ||
577 | /* Trim off the checksum blob */ | ||
578 | xdr_buf_trim(buf, GSS_KRB5_TOK_HDR_LEN + tailskip); | ||
577 | return GSS_S_COMPLETE; | 579 | return GSS_S_COMPLETE; |
578 | } | 580 | } |
579 | 581 | ||
diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c index 73e957386600..a5b41e2ac25a 100644 --- a/net/sunrpc/auth_gss/svcauth_gss.c +++ b/net/sunrpc/auth_gss/svcauth_gss.c | |||
@@ -817,13 +817,17 @@ read_u32_from_xdr_buf(struct xdr_buf *buf, int base, u32 *obj) | |||
817 | * The server uses base of head iovec as read pointer, while the | 817 | * The server uses base of head iovec as read pointer, while the |
818 | * client uses separate pointer. */ | 818 | * client uses separate pointer. */ |
819 | static int | 819 | static int |
820 | unwrap_integ_data(struct xdr_buf *buf, u32 seq, struct gss_ctx *ctx) | 820 | unwrap_integ_data(struct svc_rqst *rqstp, struct xdr_buf *buf, u32 seq, struct gss_ctx *ctx) |
821 | { | 821 | { |
822 | int stat = -EINVAL; | 822 | int stat = -EINVAL; |
823 | u32 integ_len, maj_stat; | 823 | u32 integ_len, maj_stat; |
824 | struct xdr_netobj mic; | 824 | struct xdr_netobj mic; |
825 | struct xdr_buf integ_buf; | 825 | struct xdr_buf integ_buf; |
826 | 826 | ||
827 | /* Did we already verify the signature on the original pass through? */ | ||
828 | if (rqstp->rq_deferred) | ||
829 | return 0; | ||
830 | |||
827 | integ_len = svc_getnl(&buf->head[0]); | 831 | integ_len = svc_getnl(&buf->head[0]); |
828 | if (integ_len & 3) | 832 | if (integ_len & 3) |
829 | return stat; | 833 | return stat; |
@@ -846,6 +850,8 @@ unwrap_integ_data(struct xdr_buf *buf, u32 seq, struct gss_ctx *ctx) | |||
846 | goto out; | 850 | goto out; |
847 | if (svc_getnl(&buf->head[0]) != seq) | 851 | if (svc_getnl(&buf->head[0]) != seq) |
848 | goto out; | 852 | goto out; |
853 | /* trim off the mic at the end before returning */ | ||
854 | xdr_buf_trim(buf, mic.len + 4); | ||
849 | stat = 0; | 855 | stat = 0; |
850 | out: | 856 | out: |
851 | kfree(mic.data); | 857 | kfree(mic.data); |
@@ -1190,7 +1196,7 @@ svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp) | |||
1190 | /* placeholders for length and seq. number: */ | 1196 | /* placeholders for length and seq. number: */ |
1191 | svc_putnl(resv, 0); | 1197 | svc_putnl(resv, 0); |
1192 | svc_putnl(resv, 0); | 1198 | svc_putnl(resv, 0); |
1193 | if (unwrap_integ_data(&rqstp->rq_arg, | 1199 | if (unwrap_integ_data(rqstp, &rqstp->rq_arg, |
1194 | gc->gc_seq, rsci->mechctx)) | 1200 | gc->gc_seq, rsci->mechctx)) |
1195 | goto garbage_args; | 1201 | goto garbage_args; |
1196 | break; | 1202 | break; |
diff --git a/net/sunrpc/xdr.c b/net/sunrpc/xdr.c index 56055632f151..75edcfad6e26 100644 --- a/net/sunrpc/xdr.c +++ b/net/sunrpc/xdr.c | |||
@@ -879,6 +879,47 @@ xdr_buf_subsegment(struct xdr_buf *buf, struct xdr_buf *subbuf, | |||
879 | } | 879 | } |
880 | EXPORT_SYMBOL_GPL(xdr_buf_subsegment); | 880 | EXPORT_SYMBOL_GPL(xdr_buf_subsegment); |
881 | 881 | ||
882 | /** | ||
883 | * xdr_buf_trim - lop at most "len" bytes off the end of "buf" | ||
884 | * @buf: buf to be trimmed | ||
885 | * @len: number of bytes to reduce "buf" by | ||
886 | * | ||
887 | * Trim an xdr_buf by the given number of bytes by fixing up the lengths. Note | ||
888 | * that it's possible that we'll trim less than that amount if the xdr_buf is | ||
889 | * too small, or if (for instance) it's all in the head and the parser has | ||
890 | * already read too far into it. | ||
891 | */ | ||
892 | void xdr_buf_trim(struct xdr_buf *buf, unsigned int len) | ||
893 | { | ||
894 | size_t cur; | ||
895 | unsigned int trim = len; | ||
896 | |||
897 | if (buf->tail[0].iov_len) { | ||
898 | cur = min_t(size_t, buf->tail[0].iov_len, trim); | ||
899 | buf->tail[0].iov_len -= cur; | ||
900 | trim -= cur; | ||
901 | if (!trim) | ||
902 | goto fix_len; | ||
903 | } | ||
904 | |||
905 | if (buf->page_len) { | ||
906 | cur = min_t(unsigned int, buf->page_len, trim); | ||
907 | buf->page_len -= cur; | ||
908 | trim -= cur; | ||
909 | if (!trim) | ||
910 | goto fix_len; | ||
911 | } | ||
912 | |||
913 | if (buf->head[0].iov_len) { | ||
914 | cur = min_t(size_t, buf->head[0].iov_len, trim); | ||
915 | buf->head[0].iov_len -= cur; | ||
916 | trim -= cur; | ||
917 | } | ||
918 | fix_len: | ||
919 | buf->len -= (len - trim); | ||
920 | } | ||
921 | EXPORT_SYMBOL_GPL(xdr_buf_trim); | ||
922 | |||
882 | static void __read_bytes_from_xdr_buf(struct xdr_buf *subbuf, void *obj, unsigned int len) | 923 | static void __read_bytes_from_xdr_buf(struct xdr_buf *subbuf, void *obj, unsigned int len) |
883 | { | 924 | { |
884 | unsigned int this_len; | 925 | unsigned int this_len; |