Changeset 745 for trunk/server/source4/librpc/rpc/dcerpc.c
- Timestamp:
- Nov 27, 2012, 4:43:17 PM (13 years ago)
- Location:
- trunk/server
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/server
- Property svn:mergeinfo changed
/vendor/current merged: 581,587,591,594,597,600,615,618,740
- Property svn:mergeinfo changed
-
trunk/server/source4/librpc/rpc/dcerpc.c
r414 r745 31 31 #include "auth/gensec/gensec.h" 32 32 #include "param/param.h" 33 #include "lib/util/tevent_ntstatus.h" 34 #include "librpc/rpc/rpc_common.h" 35 36 enum rpc_request_state { 37 RPC_REQUEST_QUEUED, 38 RPC_REQUEST_PENDING, 39 RPC_REQUEST_DONE 40 }; 41 42 /* 43 handle for an async dcerpc request 44 */ 45 struct rpc_request { 46 struct rpc_request *next, *prev; 47 struct dcerpc_pipe *p; 48 NTSTATUS status; 49 uint32_t call_id; 50 enum rpc_request_state state; 51 DATA_BLOB payload; 52 uint32_t flags; 53 uint32_t fault_code; 54 55 /* this is used to distinguish bind and alter_context requests 56 from normal requests */ 57 void (*recv_handler)(struct rpc_request *conn, 58 DATA_BLOB *blob, struct ncacn_packet *pkt); 59 60 const struct GUID *object; 61 uint16_t opnum; 62 DATA_BLOB request_data; 63 bool ignore_timeout; 64 65 /* use by the ndr level async recv call */ 66 struct { 67 const struct ndr_interface_table *table; 68 uint32_t opnum; 69 void *struct_ptr; 70 TALLOC_CTX *mem_ctx; 71 } ndr; 72 73 struct { 74 void (*callback)(struct rpc_request *); 75 void *private_data; 76 } async; 77 }; 33 78 34 79 _PUBLIC_ NTSTATUS dcerpc_init(struct loadparm_context *lp_ctx) … … 37 82 } 38 83 39 static void dcerpc_connection_dead(struct dcerpc_connection *conn, NTSTATUS status); 40 static void dcerpc_ship_next_request(struct dcerpc_connection *c); 84 static void dcerpc_connection_dead(struct dcecli_connection *conn, NTSTATUS status); 85 static void dcerpc_ship_next_request(struct dcecli_connection *c); 86 87 static struct rpc_request *dcerpc_request_send(struct dcerpc_pipe *p, 88 const struct GUID *object, 89 uint16_t opnum, 90 DATA_BLOB *stub_data); 91 static NTSTATUS dcerpc_request_recv(struct rpc_request *req, 92 TALLOC_CTX *mem_ctx, 93 DATA_BLOB *stub_data); 94 static NTSTATUS dcerpc_ndr_validate_in(struct dcecli_connection *c, 95 TALLOC_CTX *mem_ctx, 96 DATA_BLOB blob, 97 size_t struct_size, 98 ndr_push_flags_fn_t ndr_push, 99 ndr_pull_flags_fn_t ndr_pull); 100 static NTSTATUS dcerpc_ndr_validate_out(struct dcecli_connection *c, 101 struct ndr_pull *pull_in, 102 void *struct_ptr, 103 size_t struct_size, 104 ndr_push_flags_fn_t ndr_push, 105 ndr_pull_flags_fn_t ndr_pull, 106 ndr_print_function_t ndr_print); 41 107 42 108 /* destroy a dcerpc connection */ 43 static int dcerpc_connection_destructor(struct dce rpc_connection *conn)109 static int dcerpc_connection_destructor(struct dcecli_connection *conn) 44 110 { 45 111 if (conn->dead) { … … 55 121 the event context is optional 56 122 */ 57 static struct dcerpc_connection *dcerpc_connection_init(TALLOC_CTX *mem_ctx, 58 struct tevent_context *ev, 59 struct smb_iconv_convenience *ic) 60 { 61 struct dcerpc_connection *c; 62 63 c = talloc_zero(mem_ctx, struct dcerpc_connection); 123 static struct dcecli_connection *dcerpc_connection_init(TALLOC_CTX *mem_ctx, 124 struct tevent_context *ev) 125 { 126 struct dcecli_connection *c; 127 128 c = talloc_zero(mem_ctx, struct dcecli_connection); 64 129 if (!c) { 65 130 return NULL; 66 131 } 67 68 c->iconv_convenience = talloc_reference(c, ic);69 132 70 133 c->event_ctx = ev; … … 90 153 } 91 154 155 struct dcerpc_bh_state { 156 struct dcerpc_pipe *p; 157 }; 158 159 static bool dcerpc_bh_is_connected(struct dcerpc_binding_handle *h) 160 { 161 struct dcerpc_bh_state *hs = dcerpc_binding_handle_data(h, 162 struct dcerpc_bh_state); 163 164 if (!hs->p) { 165 return false; 166 } 167 168 return true; 169 } 170 171 static uint32_t dcerpc_bh_set_timeout(struct dcerpc_binding_handle *h, 172 uint32_t timeout) 173 { 174 struct dcerpc_bh_state *hs = dcerpc_binding_handle_data(h, 175 struct dcerpc_bh_state); 176 uint32_t old; 177 178 if (!hs->p) { 179 return DCERPC_REQUEST_TIMEOUT; 180 } 181 182 old = hs->p->request_timeout; 183 hs->p->request_timeout = timeout; 184 185 return old; 186 } 187 188 struct dcerpc_bh_raw_call_state { 189 struct dcerpc_binding_handle *h; 190 DATA_BLOB in_data; 191 DATA_BLOB out_data; 192 uint32_t out_flags; 193 }; 194 195 static void dcerpc_bh_raw_call_done(struct rpc_request *subreq); 196 197 static struct tevent_req *dcerpc_bh_raw_call_send(TALLOC_CTX *mem_ctx, 198 struct tevent_context *ev, 199 struct dcerpc_binding_handle *h, 200 const struct GUID *object, 201 uint32_t opnum, 202 uint32_t in_flags, 203 const uint8_t *in_data, 204 size_t in_length) 205 { 206 struct dcerpc_bh_state *hs = dcerpc_binding_handle_data(h, 207 struct dcerpc_bh_state); 208 struct tevent_req *req; 209 struct dcerpc_bh_raw_call_state *state; 210 bool ok; 211 struct rpc_request *subreq; 212 213 req = tevent_req_create(mem_ctx, &state, 214 struct dcerpc_bh_raw_call_state); 215 if (req == NULL) { 216 return NULL; 217 } 218 state->h = h; 219 state->in_data.data = discard_const_p(uint8_t, in_data); 220 state->in_data.length = in_length; 221 222 ok = dcerpc_bh_is_connected(h); 223 if (!ok) { 224 tevent_req_nterror(req, NT_STATUS_INVALID_CONNECTION); 225 return tevent_req_post(req, ev); 226 } 227 228 subreq = dcerpc_request_send(hs->p, 229 object, 230 opnum, 231 &state->in_data); 232 if (tevent_req_nomem(subreq, req)) { 233 return tevent_req_post(req, ev); 234 } 235 subreq->async.callback = dcerpc_bh_raw_call_done; 236 subreq->async.private_data = req; 237 238 return req; 239 } 240 241 static void dcerpc_bh_raw_call_done(struct rpc_request *subreq) 242 { 243 struct tevent_req *req = 244 talloc_get_type_abort(subreq->async.private_data, 245 struct tevent_req); 246 struct dcerpc_bh_raw_call_state *state = 247 tevent_req_data(req, 248 struct dcerpc_bh_raw_call_state); 249 NTSTATUS status; 250 uint32_t fault_code; 251 252 state->out_flags = 0; 253 if (subreq->flags & DCERPC_PULL_BIGENDIAN) { 254 state->out_flags |= LIBNDR_FLAG_BIGENDIAN; 255 } 256 257 fault_code = subreq->fault_code; 258 259 status = dcerpc_request_recv(subreq, state, &state->out_data); 260 if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) { 261 status = dcerpc_fault_to_nt_status(fault_code); 262 } 263 if (!NT_STATUS_IS_OK(status)) { 264 tevent_req_nterror(req, status); 265 return; 266 } 267 268 tevent_req_done(req); 269 } 270 271 static NTSTATUS dcerpc_bh_raw_call_recv(struct tevent_req *req, 272 TALLOC_CTX *mem_ctx, 273 uint8_t **out_data, 274 size_t *out_length, 275 uint32_t *out_flags) 276 { 277 struct dcerpc_bh_raw_call_state *state = 278 tevent_req_data(req, 279 struct dcerpc_bh_raw_call_state); 280 NTSTATUS status; 281 282 if (tevent_req_is_nterror(req, &status)) { 283 tevent_req_received(req); 284 return status; 285 } 286 287 *out_data = talloc_move(mem_ctx, &state->out_data.data); 288 *out_length = state->out_data.length; 289 *out_flags = state->out_flags; 290 tevent_req_received(req); 291 return NT_STATUS_OK; 292 } 293 294 struct dcerpc_bh_disconnect_state { 295 uint8_t _dummy; 296 }; 297 298 static struct tevent_req *dcerpc_bh_disconnect_send(TALLOC_CTX *mem_ctx, 299 struct tevent_context *ev, 300 struct dcerpc_binding_handle *h) 301 { 302 struct dcerpc_bh_state *hs = dcerpc_binding_handle_data(h, 303 struct dcerpc_bh_state); 304 struct tevent_req *req; 305 struct dcerpc_bh_disconnect_state *state; 306 bool ok; 307 308 req = tevent_req_create(mem_ctx, &state, 309 struct dcerpc_bh_disconnect_state); 310 if (req == NULL) { 311 return NULL; 312 } 313 314 ok = dcerpc_bh_is_connected(h); 315 if (!ok) { 316 tevent_req_nterror(req, NT_STATUS_INVALID_CONNECTION); 317 return tevent_req_post(req, ev); 318 } 319 320 /* TODO: do a real disconnect ... */ 321 hs->p = NULL; 322 323 tevent_req_done(req); 324 return tevent_req_post(req, ev); 325 } 326 327 static NTSTATUS dcerpc_bh_disconnect_recv(struct tevent_req *req) 328 { 329 NTSTATUS status; 330 331 if (tevent_req_is_nterror(req, &status)) { 332 tevent_req_received(req); 333 return status; 334 } 335 336 tevent_req_received(req); 337 return NT_STATUS_OK; 338 } 339 340 static bool dcerpc_bh_push_bigendian(struct dcerpc_binding_handle *h) 341 { 342 struct dcerpc_bh_state *hs = dcerpc_binding_handle_data(h, 343 struct dcerpc_bh_state); 344 345 if (hs->p->conn->flags & DCERPC_PUSH_BIGENDIAN) { 346 return true; 347 } 348 349 return false; 350 } 351 352 static bool dcerpc_bh_ref_alloc(struct dcerpc_binding_handle *h) 353 { 354 struct dcerpc_bh_state *hs = dcerpc_binding_handle_data(h, 355 struct dcerpc_bh_state); 356 357 if (hs->p->conn->flags & DCERPC_NDR_REF_ALLOC) { 358 return true; 359 } 360 361 return false; 362 } 363 364 static bool dcerpc_bh_use_ndr64(struct dcerpc_binding_handle *h) 365 { 366 struct dcerpc_bh_state *hs = dcerpc_binding_handle_data(h, 367 struct dcerpc_bh_state); 368 369 if (hs->p->conn->flags & DCERPC_NDR64) { 370 return true; 371 } 372 373 return false; 374 } 375 376 static void dcerpc_bh_do_ndr_print(struct dcerpc_binding_handle *h, 377 int ndr_flags, 378 const void *_struct_ptr, 379 const struct ndr_interface_call *call) 380 { 381 struct dcerpc_bh_state *hs = dcerpc_binding_handle_data(h, 382 struct dcerpc_bh_state); 383 void *struct_ptr = discard_const(_struct_ptr); 384 385 if (ndr_flags & NDR_IN) { 386 if (hs->p->conn->flags & DCERPC_DEBUG_PRINT_IN) { 387 ndr_print_function_debug(call->ndr_print, 388 call->name, 389 ndr_flags, 390 struct_ptr); 391 } 392 } 393 if (ndr_flags & NDR_OUT) { 394 if (hs->p->conn->flags & DCERPC_DEBUG_PRINT_OUT) { 395 ndr_print_function_debug(call->ndr_print, 396 call->name, 397 ndr_flags, 398 struct_ptr); 399 } 400 } 401 } 402 403 static void dcerpc_bh_ndr_push_failed(struct dcerpc_binding_handle *h, 404 NTSTATUS error, 405 const void *struct_ptr, 406 const struct ndr_interface_call *call) 407 { 408 DEBUG(2,("Unable to ndr_push structure for %s - %s\n", 409 call->name, nt_errstr(error))); 410 } 411 412 static void dcerpc_bh_ndr_pull_failed(struct dcerpc_binding_handle *h, 413 NTSTATUS error, 414 const DATA_BLOB *blob, 415 const struct ndr_interface_call *call) 416 { 417 struct dcerpc_bh_state *hs = dcerpc_binding_handle_data(h, 418 struct dcerpc_bh_state); 419 const uint32_t num_examples = 20; 420 uint32_t i; 421 422 DEBUG(2,("Unable to ndr_pull structure for %s - %s\n", 423 call->name, nt_errstr(error))); 424 425 if (hs->p->conn->packet_log_dir == NULL) return; 426 427 for (i=0;i<num_examples;i++) { 428 char *name=NULL; 429 asprintf(&name, "%s/rpclog/%s-out.%d", 430 hs->p->conn->packet_log_dir, 431 call->name, i); 432 if (name == NULL) { 433 return; 434 } 435 if (!file_exist(name)) { 436 if (file_save(name, blob->data, blob->length)) { 437 DEBUG(10,("Logged rpc packet to %s\n", name)); 438 } 439 free(name); 440 break; 441 } 442 free(name); 443 } 444 } 445 446 static NTSTATUS dcerpc_bh_ndr_validate_in(struct dcerpc_binding_handle *h, 447 TALLOC_CTX *mem_ctx, 448 const DATA_BLOB *blob, 449 const struct ndr_interface_call *call) 450 { 451 struct dcerpc_bh_state *hs = dcerpc_binding_handle_data(h, 452 struct dcerpc_bh_state); 453 454 if (hs->p->conn->flags & DCERPC_DEBUG_VALIDATE_IN) { 455 NTSTATUS status; 456 457 status = dcerpc_ndr_validate_in(hs->p->conn, 458 mem_ctx, 459 *blob, 460 call->struct_size, 461 call->ndr_push, 462 call->ndr_pull); 463 if (!NT_STATUS_IS_OK(status)) { 464 DEBUG(0,("Validation [in] failed for %s - %s\n", 465 call->name, nt_errstr(status))); 466 return status; 467 } 468 } 469 470 DEBUG(10,("rpc request data:\n")); 471 dump_data(10, blob->data, blob->length); 472 473 return NT_STATUS_OK; 474 } 475 476 static NTSTATUS dcerpc_bh_ndr_validate_out(struct dcerpc_binding_handle *h, 477 struct ndr_pull *pull_in, 478 const void *_struct_ptr, 479 const struct ndr_interface_call *call) 480 { 481 struct dcerpc_bh_state *hs = dcerpc_binding_handle_data(h, 482 struct dcerpc_bh_state); 483 void *struct_ptr = discard_const(_struct_ptr); 484 485 DEBUG(10,("rpc reply data:\n")); 486 dump_data(10, pull_in->data, pull_in->data_size); 487 488 if (pull_in->offset != pull_in->data_size) { 489 DEBUG(0,("Warning! ignoring %u unread bytes at ofs:%u (0x%08X) for %s!\n", 490 pull_in->data_size - pull_in->offset, 491 pull_in->offset, pull_in->offset, 492 call->name)); 493 /* we used to return NT_STATUS_INFO_LENGTH_MISMATCH here, 494 but it turns out that early versions of NT 495 (specifically NT3.1) add junk onto the end of rpc 496 packets, so if we want to interoperate at all with 497 those versions then we need to ignore this error */ 498 } 499 500 if (hs->p->conn->flags & DCERPC_DEBUG_VALIDATE_OUT) { 501 NTSTATUS status; 502 503 status = dcerpc_ndr_validate_out(hs->p->conn, 504 pull_in, 505 struct_ptr, 506 call->struct_size, 507 call->ndr_push, 508 call->ndr_pull, 509 call->ndr_print); 510 if (!NT_STATUS_IS_OK(status)) { 511 DEBUG(2,("Validation [out] failed for %s - %s\n", 512 call->name, nt_errstr(status))); 513 return status; 514 } 515 } 516 517 return NT_STATUS_OK; 518 } 519 520 static const struct dcerpc_binding_handle_ops dcerpc_bh_ops = { 521 .name = "dcerpc", 522 .is_connected = dcerpc_bh_is_connected, 523 .set_timeout = dcerpc_bh_set_timeout, 524 .raw_call_send = dcerpc_bh_raw_call_send, 525 .raw_call_recv = dcerpc_bh_raw_call_recv, 526 .disconnect_send = dcerpc_bh_disconnect_send, 527 .disconnect_recv = dcerpc_bh_disconnect_recv, 528 529 .push_bigendian = dcerpc_bh_push_bigendian, 530 .ref_alloc = dcerpc_bh_ref_alloc, 531 .use_ndr64 = dcerpc_bh_use_ndr64, 532 .do_ndr_print = dcerpc_bh_do_ndr_print, 533 .ndr_push_failed = dcerpc_bh_ndr_push_failed, 534 .ndr_pull_failed = dcerpc_bh_ndr_pull_failed, 535 .ndr_validate_in = dcerpc_bh_ndr_validate_in, 536 .ndr_validate_out = dcerpc_bh_ndr_validate_out, 537 }; 538 92 539 /* initialise a dcerpc pipe. */ 93 _PUBLIC_ struct dcerpc_pipe *dcerpc_pipe_init(TALLOC_CTX *mem_ctx, struct tevent_context *ev, 94 struct smb_iconv_convenience *ic) 540 struct dcerpc_binding_handle *dcerpc_pipe_binding_handle(struct dcerpc_pipe *p) 541 { 542 struct dcerpc_binding_handle *h; 543 struct dcerpc_bh_state *hs; 544 545 h = dcerpc_binding_handle_create(p, 546 &dcerpc_bh_ops, 547 NULL, 548 NULL, /* TODO */ 549 &hs, 550 struct dcerpc_bh_state, 551 __location__); 552 if (h == NULL) { 553 return NULL; 554 } 555 hs->p = p; 556 557 dcerpc_binding_handle_set_sync_ev(h, p->conn->event_ctx); 558 559 return h; 560 } 561 562 /* initialise a dcerpc pipe. */ 563 _PUBLIC_ struct dcerpc_pipe *dcerpc_pipe_init(TALLOC_CTX *mem_ctx, struct tevent_context *ev) 95 564 { 96 565 struct dcerpc_pipe *p; 97 566 98 p = talloc (mem_ctx, struct dcerpc_pipe);567 p = talloc_zero(mem_ctx, struct dcerpc_pipe); 99 568 if (!p) { 100 569 return NULL; 101 570 } 102 571 103 p->conn = dcerpc_connection_init(p, ev , ic);572 p->conn = dcerpc_connection_init(p, ev); 104 573 if (p->conn == NULL) { 105 574 talloc_free(p); … … 119 588 } 120 589 590 p->binding_handle = dcerpc_pipe_binding_handle(p); 591 if (p->binding_handle == NULL) { 592 talloc_free(p); 593 return NULL; 594 } 595 121 596 return p; 122 597 } … … 126 601 choose the next call id to use 127 602 */ 128 static uint32_t next_call_id(struct dce rpc_connection *c)603 static uint32_t next_call_id(struct dcecli_connection *c) 129 604 { 130 605 c->call_id++; … … 135 610 } 136 611 137 /* we need to be able to get/set the fragment length without doing a full138 decode */139 void dcerpc_set_frag_length(DATA_BLOB *blob, uint16_t v)140 {141 if (CVAL(blob->data,DCERPC_DREP_OFFSET) & DCERPC_DREP_LE) {142 SSVAL(blob->data, DCERPC_FRAG_LEN_OFFSET, v);143 } else {144 RSSVAL(blob->data, DCERPC_FRAG_LEN_OFFSET, v);145 }146 }147 148 uint16_t dcerpc_get_frag_length(const DATA_BLOB *blob)149 {150 if (CVAL(blob->data,DCERPC_DREP_OFFSET) & DCERPC_DREP_LE) {151 return SVAL(blob->data, DCERPC_FRAG_LEN_OFFSET);152 } else {153 return RSVAL(blob->data, DCERPC_FRAG_LEN_OFFSET);154 }155 }156 157 void dcerpc_set_auth_length(DATA_BLOB *blob, uint16_t v)158 {159 if (CVAL(blob->data,DCERPC_DREP_OFFSET) & DCERPC_DREP_LE) {160 SSVAL(blob->data, DCERPC_AUTH_LEN_OFFSET, v);161 } else {162 RSSVAL(blob->data, DCERPC_AUTH_LEN_OFFSET, v);163 }164 }165 166 167 612 /** 168 613 setup for a ndr pull, also setting up any flags from the binding string 169 614 */ 170 static struct ndr_pull *ndr_pull_init_flags(struct dce rpc_connection *c,615 static struct ndr_pull *ndr_pull_init_flags(struct dcecli_connection *c, 171 616 DATA_BLOB *blob, TALLOC_CTX *mem_ctx) 172 617 { 173 struct ndr_pull *ndr = ndr_pull_init_blob(blob, mem_ctx , c->iconv_convenience);618 struct ndr_pull *ndr = ndr_pull_init_blob(blob, mem_ctx); 174 619 175 620 if (ndr == NULL) return ndr; … … 194 639 input and output packets 195 640 */ 196 static NTSTATUS ncacn_pull(struct dce rpc_connection *c, DATA_BLOB *blob, TALLOC_CTX *mem_ctx,641 static NTSTATUS ncacn_pull(struct dcecli_connection *c, DATA_BLOB *blob, TALLOC_CTX *mem_ctx, 197 642 struct ncacn_packet *pkt) 198 643 { … … 220 665 parse the authentication information on a dcerpc response packet 221 666 */ 222 static NTSTATUS ncacn_pull_request_auth(struct dce rpc_connection *c, TALLOC_CTX *mem_ctx,667 static NTSTATUS ncacn_pull_request_auth(struct dcecli_connection *c, TALLOC_CTX *mem_ctx, 223 668 DATA_BLOB *raw_packet, 224 669 struct ncacn_packet *pkt) 225 670 { 226 struct ndr_pull *ndr;227 671 NTSTATUS status; 228 672 struct dcerpc_auth auth; 229 DATA_BLOB auth_blob; 230 enum ndr_err_code ndr_err; 673 uint32_t auth_length; 231 674 232 675 if (!c->security_state.auth_info || … … 255 698 } 256 699 257 auth_blob.length = 8 + pkt->auth_length; 258 259 /* check for a valid length */ 260 if (pkt->u.response.stub_and_verifier.length < auth_blob.length) { 261 return NT_STATUS_INFO_LENGTH_MISMATCH; 262 } 263 264 auth_blob.data = 265 pkt->u.response.stub_and_verifier.data + 266 pkt->u.response.stub_and_verifier.length - auth_blob.length; 267 pkt->u.response.stub_and_verifier.length -= auth_blob.length; 268 269 /* pull the auth structure */ 270 ndr = ndr_pull_init_flags(c, &auth_blob, mem_ctx); 271 if (!ndr) { 272 return NT_STATUS_NO_MEMORY; 273 } 274 275 if (!(pkt->drep[0] & DCERPC_DREP_LE)) { 276 ndr->flags |= LIBNDR_FLAG_BIGENDIAN; 277 } 278 279 ndr_err = ndr_pull_dcerpc_auth(ndr, NDR_SCALARS|NDR_BUFFERS, &auth); 280 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 281 return ndr_map_error2ntstatus(ndr_err); 282 } 283 status = NT_STATUS_OK; 700 status = dcerpc_pull_auth_trailer(pkt, mem_ctx, 701 &pkt->u.response.stub_and_verifier, 702 &auth, &auth_length, false); 703 NT_STATUS_NOT_OK_RETURN(status); 704 705 pkt->u.response.stub_and_verifier.length -= auth_length; 284 706 285 707 /* check signature or unseal the packet */ … … 318 740 } 319 741 320 /* remove the indicated amount of paddi ing */742 /* remove the indicated amount of padding */ 321 743 if (pkt->u.response.stub_and_verifier.length < auth.auth_pad_length) { 322 744 return NT_STATUS_INFO_LENGTH_MISMATCH; … … 331 753 push a dcerpc request packet into a blob, possibly signing it. 332 754 */ 333 static NTSTATUS ncacn_push_request_sign(struct dce rpc_connection *c,755 static NTSTATUS ncacn_push_request_sign(struct dcecli_connection *c, 334 756 DATA_BLOB *blob, TALLOC_CTX *mem_ctx, 335 757 size_t sig_size, … … 345 767 /* non-signed packets are simpler */ 346 768 if (sig_size == 0) { 347 return ncacn_push_auth(blob, mem_ctx, c->iconv_convenience,pkt, NULL);769 return ncacn_push_auth(blob, mem_ctx, pkt, NULL); 348 770 } 349 771 … … 355 777 case DCERPC_AUTH_LEVEL_CONNECT: 356 778 /* TODO: let the gensec mech decide if it wants to generate a signature */ 357 return ncacn_push_auth(blob, mem_ctx, c->iconv_convenience,pkt, NULL);779 return ncacn_push_auth(blob, mem_ctx, pkt, NULL); 358 780 359 781 case DCERPC_AUTH_LEVEL_NONE: 360 return ncacn_push_auth(blob, mem_ctx, c->iconv_convenience,pkt, NULL);782 return ncacn_push_auth(blob, mem_ctx, pkt, NULL); 361 783 362 784 default: … … 364 786 } 365 787 366 ndr = ndr_push_init_ctx(mem_ctx , c->iconv_convenience);788 ndr = ndr_push_init_ctx(mem_ctx); 367 789 if (!ndr) { 368 790 return NT_STATUS_NO_MEMORY; … … 386 808 return ndr_map_error2ntstatus(ndr_err); 387 809 } 388 status = NT_STATUS_OK;389 810 390 811 /* pad to 16 byte multiple in the payload portion of the 391 packet. This matches what w2k3 does */ 392 c->security_state.auth_info->auth_pad_length = 812 packet. This matches what w2k3 does. Note that we can't use 813 ndr_push_align() as that is relative to the start of the 814 whole packet, whereas w2k8 wants it relative to the start 815 of the stub */ 816 c->security_state.auth_info->auth_pad_length = 393 817 (16 - (pkt->u.request.stub_and_verifier.length & 15)) & 15; 394 818 ndr_err = ndr_push_zero(ndr, c->security_state.auth_info->auth_pad_length); … … 396 820 return ndr_map_error2ntstatus(ndr_err); 397 821 } 398 status = NT_STATUS_OK;399 822 400 823 payload_length = pkt->u.request.stub_and_verifier.length + … … 409 832 return ndr_map_error2ntstatus(ndr_err); 410 833 } 411 status = NT_STATUS_OK;412 834 413 835 /* extract the whole packet as a blob */ … … 457 879 458 880 if (creds2.length != sig_size) { 459 DEBUG(0,("ncacn_push_request_sign: creds2.length[%u] != sig_size[%u] pad[%u] stub[%u]\n", 460 creds2.length, (uint32_t)sig_size, 461 c->security_state.auth_info->auth_pad_length, 462 pkt->u.request.stub_and_verifier.length)); 463 return NT_STATUS_INTERNAL_ERROR; 881 /* this means the sig_size estimate for the signature 882 was incorrect. We have to correct the packet 883 sizes. That means we could go over the max fragment 884 length */ 885 DEBUG(3,("ncacn_push_request_sign: creds2.length[%u] != sig_size[%u] pad[%u] stub[%u]\n", 886 (unsigned) creds2.length, 887 (unsigned) sig_size, 888 (unsigned) c->security_state.auth_info->auth_pad_length, 889 (unsigned) pkt->u.request.stub_and_verifier.length)); 890 dcerpc_set_frag_length(blob, blob->length + creds2.length); 891 dcerpc_set_auth_length(blob, creds2.length); 464 892 } 465 893 … … 475 903 fill in the fixed values in a dcerpc header 476 904 */ 477 static void init_ncacn_hdr(struct dce rpc_connection *c, struct ncacn_packet *pkt)905 static void init_ncacn_hdr(struct dcecli_connection *c, struct ncacn_packet *pkt) 478 906 { 479 907 pkt->rpc_vers = 5; … … 535 963 mark the dcerpc connection dead. All outstanding requests get an error 536 964 */ 537 static void dcerpc_connection_dead(struct dce rpc_connection *conn, NTSTATUS status)965 static void dcerpc_connection_dead(struct dcecli_connection *conn, NTSTATUS status) 538 966 { 539 967 if (conn->dead) return; … … 566 994 packets we need to handle 567 995 */ 568 static void dcerpc_request_recv_data(struct dce rpc_connection *c,996 static void dcerpc_request_recv_data(struct dcecli_connection *c, 569 997 DATA_BLOB *raw_packet, struct ncacn_packet *pkt); 570 998 … … 574 1002 dispatch to the appropriate handler 575 1003 */ 576 static void dcerpc_recv_data(struct dce rpc_connection *conn, DATA_BLOB *blob, NTSTATUS status)1004 static void dcerpc_recv_data(struct dcecli_connection *conn, DATA_BLOB *blob, NTSTATUS status) 577 1005 { 578 1006 struct ncacn_packet pkt; … … 600 1028 } 601 1029 602 603 1030 /* 604 1031 Receive a bind reply from the transport … … 608 1035 { 609 1036 struct composite_context *c; 610 struct dce rpc_connection *conn;1037 struct dcecli_connection *conn; 611 1038 612 1039 c = talloc_get_type(req->async.private_data, struct composite_context); … … 623 1050 (pkt->u.bind_ack.num_results == 0) || 624 1051 (pkt->u.bind_ack.ctx_list[0].result != 0)) { 1052 req->p->last_fault_code = DCERPC_NCA_S_PROTO_ERROR; 625 1053 composite_error(c, NT_STATUS_NET_WRITE_FAULT); 626 1054 return; … … 643 1071 644 1072 /* the bind_ack might contain a reply set of credentials */ 645 if (conn->security_state.auth_info && 646 pkt->u.bind_ack.auth_info.length) { 647 enum ndr_err_code ndr_err; 648 ndr_err = ndr_pull_struct_blob( 649 &pkt->u.bind_ack.auth_info, conn, 650 NULL, 651 conn->security_state.auth_info, 652 (ndr_pull_flags_fn_t)ndr_pull_dcerpc_auth); 653 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 654 c->status = ndr_map_error2ntstatus(ndr_err); 655 if (!composite_is_ok(c)) return; 1073 if (conn->security_state.auth_info && pkt->u.bind_ack.auth_info.length) { 1074 NTSTATUS status; 1075 uint32_t auth_length; 1076 status = dcerpc_pull_auth_trailer(pkt, conn, &pkt->u.bind_ack.auth_info, 1077 conn->security_state.auth_info, &auth_length, true); 1078 if (!NT_STATUS_IS_OK(status)) { 1079 composite_error(c, status); 1080 return; 656 1081 } 657 1082 } … … 732 1157 733 1158 /* construct the NDR form of the packet */ 734 c->status = ncacn_push_auth(&blob, c, p->conn->iconv_convenience,&pkt,1159 c->status = ncacn_push_auth(&blob, c, &pkt, 735 1160 p->conn->security_state.auth_info); 736 1161 if (!composite_is_ok(c)) return c; … … 791 1216 pkt.call_id = next_call_id(p->conn); 792 1217 pkt.auth_length = 0; 793 pkt.u.auth3._pad = 0;794 1218 pkt.u.auth3.auth_info = data_blob(NULL, 0); 795 1219 … … 804 1228 /* construct the NDR form of the packet */ 805 1229 status = ncacn_push_auth(&blob, mem_ctx, 806 p->conn->iconv_convenience,807 1230 &pkt, 808 1231 p->conn->security_state.auth_info); … … 827 1250 This function frees the data 828 1251 */ 829 static void dcerpc_request_recv_data(struct dce rpc_connection *c,1252 static void dcerpc_request_recv_data(struct dcecli_connection *c, 830 1253 DATA_BLOB *raw_packet, struct ncacn_packet *pkt) 831 1254 { 832 1255 struct rpc_request *req; 833 u int_t length;1256 unsigned int length; 834 1257 NTSTATUS status = NT_STATUS_OK; 835 1258 … … 947 1370 const struct GUID *object, 948 1371 uint16_t opnum, 949 bool async,950 1372 DATA_BLOB *stub_data) 951 1373 { … … 966 1388 req->flags = 0; 967 1389 req->fault_code = 0; 968 req->async_call = async;969 1390 req->ignore_timeout = false; 970 1391 req->async.callback = NULL; … … 1007 1428 */ 1008 1429 1009 static void dcerpc_ship_next_request(struct dce rpc_connection *c)1430 static void dcerpc_ship_next_request(struct dcecli_connection *c) 1010 1431 { 1011 1432 struct rpc_request *req; … … 1017 1438 bool first_packet = true; 1018 1439 size_t sig_size = 0; 1440 bool need_async = false; 1019 1441 1020 1442 req = c->request_queue; … … 1026 1448 stub_data = &req->request_data; 1027 1449 1028 if ( !req->async_call && (c->pending != NULL)) {1029 return;1450 if (c->pending) { 1451 need_async = true; 1030 1452 } 1031 1453 … … 1064 1486 pkt.u.request.object.object = *req->object; 1065 1487 pkt.pfc_flags |= DCERPC_PFC_FLAG_OBJECT_UUID; 1066 chunk_size -= ndr_size_GUID(req->object, NULL,0);1488 chunk_size -= ndr_size_GUID(req->object,0); 1067 1489 } 1068 1490 … … 1095 1517 } 1096 1518 1097 if (last_frag && ! req->async_call) {1519 if (last_frag && !need_async) { 1098 1520 do_trans = true; 1099 1521 } … … 1133 1555 perform the receive side of a async dcerpc request 1134 1556 */ 1135 NTSTATUS dcerpc_request_recv(struct rpc_request *req,1136 1137 1557 static NTSTATUS dcerpc_request_recv(struct rpc_request *req, 1558 TALLOC_CTX *mem_ctx, 1559 DATA_BLOB *stub_data) 1138 1560 { 1139 1561 NTSTATUS status; … … 1158 1580 1159 1581 /* 1160 perform a full request/response pair on a dcerpc pipe1161 */1162 NTSTATUS dcerpc_request(struct dcerpc_pipe *p,1163 struct GUID *object,1164 uint16_t opnum,1165 TALLOC_CTX *mem_ctx,1166 DATA_BLOB *stub_data_in,1167 DATA_BLOB *stub_data_out)1168 {1169 struct rpc_request *req;1170 1171 req = dcerpc_request_send(p, object, opnum, false, stub_data_in);1172 if (req == NULL) {1173 return NT_STATUS_NO_MEMORY;1174 }1175 1176 return dcerpc_request_recv(req, mem_ctx, stub_data_out);1177 }1178 1179 1180 /*1181 1582 this is a paranoid NDR validator. For every packet we push onto the wire 1182 1583 we pull it back again, then push it again. Then we compare the raw NDR data … … 1184 1585 we must have a bug in either the pull or push side of our code 1185 1586 */ 1186 static NTSTATUS dcerpc_ndr_validate_in(struct dce rpc_connection *c,1587 static NTSTATUS dcerpc_ndr_validate_in(struct dcecli_connection *c, 1187 1588 TALLOC_CTX *mem_ctx, 1188 1589 DATA_BLOB blob, … … 1207 1608 } 1208 1609 pull->flags |= LIBNDR_FLAG_REF_ALLOC; 1610 1611 if (c->flags & DCERPC_PUSH_BIGENDIAN) { 1612 pull->flags |= LIBNDR_FLAG_BIGENDIAN; 1613 } 1614 1615 if (c->flags & DCERPC_NDR64) { 1616 pull->flags |= LIBNDR_FLAG_NDR64; 1617 } 1209 1618 1210 1619 ndr_err = ndr_pull(pull, NDR_IN, st); … … 1217 1626 } 1218 1627 1219 push = ndr_push_init_ctx(mem_ctx , c->iconv_convenience);1628 push = ndr_push_init_ctx(mem_ctx); 1220 1629 if (!push) { 1221 1630 return NT_STATUS_NO_MEMORY; 1222 1631 } 1632 1633 if (c->flags & DCERPC_PUSH_BIGENDIAN) { 1634 push->flags |= LIBNDR_FLAG_BIGENDIAN; 1635 } 1636 1637 if (c->flags & DCERPC_NDR64) { 1638 push->flags |= LIBNDR_FLAG_NDR64; 1639 } 1223 1640 1224 1641 ndr_err = ndr_push(push, NDR_IN, st); … … 1253 1670 bug in either the pull or push side of our code 1254 1671 */ 1255 static NTSTATUS dcerpc_ndr_validate_out(struct dce rpc_connection *c,1672 static NTSTATUS dcerpc_ndr_validate_out(struct dcecli_connection *c, 1256 1673 struct ndr_pull *pull_in, 1257 1674 void *struct_ptr, … … 1275 1692 memcpy(st, struct_ptr, struct_size); 1276 1693 1277 push = ndr_push_init_ctx(mem_ctx , c->iconv_convenience);1694 push = ndr_push_init_ctx(mem_ctx); 1278 1695 if (!push) { 1279 1696 return NT_STATUS_NO_MEMORY; … … 1306 1723 } 1307 1724 1308 push = ndr_push_init_ctx(mem_ctx , c->iconv_convenience);1725 push = ndr_push_init_ctx(mem_ctx); 1309 1726 if (!push) { 1310 1727 return NT_STATUS_NO_MEMORY; … … 1356 1773 } 1357 1774 1358 1359 /**1360 send a rpc request given a dcerpc_call structure1361 */1362 struct rpc_request *dcerpc_ndr_request_send(struct dcerpc_pipe *p,1363 const struct GUID *object,1364 const struct ndr_interface_table *table,1365 uint32_t opnum,1366 bool async,1367 TALLOC_CTX *mem_ctx,1368 void *r)1369 {1370 const struct ndr_interface_call *call;1371 struct ndr_push *push;1372 NTSTATUS status;1373 DATA_BLOB request;1374 struct rpc_request *req;1375 enum ndr_err_code ndr_err;1376 1377 call = &table->calls[opnum];1378 1379 /* setup for a ndr_push_* call */1380 push = ndr_push_init_ctx(mem_ctx, p->conn->iconv_convenience);1381 if (!push) {1382 return NULL;1383 }1384 1385 if (p->conn->flags & DCERPC_PUSH_BIGENDIAN) {1386 push->flags |= LIBNDR_FLAG_BIGENDIAN;1387 }1388 1389 if (p->conn->flags & DCERPC_NDR64) {1390 push->flags |= LIBNDR_FLAG_NDR64;1391 }1392 1393 /* push the structure into a blob */1394 ndr_err = call->ndr_push(push, NDR_IN, r);1395 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {1396 status = ndr_map_error2ntstatus(ndr_err);1397 DEBUG(2,("Unable to ndr_push structure in dcerpc_ndr_request_send - %s\n",1398 nt_errstr(status)));1399 talloc_free(push);1400 return NULL;1401 }1402 1403 /* retrieve the blob */1404 request = ndr_push_blob(push);1405 1406 if (p->conn->flags & DCERPC_DEBUG_VALIDATE_IN) {1407 status = dcerpc_ndr_validate_in(p->conn, push, request, call->struct_size,1408 call->ndr_push, call->ndr_pull);1409 if (!NT_STATUS_IS_OK(status)) {1410 DEBUG(2,("Validation failed in dcerpc_ndr_request_send - %s\n",1411 nt_errstr(status)));1412 talloc_free(push);1413 return NULL;1414 }1415 }1416 1417 DEBUG(10,("rpc request data:\n"));1418 dump_data(10, request.data, request.length);1419 1420 /* make the actual dcerpc request */1421 req = dcerpc_request_send(p, object, opnum, async, &request);1422 1423 if (req != NULL) {1424 req->ndr.table = table;1425 req->ndr.opnum = opnum;1426 req->ndr.struct_ptr = r;1427 req->ndr.mem_ctx = mem_ctx;1428 }1429 1430 talloc_free(push);1431 1432 return req;1433 }1434 1435 /*1436 receive the answer from a dcerpc_ndr_request_send()1437 */1438 _PUBLIC_ NTSTATUS dcerpc_ndr_request_recv(struct rpc_request *req)1439 {1440 struct dcerpc_pipe *p = req->p;1441 NTSTATUS status;1442 DATA_BLOB response;1443 struct ndr_pull *pull;1444 uint_t flags;1445 TALLOC_CTX *mem_ctx = req->ndr.mem_ctx;1446 void *r = req->ndr.struct_ptr;1447 uint32_t opnum = req->ndr.opnum;1448 const struct ndr_interface_table *table = req->ndr.table;1449 const struct ndr_interface_call *call = &table->calls[opnum];1450 enum ndr_err_code ndr_err;1451 1452 /* make sure the recv code doesn't free the request, as we1453 need to grab the flags element before it is freed */1454 if (talloc_reference(p, req) == NULL) {1455 return NT_STATUS_NO_MEMORY;1456 }1457 1458 status = dcerpc_request_recv(req, mem_ctx, &response);1459 if (!NT_STATUS_IS_OK(status)) {1460 talloc_unlink(p, req);1461 return status;1462 }1463 1464 flags = req->flags;1465 1466 /* prepare for ndr_pull_* */1467 pull = ndr_pull_init_flags(p->conn, &response, mem_ctx);1468 if (!pull) {1469 talloc_unlink(p, req);1470 return NT_STATUS_NO_MEMORY;1471 }1472 1473 if (pull->data) {1474 pull->data = talloc_steal(pull, pull->data);1475 }1476 talloc_unlink(p, req);1477 1478 if (flags & DCERPC_PULL_BIGENDIAN) {1479 pull->flags |= LIBNDR_FLAG_BIGENDIAN;1480 }1481 1482 DEBUG(10,("rpc reply data:\n"));1483 dump_data(10, pull->data, pull->data_size);1484 1485 /* pull the structure from the blob */1486 ndr_err = call->ndr_pull(pull, NDR_OUT, r);1487 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {1488 status = ndr_map_error2ntstatus(ndr_err);1489 dcerpc_log_packet(p->conn->packet_log_dir,1490 table, opnum, NDR_OUT,1491 &response);1492 return status;1493 }1494 1495 if (p->conn->flags & DCERPC_DEBUG_VALIDATE_OUT) {1496 status = dcerpc_ndr_validate_out(p->conn, pull, r, call->struct_size,1497 call->ndr_push, call->ndr_pull,1498 call->ndr_print);1499 if (!NT_STATUS_IS_OK(status)) {1500 dcerpc_log_packet(p->conn->packet_log_dir,1501 table, opnum, NDR_OUT,1502 &response);1503 return status;1504 }1505 }1506 1507 if (pull->offset != pull->data_size) {1508 DEBUG(0,("Warning! ignoring %d unread bytes in rpc packet!\n",1509 pull->data_size - pull->offset));1510 /* we used to return NT_STATUS_INFO_LENGTH_MISMATCH here,1511 but it turns out that early versions of NT1512 (specifically NT3.1) add junk onto the end of rpc1513 packets, so if we want to interoperate at all with1514 those versions then we need to ignore this error */1515 }1516 1517 /* TODO: make pull context independent from the output mem_ctx and free the pull context */1518 1519 return NT_STATUS_OK;1520 }1521 1522 1523 /*1524 a useful helper function for synchronous rpc requests1525 1526 this can be used when you have ndr push/pull functions in the1527 standard format1528 */1529 _PUBLIC_ NTSTATUS dcerpc_ndr_request(struct dcerpc_pipe *p,1530 const struct GUID *object,1531 const struct ndr_interface_table *table,1532 uint32_t opnum,1533 TALLOC_CTX *mem_ctx,1534 void *r)1535 {1536 struct rpc_request *req;1537 1538 req = dcerpc_ndr_request_send(p, object, table, opnum, false, mem_ctx, r);1539 if (req == NULL) {1540 return NT_STATUS_NO_MEMORY;1541 }1542 1543 return dcerpc_ndr_request_recv(req);1544 }1545 1546 1547 1775 /* 1548 1776 a useful function for retrieving the server name we connected to … … 1563 1791 get the dcerpc auth_level for a open connection 1564 1792 */ 1565 uint32_t dcerpc_auth_level(struct dce rpc_connection *c)1793 uint32_t dcerpc_auth_level(struct dcecli_connection *c) 1566 1794 { 1567 1795 uint8_t auth_level; … … 1600 1828 } 1601 1829 1830 if (pkt->ptype == DCERPC_PKT_FAULT) { 1831 DEBUG(5,("rpc fault: %s\n", dcerpc_errstr(c, pkt->u.fault.status))); 1832 recv_pipe->last_fault_code = pkt->u.fault.status; 1833 composite_error(c, NT_STATUS_NET_WRITE_FAULT); 1834 return; 1835 } 1836 1602 1837 if (pkt->ptype != DCERPC_PKT_ALTER_RESP || 1603 1838 pkt->u.alter_resp.num_results == 0 || 1604 1839 pkt->u.alter_resp.ctx_list[0].result != 0) { 1840 recv_pipe->last_fault_code = DCERPC_NCA_S_PROTO_ERROR; 1605 1841 composite_error(c, NT_STATUS_NET_WRITE_FAULT); 1606 1842 return; … … 1610 1846 if (recv_pipe->conn->security_state.auth_info && 1611 1847 pkt->u.alter_resp.auth_info.length) { 1612 enum ndr_err_code ndr_err; 1613 ndr_err = ndr_pull_struct_blob( 1614 &pkt->u.alter_resp.auth_info, recv_pipe, 1615 NULL, 1616 recv_pipe->conn->security_state.auth_info, 1617 (ndr_pull_flags_fn_t)ndr_pull_dcerpc_auth); 1618 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 1619 c->status = ndr_map_error2ntstatus(ndr_err); 1620 if (!composite_is_ok(c)) return; 1848 struct dcecli_connection *conn = recv_pipe->conn; 1849 NTSTATUS status; 1850 uint32_t auth_length; 1851 status = dcerpc_pull_auth_trailer(pkt, conn, &pkt->u.alter_resp.auth_info, 1852 conn->security_state.auth_info, &auth_length, true); 1853 if (!NT_STATUS_IS_OK(status)) { 1854 composite_error(c, status); 1855 return; 1621 1856 } 1622 1857 } … … 1674 1909 1675 1910 /* construct the NDR form of the packet */ 1676 c->status = ncacn_push_auth(&blob, mem_ctx, p->conn->iconv_convenience,&pkt,1911 c->status = ncacn_push_auth(&blob, mem_ctx, &pkt, 1677 1912 p->conn->security_state.auth_info); 1678 1913 if (!composite_is_ok(c)) return c; … … 1725 1960 return dcerpc_alter_context_recv(creq); 1726 1961 } 1962
Note:
See TracChangeset
for help on using the changeset viewer.