~vcs-imports/samba/main

« back to all changes in this revision

Viewing changes to source/libsmb/clirap.c

  • Committer: jerry
  • Date: 2006-07-14 21:48:39 UTC
  • Revision ID: vcs-imports@canonical.com-20060714214839-586d8c489a8fcead
gutting trunk to move to svn:externals

Show diffs side-by-side

added added

removed removed

Lines of Context:
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
 
/****************************************************************************
26
 
Call a remote api on an arbitrary pipe.  takes param, data and setup buffers.
27
 
****************************************************************************/
28
 
BOOL 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
 
BOOL cli_api(struct cli_state *cli,
51
 
             char *param, int prcnt, int mprcnt,
52
 
             char *data, int drcnt, int mdrcnt,
53
 
             char **rparam, unsigned int *rprcnt,
54
 
             char **rdata, unsigned int *rdrcnt)
55
 
{
56
 
  cli_send_trans(cli,SMBtrans,
57
 
                 PIPE_LANMAN,             /* Name */
58
 
                 0,0,                     /* fid, flags */
59
 
                 NULL,0,0,                /* Setup, length, max */
60
 
                 param, prcnt, mprcnt,    /* Params, length, max */
61
 
                 data, drcnt, mdrcnt      /* Data, length, max */ 
62
 
                );
63
 
 
64
 
  return (cli_receive_trans(cli,SMBtrans,
65
 
                            rparam, rprcnt,
66
 
                            rdata, rdrcnt));
67
 
}
68
 
 
69
 
 
70
 
/****************************************************************************
71
 
perform a NetWkstaUserLogon
72
 
****************************************************************************/
73
 
BOOL cli_NetWkstaUserLogon(struct cli_state *cli,char *user, char *workstation)
74
 
{
75
 
        char *rparam = NULL;
76
 
        char *rdata = NULL;
77
 
        char *p;
78
 
        unsigned int rdrcnt,rprcnt;
79
 
        pstring param;
80
 
 
81
 
        memset(param, 0, sizeof(param));
82
 
        
83
 
        /* send a SMBtrans command with api NetWkstaUserLogon */
84
 
        p = param;
85
 
        SSVAL(p,0,132); /* api number */
86
 
        p += 2;
87
 
        pstrcpy_base(p,"OOWb54WrLh",param);
88
 
        p = skip_string(p,1);
89
 
        pstrcpy_base(p,"WB21BWDWWDDDDDDDzzzD",param);
90
 
        p = skip_string(p,1);
91
 
        SSVAL(p,0,1);
92
 
        p += 2;
93
 
        pstrcpy_base(p,user,param);
94
 
        strupper_m(p);
95
 
        p += 21;
96
 
        p++;
97
 
        p += 15;
98
 
        p++; 
99
 
        pstrcpy_base(p, workstation, param);
100
 
        strupper_m(p);
101
 
        p += 16;
102
 
        SSVAL(p, 0, CLI_BUFFER_SIZE);
103
 
        p += 2;
104
 
        SSVAL(p, 0, CLI_BUFFER_SIZE);
105
 
        p += 2;
106
 
        
107
 
        if (cli_api(cli, 
108
 
                    param, PTR_DIFF(p,param),1024,  /* param, length, max */
109
 
                    NULL, 0, CLI_BUFFER_SIZE,           /* data, length, max */
110
 
                    &rparam, &rprcnt,               /* return params, return size */
111
 
                    &rdata, &rdrcnt                 /* return data, return size */
112
 
                   )) {
113
 
                cli->rap_error = rparam? SVAL(rparam,0) : -1;
114
 
                p = rdata;
115
 
                
116
 
                if (cli->rap_error == 0) {
117
 
                        DEBUG(4,("NetWkstaUserLogon success\n"));
118
 
                        cli->privileges = SVAL(p, 24);
119
 
                        /* The cli->eff_name field used to be set here
120
 
                           but it wasn't used anywhere else. */
121
 
                } else {
122
 
                        DEBUG(1,("NetwkstaUserLogon gave error %d\n", cli->rap_error));
123
 
                }
124
 
        }
125
 
        
126
 
        SAFE_FREE(rparam);
127
 
        SAFE_FREE(rdata);
128
 
        return (cli->rap_error == 0);
129
 
}
130
 
 
131
 
/****************************************************************************
132
 
call a NetShareEnum - try and browse available connections on a host
133
 
****************************************************************************/
134
 
int cli_RNetShareEnum(struct cli_state *cli, void (*fn)(const char *, uint32, const char *, void *), void *state)
135
 
{
136
 
        char *rparam = NULL;
137
 
        char *rdata = NULL;
138
 
        char *p;
139
 
        unsigned int rdrcnt,rprcnt;
140
 
        pstring param;
141
 
        int count = -1;
142
 
 
143
 
        /* now send a SMBtrans command with api RNetShareEnum */
144
 
        p = param;
145
 
        SSVAL(p,0,0); /* api number */
146
 
        p += 2;
147
 
        pstrcpy_base(p,"WrLeh",param);
148
 
        p = skip_string(p,1);
149
 
        pstrcpy_base(p,"B13BWz",param);
150
 
        p = skip_string(p,1);
151
 
        SSVAL(p,0,1);
152
 
        /*
153
 
         * Win2k needs a *smaller* buffer than 0xFFFF here -
154
 
         * it returns "out of server memory" with 0xFFFF !!! JRA.
155
 
         */
156
 
        SSVAL(p,2,0xFFE0);
157
 
        p += 4;
158
 
        
159
 
        if (cli_api(cli, 
160
 
                    param, PTR_DIFF(p,param), 1024,  /* Param, length, maxlen */
161
 
                    NULL, 0, 0xFFE0,            /* data, length, maxlen - Win2k needs a small buffer here too ! */
162
 
                    &rparam, &rprcnt,                /* return params, length */
163
 
                    &rdata, &rdrcnt))                /* return data, length */
164
 
                {
165
 
                        int res = rparam? SVAL(rparam,0) : -1;
166
 
                        
167
 
                        if (res == 0 || res == ERRmoredata) {
168
 
                                int converter=SVAL(rparam,2);
169
 
                                int i;
170
 
                                
171
 
                                count=SVAL(rparam,4);
172
 
                                p = rdata;
173
 
                                
174
 
                                for (i=0;i<count;i++,p+=20) {
175
 
                                        char *sname = p;
176
 
                                        int type = SVAL(p,14);
177
 
                                        int comment_offset = IVAL(p,16) & 0xFFFF;
178
 
                                        const char *cmnt = comment_offset?(rdata+comment_offset-converter):"";
179
 
                                        pstring s1, s2;
180
 
 
181
 
                                        pull_ascii_pstring(s1, sname);
182
 
                                        pull_ascii_pstring(s2, cmnt);
183
 
 
184
 
                                        fn(s1, type, s2, state);
185
 
                                }
186
 
                        } else {
187
 
                                DEBUG(4,("NetShareEnum res=%d\n", res));
188
 
                        }      
189
 
                } else {
190
 
                        DEBUG(4,("NetShareEnum failed\n"));
191
 
                }
192
 
  
193
 
        SAFE_FREE(rparam);
194
 
        SAFE_FREE(rdata);
195
 
        
196
 
        return count;
197
 
}
198
 
 
199
 
 
200
 
/****************************************************************************
201
 
call a NetServerEnum for the specified workgroup and servertype mask.  This
202
 
function then calls the specified callback function for each name returned.
203
 
 
204
 
The callback function takes 4 arguments: the machine name, the server type,
205
 
the comment and a state pointer.
206
 
****************************************************************************/
207
 
BOOL cli_NetServerEnum(struct cli_state *cli, char *workgroup, uint32 stype,
208
 
                       void (*fn)(const char *, uint32, const char *, void *),
209
 
                       void *state)
210
 
{
211
 
        char *rparam = NULL;
212
 
        char *rdata = NULL;
213
 
        unsigned int rdrcnt,rprcnt;
214
 
        char *p;
215
 
        pstring param;
216
 
        int uLevel = 1;
217
 
        int count = -1;
218
 
 
219
 
        errno = 0; /* reset */
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
 
        if (count < 0) {
275
 
            errno = cli_errno(cli);
276
 
        } else {
277
 
            if (!count) {
278
 
                /* this is a very special case, when the domain master for the 
279
 
                   work group isn't part of the work group itself, there is something
280
 
                   wild going on */
281
 
                errno = ENOENT;
282
 
            }
283
 
        }
284
 
                        
285
 
        return(count > 0);
286
 
}
287
 
 
288
 
 
289
 
 
290
 
/****************************************************************************
291
 
Send a SamOEMChangePassword command
292
 
****************************************************************************/
293
 
BOOL cli_oem_change_password(struct cli_state *cli, const char *user, const char *new_password,
294
 
                             const char *old_password)
295
 
{
296
 
  pstring param;
297
 
  unsigned char data[532];
298
 
  char *p = param;
299
 
  unsigned char old_pw_hash[16];
300
 
  unsigned char new_pw_hash[16];
301
 
  unsigned int data_len;
302
 
  unsigned int param_len = 0;
303
 
  char *rparam = NULL;
304
 
  char *rdata = NULL;
305
 
  unsigned int rprcnt, rdrcnt;
306
 
 
307
 
  if (strlen(user) >= sizeof(fstring)-1) {
308
 
    DEBUG(0,("cli_oem_change_password: user name %s is too long.\n", user));
309
 
    return False;
310
 
  }
311
 
 
312
 
  SSVAL(p,0,214); /* SamOEMChangePassword command. */
313
 
  p += 2;
314
 
  pstrcpy_base(p, "zsT", param);
315
 
  p = skip_string(p,1);
316
 
  pstrcpy_base(p, "B516B16", param);
317
 
  p = skip_string(p,1);
318
 
  pstrcpy_base(p,user, param);
319
 
  p = skip_string(p,1);
320
 
  SSVAL(p,0,532);
321
 
  p += 2;
322
 
 
323
 
  param_len = PTR_DIFF(p,param);
324
 
 
325
 
  /*
326
 
   * Get the Lanman hash of the old password, we
327
 
   * use this as the key to make_oem_passwd_hash().
328
 
   */
329
 
  E_deshash(old_password, old_pw_hash);
330
 
 
331
 
  encode_pw_buffer(data, new_password, STR_ASCII);
332
 
  
333
 
#ifdef DEBUG_PASSWORD
334
 
  DEBUG(100,("make_oem_passwd_hash\n"));
335
 
  dump_data(100, (char *)data, 516);
336
 
#endif
337
 
  SamOEMhash( (unsigned char *)data, (unsigned char *)old_pw_hash, 516);
338
 
 
339
 
  /* 
340
 
   * Now place the old password hash in the data.
341
 
   */
342
 
  E_deshash(new_password, new_pw_hash);
343
 
 
344
 
  E_old_pw_hash( new_pw_hash, old_pw_hash, (uchar *)&data[516]);
345
 
 
346
 
  data_len = 532;
347
 
    
348
 
  if (cli_send_trans(cli,SMBtrans,
349
 
                    PIPE_LANMAN,                          /* name */
350
 
                    0,0,                                  /* fid, flags */
351
 
                    NULL,0,0,                             /* setup, length, max */
352
 
                    param,param_len,2,                    /* param, length, max */
353
 
                    (char *)data,data_len,0                       /* data, length, max */
354
 
                   ) == False) {
355
 
    DEBUG(0,("cli_oem_change_password: Failed to send password change for user %s\n",
356
 
              user ));
357
 
    return False;
358
 
  }
359
 
 
360
 
  if (!cli_receive_trans(cli,SMBtrans,
361
 
                       &rparam, &rprcnt,
362
 
                       &rdata, &rdrcnt)) {
363
 
          DEBUG(0,("cli_oem_change_password: Failed to recieve reply to password change for user %s\n",
364
 
                   user ));
365
 
          return False;
366
 
  }
367
 
  
368
 
  if (rparam)
369
 
          cli->rap_error = SVAL(rparam,0);
370
 
  
371
 
  SAFE_FREE(rparam);
372
 
  SAFE_FREE(rdata);
373
 
 
374
 
  return (cli->rap_error == 0);
375
 
}
376
 
 
377
 
 
378
 
/****************************************************************************
379
 
send a qpathinfo call
380
 
****************************************************************************/
381
 
BOOL cli_qpathinfo(struct cli_state *cli, const char *fname, 
382
 
                   time_t *c_time, time_t *a_time, time_t *m_time, 
383
 
                   SMB_OFF_T *size, uint16 *mode)
384
 
{
385
 
        unsigned int data_len = 0;
386
 
        unsigned int param_len = 0;
387
 
        unsigned int rparam_len, rdata_len;
388
 
        uint16 setup = TRANSACT2_QPATHINFO;
389
 
        pstring param;
390
 
        char *rparam=NULL, *rdata=NULL;
391
 
        int count=8;
392
 
        BOOL ret;
393
 
        time_t (*date_fn)(struct cli_state *, void *);
394
 
        char *p;
395
 
 
396
 
        p = param;
397
 
        memset(p, 0, 6);
398
 
        SSVAL(p, 0, SMB_INFO_STANDARD);
399
 
        p += 6;
400
 
        p += clistr_push(cli, p, fname, sizeof(pstring)-6, STR_TERMINATE);
401
 
 
402
 
        param_len = PTR_DIFF(p, param);
403
 
 
404
 
        do {
405
 
                ret = (cli_send_trans(cli, SMBtrans2, 
406
 
                                      NULL,           /* Name */
407
 
                                      -1, 0,          /* fid, flags */
408
 
                                      &setup, 1, 0,   /* setup, length, max */
409
 
                                      param, param_len, 10, /* param, length, max */
410
 
                                      NULL, data_len, cli->max_xmit /* data, length, max */
411
 
                                      ) &&
412
 
                       cli_receive_trans(cli, SMBtrans2, 
413
 
                                         &rparam, &rparam_len,
414
 
                                         &rdata, &rdata_len));
415
 
                if (!cli_is_dos_error(cli)) break;
416
 
                if (!ret) {
417
 
                        /* we need to work around a Win95 bug - sometimes
418
 
                           it gives ERRSRV/ERRerror temprarily */
419
 
                        uint8 eclass;
420
 
                        uint32 ecode;
421
 
                        cli_dos_error(cli, &eclass, &ecode);
422
 
                        if (eclass != ERRSRV || ecode != ERRerror) break;
423
 
                        smb_msleep(100);
424
 
                }
425
 
        } while (count-- && ret==False);
426
 
 
427
 
        if (!ret || !rdata || rdata_len < 22) {
428
 
                return False;
429
 
        }
430
 
 
431
 
        if (cli->win95) {
432
 
                date_fn = cli_make_unix_date;
433
 
        } else {
434
 
                date_fn = cli_make_unix_date2;
435
 
        }
436
 
 
437
 
        if (c_time) {
438
 
                *c_time = date_fn(cli, rdata+0);
439
 
        }
440
 
        if (a_time) {
441
 
                *a_time = date_fn(cli, rdata+4);
442
 
        }
443
 
        if (m_time) {
444
 
                *m_time = date_fn(cli, rdata+8);
445
 
        }
446
 
        if (size) {
447
 
                *size = IVAL(rdata, 12);
448
 
        }
449
 
        if (mode) {
450
 
                *mode = SVAL(rdata,l1_attrFile);
451
 
        }
452
 
 
453
 
        SAFE_FREE(rdata);
454
 
        SAFE_FREE(rparam);
455
 
        return True;
456
 
}
457
 
 
458
 
 
459
 
/****************************************************************************
460
 
send a setpathinfo call
461
 
****************************************************************************/
462
 
BOOL cli_setpathinfo(struct cli_state *cli, const char *fname, 
463
 
                     time_t c_time, time_t a_time, time_t m_time, uint16 mode)
464
 
{
465
 
        unsigned int data_len = 0;
466
 
        unsigned int param_len = 0;
467
 
        unsigned int rparam_len, rdata_len;
468
 
        uint16 setup = TRANSACT2_SETPATHINFO;
469
 
        pstring param;
470
 
        pstring data;
471
 
        char *rparam=NULL, *rdata=NULL;
472
 
        int count=8;
473
 
        BOOL ret;
474
 
        char *p;
475
 
 
476
 
        memset(param, 0, sizeof(param));
477
 
        memset(data, 0, sizeof(data));
478
 
 
479
 
        p = param;
480
 
 
481
 
        /* Add the information level */
482
 
        SSVAL(p, 0, SMB_FILE_BASIC_INFORMATION);
483
 
 
484
 
        /* Skip reserved */
485
 
        p += 6;
486
 
 
487
 
        /* Add the file name */
488
 
        p += clistr_push(cli, p, fname, sizeof(pstring)-6, STR_TERMINATE);
489
 
 
490
 
        param_len = PTR_DIFF(p, param);
491
 
 
492
 
        p = data;
493
 
 
494
 
        /*
495
 
         * Add the create, last access, modification, and status change times
496
 
         */
497
 
        
498
 
        /* Don't set create time, at offset 0 */
499
 
        p += 8;
500
 
 
501
 
        put_long_date(p, a_time);
502
 
        p += 8;
503
 
        
504
 
        put_long_date(p, m_time);
505
 
        p += 8;
506
 
        
507
 
        put_long_date(p, c_time);
508
 
        p += 8;
509
 
 
510
 
        /* Add attributes */
511
 
        SIVAL(p, 0, mode);
512
 
        p += 4;
513
 
 
514
 
        /* Add padding */
515
 
        SIVAL(p, 0, 0);
516
 
        p += 4;
517
 
 
518
 
        data_len = PTR_DIFF(p, data);
519
 
 
520
 
        do {
521
 
                ret = (cli_send_trans(cli, SMBtrans2, 
522
 
                                      NULL,           /* Name */
523
 
                                      -1, 0,          /* fid, flags */
524
 
                                      &setup, 1, 0,   /* setup, length, max */
525
 
                                      param, param_len, 10, /* param, length, max */
526
 
                                      data, data_len, cli->max_xmit /* data, length, max */
527
 
                                      ) &&
528
 
                       cli_receive_trans(cli, SMBtrans2, 
529
 
                                         &rparam, &rparam_len,
530
 
                                         &rdata, &rdata_len));
531
 
                if (!cli_is_dos_error(cli)) break;
532
 
                if (!ret) {
533
 
                        /* we need to work around a Win95 bug - sometimes
534
 
                           it gives ERRSRV/ERRerror temprarily */
535
 
                        uint8 eclass;
536
 
                        uint32 ecode;
537
 
                        cli_dos_error(cli, &eclass, &ecode);
538
 
                        if (eclass != ERRSRV || ecode != ERRerror) break;
539
 
                        smb_msleep(100);
540
 
                }
541
 
        } while (count-- && ret==False);
542
 
 
543
 
        if (!ret) {
544
 
                return False;
545
 
        }
546
 
 
547
 
        SAFE_FREE(rdata);
548
 
        SAFE_FREE(rparam);
549
 
        return True;
550
 
}
551
 
 
552
 
 
553
 
/****************************************************************************
554
 
send a qpathinfo call with the SMB_QUERY_FILE_ALL_INFO info level
555
 
****************************************************************************/
556
 
BOOL cli_qpathinfo2(struct cli_state *cli, const char *fname, 
557
 
                    time_t *c_time, time_t *a_time, time_t *m_time, 
558
 
                    time_t *w_time, SMB_OFF_T *size, uint16 *mode,
559
 
                    SMB_INO_T *ino)
560
 
{
561
 
        unsigned int data_len = 0;
562
 
        unsigned int param_len = 0;
563
 
        uint16 setup = TRANSACT2_QPATHINFO;
564
 
        pstring param;
565
 
        char *rparam=NULL, *rdata=NULL;
566
 
        char *p;
567
 
 
568
 
        p = param;
569
 
        memset(p, 0, 6);
570
 
        SSVAL(p, 0, SMB_QUERY_FILE_ALL_INFO);
571
 
        p += 6;
572
 
        p += clistr_push(cli, p, fname, sizeof(pstring)-6, STR_TERMINATE);
573
 
 
574
 
        param_len = PTR_DIFF(p, param);
575
 
 
576
 
        if (!cli_send_trans(cli, SMBtrans2, 
577
 
                            NULL,                         /* name */
578
 
                            -1, 0,                        /* fid, flags */
579
 
                            &setup, 1, 0,                 /* setup, length, max */
580
 
                            param, param_len, 10,         /* param, length, max */
581
 
                            NULL, data_len, cli->max_xmit /* data, length, max */
582
 
                           )) {
583
 
                return False;
584
 
        }
585
 
 
586
 
        if (!cli_receive_trans(cli, SMBtrans2,
587
 
                               &rparam, &param_len,
588
 
                               &rdata, &data_len)) {
589
 
                return False;
590
 
        }
591
 
 
592
 
        if (!rdata || data_len < 22) {
593
 
                return False;
594
 
        }
595
 
        
596
 
        if (c_time) {
597
 
                *c_time = interpret_long_date(rdata+0);
598
 
        }
599
 
        if (a_time) {
600
 
                *a_time = interpret_long_date(rdata+8);
601
 
        }
602
 
        if (w_time) {
603
 
                *w_time = interpret_long_date(rdata+16);
604
 
        }
605
 
        if (m_time) {
606
 
                *m_time = interpret_long_date(rdata+24);
607
 
        }
608
 
        if (mode) {
609
 
                *mode = SVAL(rdata, 32);
610
 
        }
611
 
        if (size) {
612
 
                *size = IVAL2_TO_SMB_BIG_UINT(rdata,48);
613
 
        }
614
 
        if (ino) {
615
 
                *ino = IVAL(rdata, 64);
616
 
        }
617
 
 
618
 
        SAFE_FREE(rdata);
619
 
        SAFE_FREE(rparam);
620
 
        return True;
621
 
}
622
 
 
623
 
 
624
 
/****************************************************************************
625
 
send a qfileinfo QUERY_FILE_NAME_INFO call
626
 
****************************************************************************/
627
 
BOOL cli_qfilename(struct cli_state *cli, int fnum, 
628
 
                   pstring name)
629
 
{
630
 
        unsigned int data_len = 0;
631
 
        unsigned int param_len = 0;
632
 
        uint16 setup = TRANSACT2_QFILEINFO;
633
 
        pstring param;
634
 
        char *rparam=NULL, *rdata=NULL;
635
 
 
636
 
        param_len = 4;
637
 
        memset(param, 0, param_len);
638
 
        SSVAL(param, 0, fnum);
639
 
        SSVAL(param, 2, SMB_QUERY_FILE_NAME_INFO);
640
 
 
641
 
        if (!cli_send_trans(cli, SMBtrans2, 
642
 
                            NULL,                         /* name */
643
 
                            -1, 0,                        /* fid, flags */
644
 
                            &setup, 1, 0,                 /* setup, length, max */
645
 
                            param, param_len, 2,          /* param, length, max */
646
 
                            NULL, data_len, cli->max_xmit /* data, length, max */
647
 
                           )) {
648
 
                return False;
649
 
        }
650
 
 
651
 
        if (!cli_receive_trans(cli, SMBtrans2,
652
 
                               &rparam, &param_len,
653
 
                               &rdata, &data_len)) {
654
 
                return False;
655
 
        }
656
 
 
657
 
        if (!rdata || data_len < 4) {
658
 
                return False;
659
 
        }
660
 
 
661
 
        clistr_pull(cli, name, rdata+4, sizeof(pstring), IVAL(rdata, 0), STR_UNICODE);
662
 
 
663
 
        return True;
664
 
}
665
 
 
666
 
 
667
 
/****************************************************************************
668
 
send a qfileinfo call
669
 
****************************************************************************/
670
 
BOOL cli_qfileinfo(struct cli_state *cli, int fnum, 
671
 
                   uint16 *mode, SMB_OFF_T *size,
672
 
                   time_t *c_time, time_t *a_time, time_t *m_time, 
673
 
                   time_t *w_time, SMB_INO_T *ino)
674
 
{
675
 
        unsigned int data_len = 0;
676
 
        unsigned int param_len = 0;
677
 
        uint16 setup = TRANSACT2_QFILEINFO;
678
 
        pstring param;
679
 
        char *rparam=NULL, *rdata=NULL;
680
 
 
681
 
        /* if its a win95 server then fail this - win95 totally screws it
682
 
           up */
683
 
        if (cli->win95) return False;
684
 
 
685
 
        param_len = 4;
686
 
 
687
 
        memset(param, 0, param_len);
688
 
        SSVAL(param, 0, fnum);
689
 
        SSVAL(param, 2, SMB_QUERY_FILE_ALL_INFO);
690
 
 
691
 
        if (!cli_send_trans(cli, SMBtrans2, 
692
 
                            NULL,                         /* name */
693
 
                            -1, 0,                        /* fid, flags */
694
 
                            &setup, 1, 0,                 /* setup, length, max */
695
 
                            param, param_len, 2,          /* param, length, max */
696
 
                            NULL, data_len, cli->max_xmit /* data, length, max */
697
 
                           )) {
698
 
                return False;
699
 
        }
700
 
 
701
 
        if (!cli_receive_trans(cli, SMBtrans2,
702
 
                               &rparam, &param_len,
703
 
                               &rdata, &data_len)) {
704
 
                return False;
705
 
        }
706
 
 
707
 
        if (!rdata || data_len < 68) {
708
 
                return False;
709
 
        }
710
 
 
711
 
        if (c_time) {
712
 
                *c_time = interpret_long_date(rdata+0) - cli->serverzone;
713
 
        }
714
 
        if (a_time) {
715
 
                *a_time = interpret_long_date(rdata+8) - cli->serverzone;
716
 
        }
717
 
        if (m_time) {
718
 
                *m_time = interpret_long_date(rdata+16) - cli->serverzone;
719
 
        }
720
 
        if (w_time) {
721
 
                *w_time = interpret_long_date(rdata+24) - cli->serverzone;
722
 
        }
723
 
        if (mode) {
724
 
                *mode = SVAL(rdata, 32);
725
 
        }
726
 
        if (size) {
727
 
                *size = IVAL2_TO_SMB_BIG_UINT(rdata,48);
728
 
        }
729
 
        if (ino) {
730
 
                *ino = IVAL(rdata, 64);
731
 
        }
732
 
 
733
 
        SAFE_FREE(rdata);
734
 
        SAFE_FREE(rparam);
735
 
        return True;
736
 
}
737
 
 
738
 
 
739
 
/****************************************************************************
740
 
send a qpathinfo BASIC_INFO call
741
 
****************************************************************************/
742
 
BOOL cli_qpathinfo_basic( struct cli_state *cli, const char *name, 
743
 
                          SMB_STRUCT_STAT *sbuf, uint32 *attributes )
744
 
{
745
 
        unsigned int param_len = 0;
746
 
        unsigned int data_len = 0;
747
 
        uint16 setup = TRANSACT2_QPATHINFO;
748
 
        char param[sizeof(pstring)+6];
749
 
        char *rparam=NULL, *rdata=NULL;
750
 
        char *p;
751
 
        pstring path;
752
 
        int len;
753
 
        
754
 
        /* send full paths to dfs root shares */
755
 
        
756
 
        if ( cli->dfsroot )
757
 
                pstr_sprintf(path, "\\%s\\%s\\%s", cli->desthost, cli->share, name );
758
 
        else
759
 
                pstrcpy( path, name );
760
 
        
761
 
        /* cleanup */
762
 
        
763
 
        len = strlen( path );
764
 
        if ( path[len] == '\\' )
765
 
                path[len] = '\0';
766
 
 
767
 
        p = param;
768
 
        memset(p, 0, 6);
769
 
        SSVAL(p, 0, SMB_QUERY_FILE_BASIC_INFO);
770
 
        p += 6;
771
 
        p += clistr_push(cli, p, path, sizeof(pstring)-6, STR_TERMINATE);
772
 
        param_len = PTR_DIFF(p, param);
773
 
 
774
 
        if (!cli_send_trans(cli, SMBtrans2,
775
 
                NULL,                        /* name */
776
 
                -1, 0,                       /* fid, flags */
777
 
                &setup, 1, 0,                /* setup, length, max */
778
 
                param, param_len, 2,         /* param, length, max */
779
 
                NULL,  0, cli->max_xmit      /* data, length, max */
780
 
                )) {
781
 
                        return False;
782
 
        }
783
 
 
784
 
        if (!cli_receive_trans(cli, SMBtrans2,
785
 
                &rparam, &param_len,
786
 
                &rdata, &data_len)) {
787
 
                        return False;
788
 
        }
789
 
 
790
 
        if (data_len < 36) {
791
 
                SAFE_FREE(rdata);
792
 
                SAFE_FREE(rparam);
793
 
                return False;
794
 
        }
795
 
 
796
 
        sbuf->st_atime = interpret_long_date( rdata+8 );
797
 
        sbuf->st_mtime = interpret_long_date( rdata+16 );
798
 
        sbuf->st_ctime = interpret_long_date( rdata+24 );
799
 
        
800
 
        *attributes = IVAL( rdata, 32 );
801
 
        
802
 
        SAFE_FREE(rparam);
803
 
        SAFE_FREE(rdata);
804
 
        
805
 
        return True;
806
 
}
807
 
 
808
 
/****************************************************************************
809
 
send a qfileinfo call
810
 
****************************************************************************/
811
 
 
812
 
BOOL cli_qfileinfo_test(struct cli_state *cli, int fnum, int level, char **poutdata, uint32 *poutlen)
813
 
{
814
 
        unsigned int data_len = 0;
815
 
        unsigned int param_len = 0;
816
 
        uint16 setup = TRANSACT2_QFILEINFO;
817
 
        pstring param;
818
 
        char *rparam=NULL, *rdata=NULL;
819
 
 
820
 
        *poutdata = NULL;
821
 
        *poutlen = 0;
822
 
 
823
 
        /* if its a win95 server then fail this - win95 totally screws it
824
 
           up */
825
 
        if (cli->win95)
826
 
                return False;
827
 
 
828
 
        param_len = 4;
829
 
 
830
 
        memset(param, 0, param_len);
831
 
        SSVAL(param, 0, fnum);
832
 
        SSVAL(param, 2, level);
833
 
 
834
 
        if (!cli_send_trans(cli, SMBtrans2, 
835
 
                            NULL,                           /* name */
836
 
                            -1, 0,                          /* fid, flags */
837
 
                            &setup, 1, 0,                   /* setup, length, max */
838
 
                            param, param_len, 2,            /* param, length, max */
839
 
                            NULL, data_len, cli->max_xmit   /* data, length, max */
840
 
                           )) {
841
 
                return False;
842
 
        }
843
 
 
844
 
        if (!cli_receive_trans(cli, SMBtrans2,
845
 
                               &rparam, &param_len,
846
 
                               &rdata, &data_len)) {
847
 
                return False;
848
 
        }
849
 
 
850
 
        *poutdata = memdup(rdata, data_len);
851
 
        if (!*poutdata) {
852
 
                SAFE_FREE(rdata);
853
 
                SAFE_FREE(rparam);
854
 
                return False;
855
 
        }
856
 
 
857
 
        *poutlen = data_len;
858
 
 
859
 
        SAFE_FREE(rdata);
860
 
        SAFE_FREE(rparam);
861
 
        return True;
862
 
}
863
 
 
864
 
 
865
 
 
866
 
/****************************************************************************
867
 
send a qpathinfo SMB_QUERY_FILE_ALT_NAME_INFO call
868
 
****************************************************************************/
869
 
NTSTATUS cli_qpathinfo_alt_name(struct cli_state *cli, const char *fname, fstring alt_name)
870
 
{
871
 
        unsigned int data_len = 0;
872
 
        unsigned int param_len = 0;
873
 
        uint16 setup = TRANSACT2_QPATHINFO;
874
 
        pstring param;
875
 
        char *rparam=NULL, *rdata=NULL;
876
 
        int count=8;
877
 
        char *p;
878
 
        BOOL ret;
879
 
        unsigned int len;
880
 
 
881
 
        p = param;
882
 
        memset(p, 0, 6);
883
 
        SSVAL(p, 0, SMB_QUERY_FILE_ALT_NAME_INFO);
884
 
        p += 6;
885
 
        p += clistr_push(cli, p, fname, sizeof(pstring)-6, STR_TERMINATE);
886
 
 
887
 
        param_len = PTR_DIFF(p, param);
888
 
 
889
 
        do {
890
 
                ret = (cli_send_trans(cli, SMBtrans2, 
891
 
                                      NULL,           /* Name */
892
 
                                      -1, 0,          /* fid, flags */
893
 
                                      &setup, 1, 0,   /* setup, length, max */
894
 
                                      param, param_len, 10, /* param, length, max */
895
 
                                      NULL, data_len, cli->max_xmit /* data, length, max */
896
 
                                      ) &&
897
 
                       cli_receive_trans(cli, SMBtrans2, 
898
 
                                         &rparam, &param_len,
899
 
                                         &rdata, &data_len));
900
 
                if (!ret && cli_is_dos_error(cli)) {
901
 
                        /* we need to work around a Win95 bug - sometimes
902
 
                           it gives ERRSRV/ERRerror temprarily */
903
 
                        uint8 eclass;
904
 
                        uint32 ecode;
905
 
                        cli_dos_error(cli, &eclass, &ecode);
906
 
                        if (eclass != ERRSRV || ecode != ERRerror) break;
907
 
                        smb_msleep(100);
908
 
                }
909
 
        } while (count-- && ret==False);
910
 
 
911
 
        if (!ret || !rdata || data_len < 4) {
912
 
                return NT_STATUS_UNSUCCESSFUL;
913
 
        }
914
 
 
915
 
        len = IVAL(rdata, 0);
916
 
 
917
 
        if (len > data_len - 4) {
918
 
                return NT_STATUS_INVALID_NETWORK_RESPONSE;
919
 
        }
920
 
 
921
 
        clistr_pull(cli, alt_name, rdata+4, sizeof(fstring), len, STR_UNICODE);
922
 
 
923
 
        SAFE_FREE(rdata);
924
 
        SAFE_FREE(rparam);
925
 
 
926
 
        return NT_STATUS_OK;
927
 
}