source: trunk/samba/source/libsmb/clirap.c @ 26

Last change on this file since 26 was 26, checked in by Paul Smedley, 14 years ago

Updated source to 3.0.25rc1

File size: 26.9 KB
Line 
1/*
2   Unix SMB/CIFS implementation.
3   client RAP calls
4   Copyright (C) Andrew Tridgell         1994-1998
5   Copyright (C) Gerald (Jerry) Carter   2004
6   
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#include "includes.h"
23
24/****************************************************************************
25 Call a remote api on an arbitrary pipe.  takes param, data and setup buffers.
26****************************************************************************/
27
28BOOL cli_api_pipe(struct cli_state *cli, const char *pipe_name, 
29                  uint16 *setup, uint32 setup_count, uint32 max_setup_count,
30                  char *params, uint32 param_count, uint32 max_param_count,
31                  char *data, uint32 data_count, uint32 max_data_count,
32                  char **rparam, uint32 *rparam_count,
33                  char **rdata, uint32 *rdata_count)
34{
35        cli_send_trans(cli, SMBtrans, 
36                 pipe_name, 
37                 0,0,                         /* fid, flags */
38                 setup, setup_count, max_setup_count,
39                 params, param_count, max_param_count,
40                 data, data_count, max_data_count);
41
42        return (cli_receive_trans(cli, SMBtrans, 
43                            rparam, (unsigned int *)rparam_count,
44                            rdata, (unsigned int *)rdata_count));
45}
46
47/****************************************************************************
48 Call a remote api
49****************************************************************************/
50
51BOOL 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 Perform a NetWkstaUserLogon.
72****************************************************************************/
73
74BOOL 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(param,sizeof(param),p);
90        pstrcpy_base(p,"WB21BWDWWDDDDDDDzzzD",param);
91        p = skip_string(param,sizeof(param),p);
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
136int cli_RNetShareEnum(struct cli_state *cli, void (*fn)(const char *, uint32, const char *, void *), void *state)
137{
138        char *rparam = NULL;
139        char *rdata = NULL;
140        char *p;
141        unsigned int rdrcnt,rprcnt;
142        pstring param;
143        int count = -1;
144
145        /* now send a SMBtrans command with api RNetShareEnum */
146        p = param;
147        SSVAL(p,0,0); /* api number */
148        p += 2;
149        pstrcpy_base(p,"WrLeh",param);
150        p = skip_string(param,sizeof(param),p);
151        pstrcpy_base(p,"B13BWz",param);
152        p = skip_string(param,sizeof(param),p);
153        SSVAL(p,0,1);
154        /*
155         * Win2k needs a *smaller* buffer than 0xFFFF here -
156         * it returns "out of server memory" with 0xFFFF !!! JRA.
157         */
158        SSVAL(p,2,0xFFE0);
159        p += 4;
160       
161        if (cli_api(cli, 
162                    param, PTR_DIFF(p,param), 1024,  /* Param, length, maxlen */
163                    NULL, 0, 0xFFE0,            /* data, length, maxlen - Win2k needs a small buffer here too ! */
164                    &rparam, &rprcnt,                /* return params, length */
165                    &rdata, &rdrcnt))                /* return data, length */
166                {
167                        int res = rparam? SVAL(rparam,0) : -1;
168                       
169                        if (res == 0 || res == ERRmoredata) {
170                                int converter=SVAL(rparam,2);
171                                int i;
172                               
173                                count=SVAL(rparam,4);
174                                p = rdata;
175                               
176                                for (i=0;i<count;i++,p+=20) {
177                                        char *sname = p;
178                                        int type = SVAL(p,14);
179                                        int comment_offset = IVAL(p,16) & 0xFFFF;
180                                        const char *cmnt = comment_offset?(rdata+comment_offset-converter):"";
181                                        pstring s1, s2;
182
183                                        pull_ascii_pstring(s1, sname);
184                                        pull_ascii_pstring(s2, cmnt);
185
186                                        fn(s1, type, s2, state);
187                                }
188                        } else {
189                                DEBUG(4,("NetShareEnum res=%d\n", res));
190                        }     
191                } else {
192                        DEBUG(4,("NetShareEnum failed\n"));
193                }
194 
195        SAFE_FREE(rparam);
196        SAFE_FREE(rdata);
197       
198        return count;
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
209BOOL cli_NetServerEnum(struct cli_state *cli, char *workgroup, uint32 stype,
210                       void (*fn)(const char *, uint32, const char *, void *),
211                       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        errno = 0; /* reset */
222
223        /* send a SMBtrans command with api NetServerEnum */
224        p = param;
225        SSVAL(p,0,0x68); /* api number */
226        p += 2;
227        pstrcpy_base(p,"WrLehDz", param);
228        p = skip_string(param,sizeof(param),p);
229 
230        pstrcpy_base(p,"B16BBDz", param);
231
232        p = skip_string(param,sizeof(param),p);
233        SSVAL(p,0,uLevel);
234        SSVAL(p,2,CLI_BUFFER_SIZE);
235        p += 4;
236        SIVAL(p,0,stype);
237        p += 4;
238
239        p += push_ascii(p, workgroup, sizeof(pstring)-PTR_DIFF(p,param)-1, STR_TERMINATE|STR_UPPER);
240       
241        if (cli_api(cli, 
242                    param, PTR_DIFF(p,param), 8,        /* params, length, max */
243                    NULL, 0, CLI_BUFFER_SIZE,               /* data, length, max */
244                    &rparam, &rprcnt,                   /* return params, return size */
245                    &rdata, &rdrcnt                     /* return data, return size */
246                   )) {
247                int res = rparam? SVAL(rparam,0) : -1;
248                       
249                if (res == 0 || res == ERRmoredata ||
250                    (res != -1 && cli_errno(cli) == 0)) {
251                        int i;
252                        int converter=SVAL(rparam,2);
253
254                        count=SVAL(rparam,4);
255                        p = rdata;
256                                       
257                        for (i = 0;i < count;i++, p += 26) {
258                                char *sname = p;
259                                int comment_offset = (IVAL(p,22) & 0xFFFF)-converter;
260                                const char *cmnt = comment_offset?(rdata+comment_offset):"";
261                                pstring s1, s2;
262
263                                if (comment_offset < 0 || comment_offset > (int)rdrcnt) continue;
264
265                                stype = IVAL(p,18) & ~SV_TYPE_LOCAL_LIST_ONLY;
266
267                                pull_ascii_pstring(s1, sname);
268                                pull_ascii_pstring(s2, cmnt);
269                                fn(s1, stype, s2, state);
270                        }
271                }
272        }
273 
274        SAFE_FREE(rparam);
275        SAFE_FREE(rdata);
276
277        if (count < 0) {
278            errno = cli_errno(cli);
279        } else {
280            if (!count) {
281                /* this is a very special case, when the domain master for the
282                   work group isn't part of the work group itself, there is something
283                   wild going on */
284                errno = ENOENT;
285            }
286        }
287                       
288        return(count > 0);
289}
290
291/****************************************************************************
292 Send a SamOEMChangePassword command.
293****************************************************************************/
294
295BOOL cli_oem_change_password(struct cli_state *cli, const char *user, const char *new_password,
296                             const char *old_password)
297{
298        pstring param;
299        unsigned char data[532];
300        char *p = param;
301        unsigned char old_pw_hash[16];
302        unsigned char new_pw_hash[16];
303        unsigned int data_len;
304        unsigned int param_len = 0;
305        char *rparam = NULL;
306        char *rdata = NULL;
307        unsigned int rprcnt, rdrcnt;
308
309        if (strlen(user) >= sizeof(fstring)-1) {
310                DEBUG(0,("cli_oem_change_password: user name %s is too long.\n", user));
311                return False;
312        }
313
314        SSVAL(p,0,214); /* SamOEMChangePassword command. */
315        p += 2;
316        pstrcpy_base(p, "zsT", param);
317        p = skip_string(param,sizeof(param),p);
318        pstrcpy_base(p, "B516B16", param);
319        p = skip_string(param,sizeof(param),p);
320        pstrcpy_base(p,user, param);
321        p = skip_string(param,sizeof(param),p);
322        SSVAL(p,0,532);
323        p += 2;
324
325        param_len = PTR_DIFF(p,param);
326
327        /*
328         * Get the Lanman hash of the old password, we
329         * use this as the key to make_oem_passwd_hash().
330         */
331        E_deshash(old_password, old_pw_hash);
332
333        encode_pw_buffer(data, new_password, STR_ASCII);
334 
335#ifdef DEBUG_PASSWORD
336        DEBUG(100,("make_oem_passwd_hash\n"));
337        dump_data(100, (char *)data, 516);
338#endif
339        SamOEMhash( (unsigned char *)data, (unsigned char *)old_pw_hash, 516);
340
341        /*
342         * Now place the old password hash in the data.
343         */
344        E_deshash(new_password, new_pw_hash);
345
346        E_old_pw_hash( new_pw_hash, old_pw_hash, (uchar *)&data[516]);
347
348        data_len = 532;
349   
350        if (cli_send_trans(cli,SMBtrans,
351                    PIPE_LANMAN,                          /* name */
352                    0,0,                                  /* fid, flags */
353                    NULL,0,0,                             /* setup, length, max */
354                    param,param_len,2,                    /* param, length, max */
355                    (char *)data,data_len,0                       /* data, length, max */
356                   ) == False) {
357                DEBUG(0,("cli_oem_change_password: Failed to send password change for user %s\n",
358                        user ));
359                return False;
360        }
361
362        if (!cli_receive_trans(cli,SMBtrans,
363                       &rparam, &rprcnt,
364                       &rdata, &rdrcnt)) {
365                DEBUG(0,("cli_oem_change_password: Failed to recieve reply to password change for user %s\n",
366                        user ));
367                return False;
368        }
369 
370        if (rparam) {
371                cli->rap_error = SVAL(rparam,0);
372        }
373 
374        SAFE_FREE(rparam);
375        SAFE_FREE(rdata);
376
377        return (cli->rap_error == 0);
378}
379
380/****************************************************************************
381 Send a qpathinfo call.
382****************************************************************************/
383
384BOOL cli_qpathinfo(struct cli_state *cli, const char *fname, 
385                   time_t *change_time,
386                   time_t *access_time,
387                   time_t *write_time, 
388                   SMB_OFF_T *size, uint16 *mode)
389{
390        unsigned int data_len = 0;
391        unsigned int param_len = 0;
392        unsigned int rparam_len, rdata_len;
393        uint16 setup = TRANSACT2_QPATHINFO;
394        pstring param;
395        char *rparam=NULL, *rdata=NULL;
396        int count=8;
397        BOOL ret;
398        time_t (*date_fn)(struct cli_state *, void *);
399        char *p;
400
401        p = param;
402        memset(p, 0, 6);
403        SSVAL(p, 0, SMB_INFO_STANDARD);
404        p += 6;
405        p += clistr_push(cli, p, fname, sizeof(pstring)-6, STR_TERMINATE);
406
407        param_len = PTR_DIFF(p, param);
408
409        do {
410                ret = (cli_send_trans(cli, SMBtrans2, 
411                                      NULL,           /* Name */
412                                      -1, 0,          /* fid, flags */
413                                      &setup, 1, 0,   /* setup, length, max */
414                                      param, param_len, 10, /* param, length, max */
415                                      NULL, data_len, cli->max_xmit /* data, length, max */
416                                      ) &&
417                       cli_receive_trans(cli, SMBtrans2, 
418                                         &rparam, &rparam_len,
419                                         &rdata, &rdata_len));
420                if (!cli_is_dos_error(cli)) break;
421                if (!ret) {
422                        /* we need to work around a Win95 bug - sometimes
423                           it gives ERRSRV/ERRerror temprarily */
424                        uint8 eclass;
425                        uint32 ecode;
426                        cli_dos_error(cli, &eclass, &ecode);
427                        if (eclass != ERRSRV || ecode != ERRerror) break;
428                        smb_msleep(100);
429                }
430        } while (count-- && ret==False);
431
432        if (!ret || !rdata || rdata_len < 22) {
433                return False;
434        }
435
436        if (cli->win95) {
437                date_fn = cli_make_unix_date;
438        } else {
439                date_fn = cli_make_unix_date2;
440        }
441
442        if (change_time) {
443                *change_time = date_fn(cli, rdata+0);
444        }
445        if (access_time) {
446                *access_time = date_fn(cli, rdata+4);
447        }
448        if (write_time) {
449                *write_time = date_fn(cli, rdata+8);
450        }
451        if (size) {
452                *size = IVAL(rdata, 12);
453        }
454        if (mode) {
455                *mode = SVAL(rdata,l1_attrFile);
456        }
457
458        SAFE_FREE(rdata);
459        SAFE_FREE(rparam);
460        return True;
461}
462
463/****************************************************************************
464 Send a setpathinfo call.
465****************************************************************************/
466
467BOOL cli_setpathinfo(struct cli_state *cli, const char *fname, 
468                     time_t create_time,
469                     time_t access_time,
470                     time_t write_time,
471                     time_t change_time,
472                     uint16 mode)
473{
474        unsigned int data_len = 0;
475        unsigned int param_len = 0;
476        unsigned int rparam_len, rdata_len;
477        uint16 setup = TRANSACT2_SETPATHINFO;
478        pstring param;
479        pstring data;
480        char *rparam=NULL, *rdata=NULL;
481        int count=8;
482        BOOL ret;
483        char *p;
484
485        memset(param, 0, sizeof(param));
486        memset(data, 0, sizeof(data));
487
488        p = param;
489
490        /* Add the information level */
491        SSVAL(p, 0, SMB_FILE_BASIC_INFORMATION);
492
493        /* Skip reserved */
494        p += 6;
495
496        /* Add the file name */
497        p += clistr_push(cli, p, fname, sizeof(pstring)-6, STR_TERMINATE);
498
499        param_len = PTR_DIFF(p, param);
500
501        p = data;
502
503        /*
504         * Add the create, last access, modification, and status change times
505         */
506       
507        put_long_date(p, create_time);
508        p += 8;
509
510        put_long_date(p, access_time);
511        p += 8;
512       
513        put_long_date(p, write_time);
514        p += 8;
515       
516        put_long_date(p, change_time);
517        p += 8;
518
519        /* Add attributes */
520        SIVAL(p, 0, mode);
521        p += 4;
522
523        /* Add padding */
524        SIVAL(p, 0, 0);
525        p += 4;
526
527        data_len = PTR_DIFF(p, data);
528
529        do {
530                ret = (cli_send_trans(cli, SMBtrans2, 
531                                      NULL,           /* Name */
532                                      -1, 0,          /* fid, flags */
533                                      &setup, 1, 0,   /* setup, length, max */
534                                      param, param_len, 10, /* param, length, max */
535                                      data, data_len, cli->max_xmit /* data, length, max */
536                                      ) &&
537                       cli_receive_trans(cli, SMBtrans2, 
538                                         &rparam, &rparam_len,
539                                         &rdata, &rdata_len));
540                if (!cli_is_dos_error(cli)) break;
541                if (!ret) {
542                        /* we need to work around a Win95 bug - sometimes
543                           it gives ERRSRV/ERRerror temprarily */
544                        uint8 eclass;
545                        uint32 ecode;
546                        cli_dos_error(cli, &eclass, &ecode);
547                        if (eclass != ERRSRV || ecode != ERRerror) break;
548                        smb_msleep(100);
549                }
550        } while (count-- && ret==False);
551
552        if (!ret) {
553                return False;
554        }
555
556        SAFE_FREE(rdata);
557        SAFE_FREE(rparam);
558        return True;
559}
560
561/****************************************************************************
562 Send a qpathinfo call with the SMB_QUERY_FILE_ALL_INFO info level.
563****************************************************************************/
564
565BOOL cli_qpathinfo2(struct cli_state *cli, const char *fname, 
566                    struct timespec *create_time,
567                    struct timespec *access_time,
568                    struct timespec *write_time, 
569                    struct timespec *change_time,
570                    SMB_OFF_T *size, uint16 *mode,
571                    SMB_INO_T *ino)
572{
573        unsigned int data_len = 0;
574        unsigned int param_len = 0;
575        uint16 setup = TRANSACT2_QPATHINFO;
576        pstring param;
577        char *rparam=NULL, *rdata=NULL;
578        char *p;
579
580        p = param;
581        memset(p, 0, 6);
582        SSVAL(p, 0, SMB_QUERY_FILE_ALL_INFO);
583        p += 6;
584        p += clistr_push(cli, p, fname, sizeof(pstring)-6, STR_TERMINATE);
585
586        param_len = PTR_DIFF(p, param);
587
588        if (!cli_send_trans(cli, SMBtrans2, 
589                            NULL,                         /* name */
590                            -1, 0,                        /* fid, flags */
591                            &setup, 1, 0,                 /* setup, length, max */
592                            param, param_len, 10,         /* param, length, max */
593                            NULL, data_len, cli->max_xmit /* data, length, max */
594                           )) {
595                return False;
596        }
597
598        if (!cli_receive_trans(cli, SMBtrans2,
599                               &rparam, &param_len,
600                               &rdata, &data_len)) {
601                return False;
602        }
603
604        if (!rdata || data_len < 22) {
605                return False;
606        }
607       
608        if (create_time) {
609                *create_time = interpret_long_date(rdata+0);
610        }
611        if (access_time) {
612                *access_time = interpret_long_date(rdata+8);
613        }
614        if (write_time) {
615                *write_time = interpret_long_date(rdata+16);
616        }
617        if (change_time) {
618                *change_time = interpret_long_date(rdata+24);
619        }
620        if (mode) {
621                *mode = SVAL(rdata, 32);
622        }
623        if (size) {
624                *size = IVAL2_TO_SMB_BIG_UINT(rdata,48);
625        }
626        if (ino) {
627                *ino = IVAL(rdata, 64);
628        }
629
630        SAFE_FREE(rdata);
631        SAFE_FREE(rparam);
632        return True;
633}
634
635/****************************************************************************
636 Send a qfileinfo QUERY_FILE_NAME_INFO call.
637****************************************************************************/
638
639BOOL cli_qfilename(struct cli_state *cli, int fnum, 
640                   pstring name)
641{
642        unsigned int data_len = 0;
643        unsigned int param_len = 0;
644        uint16 setup = TRANSACT2_QFILEINFO;
645        pstring param;
646        char *rparam=NULL, *rdata=NULL;
647
648        param_len = 4;
649        memset(param, 0, param_len);
650        SSVAL(param, 0, fnum);
651        SSVAL(param, 2, SMB_QUERY_FILE_NAME_INFO);
652
653        if (!cli_send_trans(cli, SMBtrans2, 
654                            NULL,                         /* name */
655                            -1, 0,                        /* fid, flags */
656                            &setup, 1, 0,                 /* setup, length, max */
657                            param, param_len, 2,          /* param, length, max */
658                            NULL, data_len, cli->max_xmit /* data, length, max */
659                           )) {
660                return False;
661        }
662
663        if (!cli_receive_trans(cli, SMBtrans2,
664                               &rparam, &param_len,
665                               &rdata, &data_len)) {
666                return False;
667        }
668
669        if (!rdata || data_len < 4) {
670                return False;
671        }
672
673        clistr_pull(cli, name, rdata+4, sizeof(pstring), IVAL(rdata, 0), STR_UNICODE);
674
675        return True;
676}
677
678/****************************************************************************
679 Send a qfileinfo call.
680****************************************************************************/
681
682BOOL cli_qfileinfo(struct cli_state *cli, int fnum, 
683                   uint16 *mode, SMB_OFF_T *size,
684                   struct timespec *create_time,
685                   struct timespec *access_time,
686                   struct timespec *write_time, 
687                   struct timespec *change_time,
688                   SMB_INO_T *ino)
689{
690        unsigned int data_len = 0;
691        unsigned int param_len = 0;
692        uint16 setup = TRANSACT2_QFILEINFO;
693        pstring param;
694        char *rparam=NULL, *rdata=NULL;
695
696        /* if its a win95 server then fail this - win95 totally screws it
697           up */
698        if (cli->win95) return False;
699
700        param_len = 4;
701
702        memset(param, 0, param_len);
703        SSVAL(param, 0, fnum);
704        SSVAL(param, 2, SMB_QUERY_FILE_ALL_INFO);
705
706        if (!cli_send_trans(cli, SMBtrans2, 
707                            NULL,                         /* name */
708                            -1, 0,                        /* fid, flags */
709                            &setup, 1, 0,                 /* setup, length, max */
710                            param, param_len, 2,          /* param, length, max */
711                            NULL, data_len, cli->max_xmit /* data, length, max */
712                           )) {
713                return False;
714        }
715
716        if (!cli_receive_trans(cli, SMBtrans2,
717                               &rparam, &param_len,
718                               &rdata, &data_len)) {
719                return False;
720        }
721
722        if (!rdata || data_len < 68) {
723                return False;
724        }
725
726        if (create_time) {
727                *create_time = interpret_long_date(rdata+0);
728        }
729        if (access_time) {
730                *access_time = interpret_long_date(rdata+8);
731        }
732        if (write_time) {
733                *write_time = interpret_long_date(rdata+16);
734        }
735        if (change_time) {
736                *change_time = interpret_long_date(rdata+24);
737        }
738        if (mode) {
739                *mode = SVAL(rdata, 32);
740        }
741        if (size) {
742                *size = IVAL2_TO_SMB_BIG_UINT(rdata,48);
743        }
744        if (ino) {
745                *ino = IVAL(rdata, 64);
746        }
747
748        SAFE_FREE(rdata);
749        SAFE_FREE(rparam);
750        return True;
751}
752
753/****************************************************************************
754 Send a qpathinfo BASIC_INFO call.
755****************************************************************************/
756
757BOOL cli_qpathinfo_basic( struct cli_state *cli, const char *name, 
758                          SMB_STRUCT_STAT *sbuf, uint32 *attributes )
759{
760        unsigned int param_len = 0;
761        unsigned int data_len = 0;
762        uint16 setup = TRANSACT2_QPATHINFO;
763        char param[sizeof(pstring)+6];
764        char *rparam=NULL, *rdata=NULL;
765        char *p;
766        pstring path;
767        int len;
768       
769        pstrcpy( path, name );
770        /* cleanup */
771       
772        len = strlen( path );
773        if ( path[len-1] == '\\' || path[len-1] == '/')
774                path[len-1] = '\0';
775
776        p = param;
777        memset(p, 0, 6);
778        SSVAL(p, 0, SMB_QUERY_FILE_BASIC_INFO);
779        p += 6;
780        p += clistr_push(cli, p, path, sizeof(pstring)-6, STR_TERMINATE);
781        param_len = PTR_DIFF(p, param);
782
783        if (!cli_send_trans(cli, SMBtrans2,
784                NULL,                        /* name */
785                -1, 0,                       /* fid, flags */
786                &setup, 1, 0,                /* setup, length, max */
787                param, param_len, 2,         /* param, length, max */
788                NULL,  0, cli->max_xmit      /* data, length, max */
789                )) {
790                        return False;
791        }
792
793        if (!cli_receive_trans(cli, SMBtrans2,
794                &rparam, &param_len,
795                &rdata, &data_len)) {
796                        return False;
797        }
798
799        if (data_len < 36) {
800                SAFE_FREE(rdata);
801                SAFE_FREE(rparam);
802                return False;
803        }
804
805        set_atimespec(sbuf, interpret_long_date( rdata+8 )); /* Access time. */
806        set_mtimespec(sbuf, interpret_long_date( rdata+16 )); /* Write time. */
807        set_ctimespec(sbuf, interpret_long_date( rdata+24 )); /* Change time. */
808       
809        *attributes = IVAL( rdata, 32 );
810       
811        SAFE_FREE(rparam);
812        SAFE_FREE(rdata);
813       
814        return True;
815}
816
817/****************************************************************************
818 Send a qfileinfo call.
819****************************************************************************/
820
821BOOL cli_qfileinfo_test(struct cli_state *cli, int fnum, int level, char **poutdata, uint32 *poutlen)
822{
823        unsigned int data_len = 0;
824        unsigned int param_len = 0;
825        uint16 setup = TRANSACT2_QFILEINFO;
826        pstring param;
827        char *rparam=NULL, *rdata=NULL;
828
829        *poutdata = NULL;
830        *poutlen = 0;
831
832        /* if its a win95 server then fail this - win95 totally screws it
833           up */
834        if (cli->win95)
835                return False;
836
837        param_len = 4;
838
839        memset(param, 0, param_len);
840        SSVAL(param, 0, fnum);
841        SSVAL(param, 2, level);
842
843        if (!cli_send_trans(cli, SMBtrans2, 
844                            NULL,                           /* name */
845                            -1, 0,                          /* fid, flags */
846                            &setup, 1, 0,                   /* setup, length, max */
847                            param, param_len, 2,            /* param, length, max */
848                            NULL, data_len, cli->max_xmit   /* data, length, max */
849                           )) {
850                return False;
851        }
852
853        if (!cli_receive_trans(cli, SMBtrans2,
854                               &rparam, &param_len,
855                               &rdata, &data_len)) {
856                return False;
857        }
858
859        *poutdata = (char *)memdup(rdata, data_len);
860        if (!*poutdata) {
861                SAFE_FREE(rdata);
862                SAFE_FREE(rparam);
863                return False;
864        }
865
866        *poutlen = data_len;
867
868        SAFE_FREE(rdata);
869        SAFE_FREE(rparam);
870        return True;
871}
872
873/****************************************************************************
874 Send a qpathinfo SMB_QUERY_FILE_ALT_NAME_INFO call.
875****************************************************************************/
876
877NTSTATUS cli_qpathinfo_alt_name(struct cli_state *cli, const char *fname, fstring alt_name)
878{
879        unsigned int data_len = 0;
880        unsigned int param_len = 0;
881        uint16 setup = TRANSACT2_QPATHINFO;
882        pstring param;
883        char *rparam=NULL, *rdata=NULL;
884        int count=8;
885        char *p;
886        BOOL ret;
887        unsigned int len;
888
889        p = param;
890        memset(p, 0, 6);
891        SSVAL(p, 0, SMB_QUERY_FILE_ALT_NAME_INFO);
892        p += 6;
893        p += clistr_push(cli, p, fname, sizeof(pstring)-6, STR_TERMINATE);
894
895        param_len = PTR_DIFF(p, param);
896
897        do {
898                ret = (cli_send_trans(cli, SMBtrans2, 
899                                      NULL,           /* Name */
900                                      -1, 0,          /* fid, flags */
901                                      &setup, 1, 0,   /* setup, length, max */
902                                      param, param_len, 10, /* param, length, max */
903                                      NULL, data_len, cli->max_xmit /* data, length, max */
904                                      ) &&
905                       cli_receive_trans(cli, SMBtrans2, 
906                                         &rparam, &param_len,
907                                         &rdata, &data_len));
908                if (!ret && cli_is_dos_error(cli)) {
909                        /* we need to work around a Win95 bug - sometimes
910                           it gives ERRSRV/ERRerror temprarily */
911                        uint8 eclass;
912                        uint32 ecode;
913                        cli_dos_error(cli, &eclass, &ecode);
914                        if (eclass != ERRSRV || ecode != ERRerror) break;
915                        smb_msleep(100);
916                }
917        } while (count-- && ret==False);
918
919        if (!ret || !rdata || data_len < 4) {
920                return NT_STATUS_UNSUCCESSFUL;
921        }
922
923        len = IVAL(rdata, 0);
924
925        if (len > data_len - 4) {
926                return NT_STATUS_INVALID_NETWORK_RESPONSE;
927        }
928
929        clistr_pull(cli, alt_name, rdata+4, sizeof(fstring), len, STR_UNICODE);
930
931        SAFE_FREE(rdata);
932        SAFE_FREE(rparam);
933
934        return NT_STATUS_OK;
935}
Note: See TracBrowser for help on using the repository browser.