|
71 | 71 | struct gss_svc_data {
|
72 | 72 | /* decoded gss client cred: */
|
73 | 73 | struct rpc_gss_wire_cred clcred;
|
74 |
| - /* save a pointer to the beginning of the encoded verifier, |
75 |
| - * for use in encryption/checksumming in svcauth_gss_release: */ |
76 |
| - __be32 *verf_start; |
| 74 | + u32 gsd_databody_offset; |
77 | 75 | struct rsc *rsci;
|
78 | 76 |
|
79 | 77 | /* for temporary results */
|
@@ -1595,7 +1593,7 @@ svcauth_gss_accept(struct svc_rqst *rqstp)
|
1595 | 1593 | if (!svcdata)
|
1596 | 1594 | goto auth_err;
|
1597 | 1595 | rqstp->rq_auth_data = svcdata;
|
1598 |
| - svcdata->verf_start = NULL; |
| 1596 | + svcdata->gsd_databody_offset = 0; |
1599 | 1597 | svcdata->rsci = NULL;
|
1600 | 1598 | gc = &svcdata->clcred;
|
1601 | 1599 |
|
@@ -1647,11 +1645,11 @@ svcauth_gss_accept(struct svc_rqst *rqstp)
|
1647 | 1645 | goto complete;
|
1648 | 1646 | case RPC_GSS_PROC_DATA:
|
1649 | 1647 | rqstp->rq_auth_stat = rpcsec_gsserr_ctxproblem;
|
1650 |
| - svcdata->verf_start = xdr_reserve_space(&rqstp->rq_res_stream, 0); |
1651 | 1648 | if (!svcauth_gss_encode_verf(rqstp, rsci->mechctx, gc->gc_seq))
|
1652 | 1649 | goto auth_err;
|
1653 | 1650 | if (!svcxdr_set_accept_stat(rqstp))
|
1654 | 1651 | goto auth_err;
|
| 1652 | + svcdata->gsd_databody_offset = xdr_stream_pos(&rqstp->rq_res_stream); |
1655 | 1653 | rqstp->rq_cred = rsci->cred;
|
1656 | 1654 | get_group_info(rsci->cred.cr_group_info);
|
1657 | 1655 | rqstp->rq_auth_stat = rpc_autherr_badcred;
|
@@ -1705,30 +1703,24 @@ svcauth_gss_accept(struct svc_rqst *rqstp)
|
1705 | 1703 | return ret;
|
1706 | 1704 | }
|
1707 | 1705 |
|
1708 |
| -static __be32 * |
| 1706 | +static u32 |
1709 | 1707 | svcauth_gss_prepare_to_wrap(struct svc_rqst *rqstp, struct gss_svc_data *gsd)
|
1710 | 1708 | {
|
1711 |
| - __be32 *p; |
1712 |
| - u32 verf_len; |
| 1709 | + u32 offset; |
1713 | 1710 |
|
1714 |
| - p = gsd->verf_start; |
1715 |
| - gsd->verf_start = NULL; |
| 1711 | + /* Release can be called twice, but we only wrap once. */ |
| 1712 | + offset = gsd->gsd_databody_offset; |
| 1713 | + gsd->gsd_databody_offset = 0; |
1716 | 1714 |
|
1717 | 1715 | /* AUTH_ERROR replies are not wrapped. */
|
1718 | 1716 | if (rqstp->rq_auth_stat != rpc_auth_ok)
|
1719 |
| - return NULL; |
1720 |
| - |
1721 |
| - /* Skip the verifier: */ |
1722 |
| - p += 1; |
1723 |
| - verf_len = ntohl(*p++); |
1724 |
| - p += XDR_QUADLEN(verf_len); |
| 1717 | + return 0; |
1725 | 1718 |
|
1726 | 1719 | /* Also don't wrap if the accept_stat is nonzero: */
|
1727 | 1720 | if (*rqstp->rq_accept_statp != rpc_success)
|
1728 |
| - return NULL; |
| 1721 | + return 0; |
1729 | 1722 |
|
1730 |
| - p++; |
1731 |
| - return p; |
| 1723 | + return offset; |
1732 | 1724 | }
|
1733 | 1725 |
|
1734 | 1726 | /*
|
@@ -1756,21 +1748,21 @@ static int svcauth_gss_wrap_integ(struct svc_rqst *rqstp)
|
1756 | 1748 | struct xdr_buf *buf = xdr->buf;
|
1757 | 1749 | struct xdr_buf databody_integ;
|
1758 | 1750 | struct xdr_netobj checksum;
|
1759 |
| - u32 offset, len, maj_stat; |
1760 |
| - __be32 *p; |
| 1751 | + u32 offset, maj_stat; |
1761 | 1752 |
|
1762 |
| - p = svcauth_gss_prepare_to_wrap(rqstp, gsd); |
1763 |
| - if (p == NULL) |
| 1753 | + offset = svcauth_gss_prepare_to_wrap(rqstp, gsd); |
| 1754 | + if (!offset) |
1764 | 1755 | goto out;
|
1765 | 1756 |
|
1766 |
| - offset = (u8 *)(p + 1) - (u8 *)buf->head[0].iov_base; |
1767 |
| - len = buf->len - offset; |
1768 |
| - if (xdr_buf_subsegment(buf, &databody_integ, offset, len)) |
| 1757 | + if (xdr_buf_subsegment(buf, &databody_integ, offset + XDR_UNIT, |
| 1758 | + buf->len - offset - XDR_UNIT)) |
1769 | 1759 | goto wrap_failed;
|
1770 | 1760 | /* Buffer space for these has already been reserved in
|
1771 | 1761 | * svcauth_gss_accept(). */
|
1772 |
| - *p++ = cpu_to_be32(len); |
1773 |
| - *p = cpu_to_be32(gc->gc_seq); |
| 1762 | + if (xdr_encode_word(buf, offset, databody_integ.len)) |
| 1763 | + goto wrap_failed; |
| 1764 | + if (xdr_encode_word(buf, offset + XDR_UNIT, gc->gc_seq)) |
| 1765 | + goto wrap_failed; |
1774 | 1766 |
|
1775 | 1767 | checksum.data = gsd->gsd_scratch;
|
1776 | 1768 | maj_stat = gss_get_mic(gsd->rsci->mechctx, &databody_integ, &checksum);
|
@@ -1817,17 +1809,19 @@ static int svcauth_gss_wrap_priv(struct svc_rqst *rqstp)
|
1817 | 1809 | struct kvec *head = buf->head;
|
1818 | 1810 | struct kvec *tail = buf->tail;
|
1819 | 1811 | u32 offset, pad, maj_stat;
|
1820 |
| - __be32 *p, *lenp; |
| 1812 | + __be32 *p; |
1821 | 1813 |
|
1822 |
| - p = svcauth_gss_prepare_to_wrap(rqstp, gsd); |
1823 |
| - if (p == NULL) |
| 1814 | + offset = svcauth_gss_prepare_to_wrap(rqstp, gsd); |
| 1815 | + if (!offset) |
1824 | 1816 | return 0;
|
1825 | 1817 |
|
1826 |
| - lenp = p++; |
1827 |
| - offset = (u8 *)p - (u8 *)head->iov_base; |
1828 |
| - /* Buffer space for this field has already been reserved |
1829 |
| - * in svcauth_gss_accept(). */ |
1830 |
| - *p = cpu_to_be32(gc->gc_seq); |
| 1818 | + /* |
| 1819 | + * Buffer space for this field has already been reserved |
| 1820 | + * in svcauth_gss_accept(). Note that the GSS sequence |
| 1821 | + * number is encrypted along with the RPC reply payload. |
| 1822 | + */ |
| 1823 | + if (xdr_encode_word(buf, offset + XDR_UNIT, gc->gc_seq)) |
| 1824 | + goto wrap_failed; |
1831 | 1825 |
|
1832 | 1826 | /*
|
1833 | 1827 | * If there is currently tail data, make sure there is
|
@@ -1863,12 +1857,15 @@ static int svcauth_gss_wrap_priv(struct svc_rqst *rqstp)
|
1863 | 1857 | tail->iov_len = 0;
|
1864 | 1858 | }
|
1865 | 1859 |
|
1866 |
| - maj_stat = gss_wrap(gsd->rsci->mechctx, offset, buf, buf->pages); |
| 1860 | + maj_stat = gss_wrap(gsd->rsci->mechctx, offset + XDR_UNIT, buf, |
| 1861 | + buf->pages); |
1867 | 1862 | if (maj_stat != GSS_S_COMPLETE)
|
1868 | 1863 | goto bad_wrap;
|
1869 | 1864 |
|
1870 |
| - *lenp = cpu_to_be32(buf->len - offset); |
1871 |
| - pad = xdr_pad_size(buf->len - offset); |
| 1865 | + /* Wrapping can change the size of databody_priv. */ |
| 1866 | + if (xdr_encode_word(buf, offset, buf->len - offset - XDR_UNIT)) |
| 1867 | + goto wrap_failed; |
| 1868 | + pad = xdr_pad_size(buf->len - offset - XDR_UNIT); |
1872 | 1869 | p = (__be32 *)(tail->iov_base + tail->iov_len);
|
1873 | 1870 | memset(p, 0, pad);
|
1874 | 1871 | tail->iov_len += pad;
|
@@ -1908,9 +1905,6 @@ svcauth_gss_release(struct svc_rqst *rqstp)
|
1908 | 1905 | gc = &gsd->clcred;
|
1909 | 1906 | if (gc->gc_proc != RPC_GSS_PROC_DATA)
|
1910 | 1907 | goto out;
|
1911 |
| - /* Release can be called twice, but we only wrap once. */ |
1912 |
| - if (gsd->verf_start == NULL) |
1913 |
| - goto out; |
1914 | 1908 |
|
1915 | 1909 | switch (gc->gc_svc) {
|
1916 | 1910 | case RPC_GSS_SVC_NONE:
|
|
0 commit comments