trying to get HEAD building again. If you want the code
[gd/samba-autobuild/.git] / source3 / libsmb / clirap.c
1 /* 
2    Unix SMB/CIFS implementation.
3    client RAP calls
4    Copyright (C) Andrew Tridgell 1994-1998
5    
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2 of the License, or
9    (at your option) any later version.
10    
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15    
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21 #define NO_SYSLOG
22
23 #include "includes.h"
24
25
26 /****************************************************************************
27 Call a remote api on an arbitrary pipe.  takes param, data and setup buffers.
28 ****************************************************************************/
29 BOOL cli_api_pipe(struct cli_state *cli, const char *pipe_name, 
30                   uint16 *setup, uint32 setup_count, uint32 max_setup_count,
31                   char *params, uint32 param_count, uint32 max_param_count,
32                   char *data, uint32 data_count, uint32 max_data_count,
33                   char **rparam, uint32 *rparam_count,
34                   char **rdata, uint32 *rdata_count)
35 {
36   cli_send_trans(cli, SMBtrans, 
37                  pipe_name, 
38                  0,0,                         /* fid, flags */
39                  setup, setup_count, max_setup_count,
40                  params, param_count, max_param_count,
41                  data, data_count, max_data_count);
42
43   return (cli_receive_trans(cli, SMBtrans, 
44                             rparam, (unsigned int *)rparam_count,
45                             rdata, (unsigned int *)rdata_count));
46 }
47
48 /****************************************************************************
49 call a remote api
50 ****************************************************************************/
51 BOOL cli_api(struct cli_state *cli,
52              char *param, int prcnt, int mprcnt,
53              char *data, int drcnt, int mdrcnt,
54              char **rparam, unsigned int *rprcnt,
55              char **rdata, unsigned int *rdrcnt)
56 {
57   cli_send_trans(cli,SMBtrans,
58                  PIPE_LANMAN,             /* Name */
59                  0,0,                     /* fid, flags */
60                  NULL,0,0,                /* Setup, length, max */
61                  param, prcnt, mprcnt,    /* Params, length, max */
62                  data, drcnt, mdrcnt      /* Data, length, max */ 
63                 );
64
65   return (cli_receive_trans(cli,SMBtrans,
66                             rparam, rprcnt,
67                             rdata, rdrcnt));
68 }
69
70
71 /****************************************************************************
72 perform a NetWkstaUserLogon
73 ****************************************************************************/
74 BOOL cli_NetWkstaUserLogon(struct cli_state *cli,char *user, char *workstation)
75 {
76         char *rparam = NULL;
77         char *rdata = NULL;
78         char *p;
79         int rdrcnt,rprcnt;
80         pstring param;
81
82         memset(param, 0, sizeof(param));
83         
84         /* send a SMBtrans command with api NetWkstaUserLogon */
85         p = param;
86         SSVAL(p,0,132); /* api number */
87         p += 2;
88         pstrcpy_base(p,"OOWb54WrLh",param);
89         p = skip_string(p,1);
90         pstrcpy_base(p,"WB21BWDWWDDDDDDDzzzD",param);
91         p = skip_string(p,1);
92         SSVAL(p,0,1);
93         p += 2;
94         pstrcpy_base(p,user,param);
95         strupper_m(p);
96         p += 21;
97         p++;
98         p += 15;
99         p++; 
100         pstrcpy_base(p, workstation, param);
101         strupper_m(p);
102         p += 16;
103         SSVAL(p, 0, CLI_BUFFER_SIZE);
104         p += 2;
105         SSVAL(p, 0, CLI_BUFFER_SIZE);
106         p += 2;
107         
108         if (cli_api(cli, 
109                     param, PTR_DIFF(p,param),1024,  /* param, length, max */
110                     NULL, 0, CLI_BUFFER_SIZE,           /* data, length, max */
111                     &rparam, &rprcnt,               /* return params, return size */
112                     &rdata, &rdrcnt                 /* return data, return size */
113                    )) {
114                 cli->rap_error = rparam? SVAL(rparam,0) : -1;
115                 p = rdata;
116                 
117                 if (cli->rap_error == 0) {
118                         DEBUG(4,("NetWkstaUserLogon success\n"));
119                         cli->privileges = SVAL(p, 24);
120                         /* The cli->eff_name field used to be set here
121                            but it wasn't used anywhere else. */
122                 } else {
123                         DEBUG(1,("NetwkstaUserLogon gave error %d\n", cli->rap_error));
124                 }
125         }
126         
127         SAFE_FREE(rparam);
128         SAFE_FREE(rdata);
129         return (cli->rap_error == 0);
130 }
131
132 /****************************************************************************
133 call a NetShareEnum - try and browse available connections on a host
134 ****************************************************************************/
135 int cli_RNetShareEnum(struct cli_state *cli, void (*fn)(const char *, uint32, const char *, void *), void *state)
136 {
137         char *rparam = NULL;
138         char *rdata = NULL;
139         char *p;
140         int rdrcnt,rprcnt;
141         pstring param;
142         int count = -1;
143
144         /* now send a SMBtrans command with api RNetShareEnum */
145         p = param;
146         SSVAL(p,0,0); /* api number */
147         p += 2;
148         pstrcpy_base(p,"WrLeh",param);
149         p = skip_string(p,1);
150         pstrcpy_base(p,"B13BWz",param);
151         p = skip_string(p,1);
152         SSVAL(p,0,1);
153         /*
154          * Win2k needs a *smaller* buffer than 0xFFFF here -
155          * it returns "out of server memory" with 0xFFFF !!! JRA.
156          */
157         SSVAL(p,2,0xFFE0);
158         p += 4;
159         
160         if (cli_api(cli, 
161                     param, PTR_DIFF(p,param), 1024,  /* Param, length, maxlen */
162                     NULL, 0, 0xFFE0,            /* data, length, maxlen - Win2k needs a small buffer here too ! */
163                     &rparam, &rprcnt,                /* return params, length */
164                     &rdata, &rdrcnt))                /* return data, length */
165                 {
166                         int res = rparam? SVAL(rparam,0) : -1;
167                         
168                         if (res == 0 || res == ERRmoredata) {
169                                 int converter=SVAL(rparam,2);
170                                 int i;
171                                 
172                                 count=SVAL(rparam,4);
173                                 p = rdata;
174                                 
175                                 for (i=0;i<count;i++,p+=20) {
176                                         char *sname = p;
177                                         int type = SVAL(p,14);
178                                         int comment_offset = IVAL(p,16) & 0xFFFF;
179                                         const char *cmnt = comment_offset?(rdata+comment_offset-converter):"";
180                                         pstring s1, s2;
181
182                                         pull_ascii_pstring(s1, sname);
183                                         pull_ascii_pstring(s2, cmnt);
184
185                                         fn(s1, type, s2, state);
186                                 }
187                         } else {
188                                 DEBUG(4,("NetShareEnum res=%d\n", res));
189                         }      
190                 } else {
191                         DEBUG(4,("NetShareEnum failed\n"));
192                 }
193   
194         SAFE_FREE(rparam);
195         SAFE_FREE(rdata);
196         
197         return count;
198 }
199
200
201 /****************************************************************************
202 call a NetServerEnum for the specified workgroup and servertype mask.  This
203 function then calls the specified callback function for each name returned.
204
205 The callback function takes 4 arguments: the machine name, the server type,
206 the comment and a state pointer.
207 ****************************************************************************/
208 BOOL cli_NetServerEnum(struct cli_state *cli, char *workgroup, uint32 stype,
209                        void (*fn)(const char *, uint32, const char *, void *),
210                        void *state)
211 {
212         char *rparam = NULL;
213         char *rdata = NULL;
214         int rdrcnt,rprcnt;
215         char *p;
216         pstring param;
217         int uLevel = 1;
218         int count = -1;
219
220         /* send a SMBtrans command with api NetServerEnum */
221         p = param;
222         SSVAL(p,0,0x68); /* api number */
223         p += 2;
224         pstrcpy_base(p,"WrLehDz", param);
225         p = skip_string(p,1);
226   
227         pstrcpy_base(p,"B16BBDz", param);
228
229         p = skip_string(p,1);
230         SSVAL(p,0,uLevel);
231         SSVAL(p,2,CLI_BUFFER_SIZE);
232         p += 4;
233         SIVAL(p,0,stype);
234         p += 4;
235
236         p += push_ascii(p, workgroup, sizeof(pstring)-PTR_DIFF(p,param)-1, STR_TERMINATE|STR_UPPER);
237         
238         if (cli_api(cli, 
239                     param, PTR_DIFF(p,param), 8,        /* params, length, max */
240                     NULL, 0, CLI_BUFFER_SIZE,               /* data, length, max */
241                     &rparam, &rprcnt,                   /* return params, return size */
242                     &rdata, &rdrcnt                     /* return data, return size */
243                    )) {
244                 int res = rparam? SVAL(rparam,0) : -1;
245                         
246                 if (res == 0 || res == ERRmoredata) {
247                         int i;
248                         int converter=SVAL(rparam,2);
249
250                         count=SVAL(rparam,4);
251                         p = rdata;
252                                         
253                         for (i = 0;i < count;i++, p += 26) {
254                                 char *sname = p;
255                                 int comment_offset = (IVAL(p,22) & 0xFFFF)-converter;
256                                 const char *cmnt = comment_offset?(rdata+comment_offset):"";
257                                 pstring s1, s2;
258
259                                 if (comment_offset < 0 || comment_offset > rdrcnt) continue;
260
261                                 stype = IVAL(p,18) & ~SV_TYPE_LOCAL_LIST_ONLY;
262
263                                 pull_ascii_pstring(s1, sname);
264                                 pull_ascii_pstring(s2, cmnt);
265                                 fn(s1, stype, s2, state);
266                         }
267                 }
268         }
269   
270         SAFE_FREE(rparam);
271         SAFE_FREE(rdata);
272         
273         return(count > 0);
274 }
275
276
277
278 /****************************************************************************
279 Send a SamOEMChangePassword command
280 ****************************************************************************/
281 BOOL cli_oem_change_password(struct cli_state *cli, const char *user, const char *new_password,
282                              const char *old_password)
283 {
284   pstring param;
285   char data[532];
286   char *p = param;
287   unsigned char old_pw_hash[16];
288   unsigned char new_pw_hash[16];
289   unsigned int data_len;
290   unsigned int param_len = 0;
291   char *rparam = NULL;
292   char *rdata = NULL;
293   int rprcnt, rdrcnt;
294   pstring dos_new_password;
295
296   if (strlen(user) >= sizeof(fstring)-1) {
297     DEBUG(0,("cli_oem_change_password: user name %s is too long.\n", user));
298     return False;
299   }
300
301   SSVAL(p,0,214); /* SamOEMChangePassword command. */
302   p += 2;
303   pstrcpy_base(p, "zsT", param);
304   p = skip_string(p,1);
305   pstrcpy_base(p, "B516B16", param);
306   p = skip_string(p,1);
307   pstrcpy_base(p,user, param);
308   p = skip_string(p,1);
309   SSVAL(p,0,532);
310   p += 2;
311
312   param_len = PTR_DIFF(p,param);
313
314   /*
315    * Get the Lanman hash of the old password, we
316    * use this as the key to make_oem_passwd_hash().
317    */
318   E_deshash(old_password, old_pw_hash);
319
320   clistr_push(cli, dos_new_password, new_password, sizeof(dos_new_password), STR_TERMINATE|STR_ASCII);
321
322   if (!make_oem_passwd_hash( data, dos_new_password, old_pw_hash, False))
323     return False;
324
325   /* 
326    * Now place the old password hash in the data.
327    */
328   E_deshash(new_password, new_pw_hash);
329
330   E_old_pw_hash( new_pw_hash, old_pw_hash, (uchar *)&data[516]);
331
332   data_len = 532;
333     
334   if (cli_send_trans(cli,SMBtrans,
335                     PIPE_LANMAN,                          /* name */
336                     0,0,                                  /* fid, flags */
337                     NULL,0,0,                             /* setup, length, max */
338                     param,param_len,2,                    /* param, length, max */
339                     data,data_len,0                       /* data, length, max */
340                    ) == False) {
341     DEBUG(0,("cli_oem_change_password: Failed to send password change for user %s\n",
342               user ));
343     return False;
344   }
345
346   if (!cli_receive_trans(cli,SMBtrans,
347                        &rparam, &rprcnt,
348                        &rdata, &rdrcnt)) {
349           DEBUG(0,("cli_oem_change_password: Failed to recieve reply to password change for user %s\n",
350                    user ));
351           return False;
352   }
353   
354   if (rparam)
355           cli->rap_error = SVAL(rparam,0);
356   
357   SAFE_FREE(rparam);
358   SAFE_FREE(rdata);
359
360   return (cli->rap_error == 0);
361 }
362
363
364 /****************************************************************************
365 send a qpathinfo call
366 ****************************************************************************/
367 BOOL cli_qpathinfo(struct cli_state *cli, const char *fname, 
368                    time_t *c_time, time_t *a_time, time_t *m_time, 
369                    size_t *size, uint16 *mode)
370 {
371         unsigned int data_len = 0;
372         unsigned int param_len = 0;
373         unsigned int rparam_len, rdata_len;
374         uint16 setup = TRANSACT2_QPATHINFO;
375         pstring param;
376         char *rparam=NULL, *rdata=NULL;
377         int count=8;
378         BOOL ret;
379         time_t (*date_fn)(void *);
380         char *p;
381
382         p = param;
383         memset(p, 0, 6);
384         SSVAL(p, 0, SMB_INFO_STANDARD);
385         p += 6;
386         p += clistr_push(cli, p, fname, sizeof(pstring)-6, STR_TERMINATE);
387
388         param_len = PTR_DIFF(p, param);
389
390         do {
391                 ret = (cli_send_trans(cli, SMBtrans2, 
392                                       NULL,           /* Name */
393                                       -1, 0,          /* fid, flags */
394                                       &setup, 1, 0,   /* setup, length, max */
395                                       param, param_len, 10, /* param, length, max */
396                                       NULL, data_len, cli->max_xmit /* data, length, max */
397                                       ) &&
398                        cli_receive_trans(cli, SMBtrans2, 
399                                          &rparam, &rparam_len,
400                                          &rdata, &rdata_len));
401                 if (!cli_is_dos_error(cli)) break;
402                 if (!ret) {
403                         /* we need to work around a Win95 bug - sometimes
404                            it gives ERRSRV/ERRerror temprarily */
405                         uint8 eclass;
406                         uint32 ecode;
407                         cli_dos_error(cli, &eclass, &ecode);
408                         if (eclass != ERRSRV || ecode != ERRerror) break;
409                         msleep(100);
410                 }
411         } while (count-- && ret==False);
412
413         if (!ret || !rdata || rdata_len < 22) {
414                 return False;
415         }
416
417         if (cli->win95) {
418                 date_fn = make_unix_date;
419         } else {
420                 date_fn = make_unix_date2;
421         }
422
423         if (c_time) {
424                 *c_time = date_fn(rdata+0);
425         }
426         if (a_time) {
427                 *a_time = date_fn(rdata+4);
428         }
429         if (m_time) {
430                 *m_time = date_fn(rdata+8);
431         }
432         if (size) {
433                 *size = IVAL(rdata, 12);
434         }
435         if (mode) {
436                 *mode = SVAL(rdata,l1_attrFile);
437         }
438
439         SAFE_FREE(rdata);
440         SAFE_FREE(rparam);
441         return True;
442 }
443
444 /****************************************************************************
445 send a qpathinfo call with the SMB_QUERY_FILE_ALL_INFO info level
446 ****************************************************************************/
447 BOOL cli_qpathinfo2(struct cli_state *cli, const char *fname, 
448                     time_t *c_time, time_t *a_time, time_t *m_time, 
449                     time_t *w_time, size_t *size, uint16 *mode,
450                     SMB_INO_T *ino)
451 {
452         unsigned int data_len = 0;
453         unsigned int param_len = 0;
454         uint16 setup = TRANSACT2_QPATHINFO;
455         pstring param;
456         char *rparam=NULL, *rdata=NULL;
457         char *p;
458
459         p = param;
460         memset(p, 0, 6);
461         SSVAL(p, 0, SMB_QUERY_FILE_ALL_INFO);
462         p += 6;
463         p += clistr_push(cli, p, fname, sizeof(pstring)-6, STR_TERMINATE);
464
465         param_len = PTR_DIFF(p, param);
466
467         if (!cli_send_trans(cli, SMBtrans2, 
468                             NULL,                         /* name */
469                             -1, 0,                        /* fid, flags */
470                             &setup, 1, 0,                 /* setup, length, max */
471                             param, param_len, 10,         /* param, length, max */
472                             NULL, data_len, cli->max_xmit /* data, length, max */
473                            )) {
474                 return False;
475         }
476
477         if (!cli_receive_trans(cli, SMBtrans2,
478                                &rparam, &param_len,
479                                &rdata, &data_len)) {
480                 return False;
481         }
482
483         if (!rdata || data_len < 22) {
484                 return False;
485         }
486
487         if (c_time) {
488                 *c_time = interpret_long_date(rdata+0) - cli->serverzone;
489         }
490         if (a_time) {
491                 *a_time = interpret_long_date(rdata+8) - cli->serverzone;
492         }
493         if (m_time) {
494                 *m_time = interpret_long_date(rdata+16) - cli->serverzone;
495         }
496         if (w_time) {
497                 *w_time = interpret_long_date(rdata+24) - cli->serverzone;
498         }
499         if (mode) {
500                 *mode = SVAL(rdata, 32);
501         }
502         if (size) {
503                 *size = IVAL(rdata, 48);
504         }
505         if (ino) {
506                 *ino = IVAL(rdata, 64);
507         }
508
509         SAFE_FREE(rdata);
510         SAFE_FREE(rparam);
511         return True;
512 }
513
514
515 /****************************************************************************
516 send a qfileinfo QUERY_FILE_NAME_INFO call
517 ****************************************************************************/
518 BOOL cli_qfilename(struct cli_state *cli, int fnum, 
519                    pstring name)
520 {
521         unsigned int data_len = 0;
522         unsigned int param_len = 0;
523         uint16 setup = TRANSACT2_QFILEINFO;
524         pstring param;
525         char *rparam=NULL, *rdata=NULL;
526
527         param_len = 4;
528         memset(param, 0, param_len);
529         SSVAL(param, 0, fnum);
530         SSVAL(param, 2, SMB_QUERY_FILE_NAME_INFO);
531
532         if (!cli_send_trans(cli, SMBtrans2, 
533                             NULL,                           /* name */
534                             -1, 0,                          /* fid, flags */
535                             &setup, 1, 0,                   /* setup, length, max */
536                             param, param_len, 2,            /* param, length, max */
537                             NULL, data_len, cli->max_xmit   /* data, length, max */
538                            )) {
539                 return False;
540         }
541
542         if (!cli_receive_trans(cli, SMBtrans2,
543                                &rparam, &param_len,
544                                &rdata, &data_len)) {
545                 return False;
546         }
547
548         if (!rdata || data_len < 4) {
549                 return False;
550         }
551
552         clistr_pull(cli, name, rdata+4, sizeof(pstring), IVAL(rdata, 0), STR_UNICODE);
553
554         return True;
555 }
556
557
558 /****************************************************************************
559 send a qfileinfo call
560 ****************************************************************************/
561 BOOL cli_qfileinfo(struct cli_state *cli, int fnum, 
562                    uint16 *mode, size_t *size,
563                    time_t *c_time, time_t *a_time, time_t *m_time, 
564                    time_t *w_time, SMB_INO_T *ino)
565 {
566         unsigned int data_len = 0;
567         unsigned int param_len = 0;
568         uint16 setup = TRANSACT2_QFILEINFO;
569         pstring param;
570         char *rparam=NULL, *rdata=NULL;
571
572         /* if its a win95 server then fail this - win95 totally screws it
573            up */
574         if (cli->win95) return False;
575
576         param_len = 4;
577
578         memset(param, 0, param_len);
579         SSVAL(param, 0, fnum);
580         SSVAL(param, 2, SMB_QUERY_FILE_ALL_INFO);
581
582         if (!cli_send_trans(cli, SMBtrans2, 
583                             NULL,                           /* name */
584                             -1, 0,                          /* fid, flags */
585                             &setup, 1, 0,                   /* setup, length, max */
586                             param, param_len, 2,            /* param, length, max */
587                             NULL, data_len, cli->max_xmit   /* data, length, max */
588                            )) {
589                 return False;
590         }
591
592         if (!cli_receive_trans(cli, SMBtrans2,
593                                &rparam, &param_len,
594                                &rdata, &data_len)) {
595                 return False;
596         }
597
598         if (!rdata || data_len < 68) {
599                 return False;
600         }
601
602         if (c_time) {
603                 *c_time = interpret_long_date(rdata+0) - cli->serverzone;
604         }
605         if (a_time) {
606                 *a_time = interpret_long_date(rdata+8) - cli->serverzone;
607         }
608         if (m_time) {
609                 *m_time = interpret_long_date(rdata+16) - cli->serverzone;
610         }
611         if (w_time) {
612                 *w_time = interpret_long_date(rdata+24) - cli->serverzone;
613         }
614         if (mode) {
615                 *mode = SVAL(rdata, 32);
616         }
617         if (size) {
618                 *size = IVAL(rdata, 48);
619         }
620         if (ino) {
621                 *ino = IVAL(rdata, 64);
622         }
623
624         SAFE_FREE(rdata);
625         SAFE_FREE(rparam);
626         return True;
627 }
628
629 /****************************************************************************
630 send a qfileinfo call
631 ****************************************************************************/
632 BOOL cli_qfileinfo_test(struct cli_state *cli, int fnum, int level, char *outdata)
633 {
634         unsigned int data_len = 0;
635         unsigned int param_len = 0;
636         uint16 setup = TRANSACT2_QFILEINFO;
637         pstring param;
638         char *rparam=NULL, *rdata=NULL;
639
640         /* if its a win95 server then fail this - win95 totally screws it
641            up */
642         if (cli->win95) return False;
643
644         param_len = 4;
645
646         memset(param, 0, param_len);
647         SSVAL(param, 0, fnum);
648         SSVAL(param, 2, level);
649
650         if (!cli_send_trans(cli, SMBtrans2, 
651                             NULL,                           /* name */
652                             -1, 0,                          /* fid, flags */
653                             &setup, 1, 0,                   /* setup, length, max */
654                             param, param_len, 2,            /* param, length, max */
655                             NULL, data_len, cli->max_xmit   /* data, length, max */
656                            )) {
657                 return False;
658         }
659
660         if (!cli_receive_trans(cli, SMBtrans2,
661                                &rparam, &param_len,
662                                &rdata, &data_len)) {
663                 return False;
664         }
665
666         memcpy(outdata, rdata, data_len);
667
668         SAFE_FREE(rdata);
669         SAFE_FREE(rparam);
670         return True;
671 }
672
673
674
675 /****************************************************************************
676 send a qpathinfo SMB_QUERY_FILE_ALT_NAME_INFO call
677 ****************************************************************************/
678 NTSTATUS cli_qpathinfo_alt_name(struct cli_state *cli, const char *fname, fstring alt_name)
679 {
680         unsigned int data_len = 0;
681         unsigned int param_len = 0;
682         uint16 setup = TRANSACT2_QPATHINFO;
683         pstring param;
684         char *rparam=NULL, *rdata=NULL;
685         int count=8;
686         char *p;
687         BOOL ret;
688         unsigned int len;
689
690         p = param;
691         memset(p, 0, 6);
692         SSVAL(p, 0, SMB_QUERY_FILE_ALT_NAME_INFO);
693         p += 6;
694         p += clistr_push(cli, p, fname, sizeof(pstring)-6, STR_TERMINATE);
695
696         param_len = PTR_DIFF(p, param);
697
698         do {
699                 ret = (cli_send_trans(cli, SMBtrans2, 
700                                       NULL,           /* Name */
701                                       -1, 0,          /* fid, flags */
702                                       &setup, 1, 0,   /* setup, length, max */
703                                       param, param_len, 10, /* param, length, max */
704                                       NULL, data_len, cli->max_xmit /* data, length, max */
705                                       ) &&
706                        cli_receive_trans(cli, SMBtrans2, 
707                                          &rparam, &param_len,
708                                          &rdata, &data_len));
709                 if (!ret && cli_is_dos_error(cli)) {
710                         /* we need to work around a Win95 bug - sometimes
711                            it gives ERRSRV/ERRerror temprarily */
712                         uint8 eclass;
713                         uint32 ecode;
714                         cli_dos_error(cli, &eclass, &ecode);
715                         if (eclass != ERRSRV || ecode != ERRerror) break;
716                         msleep(100);
717                 }
718         } while (count-- && ret==False);
719
720         if (!ret || !rdata || data_len < 4) {
721                 return NT_STATUS_UNSUCCESSFUL;
722         }
723
724         len = IVAL(rdata, 0);
725
726         if (len > data_len - 4) {
727                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
728         }
729
730         clistr_pull(cli, alt_name, rdata+4, sizeof(fstring), len, STR_UNICODE);
731
732         SAFE_FREE(rdata);
733         SAFE_FREE(rparam);
734
735         return NT_STATUS_OK;
736 }