1 /* NFSv4.1 client for Windows 2 * Copyright � 2012 The Regents of the University of Michigan 3 * 4 * Olga Kornievskaia <aglo@umich.edu> 5 * Casey Bodley <cbodley@umich.edu> 6 * 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. 11 * 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. 16 * 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 20 */ 21 22 #include <wintirpc.h> 23 #include <stdio.h> 24 #include <stdlib.h> 25 #include <stdarg.h> 26 //#include <rpc/types.h> 27 #include <rpc/xdr.h> 28 #include <rpc/auth.h> 29 #include <rpc/auth_sspi.h> 30 #include <rpc/rpc.h> 31 #include <security.h> 32 33 bool_t 34 xdr_rpc_sspi_cred(XDR *xdrs, struct rpc_sspi_cred *p) 35 { 36 bool_t xdr_stat; 37 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)); 44 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); 51 52 return (xdr_stat); 53 } 54 55 bool_t 56 xdr_rpc_sspi_init_args(XDR *xdrs, sspi_buffer_desc *p) 57 { 58 bool_t xdr_stat; 59 60 xdr_stat = xdr_bytes(xdrs, (char **)&p->value, 61 (u_int *)&p->length, (u_int)(-1)); 62 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", 66 p->value, p->length); 67 68 return (xdr_stat); 69 } 70 71 bool_t 72 xdr_rpc_sspi_init_res(XDR *xdrs, struct rpc_sspi_init_res *p) 73 { 74 bool_t xdr_stat; 75 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))); 83 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); 91 92 return (xdr_stat); 93 } 94 95 bool_t 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) 99 { 100 sspi_buffer_desc databuf, wrapbuf; 101 uint32_t maj_stat; 102 int start, end, conf_state; 103 bool_t xdr_stat; 104 105 log_debug("in xdr_rpc_sspi_wrap_data()"); 106 107 /* Skip databody length. */ 108 start = XDR_GETPOS(xdrs); 109 XDR_SETPOS(xdrs, start + 4); 110 111 /* Marshal rpc_gss_data_t (sequence number + arguments). */ 112 if (!xdr_u_int(xdrs, &seq) || !(*xdr_func)(xdrs, xdr_ptr)) 113 return (FALSE); 114 end = XDR_GETPOS(xdrs); 115 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); 120 121 xdr_stat = FALSE; 122 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)) 127 return (FALSE); 128 129 /* Checksum rpc_gss_data_t. */ 130 #if 0 131 maj_stat = gss_get_mic(&min_stat, ctx, qop, 132 &databuf, &wrapbuf); 133 #else 134 maj_stat = sspi_get_mic(ctx, 0, seq, &databuf, &wrapbuf); 135 #endif 136 if (maj_stat != SEC_E_OK) { 137 log_debug("xdr_rpc_sspi_wrap_data: sspi_get_mic failed with %x", maj_stat); 138 return (FALSE); 139 } 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); 144 #if 0 145 gss_release_buffer(&min_stat, &wrapbuf); 146 #else 147 sspi_release_buffer(&wrapbuf); 148 #endif 149 } 150 else if (svc == RPCSEC_SSPI_SVC_PRIVACY) { 151 /* Encrypt rpc_gss_data_t. */ 152 #if 0 153 maj_stat = gss_wrap(&min_stat, ctx, TRUE, qop, &databuf, 154 &conf_state, &wrapbuf); 155 #else 156 maj_stat = sspi_wrap(ctx, 0, &databuf, &wrapbuf, &conf_state); 157 #endif 158 if (maj_stat != SEC_E_OK) { 159 log_debug("xdr_rpc_sspi_wrap_data: sspi_wrap failed with %x", maj_stat); 160 return (FALSE); 161 } 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); 166 #if 0 167 gss_release_buffer(&min_stat, &wrapbuf); 168 #else 169 sspi_release_buffer(&wrapbuf); 170 #endif 171 } 172 return (xdr_stat); 173 } 174 175 bool_t 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) 179 { 180 XDR tmpxdrs; 181 sspi_buffer_desc databuf, wrapbuf; 182 uint32_t maj_stat; 183 u_int seq_num, qop_state; 184 int conf_state; 185 bool_t xdr_stat; 186 187 log_debug("in xdr_rpc_sspi_unwrap_data()"); 188 189 if (xdr_func == (xdrproc_t)xdr_void || xdr_ptr == NULL) 190 return (TRUE); 191 192 memset(&databuf, 0, sizeof(databuf)); 193 memset(&wrapbuf, 0, sizeof(wrapbuf)); 194 195 if (svc == RPCSEC_SSPI_SVC_INTEGRITY) { 196 /* Decode databody_integ. */ 197 if (!xdr_bytes(xdrs, (char **)&databuf.value, (u_int *)&databuf.length, 198 (u_int)-1)) { 199 log_debug("xdr_rpc_sspi_unwrap_data: xdr decode databody_integ failed"); 200 return (FALSE); 201 } 202 /* Decode checksum. */ 203 if (!xdr_bytes(xdrs, (char **)&wrapbuf.value, (u_int *)&wrapbuf.length, 204 MAX_NETOBJ_SZ)) { 205 #if 0 206 gss_release_buffer(&min_stat, &databuf); 207 #else 208 sspi_release_buffer(&databuf); 209 #endif 210 log_debug("xdr_rpc_sspi_unwrap_data: xdr decode checksum failed"); 211 return (FALSE); 212 } 213 /* Verify checksum and QOP. */ 214 #if 0 215 maj_stat = gss_verify_mic(&min_stat, ctx, &databuf, 216 &wrapbuf, &qop_state); 217 #else 218 maj_stat = sspi_verify_mic(ctx, seq, &databuf, &wrapbuf, &qop_state); 219 #endif 220 #if 0 221 gss_release_buffer(&min_stat, &wrapbuf); 222 #else 223 sspi_release_buffer(&wrapbuf); 224 #endif 225 226 if (maj_stat != SEC_E_OK) { 227 #if 0 228 gss_release_buffer(&min_stat, &databuf); 229 #else 230 sspi_release_buffer(&databuf); 231 #endif 232 log_debug("xdr_rpc_sspi_unwrap_data: sspi_verify_mic " 233 "failed with %x", maj_stat); 234 return (FALSE); 235 } 236 } 237 else if (svc == RPCSEC_SSPI_SVC_PRIVACY) { 238 /* Decode databody_priv. */ 239 if (!xdr_bytes(xdrs, (char **)&wrapbuf.value, (u_int *)&wrapbuf.length, 240 (u_int)-1)) { 241 log_debug("xdr_rpc_sspi_unwrap_data: xdr decode databody_priv failed"); 242 return (FALSE); 243 } 244 /* Decrypt databody. */ 245 #if 0 246 maj_stat = gss_unwrap(&min_stat, ctx, &wrapbuf, &databuf, 247 &conf_state, &qop_state); 248 #else 249 maj_stat = sspi_unwrap(ctx, seq, &wrapbuf, &databuf, &conf_state, &qop_state); 250 #endif 251 #if 0 252 gss_release_buffer(&min_stat, &wrapbuf); 253 #else 254 sspi_release_buffer(&wrapbuf); 255 #endif 256 /* Verify encryption and QOP. */ 257 if (maj_stat != SEC_E_OK) { 258 #if 0 259 gss_release_buffer(&min_stat, &databuf); 260 #else 261 sspi_release_buffer(&databuf); 262 #endif 263 log_debug("xdr_rpc_sspi_unwrap_data: sspi_unwrap failed with %x", maj_stat); 264 return (FALSE); 265 } 266 } 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); 272 #if 0 273 gss_release_buffer(&min_stat, &databuf); 274 #else 275 sspi_release_buffer(&databuf); 276 #endif 277 /* Verify sequence number. */ 278 if (xdr_stat == TRUE && seq_num != seq) { 279 log_debug("wrong sequence number in databody received %d expected %d", 280 seq_num, seq); 281 return (FALSE); 282 } 283 284 return (xdr_stat); 285 } 286 287 bool_t 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) 291 { 292 switch (xdrs->x_op) { 293 294 case XDR_ENCODE: 295 return (xdr_rpc_sspi_wrap_data(xdrs, xdr_func, xdr_ptr, 296 ctx, qop, svc, seq)); 297 case XDR_DECODE: 298 return (xdr_rpc_sspi_unwrap_data(xdrs, xdr_func, xdr_ptr, 299 ctx, qop, svc, seq)); 300 case XDR_FREE: 301 return (TRUE); 302 } 303 return (FALSE); 304 } 305