s3:libsmb: don't reuse the callers stype variable in cli_NetServerEnum()
[ira/wip.git] / source3 / libsmb / clirap.c
index aab77a3d54f47223b87921ae16ccfb14421e4e1d..a9a13f7b96d3a2b0173761766f4dec86331d8c82 100644 (file)
 */
 
 #include "includes.h"
-
-/****************************************************************************
- Call a remote api on an arbitrary pipe.  takes param, data and setup buffers.
-****************************************************************************/
-
-bool cli_api_pipe(struct cli_state *cli, const char *pipe_name,
-                  uint16 *setup, uint32 setup_count, uint32 max_setup_count,
-                  char *params, uint32 param_count, uint32 max_param_count,
-                  char *data, uint32 data_count, uint32 max_data_count,
-                  char **rparam, uint32 *rparam_count,
-                  char **rdata, uint32 *rdata_count)
-{
-       cli_send_trans(cli, SMBtrans,
-                 pipe_name,
-                 0,0,                         /* fid, flags */
-                 setup, setup_count, max_setup_count,
-                 params, param_count, max_param_count,
-                 data, data_count, max_data_count);
-
-       return (cli_receive_trans(cli, SMBtrans,
-                            rparam, (unsigned int *)rparam_count,
-                            rdata, (unsigned int *)rdata_count));
-}
+#include "../libcli/auth/libcli_auth.h"
 
 /****************************************************************************
  Call a remote api
@@ -191,12 +169,13 @@ int cli_RNetShareEnum(struct cli_state *cli, void (*fn)(const char *, uint32, co
 
                                        sname = p;
                                        type = SVAL(p,14);
-                                       comment_offset = IVAL(p,16) & 0xFFFF;
-                                       if (comment_offset < 0 || comment_offset > (int)rdrcnt) {
+                                       comment_offset = (IVAL(p,16) & 0xFFFF) - converter;
+                                       if (comment_offset < 0 ||
+                                                       comment_offset > (int)rdrcnt) {
                                                TALLOC_FREE(frame);
                                                break;
                                        }
-                                       cmnt = comment_offset?(rdata+comment_offset-converter):"";
+                                       cmnt = comment_offset?(rdata+comment_offset):"";
 
                                        /* Work out the comment length. */
                                        for (p1 = cmnt, len = 0; *p1 &&
@@ -363,6 +342,7 @@ bool cli_NetServerEnum(struct cli_state *cli, char *workgroup, uint32 stype,
                                const char *p1;
                                char *s1, *s2;
                                TALLOC_CTX *frame = talloc_stackframe();
+                               uint32_t entry_stype;
 
                                if (p + 26 > rdata_end) {
                                        TALLOC_FREE(frame);
@@ -386,7 +366,7 @@ bool cli_NetServerEnum(struct cli_state *cli, char *workgroup, uint32 stype,
                                        len++;
                                }
 
-                               stype = IVAL(p,18) & ~SV_TYPE_LOCAL_LIST_ONLY;
+                               entry_stype = IVAL(p,18) & ~SV_TYPE_LOCAL_LIST_ONLY;
 
                                pull_string_talloc(frame,rdata,0,
                                        &s1,sname,16,STR_ASCII);
@@ -398,7 +378,7 @@ bool cli_NetServerEnum(struct cli_state *cli, char *workgroup, uint32 stype,
                                        continue;
                                }
 
-                               fn(s1, stype, s2, state);
+                               fn(s1, entry_stype, s2, state);
                                TALLOC_FREE(frame);
                        }
 
@@ -490,7 +470,7 @@ bool cli_oem_change_password(struct cli_state *cli, const char *user, const char
        DEBUG(100,("make_oem_passwd_hash\n"));
        dump_data(100, data, 516);
 #endif
-       SamOEMhash( (unsigned char *)data, (unsigned char *)old_pw_hash, 516);
+       arcfour_crypt( (unsigned char *)data, (unsigned char *)old_pw_hash, 516);
 
        /*
         * Now place the old password hash in the data.
@@ -805,11 +785,142 @@ bool cli_qpathinfo2(struct cli_state *cli, const char *fname,
        return True;
 }
 
+/****************************************************************************
+ Get the stream info
+****************************************************************************/
+
+bool cli_qpathinfo_streams(struct cli_state *cli, const char *fname,
+                          TALLOC_CTX *mem_ctx,
+                          unsigned int *pnum_streams,
+                          struct stream_struct **pstreams)
+{
+       unsigned int data_len = 0;
+       unsigned int param_len = 0;
+       uint16 setup = TRANSACT2_QPATHINFO;
+       char *param;
+       char *rparam=NULL, *rdata=NULL;
+       char *p;
+       unsigned int num_streams;
+       struct stream_struct *streams;
+       unsigned int ofs;
+       size_t namelen = 2*(strlen(fname)+1);
+
+       param = SMB_MALLOC_ARRAY(char, 6+namelen+2);
+       if (param == NULL) {
+               return false;
+       }
+       p = param;
+       memset(p, 0, 6);
+       SSVAL(p, 0, SMB_FILE_STREAM_INFORMATION);
+       p += 6;
+       p += clistr_push(cli, p, fname, namelen, STR_TERMINATE);
+
+       param_len = PTR_DIFF(p, param);
+
+       if (!cli_send_trans(cli, SMBtrans2,
+                            NULL,                     /* name */
+                            -1, 0,                    /* fid, flags */
+                            &setup, 1, 0,             /* setup, len, max */
+                            param, param_len, 10,     /* param, len, max */
+                            NULL, data_len, cli->max_xmit /* data, len, max */
+                           )) {
+               return false;
+       }
+
+       if (!cli_receive_trans(cli, SMBtrans2,
+                               &rparam, &param_len,
+                               &rdata, &data_len)) {
+               return false;
+       }
+
+       if (!rdata) {
+               SAFE_FREE(rparam);
+               return false;
+       }
+
+       num_streams = 0;
+       streams = NULL;
+       ofs = 0;
+
+       while ((data_len > ofs) && (data_len - ofs >= 24)) {
+               uint32_t nlen, len;
+               size_t size;
+               void *vstr;
+               struct stream_struct *tmp;
+               uint8_t *tmp_buf;
+
+               tmp = TALLOC_REALLOC_ARRAY(mem_ctx, streams,
+                                          struct stream_struct,
+                                          num_streams+1);
+
+               if (tmp == NULL) {
+                       goto fail;
+               }
+               streams = tmp;
+
+               nlen                      = IVAL(rdata, ofs + 0x04);
+
+               streams[num_streams].size = IVAL_TO_SMB_OFF_T(
+                       rdata, ofs + 0x08);
+               streams[num_streams].alloc_size = IVAL_TO_SMB_OFF_T(
+                       rdata, ofs + 0x10);
+
+               if (nlen > data_len - (ofs + 24)) {
+                       goto fail;
+               }
+
+               /*
+                * We need to null-terminate src, how do I do this with
+                * convert_string_talloc??
+                */
+
+               tmp_buf = TALLOC_ARRAY(streams, uint8_t, nlen+2);
+               if (tmp_buf == NULL) {
+                       goto fail;
+               }
+
+               memcpy(tmp_buf, rdata+ofs+24, nlen);
+               tmp_buf[nlen] = 0;
+               tmp_buf[nlen+1] = 0;
+
+               if (!convert_string_talloc(streams, CH_UTF16, CH_UNIX, tmp_buf,
+                                          nlen+2, &vstr, &size, false))
+               {
+                       TALLOC_FREE(tmp_buf);
+                       goto fail;
+               }
+
+               TALLOC_FREE(tmp_buf);
+               streams[num_streams].name = (char *)vstr;
+               num_streams++;
+
+               len = IVAL(rdata, ofs);
+               if (len > data_len - ofs) {
+                       goto fail;
+               }
+               if (len == 0) break;
+               ofs += len;
+       }
+
+       SAFE_FREE(rdata);
+       SAFE_FREE(rparam);
+
+       *pnum_streams = num_streams;
+       *pstreams = streams;
+       return true;
+
+ fail:
+       TALLOC_FREE(streams);
+       SAFE_FREE(rdata);
+       SAFE_FREE(rparam);
+       return false;
+}
+
 /****************************************************************************
  Send a qfileinfo QUERY_FILE_NAME_INFO call.
 ****************************************************************************/
 
-bool cli_qfilename(struct cli_state *cli, int fnum, char *name, size_t namelen)
+bool cli_qfilename(struct cli_state *cli, uint16_t fnum, char *name, size_t namelen)
 {
        unsigned int data_len = 0;
        unsigned int param_len = 0;
@@ -838,10 +949,16 @@ bool cli_qfilename(struct cli_state *cli, int fnum, char *name, size_t namelen)
        }
 
        if (!rdata || data_len < 4) {
+               SAFE_FREE(rparam);
+               SAFE_FREE(rdata);
                return False;
        }
 
-       clistr_pull(cli, name, rdata+4, namelen, IVAL(rdata, 0), STR_UNICODE);
+       clistr_pull(cli->inbuf, name, rdata+4, namelen, IVAL(rdata, 0),
+                   STR_UNICODE);
+
+       SAFE_FREE(rparam);
+       SAFE_FREE(rdata);
 
        return True;
 }
@@ -850,7 +967,7 @@ bool cli_qfilename(struct cli_state *cli, int fnum, char *name, size_t namelen)
  Send a qfileinfo call.
 ****************************************************************************/
 
-bool cli_qfileinfo(struct cli_state *cli, int fnum,
+bool cli_qfileinfo(struct cli_state *cli, uint16_t fnum,
                   uint16 *mode, SMB_OFF_T *size,
                   struct timespec *create_time,
                    struct timespec *access_time,
@@ -858,52 +975,45 @@ bool cli_qfileinfo(struct cli_state *cli, int fnum,
                   struct timespec *change_time,
                    SMB_INO_T *ino)
 {
-       unsigned int data_len = 0;
-       unsigned int param_len = 0;
-       uint16 setup = TRANSACT2_QFILEINFO;
-       char param[4];
-       char *rparam=NULL, *rdata=NULL;
+       uint32_t data_len = 0;
+       uint16 setup;
+       uint8_t param[4];
+       uint8_t *rdata=NULL;
+       NTSTATUS status;
 
        /* if its a win95 server then fail this - win95 totally screws it
           up */
        if (cli->win95) return False;
 
-       param_len = 4;
-
        SSVAL(param, 0, fnum);
        SSVAL(param, 2, SMB_QUERY_FILE_ALL_INFO);
 
-       if (!cli_send_trans(cli, SMBtrans2,
-                            NULL,                         /* name */
-                            -1, 0,                        /* fid, flags */
-                            &setup, 1, 0,                 /* setup, length, max */
-                            param, param_len, 2,          /* param, length, max */
-                            NULL, data_len, cli->max_xmit /* data, length, max */
-                           )) {
-               return False;
-       }
+       SSVAL(&setup, 0, TRANSACT2_QFILEINFO);
 
-       if (!cli_receive_trans(cli, SMBtrans2,
-                               &rparam, &param_len,
-                               &rdata, &data_len)) {
-               return False;
-       }
+       status = cli_trans(talloc_tos(), cli, SMBtrans2,
+                          NULL, -1, 0, 0, /* name, fid, function, flags */
+                          &setup, 1, 0,          /* setup, length, max */
+                          param, 4, 2,   /* param, length, max */
+                          NULL, 0, MIN(cli->max_xmit, 0xffff), /* data, length, max */
+                          NULL, 0, NULL, /* rsetup, length */
+                          NULL, 0, NULL,       /* rparam, length */
+                          &rdata, 68, &data_len);
 
-       if (!rdata || data_len < 68) {
-               return False;
+       if (!NT_STATUS_IS_OK(status)) {
+               return false;
        }
 
        if (create_time) {
-               *create_time = interpret_long_date(rdata+0);
+               *create_time = interpret_long_date((char *)rdata+0);
        }
        if (access_time) {
-               *access_time = interpret_long_date(rdata+8);
+               *access_time = interpret_long_date((char *)rdata+8);
        }
        if (write_time) {
-               *write_time = interpret_long_date(rdata+16);
+               *write_time = interpret_long_date((char *)rdata+16);
        }
        if (change_time) {
-               *change_time = interpret_long_date(rdata+24);
+               *change_time = interpret_long_date((char *)rdata+24);
        }
        if (mode) {
                *mode = SVAL(rdata, 32);
@@ -915,8 +1025,7 @@ bool cli_qfileinfo(struct cli_state *cli, int fnum,
                *ino = IVAL(rdata, 64);
        }
 
-       SAFE_FREE(rdata);
-       SAFE_FREE(rparam);
+       TALLOC_FREE(rdata);
        return True;
 }
 
@@ -989,9 +1098,9 @@ bool cli_qpathinfo_basic( struct cli_state *cli, const char *name,
                return False;
        }
 
-       set_atimespec(sbuf, interpret_long_date( rdata+8 )); /* Access time. */
-       set_mtimespec(sbuf, interpret_long_date( rdata+16 )); /* Write time. */
-       set_ctimespec(sbuf, interpret_long_date( rdata+24 )); /* Change time. */
+       sbuf->st_ex_atime = interpret_long_date( rdata+8 ); /* Access time. */
+       sbuf->st_ex_mtime = interpret_long_date( rdata+16 ); /* Write time. */
+       sbuf->st_ex_ctime = interpret_long_date( rdata+24 ); /* Change time. */
 
        *attributes = IVAL( rdata, 32 );
 
@@ -1005,7 +1114,7 @@ bool cli_qpathinfo_basic( struct cli_state *cli, const char *name,
  Send a qfileinfo call.
 ****************************************************************************/
 
-bool cli_qfileinfo_test(struct cli_state *cli, int fnum, int level, char **poutdata, uint32 *poutlen)
+bool cli_qfileinfo_test(struct cli_state *cli, uint16_t fnum, int level, char **poutdata, uint32 *poutlen)
 {
        unsigned int data_len = 0;
        unsigned int param_len = 0;
@@ -1118,7 +1227,8 @@ NTSTATUS cli_qpathinfo_alt_name(struct cli_state *cli, const char *fname, fstrin
                return NT_STATUS_INVALID_NETWORK_RESPONSE;
        }
 
-       clistr_pull(cli, alt_name, rdata+4, sizeof(fstring), len, STR_UNICODE);
+       clistr_pull(cli->inbuf, alt_name, rdata+4, sizeof(fstring), len,
+                   STR_UNICODE);
 
        SAFE_FREE(rdata);
        SAFE_FREE(rparam);