1 /* NFSv4.1 client for Windows
2 * Copyright © 2012 The Regents of the University of Michigan
4 * Olga Kornievskaia <aglo@umich.edu>
5 * Casey Bodley <cbodley@umich.edu>
7 * This library is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU Lesser General Public License as published by
9 * the Free Software Foundation; either version 2.1 of the License, or (at
10 * your option) any later version.
12 * This library is distributed in the hope that it will be useful, but
13 * without any warranty; without even the implied warranty of merchantability
14 * or fitness for a particular purpose. See the GNU Lesser General Public
15 * License for more details.
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with this library; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA
26 //#include <rpc/types.h>
29 #include <rpc/auth_sspi.h>
34 xdr_rpc_sspi_cred(XDR
*xdrs
, struct rpc_sspi_cred
*p
)
38 xdr_stat
= (xdr_u_int(xdrs
, &p
->gc_v
) &&
39 xdr_enum(xdrs
, (enum_t
*)&p
->gc_proc
) &&
40 xdr_u_int(xdrs
, &p
->gc_seq
) &&
41 xdr_enum(xdrs
, (enum_t
*)&p
->gc_svc
) &&
42 xdr_bytes(xdrs
, (char **)&p
->gc_ctx
.value
,
43 (u_int
*)&p
->gc_ctx
.length
, MAX_AUTH_BYTES
));
45 log_debug("xdr_rpc_gss_cred: %s %s "
46 "(v %d, proc %d, seq %d, svc %d, ctx %p:%d)",
47 (xdrs
->x_op
== XDR_ENCODE
) ? "encode" : "decode",
48 (xdr_stat
== TRUE
) ? "success" : "failure",
49 p
->gc_v
, p
->gc_proc
, p
->gc_seq
, p
->gc_svc
,
50 p
->gc_ctx
.value
, p
->gc_ctx
.length
);
56 xdr_rpc_sspi_init_args(XDR
*xdrs
, sspi_buffer_desc
*p
)
60 xdr_stat
= xdr_bytes(xdrs
, (char **)&p
->value
,
61 (u_int
*)&p
->length
, (u_int
)(-1));
63 log_debug("xdr_rpc_gss_init_args: %s %s (token %p:%d)",
64 (xdrs
->x_op
== XDR_ENCODE
) ? "encode" : "decode",
65 (xdr_stat
== TRUE
) ? "success" : "failure",
72 xdr_rpc_sspi_init_res(XDR
*xdrs
, struct rpc_sspi_init_res
*p
)
76 xdr_stat
= (xdr_bytes(xdrs
, (char **)&p
->gr_ctx
.value
,
77 (u_int
*)&p
->gr_ctx
.length
, MAX_NETOBJ_SZ
) &&
78 xdr_u_int(xdrs
, &p
->gr_major
) &&
79 xdr_u_int(xdrs
, &p
->gr_minor
) &&
80 xdr_u_int(xdrs
, &p
->gr_win
) &&
81 xdr_bytes(xdrs
, (char **)&p
->gr_token
.value
,
82 (u_int
*)&p
->gr_token
.length
, (u_int
)(-1)));
84 log_debug("xdr_rpc_gss_init_res %s %s "
85 "(ctx %p:%d, maj %d, min %d, win %d, token %p:%d)",
86 (xdrs
->x_op
== XDR_ENCODE
) ? "encode" : "decode",
87 (xdr_stat
== TRUE
) ? "success" : "failure",
88 p
->gr_ctx
.value
, p
->gr_ctx
.length
,
89 p
->gr_major
, p
->gr_minor
, p
->gr_win
,
90 p
->gr_token
.value
, p
->gr_token
.length
);
96 xdr_rpc_sspi_wrap_data(XDR
*xdrs
, xdrproc_t xdr_func
, caddr_t xdr_ptr
,
97 PCtxtHandle ctx
, sspi_qop_t qop
,
98 rpc_sspi_svc_t svc
, u_int seq
)
100 sspi_buffer_desc databuf
, wrapbuf
;
102 int start
, end
, conf_state
;
105 log_debug("in xdr_rpc_sspi_wrap_data()");
107 /* Skip databody length. */
108 start
= XDR_GETPOS(xdrs
);
109 XDR_SETPOS(xdrs
, start
+ 4);
111 /* Marshal rpc_gss_data_t (sequence number + arguments). */
112 if (!xdr_u_int(xdrs
, &seq
) || !(*xdr_func
)(xdrs
, xdr_ptr
))
114 end
= XDR_GETPOS(xdrs
);
116 /* Set databuf to marshalled rpc_gss_data_t. */
117 databuf
.length
= end
- start
- 4;
118 XDR_SETPOS(xdrs
, start
+ 4);
119 databuf
.value
= XDR_INLINE(xdrs
, databuf
.length
);
123 if (svc
== RPCSEC_SSPI_SVC_INTEGRITY
) {
124 /* Marshal databody_integ length. */
125 XDR_SETPOS(xdrs
, start
);
126 if (!xdr_u_int(xdrs
, (u_int
*)&databuf
.length
))
129 /* Checksum rpc_gss_data_t. */
131 maj_stat
= gss_get_mic(&min_stat
, ctx
, qop
,
134 maj_stat
= sspi_get_mic(ctx
, 0, seq
, &databuf
, &wrapbuf
);
136 if (maj_stat
!= SEC_E_OK
) {
137 log_debug("xdr_rpc_sspi_wrap_data: sspi_get_mic failed with %x", maj_stat
);
140 /* Marshal checksum. */
141 XDR_SETPOS(xdrs
, end
);
142 xdr_stat
= xdr_bytes(xdrs
, (char **)&wrapbuf
.value
,
143 (u_int
*)&wrapbuf
.length
, (u_int
)-1);
145 gss_release_buffer(&min_stat
, &wrapbuf
);
147 sspi_release_buffer(&wrapbuf
);
150 else if (svc
== RPCSEC_SSPI_SVC_PRIVACY
) {
151 /* Encrypt rpc_gss_data_t. */
153 maj_stat
= gss_wrap(&min_stat
, ctx
, TRUE
, qop
, &databuf
,
154 &conf_state
, &wrapbuf
);
156 maj_stat
= sspi_wrap(ctx
, 0, &databuf
, &wrapbuf
, &conf_state
);
158 if (maj_stat
!= SEC_E_OK
) {
159 log_debug("xdr_rpc_sspi_wrap_data: sspi_wrap failed with %x", maj_stat
);
162 /* Marshal databody_priv. */
163 XDR_SETPOS(xdrs
, start
);
164 xdr_stat
= xdr_bytes(xdrs
, (char **)&wrapbuf
.value
,
165 (u_int
*)&wrapbuf
.length
, (u_int
)-1);
167 gss_release_buffer(&min_stat
, &wrapbuf
);
169 sspi_release_buffer(&wrapbuf
);
176 xdr_rpc_sspi_unwrap_data(XDR
*xdrs
, xdrproc_t xdr_func
, caddr_t xdr_ptr
,
177 PCtxtHandle ctx
, sspi_qop_t qop
,
178 rpc_sspi_svc_t svc
, u_int seq
)
181 sspi_buffer_desc databuf
, wrapbuf
;
183 u_int seq_num
, qop_state
;
187 log_debug("in xdr_rpc_sspi_unwrap_data()");
189 if (xdr_func
== (xdrproc_t
)xdr_void
|| xdr_ptr
== NULL
)
192 memset(&databuf
, 0, sizeof(databuf
));
193 memset(&wrapbuf
, 0, sizeof(wrapbuf
));
195 if (svc
== RPCSEC_SSPI_SVC_INTEGRITY
) {
196 /* Decode databody_integ. */
197 if (!xdr_bytes(xdrs
, (char **)&databuf
.value
, (u_int
*)&databuf
.length
,
199 log_debug("xdr_rpc_sspi_unwrap_data: xdr decode databody_integ failed");
202 /* Decode checksum. */
203 if (!xdr_bytes(xdrs
, (char **)&wrapbuf
.value
, (u_int
*)&wrapbuf
.length
,
206 gss_release_buffer(&min_stat
, &databuf
);
208 sspi_release_buffer(&databuf
);
210 log_debug("xdr_rpc_sspi_unwrap_data: xdr decode checksum failed");
213 /* Verify checksum and QOP. */
215 maj_stat
= gss_verify_mic(&min_stat
, ctx
, &databuf
,
216 &wrapbuf
, &qop_state
);
218 maj_stat
= sspi_verify_mic(ctx
, seq
, &databuf
, &wrapbuf
, &qop_state
);
221 gss_release_buffer(&min_stat
, &wrapbuf
);
223 sspi_release_buffer(&wrapbuf
);
226 if (maj_stat
!= SEC_E_OK
) {
228 gss_release_buffer(&min_stat
, &databuf
);
230 sspi_release_buffer(&databuf
);
232 log_debug("xdr_rpc_sspi_unwrap_data: sspi_verify_mic "
233 "failed with %x", maj_stat
);
237 else if (svc
== RPCSEC_SSPI_SVC_PRIVACY
) {
238 /* Decode databody_priv. */
239 if (!xdr_bytes(xdrs
, (char **)&wrapbuf
.value
, (u_int
*)&wrapbuf
.length
,
241 log_debug("xdr_rpc_sspi_unwrap_data: xdr decode databody_priv failed");
244 /* Decrypt databody. */
246 maj_stat
= gss_unwrap(&min_stat
, ctx
, &wrapbuf
, &databuf
,
247 &conf_state
, &qop_state
);
249 maj_stat
= sspi_unwrap(ctx
, seq
, &wrapbuf
, &databuf
, &conf_state
, &qop_state
);
252 gss_release_buffer(&min_stat
, &wrapbuf
);
254 sspi_release_buffer(&wrapbuf
);
256 /* Verify encryption and QOP. */
257 if (maj_stat
!= SEC_E_OK
) {
259 gss_release_buffer(&min_stat
, &databuf
);
261 sspi_release_buffer(&databuf
);
263 log_debug("xdr_rpc_sspi_unwrap_data: sspi_unwrap failed with %x", maj_stat
);
267 /* Decode rpc_gss_data_t (sequence number + arguments). */
268 xdrmem_create(&tmpxdrs
, databuf
.value
, databuf
.length
, XDR_DECODE
);
269 xdr_stat
= (xdr_u_int(&tmpxdrs
, &seq_num
) &&
270 (*xdr_func
)(&tmpxdrs
, xdr_ptr
));
271 XDR_DESTROY(&tmpxdrs
);
273 gss_release_buffer(&min_stat
, &databuf
);
275 sspi_release_buffer(&databuf
);
277 /* Verify sequence number. */
278 if (xdr_stat
== TRUE
&& seq_num
!= seq
) {
279 log_debug("wrong sequence number in databody received %d expected %d",
288 xdr_rpc_sspi_data(XDR
*xdrs
, xdrproc_t xdr_func
, caddr_t xdr_ptr
,
289 PCtxtHandle ctx
, sspi_qop_t qop
,
290 rpc_sspi_svc_t svc
, u_int seq
)
292 switch (xdrs
->x_op
) {
295 return (xdr_rpc_sspi_wrap_data(xdrs
, xdr_func
, xdr_ptr
,
296 ctx
, qop
, svc
, seq
));
298 return (xdr_rpc_sspi_unwrap_data(xdrs
, xdr_func
, xdr_ptr
,
299 ctx
, qop
, svc
, seq
));