Apply some const
[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    
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         unsigned 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         unsigned 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 *,
210                                   const void *),
211                        const void *state)
212 {
213         char *rparam = NULL;
214         char *rdata = NULL;
215         unsigned int rdrcnt,rprcnt;
216         char *p;
217         pstring param;
218         int uLevel = 1;
219         int count = -1;
220
221         /* send a SMBtrans command with api NetServerEnum */
222         p = param;
223         SSVAL(p,0,0x68); /* api number */
224         p += 2;
225         pstrcpy_base(p,"WrLehDz", param);
226         p = skip_string(p,1);
227   
228         pstrcpy_base(p,"B16BBDz", param);
229
230         p = skip_string(p,1);
231         SSVAL(p,0,uLevel);
232         SSVAL(p,2,CLI_BUFFER_SIZE);
233         p += 4;
234         SIVAL(p,0,stype);
235         p += 4;
236
237         p += push_ascii(p, workgroup, sizeof(pstring)-PTR_DIFF(p,param)-1, STR_TERMINATE|STR_UPPER);
238         
239         if (cli_api(cli, 
240                     param, PTR_DIFF(p,param), 8,        /* params, length, max */
241                     NULL, 0, CLI_BUFFER_SIZE,               /* data, length, max */
242                     &rparam, &rprcnt,                   /* return params, return size */
243                     &rdata, &rdrcnt                     /* return data, return size */
244                    )) {
245                 int res = rparam? SVAL(rparam,0) : -1;
246                         
247                 if (res == 0 || res == ERRmoredata) {
248                         int i;
249                         int converter=SVAL(rparam,2);
250
251                         count=SVAL(rparam,4);
252                         p = rdata;
253                                         
254                         for (i = 0;i < count;i++, p += 26) {
255                                 char *sname = p;
256                                 int comment_offset = (IVAL(p,22) & 0xFFFF)-converter;
257                                 const char *cmnt = comment_offset?(rdata+comment_offset):"";
258                                 pstring s1, s2;
259
260                                 if (comment_offset < 0 || comment_offset > (int)rdrcnt) continue;
261
262                                 stype = IVAL(p,18) & ~SV_TYPE_LOCAL_LIST_ONLY;
263
264                                 pull_ascii_pstring(s1, sname);
265                                 pull_ascii_pstring(s2, cmnt);
266                                 fn(s1, stype, s2, state);
267                         }
268                 }
269         }
270   
271         SAFE_FREE(rparam);
272         SAFE_FREE(rdata);
273         
274         return(count > 0);
275 }
276
277
278
279 /****************************************************************************
280 Send a SamOEMChangePassword command
281 ****************************************************************************/
282 BOOL cli_oem_change_password(struct cli_state *cli, const char *user, const char *new_password,
283                              const char *old_password)
284 {
285   pstring param;
286   char data[532];
287   char *p = param;
288   unsigned char old_pw_hash[16];
289   unsigned char new_pw_hash[16];
290   unsigned int data_len;
291   unsigned int param_len = 0;
292   char *rparam = NULL;
293   char *rdata = NULL;
294   unsigned int rprcnt, rdrcnt;
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   encode_pw_buffer(data, new_password, STR_ASCII);
321   
322 #ifdef DEBUG_PASSWORD
323   DEBUG(100,("make_oem_passwd_hash\n"));
324   dump_data(100, data, 516);
325 #endif
326   SamOEMhash( (unsigned char *)data, (unsigned char *)old_pw_hash, 516);
327
328   /* 
329    * Now place the old password hash in the data.
330    */
331   E_deshash(new_password, new_pw_hash);
332
333   E_old_pw_hash( new_pw_hash, old_pw_hash, (uchar *)&data[516]);
334
335   data_len = 532;
336     
337   if (cli_send_trans(cli,SMBtrans,
338                     PIPE_LANMAN,                          /* name */
339                     0,0,                                  /* fid, flags */
340                     NULL,0,0,                             /* setup, length, max */
341                     param,param_len,2,                    /* param, length, max */
342                     data,data_len,0                       /* data, length, max */
343                    ) == False) {
344     DEBUG(0,("cli_oem_change_password: Failed to send password change for user %s\n",
345               user ));
346     return False;
347   }
348
349   if (!cli_receive_trans(cli,SMBtrans,
350                        &rparam, &rprcnt,
351                        &rdata, &rdrcnt)) {
352           DEBUG(0,("cli_oem_change_password: Failed to recieve reply to password change for user %s\n",
353                    user ));
354           return False;
355   }
356   
357   if (rparam)
358           cli->rap_error = SVAL(rparam,0);
359   
360   SAFE_FREE(rparam);
361   SAFE_FREE(rdata);
362
363   return (cli->rap_error == 0);
364 }
365
366
367 /****************************************************************************
368 send a qpathinfo call
369 ****************************************************************************/
370 BOOL cli_qpathinfo(struct cli_state *cli, const char *fname, 
371                    time_t *c_time, time_t *a_time, time_t *m_time, 
372                    size_t *size, uint16 *mode)
373 {
374         unsigned int data_len = 0;
375         unsigned int param_len = 0;
376         unsigned int rparam_len, rdata_len;
377         uint16 setup = TRANSACT2_QPATHINFO;
378         pstring param;
379         char *rparam=NULL, *rdata=NULL;
380         int count=8;
381         BOOL ret;
382         time_t (*date_fn)(void *);
383         char *p;
384
385         p = param;
386         memset(p, 0, 6);
387         SSVAL(p, 0, SMB_INFO_STANDARD);
388         p += 6;
389         p += clistr_push(cli, p, fname, sizeof(pstring)-6, STR_TERMINATE);
390
391         param_len = PTR_DIFF(p, param);
392
393         do {
394                 ret = (cli_send_trans(cli, SMBtrans2, 
395                                       NULL,           /* Name */
396                                       -1, 0,          /* fid, flags */
397                                       &setup, 1, 0,   /* setup, length, max */
398                                       param, param_len, 10, /* param, length, max */
399                                       NULL, data_len, cli->max_xmit /* data, length, max */
400                                       ) &&
401                        cli_receive_trans(cli, SMBtrans2, 
402                                          &rparam, &rparam_len,
403                                          &rdata, &rdata_len));
404                 if (!cli_is_dos_error(cli)) break;
405                 if (!ret) {
406                         /* we need to work around a Win95 bug - sometimes
407                            it gives ERRSRV/ERRerror temprarily */
408                         uint8 eclass;
409                         uint32 ecode;
410                         cli_dos_error(cli, &eclass, &ecode);
411                         if (eclass != ERRSRV || ecode != ERRerror) break;
412                         smb_msleep(100);
413                 }
414         } while (count-- && ret==False);
415
416         if (!ret || !rdata || rdata_len < 22) {
417                 return False;
418         }
419
420         if (cli->win95) {
421                 date_fn = make_unix_date;
422         } else {
423                 date_fn = make_unix_date2;
424         }
425
426         if (c_time) {
427                 *c_time = date_fn(rdata+0);
428         }
429         if (a_time) {
430                 *a_time = date_fn(rdata+4);
431         }
432         if (m_time) {
433                 *m_time = date_fn(rdata+8);
434         }
435         if (size) {
436                 *size = IVAL(rdata, 12);
437         }
438         if (mode) {
439                 *mode = SVAL(rdata,l1_attrFile);
440         }
441
442         SAFE_FREE(rdata);
443         SAFE_FREE(rparam);
444         return True;
445 }
446
447 /****************************************************************************
448 send a qpathinfo call with the SMB_QUERY_FILE_ALL_INFO info level
449 ****************************************************************************/
450 BOOL cli_qpathinfo2(struct cli_state *cli, const char *fname, 
451                     time_t *c_time, time_t *a_time, time_t *m_time, 
452                     time_t *w_time, size_t *size, uint16 *mode,
453                     SMB_INO_T *ino)
454 {
455         unsigned int data_len = 0;
456         unsigned int param_len = 0;
457         uint16 setup = TRANSACT2_QPATHINFO;
458         pstring param;
459         char *rparam=NULL, *rdata=NULL;
460         char *p;
461
462         p = param;
463         memset(p, 0, 6);
464         SSVAL(p, 0, SMB_QUERY_FILE_ALL_INFO);
465         p += 6;
466         p += clistr_push(cli, p, fname, sizeof(pstring)-6, STR_TERMINATE);
467
468         param_len = PTR_DIFF(p, param);
469
470         if (!cli_send_trans(cli, SMBtrans2, 
471                             NULL,                         /* name */
472                             -1, 0,                        /* fid, flags */
473                             &setup, 1, 0,                 /* setup, length, max */
474                             param, param_len, 10,         /* param, length, max */
475                             NULL, data_len, cli->max_xmit /* data, length, max */
476                            )) {
477                 return False;
478         }
479
480         if (!cli_receive_trans(cli, SMBtrans2,
481                                &rparam, &param_len,
482                                &rdata, &data_len)) {
483                 return False;
484         }
485
486         if (!rdata || data_len < 22) {
487                 return False;
488         }
489
490         if (c_time) {
491                 *c_time = interpret_long_date(rdata+0) - cli->serverzone;
492         }
493         if (a_time) {
494                 *a_time = interpret_long_date(rdata+8) - cli->serverzone;
495         }
496         if (m_time) {
497                 *m_time = interpret_long_date(rdata+16) - cli->serverzone;
498         }
499         if (w_time) {
500                 *w_time = interpret_long_date(rdata+24) - cli->serverzone;
501         }
502         if (mode) {
503                 *mode = SVAL(rdata, 32);
504         }
505         if (size) {
506                 *size = IVAL(rdata, 48);
507         }
508         if (ino) {
509                 *ino = IVAL(rdata, 64);
510         }
511
512         SAFE_FREE(rdata);
513         SAFE_FREE(rparam);
514         return True;
515 }
516
517
518 /****************************************************************************
519 send a qfileinfo QUERY_FILE_NAME_INFO call
520 ****************************************************************************/
521 BOOL cli_qfilename(struct cli_state *cli, int fnum, 
522                    pstring name)
523 {
524         unsigned int data_len = 0;
525         unsigned int param_len = 0;
526         uint16 setup = TRANSACT2_QFILEINFO;
527         pstring param;
528         char *rparam=NULL, *rdata=NULL;
529
530         param_len = 4;
531         memset(param, 0, param_len);
532         SSVAL(param, 0, fnum);
533         SSVAL(param, 2, SMB_QUERY_FILE_NAME_INFO);
534
535         if (!cli_send_trans(cli, SMBtrans2, 
536                             NULL,                           /* name */
537                             -1, 0,                          /* fid, flags */
538                             &setup, 1, 0,                   /* setup, length, max */
539                             param, param_len, 2,            /* param, length, max */
540                             NULL, data_len, cli->max_xmit   /* data, length, max */
541                            )) {
542                 return False;
543         }
544
545         if (!cli_receive_trans(cli, SMBtrans2,
546                                &rparam, &param_len,
547                                &rdata, &data_len)) {
548                 return False;
549         }
550
551         if (!rdata || data_len < 4) {
552                 return False;
553         }
554
555         clistr_pull(cli, name, rdata+4, sizeof(pstring), IVAL(rdata, 0), STR_UNICODE);
556
557         return True;
558 }
559
560
561 /****************************************************************************
562 send a qfileinfo call
563 ****************************************************************************/
564 BOOL cli_qfileinfo(struct cli_state *cli, int fnum, 
565                    uint16 *mode, size_t *size,
566                    time_t *c_time, time_t *a_time, time_t *m_time, 
567                    time_t *w_time, SMB_INO_T *ino)
568 {
569         unsigned int data_len = 0;
570         unsigned int param_len = 0;
571         uint16 setup = TRANSACT2_QFILEINFO;
572         pstring param;
573         char *rparam=NULL, *rdata=NULL;
574
575         /* if its a win95 server then fail this - win95 totally screws it
576            up */
577         if (cli->win95) return False;
578
579         param_len = 4;
580
581         memset(param, 0, param_len);
582         SSVAL(param, 0, fnum);
583         SSVAL(param, 2, SMB_QUERY_FILE_ALL_INFO);
584
585         if (!cli_send_trans(cli, SMBtrans2, 
586                             NULL,                           /* name */
587                             -1, 0,                          /* fid, flags */
588                             &setup, 1, 0,                   /* setup, length, max */
589                             param, param_len, 2,            /* param, length, max */
590                             NULL, data_len, cli->max_xmit   /* data, length, max */
591                            )) {
592                 return False;
593         }
594
595         if (!cli_receive_trans(cli, SMBtrans2,
596                                &rparam, &param_len,
597                                &rdata, &data_len)) {
598                 return False;
599         }
600
601         if (!rdata || data_len < 68) {
602                 return False;
603         }
604
605         if (c_time) {
606                 *c_time = interpret_long_date(rdata+0) - cli->serverzone;
607         }
608         if (a_time) {
609                 *a_time = interpret_long_date(rdata+8) - cli->serverzone;
610         }
611         if (m_time) {
612                 *m_time = interpret_long_date(rdata+16) - cli->serverzone;
613         }
614         if (w_time) {
615                 *w_time = interpret_long_date(rdata+24) - cli->serverzone;
616         }
617         if (mode) {
618                 *mode = SVAL(rdata, 32);
619         }
620         if (size) {
621                 *size = IVAL(rdata, 48);
622         }
623         if (ino) {
624                 *ino = IVAL(rdata, 64);
625         }
626
627         SAFE_FREE(rdata);
628         SAFE_FREE(rparam);
629         return True;
630 }
631
632 /****************************************************************************
633 send a qfileinfo call
634 ****************************************************************************/
635 BOOL cli_qfileinfo_test(struct cli_state *cli, int fnum, int level, char **poutdata, uint32 *poutlen)
636 {
637         unsigned int data_len = 0;
638         unsigned int param_len = 0;
639         uint16 setup = TRANSACT2_QFILEINFO;
640         pstring param;
641         char *rparam=NULL, *rdata=NULL;
642
643         *poutdata = NULL;
644         *poutlen = 0;
645
646         /* if its a win95 server then fail this - win95 totally screws it
647            up */
648         if (cli->win95)
649                 return False;
650
651         param_len = 4;
652
653         memset(param, 0, param_len);
654         SSVAL(param, 0, fnum);
655         SSVAL(param, 2, level);
656
657         if (!cli_send_trans(cli, SMBtrans2, 
658                             NULL,                           /* name */
659                             -1, 0,                          /* fid, flags */
660                             &setup, 1, 0,                   /* setup, length, max */
661                             param, param_len, 2,            /* param, length, max */
662                             NULL, data_len, cli->max_xmit   /* data, length, max */
663                            )) {
664                 return False;
665         }
666
667         if (!cli_receive_trans(cli, SMBtrans2,
668                                &rparam, &param_len,
669                                &rdata, &data_len)) {
670                 return False;
671         }
672
673         *poutdata = memdup(rdata, data_len);
674         *poutlen = data_len;
675
676         SAFE_FREE(rdata);
677         SAFE_FREE(rparam);
678         return True;
679 }
680
681
682
683 /****************************************************************************
684 send a qpathinfo SMB_QUERY_FILE_ALT_NAME_INFO call
685 ****************************************************************************/
686 NTSTATUS cli_qpathinfo_alt_name(struct cli_state *cli, const char *fname, fstring alt_name)
687 {
688         unsigned int data_len = 0;
689         unsigned int param_len = 0;
690         uint16 setup = TRANSACT2_QPATHINFO;
691         pstring param;
692         char *rparam=NULL, *rdata=NULL;
693         int count=8;
694         char *p;
695         BOOL ret;
696         unsigned int len;
697
698         p = param;
699         memset(p, 0, 6);
700         SSVAL(p, 0, SMB_QUERY_FILE_ALT_NAME_INFO);
701         p += 6;
702         p += clistr_push(cli, p, fname, sizeof(pstring)-6, STR_TERMINATE);
703
704         param_len = PTR_DIFF(p, param);
705
706         do {
707                 ret = (cli_send_trans(cli, SMBtrans2, 
708                                       NULL,           /* Name */
709                                       -1, 0,          /* fid, flags */
710                                       &setup, 1, 0,   /* setup, length, max */
711                                       param, param_len, 10, /* param, length, max */
712                                       NULL, data_len, cli->max_xmit /* data, length, max */
713                                       ) &&
714                        cli_receive_trans(cli, SMBtrans2, 
715                                          &rparam, &param_len,
716                                          &rdata, &data_len));
717                 if (!ret && cli_is_dos_error(cli)) {
718                         /* we need to work around a Win95 bug - sometimes
719                            it gives ERRSRV/ERRerror temprarily */
720                         uint8 eclass;
721                         uint32 ecode;
722                         cli_dos_error(cli, &eclass, &ecode);
723                         if (eclass != ERRSRV || ecode != ERRerror) break;
724                         smb_msleep(100);
725                 }
726         } while (count-- && ret==False);
727
728         if (!ret || !rdata || data_len < 4) {
729                 return NT_STATUS_UNSUCCESSFUL;
730         }
731
732         len = IVAL(rdata, 0);
733
734         if (len > data_len - 4) {
735                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
736         }
737
738         clistr_pull(cli, alt_name, rdata+4, sizeof(fstring), len, STR_UNICODE);
739
740         SAFE_FREE(rdata);
741         SAFE_FREE(rparam);
742
743         return NT_STATUS_OK;
744 }