s3: Save the received trans2 from the inbuf in cli_trans
[metze/samba/wip.git] / source3 / libsmb / clirap.c
1 /*
2    Unix SMB/CIFS implementation.
3    client RAP calls
4    Copyright (C) Andrew Tridgell         1994-1998
5    Copyright (C) Gerald (Jerry) Carter   2004
6    Copyright (C) James Peach             2007
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 #include "includes.h"
23 #include "../libcli/auth/libcli_auth.h"
24 #include "../librpc/gen_ndr/rap.h"
25 #include "../lib/crypto/arcfour.h"
26
27 /****************************************************************************
28  Call a remote api
29 ****************************************************************************/
30
31 bool cli_api(struct cli_state *cli,
32              char *param, int prcnt, int mprcnt,
33              char *data, int drcnt, int mdrcnt,
34              char **rparam, unsigned int *rprcnt,
35              char **rdata, unsigned int *rdrcnt)
36 {
37         cli_send_trans(cli,SMBtrans,
38                  PIPE_LANMAN,             /* Name */
39                  0,0,                     /* fid, flags */
40                  NULL,0,0,                /* Setup, length, max */
41                  param, prcnt, mprcnt,    /* Params, length, max */
42                  data, drcnt, mdrcnt      /* Data, length, max */
43                 );
44
45         return (cli_receive_trans(cli,SMBtrans,
46                             rparam, rprcnt,
47                             rdata, rdrcnt));
48 }
49
50 /****************************************************************************
51  Perform a NetWkstaUserLogon.
52 ****************************************************************************/
53
54 bool cli_NetWkstaUserLogon(struct cli_state *cli,char *user, char *workstation)
55 {
56         char *rparam = NULL;
57         char *rdata = NULL;
58         char *p;
59         unsigned int rdrcnt,rprcnt;
60         char param[1024];
61
62         memset(param, 0, sizeof(param));
63
64         /* send a SMBtrans command with api NetWkstaUserLogon */
65         p = param;
66         SSVAL(p,0,132); /* api number */
67         p += 2;
68         strlcpy(p,"OOWb54WrLh",sizeof(param)-PTR_DIFF(p,param));
69         p = skip_string(param,sizeof(param),p);
70         strlcpy(p,"WB21BWDWWDDDDDDDzzzD",sizeof(param)-PTR_DIFF(p,param));
71         p = skip_string(param,sizeof(param),p);
72         SSVAL(p,0,1);
73         p += 2;
74         strlcpy(p,user,sizeof(param)-PTR_DIFF(p,param));
75         strupper_m(p);
76         p += 21;
77         p++;
78         p += 15;
79         p++;
80         strlcpy(p, workstation,sizeof(param)-PTR_DIFF(p,param));
81         strupper_m(p);
82         p += 16;
83         SSVAL(p, 0, CLI_BUFFER_SIZE);
84         p += 2;
85         SSVAL(p, 0, CLI_BUFFER_SIZE);
86         p += 2;
87
88         if (cli_api(cli,
89                     param, PTR_DIFF(p,param),1024,  /* param, length, max */
90                     NULL, 0, CLI_BUFFER_SIZE,           /* data, length, max */
91                     &rparam, &rprcnt,               /* return params, return size */
92                     &rdata, &rdrcnt                 /* return data, return size */
93                    )) {
94                 cli->rap_error = rparam? SVAL(rparam,0) : -1;
95                 p = rdata;
96
97                 if (cli->rap_error == 0) {
98                         DEBUG(4,("NetWkstaUserLogon success\n"));
99                         cli->privileges = SVAL(p, 24);
100                         /* The cli->eff_name field used to be set here
101                            but it wasn't used anywhere else. */
102                 } else {
103                         DEBUG(1,("NetwkstaUserLogon gave error %d\n", cli->rap_error));
104                 }
105         }
106
107         SAFE_FREE(rparam);
108         SAFE_FREE(rdata);
109         return (cli->rap_error == 0);
110 }
111
112 /****************************************************************************
113  Call a NetShareEnum - try and browse available connections on a host.
114 ****************************************************************************/
115
116 int cli_RNetShareEnum(struct cli_state *cli, void (*fn)(const char *, uint32, const char *, void *), void *state)
117 {
118         char *rparam = NULL;
119         char *rdata = NULL;
120         char *p;
121         unsigned int rdrcnt,rprcnt;
122         char param[1024];
123         int count = -1;
124
125         /* now send a SMBtrans command with api RNetShareEnum */
126         p = param;
127         SSVAL(p,0,0); /* api number */
128         p += 2;
129         strlcpy(p,"WrLeh",sizeof(param)-PTR_DIFF(p,param));
130         p = skip_string(param,sizeof(param),p);
131         strlcpy(p,"B13BWz",sizeof(param)-PTR_DIFF(p,param));
132         p = skip_string(param,sizeof(param),p);
133         SSVAL(p,0,1);
134         /*
135          * Win2k needs a *smaller* buffer than 0xFFFF here -
136          * it returns "out of server memory" with 0xFFFF !!! JRA.
137          */
138         SSVAL(p,2,0xFFE0);
139         p += 4;
140
141         if (cli_api(cli,
142                     param, PTR_DIFF(p,param), 1024,  /* Param, length, maxlen */
143                     NULL, 0, 0xFFE0,            /* data, length, maxlen - Win2k needs a small buffer here too ! */
144                     &rparam, &rprcnt,                /* return params, length */
145                     &rdata, &rdrcnt))                /* return data, length */
146                 {
147                         int res = rparam? SVAL(rparam,0) : -1;
148
149                         if (res == 0 || res == ERRmoredata) {
150                                 int converter=SVAL(rparam,2);
151                                 int i;
152                                 char *rdata_end = rdata + rdrcnt;
153
154                                 count=SVAL(rparam,4);
155                                 p = rdata;
156
157                                 for (i=0;i<count;i++,p+=20) {
158                                         char *sname;
159                                         int type;
160                                         int comment_offset;
161                                         const char *cmnt;
162                                         const char *p1;
163                                         char *s1, *s2;
164                                         size_t len;
165                                         TALLOC_CTX *frame = talloc_stackframe();
166
167                                         if (p + 20 > rdata_end) {
168                                                 TALLOC_FREE(frame);
169                                                 break;
170                                         }
171
172                                         sname = p;
173                                         type = SVAL(p,14);
174                                         comment_offset = (IVAL(p,16) & 0xFFFF) - converter;
175                                         if (comment_offset < 0 ||
176                                                         comment_offset > (int)rdrcnt) {
177                                                 TALLOC_FREE(frame);
178                                                 break;
179                                         }
180                                         cmnt = comment_offset?(rdata+comment_offset):"";
181
182                                         /* Work out the comment length. */
183                                         for (p1 = cmnt, len = 0; *p1 &&
184                                                         p1 < rdata_end; len++)
185                                                 p1++;
186                                         if (!*p1) {
187                                                 len++;
188                                         }
189                                         pull_string_talloc(frame,rdata,0,
190                                                 &s1,sname,14,STR_ASCII);
191                                         pull_string_talloc(frame,rdata,0,
192                                                 &s2,cmnt,len,STR_ASCII);
193                                         if (!s1 || !s2) {
194                                                 TALLOC_FREE(frame);
195                                                 continue;
196                                         }
197
198                                         fn(s1, type, s2, state);
199
200                                         TALLOC_FREE(frame);
201                                 }
202                         } else {
203                                 DEBUG(4,("NetShareEnum res=%d\n", res));
204                         }
205                 } else {
206                         DEBUG(4,("NetShareEnum failed\n"));
207                 }
208
209         SAFE_FREE(rparam);
210         SAFE_FREE(rdata);
211
212         return count;
213 }
214
215 /****************************************************************************
216  Call a NetServerEnum for the specified workgroup and servertype mask.  This
217  function then calls the specified callback function for each name returned.
218
219  The callback function takes 4 arguments: the machine name, the server type,
220  the comment and a state pointer.
221 ****************************************************************************/
222
223 bool cli_NetServerEnum(struct cli_state *cli, char *workgroup, uint32 stype,
224                        void (*fn)(const char *, uint32, const char *, void *),
225                        void *state)
226 {
227         char *rparam = NULL;
228         char *rdata = NULL;
229         char *rdata_end = NULL;
230         unsigned int rdrcnt,rprcnt;
231         char *p;
232         char param[1024];
233         int uLevel = 1;
234         size_t len;
235         uint32 func = RAP_NetServerEnum2;
236         char *last_entry = NULL;
237         int total_cnt = 0;
238         int return_cnt = 0;
239         int res;
240
241         errno = 0; /* reset */
242
243         /*
244          * This may take more than one transaction, so we should loop until
245          * we no longer get a more data to process or we have all of the
246          * items.
247          */
248         do {
249                 /* send a SMBtrans command with api NetServerEnum */
250                 p = param;
251                 SIVAL(p,0,func); /* api number */
252                 p += 2;
253
254                 if (func == RAP_NetServerEnum3) {
255                         strlcpy(p,"WrLehDzz", sizeof(param)-PTR_DIFF(p,param));
256                 } else {
257                         strlcpy(p,"WrLehDz", sizeof(param)-PTR_DIFF(p,param));
258                 }
259
260                 p = skip_string(param, sizeof(param), p);
261                 strlcpy(p,"B16BBDz", sizeof(param)-PTR_DIFF(p,param));
262
263                 p = skip_string(param, sizeof(param), p);
264                 SSVAL(p,0,uLevel);
265                 SSVAL(p,2,CLI_BUFFER_SIZE);
266                 p += 4;
267                 SIVAL(p,0,stype);
268                 p += 4;
269
270                 /* If we have more data, tell the server where
271                  * to continue from.
272                  */
273                 len = push_ascii(p,
274                                 workgroup,
275                                 sizeof(param) - PTR_DIFF(p,param) - 1,
276                                 STR_TERMINATE|STR_UPPER);
277
278                 if (len == (size_t)-1) {
279                         SAFE_FREE(last_entry);
280                         return false;
281                 }
282                 p += len;
283
284                 if (func == RAP_NetServerEnum3) {
285                         len = push_ascii(p,
286                                         last_entry ? last_entry : "",
287                                         sizeof(param) - PTR_DIFF(p,param) - 1,
288                                         STR_TERMINATE);
289
290                         if (len == (size_t)-1) {
291                                 SAFE_FREE(last_entry);
292                                 return false;
293                         }
294                         p += len;
295                 }
296
297                 /* Next time through we need to use the continue api */
298                 func = RAP_NetServerEnum3;
299
300                 if (!cli_api(cli,
301                         param, PTR_DIFF(p,param), 8, /* params, length, max */
302                         NULL, 0, CLI_BUFFER_SIZE, /* data, length, max */
303                             &rparam, &rprcnt, /* return params, return size */
304                             &rdata, &rdrcnt)) { /* return data, return size */
305
306                         /* break out of the loop on error */
307                         res = -1;
308                         break;
309                 }
310
311                 rdata_end = rdata + rdrcnt;
312                 res = rparam ? SVAL(rparam,0) : -1;
313
314                 if (res == 0 || res == ERRmoredata ||
315                     (res != -1 && cli_errno(cli) == 0)) {
316                         char *sname = NULL;
317                         int i, count;
318                         int converter=SVAL(rparam,2);
319
320                         /* Get the number of items returned in this buffer */
321                         count = SVAL(rparam, 4);
322
323                         /* The next field contains the number of items left,
324                          * including those returned in this buffer. So the
325                          * first time through this should contain all of the
326                          * entries.
327                          */
328                         if (total_cnt == 0) {
329                                 total_cnt = SVAL(rparam, 6);
330                         }
331
332                         /* Keep track of how many we have read */
333                         return_cnt += count;
334                         p = rdata;
335
336                         /* The last name in the previous NetServerEnum reply is
337                          * sent back to server in the NetServerEnum3 request
338                          * (last_entry). The next reply should repeat this entry
339                          * as the first element. We have no proof that this is
340                          * always true, but from traces that seems to be the
341                          * behavior from Window Servers. So first lets do a lot
342                          * of checking, just being paranoid. If the string
343                          * matches then we already saw this entry so skip it.
344                          *
345                          * NOTE: sv1_name field must be null terminated and has
346                          * a max size of 16 (NetBIOS Name).
347                          */
348                         if (last_entry && count && p &&
349                                 (strncmp(last_entry, p, 16) == 0)) {
350                             count -= 1; /* Skip this entry */
351                             return_cnt = -1; /* Not part of total, so don't count. */
352                             p = rdata + 26; /* Skip the whole record */
353                         }
354
355                         for (i = 0; i < count; i++, p += 26) {
356                                 int comment_offset;
357                                 const char *cmnt;
358                                 const char *p1;
359                                 char *s1, *s2;
360                                 TALLOC_CTX *frame = talloc_stackframe();
361                                 uint32_t entry_stype;
362
363                                 if (p + 26 > rdata_end) {
364                                         TALLOC_FREE(frame);
365                                         break;
366                                 }
367
368                                 sname = p;
369                                 comment_offset = (IVAL(p,22) & 0xFFFF)-converter;
370                                 cmnt = comment_offset?(rdata+comment_offset):"";
371
372                                 if (comment_offset < 0 || comment_offset >= (int)rdrcnt) {
373                                         TALLOC_FREE(frame);
374                                         continue;
375                                 }
376
377                                 /* Work out the comment length. */
378                                 for (p1 = cmnt, len = 0; *p1 &&
379                                                 p1 < rdata_end; len++)
380                                         p1++;
381                                 if (!*p1) {
382                                         len++;
383                                 }
384
385                                 entry_stype = IVAL(p,18) & ~SV_TYPE_LOCAL_LIST_ONLY;
386
387                                 pull_string_talloc(frame,rdata,0,
388                                         &s1,sname,16,STR_ASCII);
389                                 pull_string_talloc(frame,rdata,0,
390                                         &s2,cmnt,len,STR_ASCII);
391
392                                 if (!s1 || !s2) {
393                                         TALLOC_FREE(frame);
394                                         continue;
395                                 }
396
397                                 fn(s1, entry_stype, s2, state);
398                                 TALLOC_FREE(frame);
399                         }
400
401                         /* We are done with the old last entry, so now we can free it */
402                         if (last_entry) {
403                                 SAFE_FREE(last_entry); /* This will set it to null */
404                         }
405
406                         /* We always make a copy of  the last entry if we have one */
407                         if (sname) {
408                                 last_entry = smb_xstrdup(sname);
409                         }
410
411                         /* If we have more data, but no last entry then error out */
412                         if (!last_entry && (res == ERRmoredata)) {
413                                 errno = EINVAL;
414                                 res = 0;
415                         }
416
417                 }
418
419                 SAFE_FREE(rparam);
420                 SAFE_FREE(rdata);
421         } while ((res == ERRmoredata) && (total_cnt > return_cnt));
422
423         SAFE_FREE(rparam);
424         SAFE_FREE(rdata);
425         SAFE_FREE(last_entry);
426
427         if (res == -1) {
428                 errno = cli_errno(cli);
429         } else {
430                 if (!return_cnt) {
431                         /* this is a very special case, when the domain master for the
432                            work group isn't part of the work group itself, there is something
433                            wild going on */
434                         errno = ENOENT;
435                 }
436             }
437
438         return(return_cnt > 0);
439 }
440
441 /****************************************************************************
442  Send a SamOEMChangePassword command.
443 ****************************************************************************/
444
445 bool cli_oem_change_password(struct cli_state *cli, const char *user, const char *new_password,
446                              const char *old_password)
447 {
448         char param[1024];
449         unsigned char data[532];
450         char *p = param;
451         unsigned char old_pw_hash[16];
452         unsigned char new_pw_hash[16];
453         unsigned int data_len;
454         unsigned int param_len = 0;
455         char *rparam = NULL;
456         char *rdata = NULL;
457         unsigned int rprcnt, rdrcnt;
458
459         if (strlen(user) >= sizeof(fstring)-1) {
460                 DEBUG(0,("cli_oem_change_password: user name %s is too long.\n", user));
461                 return False;
462         }
463
464         SSVAL(p,0,214); /* SamOEMChangePassword command. */
465         p += 2;
466         strlcpy(p, "zsT", sizeof(param)-PTR_DIFF(p,param));
467         p = skip_string(param,sizeof(param),p);
468         strlcpy(p, "B516B16", sizeof(param)-PTR_DIFF(p,param));
469         p = skip_string(param,sizeof(param),p);
470         strlcpy(p,user, sizeof(param)-PTR_DIFF(p,param));
471         p = skip_string(param,sizeof(param),p);
472         SSVAL(p,0,532);
473         p += 2;
474
475         param_len = PTR_DIFF(p,param);
476
477         /*
478          * Get the Lanman hash of the old password, we
479          * use this as the key to make_oem_passwd_hash().
480          */
481         E_deshash(old_password, old_pw_hash);
482
483         encode_pw_buffer(data, new_password, STR_ASCII);
484
485 #ifdef DEBUG_PASSWORD
486         DEBUG(100,("make_oem_passwd_hash\n"));
487         dump_data(100, data, 516);
488 #endif
489         arcfour_crypt( (unsigned char *)data, (unsigned char *)old_pw_hash, 516);
490
491         /*
492          * Now place the old password hash in the data.
493          */
494         E_deshash(new_password, new_pw_hash);
495
496         E_old_pw_hash( new_pw_hash, old_pw_hash, (uchar *)&data[516]);
497
498         data_len = 532;
499
500         if (cli_send_trans(cli,SMBtrans,
501                     PIPE_LANMAN,                          /* name */
502                     0,0,                                  /* fid, flags */
503                     NULL,0,0,                             /* setup, length, max */
504                     param,param_len,4,                    /* param, length, max */
505                     (char *)data,data_len,0                       /* data, length, max */
506                    ) == False) {
507                 DEBUG(0,("cli_oem_change_password: Failed to send password change for user %s\n",
508                         user ));
509                 return False;
510         }
511
512         if (!cli_receive_trans(cli,SMBtrans,
513                        &rparam, &rprcnt,
514                        &rdata, &rdrcnt)) {
515                 DEBUG(0,("cli_oem_change_password: Failed to recieve reply to password change for user %s\n",
516                         user ));
517                 return False;
518         }
519
520         if (rparam) {
521                 cli->rap_error = SVAL(rparam,0);
522         }
523
524         SAFE_FREE(rparam);
525         SAFE_FREE(rdata);
526
527         return (cli->rap_error == 0);
528 }
529
530 /****************************************************************************
531  Send a qpathinfo call.
532 ****************************************************************************/
533
534 struct cli_qpathinfo1_state {
535         struct cli_state *cli;
536         uint32_t num_data;
537         uint8_t *data;
538 };
539
540 static void cli_qpathinfo1_done(struct tevent_req *subreq);
541
542 struct tevent_req *cli_qpathinfo1_send(TALLOC_CTX *mem_ctx,
543                                        struct event_context *ev,
544                                        struct cli_state *cli,
545                                        const char *fname)
546 {
547         struct tevent_req *req = NULL, *subreq = NULL;
548         struct cli_qpathinfo1_state *state = NULL;
549
550         req = tevent_req_create(mem_ctx, &state, struct cli_qpathinfo1_state);
551         if (req == NULL) {
552                 return NULL;
553         }
554         state->cli = cli;
555         subreq = cli_qpathinfo_send(state, ev, cli, fname, SMB_INFO_STANDARD,
556                                     22, cli->max_xmit);
557         if (tevent_req_nomem(subreq, req)) {
558                 return tevent_req_post(req, ev);
559         }
560         tevent_req_set_callback(subreq, cli_qpathinfo1_done, req);
561         return req;
562 }
563
564 static void cli_qpathinfo1_done(struct tevent_req *subreq)
565 {
566         struct tevent_req *req = tevent_req_callback_data(
567                 subreq, struct tevent_req);
568         struct cli_qpathinfo1_state *state = tevent_req_data(
569                 req, struct cli_qpathinfo1_state);
570         NTSTATUS status;
571
572         status = cli_qpathinfo_recv(subreq, state, &state->data,
573                                     &state->num_data);
574         TALLOC_FREE(subreq);
575         if (!NT_STATUS_IS_OK(status)) {
576                 tevent_req_nterror(req, status);
577                 return;
578         }
579         tevent_req_done(req);
580 }
581
582 NTSTATUS cli_qpathinfo1_recv(struct tevent_req *req,
583                              time_t *change_time,
584                              time_t *access_time,
585                              time_t *write_time,
586                              SMB_OFF_T *size,
587                              uint16 *mode)
588 {
589         struct cli_qpathinfo1_state *state = tevent_req_data(
590                 req, struct cli_qpathinfo1_state);
591         NTSTATUS status;
592
593         time_t (*date_fn)(struct cli_state *, const void *);
594
595         if (tevent_req_is_nterror(req, &status)) {
596                 return status;
597         }
598
599         if (state->cli->win95) {
600                 date_fn = cli_make_unix_date;
601         } else {
602                 date_fn = cli_make_unix_date2;
603         }
604
605         if (change_time) {
606                 *change_time = date_fn(state->cli, state->data+0);
607         }
608         if (access_time) {
609                 *access_time = date_fn(state->cli, state->data+4);
610         }
611         if (write_time) {
612                 *write_time = date_fn(state->cli, state->data+8);
613         }
614         if (size) {
615                 *size = IVAL(state->data, 12);
616         }
617         if (mode) {
618                 *mode = SVAL(state->data, l1_attrFile);
619         }
620         return NT_STATUS_OK;
621 }
622
623 NTSTATUS cli_qpathinfo1(struct cli_state *cli,
624                         const char *fname,
625                         time_t *change_time,
626                         time_t *access_time,
627                         time_t *write_time,
628                         SMB_OFF_T *size,
629                         uint16 *mode)
630 {
631         TALLOC_CTX *frame = talloc_stackframe();
632         struct event_context *ev;
633         struct tevent_req *req;
634         NTSTATUS status = NT_STATUS_NO_MEMORY;
635
636         if (cli_has_async_calls(cli)) {
637                 /*
638                  * Can't use sync call while an async call is in flight
639                  */
640                 status = NT_STATUS_INVALID_PARAMETER;
641                 goto fail;
642         }
643         ev = event_context_init(frame);
644         if (ev == NULL) {
645                 goto fail;
646         }
647         req = cli_qpathinfo1_send(frame, ev, cli, fname);
648         if (req == NULL) {
649                 goto fail;
650         }
651         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
652                 goto fail;
653         }
654         status = cli_qpathinfo1_recv(req, change_time, access_time,
655                                      write_time, size, mode);
656  fail:
657         TALLOC_FREE(frame);
658         if (!NT_STATUS_IS_OK(status)) {
659                 cli_set_error(cli, status);
660         }
661         return status;
662 }
663
664 /****************************************************************************
665  Send a setpathinfo call.
666 ****************************************************************************/
667
668 bool cli_setpathinfo(struct cli_state *cli, const char *fname,
669                      time_t create_time,
670                      time_t access_time,
671                      time_t write_time,
672                      time_t change_time,
673                      uint16 mode)
674 {
675         unsigned int data_len = 0;
676         unsigned int param_len = 0;
677         unsigned int rparam_len, rdata_len;
678         uint16 setup = TRANSACT2_SETPATHINFO;
679         char *param;
680         char data[40];
681         char *rparam=NULL, *rdata=NULL;
682         int count=8;
683         bool ret;
684         char *p;
685         size_t nlen = 2*(strlen(fname)+1);
686
687         param = SMB_MALLOC_ARRAY(char, 6+nlen+2);
688         if (!param) {
689                 return false;
690         }
691         memset(param, '\0', 6);
692         memset(data, 0, sizeof(data));
693
694         p = param;
695
696         /* Add the information level */
697         SSVAL(p, 0, SMB_FILE_BASIC_INFORMATION);
698
699         /* Skip reserved */
700         p += 6;
701
702         /* Add the file name */
703         p += clistr_push(cli, p, fname, nlen, STR_TERMINATE);
704
705         param_len = PTR_DIFF(p, param);
706
707         p = data;
708
709         /*
710          * Add the create, last access, modification, and status change times
711          */
712         put_long_date(p, create_time);
713         p += 8;
714
715         put_long_date(p, access_time);
716         p += 8;
717
718         put_long_date(p, write_time);
719         p += 8;
720
721         put_long_date(p, change_time);
722         p += 8;
723
724         /* Add attributes */
725         SIVAL(p, 0, mode);
726         p += 4;
727
728         /* Add padding */
729         SIVAL(p, 0, 0);
730         p += 4;
731
732         data_len = PTR_DIFF(p, data);
733
734         do {
735                 ret = (cli_send_trans(cli, SMBtrans2,
736                                       NULL,           /* Name */
737                                       -1, 0,          /* fid, flags */
738                                       &setup, 1, 0,   /* setup, length, max */
739                                       param, param_len, 10, /* param, length, max */
740                                       data, data_len, cli->max_xmit /* data, length, max */
741                                       ) &&
742                        cli_receive_trans(cli, SMBtrans2,
743                                          &rparam, &rparam_len,
744                                          &rdata, &rdata_len));
745                 if (!cli_is_dos_error(cli)) break;
746                 if (!ret) {
747                         /* we need to work around a Win95 bug - sometimes
748                            it gives ERRSRV/ERRerror temprarily */
749                         uint8 eclass;
750                         uint32 ecode;
751                         cli_dos_error(cli, &eclass, &ecode);
752                         if (eclass != ERRSRV || ecode != ERRerror) break;
753                         smb_msleep(100);
754                 }
755         } while (count-- && ret==False);
756
757         SAFE_FREE(param);
758         if (!ret) {
759                 return False;
760         }
761
762         SAFE_FREE(rdata);
763         SAFE_FREE(rparam);
764         return True;
765 }
766
767 /****************************************************************************
768  Send a qpathinfo call with the SMB_QUERY_FILE_ALL_INFO info level.
769 ****************************************************************************/
770
771 struct cli_qpathinfo2_state {
772         uint32_t num_data;
773         uint8_t *data;
774 };
775
776 static void cli_qpathinfo2_done(struct tevent_req *subreq);
777
778 struct tevent_req *cli_qpathinfo2_send(TALLOC_CTX *mem_ctx,
779                                        struct event_context *ev,
780                                        struct cli_state *cli,
781                                        const char *fname)
782 {
783         struct tevent_req *req = NULL, *subreq = NULL;
784         struct cli_qpathinfo2_state *state = NULL;
785
786         req = tevent_req_create(mem_ctx, &state, struct cli_qpathinfo2_state);
787         if (req == NULL) {
788                 return NULL;
789         }
790         subreq = cli_qpathinfo_send(state, ev, cli, fname,
791                                     SMB_QUERY_FILE_ALL_INFO,
792                                     68, cli->max_xmit);
793         if (tevent_req_nomem(subreq, req)) {
794                 return tevent_req_post(req, ev);
795         }
796         tevent_req_set_callback(subreq, cli_qpathinfo2_done, req);
797         return req;
798 }
799
800 static void cli_qpathinfo2_done(struct tevent_req *subreq)
801 {
802         struct tevent_req *req = tevent_req_callback_data(
803                 subreq, struct tevent_req);
804         struct cli_qpathinfo2_state *state = tevent_req_data(
805                 req, struct cli_qpathinfo2_state);
806         NTSTATUS status;
807
808         status = cli_qpathinfo_recv(subreq, state, &state->data,
809                                     &state->num_data);
810         TALLOC_FREE(subreq);
811         if (!NT_STATUS_IS_OK(status)) {
812                 tevent_req_nterror(req, status);
813                 return;
814         }
815         tevent_req_done(req);
816 }
817
818 NTSTATUS cli_qpathinfo2_recv(struct tevent_req *req,
819                              struct timespec *create_time,
820                              struct timespec *access_time,
821                              struct timespec *write_time,
822                              struct timespec *change_time,
823                              SMB_OFF_T *size, uint16 *mode,
824                              SMB_INO_T *ino)
825 {
826         struct cli_qpathinfo2_state *state = tevent_req_data(
827                 req, struct cli_qpathinfo2_state);
828         NTSTATUS status;
829
830         if (tevent_req_is_nterror(req, &status)) {
831                 return status;
832         }
833
834         if (create_time) {
835                 *create_time = interpret_long_date((char *)state->data+0);
836         }
837         if (access_time) {
838                 *access_time = interpret_long_date((char *)state->data+8);
839         }
840         if (write_time) {
841                 *write_time = interpret_long_date((char *)state->data+16);
842         }
843         if (change_time) {
844                 *change_time = interpret_long_date((char *)state->data+24);
845         }
846         if (mode) {
847                 *mode = SVAL(state->data, 32);
848         }
849         if (size) {
850                 *size = IVAL2_TO_SMB_BIG_UINT(state->data,48);
851         }
852         if (ino) {
853                 *ino = IVAL(state->data, 64);
854         }
855         return NT_STATUS_OK;
856 }
857
858 NTSTATUS cli_qpathinfo2(struct cli_state *cli, const char *fname,
859                         struct timespec *create_time,
860                         struct timespec *access_time,
861                         struct timespec *write_time,
862                         struct timespec *change_time,
863                         SMB_OFF_T *size, uint16 *mode,
864                         SMB_INO_T *ino)
865 {
866         TALLOC_CTX *frame = talloc_stackframe();
867         struct event_context *ev;
868         struct tevent_req *req;
869         NTSTATUS status = NT_STATUS_NO_MEMORY;
870
871         if (cli_has_async_calls(cli)) {
872                 /*
873                  * Can't use sync call while an async call is in flight
874                  */
875                 status = NT_STATUS_INVALID_PARAMETER;
876                 goto fail;
877         }
878         ev = event_context_init(frame);
879         if (ev == NULL) {
880                 goto fail;
881         }
882         req = cli_qpathinfo2_send(frame, ev, cli, fname);
883         if (req == NULL) {
884                 goto fail;
885         }
886         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
887                 goto fail;
888         }
889         status = cli_qpathinfo2_recv(req, create_time, access_time,
890                                      write_time, change_time, size, mode, ino);
891  fail:
892         TALLOC_FREE(frame);
893         if (!NT_STATUS_IS_OK(status)) {
894                 cli_set_error(cli, status);
895         }
896         return status;
897 }
898
899 /****************************************************************************
900  Get the stream info
901 ****************************************************************************/
902
903 static bool parse_streams_blob(TALLOC_CTX *mem_ctx, const uint8_t *data,
904                                size_t data_len,
905                                unsigned int *pnum_streams,
906                                struct stream_struct **pstreams);
907
908 struct cli_qpathinfo_streams_state {
909         uint32_t num_data;
910         uint8_t *data;
911 };
912
913 static void cli_qpathinfo_streams_done(struct tevent_req *subreq);
914
915 struct tevent_req *cli_qpathinfo_streams_send(TALLOC_CTX *mem_ctx,
916                                               struct tevent_context *ev,
917                                               struct cli_state *cli,
918                                               const char *fname)
919 {
920         struct tevent_req *req = NULL, *subreq = NULL;
921         struct cli_qpathinfo_streams_state *state = NULL;
922
923         req = tevent_req_create(mem_ctx, &state,
924                                 struct cli_qpathinfo_streams_state);
925         if (req == NULL) {
926                 return NULL;
927         }
928         subreq = cli_qpathinfo_send(state, ev, cli, fname,
929                                     SMB_FILE_STREAM_INFORMATION,
930                                     0, cli->max_xmit);
931         if (tevent_req_nomem(subreq, req)) {
932                 return tevent_req_post(req, ev);
933         }
934         tevent_req_set_callback(subreq, cli_qpathinfo_streams_done, req);
935         return req;
936 }
937
938 static void cli_qpathinfo_streams_done(struct tevent_req *subreq)
939 {
940         struct tevent_req *req = tevent_req_callback_data(
941                 subreq, struct tevent_req);
942         struct cli_qpathinfo_streams_state *state = tevent_req_data(
943                 req, struct cli_qpathinfo_streams_state);
944         NTSTATUS status;
945
946         status = cli_qpathinfo_recv(subreq, state, &state->data,
947                                     &state->num_data);
948         TALLOC_FREE(subreq);
949         if (!NT_STATUS_IS_OK(status)) {
950                 tevent_req_nterror(req, status);
951                 return;
952         }
953         tevent_req_done(req);
954 }
955
956 NTSTATUS cli_qpathinfo_streams_recv(struct tevent_req *req,
957                                     TALLOC_CTX *mem_ctx,
958                                     unsigned int *pnum_streams,
959                                     struct stream_struct **pstreams)
960 {
961         struct cli_qpathinfo_streams_state *state = tevent_req_data(
962                 req, struct cli_qpathinfo_streams_state);
963         NTSTATUS status;
964
965         if (tevent_req_is_nterror(req, &status)) {
966                 return status;
967         }
968         if (!parse_streams_blob(mem_ctx, state->data, state->num_data,
969                                 pnum_streams, pstreams)) {
970                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
971         }
972         return NT_STATUS_OK;
973 }
974
975 NTSTATUS cli_qpathinfo_streams(struct cli_state *cli, const char *fname,
976                                TALLOC_CTX *mem_ctx,
977                                unsigned int *pnum_streams,
978                                struct stream_struct **pstreams)
979 {
980         TALLOC_CTX *frame = talloc_stackframe();
981         struct event_context *ev;
982         struct tevent_req *req;
983         NTSTATUS status = NT_STATUS_NO_MEMORY;
984
985         if (cli_has_async_calls(cli)) {
986                 /*
987                  * Can't use sync call while an async call is in flight
988                  */
989                 status = NT_STATUS_INVALID_PARAMETER;
990                 goto fail;
991         }
992         ev = event_context_init(frame);
993         if (ev == NULL) {
994                 goto fail;
995         }
996         req = cli_qpathinfo_streams_send(frame, ev, cli, fname);
997         if (req == NULL) {
998                 goto fail;
999         }
1000         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1001                 goto fail;
1002         }
1003         status = cli_qpathinfo_streams_recv(req, mem_ctx, pnum_streams,
1004                                             pstreams);
1005  fail:
1006         TALLOC_FREE(frame);
1007         if (!NT_STATUS_IS_OK(status)) {
1008                 cli_set_error(cli, status);
1009         }
1010         return status;
1011 }
1012
1013 static bool parse_streams_blob(TALLOC_CTX *mem_ctx, const uint8_t *rdata,
1014                                size_t data_len,
1015                                unsigned int *pnum_streams,
1016                                struct stream_struct **pstreams)
1017 {
1018         unsigned int num_streams;
1019         struct stream_struct *streams;
1020         unsigned int ofs;
1021
1022         num_streams = 0;
1023         streams = NULL;
1024         ofs = 0;
1025
1026         while ((data_len > ofs) && (data_len - ofs >= 24)) {
1027                 uint32_t nlen, len;
1028                 size_t size;
1029                 void *vstr;
1030                 struct stream_struct *tmp;
1031                 uint8_t *tmp_buf;
1032
1033                 tmp = TALLOC_REALLOC_ARRAY(mem_ctx, streams,
1034                                            struct stream_struct,
1035                                            num_streams+1);
1036
1037                 if (tmp == NULL) {
1038                         goto fail;
1039                 }
1040                 streams = tmp;
1041
1042                 nlen                      = IVAL(rdata, ofs + 0x04);
1043
1044                 streams[num_streams].size = IVAL_TO_SMB_OFF_T(
1045                         rdata, ofs + 0x08);
1046                 streams[num_streams].alloc_size = IVAL_TO_SMB_OFF_T(
1047                         rdata, ofs + 0x10);
1048
1049                 if (nlen > data_len - (ofs + 24)) {
1050                         goto fail;
1051                 }
1052
1053                 /*
1054                  * We need to null-terminate src, how do I do this with
1055                  * convert_string_talloc??
1056                  */
1057
1058                 tmp_buf = TALLOC_ARRAY(streams, uint8_t, nlen+2);
1059                 if (tmp_buf == NULL) {
1060                         goto fail;
1061                 }
1062
1063                 memcpy(tmp_buf, rdata+ofs+24, nlen);
1064                 tmp_buf[nlen] = 0;
1065                 tmp_buf[nlen+1] = 0;
1066
1067                 if (!convert_string_talloc(streams, CH_UTF16, CH_UNIX, tmp_buf,
1068                                            nlen+2, &vstr, &size, false))
1069                 {
1070                         TALLOC_FREE(tmp_buf);
1071                         goto fail;
1072                 }
1073
1074                 TALLOC_FREE(tmp_buf);
1075                 streams[num_streams].name = (char *)vstr;
1076                 num_streams++;
1077
1078                 len = IVAL(rdata, ofs);
1079                 if (len > data_len - ofs) {
1080                         goto fail;
1081                 }
1082                 if (len == 0) break;
1083                 ofs += len;
1084         }
1085
1086         *pnum_streams = num_streams;
1087         *pstreams = streams;
1088         return true;
1089
1090  fail:
1091         TALLOC_FREE(streams);
1092         return false;
1093 }
1094
1095 /****************************************************************************
1096  Send a qfileinfo QUERY_FILE_NAME_INFO call.
1097 ****************************************************************************/
1098
1099 bool cli_qfilename(struct cli_state *cli, uint16_t fnum, char *name, size_t namelen)
1100 {
1101         unsigned int data_len = 0;
1102         unsigned int param_len = 0;
1103         uint16 setup = TRANSACT2_QFILEINFO;
1104         char param[4];
1105         char *rparam=NULL, *rdata=NULL;
1106
1107         param_len = 4;
1108         SSVAL(param, 0, fnum);
1109         SSVAL(param, 2, SMB_QUERY_FILE_NAME_INFO);
1110
1111         if (!cli_send_trans(cli, SMBtrans2,
1112                             NULL,                         /* name */
1113                             -1, 0,                        /* fid, flags */
1114                             &setup, 1, 0,                 /* setup, length, max */
1115                             param, param_len, 2,          /* param, length, max */
1116                             NULL, data_len, cli->max_xmit /* data, length, max */
1117                            )) {
1118                 return False;
1119         }
1120
1121         if (!cli_receive_trans(cli, SMBtrans2,
1122                                &rparam, &param_len,
1123                                &rdata, &data_len)) {
1124                 return False;
1125         }
1126
1127         if (!rdata || data_len < 4) {
1128                 SAFE_FREE(rparam);
1129                 SAFE_FREE(rdata);
1130                 return False;
1131         }
1132
1133         clistr_pull(cli->inbuf, name, rdata+4, namelen, IVAL(rdata, 0),
1134                     STR_UNICODE);
1135
1136         SAFE_FREE(rparam);
1137         SAFE_FREE(rdata);
1138
1139         return True;
1140 }
1141
1142 /****************************************************************************
1143  Send a qfileinfo call.
1144 ****************************************************************************/
1145
1146 bool cli_qfileinfo(struct cli_state *cli, uint16_t fnum,
1147                    uint16 *mode, SMB_OFF_T *size,
1148                    struct timespec *create_time,
1149                    struct timespec *access_time,
1150                    struct timespec *write_time,
1151                    struct timespec *change_time,
1152                    SMB_INO_T *ino)
1153 {
1154         uint32_t data_len = 0;
1155         uint16 setup;
1156         uint8_t param[4];
1157         uint8_t *rdata=NULL;
1158         NTSTATUS status;
1159
1160         /* if its a win95 server then fail this - win95 totally screws it
1161            up */
1162         if (cli->win95) return False;
1163
1164         SSVAL(param, 0, fnum);
1165         SSVAL(param, 2, SMB_QUERY_FILE_ALL_INFO);
1166
1167         SSVAL(&setup, 0, TRANSACT2_QFILEINFO);
1168
1169         status = cli_trans(talloc_tos(), cli, SMBtrans2,
1170                            NULL, -1, 0, 0, /* name, fid, function, flags */
1171                            &setup, 1, 0,          /* setup, length, max */
1172                            param, 4, 2,   /* param, length, max */
1173                            NULL, 0, MIN(cli->max_xmit, 0xffff), /* data, length, max */
1174                            NULL,                                /* recv_flags2 */
1175                            NULL, 0, NULL, /* rsetup, length */
1176                            NULL, 0, NULL,       /* rparam, length */
1177                            &rdata, 68, &data_len);
1178
1179         if (!NT_STATUS_IS_OK(status)) {
1180                 return false;
1181         }
1182
1183         if (create_time) {
1184                 *create_time = interpret_long_date((char *)rdata+0);
1185         }
1186         if (access_time) {
1187                 *access_time = interpret_long_date((char *)rdata+8);
1188         }
1189         if (write_time) {
1190                 *write_time = interpret_long_date((char *)rdata+16);
1191         }
1192         if (change_time) {
1193                 *change_time = interpret_long_date((char *)rdata+24);
1194         }
1195         if (mode) {
1196                 *mode = SVAL(rdata, 32);
1197         }
1198         if (size) {
1199                 *size = IVAL2_TO_SMB_BIG_UINT(rdata,48);
1200         }
1201         if (ino) {
1202                 *ino = IVAL(rdata, 64);
1203         }
1204
1205         TALLOC_FREE(rdata);
1206         return True;
1207 }
1208
1209 /****************************************************************************
1210  Send a qpathinfo BASIC_INFO call.
1211 ****************************************************************************/
1212
1213 struct cli_qpathinfo_basic_state {
1214         uint32_t num_data;
1215         uint8_t *data;
1216 };
1217
1218 static void cli_qpathinfo_basic_done(struct tevent_req *subreq);
1219
1220 struct tevent_req *cli_qpathinfo_basic_send(TALLOC_CTX *mem_ctx,
1221                                             struct event_context *ev,
1222                                             struct cli_state *cli,
1223                                             const char *fname)
1224 {
1225         struct tevent_req *req = NULL, *subreq = NULL;
1226         struct cli_qpathinfo_basic_state *state = NULL;
1227
1228         req = tevent_req_create(mem_ctx, &state,
1229                                 struct cli_qpathinfo_basic_state);
1230         if (req == NULL) {
1231                 return NULL;
1232         }
1233         subreq = cli_qpathinfo_send(state, ev, cli, fname,
1234                                     SMB_QUERY_FILE_BASIC_INFO,
1235                                     36, cli->max_xmit);
1236         if (tevent_req_nomem(subreq, req)) {
1237                 return tevent_req_post(req, ev);
1238         }
1239         tevent_req_set_callback(subreq, cli_qpathinfo_basic_done, req);
1240         return req;
1241 }
1242
1243 static void cli_qpathinfo_basic_done(struct tevent_req *subreq)
1244 {
1245         struct tevent_req *req = tevent_req_callback_data(
1246                 subreq, struct tevent_req);
1247         struct cli_qpathinfo_basic_state *state = tevent_req_data(
1248                 req, struct cli_qpathinfo_basic_state);
1249         NTSTATUS status;
1250
1251         status = cli_qpathinfo_recv(subreq, state, &state->data,
1252                                     &state->num_data);
1253         TALLOC_FREE(subreq);
1254         if (!NT_STATUS_IS_OK(status)) {
1255                 tevent_req_nterror(req, status);
1256                 return;
1257         }
1258         tevent_req_done(req);
1259 }
1260
1261 NTSTATUS cli_qpathinfo_basic_recv(struct tevent_req *req,
1262                                   SMB_STRUCT_STAT *sbuf, uint32 *attributes)
1263 {
1264         struct cli_qpathinfo_basic_state *state = tevent_req_data(
1265                 req, struct cli_qpathinfo_basic_state);
1266         NTSTATUS status;
1267
1268         if (tevent_req_is_nterror(req, &status)) {
1269                 return status;
1270         }
1271
1272         sbuf->st_ex_atime = interpret_long_date((char *)state->data+8);
1273         sbuf->st_ex_mtime = interpret_long_date((char *)state->data+16);
1274         sbuf->st_ex_ctime = interpret_long_date((char *)state->data+24);
1275         *attributes = IVAL(state->data, 32);
1276         return NT_STATUS_OK;
1277 }
1278
1279 NTSTATUS cli_qpathinfo_basic(struct cli_state *cli, const char *name,
1280                              SMB_STRUCT_STAT *sbuf, uint32 *attributes)
1281 {
1282         TALLOC_CTX *frame = talloc_stackframe();
1283         struct event_context *ev;
1284         struct tevent_req *req;
1285         NTSTATUS status = NT_STATUS_NO_MEMORY;
1286
1287         if (cli_has_async_calls(cli)) {
1288                 /*
1289                  * Can't use sync call while an async call is in flight
1290                  */
1291                 status = NT_STATUS_INVALID_PARAMETER;
1292                 goto fail;
1293         }
1294         ev = event_context_init(frame);
1295         if (ev == NULL) {
1296                 goto fail;
1297         }
1298         req = cli_qpathinfo_basic_send(frame, ev, cli, name);
1299         if (req == NULL) {
1300                 goto fail;
1301         }
1302         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1303                 goto fail;
1304         }
1305         status = cli_qpathinfo_basic_recv(req, sbuf, attributes);
1306  fail:
1307         TALLOC_FREE(frame);
1308         if (!NT_STATUS_IS_OK(status)) {
1309                 cli_set_error(cli, status);
1310         }
1311         return status;
1312 }
1313
1314 /****************************************************************************
1315  Send a qfileinfo call.
1316 ****************************************************************************/
1317
1318 bool cli_qfileinfo_test(struct cli_state *cli, uint16_t fnum, int level, char **poutdata, uint32 *poutlen)
1319 {
1320         unsigned int data_len = 0;
1321         unsigned int param_len = 0;
1322         uint16 setup = TRANSACT2_QFILEINFO;
1323         char param[4];
1324         char *rparam=NULL, *rdata=NULL;
1325
1326         *poutdata = NULL;
1327         *poutlen = 0;
1328
1329         /* if its a win95 server then fail this - win95 totally screws it
1330            up */
1331         if (cli->win95)
1332                 return False;
1333
1334         param_len = 4;
1335
1336         SSVAL(param, 0, fnum);
1337         SSVAL(param, 2, level);
1338
1339         if (!cli_send_trans(cli, SMBtrans2,
1340                             NULL,                           /* name */
1341                             -1, 0,                          /* fid, flags */
1342                             &setup, 1, 0,                   /* setup, length, max */
1343                             param, param_len, 2,            /* param, length, max */
1344                             NULL, data_len, cli->max_xmit   /* data, length, max */
1345                            )) {
1346                 return False;
1347         }
1348
1349         if (!cli_receive_trans(cli, SMBtrans2,
1350                                &rparam, &param_len,
1351                                &rdata, &data_len)) {
1352                 return False;
1353         }
1354
1355         *poutdata = (char *)memdup(rdata, data_len);
1356         if (!*poutdata) {
1357                 SAFE_FREE(rdata);
1358                 SAFE_FREE(rparam);
1359                 return False;
1360         }
1361
1362         *poutlen = data_len;
1363
1364         SAFE_FREE(rdata);
1365         SAFE_FREE(rparam);
1366         return True;
1367 }
1368
1369 /****************************************************************************
1370  Send a qpathinfo SMB_QUERY_FILE_ALT_NAME_INFO call.
1371 ****************************************************************************/
1372
1373 NTSTATUS cli_qpathinfo_alt_name(struct cli_state *cli, const char *fname, fstring alt_name)
1374 {
1375         unsigned int data_len = 0;
1376         unsigned int param_len = 0;
1377         uint16 setup = TRANSACT2_QPATHINFO;
1378         char *param;
1379         char *rparam=NULL, *rdata=NULL;
1380         int count=8;
1381         char *p;
1382         bool ret;
1383         unsigned int len;
1384         size_t nlen = 2*(strlen(fname)+1);
1385
1386         param = SMB_MALLOC_ARRAY(char, 6+nlen+2);
1387         if (!param) {
1388                 return NT_STATUS_NO_MEMORY;
1389         }
1390         p = param;
1391         memset(param, '\0', 6);
1392         SSVAL(p, 0, SMB_QUERY_FILE_ALT_NAME_INFO);
1393         p += 6;
1394         p += clistr_push(cli, p, fname, nlen, STR_TERMINATE);
1395         param_len = PTR_DIFF(p, param);
1396
1397         do {
1398                 ret = (cli_send_trans(cli, SMBtrans2,
1399                                       NULL,           /* Name */
1400                                       -1, 0,          /* fid, flags */
1401                                       &setup, 1, 0,   /* setup, length, max */
1402                                       param, param_len, 10, /* param, length, max */
1403                                       NULL, data_len, cli->max_xmit /* data, length, max */
1404                                       ) &&
1405                        cli_receive_trans(cli, SMBtrans2,
1406                                          &rparam, &param_len,
1407                                          &rdata, &data_len));
1408                 if (!ret && cli_is_dos_error(cli)) {
1409                         /* we need to work around a Win95 bug - sometimes
1410                            it gives ERRSRV/ERRerror temprarily */
1411                         uint8 eclass;
1412                         uint32 ecode;
1413                         cli_dos_error(cli, &eclass, &ecode);
1414                         if (eclass != ERRSRV || ecode != ERRerror) break;
1415                         smb_msleep(100);
1416                 }
1417         } while (count-- && ret==False);
1418
1419         SAFE_FREE(param);
1420
1421         if (!ret || !rdata || data_len < 4) {
1422                 return NT_STATUS_UNSUCCESSFUL;
1423         }
1424
1425         len = IVAL(rdata, 0);
1426
1427         if (len > data_len - 4) {
1428                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
1429         }
1430
1431         clistr_pull(cli->inbuf, alt_name, rdata+4, sizeof(fstring), len,
1432                     STR_UNICODE);
1433
1434         SAFE_FREE(rdata);
1435         SAFE_FREE(rparam);
1436
1437         return NT_STATUS_OK;
1438 }