1*c2c66affSColin Finck /* NFSv4.1 client for Windows
2*c2c66affSColin Finck * Copyright � 2012 The Regents of the University of Michigan
3*c2c66affSColin Finck *
4*c2c66affSColin Finck * Olga Kornievskaia <aglo@umich.edu>
5*c2c66affSColin Finck * Casey Bodley <cbodley@umich.edu>
6*c2c66affSColin Finck *
7*c2c66affSColin Finck * This library is free software; you can redistribute it and/or modify it
8*c2c66affSColin Finck * under the terms of the GNU Lesser General Public License as published by
9*c2c66affSColin Finck * the Free Software Foundation; either version 2.1 of the License, or (at
10*c2c66affSColin Finck * your option) any later version.
11*c2c66affSColin Finck *
12*c2c66affSColin Finck * This library is distributed in the hope that it will be useful, but
13*c2c66affSColin Finck * without any warranty; without even the implied warranty of merchantability
14*c2c66affSColin Finck * or fitness for a particular purpose. See the GNU Lesser General Public
15*c2c66affSColin Finck * License for more details.
16*c2c66affSColin Finck *
17*c2c66affSColin Finck * You should have received a copy of the GNU Lesser General Public License
18*c2c66affSColin Finck * along with this library; if not, write to the Free Software Foundation,
19*c2c66affSColin Finck * Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20*c2c66affSColin Finck */
21*c2c66affSColin Finck
22*c2c66affSColin Finck #include <wintirpc.h>
23*c2c66affSColin Finck #include <stdio.h>
24*c2c66affSColin Finck #include <stdlib.h>
25*c2c66affSColin Finck #include <stdarg.h>
26*c2c66affSColin Finck //#include <rpc/types.h>
27*c2c66affSColin Finck #include <rpc/xdr.h>
28*c2c66affSColin Finck #include <rpc/auth.h>
29*c2c66affSColin Finck #include <rpc/auth_sspi.h>
30*c2c66affSColin Finck #include <rpc/rpc.h>
31*c2c66affSColin Finck #include <security.h>
32*c2c66affSColin Finck
33*c2c66affSColin Finck bool_t
xdr_rpc_sspi_cred(XDR * xdrs,struct rpc_sspi_cred * p)34*c2c66affSColin Finck xdr_rpc_sspi_cred(XDR *xdrs, struct rpc_sspi_cred *p)
35*c2c66affSColin Finck {
36*c2c66affSColin Finck bool_t xdr_stat;
37*c2c66affSColin Finck
38*c2c66affSColin Finck xdr_stat = (xdr_u_int(xdrs, &p->gc_v) &&
39*c2c66affSColin Finck xdr_enum(xdrs, (enum_t *)&p->gc_proc) &&
40*c2c66affSColin Finck xdr_u_int(xdrs, &p->gc_seq) &&
41*c2c66affSColin Finck xdr_enum(xdrs, (enum_t *)&p->gc_svc) &&
42*c2c66affSColin Finck xdr_bytes(xdrs, (char **)&p->gc_ctx.value,
43*c2c66affSColin Finck (u_int *)&p->gc_ctx.length, MAX_AUTH_BYTES));
44*c2c66affSColin Finck
45*c2c66affSColin Finck log_debug("xdr_rpc_gss_cred: %s %s "
46*c2c66affSColin Finck "(v %d, proc %d, seq %d, svc %d, ctx %p:%d)",
47*c2c66affSColin Finck (xdrs->x_op == XDR_ENCODE) ? "encode" : "decode",
48*c2c66affSColin Finck (xdr_stat == TRUE) ? "success" : "failure",
49*c2c66affSColin Finck p->gc_v, p->gc_proc, p->gc_seq, p->gc_svc,
50*c2c66affSColin Finck p->gc_ctx.value, p->gc_ctx.length);
51*c2c66affSColin Finck
52*c2c66affSColin Finck return (xdr_stat);
53*c2c66affSColin Finck }
54*c2c66affSColin Finck
55*c2c66affSColin Finck bool_t
xdr_rpc_sspi_init_args(XDR * xdrs,sspi_buffer_desc * p)56*c2c66affSColin Finck xdr_rpc_sspi_init_args(XDR *xdrs, sspi_buffer_desc *p)
57*c2c66affSColin Finck {
58*c2c66affSColin Finck bool_t xdr_stat;
59*c2c66affSColin Finck
60*c2c66affSColin Finck xdr_stat = xdr_bytes(xdrs, (char **)&p->value,
61*c2c66affSColin Finck (u_int *)&p->length, (u_int)(-1));
62*c2c66affSColin Finck
63*c2c66affSColin Finck log_debug("xdr_rpc_gss_init_args: %s %s (token %p:%d)",
64*c2c66affSColin Finck (xdrs->x_op == XDR_ENCODE) ? "encode" : "decode",
65*c2c66affSColin Finck (xdr_stat == TRUE) ? "success" : "failure",
66*c2c66affSColin Finck p->value, p->length);
67*c2c66affSColin Finck
68*c2c66affSColin Finck return (xdr_stat);
69*c2c66affSColin Finck }
70*c2c66affSColin Finck
71*c2c66affSColin Finck bool_t
xdr_rpc_sspi_init_res(XDR * xdrs,struct rpc_sspi_init_res * p)72*c2c66affSColin Finck xdr_rpc_sspi_init_res(XDR *xdrs, struct rpc_sspi_init_res *p)
73*c2c66affSColin Finck {
74*c2c66affSColin Finck bool_t xdr_stat;
75*c2c66affSColin Finck
76*c2c66affSColin Finck xdr_stat = (xdr_bytes(xdrs, (char **)&p->gr_ctx.value,
77*c2c66affSColin Finck (u_int *)&p->gr_ctx.length, MAX_NETOBJ_SZ) &&
78*c2c66affSColin Finck xdr_u_int(xdrs, &p->gr_major) &&
79*c2c66affSColin Finck xdr_u_int(xdrs, &p->gr_minor) &&
80*c2c66affSColin Finck xdr_u_int(xdrs, &p->gr_win) &&
81*c2c66affSColin Finck xdr_bytes(xdrs, (char **)&p->gr_token.value,
82*c2c66affSColin Finck (u_int *)&p->gr_token.length, (u_int)(-1)));
83*c2c66affSColin Finck
84*c2c66affSColin Finck log_debug("xdr_rpc_gss_init_res %s %s "
85*c2c66affSColin Finck "(ctx %p:%d, maj %d, min %d, win %d, token %p:%d)",
86*c2c66affSColin Finck (xdrs->x_op == XDR_ENCODE) ? "encode" : "decode",
87*c2c66affSColin Finck (xdr_stat == TRUE) ? "success" : "failure",
88*c2c66affSColin Finck p->gr_ctx.value, p->gr_ctx.length,
89*c2c66affSColin Finck p->gr_major, p->gr_minor, p->gr_win,
90*c2c66affSColin Finck p->gr_token.value, p->gr_token.length);
91*c2c66affSColin Finck
92*c2c66affSColin Finck return (xdr_stat);
93*c2c66affSColin Finck }
94*c2c66affSColin Finck
95*c2c66affSColin Finck bool_t
xdr_rpc_sspi_wrap_data(XDR * xdrs,xdrproc_t xdr_func,caddr_t xdr_ptr,PCtxtHandle ctx,sspi_qop_t qop,rpc_sspi_svc_t svc,u_int seq)96*c2c66affSColin Finck xdr_rpc_sspi_wrap_data(XDR *xdrs, xdrproc_t xdr_func, caddr_t xdr_ptr,
97*c2c66affSColin Finck PCtxtHandle ctx, sspi_qop_t qop,
98*c2c66affSColin Finck rpc_sspi_svc_t svc, u_int seq)
99*c2c66affSColin Finck {
100*c2c66affSColin Finck sspi_buffer_desc databuf, wrapbuf;
101*c2c66affSColin Finck uint32_t maj_stat;
102*c2c66affSColin Finck int start, end, conf_state;
103*c2c66affSColin Finck bool_t xdr_stat;
104*c2c66affSColin Finck
105*c2c66affSColin Finck log_debug("in xdr_rpc_sspi_wrap_data()");
106*c2c66affSColin Finck
107*c2c66affSColin Finck /* Skip databody length. */
108*c2c66affSColin Finck start = XDR_GETPOS(xdrs);
109*c2c66affSColin Finck XDR_SETPOS(xdrs, start + 4);
110*c2c66affSColin Finck
111*c2c66affSColin Finck /* Marshal rpc_gss_data_t (sequence number + arguments). */
112*c2c66affSColin Finck if (!xdr_u_int(xdrs, &seq) || !(*xdr_func)(xdrs, xdr_ptr))
113*c2c66affSColin Finck return (FALSE);
114*c2c66affSColin Finck end = XDR_GETPOS(xdrs);
115*c2c66affSColin Finck
116*c2c66affSColin Finck /* Set databuf to marshalled rpc_gss_data_t. */
117*c2c66affSColin Finck databuf.length = end - start - 4;
118*c2c66affSColin Finck XDR_SETPOS(xdrs, start + 4);
119*c2c66affSColin Finck databuf.value = XDR_INLINE(xdrs, databuf.length);
120*c2c66affSColin Finck
121*c2c66affSColin Finck xdr_stat = FALSE;
122*c2c66affSColin Finck
123*c2c66affSColin Finck if (svc == RPCSEC_SSPI_SVC_INTEGRITY) {
124*c2c66affSColin Finck /* Marshal databody_integ length. */
125*c2c66affSColin Finck XDR_SETPOS(xdrs, start);
126*c2c66affSColin Finck if (!xdr_u_int(xdrs, (u_int *)&databuf.length))
127*c2c66affSColin Finck return (FALSE);
128*c2c66affSColin Finck
129*c2c66affSColin Finck /* Checksum rpc_gss_data_t. */
130*c2c66affSColin Finck #if 0
131*c2c66affSColin Finck maj_stat = gss_get_mic(&min_stat, ctx, qop,
132*c2c66affSColin Finck &databuf, &wrapbuf);
133*c2c66affSColin Finck #else
134*c2c66affSColin Finck maj_stat = sspi_get_mic(ctx, 0, seq, &databuf, &wrapbuf);
135*c2c66affSColin Finck #endif
136*c2c66affSColin Finck if (maj_stat != SEC_E_OK) {
137*c2c66affSColin Finck log_debug("xdr_rpc_sspi_wrap_data: sspi_get_mic failed with %x", maj_stat);
138*c2c66affSColin Finck return (FALSE);
139*c2c66affSColin Finck }
140*c2c66affSColin Finck /* Marshal checksum. */
141*c2c66affSColin Finck XDR_SETPOS(xdrs, end);
142*c2c66affSColin Finck xdr_stat = xdr_bytes(xdrs, (char **)&wrapbuf.value,
143*c2c66affSColin Finck (u_int *)&wrapbuf.length, (u_int)-1);
144*c2c66affSColin Finck #if 0
145*c2c66affSColin Finck gss_release_buffer(&min_stat, &wrapbuf);
146*c2c66affSColin Finck #else
147*c2c66affSColin Finck sspi_release_buffer(&wrapbuf);
148*c2c66affSColin Finck #endif
149*c2c66affSColin Finck }
150*c2c66affSColin Finck else if (svc == RPCSEC_SSPI_SVC_PRIVACY) {
151*c2c66affSColin Finck /* Encrypt rpc_gss_data_t. */
152*c2c66affSColin Finck #if 0
153*c2c66affSColin Finck maj_stat = gss_wrap(&min_stat, ctx, TRUE, qop, &databuf,
154*c2c66affSColin Finck &conf_state, &wrapbuf);
155*c2c66affSColin Finck #else
156*c2c66affSColin Finck maj_stat = sspi_wrap(ctx, 0, &databuf, &wrapbuf, &conf_state);
157*c2c66affSColin Finck #endif
158*c2c66affSColin Finck if (maj_stat != SEC_E_OK) {
159*c2c66affSColin Finck log_debug("xdr_rpc_sspi_wrap_data: sspi_wrap failed with %x", maj_stat);
160*c2c66affSColin Finck return (FALSE);
161*c2c66affSColin Finck }
162*c2c66affSColin Finck /* Marshal databody_priv. */
163*c2c66affSColin Finck XDR_SETPOS(xdrs, start);
164*c2c66affSColin Finck xdr_stat = xdr_bytes(xdrs, (char **)&wrapbuf.value,
165*c2c66affSColin Finck (u_int *)&wrapbuf.length, (u_int)-1);
166*c2c66affSColin Finck #if 0
167*c2c66affSColin Finck gss_release_buffer(&min_stat, &wrapbuf);
168*c2c66affSColin Finck #else
169*c2c66affSColin Finck sspi_release_buffer(&wrapbuf);
170*c2c66affSColin Finck #endif
171*c2c66affSColin Finck }
172*c2c66affSColin Finck return (xdr_stat);
173*c2c66affSColin Finck }
174*c2c66affSColin Finck
175*c2c66affSColin Finck bool_t
xdr_rpc_sspi_unwrap_data(XDR * xdrs,xdrproc_t xdr_func,caddr_t xdr_ptr,PCtxtHandle ctx,sspi_qop_t qop,rpc_sspi_svc_t svc,u_int seq)176*c2c66affSColin Finck xdr_rpc_sspi_unwrap_data(XDR *xdrs, xdrproc_t xdr_func, caddr_t xdr_ptr,
177*c2c66affSColin Finck PCtxtHandle ctx, sspi_qop_t qop,
178*c2c66affSColin Finck rpc_sspi_svc_t svc, u_int seq)
179*c2c66affSColin Finck {
180*c2c66affSColin Finck XDR tmpxdrs;
181*c2c66affSColin Finck sspi_buffer_desc databuf, wrapbuf;
182*c2c66affSColin Finck uint32_t maj_stat;
183*c2c66affSColin Finck u_int seq_num, qop_state;
184*c2c66affSColin Finck int conf_state;
185*c2c66affSColin Finck bool_t xdr_stat;
186*c2c66affSColin Finck
187*c2c66affSColin Finck log_debug("in xdr_rpc_sspi_unwrap_data()");
188*c2c66affSColin Finck
189*c2c66affSColin Finck if (xdr_func == (xdrproc_t)xdr_void || xdr_ptr == NULL)
190*c2c66affSColin Finck return (TRUE);
191*c2c66affSColin Finck
192*c2c66affSColin Finck memset(&databuf, 0, sizeof(databuf));
193*c2c66affSColin Finck memset(&wrapbuf, 0, sizeof(wrapbuf));
194*c2c66affSColin Finck
195*c2c66affSColin Finck if (svc == RPCSEC_SSPI_SVC_INTEGRITY) {
196*c2c66affSColin Finck /* Decode databody_integ. */
197*c2c66affSColin Finck if (!xdr_bytes(xdrs, (char **)&databuf.value, (u_int *)&databuf.length,
198*c2c66affSColin Finck (u_int)-1)) {
199*c2c66affSColin Finck log_debug("xdr_rpc_sspi_unwrap_data: xdr decode databody_integ failed");
200*c2c66affSColin Finck return (FALSE);
201*c2c66affSColin Finck }
202*c2c66affSColin Finck /* Decode checksum. */
203*c2c66affSColin Finck if (!xdr_bytes(xdrs, (char **)&wrapbuf.value, (u_int *)&wrapbuf.length,
204*c2c66affSColin Finck MAX_NETOBJ_SZ)) {
205*c2c66affSColin Finck #if 0
206*c2c66affSColin Finck gss_release_buffer(&min_stat, &databuf);
207*c2c66affSColin Finck #else
208*c2c66affSColin Finck sspi_release_buffer(&databuf);
209*c2c66affSColin Finck #endif
210*c2c66affSColin Finck log_debug("xdr_rpc_sspi_unwrap_data: xdr decode checksum failed");
211*c2c66affSColin Finck return (FALSE);
212*c2c66affSColin Finck }
213*c2c66affSColin Finck /* Verify checksum and QOP. */
214*c2c66affSColin Finck #if 0
215*c2c66affSColin Finck maj_stat = gss_verify_mic(&min_stat, ctx, &databuf,
216*c2c66affSColin Finck &wrapbuf, &qop_state);
217*c2c66affSColin Finck #else
218*c2c66affSColin Finck maj_stat = sspi_verify_mic(ctx, seq, &databuf, &wrapbuf, &qop_state);
219*c2c66affSColin Finck #endif
220*c2c66affSColin Finck #if 0
221*c2c66affSColin Finck gss_release_buffer(&min_stat, &wrapbuf);
222*c2c66affSColin Finck #else
223*c2c66affSColin Finck sspi_release_buffer(&wrapbuf);
224*c2c66affSColin Finck #endif
225*c2c66affSColin Finck
226*c2c66affSColin Finck if (maj_stat != SEC_E_OK) {
227*c2c66affSColin Finck #if 0
228*c2c66affSColin Finck gss_release_buffer(&min_stat, &databuf);
229*c2c66affSColin Finck #else
230*c2c66affSColin Finck sspi_release_buffer(&databuf);
231*c2c66affSColin Finck #endif
232*c2c66affSColin Finck log_debug("xdr_rpc_sspi_unwrap_data: sspi_verify_mic "
233*c2c66affSColin Finck "failed with %x", maj_stat);
234*c2c66affSColin Finck return (FALSE);
235*c2c66affSColin Finck }
236*c2c66affSColin Finck }
237*c2c66affSColin Finck else if (svc == RPCSEC_SSPI_SVC_PRIVACY) {
238*c2c66affSColin Finck /* Decode databody_priv. */
239*c2c66affSColin Finck if (!xdr_bytes(xdrs, (char **)&wrapbuf.value, (u_int *)&wrapbuf.length,
240*c2c66affSColin Finck (u_int)-1)) {
241*c2c66affSColin Finck log_debug("xdr_rpc_sspi_unwrap_data: xdr decode databody_priv failed");
242*c2c66affSColin Finck return (FALSE);
243*c2c66affSColin Finck }
244*c2c66affSColin Finck /* Decrypt databody. */
245*c2c66affSColin Finck #if 0
246*c2c66affSColin Finck maj_stat = gss_unwrap(&min_stat, ctx, &wrapbuf, &databuf,
247*c2c66affSColin Finck &conf_state, &qop_state);
248*c2c66affSColin Finck #else
249*c2c66affSColin Finck maj_stat = sspi_unwrap(ctx, seq, &wrapbuf, &databuf, &conf_state, &qop_state);
250*c2c66affSColin Finck #endif
251*c2c66affSColin Finck #if 0
252*c2c66affSColin Finck gss_release_buffer(&min_stat, &wrapbuf);
253*c2c66affSColin Finck #else
254*c2c66affSColin Finck sspi_release_buffer(&wrapbuf);
255*c2c66affSColin Finck #endif
256*c2c66affSColin Finck /* Verify encryption and QOP. */
257*c2c66affSColin Finck if (maj_stat != SEC_E_OK) {
258*c2c66affSColin Finck #if 0
259*c2c66affSColin Finck gss_release_buffer(&min_stat, &databuf);
260*c2c66affSColin Finck #else
261*c2c66affSColin Finck sspi_release_buffer(&databuf);
262*c2c66affSColin Finck #endif
263*c2c66affSColin Finck log_debug("xdr_rpc_sspi_unwrap_data: sspi_unwrap failed with %x", maj_stat);
264*c2c66affSColin Finck return (FALSE);
265*c2c66affSColin Finck }
266*c2c66affSColin Finck }
267*c2c66affSColin Finck /* Decode rpc_gss_data_t (sequence number + arguments). */
268*c2c66affSColin Finck xdrmem_create(&tmpxdrs, databuf.value, databuf.length, XDR_DECODE);
269*c2c66affSColin Finck xdr_stat = (xdr_u_int(&tmpxdrs, &seq_num) &&
270*c2c66affSColin Finck (*xdr_func)(&tmpxdrs, xdr_ptr));
271*c2c66affSColin Finck XDR_DESTROY(&tmpxdrs);
272*c2c66affSColin Finck #if 0
273*c2c66affSColin Finck gss_release_buffer(&min_stat, &databuf);
274*c2c66affSColin Finck #else
275*c2c66affSColin Finck sspi_release_buffer(&databuf);
276*c2c66affSColin Finck #endif
277*c2c66affSColin Finck /* Verify sequence number. */
278*c2c66affSColin Finck if (xdr_stat == TRUE && seq_num != seq) {
279*c2c66affSColin Finck log_debug("wrong sequence number in databody received %d expected %d",
280*c2c66affSColin Finck seq_num, seq);
281*c2c66affSColin Finck return (FALSE);
282*c2c66affSColin Finck }
283*c2c66affSColin Finck
284*c2c66affSColin Finck return (xdr_stat);
285*c2c66affSColin Finck }
286*c2c66affSColin Finck
287*c2c66affSColin Finck bool_t
xdr_rpc_sspi_data(XDR * xdrs,xdrproc_t xdr_func,caddr_t xdr_ptr,PCtxtHandle ctx,sspi_qop_t qop,rpc_sspi_svc_t svc,u_int seq)288*c2c66affSColin Finck xdr_rpc_sspi_data(XDR *xdrs, xdrproc_t xdr_func, caddr_t xdr_ptr,
289*c2c66affSColin Finck PCtxtHandle ctx, sspi_qop_t qop,
290*c2c66affSColin Finck rpc_sspi_svc_t svc, u_int seq)
291*c2c66affSColin Finck {
292*c2c66affSColin Finck switch (xdrs->x_op) {
293*c2c66affSColin Finck
294*c2c66affSColin Finck case XDR_ENCODE:
295*c2c66affSColin Finck return (xdr_rpc_sspi_wrap_data(xdrs, xdr_func, xdr_ptr,
296*c2c66affSColin Finck ctx, qop, svc, seq));
297*c2c66affSColin Finck case XDR_DECODE:
298*c2c66affSColin Finck return (xdr_rpc_sspi_unwrap_data(xdrs, xdr_func, xdr_ptr,
299*c2c66affSColin Finck ctx, qop, svc, seq));
300*c2c66affSColin Finck case XDR_FREE:
301*c2c66affSColin Finck return (TRUE);
302*c2c66affSColin Finck }
303*c2c66affSColin Finck return (FALSE);
304*c2c66affSColin Finck }
305