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 <unistd.h> 26 #include <string.h> 27 #include <errno.h> 28 #include <rpc/types.h> 29 #include <rpc/xdr.h> 30 #include <rpc/auth.h> 31 #include <rpc/auth_sspi.h> 32 #include <rpc/clnt.h> 33 34 static void authsspi_nextverf(AUTH *auth); 35 static bool_t authsspi_marshal(AUTH *auth, XDR *xdrs, u_int *seq); 36 static bool_t authsspi_refresh(AUTH *auth, void *); 37 static bool_t authsspi_validate(AUTH *auth, struct opaque_auth *verf, u_int seq); 38 static void authsspi_destroy(AUTH *auth); 39 static void authsspi_destroy_context(AUTH *auth); 40 static bool_t authsspi_wrap(AUTH *auth, XDR *xdrs, xdrproc_t xdr_func, caddr_t xdr_ptr); 41 static bool_t authsspi_unwrap(AUTH *auth, XDR *xdrs, xdrproc_t xdr_func, caddr_t xdr_ptr, u_int seq); 42 43 static struct auth_ops authsspi_ops = { 44 authsspi_nextverf, 45 authsspi_marshal, 46 authsspi_validate, 47 authsspi_refresh, 48 authsspi_destroy, 49 authsspi_wrap, 50 authsspi_unwrap 51 }; 52 53 struct rpc_sspi_data { 54 bool_t established; /* context established */ 55 bool_t inprogress; 56 sspi_buffer_desc gc_wire_verf; /* save GSS_S_COMPLETE NULL RPC verfier 57 * to process at end of context negotiation*/ 58 CLIENT *clnt; /* client handle */ 59 sspi_name_t name; /* service name */ 60 struct rpc_sspi_sec *sec; /* security tuple */ 61 CtxtHandle ctx; /* context id */ 62 struct rpc_sspi_cred gc; /* client credentials */ 63 u_int win; /* sequence window */ 64 TimeStamp expiry; 65 }; 66 67 #define AUTH_PRIVATE(auth) ((struct rpc_sspi_data *)auth->ah_private) 68 69 static struct timeval AUTH_TIMEOUT = { 25, 0 }; 70 void print_rpc_gss_sec(struct rpc_sspi_sec *ptr); 71 void print_negotiated_attrs(PCtxtHandle ctx); 72 73 AUTH * 74 authsspi_create(CLIENT *clnt, sspi_name_t name, struct rpc_sspi_sec *sec) 75 { 76 AUTH *auth, *save_auth; 77 struct rpc_sspi_data *gd; 78 79 log_debug("in authgss_create()"); 80 81 memset(&rpc_createerr, 0, sizeof(rpc_createerr)); 82 83 if ((auth = calloc(sizeof(*auth), 1)) == NULL) { 84 rpc_createerr.cf_stat = RPC_SYSTEMERROR; 85 rpc_createerr.cf_error.re_errno = ENOMEM; 86 return (NULL); 87 } 88 if ((gd = calloc(sizeof(*gd), 1)) == NULL) { 89 rpc_createerr.cf_stat = RPC_SYSTEMERROR; 90 rpc_createerr.cf_error.re_errno = ENOMEM; 91 free(auth); 92 return (NULL); 93 } 94 95 #if 0 96 if (name != SSPI_C_NO_NAME) { 97 if (gss_duplicate_name(&min_stat, name, &gd->name) 98 != GSS_S_COMPLETE) { 99 rpc_createerr.cf_stat = RPC_SYSTEMERROR; 100 rpc_createerr.cf_error.re_errno = ENOMEM; 101 free(auth); 102 return (NULL); 103 } 104 } 105 else 106 #else 107 gd->name = strdup(name); 108 #endif 109 110 gd->clnt = clnt; 111 SecInvalidateHandle(&gd->ctx); 112 gd->sec = sec; 113 114 gd->gc.gc_v = RPCSEC_SSPI_VERSION; 115 gd->gc.gc_proc = RPCSEC_SSPI_INIT; 116 gd->gc.gc_svc = gd->sec->svc; 117 118 auth->ah_ops = &authsspi_ops; 119 auth->ah_private = (caddr_t)gd; 120 121 save_auth = clnt->cl_auth; 122 clnt->cl_auth = auth; 123 124 if (!authsspi_refresh(auth, NULL)) 125 auth = NULL; 126 127 clnt->cl_auth = save_auth; 128 129 return (auth); 130 } 131 132 AUTH * 133 authsspi_create_default(CLIENT *clnt, char *service, int svc) 134 { 135 AUTH *auth = NULL; 136 uint32_t maj_stat = 0; 137 sspi_buffer_desc sname; 138 sspi_name_t name = SSPI_C_NO_NAME; 139 unsigned char sec_pkg_name[] = "Kerberos"; 140 struct rpc_sspi_sec *sec; 141 142 log_debug("in authgss_create_default() for %s", service); 143 144 sname.value = service; 145 sname.length = (int)strlen(service); 146 #if 0 147 maj_stat = gss_import_name(&min_stat, &sname, 148 (gss_OID)GSS_C_NT_HOSTBASED_SERVICE, 149 &name); 150 #else 151 maj_stat = sspi_import_name(&sname, &name); 152 #endif 153 if (maj_stat != SEC_E_OK) { 154 log_debug("authgss_create_default: sspi_import_name failed with %x", maj_stat); 155 return (NULL); 156 } 157 sec = calloc(1, sizeof(struct rpc_sspi_sec)); 158 if (sec == NULL) 159 goto out_err; 160 sec->svc = svc; 161 // Let's acquire creds here for now 162 maj_stat = AcquireCredentialsHandleA(NULL, sec_pkg_name, SECPKG_CRED_BOTH, 163 NULL, NULL, NULL, NULL, &sec->cred, &sec->expiry); 164 if (maj_stat != SEC_E_OK) { 165 log_debug("authgss_create_default: AcquireCredentialsHandleA failed with %x", maj_stat); 166 free(sec); 167 goto out; 168 } 169 170 auth = authsspi_create(clnt, name, sec); 171 if (auth == NULL) 172 goto out_free_sec; 173 174 out: 175 if (name != SSPI_C_NO_NAME) { 176 #if 0 177 gss_release_name(&min_stat, &name); 178 #else 179 free(name); 180 #endif 181 } 182 183 return (auth); 184 out_free_sec: 185 if (rpc_createerr.cf_error.re_errno == ENOMEM) { 186 FreeCredentialsHandle(&sec->cred); 187 free(sec); 188 } 189 out_err: 190 rpc_createerr.cf_stat = RPC_SYSTEMERROR; 191 rpc_createerr.cf_error.re_errno = ENOMEM; 192 goto out; 193 } 194 195 static void 196 authsspi_nextverf(AUTH *auth) 197 { 198 log_debug("in authgss_nextverf()"); 199 /* no action necessary */ 200 } 201 202 static bool_t 203 authsspi_marshal(AUTH *auth, XDR *xdrs, u_int *seq) 204 { 205 XDR tmpxdrs; 206 char tmp[MAX_AUTH_BYTES]; 207 struct rpc_sspi_data *gd; 208 sspi_buffer_desc rpcbuf, checksum; 209 uint32_t maj_stat; 210 bool_t xdr_stat; 211 212 log_debug("in authgss_marshal()"); 213 214 gd = AUTH_PRIVATE(auth); 215 216 if (gd->established) { 217 gd->gc.gc_seq++; 218 *seq = gd->gc.gc_seq; 219 } 220 221 xdrmem_create(&tmpxdrs, tmp, sizeof(tmp), XDR_ENCODE); 222 223 if (!xdr_rpc_sspi_cred(&tmpxdrs, &gd->gc)) { 224 log_debug("authsspi_marshal: xdr_rpc_sspi_cred failed"); 225 XDR_DESTROY(&tmpxdrs); 226 return (FALSE); 227 } 228 auth->ah_cred.oa_flavor = RPCSEC_GSS; 229 auth->ah_cred.oa_base = tmp; 230 auth->ah_cred.oa_length = XDR_GETPOS(&tmpxdrs); 231 232 XDR_DESTROY(&tmpxdrs); 233 234 if (!xdr_opaque_auth(xdrs, &auth->ah_cred)) { 235 log_debug("authsspi_marshal: failed to xdr GSS CRED"); 236 return (FALSE); 237 } 238 if (gd->gc.gc_proc == RPCSEC_SSPI_INIT || 239 gd->gc.gc_proc == RPCSEC_SSPI_CONTINUE_INIT) { 240 return (xdr_opaque_auth(xdrs, &_null_auth)); 241 } 242 /* Checksum serialized RPC header, up to and including credential. */ 243 rpcbuf.length = XDR_GETPOS(xdrs) - 4; 244 //XDR_SETPOS(xdrs, 0); 245 //rpcbuf.value = XDR_INLINE(xdrs, rpcbuf.length); 246 rpcbuf.value = xdrrec_getoutbase(xdrs) + 1; 247 248 #if 0 249 maj_stat = gss_get_mic(&min_stat, gd->ctx, gd->sec.qop, 250 &rpcbuf, &checksum); 251 #else 252 maj_stat = sspi_get_mic(&gd->ctx, 0, gd->gc.gc_seq, &rpcbuf, &checksum); 253 #endif 254 if (maj_stat != SEC_E_OK) { 255 log_debug("authsspi_marshal: sspi_get_mic failed with %x", maj_stat); 256 if (maj_stat == SEC_E_NO_AUTHENTICATING_AUTHORITY) { 257 gd->established = FALSE; 258 authsspi_destroy_context(auth); 259 } 260 return (FALSE); 261 } 262 auth->ah_verf.oa_flavor = RPCSEC_GSS; 263 auth->ah_verf.oa_base = checksum.value; 264 auth->ah_verf.oa_length = checksum.length; 265 xdr_stat = xdr_opaque_auth(xdrs, &auth->ah_verf); 266 #if 0 267 gss_release_buffer(&min_stat, &checksum); 268 #else 269 sspi_release_buffer(&checksum); 270 #endif 271 return (xdr_stat); 272 } 273 274 static bool_t 275 authsspi_validate(AUTH *auth, struct opaque_auth *verf, u_int seq) 276 { 277 struct rpc_sspi_data *gd; 278 u_int num, qop_state, cur_seq; 279 sspi_buffer_desc signbuf, checksum; 280 uint32_t maj_stat; 281 282 log_debug("in authgss_validate(for seq=%d)", seq); 283 284 gd = AUTH_PRIVATE(auth); 285 286 if (gd->established == FALSE) { 287 /* would like to do this only on NULL rpc -- 288 * gc->established is good enough. 289 * save the on the wire verifier to validate last 290 * INIT phase packet after decode if the major 291 * status is GSS_S_COMPLETE 292 */ 293 if ((gd->gc_wire_verf.value = 294 mem_alloc(verf->oa_length)) == NULL) { 295 return (FALSE); 296 } 297 memcpy(gd->gc_wire_verf.value, verf->oa_base, verf->oa_length); 298 gd->gc_wire_verf.length = verf->oa_length; 299 return (TRUE); 300 } 301 302 if (gd->gc.gc_proc == RPCSEC_SSPI_DESTROY) 303 return TRUE; 304 305 if (gd->gc.gc_proc == RPCSEC_SSPI_INIT || 306 gd->gc.gc_proc == RPCSEC_SSPI_CONTINUE_INIT) { 307 num = htonl(gd->win); 308 } 309 else { 310 if (seq == -1) { 311 num = htonl(gd->gc.gc_seq); 312 cur_seq = gd->gc.gc_seq; 313 } 314 else { 315 num = htonl(seq); 316 cur_seq = seq; 317 } 318 } 319 320 signbuf.value = # 321 signbuf.length = sizeof(num); 322 323 checksum.value = verf->oa_base; 324 checksum.length = verf->oa_length; 325 #if 0 326 maj_stat = gss_verify_mic(&min_stat, gd->ctx, &signbuf, 327 &checksum, &qop_state); 328 #else 329 maj_stat = sspi_verify_mic(&gd->ctx, cur_seq, &signbuf, &checksum, &qop_state); 330 #endif 331 if (maj_stat != SEC_E_OK) { 332 log_debug("authsspi_validate: VerifySignature failed with %x", maj_stat); 333 if (maj_stat == SEC_E_NO_AUTHENTICATING_AUTHORITY) { 334 gd->established = FALSE; 335 authsspi_destroy_context(auth); 336 } 337 return (FALSE); 338 } 339 return (TRUE); 340 } 341 342 static bool_t 343 authsspi_refresh(AUTH *auth, void *tmp) 344 { 345 struct rpc_sspi_data *gd; 346 struct rpc_sspi_init_res gr; 347 sspi_buffer_desc *recv_tokenp, send_token; 348 uint32_t maj_stat, call_stat, ret_flags, i; 349 unsigned long flags = 350 ISC_REQ_MUTUAL_AUTH|ISC_REQ_INTEGRITY|ISC_REQ_ALLOCATE_MEMORY; 351 SecBufferDesc out_desc, in_desc; 352 SecBuffer wtkn[1], rtkn[1]; 353 354 log_debug("in authgss_refresh()"); 355 356 gd = AUTH_PRIVATE(auth); 357 358 if ((gd->established && tmp == NULL) || gd->inprogress) 359 return (TRUE); 360 else if (tmp) { 361 log_debug("trying to refresh credentials\n"); 362 DeleteSecurityContext(&gd->ctx); 363 sspi_release_buffer(&gd->gc.gc_ctx); 364 SecInvalidateHandle(&gd->ctx); 365 mem_free(gd->gc_wire_verf.value, gd->gc_wire_verf.length); 366 gd->gc_wire_verf.value = NULL; 367 gd->gc_wire_verf.length = 0; 368 gd->established = FALSE; 369 gd->gc.gc_proc = RPCSEC_SSPI_INIT; 370 } 371 372 /* GSS context establishment loop. */ 373 memset(&gr, 0, sizeof(gr)); 374 recv_tokenp = SSPI_C_NO_BUFFER; 375 send_token.length = 0; 376 send_token.value = NULL; 377 378 print_rpc_gss_sec(gd->sec); 379 380 if (gd->sec->svc == RPCSEC_SSPI_SVC_PRIVACY) 381 flags |= ISC_REQ_CONFIDENTIALITY; 382 383 for (i=0;;i++) { 384 /* print the token we just received */ 385 if (recv_tokenp != SSPI_C_NO_BUFFER) { 386 log_debug("The token we just received (length %d):", 387 recv_tokenp->length); 388 log_hexdump(0, "", recv_tokenp->value, recv_tokenp->length, 0); 389 } 390 #if 0 391 maj_stat = gss_init_sec_context(&min_stat, 392 gd->sec.cred, 393 &gd->ctx, 394 gd->name, 395 gd->sec.mech, 396 gd->sec.req_flags, 397 0, /* time req */ 398 NULL, /* channel */ 399 recv_tokenp, 400 NULL, /* used mech */ 401 &send_token, 402 &ret_flags, 403 NULL); /* time rec */ 404 #else 405 gd->inprogress = TRUE; 406 out_desc.cBuffers = 1; 407 out_desc.pBuffers = wtkn; 408 out_desc.ulVersion = SECBUFFER_VERSION; 409 wtkn[0].BufferType = SECBUFFER_TOKEN; 410 wtkn[0].cbBuffer = send_token.length; 411 wtkn[0].pvBuffer = send_token.value; 412 log_debug("calling InitializeSecurityContextA for %s", gd->name); 413 414 maj_stat = InitializeSecurityContextA( 415 &gd->sec->cred, 416 ((i==0)?NULL:&gd->ctx), 417 gd->name, 418 flags, 419 0, 420 SECURITY_NATIVE_DREP, 421 ((i==0)?NULL:&in_desc), 422 0, 423 &gd->ctx, 424 &out_desc, 425 &ret_flags, 426 &gd->expiry); 427 #endif 428 if (recv_tokenp != SSPI_C_NO_BUFFER) { 429 #if 0 430 gss_release_buffer(&min_stat, &gr.gr_token); 431 #else 432 sspi_release_buffer(&gr.gr_token); 433 #endif 434 recv_tokenp = SSPI_C_NO_BUFFER; 435 } 436 if (maj_stat != SEC_E_OK && maj_stat != SEC_I_CONTINUE_NEEDED) { 437 log_debug("InitializeSecurityContext failed with %x", maj_stat); 438 break; 439 } 440 send_token.length = wtkn[0].cbBuffer; 441 send_token.value = wtkn[0].pvBuffer; 442 if (send_token.length != 0) { 443 memset(&gr, 0, sizeof(gr)); 444 445 /* print the token we are about to send */ 446 log_debug("The token being sent (length %d):", 447 send_token.length); 448 log_hexdump(0, "", send_token.value, send_token.length, 0); 449 450 call_stat = clnt_call(gd->clnt, NULLPROC, 451 (xdrproc_t)xdr_rpc_sspi_init_args, 452 &send_token, 453 (xdrproc_t)xdr_rpc_sspi_init_res, 454 (caddr_t)&gr, AUTH_TIMEOUT); 455 #if 0 456 gss_release_buffer(&min_stat, &send_token); 457 #else 458 // 11/29/2010 [aglo] can't call sspi_relase_buffer, causes heap 459 // corruption (later) to try and free the buffer directly. 460 FreeContextBuffer(send_token.value); 461 #endif 462 if (call_stat != RPC_SUCCESS || 463 (gr.gr_major != SEC_E_OK && 464 gr.gr_major != SEC_I_CONTINUE_NEEDED)) 465 break; 466 467 if (gr.gr_ctx.length != 0) { 468 #if 0 469 if (gd->gc.gc_ctx.value) 470 gss_release_buffer(&min_stat, 471 &gd->gc.gc_ctx); 472 #else 473 sspi_release_buffer(&gd->gc.gc_ctx); 474 #endif 475 gd->gc.gc_ctx = gr.gr_ctx; 476 } 477 if (gr.gr_token.length != 0) { 478 if (maj_stat != SEC_I_CONTINUE_NEEDED) 479 break; 480 recv_tokenp = &gr.gr_token; 481 in_desc.cBuffers = 1; 482 in_desc.pBuffers = rtkn; 483 in_desc.ulVersion = SECBUFFER_VERSION; 484 rtkn[0].BufferType = SECBUFFER_TOKEN; 485 rtkn[0].cbBuffer = gr.gr_token.length; 486 rtkn[0].pvBuffer = gr.gr_token.value; 487 } 488 gd->gc.gc_proc = RPCSEC_SSPI_CONTINUE_INIT; 489 } 490 491 /* GSS_S_COMPLETE => check gss header verifier, 492 * usually checked in gss_validate 493 */ 494 if (maj_stat == SEC_E_OK) { 495 sspi_buffer_desc bufin; 496 u_int seq, qop_state = 0; 497 498 print_negotiated_attrs(&gd->ctx); 499 500 seq = htonl(gr.gr_win); 501 bufin.value = (unsigned char *)&seq; 502 bufin.length = sizeof(seq); 503 #if 0 504 maj_stat = gss_verify_mic(&min_stat, gd->ctx, 505 &bufin, &bufout, &qop_state); 506 #else 507 maj_stat = sspi_verify_mic(&gd->ctx, 0, &bufin, &gd->gc_wire_verf, &qop_state); 508 #endif 509 if (maj_stat != SEC_E_OK) { 510 log_debug("authgss_refresh: sspi_verify_mic failed with %x", maj_stat); 511 if (maj_stat == SEC_E_NO_AUTHENTICATING_AUTHORITY) { 512 gd->established = FALSE; 513 authsspi_destroy_context(auth); 514 } 515 break; 516 } 517 gd->established = TRUE; 518 gd->inprogress = FALSE; 519 gd->gc.gc_proc = RPCSEC_SSPI_DATA; 520 gd->gc.gc_seq = 0; 521 gd->win = gr.gr_win; 522 log_debug("authgss_refresh: established GSS context"); 523 break; 524 } 525 } 526 /* End context negotiation loop. */ 527 if (gd->gc.gc_proc != RPCSEC_SSPI_DATA) { 528 if (gr.gr_token.length != 0) 529 #if 0 530 gss_release_buffer(&min_stat, &gr.gr_token); 531 #else 532 sspi_release_buffer(&gr.gr_token); 533 #endif 534 authsspi_destroy(auth); 535 auth = NULL; 536 rpc_createerr.cf_stat = RPC_AUTHERROR; 537 538 return (FALSE); 539 } 540 return (TRUE); 541 } 542 543 bool_t 544 authsspi_service(AUTH *auth, int svc) 545 { 546 struct rpc_sspi_data *gd; 547 548 log_debug("in authgss_service()"); 549 550 if (!auth) 551 return(FALSE); 552 gd = AUTH_PRIVATE(auth); 553 if (!gd || !gd->established) 554 return (FALSE); 555 gd->sec->svc = svc; 556 gd->gc.gc_svc = svc; 557 return (TRUE); 558 } 559 560 static void 561 authsspi_destroy_context(AUTH *auth) 562 { 563 struct rpc_sspi_data *gd; 564 565 log_debug("in authgss_destroy_context()"); 566 567 gd = AUTH_PRIVATE(auth); 568 if (gd == NULL) return; 569 570 if (SecIsValidHandle(&gd->ctx)) { 571 if (gd->established) { 572 gd->gc.gc_proc = RPCSEC_SSPI_DESTROY; 573 clnt_call(gd->clnt, NULLPROC, (xdrproc_t)xdr_void, NULL, 574 (xdrproc_t)xdr_void, NULL, AUTH_TIMEOUT); 575 DeleteSecurityContext(&gd->ctx); 576 } 577 sspi_release_buffer(&gd->gc.gc_ctx); 578 SecInvalidateHandle(&gd->ctx); 579 #if 0 580 gss_release_buffer(&min_stat, &gd->gc.gc_ctx); 581 /* XXX ANDROS check size of context - should be 8 */ 582 memset(&gd->gc.gc_ctx, 0, sizeof(gd->gc.gc_ctx)); 583 gss_delete_sec_context(&min_stat, &gd->ctx, NULL); 584 #endif 585 } 586 587 /* free saved wire verifier (if any) */ 588 mem_free(gd->gc_wire_verf.value, gd->gc_wire_verf.length); 589 gd->gc_wire_verf.value = NULL; 590 gd->gc_wire_verf.length = 0; 591 592 gd->established = FALSE; 593 } 594 595 static void 596 authsspi_destroy(AUTH *auth) 597 { 598 struct rpc_sspi_data *gd; 599 600 log_debug("in authgss_destroy()"); 601 602 gd = AUTH_PRIVATE(auth); 603 if (gd == NULL) return; 604 605 authsspi_destroy_context(auth); 606 607 #if 0 608 if (gd->name != SSPI_C_NO_NAME) 609 gss_release_name(&min_stat, &gd->name); 610 #else 611 free(gd->name); 612 #endif 613 FreeCredentialsHandle(&gd->sec->cred); 614 free(gd->sec); 615 free(gd); 616 free(auth); 617 } 618 619 bool_t 620 authsspi_wrap(AUTH *auth, XDR *xdrs, xdrproc_t xdr_func, caddr_t xdr_ptr) 621 { 622 struct rpc_sspi_data *gd; 623 624 log_debug("in authgss_wrap()"); 625 626 gd = AUTH_PRIVATE(auth); 627 628 if (!gd->established || gd->sec->svc == RPCSEC_SSPI_SVC_NONE) { 629 return ((*xdr_func)(xdrs, xdr_ptr)); 630 } 631 return (xdr_rpc_sspi_data(xdrs, xdr_func, xdr_ptr, 632 &gd->ctx, gd->sec->qop, 633 gd->sec->svc, gd->gc.gc_seq)); 634 } 635 636 bool_t 637 authsspi_unwrap(AUTH *auth, XDR *xdrs, xdrproc_t xdr_func, caddr_t xdr_ptr, u_int seq) 638 { 639 struct rpc_sspi_data *gd; 640 641 log_debug("in authgss_unwrap()"); 642 643 gd = AUTH_PRIVATE(auth); 644 645 if (!gd->established || gd->sec->svc == RPCSEC_SSPI_SVC_NONE) { 646 return ((*xdr_func)(xdrs, xdr_ptr)); 647 } 648 return (xdr_rpc_sspi_data(xdrs, xdr_func, xdr_ptr, 649 &gd->ctx, gd->sec->qop, 650 gd->sec->svc, seq)); 651 } 652 653 #ifdef __REACTOS__ 654 uint32_t sspi_get_mic(void *dummy, u_int qop, u_int seq, 655 sspi_buffer_desc *bufin, sspi_buffer_desc *bufout) 656 { 657 PCtxtHandle ctx = dummy; 658 #else 659 uint32_t sspi_get_mic(PCtxtHandle ctx, u_int qop, u_int seq, 660 sspi_buffer_desc *bufin, sspi_buffer_desc *bufout) 661 { 662 #endif 663 uint32_t maj_stat; 664 SecPkgContext_Sizes ContextSizes; 665 SecBufferDesc desc; 666 SecBuffer sec_tkn[2]; 667 668 log_hexdump(0, "sspi_get_mic: calculating checksum of", bufin->value, bufin->length, 0); 669 670 memset(&ContextSizes, 0, sizeof(ContextSizes)); 671 maj_stat = QueryContextAttributesA(ctx, SECPKG_ATTR_SIZES, &ContextSizes); 672 if (maj_stat != SEC_E_OK) return maj_stat; 673 674 if (ContextSizes.cbMaxSignature == 0) return SEC_E_INTERNAL_ERROR; 675 676 desc.cBuffers = 2; 677 desc.pBuffers = sec_tkn; 678 desc.ulVersion = SECBUFFER_VERSION; 679 sec_tkn[0].BufferType = SECBUFFER_DATA; 680 sec_tkn[0].cbBuffer = bufin->length; 681 sec_tkn[0].pvBuffer = bufin->value; 682 sec_tkn[1].BufferType = SECBUFFER_TOKEN; 683 sec_tkn[1].cbBuffer = ContextSizes.cbMaxSignature; 684 sec_tkn[1].pvBuffer = calloc(ContextSizes.cbMaxSignature, sizeof(char)); 685 if (sec_tkn[1].pvBuffer == NULL) return SEC_E_INSUFFICIENT_MEMORY; 686 687 maj_stat = MakeSignature(ctx, 0, &desc, seq); 688 if (maj_stat == SEC_E_OK) { 689 bufout->length = sec_tkn[1].cbBuffer; 690 bufout->value = sec_tkn[1].pvBuffer; 691 log_hexdump(0, "sspi_get_mic: verifier is", bufout->value, bufout->length, 0); 692 } else 693 free(sec_tkn[1].pvBuffer); 694 695 return maj_stat; 696 } 697 698 #ifndef __REACTOS__ 699 uint32_t sspi_verify_mic(PCtxtHandle ctx, u_int seq, sspi_buffer_desc *bufin, 700 sspi_buffer_desc *bufout, u_int *qop_state) 701 { 702 #else 703 uint32_t sspi_verify_mic(void *dummy, u_int seq, sspi_buffer_desc *bufin, 704 sspi_buffer_desc *bufout, u_int *qop_state) 705 { 706 PCtxtHandle ctx = dummy; 707 #endif 708 SecBufferDesc desc; 709 SecBuffer sec_tkn[2]; 710 711 desc.cBuffers = 2; 712 desc.pBuffers = sec_tkn; 713 desc.ulVersion = SECBUFFER_VERSION; 714 sec_tkn[0].BufferType = SECBUFFER_DATA; 715 sec_tkn[0].cbBuffer = bufin->length; 716 sec_tkn[0].pvBuffer = bufin->value; 717 sec_tkn[1].BufferType = SECBUFFER_TOKEN; 718 sec_tkn[1].cbBuffer = bufout->length; 719 sec_tkn[1].pvBuffer = bufout->value; 720 721 log_hexdump(0, "sspi_verify_mic: calculating checksum over", bufin->value, bufin->length, 0); 722 log_hexdump(0, "sspi_verify_mic: received checksum ", bufout->value, bufout->length, 0); 723 724 return VerifySignature(ctx, &desc, seq, qop_state); 725 } 726 727 void sspi_release_buffer(sspi_buffer_desc *buf) 728 { 729 if (buf->value) 730 free(buf->value); 731 buf->value = NULL; 732 buf->length = 0; 733 } 734 735 uint32_t sspi_import_name(sspi_buffer_desc *name_in, sspi_name_t *name_out) 736 { 737 *name_out = calloc(name_in->length + 5, sizeof(char)); 738 if (*name_out == NULL) 739 return SEC_E_INSUFFICIENT_MEMORY; 740 741 strcpy(*name_out, "nfs/"); 742 strncat(*name_out, name_in->value, name_in->length); 743 744 log_debug("imported service name is: %s\n", *name_out); 745 746 return SEC_E_OK; 747 } 748 749 #ifndef __REACTOS__ 750 uint32_t sspi_wrap(PCtxtHandle ctx, u_int seq, sspi_buffer_desc *bufin, 751 sspi_buffer_desc *bufout, u_int *conf_state) 752 { 753 #else 754 uint32_t sspi_wrap(void *dummy, u_int seq, sspi_buffer_desc *bufin, 755 sspi_buffer_desc *bufout, u_int *conf_state) 756 { 757 PCtxtHandle ctx = dummy; 758 #endif 759 uint32_t maj_stat; 760 SecBufferDesc BuffDesc; 761 SecBuffer SecBuff[3]; 762 ULONG ulQop = 0; 763 SecPkgContext_Sizes ContextSizes; 764 PBYTE p; 765 766 maj_stat = QueryContextAttributes(ctx, SECPKG_ATTR_SIZES, 767 &ContextSizes); 768 if (maj_stat != SEC_E_OK) 769 goto out; 770 771 BuffDesc.ulVersion = 0; 772 BuffDesc.cBuffers = 3; 773 BuffDesc.pBuffers = SecBuff; 774 775 SecBuff[0].cbBuffer = ContextSizes.cbSecurityTrailer; 776 SecBuff[0].BufferType = SECBUFFER_TOKEN; 777 SecBuff[0].pvBuffer = malloc(ContextSizes.cbSecurityTrailer); 778 779 SecBuff[1].cbBuffer = bufin->length; 780 SecBuff[1].BufferType = SECBUFFER_DATA; 781 SecBuff[1].pvBuffer = bufin->value; 782 log_hexdump(0, "plaintext:", bufin->value, bufin->length, 0); 783 784 SecBuff[2].cbBuffer = ContextSizes.cbBlockSize; 785 SecBuff[2].BufferType = SECBUFFER_PADDING; 786 SecBuff[2].pvBuffer = malloc(ContextSizes.cbBlockSize); 787 788 maj_stat = EncryptMessage(ctx, ulQop, &BuffDesc, seq); 789 if (maj_stat != SEC_E_OK) 790 goto out_free; 791 792 bufout->length = SecBuff[0].cbBuffer + SecBuff[1].cbBuffer + SecBuff[2].cbBuffer; 793 p = bufout->value = malloc(bufout->length); 794 memcpy(p, SecBuff[0].pvBuffer, SecBuff[0].cbBuffer); 795 p += SecBuff[0].cbBuffer; 796 memcpy(p, SecBuff[1].pvBuffer, SecBuff[1].cbBuffer); 797 p += SecBuff[1].cbBuffer; 798 memcpy(p, SecBuff[2].pvBuffer, SecBuff[2].cbBuffer); 799 out_free: 800 free(SecBuff[0].pvBuffer); 801 free(SecBuff[2].pvBuffer); 802 803 if (!maj_stat) 804 log_hexdump(0, "cipher:", bufout->value, bufout->length, 0); 805 out: 806 return maj_stat; 807 } 808 809 #ifndef __REACTOS__ 810 uint32_t sspi_unwrap(PCtxtHandle ctx, u_int seq, sspi_buffer_desc *bufin, 811 sspi_buffer_desc *bufout, u_int *conf_state, 812 u_int *qop_state) 813 { 814 #else 815 uint32_t sspi_unwrap(void *dummy, u_int seq, sspi_buffer_desc *bufin, 816 sspi_buffer_desc *bufout, u_int *conf_state, 817 u_int *qop_state) 818 { 819 PCtxtHandle ctx = dummy; 820 #endif 821 uint32_t maj_stat; 822 SecBufferDesc BuffDesc; 823 SecBuffer SecBuff[2]; 824 ULONG ulQop = 0; 825 826 BuffDesc.ulVersion = 0; 827 BuffDesc.cBuffers = 2; 828 BuffDesc.pBuffers = SecBuff; 829 830 SecBuff[0].cbBuffer = bufin->length; 831 SecBuff[0].BufferType = SECBUFFER_STREAM; 832 SecBuff[0].pvBuffer = bufin->value; 833 834 SecBuff[1].cbBuffer = 0; 835 SecBuff[1].BufferType = SECBUFFER_DATA; 836 SecBuff[1].pvBuffer = NULL; 837 838 log_hexdump(0, "cipher:", bufin->value, bufin->length, 0); 839 840 maj_stat = DecryptMessage(ctx, &BuffDesc, seq, &ulQop); 841 if (maj_stat != SEC_E_OK) return maj_stat; 842 843 bufout->length = SecBuff[1].cbBuffer; 844 bufout->value = malloc(bufout->length); 845 memcpy(bufout->value, SecBuff[1].pvBuffer, bufout->length); 846 847 log_hexdump(0, "data:", bufout->value, bufout->length, 0); 848 849 *conf_state = 1; 850 *qop_state = 0; 851 852 return SEC_E_OK; 853 } 854 855 /* useful as i add more mechanisms */ 856 #define DEBUG 857 #ifdef DEBUG 858 #define fd_out stdout 859 void print_rpc_gss_sec(struct rpc_sspi_sec *ptr) 860 { 861 int i; 862 char *p; 863 864 fprintf(fd_out, "rpc_gss_sec:"); 865 if(ptr->mech == NULL) 866 fprintf(fd_out, "NULL gss_OID mech"); 867 else { 868 fprintf(fd_out, " mechanism_OID: {"); 869 p = (char *)ptr->mech->elements; 870 for (i=0; i < ptr->mech->length; i++) 871 /* First byte of OIDs encoded to save a byte */ 872 if (i == 0) { 873 int first, second; 874 if (*p < 40) { 875 first = 0; 876 second = *p; 877 } 878 else if (40 <= *p && *p < 80) { 879 first = 1; 880 second = *p - 40; 881 } 882 else if (80 <= *p && *p < 127) { 883 first = 2; 884 second = *p - 80; 885 } 886 else { 887 /* Invalid value! */ 888 first = -1; 889 second = -1; 890 } 891 fprintf(fd_out, " %u %u", first, second); 892 p++; 893 } 894 else { 895 fprintf(fd_out, " %u", (unsigned char)*p++); 896 } 897 fprintf(fd_out, " }\n"); 898 } 899 fprintf(fd_out, " qop: %d\n", ptr->qop); 900 fprintf(fd_out, " service: %d\n", ptr->svc); 901 fprintf(fd_out, " cred: %p\n", ptr->cred); 902 } 903 904 void print_negotiated_attrs(PCtxtHandle ctx) 905 { 906 SecPkgContext_Sizes ContextSizes; 907 unsigned long flags; 908 uint32_t maj_stat; 909 910 maj_stat = QueryContextAttributesA(ctx, SECPKG_ATTR_FLAGS, &flags); 911 if (maj_stat != SEC_E_OK) return; 912 913 log_debug("negotiated flags %x\n", flags); 914 if (flags & ISC_REQ_DELEGATE) log_debug("ISC_REQ_DELEGATE"); 915 if (flags & ISC_REQ_MUTUAL_AUTH) log_debug("ISC_REQ_MUTUAL_AUTH"); 916 if (flags & ISC_REQ_REPLAY_DETECT) log_debug("ISC_REQ_REPLAY_DETECT"); 917 if (flags & ISC_REQ_SEQUENCE_DETECT) log_debug("ISC_REQ_SEQUENCE_DETECT"); 918 if (flags & ISC_REQ_CONFIDENTIALITY) log_debug("ISC_REQ_CONFIDENTIALITY"); 919 if (flags & ISC_REQ_USE_SESSION_KEY) log_debug("ISC_REQ_USE_SESSION_KEY"); 920 if (flags & ISC_REQ_PROMPT_FOR_CREDS) log_debug("ISC_REQ_PROMPT_FOR_CREDS"); 921 if (flags & ISC_REQ_USE_SUPPLIED_CREDS) log_debug("ISC_REQ_USE_SUPPLIED_CREDS"); 922 if (flags & ISC_REQ_ALLOCATE_MEMORY) log_debug("ISC_REQ_ALLOCATE_MEMORY"); 923 if (flags & ISC_REQ_USE_DCE_STYLE) log_debug("ISC_REQ_USE_DCE_STYLE"); 924 if (flags & ISC_REQ_DATAGRAM) log_debug("ISC_REQ_DATAGRAM"); 925 if (flags & ISC_REQ_CONNECTION) log_debug("ISC_REQ_CONNECTION"); 926 if (flags & ISC_REQ_CALL_LEVEL) log_debug("ISC_REQ_CALL_LEVEL"); 927 if (flags & ISC_REQ_FRAGMENT_SUPPLIED) log_debug("ISC_REQ_FRAGMENT_SUPPLIED"); 928 if (flags & ISC_REQ_EXTENDED_ERROR) log_debug("ISC_REQ_EXTENDED_ERROR"); 929 if (flags & ISC_REQ_STREAM) log_debug("ISC_REQ_STREAM"); 930 if (flags & ISC_REQ_INTEGRITY) log_debug("ISC_REQ_INTEGRITY"); 931 if (flags & ISC_REQ_IDENTIFY) log_debug("ISC_REQ_IDENTIFY"); 932 if (flags & ISC_REQ_NULL_SESSION) log_debug("ISC_REQ_NULL_SESSION"); 933 if (flags & ISC_REQ_MANUAL_CRED_VALIDATION) log_debug("ISC_REQ_MANUAL_CRED_VALIDATION"); 934 935 maj_stat = QueryContextAttributesA(ctx, SECPKG_ATTR_SIZES, &ContextSizes); 936 if (maj_stat != SEC_E_OK) return; 937 938 log_debug("signature size is %d\n", ContextSizes.cbMaxSignature); 939 940 } 941 942 void log_hexdump(bool_t on, const u_char *title, const u_char *buf, 943 int len, int offset) 944 { 945 int i, j, jm, c; 946 947 if (!on) return; 948 949 fprintf(fd_out, "%04x: %s (len=%d)\n", GetCurrentThreadId(), title, len); 950 for (i = 0; i < len; i += 0x10) { 951 fprintf(fd_out, " %04x: ", (u_int)(i + offset)); 952 jm = len - i; 953 jm = jm > 16 ? 16 : jm; 954 955 for (j = 0; j < jm; j++) { 956 if ((j % 2) == 1) 957 fprintf(fd_out, "%02x ", (u_int) buf[i+j]); 958 else 959 fprintf(fd_out, "%02x", (u_int) buf[i+j]); 960 } 961 for (; j < 16; j++) { 962 if ((j % 2) == 1) fprintf(fd_out, " "); 963 else fprintf(fd_out, " "); 964 } 965 fprintf(fd_out, " "); 966 967 for (j = 0; j < jm; j++) { 968 c = buf[i+j]; 969 c = isprint(c) ? c : '.'; 970 fprintf(fd_out, "%c", c); 971 } 972 fprintf(fd_out, "\n"); 973 } 974 fflush(fd_out); 975 } 976 977 void log_debug(const char *fmt, ...) 978 { 979 va_list ap; 980 981 va_start(ap, fmt); 982 fprintf(fd_out, "%04x: rpcsec_gss: ", GetCurrentThreadId()); 983 vfprintf(fd_out, fmt, ap); 984 fprintf(fd_out, "\n"); 985 fflush(fd_out); 986 va_end(ap); 987 } 988 #else 989 void print_rpc_gss_sec(struct rpc_sspi_sec *ptr) { return; } 990 void print_negotiated_flags(unsigned long flags) {return; } 991 void log_hexdump(bool_t on, const u_char *title, const u_char *buf, 992 int len, int offset) { return; } 993 void log_debug(const char *fmt, ...) { return; } 994 #endif 995