Changeset 740 for vendor/current/source3/libsmb/clirap.c
- Timestamp:
- Nov 14, 2012, 12:59:34 PM (13 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
vendor/current/source3/libsmb/clirap.c
r414 r740 22 22 #include "includes.h" 23 23 #include "../libcli/auth/libcli_auth.h" 24 #include "../librpc/gen_ndr/rap.h" 25 #include "../lib/crypto/arcfour.h" 26 #include "../lib/util/tevent_ntstatus.h" 27 #include "async_smb.h" 28 #include "libsmb/libsmb.h" 29 #include "libsmb/clirap.h" 30 #include "trans2.h" 31 32 #define PIPE_LANMAN "\\PIPE\\LANMAN" 24 33 25 34 /**************************************************************************** … … 33 42 char **rdata, unsigned int *rdrcnt) 34 43 { 35 cli_send_trans(cli,SMBtrans, 36 PIPE_LANMAN, /* Name */ 37 0,0, /* fid, flags */ 38 NULL,0,0, /* Setup, length, max */ 39 param, prcnt, mprcnt, /* Params, length, max */ 40 data, drcnt, mdrcnt /* Data, length, max */ 41 ); 42 43 return (cli_receive_trans(cli,SMBtrans, 44 rparam, rprcnt, 45 rdata, rdrcnt)); 44 NTSTATUS status; 45 46 uint8_t *my_rparam, *my_rdata; 47 uint32_t num_my_rparam, num_my_rdata; 48 49 status = cli_trans(talloc_tos(), cli, SMBtrans, 50 PIPE_LANMAN, 0, /* name, fid */ 51 0, 0, /* function, flags */ 52 NULL, 0, 0, /* setup */ 53 (uint8_t *)param, prcnt, mprcnt, /* Params, length, max */ 54 (uint8_t *)data, drcnt, mdrcnt, /* Data, length, max */ 55 NULL, /* recv_flags2 */ 56 NULL, 0, NULL, /* rsetup */ 57 &my_rparam, 0, &num_my_rparam, 58 &my_rdata, 0, &num_my_rdata); 59 if (!NT_STATUS_IS_OK(status)) { 60 return false; 61 } 62 63 /* 64 * I know this memcpy massively hurts, but there are just tons 65 * of callers of cli_api that eventually need changing to 66 * talloc 67 */ 68 69 *rparam = (char *)memdup(my_rparam, num_my_rparam); 70 if (*rparam == NULL) { 71 goto fail; 72 } 73 *rprcnt = num_my_rparam; 74 TALLOC_FREE(my_rparam); 75 76 *rdata = (char *)memdup(my_rdata, num_my_rdata); 77 if (*rdata == NULL) { 78 goto fail; 79 } 80 *rdrcnt = num_my_rdata; 81 TALLOC_FREE(my_rdata); 82 83 return true; 84 fail: 85 TALLOC_FREE(my_rdata); 86 TALLOC_FREE(my_rparam); 87 *rparam = NULL; 88 *rprcnt = 0; 89 *rdata = NULL; 90 *rdrcnt = 0; 91 return false; 46 92 } 47 93 … … 496 542 data_len = 532; 497 543 498 if (cli_send_trans(cli,SMBtrans, 499 PIPE_LANMAN, /* name */ 500 0,0, /* fid, flags */ 501 NULL,0,0, /* setup, length, max */ 502 param,param_len,2, /* param, length, max */ 503 (char *)data,data_len,0 /* data, length, max */ 504 ) == False) { 544 if (!cli_api(cli, 545 param, param_len, 4, /* param, length, max */ 546 (char *)data, data_len, 0, /* data, length, max */ 547 &rparam, &rprcnt, 548 &rdata, &rdrcnt)) { 505 549 DEBUG(0,("cli_oem_change_password: Failed to send password change for user %s\n", 506 550 user )); … … 508 552 } 509 553 510 if (!cli_receive_trans(cli,SMBtrans,511 &rparam, &rprcnt,512 &rdata, &rdrcnt)) {513 DEBUG(0,("cli_oem_change_password: Failed to recieve reply to password change for user %s\n",514 user ));515 return False;516 }517 518 554 if (rparam) { 519 555 cli->rap_error = SVAL(rparam,0); … … 530 566 ****************************************************************************/ 531 567 532 bool cli_qpathinfo(struct cli_state *cli, 568 struct cli_qpathinfo1_state { 569 struct cli_state *cli; 570 uint32_t num_data; 571 uint8_t *data; 572 }; 573 574 static void cli_qpathinfo1_done(struct tevent_req *subreq); 575 576 struct tevent_req *cli_qpathinfo1_send(TALLOC_CTX *mem_ctx, 577 struct event_context *ev, 578 struct cli_state *cli, 579 const char *fname) 580 { 581 struct tevent_req *req = NULL, *subreq = NULL; 582 struct cli_qpathinfo1_state *state = NULL; 583 584 req = tevent_req_create(mem_ctx, &state, struct cli_qpathinfo1_state); 585 if (req == NULL) { 586 return NULL; 587 } 588 state->cli = cli; 589 subreq = cli_qpathinfo_send(state, ev, cli, fname, SMB_INFO_STANDARD, 590 22, cli->max_xmit); 591 if (tevent_req_nomem(subreq, req)) { 592 return tevent_req_post(req, ev); 593 } 594 tevent_req_set_callback(subreq, cli_qpathinfo1_done, req); 595 return req; 596 } 597 598 static void cli_qpathinfo1_done(struct tevent_req *subreq) 599 { 600 struct tevent_req *req = tevent_req_callback_data( 601 subreq, struct tevent_req); 602 struct cli_qpathinfo1_state *state = tevent_req_data( 603 req, struct cli_qpathinfo1_state); 604 NTSTATUS status; 605 606 status = cli_qpathinfo_recv(subreq, state, &state->data, 607 &state->num_data); 608 TALLOC_FREE(subreq); 609 if (!NT_STATUS_IS_OK(status)) { 610 tevent_req_nterror(req, status); 611 return; 612 } 613 tevent_req_done(req); 614 } 615 616 NTSTATUS cli_qpathinfo1_recv(struct tevent_req *req, 617 time_t *change_time, 618 time_t *access_time, 619 time_t *write_time, 620 SMB_OFF_T *size, 621 uint16 *mode) 622 { 623 struct cli_qpathinfo1_state *state = tevent_req_data( 624 req, struct cli_qpathinfo1_state); 625 NTSTATUS status; 626 627 time_t (*date_fn)(const void *buf, int serverzone); 628 629 if (tevent_req_is_nterror(req, &status)) { 630 return status; 631 } 632 633 if (state->cli->win95) { 634 date_fn = make_unix_date; 635 } else { 636 date_fn = make_unix_date2; 637 } 638 639 if (change_time) { 640 *change_time = date_fn(state->data+0, state->cli->serverzone); 641 } 642 if (access_time) { 643 *access_time = date_fn(state->data+4, state->cli->serverzone); 644 } 645 if (write_time) { 646 *write_time = date_fn(state->data+8, state->cli->serverzone); 647 } 648 if (size) { 649 *size = IVAL(state->data, 12); 650 } 651 if (mode) { 652 *mode = SVAL(state->data, l1_attrFile); 653 } 654 return NT_STATUS_OK; 655 } 656 657 NTSTATUS cli_qpathinfo1(struct cli_state *cli, 533 658 const char *fname, 534 659 time_t *change_time, … … 538 663 uint16 *mode) 539 664 { 540 unsigned int data_len = 0; 541 unsigned int param_len = 0; 542 unsigned int rparam_len, rdata_len; 543 uint16 setup = TRANSACT2_QPATHINFO; 544 char *param; 545 char *rparam=NULL, *rdata=NULL; 546 int count=8; 547 bool ret; 548 time_t (*date_fn)(struct cli_state *, const void *); 549 char *p; 550 size_t nlen = 2*(strlen(fname)+1); 551 552 param = SMB_MALLOC_ARRAY(char, 6+nlen+2); 553 if (!param) { 554 return false; 555 } 556 p = param; 557 memset(p, '\0', 6); 558 SSVAL(p, 0, SMB_INFO_STANDARD); 559 p += 6; 560 p += clistr_push(cli, p, fname, nlen, STR_TERMINATE); 561 param_len = PTR_DIFF(p, param); 562 563 do { 564 ret = (cli_send_trans(cli, SMBtrans2, 565 NULL, /* Name */ 566 -1, 0, /* fid, flags */ 567 &setup, 1, 0, /* setup, length, max */ 568 param, param_len, 10, /* param, length, max */ 569 NULL, data_len, cli->max_xmit /* data, length, max */ 570 ) && 571 cli_receive_trans(cli, SMBtrans2, 572 &rparam, &rparam_len, 573 &rdata, &rdata_len)); 574 if (!cli_is_dos_error(cli)) break; 575 if (!ret) { 576 /* we need to work around a Win95 bug - sometimes 577 it gives ERRSRV/ERRerror temprarily */ 578 uint8 eclass; 579 uint32 ecode; 580 cli_dos_error(cli, &eclass, &ecode); 581 if (eclass != ERRSRV || ecode != ERRerror) break; 582 smb_msleep(100); 583 } 584 } while (count-- && ret==False); 585 586 SAFE_FREE(param); 587 if (!ret || !rdata || rdata_len < 22) { 588 return False; 589 } 590 591 if (cli->win95) { 592 date_fn = cli_make_unix_date; 593 } else { 594 date_fn = cli_make_unix_date2; 595 } 596 597 if (change_time) { 598 *change_time = date_fn(cli, rdata+0); 599 } 600 if (access_time) { 601 *access_time = date_fn(cli, rdata+4); 602 } 603 if (write_time) { 604 *write_time = date_fn(cli, rdata+8); 605 } 606 if (size) { 607 *size = IVAL(rdata, 12); 608 } 609 if (mode) { 610 *mode = SVAL(rdata,l1_attrFile); 611 } 612 613 SAFE_FREE(rdata); 614 SAFE_FREE(rparam); 615 return True; 665 TALLOC_CTX *frame = talloc_stackframe(); 666 struct event_context *ev; 667 struct tevent_req *req; 668 NTSTATUS status = NT_STATUS_NO_MEMORY; 669 670 if (cli_has_async_calls(cli)) { 671 /* 672 * Can't use sync call while an async call is in flight 673 */ 674 status = NT_STATUS_INVALID_PARAMETER; 675 goto fail; 676 } 677 ev = event_context_init(frame); 678 if (ev == NULL) { 679 goto fail; 680 } 681 req = cli_qpathinfo1_send(frame, ev, cli, fname); 682 if (req == NULL) { 683 goto fail; 684 } 685 if (!tevent_req_poll_ntstatus(req, ev, &status)) { 686 goto fail; 687 } 688 status = cli_qpathinfo1_recv(req, change_time, access_time, 689 write_time, size, mode); 690 fail: 691 TALLOC_FREE(frame); 692 if (!NT_STATUS_IS_OK(status)) { 693 cli_set_error(cli, status); 694 } 695 return status; 616 696 } 617 697 … … 620 700 ****************************************************************************/ 621 701 622 bool cli_setpathinfo(struct cli_state *cli, const char *fname,623 624 625 626 627 702 NTSTATUS cli_setpathinfo_basic(struct cli_state *cli, const char *fname, 703 time_t create_time, 704 time_t access_time, 705 time_t write_time, 706 time_t change_time, 707 uint16 mode) 628 708 { 629 709 unsigned int data_len = 0; 630 unsigned int param_len = 0;631 unsigned int rparam_len, rdata_len;632 uint16 setup = TRANSACT2_SETPATHINFO;633 char *param;634 710 char data[40]; 635 char *rparam=NULL, *rdata=NULL;636 int count=8;637 bool ret;638 711 char *p; 639 size_t nlen = 2*(strlen(fname)+1);640 641 param = SMB_MALLOC_ARRAY(char, 6+nlen+2);642 if (!param) {643 return false;644 }645 memset(param, '\0', 6);646 memset(data, 0, sizeof(data));647 648 p = param;649 650 /* Add the information level */651 SSVAL(p, 0, SMB_FILE_BASIC_INFORMATION);652 653 /* Skip reserved */654 p += 6;655 656 /* Add the file name */657 p += clistr_push(cli, p, fname, nlen, STR_TERMINATE);658 659 param_len = PTR_DIFF(p, param);660 712 661 713 p = data; … … 686 738 data_len = PTR_DIFF(p, data); 687 739 688 do { 689 ret = (cli_send_trans(cli, SMBtrans2, 690 NULL, /* Name */ 691 -1, 0, /* fid, flags */ 692 &setup, 1, 0, /* setup, length, max */ 693 param, param_len, 10, /* param, length, max */ 694 data, data_len, cli->max_xmit /* data, length, max */ 695 ) && 696 cli_receive_trans(cli, SMBtrans2, 697 &rparam, &rparam_len, 698 &rdata, &rdata_len)); 699 if (!cli_is_dos_error(cli)) break; 700 if (!ret) { 701 /* we need to work around a Win95 bug - sometimes 702 it gives ERRSRV/ERRerror temprarily */ 703 uint8 eclass; 704 uint32 ecode; 705 cli_dos_error(cli, &eclass, &ecode); 706 if (eclass != ERRSRV || ecode != ERRerror) break; 707 smb_msleep(100); 708 } 709 } while (count-- && ret==False); 710 711 SAFE_FREE(param); 712 if (!ret) { 713 return False; 714 } 715 716 SAFE_FREE(rdata); 717 SAFE_FREE(rparam); 718 return True; 740 return cli_setpathinfo(cli, SMB_FILE_BASIC_INFORMATION, fname, 741 (uint8_t *)data, data_len); 719 742 } 720 743 … … 723 746 ****************************************************************************/ 724 747 725 bool cli_qpathinfo2(struct cli_state *cli, const char *fname, 726 struct timespec *create_time, 727 struct timespec *access_time, 728 struct timespec *write_time, 729 struct timespec *change_time, 730 SMB_OFF_T *size, uint16 *mode, 731 SMB_INO_T *ino) 732 { 733 unsigned int data_len = 0; 734 unsigned int param_len = 0; 735 uint16 setup = TRANSACT2_QPATHINFO; 736 char *param; 737 char *rparam=NULL, *rdata=NULL; 738 char *p; 739 size_t nlen = 2*(strlen(fname)+1); 740 741 param = SMB_MALLOC_ARRAY(char, 6+nlen+2); 742 if (!param) { 743 return false; 744 } 745 p = param; 746 memset(param, '\0', 6); 747 SSVAL(p, 0, SMB_QUERY_FILE_ALL_INFO); 748 p += 6; 749 p += clistr_push(cli, p, fname, nlen, STR_TERMINATE); 750 751 param_len = PTR_DIFF(p, param); 752 753 if (!cli_send_trans(cli, SMBtrans2, 754 NULL, /* name */ 755 -1, 0, /* fid, flags */ 756 &setup, 1, 0, /* setup, length, max */ 757 param, param_len, 10, /* param, length, max */ 758 NULL, data_len, cli->max_xmit /* data, length, max */ 759 )) { 760 SAFE_FREE(param); 761 return False; 762 } 763 764 SAFE_FREE(param); 765 if (!cli_receive_trans(cli, SMBtrans2, 766 &rparam, ¶m_len, 767 &rdata, &data_len)) { 768 return False; 769 } 770 771 if (!rdata || data_len < 22) { 772 return False; 748 struct cli_qpathinfo2_state { 749 uint32_t num_data; 750 uint8_t *data; 751 }; 752 753 static void cli_qpathinfo2_done(struct tevent_req *subreq); 754 755 struct tevent_req *cli_qpathinfo2_send(TALLOC_CTX *mem_ctx, 756 struct event_context *ev, 757 struct cli_state *cli, 758 const char *fname) 759 { 760 struct tevent_req *req = NULL, *subreq = NULL; 761 struct cli_qpathinfo2_state *state = NULL; 762 763 req = tevent_req_create(mem_ctx, &state, struct cli_qpathinfo2_state); 764 if (req == NULL) { 765 return NULL; 766 } 767 subreq = cli_qpathinfo_send(state, ev, cli, fname, 768 SMB_QUERY_FILE_ALL_INFO, 769 68, cli->max_xmit); 770 if (tevent_req_nomem(subreq, req)) { 771 return tevent_req_post(req, ev); 772 } 773 tevent_req_set_callback(subreq, cli_qpathinfo2_done, req); 774 return req; 775 } 776 777 static void cli_qpathinfo2_done(struct tevent_req *subreq) 778 { 779 struct tevent_req *req = tevent_req_callback_data( 780 subreq, struct tevent_req); 781 struct cli_qpathinfo2_state *state = tevent_req_data( 782 req, struct cli_qpathinfo2_state); 783 NTSTATUS status; 784 785 status = cli_qpathinfo_recv(subreq, state, &state->data, 786 &state->num_data); 787 TALLOC_FREE(subreq); 788 if (!NT_STATUS_IS_OK(status)) { 789 tevent_req_nterror(req, status); 790 return; 791 } 792 tevent_req_done(req); 793 } 794 795 NTSTATUS cli_qpathinfo2_recv(struct tevent_req *req, 796 struct timespec *create_time, 797 struct timespec *access_time, 798 struct timespec *write_time, 799 struct timespec *change_time, 800 SMB_OFF_T *size, uint16 *mode, 801 SMB_INO_T *ino) 802 { 803 struct cli_qpathinfo2_state *state = tevent_req_data( 804 req, struct cli_qpathinfo2_state); 805 NTSTATUS status; 806 807 if (tevent_req_is_nterror(req, &status)) { 808 return status; 773 809 } 774 810 775 811 if (create_time) { 776 *create_time = interpret_long_date( rdata+0);812 *create_time = interpret_long_date((char *)state->data+0); 777 813 } 778 814 if (access_time) { 779 *access_time = interpret_long_date( rdata+8);815 *access_time = interpret_long_date((char *)state->data+8); 780 816 } 781 817 if (write_time) { 782 *write_time = interpret_long_date( rdata+16);818 *write_time = interpret_long_date((char *)state->data+16); 783 819 } 784 820 if (change_time) { 785 *change_time = interpret_long_date( rdata+24);821 *change_time = interpret_long_date((char *)state->data+24); 786 822 } 787 823 if (mode) { 788 *mode = SVAL( rdata, 32);824 *mode = SVAL(state->data, 32); 789 825 } 790 826 if (size) { 791 *size = IVAL2_TO_SMB_BIG_UINT( rdata,48);827 *size = IVAL2_TO_SMB_BIG_UINT(state->data,48); 792 828 } 793 829 if (ino) { 794 *ino = IVAL(rdata, 64); 795 } 796 797 SAFE_FREE(rdata); 798 SAFE_FREE(rparam); 799 return True; 830 *ino = IVAL(state->data, 64); 831 } 832 return NT_STATUS_OK; 833 } 834 835 NTSTATUS cli_qpathinfo2(struct cli_state *cli, const char *fname, 836 struct timespec *create_time, 837 struct timespec *access_time, 838 struct timespec *write_time, 839 struct timespec *change_time, 840 SMB_OFF_T *size, uint16 *mode, 841 SMB_INO_T *ino) 842 { 843 TALLOC_CTX *frame = talloc_stackframe(); 844 struct event_context *ev; 845 struct tevent_req *req; 846 NTSTATUS status = NT_STATUS_NO_MEMORY; 847 848 if (cli_has_async_calls(cli)) { 849 /* 850 * Can't use sync call while an async call is in flight 851 */ 852 status = NT_STATUS_INVALID_PARAMETER; 853 goto fail; 854 } 855 ev = event_context_init(frame); 856 if (ev == NULL) { 857 goto fail; 858 } 859 req = cli_qpathinfo2_send(frame, ev, cli, fname); 860 if (req == NULL) { 861 goto fail; 862 } 863 if (!tevent_req_poll_ntstatus(req, ev, &status)) { 864 goto fail; 865 } 866 status = cli_qpathinfo2_recv(req, create_time, access_time, 867 write_time, change_time, size, mode, ino); 868 fail: 869 TALLOC_FREE(frame); 870 if (!NT_STATUS_IS_OK(status)) { 871 cli_set_error(cli, status); 872 } 873 return status; 800 874 } 801 875 … … 804 878 ****************************************************************************/ 805 879 806 bool cli_qpathinfo_streams(struct cli_state *cli, const char *fname, 807 TALLOC_CTX *mem_ctx, 808 unsigned int *pnum_streams, 809 struct stream_struct **pstreams) 810 { 811 unsigned int data_len = 0; 812 unsigned int param_len = 0; 813 uint16 setup = TRANSACT2_QPATHINFO; 814 char *param; 815 char *rparam=NULL, *rdata=NULL; 816 char *p; 880 static bool parse_streams_blob(TALLOC_CTX *mem_ctx, const uint8_t *data, 881 size_t data_len, 882 unsigned int *pnum_streams, 883 struct stream_struct **pstreams); 884 885 struct cli_qpathinfo_streams_state { 886 uint32_t num_data; 887 uint8_t *data; 888 }; 889 890 static void cli_qpathinfo_streams_done(struct tevent_req *subreq); 891 892 struct tevent_req *cli_qpathinfo_streams_send(TALLOC_CTX *mem_ctx, 893 struct tevent_context *ev, 894 struct cli_state *cli, 895 const char *fname) 896 { 897 struct tevent_req *req = NULL, *subreq = NULL; 898 struct cli_qpathinfo_streams_state *state = NULL; 899 900 req = tevent_req_create(mem_ctx, &state, 901 struct cli_qpathinfo_streams_state); 902 if (req == NULL) { 903 return NULL; 904 } 905 subreq = cli_qpathinfo_send(state, ev, cli, fname, 906 SMB_FILE_STREAM_INFORMATION, 907 0, cli->max_xmit); 908 if (tevent_req_nomem(subreq, req)) { 909 return tevent_req_post(req, ev); 910 } 911 tevent_req_set_callback(subreq, cli_qpathinfo_streams_done, req); 912 return req; 913 } 914 915 static void cli_qpathinfo_streams_done(struct tevent_req *subreq) 916 { 917 struct tevent_req *req = tevent_req_callback_data( 918 subreq, struct tevent_req); 919 struct cli_qpathinfo_streams_state *state = tevent_req_data( 920 req, struct cli_qpathinfo_streams_state); 921 NTSTATUS status; 922 923 status = cli_qpathinfo_recv(subreq, state, &state->data, 924 &state->num_data); 925 TALLOC_FREE(subreq); 926 if (!NT_STATUS_IS_OK(status)) { 927 tevent_req_nterror(req, status); 928 return; 929 } 930 tevent_req_done(req); 931 } 932 933 NTSTATUS cli_qpathinfo_streams_recv(struct tevent_req *req, 934 TALLOC_CTX *mem_ctx, 935 unsigned int *pnum_streams, 936 struct stream_struct **pstreams) 937 { 938 struct cli_qpathinfo_streams_state *state = tevent_req_data( 939 req, struct cli_qpathinfo_streams_state); 940 NTSTATUS status; 941 942 if (tevent_req_is_nterror(req, &status)) { 943 return status; 944 } 945 if (!parse_streams_blob(mem_ctx, state->data, state->num_data, 946 pnum_streams, pstreams)) { 947 return NT_STATUS_INVALID_NETWORK_RESPONSE; 948 } 949 return NT_STATUS_OK; 950 } 951 952 NTSTATUS cli_qpathinfo_streams(struct cli_state *cli, const char *fname, 953 TALLOC_CTX *mem_ctx, 954 unsigned int *pnum_streams, 955 struct stream_struct **pstreams) 956 { 957 TALLOC_CTX *frame = talloc_stackframe(); 958 struct event_context *ev; 959 struct tevent_req *req; 960 NTSTATUS status = NT_STATUS_NO_MEMORY; 961 962 if (cli_has_async_calls(cli)) { 963 /* 964 * Can't use sync call while an async call is in flight 965 */ 966 status = NT_STATUS_INVALID_PARAMETER; 967 goto fail; 968 } 969 ev = event_context_init(frame); 970 if (ev == NULL) { 971 goto fail; 972 } 973 req = cli_qpathinfo_streams_send(frame, ev, cli, fname); 974 if (req == NULL) { 975 goto fail; 976 } 977 if (!tevent_req_poll_ntstatus(req, ev, &status)) { 978 goto fail; 979 } 980 status = cli_qpathinfo_streams_recv(req, mem_ctx, pnum_streams, 981 pstreams); 982 fail: 983 TALLOC_FREE(frame); 984 if (!NT_STATUS_IS_OK(status)) { 985 cli_set_error(cli, status); 986 } 987 return status; 988 } 989 990 static bool parse_streams_blob(TALLOC_CTX *mem_ctx, const uint8_t *rdata, 991 size_t data_len, 992 unsigned int *pnum_streams, 993 struct stream_struct **pstreams) 994 { 817 995 unsigned int num_streams; 818 996 struct stream_struct *streams; 819 997 unsigned int ofs; 820 size_t namelen = 2*(strlen(fname)+1);821 822 param = SMB_MALLOC_ARRAY(char, 6+namelen+2);823 if (param == NULL) {824 return false;825 }826 p = param;827 memset(p, 0, 6);828 SSVAL(p, 0, SMB_FILE_STREAM_INFORMATION);829 p += 6;830 p += clistr_push(cli, p, fname, namelen, STR_TERMINATE);831 832 param_len = PTR_DIFF(p, param);833 834 if (!cli_send_trans(cli, SMBtrans2,835 NULL, /* name */836 -1, 0, /* fid, flags */837 &setup, 1, 0, /* setup, len, max */838 param, param_len, 10, /* param, len, max */839 NULL, data_len, cli->max_xmit /* data, len, max */840 )) {841 return false;842 }843 844 if (!cli_receive_trans(cli, SMBtrans2,845 &rparam, ¶m_len,846 &rdata, &data_len)) {847 return false;848 }849 850 if (!rdata) {851 SAFE_FREE(rparam);852 return false;853 }854 998 855 999 num_streams = 0; … … 917 1061 } 918 1062 919 SAFE_FREE(rdata);920 SAFE_FREE(rparam);921 922 1063 *pnum_streams = num_streams; 923 1064 *pstreams = streams; … … 926 1067 fail: 927 1068 TALLOC_FREE(streams); 928 SAFE_FREE(rdata);929 SAFE_FREE(rparam);930 1069 return false; 931 1070 } … … 935 1074 ****************************************************************************/ 936 1075 937 bool cli_qfilename(struct cli_state *cli, uint16_t fnum, char *name, size_t namelen) 938 { 939 unsigned int data_len = 0; 940 unsigned int param_len = 0; 941 uint16 setup = TRANSACT2_QFILEINFO; 942 char param[4]; 943 char *rparam=NULL, *rdata=NULL; 944 945 param_len = 4; 946 SSVAL(param, 0, fnum); 947 SSVAL(param, 2, SMB_QUERY_FILE_NAME_INFO); 948 949 if (!cli_send_trans(cli, SMBtrans2, 950 NULL, /* name */ 951 -1, 0, /* fid, flags */ 952 &setup, 1, 0, /* setup, length, max */ 953 param, param_len, 2, /* param, length, max */ 954 NULL, data_len, cli->max_xmit /* data, length, max */ 955 )) { 956 return False; 957 } 958 959 if (!cli_receive_trans(cli, SMBtrans2, 960 &rparam, ¶m_len, 961 &rdata, &data_len)) { 962 return False; 963 } 964 965 if (!rdata || data_len < 4) { 966 SAFE_FREE(rparam); 967 SAFE_FREE(rdata); 968 return False; 1076 NTSTATUS cli_qfilename(struct cli_state *cli, uint16_t fnum, char *name, 1077 size_t namelen) 1078 { 1079 uint8_t *rdata; 1080 uint32_t num_rdata; 1081 NTSTATUS status; 1082 1083 status = cli_qfileinfo(talloc_tos(), cli, fnum, 1084 SMB_QUERY_FILE_NAME_INFO, 1085 4, cli->max_xmit, 1086 &rdata, &num_rdata); 1087 if (!NT_STATUS_IS_OK(status)) { 1088 return status; 969 1089 } 970 1090 971 1091 clistr_pull(cli->inbuf, name, rdata+4, namelen, IVAL(rdata, 0), 972 1092 STR_UNICODE); 973 974 SAFE_FREE(rparam); 975 SAFE_FREE(rdata); 976 977 return True; 1093 TALLOC_FREE(rdata); 1094 return NT_STATUS_OK; 978 1095 } 979 1096 … … 982 1099 ****************************************************************************/ 983 1100 984 bool cli_qfileinfo(struct cli_state *cli, uint16_t fnum, 985 uint16 *mode, SMB_OFF_T *size, 986 struct timespec *create_time, 987 struct timespec *access_time, 988 struct timespec *write_time, 989 struct timespec *change_time, 990 SMB_INO_T *ino) 991 { 992 unsigned int data_len = 0; 993 unsigned int param_len = 0; 994 uint16 setup; 995 uint8_t param[4]; 996 uint8_t *rparam=NULL, *rdata=NULL; 1101 NTSTATUS cli_qfileinfo_basic(struct cli_state *cli, uint16_t fnum, 1102 uint16 *mode, SMB_OFF_T *size, 1103 struct timespec *create_time, 1104 struct timespec *access_time, 1105 struct timespec *write_time, 1106 struct timespec *change_time, 1107 SMB_INO_T *ino) 1108 { 1109 uint8_t *rdata; 1110 uint32_t num_rdata; 997 1111 NTSTATUS status; 998 1112 999 1113 /* if its a win95 server then fail this - win95 totally screws it 1000 1114 up */ 1001 if (cli->win95) return False; 1002 1003 param_len = 4; 1004 1005 SSVAL(param, 0, fnum); 1006 SSVAL(param, 2, SMB_QUERY_FILE_ALL_INFO); 1007 1008 SSVAL(&setup, 0, TRANSACT2_QFILEINFO); 1009 1010 status = cli_trans(talloc_tos(), cli, SMBtrans2, 1011 NULL, -1, 0, 0, /* name, fid, function, flags */ 1012 &setup, 1, 0, /* setup, length, max */ 1013 param, param_len, 2, /* param, length, max */ 1014 NULL, 0, MIN(cli->max_xmit, 0xffff), /* data, length, max */ 1015 NULL, NULL, /* rsetup, length */ 1016 &rparam, ¶m_len, /* rparam, length */ 1017 &rdata, &data_len); 1018 1115 if (cli->win95) { 1116 return NT_STATUS_NOT_SUPPORTED; 1117 } 1118 1119 status = cli_qfileinfo(talloc_tos(), cli, fnum, 1120 SMB_QUERY_FILE_ALL_INFO, 1121 68, MIN(cli->max_xmit, 0xffff), 1122 &rdata, &num_rdata); 1019 1123 if (!NT_STATUS_IS_OK(status)) { 1020 return false; 1021 } 1022 1023 if (!rdata || data_len < 68) { 1024 return False; 1124 return status; 1025 1125 } 1026 1126 … … 1048 1148 1049 1149 TALLOC_FREE(rdata); 1050 TALLOC_FREE(rparam); 1051 return True; 1150 return NT_STATUS_OK; 1052 1151 } 1053 1152 … … 1056 1155 ****************************************************************************/ 1057 1156 1058 bool cli_qpathinfo_basic( struct cli_state *cli, const char *name, 1059 SMB_STRUCT_STAT *sbuf, uint32 *attributes ) 1060 { 1061 unsigned int param_len = 0; 1062 unsigned int data_len = 0; 1063 uint16 setup = TRANSACT2_QPATHINFO; 1064 char *param; 1065 char *rparam=NULL, *rdata=NULL; 1066 char *p; 1067 char *path; 1068 int len; 1069 size_t nlen; 1157 struct cli_qpathinfo_basic_state { 1158 uint32_t num_data; 1159 uint8_t *data; 1160 }; 1161 1162 static void cli_qpathinfo_basic_done(struct tevent_req *subreq); 1163 1164 struct tevent_req *cli_qpathinfo_basic_send(TALLOC_CTX *mem_ctx, 1165 struct event_context *ev, 1166 struct cli_state *cli, 1167 const char *fname) 1168 { 1169 struct tevent_req *req = NULL, *subreq = NULL; 1170 struct cli_qpathinfo_basic_state *state = NULL; 1171 1172 req = tevent_req_create(mem_ctx, &state, 1173 struct cli_qpathinfo_basic_state); 1174 if (req == NULL) { 1175 return NULL; 1176 } 1177 subreq = cli_qpathinfo_send(state, ev, cli, fname, 1178 SMB_QUERY_FILE_BASIC_INFO, 1179 36, cli->max_xmit); 1180 if (tevent_req_nomem(subreq, req)) { 1181 return tevent_req_post(req, ev); 1182 } 1183 tevent_req_set_callback(subreq, cli_qpathinfo_basic_done, req); 1184 return req; 1185 } 1186 1187 static void cli_qpathinfo_basic_done(struct tevent_req *subreq) 1188 { 1189 struct tevent_req *req = tevent_req_callback_data( 1190 subreq, struct tevent_req); 1191 struct cli_qpathinfo_basic_state *state = tevent_req_data( 1192 req, struct cli_qpathinfo_basic_state); 1193 NTSTATUS status; 1194 1195 status = cli_qpathinfo_recv(subreq, state, &state->data, 1196 &state->num_data); 1197 TALLOC_FREE(subreq); 1198 if (!NT_STATUS_IS_OK(status)) { 1199 tevent_req_nterror(req, status); 1200 return; 1201 } 1202 tevent_req_done(req); 1203 } 1204 1205 NTSTATUS cli_qpathinfo_basic_recv(struct tevent_req *req, 1206 SMB_STRUCT_STAT *sbuf, uint32 *attributes) 1207 { 1208 struct cli_qpathinfo_basic_state *state = tevent_req_data( 1209 req, struct cli_qpathinfo_basic_state); 1210 NTSTATUS status; 1211 1212 if (tevent_req_is_nterror(req, &status)) { 1213 return status; 1214 } 1215 1216 sbuf->st_ex_atime = interpret_long_date((char *)state->data+8); 1217 sbuf->st_ex_mtime = interpret_long_date((char *)state->data+16); 1218 sbuf->st_ex_ctime = interpret_long_date((char *)state->data+24); 1219 *attributes = IVAL(state->data, 32); 1220 return NT_STATUS_OK; 1221 } 1222 1223 NTSTATUS cli_qpathinfo_basic(struct cli_state *cli, const char *name, 1224 SMB_STRUCT_STAT *sbuf, uint32 *attributes) 1225 { 1070 1226 TALLOC_CTX *frame = talloc_stackframe(); 1071 1072 path = talloc_strdup(frame, name); 1073 if (!path) { 1074 TALLOC_FREE(frame); 1075 return false; 1076 } 1077 /* cleanup */ 1078 1079 len = strlen(path); 1080 if ( path[len-1] == '\\' || path[len-1] == '/') { 1081 path[len-1] = '\0'; 1082 } 1083 nlen = 2*(strlen(path)+1); 1084 1085 param = TALLOC_ARRAY(frame,char,6+nlen+2); 1086 if (!param) { 1087 return false; 1088 } 1089 p = param; 1090 memset(param, '\0', 6); 1091 1092 SSVAL(p, 0, SMB_QUERY_FILE_BASIC_INFO); 1093 p += 6; 1094 p += clistr_push(cli, p, path, nlen, STR_TERMINATE); 1095 param_len = PTR_DIFF(p, param); 1096 1097 1098 if (!cli_send_trans(cli, SMBtrans2, 1099 NULL, /* name */ 1100 -1, 0, /* fid, flags */ 1101 &setup, 1, 0, /* setup, length, max */ 1102 param, param_len, 2, /* param, length, max */ 1103 NULL, 0, cli->max_xmit /* data, length, max */ 1104 )) { 1105 TALLOC_FREE(frame); 1106 return False; 1107 } 1108 1227 struct event_context *ev; 1228 struct tevent_req *req; 1229 NTSTATUS status = NT_STATUS_NO_MEMORY; 1230 1231 if (cli_has_async_calls(cli)) { 1232 /* 1233 * Can't use sync call while an async call is in flight 1234 */ 1235 status = NT_STATUS_INVALID_PARAMETER; 1236 goto fail; 1237 } 1238 ev = event_context_init(frame); 1239 if (ev == NULL) { 1240 goto fail; 1241 } 1242 req = cli_qpathinfo_basic_send(frame, ev, cli, name); 1243 if (req == NULL) { 1244 goto fail; 1245 } 1246 if (!tevent_req_poll_ntstatus(req, ev, &status)) { 1247 goto fail; 1248 } 1249 status = cli_qpathinfo_basic_recv(req, sbuf, attributes); 1250 fail: 1109 1251 TALLOC_FREE(frame); 1110 1111 if (!cli_receive_trans(cli, SMBtrans2, 1112 &rparam, ¶m_len, 1113 &rdata, &data_len)) { 1114 return False; 1115 } 1116 1117 if (data_len < 36) { 1118 SAFE_FREE(rdata); 1119 SAFE_FREE(rparam); 1120 return False; 1121 } 1122 1123 sbuf->st_ex_atime = interpret_long_date( rdata+8 ); /* Access time. */ 1124 sbuf->st_ex_mtime = interpret_long_date( rdata+16 ); /* Write time. */ 1125 sbuf->st_ex_ctime = interpret_long_date( rdata+24 ); /* Change time. */ 1126 1127 *attributes = IVAL( rdata, 32 ); 1128 1129 SAFE_FREE(rparam); 1130 SAFE_FREE(rdata); 1131 1132 return True; 1133 } 1134 1135 /**************************************************************************** 1136 Send a qfileinfo call. 1137 ****************************************************************************/ 1138 1139 bool cli_qfileinfo_test(struct cli_state *cli, uint16_t fnum, int level, char **poutdata, uint32 *poutlen) 1140 { 1141 unsigned int data_len = 0; 1142 unsigned int param_len = 0; 1143 uint16 setup = TRANSACT2_QFILEINFO; 1144 char param[4]; 1145 char *rparam=NULL, *rdata=NULL; 1146 1147 *poutdata = NULL; 1148 *poutlen = 0; 1149 1150 /* if its a win95 server then fail this - win95 totally screws it 1151 up */ 1152 if (cli->win95) 1153 return False; 1154 1155 param_len = 4; 1156 1157 SSVAL(param, 0, fnum); 1158 SSVAL(param, 2, level); 1159 1160 if (!cli_send_trans(cli, SMBtrans2, 1161 NULL, /* name */ 1162 -1, 0, /* fid, flags */ 1163 &setup, 1, 0, /* setup, length, max */ 1164 param, param_len, 2, /* param, length, max */ 1165 NULL, data_len, cli->max_xmit /* data, length, max */ 1166 )) { 1167 return False; 1168 } 1169 1170 if (!cli_receive_trans(cli, SMBtrans2, 1171 &rparam, ¶m_len, 1172 &rdata, &data_len)) { 1173 return False; 1174 } 1175 1176 *poutdata = (char *)memdup(rdata, data_len); 1177 if (!*poutdata) { 1178 SAFE_FREE(rdata); 1179 SAFE_FREE(rparam); 1180 return False; 1181 } 1182 1183 *poutlen = data_len; 1184 1185 SAFE_FREE(rdata); 1186 SAFE_FREE(rparam); 1187 return True; 1252 if (!NT_STATUS_IS_OK(status)) { 1253 cli_set_error(cli, status); 1254 } 1255 return status; 1188 1256 } 1189 1257 … … 1194 1262 NTSTATUS cli_qpathinfo_alt_name(struct cli_state *cli, const char *fname, fstring alt_name) 1195 1263 { 1196 unsigned int data_len = 0; 1197 unsigned int param_len = 0; 1198 uint16 setup = TRANSACT2_QPATHINFO; 1199 char *param; 1200 char *rparam=NULL, *rdata=NULL; 1201 int count=8; 1202 char *p; 1203 bool ret; 1264 uint8_t *rdata; 1265 uint32_t num_rdata; 1204 1266 unsigned int len; 1205 size_t nlen = 2*(strlen(fname)+1); 1206 1207 param = SMB_MALLOC_ARRAY(char, 6+nlen+2); 1208 if (!param) { 1267 char *converted = NULL; 1268 size_t converted_size = 0; 1269 NTSTATUS status; 1270 1271 status = cli_qpathinfo(talloc_tos(), cli, fname, 1272 SMB_QUERY_FILE_ALT_NAME_INFO, 1273 4, cli->max_xmit, &rdata, &num_rdata); 1274 if (!NT_STATUS_IS_OK(status)) { 1275 return status; 1276 } 1277 1278 len = IVAL(rdata, 0); 1279 1280 if (len > num_rdata - 4) { 1281 return NT_STATUS_INVALID_NETWORK_RESPONSE; 1282 } 1283 1284 /* The returned data is a pushed string, not raw data. */ 1285 if (!convert_string_talloc(talloc_tos(), 1286 cli_ucs2(cli) ? CH_UTF16LE : CH_DOS, 1287 CH_UNIX, 1288 rdata + 4, 1289 len, 1290 &converted, 1291 &converted_size, 1292 true)) { 1209 1293 return NT_STATUS_NO_MEMORY; 1210 1294 } 1211 p = param; 1212 memset(param, '\0', 6); 1213 SSVAL(p, 0, SMB_QUERY_FILE_ALT_NAME_INFO); 1214 p += 6; 1215 p += clistr_push(cli, p, fname, nlen, STR_TERMINATE); 1216 param_len = PTR_DIFF(p, param); 1217 1218 do { 1219 ret = (cli_send_trans(cli, SMBtrans2, 1220 NULL, /* Name */ 1221 -1, 0, /* fid, flags */ 1222 &setup, 1, 0, /* setup, length, max */ 1223 param, param_len, 10, /* param, length, max */ 1224 NULL, data_len, cli->max_xmit /* data, length, max */ 1225 ) && 1226 cli_receive_trans(cli, SMBtrans2, 1227 &rparam, ¶m_len, 1228 &rdata, &data_len)); 1229 if (!ret && cli_is_dos_error(cli)) { 1230 /* we need to work around a Win95 bug - sometimes 1231 it gives ERRSRV/ERRerror temprarily */ 1232 uint8 eclass; 1233 uint32 ecode; 1234 cli_dos_error(cli, &eclass, &ecode); 1235 if (eclass != ERRSRV || ecode != ERRerror) break; 1236 smb_msleep(100); 1237 } 1238 } while (count-- && ret==False); 1239 1240 SAFE_FREE(param); 1241 1242 if (!ret || !rdata || data_len < 4) { 1243 return NT_STATUS_UNSUCCESSFUL; 1244 } 1245 1246 len = IVAL(rdata, 0); 1247 1248 if (len > data_len - 4) { 1249 return NT_STATUS_INVALID_NETWORK_RESPONSE; 1250 } 1251 1252 clistr_pull(cli->inbuf, alt_name, rdata+4, sizeof(fstring), len, 1253 STR_UNICODE); 1254 1255 SAFE_FREE(rdata); 1256 SAFE_FREE(rparam); 1295 fstrcpy(alt_name, converted); 1296 1297 TALLOC_FREE(converted); 1298 TALLOC_FREE(rdata); 1257 1299 1258 1300 return NT_STATUS_OK;
Note:
See TracChangeset
for help on using the changeset viewer.