Adding the same changes to HEAD as were added to BRANCH_1_9_18.
[samba.git] / source3 / libsmb / clientgen.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    SMB client generic functions
5    Copyright (C) Andrew Tridgell 1994-1998
6    
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 #ifdef SYSLOG
23 #undef SYSLOG
24 #endif
25
26 #include "includes.h"
27 #include "trans2.h"
28
29
30 extern int DEBUGLEVEL;
31
32 /****************************************************************************
33 setup basics in a outgoing packet
34 ****************************************************************************/
35 static void cli_setup_packet(struct cli_state *cli)
36 {
37         SSVAL(cli->outbuf,smb_pid,cli->pid);
38         SSVAL(cli->outbuf,smb_uid,cli->uid);
39         SSVAL(cli->outbuf,smb_mid,cli->mid);
40         if (cli->protocol > PROTOCOL_CORE) {
41                 SCVAL(cli->outbuf,smb_flg,0x8);
42                 SSVAL(cli->outbuf,smb_flg2,0x1);
43         }
44 }
45
46
47 /****************************************************************************
48   send a SMB trans or trans2 request
49   ****************************************************************************/
50 static BOOL cli_send_trans(struct cli_state *cli,
51                            int trans, char *name, int fid, int flags,
52                            char *data,char *param,uint16 *setup, int ldata,int lparam,
53                            int lsetup,int mdata,int mparam,int msetup)
54 {
55         int i;
56         int this_ldata,this_lparam;
57         int tot_data=0,tot_param=0;
58         char *outdata,*outparam;
59         char *p;
60
61         this_lparam = MIN(lparam,cli->max_xmit - (500+lsetup*2)); /* hack */
62         this_ldata = MIN(ldata,cli->max_xmit - (500+lsetup*2+this_lparam));
63
64         bzero(cli->outbuf,smb_size);
65         set_message(cli->outbuf,14+lsetup,0,True);
66         CVAL(cli->outbuf,smb_com) = trans;
67         SSVAL(cli->outbuf,smb_tid, cli->cnum);
68         cli_setup_packet(cli);
69
70         outparam = smb_buf(cli->outbuf)+(trans==SMBtrans ? strlen(name)+1 : 3);
71         outdata = outparam+this_lparam;
72
73         /* primary request */
74         SSVAL(cli->outbuf,smb_tpscnt,lparam);   /* tpscnt */
75         SSVAL(cli->outbuf,smb_tdscnt,ldata);    /* tdscnt */
76         SSVAL(cli->outbuf,smb_mprcnt,mparam);   /* mprcnt */
77         SSVAL(cli->outbuf,smb_mdrcnt,mdata);    /* mdrcnt */
78         SCVAL(cli->outbuf,smb_msrcnt,msetup);   /* msrcnt */
79         SSVAL(cli->outbuf,smb_flags,flags);     /* flags */
80         SIVAL(cli->outbuf,smb_timeout,0);               /* timeout */
81         SSVAL(cli->outbuf,smb_pscnt,this_lparam);       /* pscnt */
82         SSVAL(cli->outbuf,smb_psoff,smb_offset(outparam,cli->outbuf)); /* psoff */
83         SSVAL(cli->outbuf,smb_dscnt,this_ldata);        /* dscnt */
84         SSVAL(cli->outbuf,smb_dsoff,smb_offset(outdata,cli->outbuf)); /* dsoff */
85         SCVAL(cli->outbuf,smb_suwcnt,lsetup);   /* suwcnt */
86         for (i=0;i<lsetup;i++)          /* setup[] */
87                 SSVAL(cli->outbuf,smb_setup+i*2,setup[i]);
88         p = smb_buf(cli->outbuf);
89         if (trans==SMBtrans) {
90                 strcpy(p,name);                 /* name[] */
91         } else {
92                 *p++ = 0;  /* put in a null smb_name */
93                 *p++ = 'D'; *p++ = ' '; /* observed in OS/2 */
94         }
95         if (this_lparam)                        /* param[] */
96                 memcpy(outparam,param,this_lparam);
97         if (this_ldata)                 /* data[] */
98                 memcpy(outdata,data,this_ldata);
99         set_message(cli->outbuf,14+lsetup,              /* wcnt, bcc */
100                     PTR_DIFF(outdata+this_ldata,smb_buf(cli->outbuf)),False);
101
102         show_msg(cli->outbuf);
103         send_smb(cli->fd,cli->outbuf);
104
105         if (this_ldata < ldata || this_lparam < lparam) {
106                 /* receive interim response */
107                 if (!client_receive_smb(cli->fd,cli->inbuf,cli->timeout) || 
108                     CVAL(cli->inbuf,smb_rcls) != 0) {
109                         return(False);
110                 }      
111
112                 tot_data = this_ldata;
113                 tot_param = this_lparam;
114                 
115                 while (tot_data < ldata || tot_param < lparam)  {
116                         this_lparam = MIN(lparam-tot_param,cli->max_xmit - 500); /* hack */
117                         this_ldata = MIN(ldata-tot_data,cli->max_xmit - (500+this_lparam));
118
119                         set_message(cli->outbuf,trans==SMBtrans?8:9,0,True);
120                         CVAL(cli->outbuf,smb_com) = trans==SMBtrans ? SMBtranss : SMBtranss2;
121                         
122                         outparam = smb_buf(cli->outbuf);
123                         outdata = outparam+this_lparam;
124                         
125                         /* secondary request */
126                         SSVAL(cli->outbuf,smb_tpscnt,lparam);   /* tpscnt */
127                         SSVAL(cli->outbuf,smb_tdscnt,ldata);    /* tdscnt */
128                         SSVAL(cli->outbuf,smb_spscnt,this_lparam);      /* pscnt */
129                         SSVAL(cli->outbuf,smb_spsoff,smb_offset(outparam,cli->outbuf)); /* psoff */
130                         SSVAL(cli->outbuf,smb_spsdisp,tot_param);       /* psdisp */
131                         SSVAL(cli->outbuf,smb_sdscnt,this_ldata);       /* dscnt */
132                         SSVAL(cli->outbuf,smb_sdsoff,smb_offset(outdata,cli->outbuf)); /* dsoff */
133                         SSVAL(cli->outbuf,smb_sdsdisp,tot_data);        /* dsdisp */
134                         if (trans==SMBtrans2)
135                                 SSVALS(cli->outbuf,smb_sfid,fid);               /* fid */
136                         if (this_lparam)                        /* param[] */
137                                 memcpy(outparam,param,this_lparam);
138                         if (this_ldata)                 /* data[] */
139                                 memcpy(outdata,data,this_ldata);
140                         set_message(cli->outbuf,trans==SMBtrans?8:9, /* wcnt, bcc */
141                                     PTR_DIFF(outdata+this_ldata,smb_buf(cli->outbuf)),False);
142                         
143                         show_msg(cli->outbuf);
144                         send_smb(cli->fd,cli->outbuf);
145                         
146                         tot_data += this_ldata;
147                         tot_param += this_lparam;
148                 }
149         }
150
151         return(True);
152 }
153
154
155 /****************************************************************************
156   receive a SMB trans or trans2 response allocating the necessary memory
157   ****************************************************************************/
158 static BOOL cli_receive_trans(struct cli_state *cli,
159                               int trans,int *data_len,
160                               int *param_len, char **data,char **param)
161 {
162         int total_data=0;
163         int total_param=0;
164         int this_data,this_param;
165         
166         *data_len = *param_len = 0;
167         
168         if (!client_receive_smb(cli->fd,cli->inbuf,cli->timeout))
169                 return False;
170
171         show_msg(cli->inbuf);
172         
173         /* sanity check */
174         if (CVAL(cli->inbuf,smb_com) != trans) {
175                 DEBUG(0,("Expected %s response, got command 0x%02x\n",
176                          trans==SMBtrans?"SMBtrans":"SMBtrans2", 
177                          CVAL(cli->inbuf,smb_com)));
178                 return(False);
179         }
180         if (CVAL(cli->inbuf,smb_rcls) != 0)
181                 return(False);
182
183         /* parse out the lengths */
184         total_data = SVAL(cli->inbuf,smb_tdrcnt);
185         total_param = SVAL(cli->inbuf,smb_tprcnt);
186
187         /* allocate it */
188         *data = Realloc(*data,total_data);
189         *param = Realloc(*param,total_param);
190
191         while (1)  {
192                 this_data = SVAL(cli->inbuf,smb_drcnt);
193                 this_param = SVAL(cli->inbuf,smb_prcnt);
194
195                 if (this_data + *data_len > total_data ||
196                     this_param + *param_len > total_param) {
197                         DEBUG(1,("Data overflow in cli_receive_trans\n"));
198                         return False;
199                 }
200
201                 if (this_data)
202                         memcpy(*data + SVAL(cli->inbuf,smb_drdisp),
203                                smb_base(cli->inbuf) + SVAL(cli->inbuf,smb_droff),
204                                this_data);
205                 if (this_param)
206                         memcpy(*param + SVAL(cli->inbuf,smb_prdisp),
207                                smb_base(cli->inbuf) + SVAL(cli->inbuf,smb_proff),
208                                this_param);
209                 *data_len += this_data;
210                 *param_len += this_param;
211
212                 /* parse out the total lengths again - they can shrink! */
213                 total_data = SVAL(cli->inbuf,smb_tdrcnt);
214                 total_param = SVAL(cli->inbuf,smb_tprcnt);
215                 
216                 if (total_data <= *data_len && total_param <= *param_len)
217                         break;
218                 
219                 if (!client_receive_smb(cli->fd,cli->inbuf,cli->timeout))
220                         return False;
221
222                 show_msg(cli->inbuf);
223                 
224                 /* sanity check */
225                 if (CVAL(cli->inbuf,smb_com) != trans) {
226                         DEBUG(0,("Expected %s response, got command 0x%02x\n",
227                                  trans==SMBtrans?"SMBtrans":"SMBtrans2", 
228                                  CVAL(cli->inbuf,smb_com)));
229                         return(False);
230                 }
231                 if (CVAL(cli->inbuf,smb_rcls) != 0)
232                         return(False);
233         }
234         
235         return(True);
236 }
237
238
239 /****************************************************************************
240 call a remote api
241 ****************************************************************************/
242 static BOOL cli_api(struct cli_state *cli,
243                     int prcnt,int drcnt,int mprcnt,int mdrcnt,int *rprcnt,
244                     int *rdrcnt, char *param,char *data, 
245                     char **rparam, char **rdata)
246 {
247   cli_send_trans(cli,SMBtrans,PIPE_LANMAN,0,0,
248                  data,param,NULL,
249                  drcnt,prcnt,0,
250                  mdrcnt,mprcnt,0);
251
252   return (cli_receive_trans(cli,SMBtrans,
253                                      rdrcnt,rprcnt,
254                                      rdata,rparam));
255 }
256
257
258 /****************************************************************************
259 perform a NetWkstaUserLogon
260 ****************************************************************************/
261 BOOL cli_NetWkstaUserLogon(struct cli_state *cli,char *user, char *workstation)
262 {
263         char *rparam = NULL;
264         char *rdata = NULL;
265         char *p;
266         int rdrcnt,rprcnt;
267         pstring param;
268
269         memset(param, 0, sizeof(param));
270         
271         /* send a SMBtrans command with api NetWkstaUserLogon */
272         p = param;
273         SSVAL(p,0,132); /* api number */
274         p += 2;
275         strcpy(p,"OOWb54WrLh");
276         p = skip_string(p,1);
277         strcpy(p,"WB21BWDWWDDDDDDDzzzD");
278         p = skip_string(p,1);
279         SSVAL(p,0,1);
280         p += 2;
281         strcpy(p,user);
282         strupper(p);
283         p += 21; p++; p += 15; p++; 
284         strcpy(p, workstation); 
285         strupper(p);
286         p += 16;
287         SSVAL(p, 0, BUFFER_SIZE);
288         p += 2;
289         SSVAL(p, 0, BUFFER_SIZE);
290         p += 2;
291         
292         cli->error = -1;
293         
294         if (cli_api(cli, PTR_DIFF(p,param),0,
295                     1024,BUFFER_SIZE,
296                     &rprcnt,&rdrcnt,
297                     param,NULL,
298                     &rparam,&rdata)) {
299                 cli->error = SVAL(rparam,0);
300                 p = rdata;
301                 
302                 if (cli->error == 0) {
303                         DEBUG(4,("NetWkstaUserLogon success\n"));
304                         cli->privilages = SVAL(p, 24);
305                         fstrcpy(cli->eff_name,p+2);
306                 } else {
307                         DEBUG(1,("NetwkstaUserLogon gave error %d\n", cli->error));
308                 }
309         }
310         
311         if (rparam) free(rparam);
312         if (rdata) free(rdata);
313         return cli->error == 0;
314 }
315
316
317 /****************************************************************************
318 call a NetServerEnum for the specified workgroup and servertype mask.
319 This function then calls the specified callback function for each name returned.
320
321 The callback function takes 3 arguments: the machine name, the server type and
322 the comment.
323 ****************************************************************************/
324 BOOL cli_NetServerEnum(struct cli_state *cli, char *workgroup, uint32 stype,
325                        void (*fn)(char *, uint32, char *))
326 {
327         char *rparam = NULL;
328         char *rdata = NULL;
329         int rdrcnt,rprcnt;
330         char *p;
331         pstring param;
332         int uLevel = 1;
333         int count = -1;
334   
335         /* send a SMBtrans command with api NetServerEnum */
336         p = param;
337         SSVAL(p,0,0x68); /* api number */
338         p += 2;
339         strcpy(p,"WrLehDz");
340         p = skip_string(p,1);
341   
342         strcpy(p,"B16BBDz");
343   
344         p = skip_string(p,1);
345         SSVAL(p,0,uLevel);
346         SSVAL(p,2,BUFFER_SIZE);
347         p += 4;
348         SIVAL(p,0,stype);
349         p += 4;
350         
351         pstrcpy(p, workgroup);
352         p = skip_string(p,1);
353         
354         if (cli_api(cli, 
355                     PTR_DIFF(p,param), /* param count */
356                     0, /*data count */
357                     8, /* mprcount */
358                     BUFFER_SIZE, /* mdrcount */
359                     &rprcnt,&rdrcnt,
360                     param, NULL, 
361                     &rparam,&rdata)) {
362                 int res = SVAL(rparam,0);
363                 int converter=SVAL(rparam,2);
364                 int i;
365                         
366                 if (res == 0) {
367                         count=SVAL(rparam,4);
368                         p = rdata;
369                                         
370                         for (i = 0;i < count;i++, p += 26) {
371                                 char *sname = p;
372                                 int comment_offset = (IVAL(p,22) & 0xFFFF)-converter;
373                                 char *cmnt = comment_offset?(rdata+comment_offset):"";
374                                 if (comment_offset < 0 || comment_offset > rdrcnt) continue;
375
376                                 stype = IVAL(p,18) & ~SV_TYPE_LOCAL_LIST_ONLY;
377
378                                 fn(sname, stype, cmnt);
379                         }
380                 }
381         }
382   
383         if (rparam) free(rparam);
384         if (rdata) free(rdata);
385         
386         return(count > 0);
387 }
388
389
390
391
392 static  struct {
393     int prot;
394     char *name;
395   }
396 prots[] = 
397     {
398       {PROTOCOL_CORE,"PC NETWORK PROGRAM 1.0"},
399       {PROTOCOL_COREPLUS,"MICROSOFT NETWORKS 1.03"},
400       {PROTOCOL_LANMAN1,"MICROSOFT NETWORKS 3.0"},
401       {PROTOCOL_LANMAN1,"LANMAN1.0"},
402       {PROTOCOL_LANMAN2,"LM1.2X002"},
403       {PROTOCOL_LANMAN2,"Samba"},
404       {PROTOCOL_NT1,"NT LM 0.12"},
405       {PROTOCOL_NT1,"NT LANMAN 1.0"},
406       {-1,NULL}
407     };
408
409
410 /****************************************************************************
411 send a session setup
412 ****************************************************************************/
413 BOOL cli_session_setup(struct cli_state *cli, 
414                        char *user, 
415                        char *pass, int passlen,
416                        char *ntpass, int ntpasslen,
417                        char *workgroup)
418 {
419         char *p;
420         fstring pword;
421
422         if (cli->protocol < PROTOCOL_LANMAN1)
423                 return True;
424
425         if (passlen > sizeof(pword)-1) {
426                 return False;
427         }
428
429         if ((cli->sec_mode & 2) && passlen != 24) {
430                 passlen = 24;
431                 SMBencrypt((uchar *)pass,(uchar *)cli->cryptkey,(uchar *)pword);
432         } else {
433                 memcpy(pword, pass, passlen);
434         }
435
436         /* if in share level security then don't send a password now */
437         if (!(cli->sec_mode & 1)) {fstrcpy(pword, "");passlen=1;} 
438
439         /* send a session setup command */
440         bzero(cli->outbuf,smb_size);
441
442         if (cli->protocol < PROTOCOL_NT1) {
443                 set_message(cli->outbuf,10,1 + strlen(user) + passlen,True);
444                 CVAL(cli->outbuf,smb_com) = SMBsesssetupX;
445                 cli_setup_packet(cli);
446
447                 CVAL(cli->outbuf,smb_vwv0) = 0xFF;
448                 SSVAL(cli->outbuf,smb_vwv2,cli->max_xmit);
449                 SSVAL(cli->outbuf,smb_vwv3,2);
450                 SSVAL(cli->outbuf,smb_vwv4,1);
451                 SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
452                 SSVAL(cli->outbuf,smb_vwv7,passlen);
453                 p = smb_buf(cli->outbuf);
454                 memcpy(p,pword,passlen);
455                 p += passlen;
456                 strcpy(p,user);
457                 strupper(p);
458         } else {
459                 set_message(cli->outbuf,13,0,True);
460                 CVAL(cli->outbuf,smb_com) = SMBsesssetupX;
461                 cli_setup_packet(cli);
462                 
463                 CVAL(cli->outbuf,smb_vwv0) = 0xFF;
464                 SSVAL(cli->outbuf,smb_vwv2,BUFFER_SIZE);
465                 SSVAL(cli->outbuf,smb_vwv3,2);
466                 SSVAL(cli->outbuf,smb_vwv4,cli->pid);
467                 SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
468                 SSVAL(cli->outbuf,smb_vwv7,passlen);
469                 SSVAL(cli->outbuf,smb_vwv8,ntpasslen);
470                 p = smb_buf(cli->outbuf);
471                 memcpy(p,pword,passlen); 
472                 p += SVAL(cli->outbuf,smb_vwv7);
473                 memcpy(p,ntpass,ntpasslen); 
474                 p += SVAL(cli->outbuf,smb_vwv8);
475                 strcpy(p,user);
476                 strupper(p);
477                 p = skip_string(p,1);
478                 strcpy(p,workgroup);
479                 strupper(p);
480                 p = skip_string(p,1);
481                 strcpy(p,"Unix");p = skip_string(p,1);
482                 strcpy(p,"Samba");p = skip_string(p,1);
483                 set_message(cli->outbuf,13,PTR_DIFF(p,smb_buf(cli->outbuf)),False);
484         }
485
486       send_smb(cli->fd,cli->outbuf);
487       if (!client_receive_smb(cli->fd,cli->inbuf,cli->timeout))
488               return False;
489
490       show_msg(cli->inbuf);
491
492       if (CVAL(cli->inbuf,smb_rcls) != 0) {
493               return False;
494       }
495
496       /* use the returned uid from now on */
497       cli->uid = SVAL(cli->inbuf,smb_uid);
498
499       return True;
500 }
501
502
503 /****************************************************************************
504 send a tconX
505 ****************************************************************************/
506 BOOL cli_send_tconX(struct cli_state *cli, 
507                     char *share, char *dev, char *pass, int passlen)
508 {
509         fstring fullshare, pword;
510         char *p;
511         bzero(cli->outbuf,smb_size);
512         bzero(cli->inbuf,smb_size);
513
514         if (cli->sec_mode & 1) {
515                 passlen = 1;
516                 pass = "";
517         }
518
519         if ((cli->sec_mode & 2) && *pass && passlen != 24) {
520                 passlen = 24;
521                 SMBencrypt((uchar *)pass,(uchar *)cli->cryptkey,(uchar *)pword);
522         } else {
523                 memcpy(pword, pass, passlen);
524         }
525
526         sprintf(fullshare, "\\\\%s\\%s", cli->desthost, share);
527
528         set_message(cli->outbuf,4,
529                     2 + strlen(fullshare) + passlen + strlen(dev),True);
530         CVAL(cli->outbuf,smb_com) = SMBtconX;
531         cli_setup_packet(cli);
532
533         SSVAL(cli->outbuf,smb_vwv0,0xFF);
534         SSVAL(cli->outbuf,smb_vwv3,passlen);
535
536         p = smb_buf(cli->outbuf);
537         memcpy(p,pword,passlen);
538         p += passlen;
539         strcpy(p,fullshare);
540         p = skip_string(p,1);
541         strcpy(p,dev);
542
543         SCVAL(cli->inbuf,smb_rcls, 1);
544
545         send_smb(cli->fd,cli->outbuf);
546         if (!client_receive_smb(cli->fd,cli->inbuf,cli->timeout))
547                 return False;
548
549         if (CVAL(cli->inbuf,smb_rcls) != 0) {
550                 return False;
551         }
552
553         cli->cnum = SVAL(cli->inbuf,smb_tid);
554         return True;
555 }
556
557
558 /****************************************************************************
559 send a tree disconnect
560 ****************************************************************************/
561 BOOL cli_tdis(struct cli_state *cli)
562 {
563         bzero(cli->outbuf,smb_size);
564         set_message(cli->outbuf,0,0,True);
565         CVAL(cli->outbuf,smb_com) = SMBtdis;
566         SSVAL(cli->outbuf,smb_tid,cli->cnum);
567         cli_setup_packet(cli);
568         
569         send_smb(cli->fd,cli->outbuf);
570         if (!client_receive_smb(cli->fd,cli->inbuf,cli->timeout))
571                 return False;
572         
573         return CVAL(cli->inbuf,smb_rcls) == 0;
574 }
575
576 /****************************************************************************
577 rename a file
578 ****************************************************************************/
579 BOOL cli_mv(struct cli_state *cli, char *fname_src, char *fname_dst)
580 {
581         char *p;
582
583         bzero(cli->outbuf,smb_size);
584         bzero(cli->inbuf,smb_size);
585
586         set_message(cli->outbuf,1, 4 + strlen(fname_src) + strlen(fname_dst), True);
587
588         CVAL(cli->outbuf,smb_com) = SMBmv;
589         SSVAL(cli->outbuf,smb_tid,cli->cnum);
590         cli_setup_packet(cli);
591
592         SSVAL(cli->outbuf,smb_vwv0,aSYSTEM | aHIDDEN);
593
594         p = smb_buf(cli->outbuf);
595         *p++ = 4;
596         strcpy(p,fname_src);
597         p = skip_string(p,1);
598         *p++ = 4;
599         strcpy(p,fname_dst);
600
601         send_smb(cli->fd,cli->outbuf);
602         if (!client_receive_smb(cli->fd,cli->inbuf,cli->timeout)) {
603                 return False;
604         }
605
606         if (CVAL(cli->inbuf,smb_rcls) != 0) {
607                 return False;
608         }
609
610         return True;
611 }
612
613 /****************************************************************************
614 delete a file
615 ****************************************************************************/
616 BOOL cli_unlink(struct cli_state *cli, char *fname)
617 {
618         char *p;
619
620         bzero(cli->outbuf,smb_size);
621         bzero(cli->inbuf,smb_size);
622
623         set_message(cli->outbuf,1, 2 + strlen(fname),True);
624
625         CVAL(cli->outbuf,smb_com) = SMBunlink;
626         SSVAL(cli->outbuf,smb_tid,cli->cnum);
627         cli_setup_packet(cli);
628
629         SSVAL(cli->outbuf,smb_vwv0,aSYSTEM | aHIDDEN);
630   
631         p = smb_buf(cli->outbuf);
632         *p++ = 4;      
633         strcpy(p,fname);
634
635         send_smb(cli->fd,cli->outbuf);
636         if (!client_receive_smb(cli->fd,cli->inbuf,cli->timeout)) {
637                 return False;
638         }
639
640         if (CVAL(cli->inbuf,smb_rcls) != 0) {
641                 return False;
642         }
643
644         return True;
645 }
646
647
648 /****************************************************************************
649 create a directory
650 ****************************************************************************/
651 BOOL cli_mkdir(struct cli_state *cli, char *dname)
652 {
653         char *p;
654
655         bzero(cli->outbuf,smb_size);
656         bzero(cli->inbuf,smb_size);
657
658         set_message(cli->outbuf,0, 2 + strlen(dname),True);
659
660         CVAL(cli->outbuf,smb_com) = SMBmkdir;
661         SSVAL(cli->outbuf,smb_tid,cli->cnum);
662         cli_setup_packet(cli);
663
664         p = smb_buf(cli->outbuf);
665         *p++ = 4;      
666         strcpy(p,dname);
667
668         send_smb(cli->fd,cli->outbuf);
669         if (!client_receive_smb(cli->fd,cli->inbuf,cli->timeout)) {
670                 return False;
671         }
672
673         if (CVAL(cli->inbuf,smb_rcls) != 0) {
674                 return False;
675         }
676
677         return True;
678 }
679
680 /****************************************************************************
681 remove a directory
682 ****************************************************************************/
683 BOOL cli_rmdir(struct cli_state *cli, char *dname)
684 {
685         char *p;
686
687         bzero(cli->outbuf,smb_size);
688         bzero(cli->inbuf,smb_size);
689
690         set_message(cli->outbuf,0, 2 + strlen(dname),True);
691
692         CVAL(cli->outbuf,smb_com) = SMBrmdir;
693         SSVAL(cli->outbuf,smb_tid,cli->cnum);
694         cli_setup_packet(cli);
695
696         p = smb_buf(cli->outbuf);
697         *p++ = 4;      
698         strcpy(p,dname);
699
700         send_smb(cli->fd,cli->outbuf);
701         if (!client_receive_smb(cli->fd,cli->inbuf,cli->timeout)) {
702                 return False;
703         }
704
705         if (CVAL(cli->inbuf,smb_rcls) != 0) {
706                 return False;
707         }
708
709         return True;
710 }
711
712
713
714 /****************************************************************************
715 open a file
716 ****************************************************************************/
717 int cli_open(struct cli_state *cli, char *fname, int flags, int share_mode)
718 {
719         char *p;
720         unsigned openfn=0;
721         unsigned accessmode=0;
722
723         if (flags & O_CREAT)
724                 openfn |= (1<<4);
725         if (!(flags & O_EXCL)) {
726                 if (flags & O_TRUNC)
727                         openfn |= (1<<1);
728                 else
729                         openfn |= (1<<0);
730         }
731
732         accessmode = (share_mode<<4);
733
734         if ((flags & O_RDWR) == O_RDWR) {
735                 accessmode |= 2;
736         } else if ((flags & O_WRONLY) == O_WRONLY) {
737                 accessmode |= 1;
738         } 
739
740         bzero(cli->outbuf,smb_size);
741         bzero(cli->inbuf,smb_size);
742
743         set_message(cli->outbuf,15,1 + strlen(fname),True);
744
745         CVAL(cli->outbuf,smb_com) = SMBopenX;
746         SSVAL(cli->outbuf,smb_tid,cli->cnum);
747         cli_setup_packet(cli);
748
749         SSVAL(cli->outbuf,smb_vwv0,0xFF);
750         SSVAL(cli->outbuf,smb_vwv2,0);  /* no additional info */
751         SSVAL(cli->outbuf,smb_vwv3,accessmode);
752         SSVAL(cli->outbuf,smb_vwv4,aSYSTEM | aHIDDEN);
753         SSVAL(cli->outbuf,smb_vwv5,0);
754         SSVAL(cli->outbuf,smb_vwv8,openfn);
755   
756         p = smb_buf(cli->outbuf);
757         strcpy(p,fname);
758         p = skip_string(p,1);
759
760         send_smb(cli->fd,cli->outbuf);
761         if (!client_receive_smb(cli->fd,cli->inbuf,cli->timeout)) {
762                 return -1;
763         }
764
765         if (CVAL(cli->inbuf,smb_rcls) != 0) {
766                 return -1;
767         }
768
769         return SVAL(cli->inbuf,smb_vwv2);
770 }
771
772
773
774
775 /****************************************************************************
776   close a file
777 ****************************************************************************/
778 BOOL cli_close(struct cli_state *cli, int fnum)
779 {
780         bzero(cli->outbuf,smb_size);
781         bzero(cli->inbuf,smb_size);
782
783         set_message(cli->outbuf,3,0,True);
784
785         CVAL(cli->outbuf,smb_com) = SMBclose;
786         SSVAL(cli->outbuf,smb_tid,cli->cnum);
787         cli_setup_packet(cli);
788
789         SSVAL(cli->outbuf,smb_vwv0,fnum);
790         SIVALS(cli->outbuf,smb_vwv1,-1);
791
792         send_smb(cli->fd,cli->outbuf);
793         if (!client_receive_smb(cli->fd,cli->inbuf,cli->timeout)) {
794                 return False;
795         }
796
797         if (CVAL(cli->inbuf,smb_rcls) != 0) {
798                 return False;
799         }
800
801         return True;
802 }
803
804
805 /****************************************************************************
806   lock a file
807 ****************************************************************************/
808 BOOL cli_lock(struct cli_state *cli, int fnum, uint32 offset, uint32 len, int timeout)
809 {
810         char *p;
811
812         bzero(cli->outbuf,smb_size);
813         bzero(cli->inbuf,smb_size);
814
815         set_message(cli->outbuf,8,10,True);
816
817         CVAL(cli->outbuf,smb_com) = SMBlockingX;
818         SSVAL(cli->outbuf,smb_tid,cli->cnum);
819         cli_setup_packet(cli);
820
821         CVAL(cli->outbuf,smb_vwv0) = 0xFF;
822         SSVAL(cli->outbuf,smb_vwv2,fnum);
823         CVAL(cli->outbuf,smb_vwv3) = 0;
824         SIVALS(cli->outbuf, smb_vwv4, timeout);
825         SSVAL(cli->outbuf,smb_vwv6,0);
826         SSVAL(cli->outbuf,smb_vwv7,1);
827
828         p = smb_buf(cli->outbuf);
829         SSVAL(p, 0, cli->pid);
830         SIVAL(p, 2, offset);
831         SIVAL(p, 6, len);
832
833         send_smb(cli->fd,cli->outbuf);
834         if (!client_receive_smb(cli->fd,cli->inbuf,cli->timeout)) {
835                 return False;
836         }
837
838         if (CVAL(cli->inbuf,smb_rcls) != 0) {
839                 return False;
840         }
841
842         return True;
843 }
844
845 /****************************************************************************
846   unlock a file
847 ****************************************************************************/
848 BOOL cli_unlock(struct cli_state *cli, int fnum, uint32 offset, uint32 len, int timeout)
849 {
850         char *p;
851
852         bzero(cli->outbuf,smb_size);
853         bzero(cli->inbuf,smb_size);
854
855         set_message(cli->outbuf,8,10,True);
856
857         CVAL(cli->outbuf,smb_com) = SMBlockingX;
858         SSVAL(cli->outbuf,smb_tid,cli->cnum);
859         cli_setup_packet(cli);
860
861         CVAL(cli->outbuf,smb_vwv0) = 0xFF;
862         SSVAL(cli->outbuf,smb_vwv2,fnum);
863         CVAL(cli->outbuf,smb_vwv3) = 0;
864         SIVALS(cli->outbuf, smb_vwv4, timeout);
865         SSVAL(cli->outbuf,smb_vwv6,1);
866         SSVAL(cli->outbuf,smb_vwv7,0);
867
868         p = smb_buf(cli->outbuf);
869         SSVAL(p, 0, cli->pid);
870         SIVAL(p, 2, offset);
871         SIVAL(p, 6, len);
872
873         send_smb(cli->fd,cli->outbuf);
874         if (!client_receive_smb(cli->fd,cli->inbuf,cli->timeout)) {
875                 return False;
876         }
877
878         if (CVAL(cli->inbuf,smb_rcls) != 0) {
879                 return False;
880         }
881
882         return True;
883 }
884
885
886 /****************************************************************************
887   read from a file
888 ****************************************************************************/
889 int cli_read(struct cli_state *cli, int fnum, char *buf, uint32 offset, uint16 size)
890 {
891         char *p;
892
893         bzero(cli->outbuf,smb_size);
894         bzero(cli->inbuf,smb_size);
895
896         set_message(cli->outbuf,10,0,True);
897
898         CVAL(cli->outbuf,smb_com) = SMBreadX;
899         SSVAL(cli->outbuf,smb_tid,cli->cnum);
900         cli_setup_packet(cli);
901
902         CVAL(cli->outbuf,smb_vwv0) = 0xFF;
903         SSVAL(cli->outbuf,smb_vwv2,fnum);
904         SIVAL(cli->outbuf,smb_vwv3,offset);
905         SSVAL(cli->outbuf,smb_vwv5,size);
906         SSVAL(cli->outbuf,smb_vwv6,size);
907
908         send_smb(cli->fd,cli->outbuf);
909         if (!client_receive_smb(cli->fd,cli->inbuf,cli->timeout)) {
910                 return -1;
911         }
912
913         if (CVAL(cli->inbuf,smb_rcls) != 0) {
914                 return -1;
915         }
916
917         size = SVAL(cli->inbuf, smb_vwv5);
918         p = smb_base(cli->inbuf) + SVAL(cli->inbuf,smb_vwv6);
919
920         memcpy(buf, p, size);
921
922         return size;
923 }
924
925
926 /****************************************************************************
927   write to a file
928 ****************************************************************************/
929 int cli_write(struct cli_state *cli, int fnum, char *buf, uint32 offset, uint16 size)
930 {
931         char *p;
932
933         bzero(cli->outbuf,smb_size);
934         bzero(cli->inbuf,smb_size);
935
936         set_message(cli->outbuf,12,size,True);
937
938         CVAL(cli->outbuf,smb_com) = SMBwriteX;
939         SSVAL(cli->outbuf,smb_tid,cli->cnum);
940         cli_setup_packet(cli);
941
942         CVAL(cli->outbuf,smb_vwv0) = 0xFF;
943         SSVAL(cli->outbuf,smb_vwv2,fnum);
944         SIVAL(cli->outbuf,smb_vwv3,offset);
945
946         SSVAL(cli->outbuf,smb_vwv10,size);
947         SSVAL(cli->outbuf,smb_vwv11,smb_buf(cli->outbuf) - smb_base(cli->outbuf));
948
949         p = smb_base(cli->outbuf) + SVAL(cli->outbuf,smb_vwv11);
950         memcpy(p, buf, size);
951
952         send_smb(cli->fd,cli->outbuf);
953         if (!client_receive_smb(cli->fd,cli->inbuf,cli->timeout)) {
954                 return -1;
955         }
956
957         if (CVAL(cli->inbuf,smb_rcls) != 0) {
958                 return -1;
959         }
960
961         return SVAL(cli->inbuf, smb_vwv2);
962 }
963
964
965 /****************************************************************************
966 do a SMBgetatr call
967 ****************************************************************************/
968 BOOL cli_getatr(struct cli_state *cli, char *fname, 
969                 int *attr, uint32 *size, time_t *t)
970 {
971         char *p;
972
973         bzero(cli->outbuf,smb_size);
974         bzero(cli->inbuf,smb_size);
975
976         set_message(cli->outbuf,0,strlen(fname)+2,True);
977
978         CVAL(cli->outbuf,smb_com) = SMBgetatr;
979         SSVAL(cli->outbuf,smb_tid,cli->cnum);
980         cli_setup_packet(cli);
981
982         p = smb_buf(cli->outbuf);
983         *p = 4;
984         strcpy(p+1, fname);
985
986         send_smb(cli->fd,cli->outbuf);
987         if (!client_receive_smb(cli->fd,cli->inbuf,cli->timeout)) {
988                 return False;
989         }
990         
991         if (CVAL(cli->inbuf,smb_rcls) != 0) {
992                 return False;
993         }
994
995         if (size) {
996                 *size = IVAL(cli->inbuf, smb_vwv3);
997         }
998
999         if (t) {
1000                 *t = make_unix_date3(cli->inbuf+smb_vwv1);
1001         }
1002
1003         if (attr) {
1004                 *attr = SVAL(cli->inbuf,smb_vwv0);
1005         }
1006
1007
1008         return True;
1009 }
1010
1011
1012 /****************************************************************************
1013 do a SMBsetatr call
1014 ****************************************************************************/
1015 BOOL cli_setatr(struct cli_state *cli, char *fname, int attr, time_t t)
1016 {
1017         char *p;
1018
1019         bzero(cli->outbuf,smb_size);
1020         bzero(cli->inbuf,smb_size);
1021
1022         set_message(cli->outbuf,8,strlen(fname)+4,True);
1023
1024         CVAL(cli->outbuf,smb_com) = SMBsetatr;
1025         SSVAL(cli->outbuf,smb_tid,cli->cnum);
1026         cli_setup_packet(cli);
1027
1028         SSVAL(cli->outbuf,smb_vwv0, attr);
1029         put_dos_date3(cli->outbuf,smb_vwv1, t);
1030
1031         p = smb_buf(cli->outbuf);
1032         *p = 4;
1033         strcpy(p+1, fname);
1034         p = skip_string(p,1);
1035         *p = 4;
1036
1037         send_smb(cli->fd,cli->outbuf);
1038         if (!client_receive_smb(cli->fd,cli->inbuf,cli->timeout)) {
1039                 return False;
1040         }
1041         
1042         if (CVAL(cli->inbuf,smb_rcls) != 0) {
1043                 return False;
1044         }
1045
1046         return True;
1047 }
1048
1049 /****************************************************************************
1050 send a qpathinfo call
1051 ****************************************************************************/
1052 BOOL cli_qpathinfo(struct cli_state *cli, char *fname, 
1053                    time_t *c_time, time_t *a_time, time_t *m_time, uint32 *size)
1054 {
1055         int data_len = 0;
1056         int param_len = 0;
1057         uint16 setup = TRANSACT2_QPATHINFO;
1058         pstring param;
1059         char *rparam=NULL, *rdata=NULL;
1060
1061         param_len = strlen(fname) + 7;
1062
1063         memset(param, 0, param_len);
1064         SSVAL(param, 0, SMB_INFO_STANDARD);
1065         pstrcpy(&param[6], fname);
1066
1067         if (!cli_send_trans(cli, SMBtrans2, NULL, -1, 0, 
1068                             NULL, param, &setup, 
1069                             data_len, param_len, 1,
1070                             cli->max_xmit, 10, 0)) {
1071                 return False;
1072         }
1073
1074         if (!cli_receive_trans(cli, SMBtrans2, &data_len, &param_len, 
1075                                &rdata, &rparam)) {
1076                 return False;
1077         }
1078
1079         if (!rdata || data_len < 22) {
1080                 return False;
1081         }
1082
1083         if (c_time) {
1084                 *c_time = make_unix_date2(rdata+0);
1085         }
1086         if (a_time) {
1087                 *a_time = make_unix_date2(rdata+4);
1088         }
1089         if (m_time) {
1090                 *m_time = make_unix_date2(rdata+8);
1091         }
1092         if (size) {
1093                 *size = IVAL(rdata, 12);
1094         }
1095
1096         if (rdata) free(rdata);
1097         if (rparam) free(rparam);
1098         return True;
1099 }
1100
1101 /****************************************************************************
1102 send a qpathinfo call with the SMB_QUERY_FILE_ALL_INFO info level
1103 ****************************************************************************/
1104 BOOL cli_qpathinfo2(struct cli_state *cli, char *fname, 
1105                     time_t *c_time, time_t *a_time, time_t *m_time, 
1106                     time_t *w_time, uint32 *size)
1107 {
1108         int data_len = 0;
1109         int param_len = 0;
1110         uint16 setup = TRANSACT2_QPATHINFO;
1111         pstring param;
1112         char *rparam=NULL, *rdata=NULL;
1113
1114         param_len = strlen(fname) + 7;
1115
1116         memset(param, 0, param_len);
1117         SSVAL(param, 0, SMB_QUERY_FILE_ALL_INFO);
1118         pstrcpy(&param[6], fname);
1119
1120         if (!cli_send_trans(cli, SMBtrans2, NULL, -1, 0, 
1121                             NULL, param, &setup, 
1122                             data_len, param_len, 1,
1123                             cli->max_xmit, 10, 0)) {
1124                 return False;
1125         }
1126
1127         if (!cli_receive_trans(cli, SMBtrans2, &data_len, &param_len, 
1128                                &rdata, &rparam)) {
1129                 return False;
1130         }
1131
1132         if (!rdata || data_len < 22) {
1133                 return False;
1134         }
1135
1136         if (c_time) {
1137                 *c_time = interpret_long_date(rdata+0) - cli->serverzone;
1138         }
1139         if (a_time) {
1140                 *a_time = interpret_long_date(rdata+8) - cli->serverzone;
1141         }
1142         if (m_time) {
1143                 *m_time = interpret_long_date(rdata+16) - cli->serverzone;
1144         }
1145         if (w_time) {
1146                 *w_time = interpret_long_date(rdata+24) - cli->serverzone;
1147         }
1148         if (size) {
1149                 *size = IVAL(rdata, 40);
1150         }
1151
1152         if (rdata) free(rdata);
1153         if (rparam) free(rparam);
1154         return True;
1155 }
1156
1157
1158 /****************************************************************************
1159 send a qfileinfo call
1160 ****************************************************************************/
1161 BOOL cli_qfileinfo(struct cli_state *cli, int fnum, 
1162                    time_t *c_time, time_t *a_time, time_t *m_time, uint32 *size)
1163 {
1164         int data_len = 0;
1165         int param_len = 0;
1166         uint16 setup = TRANSACT2_QFILEINFO;
1167         pstring param;
1168         char *rparam=NULL, *rdata=NULL;
1169
1170         param_len = 4;
1171
1172         memset(param, 0, param_len);
1173         SSVAL(param, 0, fnum);
1174         SSVAL(param, 2, SMB_INFO_STANDARD);
1175
1176         if (!cli_send_trans(cli, SMBtrans2, NULL, -1, 0, 
1177                             NULL, param, &setup, 
1178                             data_len, param_len, 1,
1179                             cli->max_xmit, 2, 0)) {
1180                 return False;
1181         }
1182
1183         if (!cli_receive_trans(cli, SMBtrans2, &data_len, &param_len, 
1184                                &rdata, &rparam)) {
1185                 return False;
1186         }
1187
1188         if (!rdata || data_len < 22) {
1189                 return False;
1190         }
1191
1192         if (c_time) {
1193                 *c_time = make_unix_date2(rdata+0);
1194         }
1195         if (a_time) {
1196                 *a_time = make_unix_date2(rdata+4);
1197         }
1198         if (m_time) {
1199                 *m_time = make_unix_date2(rdata+8);
1200         }
1201         if (size) {
1202                 *size = IVAL(rdata, 12);
1203         }
1204
1205         if (rdata) free(rdata);
1206         if (rparam) free(rparam);
1207         return True;
1208 }
1209
1210 /****************************************************************************
1211 Send a SamOEMChangePassword command
1212 ****************************************************************************/
1213
1214 BOOL cli_oem_change_password(struct cli_state *cli, char *user, char *new_password,
1215                              char *old_password)
1216 {
1217   char param[16+sizeof(fstring)];
1218   char data[532];
1219   char *p = param;
1220   fstring upper_case_old_pw;
1221   fstring upper_case_new_pw;
1222   unsigned char old_pw_hash[16];
1223   unsigned char new_pw_hash[16];
1224   int data_len;
1225   int param_len = 0;
1226   int new_pw_len = strlen(new_password);
1227   char *rparam = NULL;
1228   char *rdata = NULL;
1229   int rprcnt, rdrcnt;
1230
1231   cli->error = -1;
1232
1233   if(strlen(user) >= sizeof(fstring)-1) {
1234     DEBUG(0,("cli_oem_change_password: user name %s is too long.\n", user));
1235     return False;
1236   }
1237
1238   if(new_pw_len > 512) {
1239     DEBUG(0,("cli_oem_change_password: new password for user %s is too long.\n", user));
1240     return False;
1241   }
1242
1243   SSVAL(p,0,214); /* SamOEMChangePassword command. */
1244   p += 2;
1245   strcpy(p, "zsT");
1246   p = skip_string(p,1);
1247   strcpy(p, "B516B16");
1248   p = skip_string(p,1);
1249   fstrcpy(p,user);
1250   p = skip_string(p,1);
1251   SSVAL(p,0,532);
1252   p += 2;
1253
1254   param_len = PTR_DIFF(p,param);
1255
1256   /*
1257    * Now setup the data area.
1258    */
1259   memset(data, '\0', sizeof(data));
1260   fstrcpy( &data[512 - new_pw_len], new_password);
1261   SIVAL(data, 512, new_pw_len);
1262
1263   /*
1264    * Get the Lanman hash of the old password, we
1265    * use this as the key to SamOEMHash().
1266    */
1267   memset(upper_case_old_pw, '\0', sizeof(upper_case_old_pw));
1268   fstrcpy(upper_case_old_pw, old_password);
1269   strupper(upper_case_old_pw);
1270   E_P16((uchar *)upper_case_old_pw, old_pw_hash);
1271
1272   SamOEMhash( (unsigned char *)data, (unsigned char *)old_pw_hash, True);
1273
1274   /* 
1275    * Now place the old password hash in the data.
1276    */
1277   memset(upper_case_new_pw, '\0', sizeof(upper_case_new_pw));
1278   fstrcpy(upper_case_new_pw, new_password);
1279   strupper(upper_case_new_pw);
1280
1281   E_P16((uchar *)upper_case_new_pw, new_pw_hash);
1282
1283   E_old_pw_hash( new_pw_hash, old_pw_hash, &data[516]);
1284
1285   data_len = 532;
1286     
1287   if(cli_send_trans(cli,SMBtrans,PIPE_LANMAN,0,0,
1288                  data,param,NULL,
1289                  data_len , param_len,0,
1290                  0,2,0) == False) {
1291     DEBUG(0,("cli_oem_change_password: Failed to send password change for user %s\n",
1292               user ));
1293     return False;
1294   }
1295
1296   if(cli_receive_trans(cli,SMBtrans, &rdrcnt, &rprcnt, &rdata, &rparam)) {
1297     if(rparam)
1298       cli->error = SVAL(rparam,0);
1299   }
1300
1301   if (rparam)
1302     free(rparam);
1303   if (rdata)
1304     free(rdata);
1305
1306   return (cli->error == 0);
1307 }
1308
1309 /****************************************************************************
1310 send a negprot command
1311 ****************************************************************************/
1312 BOOL cli_negprot(struct cli_state *cli)
1313 {
1314         char *p;
1315         int numprots;
1316         int plength;
1317
1318         bzero(cli->outbuf,smb_size);
1319
1320         /* setup the protocol strings */
1321         for (plength=0,numprots=0;
1322              prots[numprots].name && prots[numprots].prot<=cli->protocol;
1323              numprots++)
1324                 plength += strlen(prots[numprots].name)+2;
1325     
1326         set_message(cli->outbuf,0,plength,True);
1327
1328         p = smb_buf(cli->outbuf);
1329         for (numprots=0;
1330              prots[numprots].name && prots[numprots].prot<=cli->protocol;
1331              numprots++) {
1332                 *p++ = 2;
1333                 strcpy(p,prots[numprots].name);
1334                 p += strlen(p) + 1;
1335         }
1336
1337         CVAL(cli->outbuf,smb_com) = SMBnegprot;
1338         cli_setup_packet(cli);
1339
1340         CVAL(smb_buf(cli->outbuf),0) = 2;
1341
1342         send_smb(cli->fd,cli->outbuf);
1343         if (!client_receive_smb(cli->fd,cli->inbuf,cli->timeout))
1344                 return False;
1345
1346         show_msg(cli->inbuf);
1347
1348         if (CVAL(cli->inbuf,smb_rcls) != 0 || 
1349             ((int)SVAL(cli->inbuf,smb_vwv0) >= numprots)) {
1350                 return(False);
1351         }
1352
1353         cli->protocol = prots[SVAL(cli->inbuf,smb_vwv0)].prot;
1354
1355
1356         if (cli->protocol >= PROTOCOL_NT1) {    
1357                 /* NT protocol */
1358                 cli->sec_mode = CVAL(cli->inbuf,smb_vwv1);
1359                 cli->max_xmit = IVAL(cli->inbuf,smb_vwv3+1);
1360                 cli->sesskey = IVAL(cli->inbuf,smb_vwv7+1);
1361                 cli->serverzone = SVALS(cli->inbuf,smb_vwv15+1)*60;
1362                 /* this time arrives in real GMT */
1363                 cli->servertime = interpret_long_date(cli->inbuf+smb_vwv11+1);
1364                 memcpy(cli->cryptkey,smb_buf(cli->inbuf),8);
1365                 if (IVAL(cli->inbuf,smb_vwv9+1) & 1)
1366                         cli->readbraw_supported = 
1367                                 cli->writebraw_supported = True;      
1368         } else if (cli->protocol >= PROTOCOL_LANMAN1) {
1369                 cli->sec_mode = SVAL(cli->inbuf,smb_vwv1);
1370                 cli->max_xmit = SVAL(cli->inbuf,smb_vwv2);
1371                 cli->sesskey = IVAL(cli->inbuf,smb_vwv6);
1372                 cli->serverzone = SVALS(cli->inbuf,smb_vwv10)*60;
1373                 /* this time is converted to GMT by make_unix_date */
1374                 cli->servertime = make_unix_date(cli->inbuf+smb_vwv8);
1375                 cli->readbraw_supported = ((SVAL(cli->inbuf,smb_vwv5) & 0x1) != 0);
1376                 cli->writebraw_supported = ((SVAL(cli->inbuf,smb_vwv5) & 0x2) != 0);
1377                 memcpy(cli->cryptkey,smb_buf(cli->inbuf),8);
1378         } else {
1379                 /* the old core protocol */
1380                 cli->sec_mode = 0;
1381                 cli->serverzone = TimeDiff(time(NULL));
1382         }
1383
1384         return True;
1385 }
1386
1387
1388 /****************************************************************************
1389   send a session request
1390 ****************************************************************************/
1391 BOOL cli_session_request(struct cli_state *cli, char *host, int name_type,
1392                          char *myname)
1393 {
1394         fstring dest;
1395         char *p;
1396         int len = 4;
1397         /* send a session request (RFC 1002) */
1398
1399         fstrcpy(dest,host);
1400   
1401         p = strchr(dest,'.');
1402         if (p) *p = 0;
1403
1404         fstrcpy(cli->desthost, dest);
1405
1406         /* put in the destination name */
1407         p = cli->outbuf+len;
1408         name_mangle(dest,p,name_type);
1409         len += name_len(p);
1410
1411         /* and my name */
1412         p = cli->outbuf+len;
1413         name_mangle(myname,p,0);
1414         len += name_len(p);
1415
1416         /* setup the packet length */
1417         _smb_setlen(cli->outbuf,len);
1418         CVAL(cli->outbuf,0) = 0x81;
1419
1420         send_smb(cli->fd,cli->outbuf);
1421         DEBUG(5,("Sent session request\n"));
1422
1423         if (!client_receive_smb(cli->fd,cli->inbuf,cli->timeout))
1424                 return False;
1425
1426         if (CVAL(cli->inbuf,0) != 0x82) {
1427                 cli->error = CVAL(cli->inbuf,0);
1428                 return False;
1429         }
1430         return(True);
1431 }
1432
1433
1434 /****************************************************************************
1435 open the client sockets
1436 ****************************************************************************/
1437 BOOL cli_connect(struct cli_state *cli, char *host, struct in_addr *ip)
1438 {
1439         struct in_addr dest_ip;
1440
1441         fstrcpy(cli->desthost, host);
1442         
1443         if (!ip) {
1444                 if(!resolve_name( cli->desthost, &dest_ip)) {
1445                         return False;
1446                 }
1447         } else {
1448                 dest_ip = *ip;
1449         }
1450
1451
1452         cli->fd = open_socket_out(SOCK_STREAM, &dest_ip, 139, cli->timeout);
1453         if (cli->fd == -1)
1454                 return False;
1455
1456         return True;
1457 }
1458
1459
1460 /****************************************************************************
1461 initialise a client structure
1462 ****************************************************************************/
1463 BOOL cli_initialise(struct cli_state *cli)
1464 {
1465         if (cli->initialised) cli_shutdown(cli);
1466
1467         memset(cli, 0, sizeof(*cli));
1468         cli->fd = -1;
1469         cli->cnum = -1;
1470         cli->pid = getpid();
1471         cli->mid = 1;
1472         cli->uid = getuid();
1473         cli->protocol = PROTOCOL_NT1;
1474         cli->timeout = 20000;
1475         cli->bufsize = 0x10000;
1476         cli->max_xmit = cli->bufsize - 4;
1477         cli->outbuf = (char *)malloc(cli->bufsize);
1478         cli->inbuf = (char *)malloc(cli->bufsize);
1479         if (!cli->outbuf || !cli->inbuf) return False;
1480         cli->initialised = 1;
1481         return True;
1482 }
1483
1484 /****************************************************************************
1485 shutdown a client structure
1486 ****************************************************************************/
1487 void cli_shutdown(struct cli_state *cli)
1488 {
1489         if (cli->outbuf) free(cli->outbuf);
1490         if (cli->inbuf) free(cli->inbuf);
1491         if (cli->fd != -1) close(cli->fd);
1492         memset(cli, 0, sizeof(*cli));
1493 }
1494
1495 /****************************************************************************
1496   return a description of the error
1497 ****************************************************************************/
1498 char *cli_errstr(struct cli_state *cli)
1499 {
1500         return smb_errstr(cli->inbuf);
1501 }
1502
1503 /****************************************************************************
1504   return error codes for the last packet
1505 ****************************************************************************/
1506 void cli_error(struct cli_state *cli, int *eclass, int *num)
1507 {
1508         *eclass = CVAL(cli->inbuf,smb_rcls);
1509         *num = SVAL(cli->inbuf,smb_err);
1510 }
1511
1512 /****************************************************************************
1513 set socket options on a open connection
1514 ****************************************************************************/
1515 void cli_sockopt(struct cli_state *cli, char *options)
1516 {
1517         set_socket_options(cli->fd, options);
1518 }
1519
1520 /****************************************************************************
1521 set the PID to use for smb messages. Return the old pid.
1522 ****************************************************************************/
1523 int cli_setpid(struct cli_state *cli, int pid)
1524 {
1525         int ret = cli->pid;
1526         cli->pid = pid;
1527         return ret;
1528 }