~zulcss/samba/server-dailies-3.4

« back to all changes in this revision

Viewing changes to source3/smbd/lanman.c

  • Committer: Chuck Short
  • Date: 2010-09-28 20:38:39 UTC
  • Revision ID: zulcss@ubuntu.com-20100928203839-pgjulytsi9ue63x1
Initial version

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* 
 
2
   Unix SMB/CIFS implementation.
 
3
   Inter-process communication and named pipe handling
 
4
   Copyright (C) Andrew Tridgell 1992-1998
 
5
   Copyright (C) Jeremy Allison 2007.
 
6
 
 
7
   SMB Version handling
 
8
   Copyright (C) John H Terpstra 1995-1998
 
9
 
 
10
   This program is free software; you can redistribute it and/or modify
 
11
   it under the terms of the GNU General Public License as published by
 
12
   the Free Software Foundation; either version 3 of the License, or
 
13
   (at your option) any later version.
 
14
 
 
15
   This program is distributed in the hope that it will be useful,
 
16
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
17
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
18
   GNU General Public License for more details.
 
19
 
 
20
   You should have received a copy of the GNU General Public License
 
21
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
22
   */
 
23
/*
 
24
   This file handles the named pipe and mailslot calls
 
25
   in the SMBtrans protocol
 
26
   */
 
27
 
 
28
#include "includes.h"
 
29
#include "../lib/util/binsearch.h"
 
30
 
 
31
#ifdef CHECK_TYPES
 
32
#undef CHECK_TYPES
 
33
#endif
 
34
#define CHECK_TYPES 0
 
35
 
 
36
#define NERR_Success 0
 
37
#define NERR_badpass 86
 
38
#define NERR_notsupported 50
 
39
 
 
40
#define NERR_BASE (2100)
 
41
#define NERR_BufTooSmall (NERR_BASE+23)
 
42
#define NERR_JobNotFound (NERR_BASE+51)
 
43
#define NERR_DestNotFound (NERR_BASE+52)
 
44
 
 
45
#define ACCESS_READ 0x01
 
46
#define ACCESS_WRITE 0x02
 
47
#define ACCESS_CREATE 0x04
 
48
 
 
49
#define SHPWLEN 8               /* share password length */
 
50
 
 
51
/* Limit size of ipc replies */
 
52
 
 
53
static char *smb_realloc_limit(void *ptr, size_t size)
 
54
{
 
55
        char *val;
 
56
 
 
57
        size = MAX((size),4*1024);
 
58
        val = (char *)SMB_REALLOC(ptr,size);
 
59
        if (val) {
 
60
                memset(val,'\0',size);
 
61
        }
 
62
        return val;
 
63
}
 
64
 
 
65
static bool api_Unsupported(connection_struct *conn, uint16 vuid,
 
66
                                char *param, int tpscnt,
 
67
                                char *data, int tdscnt,
 
68
                                int mdrcnt, int mprcnt,
 
69
                                char **rdata, char **rparam,
 
70
                                int *rdata_len, int *rparam_len);
 
71
 
 
72
static bool api_TooSmall(connection_struct *conn, uint16 vuid, char *param, char *data,
 
73
                         int mdrcnt, int mprcnt,
 
74
                         char **rdata, char **rparam,
 
75
                         int *rdata_len, int *rparam_len);
 
76
 
 
77
 
 
78
static int CopyExpanded(connection_struct *conn,
 
79
                        int snum, char **dst, char *src, int *p_space_remaining)
 
80
{
 
81
        TALLOC_CTX *ctx = talloc_tos();
 
82
        char *buf = NULL;
 
83
        int l;
 
84
 
 
85
        if (!src || !dst || !p_space_remaining || !(*dst) ||
 
86
                        *p_space_remaining <= 0) {
 
87
                return 0;
 
88
        }
 
89
 
 
90
        buf = talloc_strdup(ctx, src);
 
91
        if (!buf) {
 
92
                *p_space_remaining = 0;
 
93
                return 0;
 
94
        }
 
95
        buf = talloc_string_sub(ctx, buf,"%S",lp_servicename(snum));
 
96
        if (!buf) {
 
97
                *p_space_remaining = 0;
 
98
                return 0;
 
99
        }
 
100
        buf = talloc_sub_advanced(ctx,
 
101
                                lp_servicename(SNUM(conn)),
 
102
                                conn->server_info->unix_name,
 
103
                                conn->connectpath,
 
104
                                conn->server_info->utok.gid,
 
105
                                conn->server_info->sanitized_username,
 
106
                                pdb_get_domain(conn->server_info->sam_account),
 
107
                                buf);
 
108
        if (!buf) {
 
109
                *p_space_remaining = 0;
 
110
                return 0;
 
111
        }
 
112
        l = push_ascii(*dst,buf,*p_space_remaining, STR_TERMINATE);
 
113
        if (l == -1) {
 
114
                return 0;
 
115
        }
 
116
        (*dst) += l;
 
117
        (*p_space_remaining) -= l;
 
118
        return l;
 
119
}
 
120
 
 
121
static int CopyAndAdvance(char **dst, char *src, int *n)
 
122
{
 
123
        int l;
 
124
        if (!src || !dst || !n || !(*dst)) {
 
125
                return 0;
 
126
        }
 
127
        l = push_ascii(*dst,src,*n, STR_TERMINATE);
 
128
        if (l == -1) {
 
129
                return 0;
 
130
        }
 
131
        (*dst) += l;
 
132
        (*n) -= l;
 
133
        return l;
 
134
}
 
135
 
 
136
static int StrlenExpanded(connection_struct *conn, int snum, char *s)
 
137
{
 
138
        TALLOC_CTX *ctx = talloc_tos();
 
139
        char *buf = NULL;
 
140
        if (!s) {
 
141
                return 0;
 
142
        }
 
143
        buf = talloc_strdup(ctx,s);
 
144
        if (!buf) {
 
145
                return 0;
 
146
        }
 
147
        buf = talloc_string_sub(ctx,buf,"%S",lp_servicename(snum));
 
148
        if (!buf) {
 
149
                return 0;
 
150
        }
 
151
        buf = talloc_sub_advanced(ctx,
 
152
                                lp_servicename(SNUM(conn)),
 
153
                                conn->server_info->unix_name,
 
154
                                conn->connectpath,
 
155
                                conn->server_info->utok.gid,
 
156
                                conn->server_info->sanitized_username,
 
157
                                pdb_get_domain(conn->server_info->sam_account),
 
158
                                buf);
 
159
        if (!buf) {
 
160
                return 0;
 
161
        }
 
162
        return strlen(buf) + 1;
 
163
}
 
164
 
 
165
static char *Expand(connection_struct *conn, int snum, char *s)
 
166
{
 
167
        TALLOC_CTX *ctx = talloc_tos();
 
168
        char *buf = NULL;
 
169
 
 
170
        if (!s) {
 
171
                return NULL;
 
172
        }
 
173
        buf = talloc_strdup(ctx,s);
 
174
        if (!buf) {
 
175
                return 0;
 
176
        }
 
177
        buf = talloc_string_sub(ctx,buf,"%S",lp_servicename(snum));
 
178
        if (!buf) {
 
179
                return 0;
 
180
        }
 
181
        return talloc_sub_advanced(ctx,
 
182
                                lp_servicename(SNUM(conn)),
 
183
                                conn->server_info->unix_name,
 
184
                                conn->connectpath,
 
185
                                conn->server_info->utok.gid,
 
186
                                conn->server_info->sanitized_username,
 
187
                                pdb_get_domain(conn->server_info->sam_account),
 
188
                                buf);
 
189
}
 
190
 
 
191
/*******************************************************************
 
192
 Check a API string for validity when we only need to check the prefix.
 
193
******************************************************************/
 
194
 
 
195
static bool prefix_ok(const char *str, const char *prefix)
 
196
{
 
197
        return(strncmp(str,prefix,strlen(prefix)) == 0);
 
198
}
 
199
 
 
200
struct pack_desc {
 
201
        const char *format;         /* formatstring for structure */
 
202
        const char *subformat;  /* subformat for structure */
 
203
        char *base;         /* baseaddress of buffer */
 
204
        int buflen;        /* remaining size for fixed part; on init: length of base */
 
205
        int subcount;       /* count of substructures */
 
206
        char *structbuf;  /* pointer into buffer for remaining fixed part */
 
207
        int stringlen;    /* remaining size for variable part */                
 
208
        char *stringbuf;  /* pointer into buffer for remaining variable part */
 
209
        int neededlen;    /* total needed size */
 
210
        int usedlen;        /* total used size (usedlen <= neededlen and usedlen <= buflen) */
 
211
        const char *curpos;         /* current position; pointer into format or subformat */
 
212
        int errcode;
 
213
};
 
214
 
 
215
static int get_counter(const char **p)
 
216
{
 
217
        int i, n;
 
218
        if (!p || !(*p)) {
 
219
                return 1;
 
220
        }
 
221
        if (!isdigit((int)**p)) {
 
222
                return 1;
 
223
        }
 
224
        for (n = 0;;) {
 
225
                i = **p;
 
226
                if (isdigit(i)) {
 
227
                        n = 10 * n + (i - '0');
 
228
                } else {
 
229
                        return n;
 
230
                }
 
231
                (*p)++;
 
232
        }
 
233
}
 
234
 
 
235
static int getlen(const char *p)
 
236
{
 
237
        int n = 0;
 
238
        if (!p) {
 
239
                return 0;
 
240
        }
 
241
 
 
242
        while (*p) {
 
243
                switch( *p++ ) {
 
244
                case 'W':                       /* word (2 byte) */
 
245
                        n += 2;
 
246
                        break;
 
247
                case 'K':                       /* status word? (2 byte) */
 
248
                        n += 2;
 
249
                        break;
 
250
                case 'N':                       /* count of substructures (word) at end */
 
251
                        n += 2;
 
252
                        break;
 
253
                case 'D':                       /* double word (4 byte) */
 
254
                case 'z':                       /* offset to zero terminated string (4 byte) */
 
255
                case 'l':                       /* offset to user data (4 byte) */
 
256
                        n += 4;
 
257
                        break;
 
258
                case 'b':                       /* offset to data (with counter) (4 byte) */
 
259
                        n += 4;
 
260
                        get_counter(&p);
 
261
                        break;
 
262
                case 'B':                       /* byte (with optional counter) */
 
263
                        n += get_counter(&p);
 
264
                        break;
 
265
                }
 
266
        }
 
267
        return n;
 
268
}
 
269
 
 
270
static bool init_package(struct pack_desc *p, int count, int subcount)
 
271
{
 
272
        int n = p->buflen;
 
273
        int i;
 
274
 
 
275
        if (!p->format || !p->base) {
 
276
                return False;
 
277
        }
 
278
 
 
279
        i = count * getlen(p->format);
 
280
        if (p->subformat) {
 
281
                i += subcount * getlen(p->subformat);
 
282
        }
 
283
        p->structbuf = p->base;
 
284
        p->neededlen = 0;
 
285
        p->usedlen = 0;
 
286
        p->subcount = 0;
 
287
        p->curpos = p->format;
 
288
        if (i > n) {
 
289
                p->neededlen = i;
 
290
                i = n = 0;
 
291
#if 0
 
292
                /*
 
293
                 * This is the old error code we used. Aparently
 
294
                 * WinNT/2k systems return ERRbuftoosmall (2123) and
 
295
                 * OS/2 needs this. I'm leaving this here so we can revert
 
296
                 * if needed. JRA.
 
297
                 */
 
298
                p->errcode = ERRmoredata;
 
299
#else
 
300
                p->errcode = ERRbuftoosmall;
 
301
#endif
 
302
        } else {
 
303
                p->errcode = NERR_Success;
 
304
        }
 
305
        p->buflen = i;
 
306
        n -= i;
 
307
        p->stringbuf = p->base + i;
 
308
        p->stringlen = n;
 
309
        return (p->errcode == NERR_Success);
 
310
}
 
311
 
 
312
static int package(struct pack_desc *p, ...)
 
313
{
 
314
        va_list args;
 
315
        int needed=0, stringneeded;
 
316
        const char *str=NULL;
 
317
        int is_string=0, stringused;
 
318
        int32 temp;
 
319
 
 
320
        va_start(args,p);
 
321
 
 
322
        if (!*p->curpos) {
 
323
                if (!p->subcount) {
 
324
                        p->curpos = p->format;
 
325
                } else {
 
326
                        p->curpos = p->subformat;
 
327
                        p->subcount--;
 
328
                }
 
329
        }
 
330
#if CHECK_TYPES
 
331
        str = va_arg(args,char*);
 
332
        SMB_ASSERT(strncmp(str,p->curpos,strlen(str)) == 0);
 
333
#endif
 
334
        stringneeded = -1;
 
335
 
 
336
        if (!p->curpos) {
 
337
                va_end(args);
 
338
                return 0;
 
339
        }
 
340
 
 
341
        switch( *p->curpos++ ) {
 
342
                case 'W':                       /* word (2 byte) */
 
343
                        needed = 2;
 
344
                        temp = va_arg(args,int);
 
345
                        if (p->buflen >= needed) {
 
346
                                SSVAL(p->structbuf,0,temp);
 
347
                        }
 
348
                        break;
 
349
                case 'K':                       /* status word? (2 byte) */
 
350
                        needed = 2;
 
351
                        temp = va_arg(args,int);
 
352
                        if (p->buflen >= needed) {
 
353
                                SSVAL(p->structbuf,0,temp);
 
354
                        }
 
355
                        break;
 
356
                case 'N':                       /* count of substructures (word) at end */
 
357
                        needed = 2;
 
358
                        p->subcount = va_arg(args,int);
 
359
                        if (p->buflen >= needed) {
 
360
                                SSVAL(p->structbuf,0,p->subcount);
 
361
                        }
 
362
                        break;
 
363
                case 'D':                       /* double word (4 byte) */
 
364
                        needed = 4;
 
365
                        temp = va_arg(args,int);
 
366
                        if (p->buflen >= needed) {
 
367
                                SIVAL(p->structbuf,0,temp);
 
368
                        }
 
369
                        break;
 
370
                case 'B':                       /* byte (with optional counter) */
 
371
                        needed = get_counter(&p->curpos);
 
372
                        {
 
373
                                char *s = va_arg(args,char*);
 
374
                                if (p->buflen >= needed) {
 
375
                                        StrnCpy(p->structbuf,s?s:"",needed-1);
 
376
                                }
 
377
                        }
 
378
                        break;
 
379
                case 'z':                       /* offset to zero terminated string (4 byte) */
 
380
                        str = va_arg(args,char*);
 
381
                        stringneeded = (str ? strlen(str)+1 : 0);
 
382
                        is_string = 1;
 
383
                        break;
 
384
                case 'l':                       /* offset to user data (4 byte) */
 
385
                        str = va_arg(args,char*);
 
386
                        stringneeded = va_arg(args,int);
 
387
                        is_string = 0;
 
388
                        break;
 
389
                case 'b':                       /* offset to data (with counter) (4 byte) */
 
390
                        str = va_arg(args,char*);
 
391
                        stringneeded = get_counter(&p->curpos);
 
392
                        is_string = 0;
 
393
                        break;
 
394
        }
 
395
 
 
396
        va_end(args);
 
397
        if (stringneeded >= 0) {
 
398
                needed = 4;
 
399
                if (p->buflen >= needed) {
 
400
                        stringused = stringneeded;
 
401
                        if (stringused > p->stringlen) {
 
402
                                stringused = (is_string ? p->stringlen : 0);
 
403
                                if (p->errcode == NERR_Success) {
 
404
                                        p->errcode = ERRmoredata;
 
405
                                }
 
406
                        }
 
407
                        if (!stringused) {
 
408
                                SIVAL(p->structbuf,0,0);
 
409
                        } else {
 
410
                                SIVAL(p->structbuf,0,PTR_DIFF(p->stringbuf,p->base));
 
411
                                memcpy(p->stringbuf,str?str:"",stringused);
 
412
                                if (is_string) {
 
413
                                        p->stringbuf[stringused-1] = '\0';
 
414
                                }
 
415
                                p->stringbuf += stringused;
 
416
                                p->stringlen -= stringused;
 
417
                                p->usedlen += stringused;
 
418
                        }
 
419
                }
 
420
                p->neededlen += stringneeded;
 
421
        }
 
422
 
 
423
        p->neededlen += needed;
 
424
        if (p->buflen >= needed) {
 
425
                p->structbuf += needed;
 
426
                p->buflen -= needed;
 
427
                p->usedlen += needed;
 
428
        } else {
 
429
                if (p->errcode == NERR_Success) {
 
430
                        p->errcode = ERRmoredata;
 
431
                }
 
432
        }
 
433
        return 1;
 
434
}
 
435
 
 
436
#if CHECK_TYPES
 
437
#define PACK(desc,t,v) package(desc,t,v,0,0,0,0)
 
438
#define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0)
 
439
#else
 
440
#define PACK(desc,t,v) package(desc,v)
 
441
#define PACKl(desc,t,v,l) package(desc,v,l)
 
442
#endif
 
443
 
 
444
static void PACKI(struct pack_desc* desc, const char *t,int v)
 
445
{
 
446
        PACK(desc,t,v);
 
447
}
 
448
 
 
449
static void PACKS(struct pack_desc* desc,const char *t,const char *v)
 
450
{
 
451
        PACK(desc,t,v);
 
452
}
 
453
 
 
454
/****************************************************************************
 
455
 Get a print queue.
 
456
****************************************************************************/
 
457
 
 
458
static void PackDriverData(struct pack_desc* desc)
 
459
{
 
460
        char drivdata[4+4+32];
 
461
        SIVAL(drivdata,0,sizeof drivdata); /* cb */
 
462
        SIVAL(drivdata,4,1000); /* lVersion */
 
463
        memset(drivdata+8,0,32);        /* szDeviceName */
 
464
        push_ascii(drivdata+8,"NULL",32, STR_TERMINATE);
 
465
        PACKl(desc,"l",drivdata,sizeof drivdata); /* pDriverData */
 
466
}
 
467
 
 
468
static int check_printq_info(struct pack_desc* desc,
 
469
                                unsigned int uLevel, char *id1, char *id2)
 
470
{
 
471
        desc->subformat = NULL;
 
472
        switch( uLevel ) {
 
473
                case 0:
 
474
                        desc->format = "B13";
 
475
                        break;
 
476
                case 1:
 
477
                        desc->format = "B13BWWWzzzzzWW";
 
478
                        break;
 
479
                case 2:
 
480
                        desc->format = "B13BWWWzzzzzWN";
 
481
                        desc->subformat = "WB21BB16B10zWWzDDz";
 
482
                        break;
 
483
                case 3:
 
484
                        desc->format = "zWWWWzzzzWWzzl";
 
485
                        break;
 
486
                case 4:
 
487
                        desc->format = "zWWWWzzzzWNzzl";
 
488
                        desc->subformat = "WWzWWDDzz";
 
489
                        break;
 
490
                case 5:
 
491
                        desc->format = "z";
 
492
                        break;
 
493
                case 51:
 
494
                        desc->format = "K";
 
495
                        break;
 
496
                case 52:
 
497
                        desc->format = "WzzzzzzzzN";
 
498
                        desc->subformat = "z";
 
499
                        break;
 
500
                default:
 
501
                        DEBUG(0,("check_printq_info: invalid level %d\n",
 
502
                                uLevel ));
 
503
                        return False;
 
504
        }
 
505
        if (id1 == NULL || strcmp(desc->format,id1) != 0) {
 
506
                DEBUG(0,("check_printq_info: invalid format %s\n",
 
507
                        id1 ? id1 : "<NULL>" ));
 
508
                return False;
 
509
        }
 
510
        if (desc->subformat && (id2 == NULL || strcmp(desc->subformat,id2) != 0)) {
 
511
                DEBUG(0,("check_printq_info: invalid subformat %s\n",
 
512
                        id2 ? id2 : "<NULL>" ));
 
513
                return False;
 
514
        }
 
515
        return True;
 
516
}
 
517
 
 
518
 
 
519
#define RAP_JOB_STATUS_QUEUED 0
 
520
#define RAP_JOB_STATUS_PAUSED 1
 
521
#define RAP_JOB_STATUS_SPOOLING 2
 
522
#define RAP_JOB_STATUS_PRINTING 3
 
523
#define RAP_JOB_STATUS_PRINTED 4
 
524
 
 
525
#define RAP_QUEUE_STATUS_PAUSED 1
 
526
#define RAP_QUEUE_STATUS_ERROR 2
 
527
 
 
528
/* turn a print job status into a on the wire status 
 
529
*/
 
530
static int printj_status(int v)
 
531
{
 
532
        switch (v) {
 
533
        case LPQ_QUEUED:
 
534
                return RAP_JOB_STATUS_QUEUED;
 
535
        case LPQ_PAUSED:
 
536
                return RAP_JOB_STATUS_PAUSED;
 
537
        case LPQ_SPOOLING:
 
538
                return RAP_JOB_STATUS_SPOOLING;
 
539
        case LPQ_PRINTING:
 
540
                return RAP_JOB_STATUS_PRINTING;
 
541
        }
 
542
        return 0;
 
543
}
 
544
 
 
545
/* turn a print queue status into a on the wire status 
 
546
*/
 
547
static int printq_status(int v)
 
548
{
 
549
        switch (v) {
 
550
        case LPQ_QUEUED:
 
551
                return 0;
 
552
        case LPQ_PAUSED:
 
553
                return RAP_QUEUE_STATUS_PAUSED;
 
554
        }
 
555
        return RAP_QUEUE_STATUS_ERROR;
 
556
}
 
557
 
 
558
static void fill_printjob_info(connection_struct *conn, int snum, int uLevel,
 
559
                               struct pack_desc *desc,
 
560
                               print_queue_struct *queue, int n)
 
561
{
 
562
        time_t t = queue->time;
 
563
 
 
564
        /* the client expects localtime */
 
565
        t -= get_time_zone(t);
 
566
 
 
567
        PACKI(desc,"W",pjobid_to_rap(lp_const_servicename(snum),queue->job)); /* uJobId */
 
568
        if (uLevel == 1) {
 
569
                PACKS(desc,"B21",queue->fs_user); /* szUserName */
 
570
                PACKS(desc,"B","");             /* pad */
 
571
                PACKS(desc,"B16","");   /* szNotifyName */
 
572
                PACKS(desc,"B10","PM_Q_RAW"); /* szDataType */
 
573
                PACKS(desc,"z","");             /* pszParms */
 
574
                PACKI(desc,"W",n+1);            /* uPosition */
 
575
                PACKI(desc,"W",printj_status(queue->status)); /* fsStatus */
 
576
                PACKS(desc,"z","");             /* pszStatus */
 
577
                PACKI(desc,"D",t); /* ulSubmitted */
 
578
                PACKI(desc,"D",queue->size); /* ulSize */
 
579
                PACKS(desc,"z",queue->fs_file); /* pszComment */
 
580
        }
 
581
        if (uLevel == 2 || uLevel == 3 || uLevel == 4) {
 
582
                PACKI(desc,"W",queue->priority);                /* uPriority */
 
583
                PACKS(desc,"z",queue->fs_user); /* pszUserName */
 
584
                PACKI(desc,"W",n+1);            /* uPosition */
 
585
                PACKI(desc,"W",printj_status(queue->status)); /* fsStatus */
 
586
                PACKI(desc,"D",t); /* ulSubmitted */
 
587
                PACKI(desc,"D",queue->size); /* ulSize */
 
588
                PACKS(desc,"z","Samba");        /* pszComment */
 
589
                PACKS(desc,"z",queue->fs_file); /* pszDocument */
 
590
                if (uLevel == 3) {
 
591
                        PACKS(desc,"z","");     /* pszNotifyName */
 
592
                        PACKS(desc,"z","PM_Q_RAW"); /* pszDataType */
 
593
                        PACKS(desc,"z","");     /* pszParms */
 
594
                        PACKS(desc,"z","");     /* pszStatus */
 
595
                        PACKS(desc,"z",SERVICE(snum)); /* pszQueue */
 
596
                        PACKS(desc,"z","lpd");  /* pszQProcName */
 
597
                        PACKS(desc,"z","");     /* pszQProcParms */
 
598
                        PACKS(desc,"z","NULL"); /* pszDriverName */
 
599
                        PackDriverData(desc);   /* pDriverData */
 
600
                        PACKS(desc,"z","");     /* pszPrinterName */
 
601
                } else if (uLevel == 4) {   /* OS2 */
 
602
                        PACKS(desc,"z","");       /* pszSpoolFileName  */
 
603
                        PACKS(desc,"z","");       /* pszPortName       */
 
604
                        PACKS(desc,"z","");       /* pszStatus         */
 
605
                        PACKI(desc,"D",0);        /* ulPagesSpooled    */
 
606
                        PACKI(desc,"D",0);        /* ulPagesSent       */
 
607
                        PACKI(desc,"D",0);        /* ulPagesPrinted    */
 
608
                        PACKI(desc,"D",0);        /* ulTimePrinted     */
 
609
                        PACKI(desc,"D",0);        /* ulExtendJobStatus */
 
610
                        PACKI(desc,"D",0);        /* ulStartPage       */
 
611
                        PACKI(desc,"D",0);        /* ulEndPage         */
 
612
                }
 
613
        }
 
614
}
 
615
 
 
616
/********************************************************************
 
617
 Return a driver name given an snum.
 
618
 Returns True if from tdb, False otherwise.
 
619
 ********************************************************************/
 
620
 
 
621
static bool get_driver_name(int snum, char **pp_drivername)
 
622
{
 
623
        NT_PRINTER_INFO_LEVEL *info = NULL;
 
624
        bool in_tdb = false;
 
625
 
 
626
        get_a_printer (NULL, &info, 2, lp_servicename(snum));
 
627
        if (info != NULL) {
 
628
                *pp_drivername = talloc_strdup(talloc_tos(),
 
629
                                        info->info_2->drivername);
 
630
                in_tdb = true;
 
631
                free_a_printer(&info, 2);
 
632
                if (!*pp_drivername) {
 
633
                        return false;
 
634
                }
 
635
        }
 
636
 
 
637
        return in_tdb;
 
638
}
 
639
 
 
640
/********************************************************************
 
641
 Respond to the DosPrintQInfo command with a level of 52
 
642
 This is used to get printer driver information for Win9x clients
 
643
 ********************************************************************/
 
644
static void fill_printq_info_52(connection_struct *conn, int snum, 
 
645
                                struct pack_desc* desc, int count )
 
646
{
 
647
        int                             i;
 
648
        fstring                         location;
 
649
        NT_PRINTER_DRIVER_INFO_LEVEL    driver;
 
650
        NT_PRINTER_INFO_LEVEL           *printer = NULL;
 
651
 
 
652
        ZERO_STRUCT(driver);
 
653
 
 
654
        if ( !W_ERROR_IS_OK(get_a_printer( NULL, &printer, 2, lp_servicename(snum))) ) {
 
655
                DEBUG(3,("fill_printq_info_52: Failed to lookup printer [%s]\n", 
 
656
                        lp_servicename(snum)));
 
657
                goto err;
 
658
        }
 
659
 
 
660
        if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, 
 
661
                "Windows 4.0", 0)) )
 
662
        {
 
663
                DEBUG(3,("fill_printq_info_52: Failed to lookup driver [%s]\n", 
 
664
                        printer->info_2->drivername));
 
665
                goto err;
 
666
        }
 
667
 
 
668
        trim_string(driver.info_3->driverpath, "\\print$\\WIN40\\0\\", 0);
 
669
        trim_string(driver.info_3->datafile, "\\print$\\WIN40\\0\\", 0);
 
670
        trim_string(driver.info_3->helpfile, "\\print$\\WIN40\\0\\", 0);
 
671
 
 
672
        PACKI(desc, "W", 0x0400);                     /* don't know */
 
673
        PACKS(desc, "z", driver.info_3->name);        /* long printer name */
 
674
        PACKS(desc, "z", driver.info_3->driverpath);  /* Driverfile Name */
 
675
        PACKS(desc, "z", driver.info_3->datafile);    /* Datafile name */
 
676
        PACKS(desc, "z", driver.info_3->monitorname); /* language monitor */
 
677
 
 
678
        fstrcpy(location, "\\\\%L\\print$\\WIN40\\0");
 
679
        standard_sub_basic( "", "", location, sizeof(location)-1 );
 
680
        PACKS(desc,"z", location);                          /* share to retrieve files */
 
681
 
 
682
        PACKS(desc,"z", driver.info_3->defaultdatatype);    /* default data type */
 
683
        PACKS(desc,"z", driver.info_3->helpfile);           /* helpfile name */
 
684
        PACKS(desc,"z", driver.info_3->driverpath);               /* driver name */
 
685
 
 
686
        DEBUG(3,("Printer Driver Name: %s:\n",driver.info_3->name));
 
687
        DEBUG(3,("Driver: %s:\n",driver.info_3->driverpath));
 
688
        DEBUG(3,("Data File: %s:\n",driver.info_3->datafile));
 
689
        DEBUG(3,("Language Monitor: %s:\n",driver.info_3->monitorname));
 
690
        DEBUG(3,("Driver Location: %s:\n",location));
 
691
        DEBUG(3,("Data Type: %s:\n",driver.info_3->defaultdatatype));
 
692
        DEBUG(3,("Help File: %s:\n",driver.info_3->helpfile));
 
693
        PACKI(desc,"N",count);                     /* number of files to copy */
 
694
 
 
695
        for ( i=0; i<count && driver.info_3->dependentfiles && *driver.info_3->dependentfiles[i]; i++) 
 
696
        {
 
697
                trim_string(driver.info_3->dependentfiles[i], "\\print$\\WIN40\\0\\", 0);
 
698
                PACKS(desc,"z",driver.info_3->dependentfiles[i]);         /* driver files to copy */
 
699
                DEBUG(3,("Dependent File: %s:\n",driver.info_3->dependentfiles[i]));
 
700
        }
 
701
 
 
702
        /* sanity check */
 
703
        if ( i != count )
 
704
                DEBUG(3,("fill_printq_info_52: file count specified by client [%d] != number of dependent files [%i]\n",
 
705
                        count, i));
 
706
 
 
707
        DEBUG(3,("fill_printq_info on <%s> gave %d entries\n", SERVICE(snum),i));
 
708
 
 
709
        desc->errcode=NERR_Success;
 
710
        goto done;
 
711
 
 
712
err:
 
713
        DEBUG(3,("fill_printq_info: Can't supply driver files\n"));
 
714
        desc->errcode=NERR_notsupported;
 
715
 
 
716
done:
 
717
        if ( printer )
 
718
                free_a_printer( &printer, 2 );
 
719
 
 
720
        if ( driver.info_3 )
 
721
                free_a_printer_driver( driver, 3 );
 
722
}
 
723
 
 
724
 
 
725
static void fill_printq_info(connection_struct *conn, int snum, int uLevel,
 
726
                             struct pack_desc* desc,
 
727
                             int count, print_queue_struct* queue,
 
728
                             print_status_struct* status)
 
729
{
 
730
        switch (uLevel) {
 
731
        case 1:
 
732
        case 2:
 
733
                PACKS(desc,"B13",SERVICE(snum));
 
734
                break;
 
735
        case 3:
 
736
        case 4:
 
737
        case 5:
 
738
                PACKS(desc,"z",Expand(conn,snum,SERVICE(snum)));
 
739
                break;
 
740
        case 51:
 
741
                PACKI(desc,"K",printq_status(status->status));
 
742
                break;
 
743
        }
 
744
 
 
745
        if (uLevel == 1 || uLevel == 2) {
 
746
                PACKS(desc,"B","");             /* alignment */
 
747
                PACKI(desc,"W",5);              /* priority */
 
748
                PACKI(desc,"W",0);              /* start time */
 
749
                PACKI(desc,"W",0);              /* until time */
 
750
                PACKS(desc,"z","");             /* pSepFile */
 
751
                PACKS(desc,"z","lpd");  /* pPrProc */
 
752
                PACKS(desc,"z",SERVICE(snum)); /* pDestinations */
 
753
                PACKS(desc,"z","");             /* pParms */
 
754
                if (snum < 0) {
 
755
                        PACKS(desc,"z","UNKNOWN PRINTER");
 
756
                        PACKI(desc,"W",LPSTAT_ERROR);
 
757
                }
 
758
                else if (!status || !status->message[0]) {
 
759
                        PACKS(desc,"z",Expand(conn,snum,lp_comment(snum)));
 
760
                        PACKI(desc,"W",LPSTAT_OK); /* status */
 
761
                } else {
 
762
                        PACKS(desc,"z",status->message);
 
763
                        PACKI(desc,"W",printq_status(status->status)); /* status */
 
764
                }
 
765
                PACKI(desc,(uLevel == 1 ? "W" : "N"),count);
 
766
        }
 
767
 
 
768
        if (uLevel == 3 || uLevel == 4) {
 
769
                char *drivername = NULL;
 
770
 
 
771
                PACKI(desc,"W",5);              /* uPriority */
 
772
                PACKI(desc,"W",0);              /* uStarttime */
 
773
                PACKI(desc,"W",0);              /* uUntiltime */
 
774
                PACKI(desc,"W",5);              /* pad1 */
 
775
                PACKS(desc,"z","");             /* pszSepFile */
 
776
                PACKS(desc,"z","WinPrint");     /* pszPrProc */
 
777
                PACKS(desc,"z",NULL);           /* pszParms */
 
778
                PACKS(desc,"z",NULL);           /* pszComment - don't ask.... JRA */
 
779
                /* "don't ask" that it's done this way to fix corrupted
 
780
                   Win9X/ME printer comments. */
 
781
                if (!status) {
 
782
                        PACKI(desc,"W",LPSTAT_OK); /* fsStatus */
 
783
                } else {
 
784
                        PACKI(desc,"W",printq_status(status->status)); /* fsStatus */
 
785
                }
 
786
                PACKI(desc,(uLevel == 3 ? "W" : "N"),count);    /* cJobs */
 
787
                PACKS(desc,"z",SERVICE(snum)); /* pszPrinters */
 
788
                get_driver_name(snum,&drivername);
 
789
                if (!drivername) {
 
790
                        return;
 
791
                }
 
792
                PACKS(desc,"z",drivername);             /* pszDriverName */
 
793
                PackDriverData(desc);   /* pDriverData */
 
794
        }
 
795
 
 
796
        if (uLevel == 2 || uLevel == 4) {
 
797
                int i;
 
798
                for (i=0;i<count;i++)
 
799
                        fill_printjob_info(conn,snum,uLevel == 2 ? 1 : 2,desc,&queue[i],i);
 
800
        }
 
801
 
 
802
        if (uLevel==52)
 
803
                fill_printq_info_52( conn, snum, desc, count );
 
804
}
 
805
 
 
806
/* This function returns the number of files for a given driver */
 
807
static int get_printerdrivernumber(int snum)
 
808
{
 
809
        int                             result = 0;
 
810
        NT_PRINTER_DRIVER_INFO_LEVEL    driver;
 
811
        NT_PRINTER_INFO_LEVEL           *printer = NULL;
 
812
 
 
813
        ZERO_STRUCT(driver);
 
814
 
 
815
        if ( !W_ERROR_IS_OK(get_a_printer( NULL, &printer, 2, lp_servicename(snum))) ) {
 
816
                DEBUG(3,("get_printerdrivernumber: Failed to lookup printer [%s]\n", 
 
817
                        lp_servicename(snum)));
 
818
                goto done;
 
819
        }
 
820
 
 
821
        if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, 
 
822
                "Windows 4.0", 0)) )
 
823
        {
 
824
                DEBUG(3,("get_printerdrivernumber: Failed to lookup driver [%s]\n", 
 
825
                        printer->info_2->drivername));
 
826
                goto done;
 
827
        }
 
828
 
 
829
        /* count the number of files */
 
830
        while ( driver.info_3->dependentfiles && *driver.info_3->dependentfiles[result] )
 
831
                        result++;
 
832
                        \
 
833
 done:
 
834
        if ( printer )
 
835
                free_a_printer( &printer, 2 );
 
836
 
 
837
        if ( driver.info_3 )
 
838
                free_a_printer_driver( driver, 3 );
 
839
 
 
840
        return result;
 
841
}
 
842
 
 
843
static bool api_DosPrintQGetInfo(connection_struct *conn, uint16 vuid,
 
844
                                char *param, int tpscnt,
 
845
                                char *data, int tdscnt,
 
846
                                int mdrcnt,int mprcnt,
 
847
                                char **rdata,char **rparam,
 
848
                                int *rdata_len,int *rparam_len)
 
849
{
 
850
        char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
 
851
        char *str2 = skip_string(param,tpscnt,str1);
 
852
        char *p = skip_string(param,tpscnt,str2);
 
853
        char *QueueName = p;
 
854
        unsigned int uLevel;
 
855
        int count=0;
 
856
        int snum;
 
857
        char *str3;
 
858
        struct pack_desc desc;
 
859
        print_queue_struct *queue=NULL;
 
860
        print_status_struct status;
 
861
        char* tmpdata=NULL;
 
862
 
 
863
        if (!str1 || !str2 || !p) {
 
864
                return False;
 
865
        }
 
866
        memset((char *)&status,'\0',sizeof(status));
 
867
        memset((char *)&desc,'\0',sizeof(desc));
 
868
 
 
869
        p = skip_string(param,tpscnt,p);
 
870
        if (!p) {
 
871
                return False;
 
872
        }
 
873
        uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
 
874
        str3 = get_safe_str_ptr(param,tpscnt,p,4);
 
875
        /* str3 may be null here and is checked in check_printq_info(). */
 
876
 
 
877
        /* remove any trailing username */
 
878
        if ((p = strchr_m(QueueName,'%')))
 
879
                *p = 0;
 
880
 
 
881
        DEBUG(3,("api_DosPrintQGetInfo uLevel=%d name=%s\n",uLevel,QueueName));
 
882
 
 
883
        /* check it's a supported varient */
 
884
        if (!prefix_ok(str1,"zWrLh"))
 
885
                return False;
 
886
        if (!check_printq_info(&desc,uLevel,str2,str3)) {
 
887
                /*
 
888
                 * Patch from Scott Moomaw <scott@bridgewater.edu>
 
889
                 * to return the 'invalid info level' error if an
 
890
                 * unknown level was requested.
 
891
                 */
 
892
                *rdata_len = 0;
 
893
                *rparam_len = 6;
 
894
                *rparam = smb_realloc_limit(*rparam,*rparam_len);
 
895
                if (!*rparam) {
 
896
                        return False;
 
897
                }
 
898
                SSVALS(*rparam,0,ERRunknownlevel);
 
899
                SSVAL(*rparam,2,0);
 
900
                SSVAL(*rparam,4,0);
 
901
                return(True);
 
902
        }
 
903
 
 
904
        snum = find_service(QueueName);
 
905
        if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) )
 
906
                return False;
 
907
 
 
908
        if (uLevel==52) {
 
909
                count = get_printerdrivernumber(snum);
 
910
                DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count));
 
911
        } else {
 
912
                count = print_queue_status(snum, &queue,&status);
 
913
        }
 
914
 
 
915
        if (mdrcnt > 0) {
 
916
                *rdata = smb_realloc_limit(*rdata,mdrcnt);
 
917
                if (!*rdata) {
 
918
                        SAFE_FREE(queue);
 
919
                        return False;
 
920
                }
 
921
                desc.base = *rdata;
 
922
                desc.buflen = mdrcnt;
 
923
        } else {
 
924
                /*
 
925
                 * Don't return data but need to get correct length
 
926
                 * init_package will return wrong size if buflen=0
 
927
                 */
 
928
                desc.buflen = getlen(desc.format);
 
929
                desc.base = tmpdata = (char *) SMB_MALLOC (desc.buflen);
 
930
        }
 
931
 
 
932
        if (init_package(&desc,1,count)) {
 
933
                desc.subcount = count;
 
934
                fill_printq_info(conn,snum,uLevel,&desc,count,queue,&status);
 
935
        }
 
936
 
 
937
        *rdata_len = desc.usedlen;
 
938
 
 
939
        /*
 
940
         * We must set the return code to ERRbuftoosmall
 
941
         * in order to support lanman style printing with Win NT/2k
 
942
         * clients       --jerry
 
943
         */
 
944
        if (!mdrcnt && lp_disable_spoolss())
 
945
                desc.errcode = ERRbuftoosmall;
 
946
 
 
947
        *rdata_len = desc.usedlen;
 
948
        *rparam_len = 6;
 
949
        *rparam = smb_realloc_limit(*rparam,*rparam_len);
 
950
        if (!*rparam) {
 
951
                SAFE_FREE(queue);
 
952
                SAFE_FREE(tmpdata);
 
953
                return False;
 
954
        }
 
955
        SSVALS(*rparam,0,desc.errcode);
 
956
        SSVAL(*rparam,2,0);
 
957
        SSVAL(*rparam,4,desc.neededlen);
 
958
 
 
959
        DEBUG(4,("printqgetinfo: errorcode %d\n",desc.errcode));
 
960
 
 
961
        SAFE_FREE(queue);
 
962
        SAFE_FREE(tmpdata);
 
963
 
 
964
        return(True);
 
965
}
 
966
 
 
967
/****************************************************************************
 
968
 View list of all print jobs on all queues.
 
969
****************************************************************************/
 
970
 
 
971
static bool api_DosPrintQEnum(connection_struct *conn, uint16 vuid,
 
972
                                char *param, int tpscnt,
 
973
                                char *data, int tdscnt,
 
974
                                int mdrcnt, int mprcnt,
 
975
                                char **rdata, char** rparam,
 
976
                                int *rdata_len, int *rparam_len)
 
977
{
 
978
        char *param_format = get_safe_str_ptr(param,tpscnt,param,2);
 
979
        char *output_format1 = skip_string(param,tpscnt,param_format);
 
980
        char *p = skip_string(param,tpscnt,output_format1);
 
981
        unsigned int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
 
982
        char *output_format2 = get_safe_str_ptr(param,tpscnt,p,4);
 
983
        int services = lp_numservices();
 
984
        int i, n;
 
985
        struct pack_desc desc;
 
986
        print_queue_struct **queue = NULL;
 
987
        print_status_struct *status = NULL;
 
988
        int *subcntarr = NULL;
 
989
        int queuecnt = 0, subcnt = 0, succnt = 0;
 
990
 
 
991
        if (!param_format || !output_format1 || !p) {
 
992
                return False;
 
993
        }
 
994
 
 
995
        memset((char *)&desc,'\0',sizeof(desc));
 
996
 
 
997
        DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel));
 
998
 
 
999
        if (!prefix_ok(param_format,"WrLeh")) {
 
1000
                return False;
 
1001
        }
 
1002
        if (!check_printq_info(&desc,uLevel,output_format1,output_format2)) {
 
1003
                /*
 
1004
                 * Patch from Scott Moomaw <scott@bridgewater.edu>
 
1005
                 * to return the 'invalid info level' error if an
 
1006
                 * unknown level was requested.
 
1007
                 */
 
1008
                *rdata_len = 0;
 
1009
                *rparam_len = 6;
 
1010
                *rparam = smb_realloc_limit(*rparam,*rparam_len);
 
1011
                if (!*rparam) {
 
1012
                        return False;
 
1013
                }
 
1014
                SSVALS(*rparam,0,ERRunknownlevel);
 
1015
                SSVAL(*rparam,2,0);
 
1016
                SSVAL(*rparam,4,0);
 
1017
                return(True);
 
1018
        }
 
1019
 
 
1020
        for (i = 0; i < services; i++) {
 
1021
                if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
 
1022
                        queuecnt++;
 
1023
                }
 
1024
        }
 
1025
 
 
1026
        if((queue = SMB_MALLOC_ARRAY(print_queue_struct*, queuecnt)) == NULL) {
 
1027
                DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
 
1028
                goto err;
 
1029
        }
 
1030
        memset(queue,0,queuecnt*sizeof(print_queue_struct*));
 
1031
        if((status = SMB_MALLOC_ARRAY(print_status_struct,queuecnt)) == NULL) {
 
1032
                DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
 
1033
                goto err;
 
1034
        }
 
1035
        memset(status,0,queuecnt*sizeof(print_status_struct));
 
1036
        if((subcntarr = SMB_MALLOC_ARRAY(int,queuecnt)) == NULL) {
 
1037
                DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
 
1038
                goto err;
 
1039
        }
 
1040
 
 
1041
        subcnt = 0;
 
1042
        n = 0;
 
1043
        for (i = 0; i < services; i++) {
 
1044
                if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
 
1045
                        subcntarr[n] = print_queue_status(i, &queue[n],&status[n]);
 
1046
                        subcnt += subcntarr[n];
 
1047
                        n++;
 
1048
                }
 
1049
        }
 
1050
 
 
1051
        if (mdrcnt > 0) {
 
1052
                *rdata = smb_realloc_limit(*rdata,mdrcnt);
 
1053
                if (!*rdata) {
 
1054
                        goto err;
 
1055
                }
 
1056
        }
 
1057
        desc.base = *rdata;
 
1058
        desc.buflen = mdrcnt;
 
1059
 
 
1060
        if (init_package(&desc,queuecnt,subcnt)) {
 
1061
                n = 0;
 
1062
                succnt = 0;
 
1063
                for (i = 0; i < services; i++) {
 
1064
                        if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
 
1065
                                fill_printq_info(conn,i,uLevel,&desc,subcntarr[n],queue[n],&status[n]);
 
1066
                                n++;
 
1067
                                if (desc.errcode == NERR_Success) {
 
1068
                                        succnt = n;
 
1069
                                }
 
1070
                        }
 
1071
                }
 
1072
        }
 
1073
 
 
1074
        SAFE_FREE(subcntarr);
 
1075
 
 
1076
        *rdata_len = desc.usedlen;
 
1077
        *rparam_len = 8;
 
1078
        *rparam = smb_realloc_limit(*rparam,*rparam_len);
 
1079
        if (!*rparam) {
 
1080
                goto err;
 
1081
        }
 
1082
        SSVALS(*rparam,0,desc.errcode);
 
1083
        SSVAL(*rparam,2,0);
 
1084
        SSVAL(*rparam,4,succnt);
 
1085
        SSVAL(*rparam,6,queuecnt);
 
1086
 
 
1087
        for (i = 0; i < queuecnt; i++) {
 
1088
                if (queue) {
 
1089
                        SAFE_FREE(queue[i]);
 
1090
                }
 
1091
        }
 
1092
 
 
1093
        SAFE_FREE(queue);
 
1094
        SAFE_FREE(status);
 
1095
 
 
1096
        return True;
 
1097
 
 
1098
  err:
 
1099
 
 
1100
        SAFE_FREE(subcntarr);
 
1101
        for (i = 0; i < queuecnt; i++) {
 
1102
                if (queue) {
 
1103
                        SAFE_FREE(queue[i]);
 
1104
                }
 
1105
        }
 
1106
        SAFE_FREE(queue);
 
1107
        SAFE_FREE(status);
 
1108
 
 
1109
        return False;
 
1110
}
 
1111
 
 
1112
/****************************************************************************
 
1113
 Get info level for a server list query.
 
1114
****************************************************************************/
 
1115
 
 
1116
static bool check_server_info(int uLevel, char* id)
 
1117
{
 
1118
        switch( uLevel ) {
 
1119
                case 0:
 
1120
                        if (strcmp(id,"B16") != 0) {
 
1121
                                return False;
 
1122
                        }
 
1123
                        break;
 
1124
                case 1:
 
1125
                        if (strcmp(id,"B16BBDz") != 0) {
 
1126
                                return False;
 
1127
                        }
 
1128
                        break;
 
1129
                default: 
 
1130
                        return False;
 
1131
        }
 
1132
        return True;
 
1133
}
 
1134
 
 
1135
struct srv_info_struct {
 
1136
        fstring name;
 
1137
        uint32 type;
 
1138
        fstring comment;
 
1139
        fstring domain;
 
1140
        bool server_added;
 
1141
};
 
1142
 
 
1143
/*******************************************************************
 
1144
 Get server info lists from the files saved by nmbd. Return the
 
1145
 number of entries.
 
1146
******************************************************************/
 
1147
 
 
1148
static int get_server_info(uint32 servertype, 
 
1149
                           struct srv_info_struct **servers,
 
1150
                           const char *domain)
 
1151
{
 
1152
        int count=0;
 
1153
        int alloced=0;
 
1154
        char **lines;
 
1155
        bool local_list_only;
 
1156
        int i;
 
1157
 
 
1158
        lines = file_lines_load(cache_path(SERVER_LIST), NULL, 0, NULL);
 
1159
        if (!lines) {
 
1160
                DEBUG(4,("Can't open %s - %s\n",cache_path(SERVER_LIST),strerror(errno)));
 
1161
                return 0;
 
1162
        }
 
1163
 
 
1164
        /* request for everything is code for request all servers */
 
1165
        if (servertype == SV_TYPE_ALL) {
 
1166
                servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
 
1167
        }
 
1168
 
 
1169
        local_list_only = (servertype & SV_TYPE_LOCAL_LIST_ONLY);
 
1170
 
 
1171
        DEBUG(4,("Servertype search: %8x\n",servertype));
 
1172
 
 
1173
        for (i=0;lines[i];i++) {
 
1174
                fstring stype;
 
1175
                struct srv_info_struct *s;
 
1176
                const char *ptr = lines[i];
 
1177
                bool ok = True;
 
1178
                TALLOC_CTX *frame = NULL;
 
1179
                char *p;
 
1180
 
 
1181
                if (!*ptr) {
 
1182
                        continue;
 
1183
                }
 
1184
 
 
1185
                if (count == alloced) {
 
1186
                        alloced += 10;
 
1187
                        *servers = SMB_REALLOC_ARRAY(*servers,struct srv_info_struct, alloced);
 
1188
                        if (!*servers) {
 
1189
                                DEBUG(0,("get_server_info: failed to enlarge servers info struct!\n"));
 
1190
                                TALLOC_FREE(lines);
 
1191
                                return 0;
 
1192
                        }
 
1193
                        memset((char *)((*servers)+count),'\0',sizeof(**servers)*(alloced-count));
 
1194
                }
 
1195
                s = &(*servers)[count];
 
1196
 
 
1197
                frame = talloc_stackframe();
 
1198
                s->name[0] = '\0';
 
1199
                if (!next_token_talloc(frame,&ptr,&p, NULL)) {
 
1200
                        TALLOC_FREE(frame);
 
1201
                        continue;
 
1202
                }
 
1203
                fstrcpy(s->name, p);
 
1204
 
 
1205
                stype[0] = '\0';
 
1206
                if (!next_token_talloc(frame,&ptr, &p, NULL)) {
 
1207
                        TALLOC_FREE(frame);
 
1208
                        continue;
 
1209
                }
 
1210
                fstrcpy(stype, p);
 
1211
 
 
1212
                s->comment[0] = '\0';
 
1213
                if (!next_token_talloc(frame,&ptr, &p, NULL)) {
 
1214
                        TALLOC_FREE(frame);
 
1215
                        continue;
 
1216
                }
 
1217
                fstrcpy(s->comment, p);
 
1218
                string_truncate(s->comment, MAX_SERVER_STRING_LENGTH);
 
1219
 
 
1220
                s->domain[0] = '\0';
 
1221
                if (!next_token_talloc(frame,&ptr,&p, NULL)) {
 
1222
                        /* this allows us to cope with an old nmbd */
 
1223
                        fstrcpy(s->domain,lp_workgroup());
 
1224
                } else {
 
1225
                        fstrcpy(s->domain, p);
 
1226
                }
 
1227
                TALLOC_FREE(frame);
 
1228
 
 
1229
                if (sscanf(stype,"%X",&s->type) != 1) {
 
1230
                        DEBUG(4,("r:host file "));
 
1231
                        ok = False;
 
1232
                }
 
1233
 
 
1234
                /* Filter the servers/domains we return based on what was asked for. */
 
1235
 
 
1236
                /* Check to see if we are being asked for a local list only. */
 
1237
                if(local_list_only && ((s->type & SV_TYPE_LOCAL_LIST_ONLY) == 0)) {
 
1238
                        DEBUG(4,("r: local list only"));
 
1239
                        ok = False;
 
1240
                }
 
1241
 
 
1242
                /* doesn't match up: don't want it */
 
1243
                if (!(servertype & s->type)) {
 
1244
                        DEBUG(4,("r:serv type "));
 
1245
                        ok = False;
 
1246
                }
 
1247
 
 
1248
                if ((servertype & SV_TYPE_DOMAIN_ENUM) != 
 
1249
                                (s->type & SV_TYPE_DOMAIN_ENUM)) {
 
1250
                        DEBUG(4,("s: dom mismatch "));
 
1251
                        ok = False;
 
1252
                }
 
1253
 
 
1254
                if (!strequal(domain, s->domain) && !(servertype & SV_TYPE_DOMAIN_ENUM)) {
 
1255
                        ok = False;
 
1256
                }
 
1257
 
 
1258
                /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
 
1259
                s->type &= ~SV_TYPE_LOCAL_LIST_ONLY;
 
1260
 
 
1261
                if (ok) {
 
1262
                        DEBUG(4,("**SV** %20s %8x %25s %15s\n",
 
1263
                                s->name, s->type, s->comment, s->domain));
 
1264
                        s->server_added = True;
 
1265
                        count++;
 
1266
                } else {
 
1267
                        DEBUG(4,("%20s %8x %25s %15s\n",
 
1268
                                s->name, s->type, s->comment, s->domain));
 
1269
                }
 
1270
        }
 
1271
 
 
1272
        TALLOC_FREE(lines);
 
1273
        return count;
 
1274
}
 
1275
 
 
1276
/*******************************************************************
 
1277
 Fill in a server info structure.
 
1278
******************************************************************/
 
1279
 
 
1280
static int fill_srv_info(struct srv_info_struct *service, 
 
1281
                         int uLevel, char **buf, int *buflen, 
 
1282
                         char **stringbuf, int *stringspace, char *baseaddr)
 
1283
{
 
1284
        int struct_len;
 
1285
        char* p;
 
1286
        char* p2;
 
1287
        int l2;
 
1288
        int len;
 
1289
 
 
1290
        switch (uLevel) {
 
1291
                case 0:
 
1292
                        struct_len = 16;
 
1293
                        break;
 
1294
                case 1:
 
1295
                        struct_len = 26;
 
1296
                        break;
 
1297
                default:
 
1298
                        return -1;
 
1299
        }
 
1300
 
 
1301
        if (!buf) {
 
1302
                len = 0;
 
1303
                switch (uLevel) {
 
1304
                        case 1:
 
1305
                                len = strlen(service->comment)+1;
 
1306
                                break;
 
1307
                }
 
1308
 
 
1309
                *buflen = struct_len;
 
1310
                *stringspace = len;
 
1311
                return struct_len + len;
 
1312
        }
 
1313
 
 
1314
        len = struct_len;
 
1315
        p = *buf;
 
1316
        if (*buflen < struct_len) {
 
1317
                return -1;
 
1318
        }
 
1319
        if (stringbuf) {
 
1320
                p2 = *stringbuf;
 
1321
                l2 = *stringspace;
 
1322
        } else {
 
1323
                p2 = p + struct_len;
 
1324
                l2 = *buflen - struct_len;
 
1325
        }
 
1326
        if (!baseaddr) {
 
1327
                baseaddr = p;
 
1328
        }
 
1329
 
 
1330
        switch (uLevel) {
 
1331
                case 0:
 
1332
                        push_ascii(p,service->name, MAX_NETBIOSNAME_LEN, STR_TERMINATE);
 
1333
                        break;
 
1334
 
 
1335
                case 1:
 
1336
                        push_ascii(p,service->name,MAX_NETBIOSNAME_LEN, STR_TERMINATE);
 
1337
                        SIVAL(p,18,service->type);
 
1338
                        SIVAL(p,22,PTR_DIFF(p2,baseaddr));
 
1339
                        len += CopyAndAdvance(&p2,service->comment,&l2);
 
1340
                        break;
 
1341
        }
 
1342
 
 
1343
        if (stringbuf) {
 
1344
                *buf = p + struct_len;
 
1345
                *buflen -= struct_len;
 
1346
                *stringbuf = p2;
 
1347
                *stringspace = l2;
 
1348
        } else {
 
1349
                *buf = p2;
 
1350
                *buflen -= len;
 
1351
        }
 
1352
        return len;
 
1353
}
 
1354
 
 
1355
 
 
1356
static int srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2)
 
1357
{
 
1358
        return StrCaseCmp(s1->name,s2->name);
 
1359
}
 
1360
 
 
1361
/****************************************************************************
 
1362
 View list of servers available (or possibly domains). The info is
 
1363
 extracted from lists saved by nmbd on the local host.
 
1364
****************************************************************************/
 
1365
 
 
1366
static bool api_RNetServerEnum2(connection_struct *conn, uint16 vuid,
 
1367
                                char *param, int tpscnt,
 
1368
                                char *data, int tdscnt,
 
1369
                                int mdrcnt, int mprcnt, char **rdata, 
 
1370
                                char **rparam, int *rdata_len, int *rparam_len)
 
1371
{
 
1372
        char *str1 = get_safe_str_ptr(param, tpscnt, param, 2);
 
1373
        char *str2 = skip_string(param,tpscnt,str1);
 
1374
        char *p = skip_string(param,tpscnt,str2);
 
1375
        int uLevel = get_safe_SVAL(param, tpscnt, p, 0, -1);
 
1376
        int buf_len = get_safe_SVAL(param,tpscnt, p, 2, 0);
 
1377
        uint32 servertype = get_safe_IVAL(param,tpscnt,p,4, 0);
 
1378
        char *p2;
 
1379
        int data_len, fixed_len, string_len;
 
1380
        int f_len = 0, s_len = 0;
 
1381
        struct srv_info_struct *servers=NULL;
 
1382
        int counted=0,total=0;
 
1383
        int i,missed;
 
1384
        fstring domain;
 
1385
        bool domain_request;
 
1386
        bool local_request;
 
1387
 
 
1388
        if (!str1 || !str2 || !p) {
 
1389
                return False;
 
1390
        }
 
1391
 
 
1392
        /* If someone sets all the bits they don't really mean to set
 
1393
           DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
 
1394
           known servers. */
 
1395
 
 
1396
        if (servertype == SV_TYPE_ALL) {
 
1397
                servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
 
1398
        }
 
1399
 
 
1400
        /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
 
1401
           any other bit (they may just set this bit on its own) they 
 
1402
           want all the locally seen servers. However this bit can be 
 
1403
           set on its own so set the requested servers to be 
 
1404
           ALL - DOMAIN_ENUM. */
 
1405
 
 
1406
        if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) && !(servertype & SV_TYPE_DOMAIN_ENUM)) {
 
1407
                servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM);
 
1408
        }
 
1409
 
 
1410
        domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
 
1411
        local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0);
 
1412
 
 
1413
        p += 8;
 
1414
 
 
1415
        if (!prefix_ok(str1,"WrLehD")) {
 
1416
                return False;
 
1417
        }
 
1418
        if (!check_server_info(uLevel,str2)) {
 
1419
                return False;
 
1420
        }
 
1421
 
 
1422
        DEBUG(4, ("server request level: %s %8x ", str2, servertype));
 
1423
        DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
 
1424
        DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
 
1425
 
 
1426
        if (strcmp(str1, "WrLehDz") == 0) {
 
1427
                if (skip_string(param,tpscnt,p) == NULL) {
 
1428
                        return False;
 
1429
                }
 
1430
                pull_ascii_fstring(domain, p);
 
1431
        } else {
 
1432
                fstrcpy(domain, lp_workgroup());
 
1433
        }
 
1434
 
 
1435
        DEBUG(4, ("domain [%s]\n", domain));
 
1436
 
 
1437
        if (lp_browse_list()) {
 
1438
                total = get_server_info(servertype,&servers,domain);
 
1439
        }
 
1440
 
 
1441
        data_len = fixed_len = string_len = 0;
 
1442
        missed = 0;
 
1443
 
 
1444
        if (total > 0) {
 
1445
                qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp);
 
1446
        }
 
1447
 
 
1448
        {
 
1449
                char *lastname=NULL;
 
1450
 
 
1451
                for (i=0;i<total;i++) {
 
1452
                        struct srv_info_struct *s = &servers[i];
 
1453
 
 
1454
                        if (lastname && strequal(lastname,s->name)) {
 
1455
                                continue;
 
1456
                        }
 
1457
                        lastname = s->name;
 
1458
                        data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
 
1459
                        DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
 
1460
                                i, s->name, s->type, s->comment, s->domain));
 
1461
 
 
1462
                        if (data_len < buf_len) {
 
1463
                                counted++;
 
1464
                                fixed_len += f_len;
 
1465
                                string_len += s_len;
 
1466
                        } else {
 
1467
                                missed++;
 
1468
                        }
 
1469
                }
 
1470
        }
 
1471
 
 
1472
        *rdata_len = fixed_len + string_len;
 
1473
        *rdata = smb_realloc_limit(*rdata,*rdata_len);
 
1474
        if (!*rdata) {
 
1475
                return False;
 
1476
        }
 
1477
 
 
1478
        p2 = (*rdata) + fixed_len;      /* auxilliary data (strings) will go here */
 
1479
        p = *rdata;
 
1480
        f_len = fixed_len;
 
1481
        s_len = string_len;
 
1482
 
 
1483
        {
 
1484
                char *lastname=NULL;
 
1485
                int count2 = counted;
 
1486
 
 
1487
                for (i = 0; i < total && count2;i++) {
 
1488
                        struct srv_info_struct *s = &servers[i];
 
1489
 
 
1490
                        if (lastname && strequal(lastname,s->name)) {
 
1491
                                continue;
 
1492
                        }
 
1493
                        lastname = s->name;
 
1494
                        fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
 
1495
                        DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
 
1496
                                i, s->name, s->type, s->comment, s->domain));
 
1497
                        count2--;
 
1498
                }
 
1499
        }
 
1500
 
 
1501
        *rparam_len = 8;
 
1502
        *rparam = smb_realloc_limit(*rparam,*rparam_len);
 
1503
        if (!*rparam) {
 
1504
                return False;
 
1505
        }
 
1506
        SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERRmoredata));
 
1507
        SSVAL(*rparam,2,0);
 
1508
        SSVAL(*rparam,4,counted);
 
1509
        SSVAL(*rparam,6,counted+missed);
 
1510
 
 
1511
        SAFE_FREE(servers);
 
1512
 
 
1513
        DEBUG(3,("NetServerEnum2 domain = %s uLevel=%d counted=%d total=%d\n",
 
1514
                domain,uLevel,counted,counted+missed));
 
1515
 
 
1516
        return True;
 
1517
}
 
1518
 
 
1519
static int srv_name_match(const char *n1, const char *n2)
 
1520
{
 
1521
        /*
 
1522
         * [MS-RAP] footnote <88> for Section 3.2.5.15 says:
 
1523
         *
 
1524
         *  In Windows, FirstNameToReturn need not be an exact match:
 
1525
         *  the server will return a list of servers that exist on
 
1526
         *  the network greater than or equal to the FirstNameToReturn.
 
1527
         */
 
1528
        int ret = StrCaseCmp(n1, n2);
 
1529
 
 
1530
        if (ret <= 0) {
 
1531
                return 0;
 
1532
        }
 
1533
 
 
1534
        return ret;
 
1535
}
 
1536
 
 
1537
static bool api_RNetServerEnum3(connection_struct *conn, uint16 vuid,
 
1538
                                char *param, int tpscnt,
 
1539
                                char *data, int tdscnt,
 
1540
                                int mdrcnt, int mprcnt, char **rdata,
 
1541
                                char **rparam, int *rdata_len, int *rparam_len)
 
1542
{
 
1543
        char *str1 = get_safe_str_ptr(param, tpscnt, param, 2);
 
1544
        char *str2 = skip_string(param,tpscnt,str1);
 
1545
        char *p = skip_string(param,tpscnt,str2);
 
1546
        int uLevel = get_safe_SVAL(param, tpscnt, p, 0, -1);
 
1547
        int buf_len = get_safe_SVAL(param,tpscnt, p, 2, 0);
 
1548
        uint32 servertype = get_safe_IVAL(param,tpscnt,p,4, 0);
 
1549
        char *p2;
 
1550
        int data_len, fixed_len, string_len;
 
1551
        int f_len = 0, s_len = 0;
 
1552
        struct srv_info_struct *servers=NULL;
 
1553
        int counted=0,first=0,total=0;
 
1554
        int i,missed;
 
1555
        fstring domain;
 
1556
        fstring first_name;
 
1557
        bool domain_request;
 
1558
        bool local_request;
 
1559
 
 
1560
        if (!str1 || !str2 || !p) {
 
1561
                return False;
 
1562
        }
 
1563
 
 
1564
        /* If someone sets all the bits they don't really mean to set
 
1565
           DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
 
1566
           known servers. */
 
1567
 
 
1568
        if (servertype == SV_TYPE_ALL) {
 
1569
                servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
 
1570
        }
 
1571
 
 
1572
        /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
 
1573
           any other bit (they may just set this bit on its own) they
 
1574
           want all the locally seen servers. However this bit can be
 
1575
           set on its own so set the requested servers to be
 
1576
           ALL - DOMAIN_ENUM. */
 
1577
 
 
1578
        if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) && !(servertype & SV_TYPE_DOMAIN_ENUM)) {
 
1579
                servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM);
 
1580
        }
 
1581
 
 
1582
        domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
 
1583
        local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0);
 
1584
 
 
1585
        p += 8;
 
1586
 
 
1587
        if (strcmp(str1, "WrLehDzz") != 0) {
 
1588
                return false;
 
1589
        }
 
1590
        if (!check_server_info(uLevel,str2)) {
 
1591
                return False;
 
1592
        }
 
1593
 
 
1594
        DEBUG(4, ("server request level: %s %8x ", str2, servertype));
 
1595
        DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
 
1596
        DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
 
1597
 
 
1598
        if (skip_string(param,tpscnt,p) == NULL) {
 
1599
                return False;
 
1600
        }
 
1601
        pull_ascii_fstring(domain, p);
 
1602
        if (domain[0] == '\0') {
 
1603
                fstrcpy(domain, lp_workgroup());
 
1604
        }
 
1605
        p = skip_string(param,tpscnt,p);
 
1606
        if (skip_string(param,tpscnt,p) == NULL) {
 
1607
                return False;
 
1608
        }
 
1609
        pull_ascii_fstring(first_name, p);
 
1610
 
 
1611
        DEBUG(4, ("domain: '%s' first_name: '%s'\n",
 
1612
                  domain, first_name));
 
1613
 
 
1614
        if (lp_browse_list()) {
 
1615
                total = get_server_info(servertype,&servers,domain);
 
1616
        }
 
1617
 
 
1618
        data_len = fixed_len = string_len = 0;
 
1619
        missed = 0;
 
1620
 
 
1621
        if (total > 0) {
 
1622
                qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp);
 
1623
        }
 
1624
 
 
1625
        if (first_name[0] != '\0') {
 
1626
                struct srv_info_struct *first_server = NULL;
 
1627
 
 
1628
                BINARY_ARRAY_SEARCH(servers, total, name, first_name,
 
1629
                                    srv_name_match, first_server);
 
1630
                if (first_server) {
 
1631
                        first = PTR_DIFF(first_server, servers) / sizeof(*servers);
 
1632
                        /*
 
1633
                         * The binary search may not find the exact match
 
1634
                         * so we need to search backward to find the first match
 
1635
                         *
 
1636
                         * This implements the strange matching windows
 
1637
                         * implements. (see the comment in srv_name_match().
 
1638
                         */
 
1639
                        for (;first > 0;) {
 
1640
                                int ret;
 
1641
                                ret = StrCaseCmp(first_name,
 
1642
                                                 servers[first-1].name);
 
1643
                                if (ret > 0) {
 
1644
                                        break;
 
1645
                                }
 
1646
                                first--;
 
1647
                        }
 
1648
                } else {
 
1649
                        /* we should return no entries */
 
1650
                        first = total;
 
1651
                }
 
1652
        }
 
1653
 
 
1654
        {
 
1655
                char *lastname=NULL;
 
1656
 
 
1657
                for (i=first;i<total;i++) {
 
1658
                        struct srv_info_struct *s = &servers[i];
 
1659
 
 
1660
                        if (lastname && strequal(lastname,s->name)) {
 
1661
                                continue;
 
1662
                        }
 
1663
                        lastname = s->name;
 
1664
                        data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
 
1665
                        DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
 
1666
                                i, s->name, s->type, s->comment, s->domain));
 
1667
 
 
1668
                        if (data_len < buf_len) {
 
1669
                                counted++;
 
1670
                                fixed_len += f_len;
 
1671
                                string_len += s_len;
 
1672
                        } else {
 
1673
                                missed++;
 
1674
                        }
 
1675
                }
 
1676
        }
 
1677
 
 
1678
        *rdata_len = fixed_len + string_len;
 
1679
        *rdata = smb_realloc_limit(*rdata,*rdata_len);
 
1680
        if (!*rdata) {
 
1681
                return False;
 
1682
        }
 
1683
 
 
1684
        p2 = (*rdata) + fixed_len;      /* auxilliary data (strings) will go here */
 
1685
        p = *rdata;
 
1686
        f_len = fixed_len;
 
1687
        s_len = string_len;
 
1688
 
 
1689
        {
 
1690
                char *lastname=NULL;
 
1691
                int count2 = counted;
 
1692
 
 
1693
                for (i = first; i < total && count2;i++) {
 
1694
                        struct srv_info_struct *s = &servers[i];
 
1695
 
 
1696
                        if (lastname && strequal(lastname,s->name)) {
 
1697
                                continue;
 
1698
                        }
 
1699
                        lastname = s->name;
 
1700
                        fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
 
1701
                        DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
 
1702
                                i, s->name, s->type, s->comment, s->domain));
 
1703
                        count2--;
 
1704
                }
 
1705
        }
 
1706
 
 
1707
        *rparam_len = 8;
 
1708
        *rparam = smb_realloc_limit(*rparam,*rparam_len);
 
1709
        if (!*rparam) {
 
1710
                return False;
 
1711
        }
 
1712
        SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERRmoredata));
 
1713
        SSVAL(*rparam,2,0);
 
1714
        SSVAL(*rparam,4,counted);
 
1715
        SSVAL(*rparam,6,counted+missed);
 
1716
 
 
1717
        DEBUG(3,("NetServerEnum3 domain = %s uLevel=%d first=%d[%s => %s] counted=%d total=%d\n",
 
1718
                domain,uLevel,first,first_name,
 
1719
                first < total ? servers[first].name : "",
 
1720
                counted,counted+missed));
 
1721
 
 
1722
        SAFE_FREE(servers);
 
1723
 
 
1724
        return True;
 
1725
}
 
1726
 
 
1727
/****************************************************************************
 
1728
  command 0x34 - suspected of being a "Lookup Names" stub api
 
1729
  ****************************************************************************/
 
1730
 
 
1731
static bool api_RNetGroupGetUsers(connection_struct *conn, uint16 vuid,
 
1732
                                char *param, int tpscnt,
 
1733
                                char *data, int tdscnt,
 
1734
                                int mdrcnt, int mprcnt, char **rdata, 
 
1735
                                char **rparam, int *rdata_len, int *rparam_len)
 
1736
{
 
1737
        char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
 
1738
        char *str2 = skip_string(param,tpscnt,str1);
 
1739
        char *p = skip_string(param,tpscnt,str2);
 
1740
        int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
 
1741
        int buf_len = get_safe_SVAL(param,tpscnt,p,2,0);
 
1742
        int counted=0;
 
1743
        int missed=0;
 
1744
 
 
1745
        if (!str1 || !str2 || !p) {
 
1746
                return False;
 
1747
        }
 
1748
 
 
1749
        DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
 
1750
                str1, str2, p, uLevel, buf_len));
 
1751
 
 
1752
        if (!prefix_ok(str1,"zWrLeh")) {
 
1753
                return False;
 
1754
        }
 
1755
 
 
1756
        *rdata_len = 0;
 
1757
 
 
1758
        *rparam_len = 8;
 
1759
        *rparam = smb_realloc_limit(*rparam,*rparam_len);
 
1760
        if (!*rparam) {
 
1761
                return False;
 
1762
        }
 
1763
 
 
1764
        SSVAL(*rparam,0,0x08AC); /* informational warning message */
 
1765
        SSVAL(*rparam,2,0);
 
1766
        SSVAL(*rparam,4,counted);
 
1767
        SSVAL(*rparam,6,counted+missed);
 
1768
 
 
1769
        return True;
 
1770
}
 
1771
 
 
1772
/****************************************************************************
 
1773
  get info about a share
 
1774
  ****************************************************************************/
 
1775
 
 
1776
static bool check_share_info(int uLevel, char* id)
 
1777
{
 
1778
        switch( uLevel ) {
 
1779
                case 0:
 
1780
                        if (strcmp(id,"B13") != 0) {
 
1781
                                return False;
 
1782
                        }
 
1783
                        break;
 
1784
                case 1:
 
1785
                        if (strcmp(id,"B13BWz") != 0) {
 
1786
                                return False;
 
1787
                        }
 
1788
                        break;
 
1789
                case 2:
 
1790
                        if (strcmp(id,"B13BWzWWWzB9B") != 0) {
 
1791
                                return False;
 
1792
                        }
 
1793
                        break;
 
1794
                case 91:
 
1795
                        if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) {
 
1796
                                return False;
 
1797
                        }
 
1798
                        break;
 
1799
                default:
 
1800
                        return False;
 
1801
        }
 
1802
        return True;
 
1803
}
 
1804
 
 
1805
static int fill_share_info(connection_struct *conn, int snum, int uLevel,
 
1806
                           char** buf, int* buflen,
 
1807
                           char** stringbuf, int* stringspace, char* baseaddr)
 
1808
{
 
1809
        int struct_len;
 
1810
        char* p;
 
1811
        char* p2;
 
1812
        int l2;
 
1813
        int len;
 
1814
 
 
1815
        switch( uLevel ) {
 
1816
                case 0:
 
1817
                        struct_len = 13;
 
1818
                        break;
 
1819
                case 1:
 
1820
                        struct_len = 20;
 
1821
                        break;
 
1822
                case 2:
 
1823
                        struct_len = 40;
 
1824
                        break;
 
1825
                case 91:
 
1826
                        struct_len = 68;
 
1827
                        break;
 
1828
                default:
 
1829
                        return -1;
 
1830
        }
 
1831
 
 
1832
        if (!buf) {
 
1833
                len = 0;
 
1834
 
 
1835
                if (uLevel > 0) {
 
1836
                        len += StrlenExpanded(conn,snum,lp_comment(snum));
 
1837
                }
 
1838
                if (uLevel > 1) {
 
1839
                        len += strlen(lp_pathname(snum)) + 1;
 
1840
                }
 
1841
                if (buflen) {
 
1842
                        *buflen = struct_len;
 
1843
                }
 
1844
                if (stringspace) {
 
1845
                        *stringspace = len;
 
1846
                }
 
1847
                return struct_len + len;
 
1848
        }
 
1849
 
 
1850
        len = struct_len;
 
1851
        p = *buf;
 
1852
        if ((*buflen) < struct_len) {
 
1853
                return -1;
 
1854
        }
 
1855
 
 
1856
        if (stringbuf) {
 
1857
                p2 = *stringbuf;
 
1858
                l2 = *stringspace;
 
1859
        } else {
 
1860
                p2 = p + struct_len;
 
1861
                l2 = (*buflen) - struct_len;
 
1862
        }
 
1863
 
 
1864
        if (!baseaddr) {
 
1865
                baseaddr = p;
 
1866
        }
 
1867
 
 
1868
        push_ascii(p,lp_servicename(snum),13, STR_TERMINATE);
 
1869
 
 
1870
        if (uLevel > 0) {
 
1871
                int type;
 
1872
 
 
1873
                SCVAL(p,13,0);
 
1874
                type = STYPE_DISKTREE;
 
1875
                if (lp_print_ok(snum)) {
 
1876
                        type = STYPE_PRINTQ;
 
1877
                }
 
1878
                if (strequal("IPC",lp_fstype(snum))) {
 
1879
                        type = STYPE_IPC;
 
1880
                }
 
1881
                SSVAL(p,14,type);               /* device type */
 
1882
                SIVAL(p,16,PTR_DIFF(p2,baseaddr));
 
1883
                len += CopyExpanded(conn,snum,&p2,lp_comment(snum),&l2);
 
1884
        }
 
1885
 
 
1886
        if (uLevel > 1) {
 
1887
                SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */
 
1888
                SSVALS(p,22,-1);                /* max uses */
 
1889
                SSVAL(p,24,1); /* current uses */
 
1890
                SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */
 
1891
                len += CopyAndAdvance(&p2,lp_pathname(snum),&l2);
 
1892
                memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */
 
1893
        }
 
1894
 
 
1895
        if (uLevel > 2) {
 
1896
                memset(p+40,0,SHPWLEN+2);
 
1897
                SSVAL(p,50,0);
 
1898
                SIVAL(p,52,0);
 
1899
                SSVAL(p,56,0);
 
1900
                SSVAL(p,58,0);
 
1901
                SIVAL(p,60,0);
 
1902
                SSVAL(p,64,0);
 
1903
                SSVAL(p,66,0);
 
1904
        }
 
1905
 
 
1906
        if (stringbuf) {
 
1907
                (*buf) = p + struct_len;
 
1908
                (*buflen) -= struct_len;
 
1909
                (*stringbuf) = p2;
 
1910
                (*stringspace) = l2;
 
1911
        } else {
 
1912
                (*buf) = p2;
 
1913
                (*buflen) -= len;
 
1914
        }
 
1915
 
 
1916
        return len;
 
1917
}
 
1918
 
 
1919
static bool api_RNetShareGetInfo(connection_struct *conn,uint16 vuid,
 
1920
                                char *param, int tpscnt,
 
1921
                                char *data, int tdscnt,
 
1922
                                int mdrcnt,int mprcnt,
 
1923
                                char **rdata,char **rparam,
 
1924
                                int *rdata_len,int *rparam_len)
 
1925
{
 
1926
        char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
 
1927
        char *str2 = skip_string(param,tpscnt,str1);
 
1928
        char *netname = skip_string(param,tpscnt,str2);
 
1929
        char *p = skip_string(param,tpscnt,netname);
 
1930
        int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
 
1931
        int snum;
 
1932
 
 
1933
        if (!str1 || !str2 || !netname || !p) {
 
1934
                return False;
 
1935
        }
 
1936
 
 
1937
        snum = find_service(netname);
 
1938
        if (snum < 0) {
 
1939
                return False;
 
1940
        }
 
1941
 
 
1942
        /* check it's a supported varient */
 
1943
        if (!prefix_ok(str1,"zWrLh")) {
 
1944
                return False;
 
1945
        }
 
1946
        if (!check_share_info(uLevel,str2)) {
 
1947
                return False;
 
1948
        }
 
1949
 
 
1950
        *rdata = smb_realloc_limit(*rdata,mdrcnt);
 
1951
        if (!*rdata) {
 
1952
                return False;
 
1953
        }
 
1954
        p = *rdata;
 
1955
        *rdata_len = fill_share_info(conn,snum,uLevel,&p,&mdrcnt,0,0,0);
 
1956
        if (*rdata_len < 0) {
 
1957
                return False;
 
1958
        }
 
1959
 
 
1960
        *rparam_len = 6;
 
1961
        *rparam = smb_realloc_limit(*rparam,*rparam_len);
 
1962
        if (!*rparam) {
 
1963
                return False;
 
1964
        }
 
1965
        SSVAL(*rparam,0,NERR_Success);
 
1966
        SSVAL(*rparam,2,0);             /* converter word */
 
1967
        SSVAL(*rparam,4,*rdata_len);
 
1968
 
 
1969
        return True;
 
1970
}
 
1971
 
 
1972
/****************************************************************************
 
1973
  View the list of available shares.
 
1974
 
 
1975
  This function is the server side of the NetShareEnum() RAP call.
 
1976
  It fills the return buffer with share names and share comments.
 
1977
  Note that the return buffer normally (in all known cases) allows only
 
1978
  twelve byte strings for share names (plus one for a nul terminator).
 
1979
  Share names longer than 12 bytes must be skipped.
 
1980
 ****************************************************************************/
 
1981
 
 
1982
static bool api_RNetShareEnum( connection_struct *conn, uint16 vuid,
 
1983
                                char *param, int tpscnt,
 
1984
                                char *data, int tdscnt,
 
1985
                                int                mdrcnt,
 
1986
                                int                mprcnt,
 
1987
                                char             **rdata,
 
1988
                                char             **rparam,
 
1989
                                int               *rdata_len,
 
1990
                                int               *rparam_len )
 
1991
{
 
1992
        char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
 
1993
        char *str2 = skip_string(param,tpscnt,str1);
 
1994
        char *p = skip_string(param,tpscnt,str2);
 
1995
        int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
 
1996
        int buf_len = get_safe_SVAL(param,tpscnt,p,2,0);
 
1997
        char *p2;
 
1998
        int count = 0;
 
1999
        int total=0,counted=0;
 
2000
        bool missed = False;
 
2001
        int i;
 
2002
        int data_len, fixed_len, string_len;
 
2003
        int f_len = 0, s_len = 0;
 
2004
 
 
2005
        if (!str1 || !str2 || !p) {
 
2006
                return False;
 
2007
        }
 
2008
 
 
2009
        if (!prefix_ok(str1,"WrLeh")) {
 
2010
                return False;
 
2011
        }
 
2012
        if (!check_share_info(uLevel,str2)) {
 
2013
                return False;
 
2014
        }
 
2015
 
 
2016
        /* Ensure all the usershares are loaded. */
 
2017
        become_root();
 
2018
        load_registry_shares();
 
2019
        count = load_usershare_shares();
 
2020
        unbecome_root();
 
2021
 
 
2022
        data_len = fixed_len = string_len = 0;
 
2023
        for (i=0;i<count;i++) {
 
2024
                fstring servicename_dos;
 
2025
                if (!(lp_browseable(i) && lp_snum_ok(i))) {
 
2026
                        continue;
 
2027
                }
 
2028
                push_ascii_fstring(servicename_dos, lp_servicename(i));
 
2029
                /* Maximum name length = 13. */
 
2030
                if( lp_browseable( i ) && lp_snum_ok( i ) && (strlen(servicename_dos) < 13)) {
 
2031
                        total++;
 
2032
                        data_len += fill_share_info(conn,i,uLevel,0,&f_len,0,&s_len,0);
 
2033
                        if (data_len < buf_len) {
 
2034
                                counted++;
 
2035
                                fixed_len += f_len;
 
2036
                                string_len += s_len;
 
2037
                        } else {
 
2038
                                missed = True;
 
2039
                        }
 
2040
                }
 
2041
        }
 
2042
 
 
2043
        *rdata_len = fixed_len + string_len;
 
2044
        *rdata = smb_realloc_limit(*rdata,*rdata_len);
 
2045
        if (!*rdata) {
 
2046
                return False;
 
2047
        }
 
2048
 
 
2049
        p2 = (*rdata) + fixed_len;      /* auxiliary data (strings) will go here */
 
2050
        p = *rdata;
 
2051
        f_len = fixed_len;
 
2052
        s_len = string_len;
 
2053
 
 
2054
        for( i = 0; i < count; i++ ) {
 
2055
                fstring servicename_dos;
 
2056
                if (!(lp_browseable(i) && lp_snum_ok(i))) {
 
2057
                        continue;
 
2058
                }
 
2059
 
 
2060
                push_ascii_fstring(servicename_dos, lp_servicename(i));
 
2061
                if (lp_browseable(i) && lp_snum_ok(i) && (strlen(servicename_dos) < 13)) {
 
2062
                        if (fill_share_info( conn,i,uLevel,&p,&f_len,&p2,&s_len,*rdata ) < 0) {
 
2063
                                break;
 
2064
                        }
 
2065
                }
 
2066
        }
 
2067
 
 
2068
        *rparam_len = 8;
 
2069
        *rparam = smb_realloc_limit(*rparam,*rparam_len);
 
2070
        if (!*rparam) {
 
2071
                return False;
 
2072
        }
 
2073
        SSVAL(*rparam,0,missed ? ERRmoredata : NERR_Success);
 
2074
        SSVAL(*rparam,2,0);
 
2075
        SSVAL(*rparam,4,counted);
 
2076
        SSVAL(*rparam,6,total);
 
2077
 
 
2078
        DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
 
2079
                counted,total,uLevel,
 
2080
                buf_len,*rdata_len,mdrcnt));
 
2081
 
 
2082
        return True;
 
2083
}
 
2084
 
 
2085
/****************************************************************************
 
2086
  Add a share
 
2087
  ****************************************************************************/
 
2088
 
 
2089
static bool api_RNetShareAdd(connection_struct *conn,uint16 vuid,
 
2090
                                char *param, int tpscnt,
 
2091
                                char *data, int tdscnt,
 
2092
                                int mdrcnt,int mprcnt,
 
2093
                                char **rdata,char **rparam,
 
2094
                                int *rdata_len,int *rparam_len)
 
2095
{
 
2096
        char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
 
2097
        char *str2 = skip_string(param,tpscnt,str1);
 
2098
        char *p = skip_string(param,tpscnt,str2);
 
2099
        int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
 
2100
        fstring sharename;
 
2101
        fstring comment;
 
2102
        char *pathname = NULL;
 
2103
        char *command, *cmdname;
 
2104
        unsigned int offset;
 
2105
        int snum;
 
2106
        int res = ERRunsup;
 
2107
        size_t converted_size;
 
2108
 
 
2109
        if (!str1 || !str2 || !p) {
 
2110
                return False;
 
2111
        }
 
2112
 
 
2113
        /* check it's a supported varient */
 
2114
        if (!prefix_ok(str1,RAP_WShareAdd_REQ)) {
 
2115
                return False;
 
2116
        }
 
2117
        if (!check_share_info(uLevel,str2)) {
 
2118
                return False;
 
2119
        }
 
2120
        if (uLevel != 2) {
 
2121
                return False;
 
2122
        }
 
2123
 
 
2124
        /* Do we have a string ? */
 
2125
        if (skip_string(data,mdrcnt,data) == NULL) {
 
2126
                return False;
 
2127
        }
 
2128
        pull_ascii_fstring(sharename,data);
 
2129
        snum = find_service(sharename);
 
2130
        if (snum >= 0) { /* already exists */
 
2131
                res = ERRfilexists;
 
2132
                goto error_exit;
 
2133
        }
 
2134
 
 
2135
        if (mdrcnt < 28) {
 
2136
                return False;
 
2137
        }
 
2138
 
 
2139
        /* only support disk share adds */
 
2140
        if (SVAL(data,14)!=STYPE_DISKTREE) {
 
2141
                return False;
 
2142
        }
 
2143
 
 
2144
        offset = IVAL(data, 16);
 
2145
        if (offset >= mdrcnt) {
 
2146
                res = ERRinvalidparam;
 
2147
                goto error_exit;
 
2148
        }
 
2149
 
 
2150
        /* Do we have a string ? */
 
2151
        if (skip_string(data,mdrcnt,data+offset) == NULL) {
 
2152
                return False;
 
2153
        }
 
2154
        pull_ascii_fstring(comment, offset? (data+offset) : "");
 
2155
 
 
2156
        offset = IVAL(data, 26);
 
2157
 
 
2158
        if (offset >= mdrcnt) {
 
2159
                res = ERRinvalidparam;
 
2160
                goto error_exit;
 
2161
        }
 
2162
 
 
2163
        /* Do we have a string ? */
 
2164
        if (skip_string(data,mdrcnt,data+offset) == NULL) {
 
2165
                return False;
 
2166
        }
 
2167
 
 
2168
        if (!pull_ascii_talloc(talloc_tos(), &pathname,
 
2169
                               offset ? (data+offset) : "", &converted_size))
 
2170
        {
 
2171
                DEBUG(0,("api_RNetShareAdd: pull_ascii_talloc failed: %s",
 
2172
                         strerror(errno)));
 
2173
        }
 
2174
 
 
2175
        if (!pathname) {
 
2176
                return false;
 
2177
        }
 
2178
 
 
2179
        string_replace(sharename, '"', ' ');
 
2180
        string_replace(pathname, '"', ' ');
 
2181
        string_replace(comment, '"', ' ');
 
2182
 
 
2183
        cmdname = lp_add_share_cmd();
 
2184
 
 
2185
        if (!cmdname || *cmdname == '\0') {
 
2186
                return False;
 
2187
        }
 
2188
 
 
2189
        if (asprintf(&command, "%s \"%s\" \"%s\" \"%s\" \"%s\"",
 
2190
                     lp_add_share_cmd(), get_dyn_CONFIGFILE(), sharename,
 
2191
                     pathname, comment) == -1) {
 
2192
                return false;
 
2193
        }
 
2194
 
 
2195
        DEBUG(10,("api_RNetShareAdd: Running [%s]\n", command ));
 
2196
 
 
2197
        if ((res = smbrun(command, NULL)) != 0) {
 
2198
                DEBUG(1,("api_RNetShareAdd: Running [%s] returned (%d)\n",
 
2199
                         command, res ));
 
2200
                SAFE_FREE(command);
 
2201
                res = ERRnoaccess;
 
2202
                goto error_exit;
 
2203
        } else {
 
2204
                SAFE_FREE(command);
 
2205
                message_send_all(smbd_messaging_context(),
 
2206
                                 MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
 
2207
        }
 
2208
 
 
2209
        *rparam_len = 6;
 
2210
        *rparam = smb_realloc_limit(*rparam,*rparam_len);
 
2211
        if (!*rparam) {
 
2212
                return False;
 
2213
        }
 
2214
        SSVAL(*rparam,0,NERR_Success);
 
2215
        SSVAL(*rparam,2,0);             /* converter word */
 
2216
        SSVAL(*rparam,4,*rdata_len);
 
2217
        *rdata_len = 0;
 
2218
 
 
2219
        return True;
 
2220
 
 
2221
  error_exit:
 
2222
 
 
2223
        *rparam_len = 4;
 
2224
        *rparam = smb_realloc_limit(*rparam,*rparam_len);
 
2225
        if (!*rparam) {
 
2226
                return False;
 
2227
        }
 
2228
        *rdata_len = 0;
 
2229
        SSVAL(*rparam,0,res);
 
2230
        SSVAL(*rparam,2,0);
 
2231
        return True;
 
2232
}
 
2233
 
 
2234
/****************************************************************************
 
2235
  view list of groups available
 
2236
  ****************************************************************************/
 
2237
 
 
2238
static bool api_RNetGroupEnum(connection_struct *conn,uint16 vuid,
 
2239
                                char *param, int tpscnt,
 
2240
                                char *data, int tdscnt,
 
2241
                                int mdrcnt,int mprcnt,
 
2242
                                char **rdata,char **rparam,
 
2243
                                int *rdata_len,int *rparam_len)
 
2244
{
 
2245
        int i;
 
2246
        int errflags=0;
 
2247
        int resume_context, cli_buf_size;
 
2248
        char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
 
2249
        char *str2 = skip_string(param,tpscnt,str1);
 
2250
        char *p = skip_string(param,tpscnt,str2);
 
2251
 
 
2252
        uint32_t num_groups;
 
2253
        uint32_t resume_handle;
 
2254
        struct rpc_pipe_client *samr_pipe;
 
2255
        struct policy_handle samr_handle, domain_handle;
 
2256
        NTSTATUS status;
 
2257
 
 
2258
        if (!str1 || !str2 || !p) {
 
2259
                return False;
 
2260
        }
 
2261
 
 
2262
        if (strcmp(str1,"WrLeh") != 0) {
 
2263
                return False;
 
2264
        }
 
2265
 
 
2266
        /* parameters  
 
2267
         * W-> resume context (number of users to skip)
 
2268
         * r -> return parameter pointer to receive buffer 
 
2269
         * L -> length of receive buffer
 
2270
         * e -> return parameter number of entries
 
2271
         * h -> return parameter total number of users
 
2272
         */
 
2273
 
 
2274
        if (strcmp("B21",str2) != 0) {
 
2275
                return False;
 
2276
        }
 
2277
 
 
2278
        status = rpc_pipe_open_internal(
 
2279
                talloc_tos(), &ndr_table_samr.syntax_id, rpc_samr_dispatch,
 
2280
                conn->server_info, &samr_pipe);
 
2281
        if (!NT_STATUS_IS_OK(status)) {
 
2282
                DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
 
2283
                          nt_errstr(status)));
 
2284
                return false;
 
2285
        }
 
2286
 
 
2287
        status = rpccli_samr_Connect2(samr_pipe, talloc_tos(), global_myname(),
 
2288
                                      SAMR_ACCESS_LOOKUP_DOMAIN, &samr_handle);
 
2289
        if (!NT_STATUS_IS_OK(status)) {
 
2290
                DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
 
2291
                          nt_errstr(status)));
 
2292
                return false;
 
2293
        }
 
2294
 
 
2295
        status = rpccli_samr_OpenDomain(samr_pipe, talloc_tos(), &samr_handle,
 
2296
                                        SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS,
 
2297
                                        get_global_sam_sid(), &domain_handle);
 
2298
        if (!NT_STATUS_IS_OK(status)) {
 
2299
                DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
 
2300
                          nt_errstr(status)));
 
2301
                rpccli_samr_Close(samr_pipe, talloc_tos(), &samr_handle);
 
2302
                return false;
 
2303
        }
 
2304
 
 
2305
        resume_context = get_safe_SVAL(param,tpscnt,p,0,-1);
 
2306
        cli_buf_size= get_safe_SVAL(param,tpscnt,p,2,0);
 
2307
        DEBUG(10,("api_RNetGroupEnum:resume context: %d, client buffer size: "
 
2308
                  "%d\n", resume_context, cli_buf_size));
 
2309
 
 
2310
        *rdata_len = cli_buf_size;
 
2311
        *rdata = smb_realloc_limit(*rdata,*rdata_len);
 
2312
        if (!*rdata) {
 
2313
                return False;
 
2314
        }
 
2315
 
 
2316
        p = *rdata;
 
2317
 
 
2318
        errflags = NERR_Success;
 
2319
        num_groups = 0;
 
2320
        resume_handle = 0;
 
2321
 
 
2322
        while (true) {
 
2323
                struct samr_SamArray *sam_entries;
 
2324
                uint32_t num_entries;
 
2325
 
 
2326
                status = rpccli_samr_EnumDomainGroups(samr_pipe, talloc_tos(),
 
2327
                                                      &domain_handle,
 
2328
                                                      &resume_handle,
 
2329
                                                      &sam_entries, 1,
 
2330
                                                      &num_entries);
 
2331
                if (!NT_STATUS_IS_OK(status)) {
 
2332
                        DEBUG(10, ("rpccli_samr_EnumDomainGroups returned "
 
2333
                                   "%s\n", nt_errstr(status)));
 
2334
                        break;
 
2335
                }
 
2336
 
 
2337
                if (num_entries == 0) {
 
2338
                        DEBUG(10, ("rpccli_samr_EnumDomainGroups returned "
 
2339
                                   "no entries -- done\n"));
 
2340
                        break;
 
2341
                }
 
2342
 
 
2343
                for(i=0; i<num_entries; i++) {
 
2344
                        const char *name;
 
2345
 
 
2346
                        name = sam_entries->entries[i].name.string;
 
2347
 
 
2348
                        if( ((PTR_DIFF(p,*rdata)+21) > *rdata_len) ) {
 
2349
                                /* set overflow error */
 
2350
                                DEBUG(3,("overflow on entry %d group %s\n", i,
 
2351
                                         name));
 
2352
                                errflags=234;
 
2353
                                break;
 
2354
                        }
 
2355
 
 
2356
                        /* truncate the name at 21 chars. */
 
2357
                        memset(p, 0, 21);
 
2358
                        strlcpy(p, name, 21);
 
2359
                        DEBUG(10,("adding entry %d group %s\n", i, p));
 
2360
                        p += 21;
 
2361
                        p += 5; /* Both NT4 and W2k3SP1 do padding here.  No
 
2362
                                 * idea why... */
 
2363
                        num_groups += 1;
 
2364
                }
 
2365
 
 
2366
                if (errflags != NERR_Success) {
 
2367
                        break;
 
2368
                }
 
2369
 
 
2370
                TALLOC_FREE(sam_entries);
 
2371
        }
 
2372
 
 
2373
        rpccli_samr_Close(samr_pipe, talloc_tos(), &domain_handle);
 
2374
        rpccli_samr_Close(samr_pipe, talloc_tos(), &samr_handle);
 
2375
 
 
2376
        *rdata_len = PTR_DIFF(p,*rdata);
 
2377
 
 
2378
        *rparam_len = 8;
 
2379
        *rparam = smb_realloc_limit(*rparam,*rparam_len);
 
2380
        if (!*rparam) {
 
2381
                return False;
 
2382
        }
 
2383
        SSVAL(*rparam, 0, errflags);
 
2384
        SSVAL(*rparam, 2, 0);           /* converter word */
 
2385
        SSVAL(*rparam, 4, num_groups);  /* is this right?? */
 
2386
        SSVAL(*rparam, 6, resume_context+num_groups);   /* is this right?? */
 
2387
 
 
2388
        return(True);
 
2389
}
 
2390
 
 
2391
/*******************************************************************
 
2392
 Get groups that a user is a member of.
 
2393
******************************************************************/
 
2394
 
 
2395
static bool api_NetUserGetGroups(connection_struct *conn,uint16 vuid,
 
2396
                                char *param, int tpscnt,
 
2397
                                char *data, int tdscnt,
 
2398
                                int mdrcnt,int mprcnt,
 
2399
                                char **rdata,char **rparam,
 
2400
                                int *rdata_len,int *rparam_len)
 
2401
{
 
2402
        char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
 
2403
        char *str2 = skip_string(param,tpscnt,str1);
 
2404
        char *UserName = skip_string(param,tpscnt,str2);
 
2405
        char *p = skip_string(param,tpscnt,UserName);
 
2406
        int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
 
2407
        const char *level_string;
 
2408
        int count=0;
 
2409
        bool ret = False;
 
2410
        uint32_t i;
 
2411
        char *endp = NULL;
 
2412
 
 
2413
        struct rpc_pipe_client *samr_pipe;
 
2414
        struct policy_handle samr_handle, domain_handle, user_handle;
 
2415
        struct lsa_String name;
 
2416
        struct lsa_Strings names;
 
2417
        struct samr_Ids type, rid;
 
2418
        struct samr_RidWithAttributeArray *rids;
 
2419
        NTSTATUS status;
 
2420
 
 
2421
        if (!str1 || !str2 || !UserName || !p) {
 
2422
                return False;
 
2423
        }
 
2424
 
 
2425
        *rparam_len = 8;
 
2426
        *rparam = smb_realloc_limit(*rparam,*rparam_len);
 
2427
        if (!*rparam) {
 
2428
                return False;
 
2429
        }
 
2430
 
 
2431
        /* check it's a supported varient */
 
2432
 
 
2433
        if ( strcmp(str1,"zWrLeh") != 0 )
 
2434
                return False;
 
2435
 
 
2436
        switch( uLevel ) {
 
2437
                case 0:
 
2438
                        level_string = "B21";
 
2439
                        break;
 
2440
                default:
 
2441
                        return False;
 
2442
        }
 
2443
 
 
2444
        if (strcmp(level_string,str2) != 0)
 
2445
                return False;
 
2446
 
 
2447
        *rdata_len = mdrcnt + 1024;
 
2448
        *rdata = smb_realloc_limit(*rdata,*rdata_len);
 
2449
        if (!*rdata) {
 
2450
                return False;
 
2451
        }
 
2452
 
 
2453
        SSVAL(*rparam,0,NERR_Success);
 
2454
        SSVAL(*rparam,2,0);             /* converter word */
 
2455
 
 
2456
        p = *rdata;
 
2457
        endp = *rdata + *rdata_len;
 
2458
 
 
2459
        status = rpc_pipe_open_internal(
 
2460
                talloc_tos(), &ndr_table_samr.syntax_id, rpc_samr_dispatch,
 
2461
                conn->server_info, &samr_pipe);
 
2462
        if (!NT_STATUS_IS_OK(status)) {
 
2463
                DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
 
2464
                          nt_errstr(status)));
 
2465
                return false;
 
2466
        }
 
2467
 
 
2468
        status = rpccli_samr_Connect2(samr_pipe, talloc_tos(), global_myname(),
 
2469
                                      SAMR_ACCESS_LOOKUP_DOMAIN, &samr_handle);
 
2470
        if (!NT_STATUS_IS_OK(status)) {
 
2471
                DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
 
2472
                          nt_errstr(status)));
 
2473
                return false;
 
2474
        }
 
2475
 
 
2476
        status = rpccli_samr_OpenDomain(samr_pipe, talloc_tos(), &samr_handle,
 
2477
                                        SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
 
2478
                                        get_global_sam_sid(), &domain_handle);
 
2479
        if (!NT_STATUS_IS_OK(status)) {
 
2480
                DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
 
2481
                          nt_errstr(status)));
 
2482
                goto close_sam;
 
2483
        }
 
2484
 
 
2485
        name.string = UserName;
 
2486
 
 
2487
        status = rpccli_samr_LookupNames(samr_pipe, talloc_tos(),
 
2488
                                         &domain_handle, 1, &name,
 
2489
                                         &rid, &type);
 
2490
        if (!NT_STATUS_IS_OK(status)) {
 
2491
                DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
 
2492
                          nt_errstr(status)));
 
2493
                goto close_domain;
 
2494
        }
 
2495
 
 
2496
        if (type.ids[0] != SID_NAME_USER) {
 
2497
                DEBUG(10, ("%s is a %s, not a user\n", UserName,
 
2498
                           sid_type_lookup(type.ids[0])));
 
2499
                goto close_domain;
 
2500
        }
 
2501
 
 
2502
        status = rpccli_samr_OpenUser(samr_pipe, talloc_tos(),
 
2503
                                      &domain_handle,
 
2504
                                      SAMR_USER_ACCESS_GET_GROUPS,
 
2505
                                      rid.ids[0], &user_handle);
 
2506
        if (!NT_STATUS_IS_OK(status)) {
 
2507
                DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
 
2508
                          nt_errstr(status)));
 
2509
                goto close_domain;
 
2510
        }
 
2511
 
 
2512
        status = rpccli_samr_GetGroupsForUser(samr_pipe, talloc_tos(),
 
2513
                                              &user_handle, &rids);
 
2514
        if (!NT_STATUS_IS_OK(status)) {
 
2515
                DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
 
2516
                          nt_errstr(status)));
 
2517
                goto close_user;
 
2518
        }
 
2519
 
 
2520
        for (i=0; i<rids->count; i++) {
 
2521
 
 
2522
                status = rpccli_samr_LookupRids(samr_pipe, talloc_tos(),
 
2523
                                                &domain_handle,
 
2524
                                                1, &rids->rids[i].rid,
 
2525
                                                &names, &type);
 
2526
                if (NT_STATUS_IS_OK(status) && (names.count == 1)) {
 
2527
                        strlcpy(p, names.names[0].string, PTR_DIFF(endp,p));
 
2528
                        p += 21;
 
2529
                        count++;
 
2530
                }
 
2531
        }
 
2532
 
 
2533
        *rdata_len = PTR_DIFF(p,*rdata);
 
2534
 
 
2535
        SSVAL(*rparam,4,count); /* is this right?? */
 
2536
        SSVAL(*rparam,6,count); /* is this right?? */
 
2537
 
 
2538
        ret = True;
 
2539
 
 
2540
 close_user:
 
2541
        rpccli_samr_Close(samr_pipe, talloc_tos(), &user_handle);
 
2542
 close_domain:
 
2543
        rpccli_samr_Close(samr_pipe, talloc_tos(), &domain_handle);
 
2544
 close_sam:
 
2545
        rpccli_samr_Close(samr_pipe, talloc_tos(), &samr_handle);
 
2546
 
 
2547
        return ret;
 
2548
}
 
2549
 
 
2550
/*******************************************************************
 
2551
 Get all users.
 
2552
******************************************************************/
 
2553
 
 
2554
static bool api_RNetUserEnum(connection_struct *conn, uint16 vuid,
 
2555
                                char *param, int tpscnt,
 
2556
                                char *data, int tdscnt,
 
2557
                                int mdrcnt,int mprcnt,
 
2558
                                char **rdata,char **rparam,
 
2559
                                int *rdata_len,int *rparam_len)
 
2560
{
 
2561
        int count_sent=0;
 
2562
        int num_users=0;
 
2563
        int errflags=0;
 
2564
        int i, resume_context, cli_buf_size;
 
2565
        uint32_t resume_handle;
 
2566
 
 
2567
        struct rpc_pipe_client *samr_pipe;
 
2568
        struct policy_handle samr_handle, domain_handle;
 
2569
        NTSTATUS status;
 
2570
 
 
2571
        char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
 
2572
        char *str2 = skip_string(param,tpscnt,str1);
 
2573
        char *p = skip_string(param,tpscnt,str2);
 
2574
        char *endp = NULL;
 
2575
 
 
2576
        if (!str1 || !str2 || !p) {
 
2577
                return False;
 
2578
        }
 
2579
 
 
2580
        if (strcmp(str1,"WrLeh") != 0)
 
2581
                return False;
 
2582
        /* parameters
 
2583
          * W-> resume context (number of users to skip)
 
2584
          * r -> return parameter pointer to receive buffer
 
2585
          * L -> length of receive buffer
 
2586
          * e -> return parameter number of entries
 
2587
          * h -> return parameter total number of users
 
2588
          */
 
2589
 
 
2590
        resume_context = get_safe_SVAL(param,tpscnt,p,0,-1);
 
2591
        cli_buf_size= get_safe_SVAL(param,tpscnt,p,2,0);
 
2592
        DEBUG(10,("api_RNetUserEnum:resume context: %d, client buffer size: %d\n",
 
2593
                        resume_context, cli_buf_size));
 
2594
 
 
2595
        *rparam_len = 8;
 
2596
        *rparam = smb_realloc_limit(*rparam,*rparam_len);
 
2597
        if (!*rparam) {
 
2598
                return False;
 
2599
        }
 
2600
 
 
2601
        /* check it's a supported varient */
 
2602
        if (strcmp("B21",str2) != 0)
 
2603
                return False;
 
2604
 
 
2605
        *rdata_len = cli_buf_size;
 
2606
        *rdata = smb_realloc_limit(*rdata,*rdata_len);
 
2607
        if (!*rdata) {
 
2608
                return False;
 
2609
        }
 
2610
 
 
2611
        p = *rdata;
 
2612
        endp = *rdata + *rdata_len;
 
2613
 
 
2614
        status = rpc_pipe_open_internal(
 
2615
                talloc_tos(), &ndr_table_samr.syntax_id, rpc_samr_dispatch,
 
2616
                conn->server_info, &samr_pipe);
 
2617
        if (!NT_STATUS_IS_OK(status)) {
 
2618
                DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
 
2619
                          nt_errstr(status)));
 
2620
                return false;
 
2621
        }
 
2622
 
 
2623
        status = rpccli_samr_Connect2(samr_pipe, talloc_tos(), global_myname(),
 
2624
                                      SAMR_ACCESS_LOOKUP_DOMAIN, &samr_handle);
 
2625
        if (!NT_STATUS_IS_OK(status)) {
 
2626
                DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
 
2627
                          nt_errstr(status)));
 
2628
                return false;
 
2629
        }
 
2630
 
 
2631
        status = rpccli_samr_OpenDomain(samr_pipe, talloc_tos(), &samr_handle,
 
2632
                                        SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS,
 
2633
                                        get_global_sam_sid(), &domain_handle);
 
2634
        if (!NT_STATUS_IS_OK(status)) {
 
2635
                DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
 
2636
                          nt_errstr(status)));
 
2637
                rpccli_samr_Close(samr_pipe, talloc_tos(), &samr_handle);
 
2638
                return false;
 
2639
        }
 
2640
 
 
2641
        errflags=NERR_Success;
 
2642
 
 
2643
        resume_handle = 0;
 
2644
 
 
2645
        while (true) {
 
2646
                struct samr_SamArray *sam_entries;
 
2647
                uint32_t num_entries;
 
2648
 
 
2649
                status = rpccli_samr_EnumDomainUsers(samr_pipe, talloc_tos(),
 
2650
                                                     &domain_handle,
 
2651
                                                     &resume_handle,
 
2652
                                                     0, &sam_entries, 1,
 
2653
                                                     &num_entries);
 
2654
 
 
2655
                if (!NT_STATUS_IS_OK(status)) {
 
2656
                        DEBUG(10, ("rpccli_samr_EnumDomainUsers returned "
 
2657
                                   "%s\n", nt_errstr(status)));
 
2658
                        break;
 
2659
                }
 
2660
 
 
2661
                if (num_entries == 0) {
 
2662
                        DEBUG(10, ("rpccli_samr_EnumDomainUsers returned "
 
2663
                                   "no entries -- done\n"));
 
2664
                        break;
 
2665
                }
 
2666
 
 
2667
                for (i=0; i<num_entries; i++) {
 
2668
                        const char *name;
 
2669
 
 
2670
                        name = sam_entries->entries[i].name.string;
 
2671
 
 
2672
                        if(((PTR_DIFF(p,*rdata)+21)<=*rdata_len)
 
2673
                           &&(strlen(name)<=21)) {
 
2674
                                strlcpy(p,name,PTR_DIFF(endp,p));
 
2675
                                DEBUG(10,("api_RNetUserEnum:adding entry %d "
 
2676
                                          "username %s\n",count_sent,p));
 
2677
                                p += 21;
 
2678
                                count_sent++;
 
2679
                        } else {
 
2680
                                /* set overflow error */
 
2681
                                DEBUG(10,("api_RNetUserEnum:overflow on entry %d "
 
2682
                                          "username %s\n",count_sent,name));
 
2683
                                errflags=234;
 
2684
                                break;
 
2685
                        }
 
2686
                }
 
2687
 
 
2688
                if (errflags != NERR_Success) {
 
2689
                        break;
 
2690
                }
 
2691
 
 
2692
                TALLOC_FREE(sam_entries);
 
2693
        }
 
2694
 
 
2695
        rpccli_samr_Close(samr_pipe, talloc_tos(), &domain_handle);
 
2696
        rpccli_samr_Close(samr_pipe, talloc_tos(), &samr_handle);
 
2697
 
 
2698
        *rdata_len = PTR_DIFF(p,*rdata);
 
2699
 
 
2700
        SSVAL(*rparam,0,errflags);
 
2701
        SSVAL(*rparam,2,0);           /* converter word */
 
2702
        SSVAL(*rparam,4,count_sent);  /* is this right?? */
 
2703
        SSVAL(*rparam,6,num_users); /* is this right?? */
 
2704
 
 
2705
        return True;
 
2706
}
 
2707
 
 
2708
/****************************************************************************
 
2709
 Get the time of day info.
 
2710
****************************************************************************/
 
2711
 
 
2712
static bool api_NetRemoteTOD(connection_struct *conn,uint16 vuid,
 
2713
                                char *param, int tpscnt,
 
2714
                                char *data, int tdscnt,
 
2715
                                int mdrcnt,int mprcnt,
 
2716
                                char **rdata,char **rparam,
 
2717
                                int *rdata_len,int *rparam_len)
 
2718
{
 
2719
        struct tm *t;
 
2720
        time_t unixdate = time(NULL);
 
2721
        char *p;
 
2722
 
 
2723
        *rparam_len = 4;
 
2724
        *rparam = smb_realloc_limit(*rparam,*rparam_len);
 
2725
        if (!*rparam) {
 
2726
                return False;
 
2727
        }
 
2728
 
 
2729
        *rdata_len = 21;
 
2730
        *rdata = smb_realloc_limit(*rdata,*rdata_len);
 
2731
        if (!*rdata) {
 
2732
                return False;
 
2733
        }
 
2734
 
 
2735
        SSVAL(*rparam,0,NERR_Success);
 
2736
        SSVAL(*rparam,2,0);             /* converter word */
 
2737
 
 
2738
        p = *rdata;
 
2739
 
 
2740
        srv_put_dos_date3(p,0,unixdate); /* this is the time that is looked at
 
2741
                                            by NT in a "net time" operation,
 
2742
                                            it seems to ignore the one below */
 
2743
 
 
2744
        /* the client expects to get localtime, not GMT, in this bit 
 
2745
                (I think, this needs testing) */
 
2746
        t = localtime(&unixdate);
 
2747
        if (!t) {
 
2748
                return False;
 
2749
        }
 
2750
 
 
2751
        SIVAL(p,4,0);           /* msecs ? */
 
2752
        SCVAL(p,8,t->tm_hour);
 
2753
        SCVAL(p,9,t->tm_min);
 
2754
        SCVAL(p,10,t->tm_sec);
 
2755
        SCVAL(p,11,0);          /* hundredths of seconds */
 
2756
        SSVALS(p,12,get_time_zone(unixdate)/60); /* timezone in minutes from GMT */
 
2757
        SSVAL(p,14,10000);              /* timer interval in 0.0001 of sec */
 
2758
        SCVAL(p,16,t->tm_mday);
 
2759
        SCVAL(p,17,t->tm_mon + 1);
 
2760
        SSVAL(p,18,1900+t->tm_year);
 
2761
        SCVAL(p,20,t->tm_wday);
 
2762
 
 
2763
        return True;
 
2764
}
 
2765
 
 
2766
/****************************************************************************
 
2767
 Set the user password.
 
2768
*****************************************************************************/
 
2769
 
 
2770
static bool api_SetUserPassword(connection_struct *conn,uint16 vuid,
 
2771
                                char *param, int tpscnt,
 
2772
                                char *data, int tdscnt,
 
2773
                                int mdrcnt,int mprcnt,
 
2774
                                char **rdata,char **rparam,
 
2775
                                int *rdata_len,int *rparam_len)
 
2776
{
 
2777
        char *np = get_safe_str_ptr(param,tpscnt,param,2);
 
2778
        char *p = NULL;
 
2779
        fstring user;
 
2780
        fstring pass1,pass2;
 
2781
 
 
2782
        /* Skip 2 strings. */
 
2783
        p = skip_string(param,tpscnt,np);
 
2784
        p = skip_string(param,tpscnt,p);
 
2785
 
 
2786
        if (!np || !p) {
 
2787
                return False;
 
2788
        }
 
2789
 
 
2790
        /* Do we have a string ? */
 
2791
        if (skip_string(param,tpscnt,p) == NULL) {
 
2792
                return False;
 
2793
        }
 
2794
        pull_ascii_fstring(user,p);
 
2795
 
 
2796
        p = skip_string(param,tpscnt,p);
 
2797
        if (!p) {
 
2798
                return False;
 
2799
        }
 
2800
 
 
2801
        memset(pass1,'\0',sizeof(pass1));
 
2802
        memset(pass2,'\0',sizeof(pass2));
 
2803
        /*
 
2804
         * We use 31 here not 32 as we're checking
 
2805
         * the last byte we want to access is safe.
 
2806
         */
 
2807
        if (!is_offset_safe(param,tpscnt,p,31)) {
 
2808
                return False;
 
2809
        }
 
2810
        memcpy(pass1,p,16);
 
2811
        memcpy(pass2,p+16,16);
 
2812
 
 
2813
        *rparam_len = 4;
 
2814
        *rparam = smb_realloc_limit(*rparam,*rparam_len);
 
2815
        if (!*rparam) {
 
2816
                return False;
 
2817
        }
 
2818
 
 
2819
        *rdata_len = 0;
 
2820
 
 
2821
        SSVAL(*rparam,0,NERR_badpass);
 
2822
        SSVAL(*rparam,2,0);             /* converter word */
 
2823
 
 
2824
        DEBUG(3,("Set password for <%s>\n",user));
 
2825
 
 
2826
        /*
 
2827
         * Attempt to verify the old password against smbpasswd entries
 
2828
         * Win98 clients send old and new password in plaintext for this call.
 
2829
         */
 
2830
 
 
2831
        {
 
2832
                auth_serversupplied_info *server_info = NULL;
 
2833
                DATA_BLOB password = data_blob(pass1, strlen(pass1)+1);
 
2834
 
 
2835
                if (NT_STATUS_IS_OK(check_plaintext_password(user,password,&server_info))) {
 
2836
 
 
2837
                        become_root();
 
2838
                        if (NT_STATUS_IS_OK(change_oem_password(server_info->sam_account, pass1, pass2, False, NULL))) {
 
2839
                                SSVAL(*rparam,0,NERR_Success);
 
2840
                        }
 
2841
                        unbecome_root();
 
2842
 
 
2843
                        TALLOC_FREE(server_info);
 
2844
                }
 
2845
                data_blob_clear_free(&password);
 
2846
        }
 
2847
 
 
2848
        /*
 
2849
         * If the plaintext change failed, attempt
 
2850
         * the old encrypted method. NT will generate this
 
2851
         * after trying the samr method. Note that this
 
2852
         * method is done as a last resort as this
 
2853
         * password change method loses the NT password hash
 
2854
         * and cannot change the UNIX password as no plaintext
 
2855
         * is received.
 
2856
         */
 
2857
 
 
2858
        if(SVAL(*rparam,0) != NERR_Success) {
 
2859
                struct samu *hnd = NULL;
 
2860
 
 
2861
                if (check_lanman_password(user,(unsigned char *)pass1,(unsigned char *)pass2, &hnd)) {
 
2862
                        become_root();
 
2863
                        if (change_lanman_password(hnd,(uchar *)pass2)) {
 
2864
                                SSVAL(*rparam,0,NERR_Success);
 
2865
                        }
 
2866
                        unbecome_root();
 
2867
                        TALLOC_FREE(hnd);
 
2868
                }
 
2869
        }
 
2870
 
 
2871
        memset((char *)pass1,'\0',sizeof(fstring));
 
2872
        memset((char *)pass2,'\0',sizeof(fstring));      
 
2873
 
 
2874
        return(True);
 
2875
}
 
2876
 
 
2877
/****************************************************************************
 
2878
  Set the user password (SamOEM version - gets plaintext).
 
2879
****************************************************************************/
 
2880
 
 
2881
static bool api_SamOEMChangePassword(connection_struct *conn,uint16 vuid,
 
2882
                                char *param, int tpscnt,
 
2883
                                char *data, int tdscnt,
 
2884
                                int mdrcnt,int mprcnt,
 
2885
                                char **rdata,char **rparam,
 
2886
                                int *rdata_len,int *rparam_len)
 
2887
{
 
2888
        fstring user;
 
2889
        char *p = get_safe_str_ptr(param,tpscnt,param,2);
 
2890
        *rparam_len = 2;
 
2891
        *rparam = smb_realloc_limit(*rparam,*rparam_len);
 
2892
        if (!*rparam) {
 
2893
                return False;
 
2894
        }
 
2895
 
 
2896
        if (!p) {
 
2897
                return False;
 
2898
        }
 
2899
        *rdata_len = 0;
 
2900
 
 
2901
        SSVAL(*rparam,0,NERR_badpass);
 
2902
 
 
2903
        /*
 
2904
         * Check the parameter definition is correct.
 
2905
         */
 
2906
 
 
2907
        /* Do we have a string ? */
 
2908
        if (skip_string(param,tpscnt,p) == 0) {
 
2909
                return False;
 
2910
        }
 
2911
        if(!strequal(p, "zsT")) {
 
2912
                DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", p));
 
2913
                return False;
 
2914
        }
 
2915
        p = skip_string(param, tpscnt, p);
 
2916
        if (!p) {
 
2917
                return False;
 
2918
        }
 
2919
 
 
2920
        /* Do we have a string ? */
 
2921
        if (skip_string(param,tpscnt,p) == 0) {
 
2922
                return False;
 
2923
        }
 
2924
        if(!strequal(p, "B516B16")) {
 
2925
                DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p));
 
2926
                return False;
 
2927
        }
 
2928
        p = skip_string(param,tpscnt,p);
 
2929
        if (!p) {
 
2930
                return False;
 
2931
        }
 
2932
        /* Do we have a string ? */
 
2933
        if (skip_string(param,tpscnt,p) == 0) {
 
2934
                return False;
 
2935
        }
 
2936
        p += pull_ascii_fstring(user,p);
 
2937
 
 
2938
        DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user));
 
2939
 
 
2940
        /*
 
2941
         * Pass the user through the NT -> unix user mapping
 
2942
         * function.
 
2943
         */
 
2944
 
 
2945
        (void)map_username(user);
 
2946
 
 
2947
        if (NT_STATUS_IS_OK(pass_oem_change(user, (uchar*) data, (uchar *)&data[516], NULL, NULL, NULL))) {
 
2948
                SSVAL(*rparam,0,NERR_Success);
 
2949
        }
 
2950
 
 
2951
        return(True);
 
2952
}
 
2953
 
 
2954
/****************************************************************************
 
2955
  delete a print job
 
2956
  Form: <W> <> 
 
2957
  ****************************************************************************/
 
2958
 
 
2959
static bool api_RDosPrintJobDel(connection_struct *conn,uint16 vuid,
 
2960
                                char *param, int tpscnt,
 
2961
                                char *data, int tdscnt,
 
2962
                                int mdrcnt,int mprcnt,
 
2963
                                char **rdata,char **rparam,
 
2964
                                int *rdata_len,int *rparam_len)
 
2965
{
 
2966
        int function = get_safe_SVAL(param,tpscnt,param,0,0);
 
2967
        char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
 
2968
        char *str2 = skip_string(param,tpscnt,str1);
 
2969
        char *p = skip_string(param,tpscnt,str2);
 
2970
        uint32 jobid;
 
2971
        int snum;
 
2972
        fstring sharename;
 
2973
        int errcode;
 
2974
        WERROR werr = WERR_OK;
 
2975
 
 
2976
        if (!str1 || !str2 || !p) {
 
2977
                return False;
 
2978
        }
 
2979
        /*
 
2980
         * We use 1 here not 2 as we're checking
 
2981
         * the last byte we want to access is safe.
 
2982
         */
 
2983
        if (!is_offset_safe(param,tpscnt,p,1)) {
 
2984
                return False;
 
2985
        }
 
2986
        if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid))
 
2987
                return False;
 
2988
 
 
2989
        /* check it's a supported varient */
 
2990
        if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
 
2991
                return(False);
 
2992
 
 
2993
        *rparam_len = 4;
 
2994
        *rparam = smb_realloc_limit(*rparam,*rparam_len);
 
2995
        if (!*rparam) {
 
2996
                return False;
 
2997
        }
 
2998
        *rdata_len = 0;
 
2999
 
 
3000
        if (!print_job_exists(sharename, jobid)) {
 
3001
                errcode = NERR_JobNotFound;
 
3002
                goto out;
 
3003
        }
 
3004
 
 
3005
        snum = lp_servicenumber( sharename);
 
3006
        if (snum == -1) {
 
3007
                errcode = NERR_DestNotFound;
 
3008
                goto out;
 
3009
        }
 
3010
 
 
3011
        errcode = NERR_notsupported;
 
3012
 
 
3013
        switch (function) {
 
3014
        case 81:                /* delete */ 
 
3015
                if (print_job_delete(conn->server_info, snum, jobid, &werr))
 
3016
                        errcode = NERR_Success;
 
3017
                break;
 
3018
        case 82:                /* pause */
 
3019
                if (print_job_pause(conn->server_info, snum, jobid, &werr))
 
3020
                        errcode = NERR_Success;
 
3021
                break;
 
3022
        case 83:                /* resume */
 
3023
                if (print_job_resume(conn->server_info, snum, jobid, &werr))
 
3024
                        errcode = NERR_Success;
 
3025
                break;
 
3026
        }
 
3027
 
 
3028
        if (!W_ERROR_IS_OK(werr))
 
3029
                errcode = W_ERROR_V(werr);
 
3030
 
 
3031
 out:
 
3032
        SSVAL(*rparam,0,errcode);       
 
3033
        SSVAL(*rparam,2,0);             /* converter word */
 
3034
 
 
3035
        return(True);
 
3036
}
 
3037
 
 
3038
/****************************************************************************
 
3039
  Purge a print queue - or pause or resume it.
 
3040
  ****************************************************************************/
 
3041
 
 
3042
static bool api_WPrintQueueCtrl(connection_struct *conn,uint16 vuid,
 
3043
                                char *param, int tpscnt,
 
3044
                                char *data, int tdscnt,
 
3045
                                int mdrcnt,int mprcnt,
 
3046
                                char **rdata,char **rparam,
 
3047
                                int *rdata_len,int *rparam_len)
 
3048
{
 
3049
        int function = get_safe_SVAL(param,tpscnt,param,0,0);
 
3050
        char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
 
3051
        char *str2 = skip_string(param,tpscnt,str1);
 
3052
        char *QueueName = skip_string(param,tpscnt,str2);
 
3053
        int errcode = NERR_notsupported;
 
3054
        int snum;
 
3055
        WERROR werr = WERR_OK;
 
3056
 
 
3057
        if (!str1 || !str2 || !QueueName) {
 
3058
                return False;
 
3059
        }
 
3060
 
 
3061
        /* check it's a supported varient */
 
3062
        if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
 
3063
                return(False);
 
3064
 
 
3065
        *rparam_len = 4;
 
3066
        *rparam = smb_realloc_limit(*rparam,*rparam_len);
 
3067
        if (!*rparam) {
 
3068
                return False;
 
3069
        }
 
3070
        *rdata_len = 0;
 
3071
 
 
3072
        if (skip_string(param,tpscnt,QueueName) == NULL) {
 
3073
                return False;
 
3074
        }
 
3075
        snum = print_queue_snum(QueueName);
 
3076
 
 
3077
        if (snum == -1) {
 
3078
                errcode = NERR_JobNotFound;
 
3079
                goto out;
 
3080
        }
 
3081
 
 
3082
        switch (function) {
 
3083
        case 74: /* Pause queue */
 
3084
                werr = print_queue_pause(conn->server_info, snum);
 
3085
                break;
 
3086
        case 75: /* Resume queue */
 
3087
                werr = print_queue_resume(conn->server_info, snum);
 
3088
                break;
 
3089
        case 103: /* Purge */
 
3090
                werr = print_queue_purge(conn->server_info, snum);
 
3091
                break;
 
3092
        default:
 
3093
                werr = WERR_NOT_SUPPORTED;
 
3094
                break;
 
3095
        }
 
3096
 
 
3097
        errcode = W_ERROR_V(werr);
 
3098
 
 
3099
 out:
 
3100
        SSVAL(*rparam,0,errcode);
 
3101
        SSVAL(*rparam,2,0);             /* converter word */
 
3102
 
 
3103
        return(True);
 
3104
}
 
3105
 
 
3106
/****************************************************************************
 
3107
  set the property of a print job (undocumented?)
 
3108
  ? function = 0xb -> set name of print job
 
3109
  ? function = 0x6 -> move print job up/down
 
3110
  Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz> 
 
3111
  or   <WWsTP> <WB21BB16B10zWWzDDz> 
 
3112
****************************************************************************/
 
3113
 
 
3114
static int check_printjob_info(struct pack_desc* desc,
 
3115
                               int uLevel, char* id)
 
3116
{
 
3117
        desc->subformat = NULL;
 
3118
        switch( uLevel ) {
 
3119
        case 0: desc->format = "W"; break;
 
3120
        case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
 
3121
        case 2: desc->format = "WWzWWDDzz"; break;
 
3122
        case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
 
3123
        case 4: desc->format = "WWzWWDDzzzzzDDDDDDD"; break;
 
3124
        default:
 
3125
                DEBUG(0,("check_printjob_info: invalid level %d\n",
 
3126
                        uLevel ));
 
3127
                return False;
 
3128
        }
 
3129
        if (id == NULL || strcmp(desc->format,id) != 0) {
 
3130
                DEBUG(0,("check_printjob_info: invalid format %s\n",
 
3131
                        id ? id : "<NULL>" ));
 
3132
                return False;
 
3133
        }
 
3134
        return True;
 
3135
}
 
3136
 
 
3137
static bool api_PrintJobInfo(connection_struct *conn, uint16 vuid,
 
3138
                                char *param, int tpscnt,
 
3139
                                char *data, int tdscnt,
 
3140
                                int mdrcnt,int mprcnt,
 
3141
                                char **rdata,char **rparam,
 
3142
                                int *rdata_len,int *rparam_len)
 
3143
{
 
3144
        struct pack_desc desc;
 
3145
        char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
 
3146
        char *str2 = skip_string(param,tpscnt,str1);
 
3147
        char *p = skip_string(param,tpscnt,str2);
 
3148
        uint32 jobid;
 
3149
        fstring sharename;
 
3150
        int uLevel = get_safe_SVAL(param,tpscnt,p,2,-1);
 
3151
        int function = get_safe_SVAL(param,tpscnt,p,4,-1);
 
3152
        int place, errcode;
 
3153
 
 
3154
        if (!str1 || !str2 || !p) {
 
3155
                return False;
 
3156
        }
 
3157
        /*
 
3158
         * We use 1 here not 2 as we're checking
 
3159
         * the last byte we want to access is safe.
 
3160
         */
 
3161
        if (!is_offset_safe(param,tpscnt,p,1)) {
 
3162
                return False;
 
3163
        }
 
3164
        if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid))
 
3165
                return False;
 
3166
        *rparam_len = 4;
 
3167
        *rparam = smb_realloc_limit(*rparam,*rparam_len);
 
3168
        if (!*rparam) {
 
3169
                return False;
 
3170
        }
 
3171
 
 
3172
        if (!share_defined(sharename)) {
 
3173
                DEBUG(0,("api_PrintJobInfo: sharen [%s] not defined\n",
 
3174
                         sharename));
 
3175
                return False;
 
3176
        }
 
3177
 
 
3178
        *rdata_len = 0;
 
3179
 
 
3180
        /* check it's a supported varient */
 
3181
        if ((strcmp(str1,"WWsTP")) || 
 
3182
            (!check_printjob_info(&desc,uLevel,str2)))
 
3183
                return(False);
 
3184
 
 
3185
        if (!print_job_exists(sharename, jobid)) {
 
3186
                errcode=NERR_JobNotFound;
 
3187
                goto out;
 
3188
        }
 
3189
 
 
3190
        errcode = NERR_notsupported;
 
3191
 
 
3192
        switch (function) {
 
3193
        case 0x6:
 
3194
                /* change job place in the queue, 
 
3195
                   data gives the new place */
 
3196
                place = SVAL(data,0);
 
3197
                if (print_job_set_place(sharename, jobid, place)) {
 
3198
                        errcode=NERR_Success;
 
3199
                }
 
3200
                break;
 
3201
 
 
3202
        case 0xb:   
 
3203
                /* change print job name, data gives the name */
 
3204
                if (print_job_set_name(sharename, jobid, data)) {
 
3205
                        errcode=NERR_Success;
 
3206
                }
 
3207
                break;
 
3208
 
 
3209
        default:
 
3210
                return False;
 
3211
        }
 
3212
 
 
3213
 out:
 
3214
        SSVALS(*rparam,0,errcode);
 
3215
        SSVAL(*rparam,2,0);             /* converter word */
 
3216
 
 
3217
        return(True);
 
3218
}
 
3219
 
 
3220
 
 
3221
/****************************************************************************
 
3222
 Get info about the server.
 
3223
****************************************************************************/
 
3224
 
 
3225
static bool api_RNetServerGetInfo(connection_struct *conn,uint16 vuid,
 
3226
                                char *param, int tpscnt,
 
3227
                                char *data, int tdscnt,
 
3228
                                int mdrcnt,int mprcnt,
 
3229
                                char **rdata,char **rparam,
 
3230
                                int *rdata_len,int *rparam_len)
 
3231
{
 
3232
        char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
 
3233
        char *str2 = skip_string(param,tpscnt,str1);
 
3234
        char *p = skip_string(param,tpscnt,str2);
 
3235
        int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
 
3236
        char *p2;
 
3237
        int struct_len;
 
3238
 
 
3239
        if (!str1 || !str2 || !p) {
 
3240
                return False;
 
3241
        }
 
3242
 
 
3243
        DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
 
3244
 
 
3245
        /* check it's a supported varient */
 
3246
        if (!prefix_ok(str1,"WrLh")) {
 
3247
                return False;
 
3248
        }
 
3249
 
 
3250
        switch( uLevel ) {
 
3251
                case 0:
 
3252
                        if (strcmp(str2,"B16") != 0) {
 
3253
                                return False;
 
3254
                        }
 
3255
                        struct_len = 16;
 
3256
                        break;
 
3257
                case 1:
 
3258
                        if (strcmp(str2,"B16BBDz") != 0) {
 
3259
                                return False;
 
3260
                        }
 
3261
                        struct_len = 26;
 
3262
                        break;
 
3263
                case 2:
 
3264
                        if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")!= 0) {
 
3265
                                return False;
 
3266
                        }
 
3267
                        struct_len = 134;
 
3268
                        break;
 
3269
                case 3:
 
3270
                        if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz") != 0) {
 
3271
                                return False;
 
3272
                        }
 
3273
                        struct_len = 144;
 
3274
                        break;
 
3275
                case 20:
 
3276
                        if (strcmp(str2,"DN") != 0) {
 
3277
                                return False;
 
3278
                        }
 
3279
                        struct_len = 6;
 
3280
                        break;
 
3281
                case 50:
 
3282
                        if (strcmp(str2,"B16BBDzWWzzz") != 0) {
 
3283
                                return False;
 
3284
                        }
 
3285
                        struct_len = 42;
 
3286
                        break;
 
3287
                default:
 
3288
                        return False;
 
3289
        }
 
3290
 
 
3291
        *rdata_len = mdrcnt;
 
3292
        *rdata = smb_realloc_limit(*rdata,*rdata_len);
 
3293
        if (!*rdata) {
 
3294
                return False;
 
3295
        }
 
3296
 
 
3297
        p = *rdata;
 
3298
        p2 = p + struct_len;
 
3299
        if (uLevel != 20) {
 
3300
                srvstr_push(NULL, 0, p,global_myname(),16,
 
3301
                        STR_ASCII|STR_UPPER|STR_TERMINATE);
 
3302
        }
 
3303
        p += 16;
 
3304
        if (uLevel > 0) {
 
3305
                struct srv_info_struct *servers=NULL;
 
3306
                int i,count;
 
3307
                char *comment = NULL;
 
3308
                TALLOC_CTX *ctx = talloc_tos();
 
3309
                uint32 servertype= lp_default_server_announce();
 
3310
 
 
3311
                comment = talloc_strdup(ctx,lp_serverstring());
 
3312
                if (!comment) {
 
3313
                        return false;
 
3314
                }
 
3315
 
 
3316
                if ((count=get_server_info(SV_TYPE_ALL,&servers,lp_workgroup()))>0) {
 
3317
                        for (i=0;i<count;i++) {
 
3318
                                if (strequal(servers[i].name,global_myname())) {
 
3319
                                        servertype = servers[i].type;
 
3320
                                        TALLOC_FREE(comment);
 
3321
                                        comment = talloc_strdup(ctx,
 
3322
                                                        servers[i].comment);
 
3323
                                        if (comment) {
 
3324
                                                return false;
 
3325
                                        }
 
3326
                                }
 
3327
                        }
 
3328
                }
 
3329
 
 
3330
                SAFE_FREE(servers);
 
3331
 
 
3332
                SCVAL(p,0,lp_major_announce_version());
 
3333
                SCVAL(p,1,lp_minor_announce_version());
 
3334
                SIVAL(p,2,servertype);
 
3335
 
 
3336
                if (mdrcnt == struct_len) {
 
3337
                        SIVAL(p,6,0);
 
3338
                } else {
 
3339
                        SIVAL(p,6,PTR_DIFF(p2,*rdata));
 
3340
                        comment = talloc_sub_advanced(
 
3341
                                ctx,
 
3342
                                lp_servicename(SNUM(conn)),
 
3343
                                conn->server_info->unix_name,
 
3344
                                conn->connectpath,
 
3345
                                conn->server_info->utok.gid,
 
3346
                                conn->server_info->sanitized_username,
 
3347
                                pdb_get_domain(conn->server_info->sam_account),
 
3348
                                comment);
 
3349
                        if (comment) {
 
3350
                                return false;
 
3351
                        }
 
3352
                        if (mdrcnt - struct_len <= 0) {
 
3353
                                return false;
 
3354
                        }
 
3355
                        push_ascii(p2,
 
3356
                                comment,
 
3357
                                MIN(mdrcnt - struct_len,
 
3358
                                        MAX_SERVER_STRING_LENGTH),
 
3359
                                STR_TERMINATE);
 
3360
                        p2 = skip_string(*rdata,*rdata_len,p2);
 
3361
                        if (!p2) {
 
3362
                                return False;
 
3363
                        }
 
3364
                }
 
3365
        }
 
3366
 
 
3367
        if (uLevel > 1) {
 
3368
                return False;           /* not yet implemented */
 
3369
        }
 
3370
 
 
3371
        *rdata_len = PTR_DIFF(p2,*rdata);
 
3372
 
 
3373
        *rparam_len = 6;
 
3374
        *rparam = smb_realloc_limit(*rparam,*rparam_len);
 
3375
        if (!*rparam) {
 
3376
                return False;
 
3377
        }
 
3378
        SSVAL(*rparam,0,NERR_Success);
 
3379
        SSVAL(*rparam,2,0);             /* converter word */
 
3380
        SSVAL(*rparam,4,*rdata_len);
 
3381
 
 
3382
        return True;
 
3383
}
 
3384
 
 
3385
/****************************************************************************
 
3386
 Get info about the server.
 
3387
****************************************************************************/
 
3388
 
 
3389
static bool api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid,
 
3390
                                char *param, int tpscnt,
 
3391
                                char *data, int tdscnt,
 
3392
                                int mdrcnt,int mprcnt,
 
3393
                                char **rdata,char **rparam,
 
3394
                                int *rdata_len,int *rparam_len)
 
3395
{
 
3396
        char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
 
3397
        char *str2 = skip_string(param,tpscnt,str1);
 
3398
        char *p = skip_string(param,tpscnt,str2);
 
3399
        char *p2;
 
3400
        char *endp;
 
3401
        int level = get_safe_SVAL(param,tpscnt,p,0,-1);
 
3402
 
 
3403
        if (!str1 || !str2 || !p) {
 
3404
                return False;
 
3405
        }
 
3406
 
 
3407
        DEBUG(4,("NetWkstaGetInfo level %d\n",level));
 
3408
 
 
3409
        *rparam_len = 6;
 
3410
        *rparam = smb_realloc_limit(*rparam,*rparam_len);
 
3411
        if (!*rparam) {
 
3412
                return False;
 
3413
        }
 
3414
 
 
3415
        /* check it's a supported varient */
 
3416
        if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz"))) {
 
3417
                return False;
 
3418
        }
 
3419
 
 
3420
        *rdata_len = mdrcnt + 1024;
 
3421
        *rdata = smb_realloc_limit(*rdata,*rdata_len);
 
3422
        if (!*rdata) {
 
3423
                return False;
 
3424
        }
 
3425
 
 
3426
        SSVAL(*rparam,0,NERR_Success);
 
3427
        SSVAL(*rparam,2,0);             /* converter word */
 
3428
 
 
3429
        p = *rdata;
 
3430
        endp = *rdata + *rdata_len;
 
3431
 
 
3432
        p2 = get_safe_ptr(*rdata,*rdata_len,p,22);
 
3433
        if (!p2) {
 
3434
                return False;
 
3435
        }
 
3436
 
 
3437
        SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */
 
3438
        strlcpy(p2,get_local_machine_name(),PTR_DIFF(endp,p2));
 
3439
        strupper_m(p2);
 
3440
        p2 = skip_string(*rdata,*rdata_len,p2);
 
3441
        if (!p2) {
 
3442
                return False;
 
3443
        }
 
3444
        p += 4;
 
3445
 
 
3446
        SIVAL(p,0,PTR_DIFF(p2,*rdata));
 
3447
        strlcpy(p2,conn->server_info->sanitized_username,PTR_DIFF(endp,p2));
 
3448
        p2 = skip_string(*rdata,*rdata_len,p2);
 
3449
        if (!p2) {
 
3450
                return False;
 
3451
        }
 
3452
        p += 4;
 
3453
 
 
3454
        SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
 
3455
        strlcpy(p2,lp_workgroup(),PTR_DIFF(endp,p2));
 
3456
        strupper_m(p2);
 
3457
        p2 = skip_string(*rdata,*rdata_len,p2);
 
3458
        if (!p2) {
 
3459
                return False;
 
3460
        }
 
3461
        p += 4;
 
3462
 
 
3463
        SCVAL(p,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
 
3464
        SCVAL(p,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
 
3465
        p += 2;
 
3466
 
 
3467
        SIVAL(p,0,PTR_DIFF(p2,*rdata));
 
3468
        strlcpy(p2,lp_workgroup(),PTR_DIFF(endp,p2));   /* don't know.  login domain?? */
 
3469
        p2 = skip_string(*rdata,*rdata_len,p2);
 
3470
        if (!p2) {
 
3471
                return False;
 
3472
        }
 
3473
        p += 4;
 
3474
 
 
3475
        SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */
 
3476
        strlcpy(p2,"",PTR_DIFF(endp,p2));
 
3477
        p2 = skip_string(*rdata,*rdata_len,p2);
 
3478
        if (!p2) {
 
3479
                return False;
 
3480
        }
 
3481
        p += 4;
 
3482
 
 
3483
        *rdata_len = PTR_DIFF(p2,*rdata);
 
3484
 
 
3485
        SSVAL(*rparam,4,*rdata_len);
 
3486
 
 
3487
        return True;
 
3488
}
 
3489
 
 
3490
/****************************************************************************
 
3491
  get info about a user
 
3492
 
 
3493
    struct user_info_11 {
 
3494
        char                usri11_name[21];  0-20 
 
3495
        char                usri11_pad;       21 
 
3496
        char                *usri11_comment;  22-25 
 
3497
        char            *usri11_usr_comment;  26-29
 
3498
        unsigned short      usri11_priv;      30-31
 
3499
        unsigned long       usri11_auth_flags; 32-35
 
3500
        long                usri11_password_age; 36-39
 
3501
        char                *usri11_homedir; 40-43
 
3502
        char            *usri11_parms; 44-47
 
3503
        long                usri11_last_logon; 48-51
 
3504
        long                usri11_last_logoff; 52-55
 
3505
        unsigned short      usri11_bad_pw_count; 56-57
 
3506
        unsigned short      usri11_num_logons; 58-59
 
3507
        char                *usri11_logon_server; 60-63
 
3508
        unsigned short      usri11_country_code; 64-65
 
3509
        char            *usri11_workstations; 66-69
 
3510
        unsigned long       usri11_max_storage; 70-73
 
3511
        unsigned short      usri11_units_per_week; 74-75
 
3512
        unsigned char       *usri11_logon_hours; 76-79
 
3513
        unsigned short      usri11_code_page; 80-81
 
3514
    };
 
3515
 
 
3516
where:
 
3517
 
 
3518
  usri11_name specifies the user name for which information is retrieved
 
3519
 
 
3520
  usri11_pad aligns the next data structure element to a word boundary
 
3521
 
 
3522
  usri11_comment is a null terminated ASCII comment
 
3523
 
 
3524
  usri11_user_comment is a null terminated ASCII comment about the user
 
3525
 
 
3526
  usri11_priv specifies the level of the privilege assigned to the user.
 
3527
       The possible values are:
 
3528
 
 
3529
Name             Value  Description
 
3530
USER_PRIV_GUEST  0      Guest privilege
 
3531
USER_PRIV_USER   1      User privilege
 
3532
USER_PRV_ADMIN   2      Administrator privilege
 
3533
 
 
3534
  usri11_auth_flags specifies the account operator privileges. The
 
3535
       possible values are:
 
3536
 
 
3537
Name            Value   Description
 
3538
AF_OP_PRINT     0       Print operator
 
3539
 
 
3540
 
 
3541
Leach, Naik                                        [Page 28]
 
3542
 
 
3543
 
 
3544
 
 
3545
INTERNET-DRAFT   CIFS Remote Admin Protocol     January 10, 1997
 
3546
 
 
3547
 
 
3548
AF_OP_COMM      1       Communications operator
 
3549
AF_OP_SERVER    2       Server operator
 
3550
AF_OP_ACCOUNTS  3       Accounts operator
 
3551
 
 
3552
 
 
3553
  usri11_password_age specifies how many seconds have elapsed since the
 
3554
       password was last changed.
 
3555
 
 
3556
  usri11_home_dir points to a null terminated ASCII string that contains
 
3557
       the path name of the user's home directory.
 
3558
 
 
3559
  usri11_parms points to a null terminated ASCII string that is set
 
3560
       aside for use by applications.
 
3561
 
 
3562
  usri11_last_logon specifies the time when the user last logged on.
 
3563
       This value is stored as the number of seconds elapsed since
 
3564
       00:00:00, January 1, 1970.
 
3565
 
 
3566
  usri11_last_logoff specifies the time when the user last logged off.
 
3567
       This value is stored as the number of seconds elapsed since
 
3568
       00:00:00, January 1, 1970. A value of 0 means the last logoff
 
3569
       time is unknown.
 
3570
 
 
3571
  usri11_bad_pw_count specifies the number of incorrect passwords
 
3572
       entered since the last successful logon.
 
3573
 
 
3574
  usri11_log1_num_logons specifies the number of times this user has
 
3575
       logged on. A value of -1 means the number of logons is unknown.
 
3576
 
 
3577
  usri11_logon_server points to a null terminated ASCII string that
 
3578
       contains the name of the server to which logon requests are sent.
 
3579
       A null string indicates logon requests should be sent to the
 
3580
       domain controller.
 
3581
 
 
3582
  usri11_country_code specifies the country code for the user's language
 
3583
       of choice.
 
3584
 
 
3585
  usri11_workstations points to a null terminated ASCII string that
 
3586
       contains the names of workstations the user may log on from.
 
3587
       There may be up to 8 workstations, with the names separated by
 
3588
       commas. A null strings indicates there are no restrictions.
 
3589
 
 
3590
  usri11_max_storage specifies the maximum amount of disk space the user
 
3591
       can occupy. A value of 0xffffffff indicates there are no
 
3592
       restrictions.
 
3593
 
 
3594
  usri11_units_per_week specifies the equal number of time units into
 
3595
       which a week is divided. This value must be equal to 168.
 
3596
 
 
3597
  usri11_logon_hours points to a 21 byte (168 bits) string that
 
3598
       specifies the time during which the user can log on. Each bit
 
3599
       represents one unique hour in a week. The first bit (bit 0, word
 
3600
       0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
 
3601
 
 
3602
 
 
3603
 
 
3604
Leach, Naik                                        [Page 29]
 
3605
 
 
3606
 
 
3607
 
 
3608
INTERNET-DRAFT   CIFS Remote Admin Protocol     January 10, 1997
 
3609
 
 
3610
 
 
3611
       Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
 
3612
       are no restrictions.
 
3613
 
 
3614
  usri11_code_page specifies the code page for the user's language of
 
3615
       choice
 
3616
 
 
3617
All of the pointers in this data structure need to be treated
 
3618
specially. The  pointer is a 32 bit pointer. The higher 16 bits need
 
3619
to be ignored. The converter word returned in the parameters section
 
3620
needs to be subtracted from the lower 16 bits to calculate an offset
 
3621
into the return buffer where this ASCII string resides.
 
3622
 
 
3623
There is no auxiliary data in the response.
 
3624
 
 
3625
  ****************************************************************************/
 
3626
 
 
3627
#define usri11_name           0 
 
3628
#define usri11_pad            21
 
3629
#define usri11_comment        22
 
3630
#define usri11_usr_comment    26
 
3631
#define usri11_full_name      30
 
3632
#define usri11_priv           34
 
3633
#define usri11_auth_flags     36
 
3634
#define usri11_password_age   40
 
3635
#define usri11_homedir        44
 
3636
#define usri11_parms          48
 
3637
#define usri11_last_logon     52
 
3638
#define usri11_last_logoff    56
 
3639
#define usri11_bad_pw_count   60
 
3640
#define usri11_num_logons     62
 
3641
#define usri11_logon_server   64
 
3642
#define usri11_country_code   68
 
3643
#define usri11_workstations   70
 
3644
#define usri11_max_storage    74
 
3645
#define usri11_units_per_week 78
 
3646
#define usri11_logon_hours    80
 
3647
#define usri11_code_page      84
 
3648
#define usri11_end            86
 
3649
 
 
3650
#define USER_PRIV_GUEST 0
 
3651
#define USER_PRIV_USER 1
 
3652
#define USER_PRIV_ADMIN 2
 
3653
 
 
3654
#define AF_OP_PRINT     0 
 
3655
#define AF_OP_COMM      1
 
3656
#define AF_OP_SERVER    2
 
3657
#define AF_OP_ACCOUNTS  3
 
3658
 
 
3659
 
 
3660
static bool api_RNetUserGetInfo(connection_struct *conn, uint16 vuid,
 
3661
                                char *param, int tpscnt,
 
3662
                                char *data, int tdscnt,
 
3663
                                int mdrcnt,int mprcnt,
 
3664
                                char **rdata,char **rparam,
 
3665
                                int *rdata_len,int *rparam_len)
 
3666
{
 
3667
        char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
 
3668
        char *str2 = skip_string(param,tpscnt,str1);
 
3669
        char *UserName = skip_string(param,tpscnt,str2);
 
3670
        char *p = skip_string(param,tpscnt,UserName);
 
3671
        int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
 
3672
        char *p2;
 
3673
        char *endp;
 
3674
        const char *level_string;
 
3675
 
 
3676
        /* get NIS home of a previously validated user - simeon */
 
3677
        /* With share level security vuid will always be zero.
 
3678
           Don't depend on vuser being non-null !!. JRA */
 
3679
        user_struct *vuser = get_valid_user_struct(vuid);
 
3680
        if(vuser != NULL) {
 
3681
                DEBUG(3,("  Username of UID %d is %s\n",
 
3682
                         (int)vuser->server_info->utok.uid,
 
3683
                         vuser->server_info->unix_name));
 
3684
        }
 
3685
 
 
3686
        if (!str1 || !str2 || !UserName || !p) {
 
3687
                return False;
 
3688
        }
 
3689
 
 
3690
        *rparam_len = 6;
 
3691
        *rparam = smb_realloc_limit(*rparam,*rparam_len);
 
3692
        if (!*rparam) {
 
3693
                return False;
 
3694
        }
 
3695
 
 
3696
        DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel));
 
3697
 
 
3698
        /* check it's a supported variant */
 
3699
        if (strcmp(str1,"zWrLh") != 0) {
 
3700
                return False;
 
3701
        }
 
3702
        switch( uLevel ) {
 
3703
                case 0: level_string = "B21"; break;
 
3704
                case 1: level_string = "B21BB16DWzzWz"; break;
 
3705
                case 2: level_string = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
 
3706
                case 10: level_string = "B21Bzzz"; break;
 
3707
                case 11: level_string = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
 
3708
                default: return False;
 
3709
        }
 
3710
 
 
3711
        if (strcmp(level_string,str2) != 0) {
 
3712
                return False;
 
3713
        }
 
3714
 
 
3715
        *rdata_len = mdrcnt + 1024;
 
3716
        *rdata = smb_realloc_limit(*rdata,*rdata_len);
 
3717
        if (!*rdata) {
 
3718
                return False;
 
3719
        }
 
3720
 
 
3721
        SSVAL(*rparam,0,NERR_Success);
 
3722
        SSVAL(*rparam,2,0);             /* converter word */
 
3723
 
 
3724
        p = *rdata;
 
3725
        endp = *rdata + *rdata_len;
 
3726
        p2 = get_safe_ptr(*rdata,*rdata_len,p,usri11_end);
 
3727
        if (!p2) {
 
3728
                return False;
 
3729
        }
 
3730
 
 
3731
        memset(p,0,21);
 
3732
        fstrcpy(p+usri11_name,UserName); /* 21 bytes - user name */
 
3733
 
 
3734
        if (uLevel > 0) {
 
3735
                SCVAL(p,usri11_pad,0); /* padding - 1 byte */
 
3736
                *p2 = 0;
 
3737
        }
 
3738
 
 
3739
        if (uLevel >= 10) {
 
3740
                SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */
 
3741
                strlcpy(p2,"Comment",PTR_DIFF(endp,p2));
 
3742
                p2 = skip_string(*rdata,*rdata_len,p2);
 
3743
                if (!p2) {
 
3744
                        return False;
 
3745
                }
 
3746
 
 
3747
                SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */
 
3748
                strlcpy(p2,"UserComment",PTR_DIFF(endp,p2));
 
3749
                p2 = skip_string(*rdata,*rdata_len,p2);
 
3750
                if (!p2) {
 
3751
                        return False;
 
3752
                }
 
3753
 
 
3754
                /* EEK! the cifsrap.txt doesn't have this in!!!! */
 
3755
                SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */
 
3756
                strlcpy(p2,((vuser != NULL)
 
3757
                            ? pdb_get_fullname(vuser->server_info->sam_account)
 
3758
                            : UserName),PTR_DIFF(endp,p2));
 
3759
                p2 = skip_string(*rdata,*rdata_len,p2);
 
3760
                if (!p2) {
 
3761
                        return False;
 
3762
                }
 
3763
        }
 
3764
 
 
3765
        if (uLevel == 11) {
 
3766
                const char *homedir = "";
 
3767
                if (vuser != NULL) {
 
3768
                        homedir = pdb_get_homedir(
 
3769
                                vuser->server_info->sam_account);
 
3770
                }
 
3771
                /* modelled after NTAS 3.51 reply */
 
3772
                SSVAL(p,usri11_priv,conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER); 
 
3773
                SIVAL(p,usri11_auth_flags,AF_OP_PRINT);         /* auth flags */
 
3774
                SIVALS(p,usri11_password_age,-1);               /* password age */
 
3775
                SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */
 
3776
                strlcpy(p2, homedir, PTR_DIFF(endp,p2));
 
3777
                p2 = skip_string(*rdata,*rdata_len,p2);
 
3778
                if (!p2) {
 
3779
                        return False;
 
3780
                }
 
3781
                SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */
 
3782
                strlcpy(p2,"",PTR_DIFF(endp,p2));
 
3783
                p2 = skip_string(*rdata,*rdata_len,p2);
 
3784
                if (!p2) {
 
3785
                        return False;
 
3786
                }
 
3787
                SIVAL(p,usri11_last_logon,0);           /* last logon */
 
3788
                SIVAL(p,usri11_last_logoff,0);          /* last logoff */
 
3789
                SSVALS(p,usri11_bad_pw_count,-1);       /* bad pw counts */
 
3790
                SSVALS(p,usri11_num_logons,-1);         /* num logons */
 
3791
                SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */
 
3792
                strlcpy(p2,"\\\\*",PTR_DIFF(endp,p2));
 
3793
                p2 = skip_string(*rdata,*rdata_len,p2);
 
3794
                if (!p2) {
 
3795
                        return False;
 
3796
                }
 
3797
                SSVAL(p,usri11_country_code,0);         /* country code */
 
3798
 
 
3799
                SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */
 
3800
                strlcpy(p2,"",PTR_DIFF(endp,p2));
 
3801
                p2 = skip_string(*rdata,*rdata_len,p2);
 
3802
                if (!p2) {
 
3803
                        return False;
 
3804
                }
 
3805
 
 
3806
                SIVALS(p,usri11_max_storage,-1);                /* max storage */
 
3807
                SSVAL(p,usri11_units_per_week,168);             /* units per week */
 
3808
                SIVAL(p,usri11_logon_hours,PTR_DIFF(p2,p)); /* logon hours */
 
3809
 
 
3810
                /* a simple way to get logon hours at all times. */
 
3811
                memset(p2,0xff,21);
 
3812
                SCVAL(p2,21,0);           /* fix zero termination */
 
3813
                p2 = skip_string(*rdata,*rdata_len,p2);
 
3814
                if (!p2) {
 
3815
                        return False;
 
3816
                }
 
3817
 
 
3818
                SSVAL(p,usri11_code_page,0);            /* code page */
 
3819
        }
 
3820
 
 
3821
        if (uLevel == 1 || uLevel == 2) {
 
3822
                memset(p+22,' ',16);    /* password */
 
3823
                SIVALS(p,38,-1);                /* password age */
 
3824
                SSVAL(p,42,
 
3825
                conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
 
3826
                SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
 
3827
                strlcpy(p2, vuser ? pdb_get_homedir(
 
3828
                                vuser->server_info->sam_account) : "",
 
3829
                        PTR_DIFF(endp,p2));
 
3830
                p2 = skip_string(*rdata,*rdata_len,p2);
 
3831
                if (!p2) {
 
3832
                        return False;
 
3833
                }
 
3834
                SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
 
3835
                *p2++ = 0;
 
3836
                SSVAL(p,52,0);          /* flags */
 
3837
                SIVAL(p,54,PTR_DIFF(p2,*rdata));                /* script_path */
 
3838
                strlcpy(p2, vuser ? pdb_get_logon_script(
 
3839
                                vuser->server_info->sam_account) : "",
 
3840
                        PTR_DIFF(endp,p2));
 
3841
                p2 = skip_string(*rdata,*rdata_len,p2);
 
3842
                if (!p2) {
 
3843
                        return False;
 
3844
                }
 
3845
                if (uLevel == 2) {
 
3846
                        SIVAL(p,60,0);          /* auth_flags */
 
3847
                        SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
 
3848
                        strlcpy(p2,((vuser != NULL)
 
3849
                                    ? pdb_get_fullname(vuser->server_info->sam_account)
 
3850
                                    : UserName),PTR_DIFF(endp,p2));
 
3851
                        p2 = skip_string(*rdata,*rdata_len,p2);
 
3852
                        if (!p2) {
 
3853
                                return False;
 
3854
                        }
 
3855
                        SIVAL(p,68,0);          /* urs_comment */
 
3856
                        SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
 
3857
                        strlcpy(p2,"",PTR_DIFF(endp,p2));
 
3858
                        p2 = skip_string(*rdata,*rdata_len,p2);
 
3859
                        if (!p2) {
 
3860
                                return False;
 
3861
                        }
 
3862
                        SIVAL(p,76,0);          /* workstations */
 
3863
                        SIVAL(p,80,0);          /* last_logon */
 
3864
                        SIVAL(p,84,0);          /* last_logoff */
 
3865
                        SIVALS(p,88,-1);                /* acct_expires */
 
3866
                        SIVALS(p,92,-1);                /* max_storage */
 
3867
                        SSVAL(p,96,168);        /* units_per_week */
 
3868
                        SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
 
3869
                        memset(p2,-1,21);
 
3870
                        p2 += 21;
 
3871
                        SSVALS(p,102,-1);       /* bad_pw_count */
 
3872
                        SSVALS(p,104,-1);       /* num_logons */
 
3873
                        SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
 
3874
                        {
 
3875
                                TALLOC_CTX *ctx = talloc_tos();
 
3876
                                int space_rem = *rdata_len - (p2 - *rdata);
 
3877
                                char *tmp;
 
3878
 
 
3879
                                if (space_rem <= 0) {
 
3880
                                        return false;
 
3881
                                }
 
3882
                                tmp = talloc_strdup(ctx, "\\\\%L");
 
3883
                                if (!tmp) {
 
3884
                                        return false;
 
3885
                                }
 
3886
                                tmp = talloc_sub_basic(ctx,
 
3887
                                                "",
 
3888
                                                "",
 
3889
                                                tmp);
 
3890
                                if (!tmp) {
 
3891
                                        return false;
 
3892
                                }
 
3893
 
 
3894
                                push_ascii(p2,
 
3895
                                        tmp,
 
3896
                                        space_rem,
 
3897
                                        STR_TERMINATE);
 
3898
                        }
 
3899
                        p2 = skip_string(*rdata,*rdata_len,p2);
 
3900
                        if (!p2) {
 
3901
                                return False;
 
3902
                        }
 
3903
                        SSVAL(p,110,49);        /* country_code */
 
3904
                        SSVAL(p,112,860);       /* code page */
 
3905
                }
 
3906
        }
 
3907
 
 
3908
        *rdata_len = PTR_DIFF(p2,*rdata);
 
3909
 
 
3910
        SSVAL(*rparam,4,*rdata_len);    /* is this right?? */
 
3911
 
 
3912
        return(True);
 
3913
}
 
3914
 
 
3915
static bool api_WWkstaUserLogon(connection_struct *conn,uint16 vuid,
 
3916
                                char *param, int tpscnt,
 
3917
                                char *data, int tdscnt,
 
3918
                                int mdrcnt,int mprcnt,
 
3919
                                char **rdata,char **rparam,
 
3920
                                int *rdata_len,int *rparam_len)
 
3921
{
 
3922
        char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
 
3923
        char *str2 = skip_string(param,tpscnt,str1);
 
3924
        char *p = skip_string(param,tpscnt,str2);
 
3925
        int uLevel;
 
3926
        struct pack_desc desc;
 
3927
        char* name;
 
3928
                /* With share level security vuid will always be zero.
 
3929
                   Don't depend on vuser being non-null !!. JRA */
 
3930
        user_struct *vuser = get_valid_user_struct(vuid);
 
3931
 
 
3932
        if (!str1 || !str2 || !p) {
 
3933
                return False;
 
3934
        }
 
3935
 
 
3936
        if(vuser != NULL) {
 
3937
                DEBUG(3,("  Username of UID %d is %s\n",
 
3938
                         (int)vuser->server_info->utok.uid,
 
3939
                         vuser->server_info->unix_name));
 
3940
        }
 
3941
 
 
3942
        uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
 
3943
        name = get_safe_str_ptr(param,tpscnt,p,2);
 
3944
        if (!name) {
 
3945
                return False;
 
3946
        }
 
3947
 
 
3948
        memset((char *)&desc,'\0',sizeof(desc));
 
3949
 
 
3950
        DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
 
3951
 
 
3952
        /* check it's a supported varient */
 
3953
        if (strcmp(str1,"OOWb54WrLh") != 0) {
 
3954
                return False;
 
3955
        }
 
3956
        if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) {
 
3957
                return False;
 
3958
        }
 
3959
        if (mdrcnt > 0) {
 
3960
                *rdata = smb_realloc_limit(*rdata,mdrcnt);
 
3961
                if (!*rdata) {
 
3962
                        return False;
 
3963
                }
 
3964
        }
 
3965
 
 
3966
        desc.base = *rdata;
 
3967
        desc.buflen = mdrcnt;
 
3968
        desc.subformat = NULL;
 
3969
        desc.format = str2;
 
3970
 
 
3971
        if (init_package(&desc,1,0)) {
 
3972
                PACKI(&desc,"W",0);             /* code */
 
3973
                PACKS(&desc,"B21",name);        /* eff. name */
 
3974
                PACKS(&desc,"B","");            /* pad */
 
3975
                PACKI(&desc,"W", conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
 
3976
                PACKI(&desc,"D",0);             /* auth flags XXX */
 
3977
                PACKI(&desc,"W",0);             /* num logons */
 
3978
                PACKI(&desc,"W",0);             /* bad pw count */
 
3979
                PACKI(&desc,"D",0);             /* last logon */
 
3980
                PACKI(&desc,"D",-1);            /* last logoff */
 
3981
                PACKI(&desc,"D",-1);            /* logoff time */
 
3982
                PACKI(&desc,"D",-1);            /* kickoff time */
 
3983
                PACKI(&desc,"D",0);             /* password age */
 
3984
                PACKI(&desc,"D",0);             /* password can change */
 
3985
                PACKI(&desc,"D",-1);            /* password must change */
 
3986
 
 
3987
                {
 
3988
                        fstring mypath;
 
3989
                        fstrcpy(mypath,"\\\\");
 
3990
                        fstrcat(mypath,get_local_machine_name());
 
3991
                        strupper_m(mypath);
 
3992
                        PACKS(&desc,"z",mypath); /* computer */
 
3993
                }
 
3994
 
 
3995
                PACKS(&desc,"z",lp_workgroup());/* domain */
 
3996
                PACKS(&desc,"z", vuser ? pdb_get_logon_script(
 
3997
                              vuser->server_info->sam_account) : ""); /* script path */
 
3998
                PACKI(&desc,"D",0x00000000);            /* reserved */
 
3999
        }
 
4000
 
 
4001
        *rdata_len = desc.usedlen;
 
4002
        *rparam_len = 6;
 
4003
        *rparam = smb_realloc_limit(*rparam,*rparam_len);
 
4004
        if (!*rparam) {
 
4005
                return False;
 
4006
        }
 
4007
        SSVALS(*rparam,0,desc.errcode);
 
4008
        SSVAL(*rparam,2,0);
 
4009
        SSVAL(*rparam,4,desc.neededlen);
 
4010
 
 
4011
        DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
 
4012
 
 
4013
        return True;
 
4014
}
 
4015
 
 
4016
/****************************************************************************
 
4017
 api_WAccessGetUserPerms
 
4018
****************************************************************************/
 
4019
 
 
4020
static bool api_WAccessGetUserPerms(connection_struct *conn,uint16 vuid,
 
4021
                                char *param, int tpscnt,
 
4022
                                char *data, int tdscnt,
 
4023
                                int mdrcnt,int mprcnt,
 
4024
                                char **rdata,char **rparam,
 
4025
                                int *rdata_len,int *rparam_len)
 
4026
{
 
4027
        char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
 
4028
        char *str2 = skip_string(param,tpscnt,str1);
 
4029
        char *user = skip_string(param,tpscnt,str2);
 
4030
        char *resource = skip_string(param,tpscnt,user);
 
4031
 
 
4032
        if (!str1 || !str2 || !user || !resource) {
 
4033
                return False;
 
4034
        }
 
4035
 
 
4036
        if (skip_string(param,tpscnt,resource) == NULL) {
 
4037
                return False;
 
4038
        }
 
4039
        DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
 
4040
 
 
4041
        /* check it's a supported varient */
 
4042
        if (strcmp(str1,"zzh") != 0) {
 
4043
                return False;
 
4044
        }
 
4045
        if (strcmp(str2,"") != 0) {
 
4046
                return False;
 
4047
        }
 
4048
 
 
4049
        *rparam_len = 6;
 
4050
        *rparam = smb_realloc_limit(*rparam,*rparam_len);
 
4051
        if (!*rparam) {
 
4052
                return False;
 
4053
        }
 
4054
        SSVALS(*rparam,0,0);            /* errorcode */
 
4055
        SSVAL(*rparam,2,0);             /* converter word */
 
4056
        SSVAL(*rparam,4,0x7f);  /* permission flags */
 
4057
 
 
4058
        return True;
 
4059
}
 
4060
 
 
4061
/****************************************************************************
 
4062
  api_WPrintJobEnumerate
 
4063
  ****************************************************************************/
 
4064
 
 
4065
static bool api_WPrintJobGetInfo(connection_struct *conn, uint16 vuid,
 
4066
                                char *param, int tpscnt,
 
4067
                                char *data, int tdscnt,
 
4068
                                int mdrcnt,int mprcnt,
 
4069
                                char **rdata,char **rparam,
 
4070
                                int *rdata_len,int *rparam_len)
 
4071
{
 
4072
        char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
 
4073
        char *str2 = skip_string(param,tpscnt,str1);
 
4074
        char *p = skip_string(param,tpscnt,str2);
 
4075
        int uLevel;
 
4076
        int count;
 
4077
        int i;
 
4078
        int snum;
 
4079
        fstring sharename;
 
4080
        uint32 jobid;
 
4081
        struct pack_desc desc;
 
4082
        print_queue_struct *queue=NULL;
 
4083
        print_status_struct status;
 
4084
        char *tmpdata=NULL;
 
4085
 
 
4086
        if (!str1 || !str2 || !p) {
 
4087
                return False;
 
4088
        }
 
4089
 
 
4090
        uLevel = get_safe_SVAL(param,tpscnt,p,2,-1);
 
4091
 
 
4092
        memset((char *)&desc,'\0',sizeof(desc));
 
4093
        memset((char *)&status,'\0',sizeof(status));
 
4094
 
 
4095
        DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,SVAL(p,0)));
 
4096
 
 
4097
        /* check it's a supported varient */
 
4098
        if (strcmp(str1,"WWrLh") != 0) {
 
4099
                return False;
 
4100
        }
 
4101
        if (!check_printjob_info(&desc,uLevel,str2)) {
 
4102
                return False;
 
4103
        }
 
4104
 
 
4105
        if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid)) {
 
4106
                return False;
 
4107
        }
 
4108
 
 
4109
        snum = lp_servicenumber( sharename);
 
4110
        if (snum < 0 || !VALID_SNUM(snum)) {
 
4111
                return(False);
 
4112
        }
 
4113
 
 
4114
        count = print_queue_status(snum,&queue,&status);
 
4115
        for (i = 0; i < count; i++) {
 
4116
                if (queue[i].job == jobid) {
 
4117
                        break;
 
4118
                }
 
4119
        }
 
4120
 
 
4121
        if (mdrcnt > 0) {
 
4122
                *rdata = smb_realloc_limit(*rdata,mdrcnt);
 
4123
                if (!*rdata) {
 
4124
                        return False;
 
4125
                }
 
4126
                desc.base = *rdata;
 
4127
                desc.buflen = mdrcnt;
 
4128
        } else {
 
4129
                /*
 
4130
                 * Don't return data but need to get correct length
 
4131
                 *  init_package will return wrong size if buflen=0
 
4132
                 */
 
4133
                desc.buflen = getlen(desc.format);
 
4134
                desc.base = tmpdata = (char *)SMB_MALLOC( desc.buflen );
 
4135
        }
 
4136
 
 
4137
        if (init_package(&desc,1,0)) {
 
4138
                if (i < count) {
 
4139
                        fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
 
4140
                        *rdata_len = desc.usedlen;
 
4141
                } else {
 
4142
                        desc.errcode = NERR_JobNotFound;
 
4143
                        *rdata_len = 0;
 
4144
                }
 
4145
        }
 
4146
 
 
4147
        *rparam_len = 6;
 
4148
        *rparam = smb_realloc_limit(*rparam,*rparam_len);
 
4149
        if (!*rparam) {
 
4150
                return False;
 
4151
        }
 
4152
        SSVALS(*rparam,0,desc.errcode);
 
4153
        SSVAL(*rparam,2,0);
 
4154
        SSVAL(*rparam,4,desc.neededlen);
 
4155
 
 
4156
        SAFE_FREE(queue);
 
4157
        SAFE_FREE(tmpdata);
 
4158
 
 
4159
        DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
 
4160
 
 
4161
        return True;
 
4162
}
 
4163
 
 
4164
static bool api_WPrintJobEnumerate(connection_struct *conn, uint16 vuid,
 
4165
                                char *param, int tpscnt,
 
4166
                                char *data, int tdscnt,
 
4167
                                int mdrcnt,int mprcnt,
 
4168
                                char **rdata,char **rparam,
 
4169
                                int *rdata_len,int *rparam_len)
 
4170
{
 
4171
        char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
 
4172
        char *str2 = skip_string(param,tpscnt,str1);
 
4173
        char *p = skip_string(param,tpscnt,str2);
 
4174
        char *name = p;
 
4175
        int uLevel;
 
4176
        int count;
 
4177
        int i, succnt=0;
 
4178
        int snum;
 
4179
        struct pack_desc desc;
 
4180
        print_queue_struct *queue=NULL;
 
4181
        print_status_struct status;
 
4182
 
 
4183
        if (!str1 || !str2 || !p) {
 
4184
                return False;
 
4185
        }
 
4186
 
 
4187
        memset((char *)&desc,'\0',sizeof(desc));
 
4188
        memset((char *)&status,'\0',sizeof(status));
 
4189
 
 
4190
        p = skip_string(param,tpscnt,p);
 
4191
        if (!p) {
 
4192
                return False;
 
4193
        }
 
4194
        uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
 
4195
 
 
4196
        DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
 
4197
 
 
4198
        /* check it's a supported variant */
 
4199
        if (strcmp(str1,"zWrLeh") != 0) {
 
4200
                return False;
 
4201
        }
 
4202
 
 
4203
        if (uLevel > 2) {
 
4204
                return False;   /* defined only for uLevel 0,1,2 */
 
4205
        }
 
4206
 
 
4207
        if (!check_printjob_info(&desc,uLevel,str2)) { 
 
4208
                return False;
 
4209
        }
 
4210
 
 
4211
        snum = find_service(name);
 
4212
        if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) ) {
 
4213
                return False;
 
4214
        }
 
4215
 
 
4216
        count = print_queue_status(snum,&queue,&status);
 
4217
        if (mdrcnt > 0) {
 
4218
                *rdata = smb_realloc_limit(*rdata,mdrcnt);
 
4219
                if (!*rdata) {
 
4220
                        return False;
 
4221
                }
 
4222
        }
 
4223
        desc.base = *rdata;
 
4224
        desc.buflen = mdrcnt;
 
4225
 
 
4226
        if (init_package(&desc,count,0)) {
 
4227
                succnt = 0;
 
4228
                for (i = 0; i < count; i++) {
 
4229
                        fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
 
4230
                        if (desc.errcode == NERR_Success) {
 
4231
                                succnt = i+1;
 
4232
                        }
 
4233
                }
 
4234
        }
 
4235
 
 
4236
        *rdata_len = desc.usedlen;
 
4237
 
 
4238
        *rparam_len = 8;
 
4239
        *rparam = smb_realloc_limit(*rparam,*rparam_len);
 
4240
        if (!*rparam) {
 
4241
                return False;
 
4242
        }
 
4243
        SSVALS(*rparam,0,desc.errcode);
 
4244
        SSVAL(*rparam,2,0);
 
4245
        SSVAL(*rparam,4,succnt);
 
4246
        SSVAL(*rparam,6,count);
 
4247
 
 
4248
        SAFE_FREE(queue);
 
4249
 
 
4250
        DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
 
4251
 
 
4252
        return True;
 
4253
}
 
4254
 
 
4255
static int check_printdest_info(struct pack_desc* desc,
 
4256
                                int uLevel, char* id)
 
4257
{
 
4258
        desc->subformat = NULL;
 
4259
        switch( uLevel ) {
 
4260
                case 0:
 
4261
                        desc->format = "B9";
 
4262
                        break;
 
4263
                case 1:
 
4264
                        desc->format = "B9B21WWzW";
 
4265
                        break;
 
4266
                case 2:
 
4267
                        desc->format = "z";
 
4268
                        break;
 
4269
                case 3:
 
4270
                        desc->format = "zzzWWzzzWW";
 
4271
                        break;
 
4272
                default:
 
4273
                        DEBUG(0,("check_printdest_info: invalid level %d\n",
 
4274
                                uLevel));
 
4275
                        return False;
 
4276
        }
 
4277
        if (id == NULL || strcmp(desc->format,id) != 0) {
 
4278
                DEBUG(0,("check_printdest_info: invalid string %s\n", 
 
4279
                        id ? id : "<NULL>" ));
 
4280
                return False;
 
4281
        }
 
4282
        return True;
 
4283
}
 
4284
 
 
4285
static void fill_printdest_info(connection_struct *conn, int snum, int uLevel,
 
4286
                                struct pack_desc* desc)
 
4287
{
 
4288
        char buf[100];
 
4289
 
 
4290
        strncpy(buf,SERVICE(snum),sizeof(buf)-1);
 
4291
        buf[sizeof(buf)-1] = 0;
 
4292
        strupper_m(buf);
 
4293
 
 
4294
        if (uLevel <= 1) {
 
4295
                PACKS(desc,"B9",buf);   /* szName */
 
4296
                if (uLevel == 1) {
 
4297
                        PACKS(desc,"B21","");   /* szUserName */
 
4298
                        PACKI(desc,"W",0);              /* uJobId */
 
4299
                        PACKI(desc,"W",0);              /* fsStatus */
 
4300
                        PACKS(desc,"z","");     /* pszStatus */
 
4301
                        PACKI(desc,"W",0);              /* time */
 
4302
                }
 
4303
        }
 
4304
 
 
4305
        if (uLevel == 2 || uLevel == 3) {
 
4306
                PACKS(desc,"z",buf);            /* pszPrinterName */
 
4307
                if (uLevel == 3) {
 
4308
                        PACKS(desc,"z","");     /* pszUserName */
 
4309
                        PACKS(desc,"z","");     /* pszLogAddr */
 
4310
                        PACKI(desc,"W",0);              /* uJobId */
 
4311
                        PACKI(desc,"W",0);              /* fsStatus */
 
4312
                        PACKS(desc,"z","");     /* pszStatus */
 
4313
                        PACKS(desc,"z","");     /* pszComment */
 
4314
                        PACKS(desc,"z","NULL"); /* pszDrivers */
 
4315
                        PACKI(desc,"W",0);              /* time */
 
4316
                        PACKI(desc,"W",0);              /* pad1 */
 
4317
                }
 
4318
        }
 
4319
}
 
4320
 
 
4321
static bool api_WPrintDestGetInfo(connection_struct *conn, uint16 vuid,
 
4322
                                char *param, int tpscnt,
 
4323
                                char *data, int tdscnt,
 
4324
                                int mdrcnt,int mprcnt,
 
4325
                                char **rdata,char **rparam,
 
4326
                                int *rdata_len,int *rparam_len)
 
4327
{
 
4328
        char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
 
4329
        char *str2 = skip_string(param,tpscnt,str1);
 
4330
        char *p = skip_string(param,tpscnt,str2);
 
4331
        char* PrinterName = p;
 
4332
        int uLevel;
 
4333
        struct pack_desc desc;
 
4334
        int snum;
 
4335
        char *tmpdata=NULL;
 
4336
 
 
4337
        if (!str1 || !str2 || !p) {
 
4338
                return False;
 
4339
        }
 
4340
 
 
4341
        memset((char *)&desc,'\0',sizeof(desc));
 
4342
 
 
4343
        p = skip_string(param,tpscnt,p);
 
4344
        if (!p) {
 
4345
                return False;
 
4346
        }
 
4347
        uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
 
4348
 
 
4349
        DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
 
4350
 
 
4351
        /* check it's a supported varient */
 
4352
        if (strcmp(str1,"zWrLh") != 0) {
 
4353
                return False;
 
4354
        }
 
4355
        if (!check_printdest_info(&desc,uLevel,str2)) {
 
4356
                return False;
 
4357
        }
 
4358
 
 
4359
        snum = find_service(PrinterName);
 
4360
        if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) ) {
 
4361
                *rdata_len = 0;
 
4362
                desc.errcode = NERR_DestNotFound;
 
4363
                desc.neededlen = 0;
 
4364
        } else {
 
4365
                if (mdrcnt > 0) {
 
4366
                        *rdata = smb_realloc_limit(*rdata,mdrcnt);
 
4367
                        if (!*rdata) {
 
4368
                                return False;
 
4369
                        }
 
4370
                        desc.base = *rdata;
 
4371
                        desc.buflen = mdrcnt;
 
4372
                } else {
 
4373
                        /*
 
4374
                         * Don't return data but need to get correct length
 
4375
                         * init_package will return wrong size if buflen=0
 
4376
                         */
 
4377
                        desc.buflen = getlen(desc.format);
 
4378
                        desc.base = tmpdata = (char *)SMB_MALLOC( desc.buflen );
 
4379
                }
 
4380
                if (init_package(&desc,1,0)) {
 
4381
                        fill_printdest_info(conn,snum,uLevel,&desc);
 
4382
                }
 
4383
                *rdata_len = desc.usedlen;
 
4384
        }
 
4385
 
 
4386
        *rparam_len = 6;
 
4387
        *rparam = smb_realloc_limit(*rparam,*rparam_len);
 
4388
        if (!*rparam) {
 
4389
                return False;
 
4390
        }
 
4391
        SSVALS(*rparam,0,desc.errcode);
 
4392
        SSVAL(*rparam,2,0);
 
4393
        SSVAL(*rparam,4,desc.neededlen);
 
4394
 
 
4395
        DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
 
4396
        SAFE_FREE(tmpdata);
 
4397
 
 
4398
        return True;
 
4399
}
 
4400
 
 
4401
static bool api_WPrintDestEnum(connection_struct *conn, uint16 vuid,
 
4402
                                char *param, int tpscnt,
 
4403
                                char *data, int tdscnt,
 
4404
                                int mdrcnt,int mprcnt,
 
4405
                                char **rdata,char **rparam,
 
4406
                                int *rdata_len,int *rparam_len)
 
4407
{
 
4408
        char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
 
4409
        char *str2 = skip_string(param,tpscnt,str1);
 
4410
        char *p = skip_string(param,tpscnt,str2);
 
4411
        int uLevel;
 
4412
        int queuecnt;
 
4413
        int i, n, succnt=0;
 
4414
        struct pack_desc desc;
 
4415
        int services = lp_numservices();
 
4416
 
 
4417
        if (!str1 || !str2 || !p) {
 
4418
                return False;
 
4419
        }
 
4420
 
 
4421
        memset((char *)&desc,'\0',sizeof(desc));
 
4422
 
 
4423
        uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
 
4424
 
 
4425
        DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
 
4426
 
 
4427
        /* check it's a supported varient */
 
4428
        if (strcmp(str1,"WrLeh") != 0) {
 
4429
                return False;
 
4430
        }
 
4431
        if (!check_printdest_info(&desc,uLevel,str2)) {
 
4432
                return False;
 
4433
        }
 
4434
 
 
4435
        queuecnt = 0;
 
4436
        for (i = 0; i < services; i++) {
 
4437
                if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
 
4438
                        queuecnt++;
 
4439
                }
 
4440
        }
 
4441
 
 
4442
        if (mdrcnt > 0) {
 
4443
                *rdata = smb_realloc_limit(*rdata,mdrcnt);
 
4444
                if (!*rdata) {
 
4445
                        return False;
 
4446
                }
 
4447
        }
 
4448
 
 
4449
        desc.base = *rdata;
 
4450
        desc.buflen = mdrcnt;
 
4451
        if (init_package(&desc,queuecnt,0)) {    
 
4452
                succnt = 0;
 
4453
                n = 0;
 
4454
                for (i = 0; i < services; i++) {
 
4455
                        if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
 
4456
                                fill_printdest_info(conn,i,uLevel,&desc);
 
4457
                                n++;
 
4458
                                if (desc.errcode == NERR_Success) {
 
4459
                                        succnt = n;
 
4460
                                }
 
4461
                        }
 
4462
                }
 
4463
        }
 
4464
 
 
4465
        *rdata_len = desc.usedlen;
 
4466
 
 
4467
        *rparam_len = 8;
 
4468
        *rparam = smb_realloc_limit(*rparam,*rparam_len);
 
4469
        if (!*rparam) {
 
4470
                return False;
 
4471
        }
 
4472
        SSVALS(*rparam,0,desc.errcode);
 
4473
        SSVAL(*rparam,2,0);
 
4474
        SSVAL(*rparam,4,succnt);
 
4475
        SSVAL(*rparam,6,queuecnt);
 
4476
 
 
4477
        DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
 
4478
 
 
4479
        return True;
 
4480
}
 
4481
 
 
4482
static bool api_WPrintDriverEnum(connection_struct *conn, uint16 vuid,
 
4483
                                char *param, int tpscnt,
 
4484
                                char *data, int tdscnt,
 
4485
                                int mdrcnt,int mprcnt,
 
4486
                                char **rdata,char **rparam,
 
4487
                                int *rdata_len,int *rparam_len)
 
4488
{
 
4489
        char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
 
4490
        char *str2 = skip_string(param,tpscnt,str1);
 
4491
        char *p = skip_string(param,tpscnt,str2);
 
4492
        int uLevel;
 
4493
        int succnt;
 
4494
        struct pack_desc desc;
 
4495
 
 
4496
        if (!str1 || !str2 || !p) {
 
4497
                return False;
 
4498
        }
 
4499
 
 
4500
        memset((char *)&desc,'\0',sizeof(desc));
 
4501
 
 
4502
        uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
 
4503
 
 
4504
        DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
 
4505
 
 
4506
        /* check it's a supported varient */
 
4507
        if (strcmp(str1,"WrLeh") != 0) {
 
4508
                return False;
 
4509
        }
 
4510
        if (uLevel != 0 || strcmp(str2,"B41") != 0) {
 
4511
                return False;
 
4512
        }
 
4513
 
 
4514
        if (mdrcnt > 0) {
 
4515
                *rdata = smb_realloc_limit(*rdata,mdrcnt);
 
4516
                if (!*rdata) {
 
4517
                        return False;
 
4518
                }
 
4519
        }
 
4520
        desc.base = *rdata;
 
4521
        desc.buflen = mdrcnt;
 
4522
        if (init_package(&desc,1,0)) {
 
4523
                PACKS(&desc,"B41","NULL");
 
4524
        }
 
4525
 
 
4526
        succnt = (desc.errcode == NERR_Success ? 1 : 0);
 
4527
 
 
4528
        *rdata_len = desc.usedlen;
 
4529
 
 
4530
        *rparam_len = 8;
 
4531
        *rparam = smb_realloc_limit(*rparam,*rparam_len);
 
4532
        if (!*rparam) {
 
4533
                return False;
 
4534
        }
 
4535
        SSVALS(*rparam,0,desc.errcode);
 
4536
        SSVAL(*rparam,2,0);
 
4537
        SSVAL(*rparam,4,succnt);
 
4538
        SSVAL(*rparam,6,1);
 
4539
 
 
4540
        DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
 
4541
 
 
4542
        return True;
 
4543
}
 
4544
 
 
4545
static bool api_WPrintQProcEnum(connection_struct *conn, uint16 vuid,
 
4546
                                char *param, int tpscnt,
 
4547
                                char *data, int tdscnt,
 
4548
                                int mdrcnt,int mprcnt,
 
4549
                                char **rdata,char **rparam,
 
4550
                                int *rdata_len,int *rparam_len)
 
4551
{
 
4552
        char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
 
4553
        char *str2 = skip_string(param,tpscnt,str1);
 
4554
        char *p = skip_string(param,tpscnt,str2);
 
4555
        int uLevel;
 
4556
        int succnt;
 
4557
        struct pack_desc desc;
 
4558
 
 
4559
        if (!str1 || !str2 || !p) {
 
4560
                return False;
 
4561
        }
 
4562
        memset((char *)&desc,'\0',sizeof(desc));
 
4563
 
 
4564
        uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
 
4565
 
 
4566
        DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
 
4567
 
 
4568
        /* check it's a supported varient */
 
4569
        if (strcmp(str1,"WrLeh") != 0) {
 
4570
                return False;
 
4571
        }
 
4572
        if (uLevel != 0 || strcmp(str2,"B13") != 0) {
 
4573
                return False;
 
4574
        }
 
4575
 
 
4576
        if (mdrcnt > 0) {
 
4577
                *rdata = smb_realloc_limit(*rdata,mdrcnt);
 
4578
                if (!*rdata) {
 
4579
                        return False;
 
4580
                }
 
4581
        }
 
4582
        desc.base = *rdata;
 
4583
        desc.buflen = mdrcnt;
 
4584
        desc.format = str2;
 
4585
        if (init_package(&desc,1,0)) {
 
4586
                PACKS(&desc,"B13","lpd");
 
4587
        }
 
4588
 
 
4589
        succnt = (desc.errcode == NERR_Success ? 1 : 0);
 
4590
 
 
4591
        *rdata_len = desc.usedlen;
 
4592
 
 
4593
        *rparam_len = 8;
 
4594
        *rparam = smb_realloc_limit(*rparam,*rparam_len);
 
4595
        if (!*rparam) {
 
4596
                return False;
 
4597
        }
 
4598
        SSVALS(*rparam,0,desc.errcode);
 
4599
        SSVAL(*rparam,2,0);
 
4600
        SSVAL(*rparam,4,succnt);
 
4601
        SSVAL(*rparam,6,1);
 
4602
 
 
4603
        DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
 
4604
 
 
4605
        return True;
 
4606
}
 
4607
 
 
4608
static bool api_WPrintPortEnum(connection_struct *conn, uint16 vuid,
 
4609
                                char *param, int tpscnt,
 
4610
                                char *data, int tdscnt,
 
4611
                                int mdrcnt,int mprcnt,
 
4612
                                char **rdata,char **rparam,
 
4613
                                int *rdata_len,int *rparam_len)
 
4614
{
 
4615
        char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
 
4616
        char *str2 = skip_string(param,tpscnt,str1);
 
4617
        char *p = skip_string(param,tpscnt,str2);
 
4618
        int uLevel;
 
4619
        int succnt;
 
4620
        struct pack_desc desc;
 
4621
 
 
4622
        if (!str1 || !str2 || !p) {
 
4623
                return False;
 
4624
        }
 
4625
 
 
4626
        memset((char *)&desc,'\0',sizeof(desc));
 
4627
 
 
4628
        uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
 
4629
 
 
4630
        DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
 
4631
 
 
4632
        /* check it's a supported varient */
 
4633
        if (strcmp(str1,"WrLeh") != 0) {
 
4634
                return False;
 
4635
        }
 
4636
        if (uLevel != 0 || strcmp(str2,"B9") != 0) {
 
4637
                return False;
 
4638
        }
 
4639
 
 
4640
        if (mdrcnt > 0) {
 
4641
                *rdata = smb_realloc_limit(*rdata,mdrcnt);
 
4642
                if (!*rdata) {
 
4643
                        return False;
 
4644
                }
 
4645
        }
 
4646
        memset((char *)&desc,'\0',sizeof(desc));
 
4647
        desc.base = *rdata;
 
4648
        desc.buflen = mdrcnt;
 
4649
        desc.format = str2;
 
4650
        if (init_package(&desc,1,0)) {
 
4651
                PACKS(&desc,"B13","lp0");
 
4652
        }
 
4653
 
 
4654
        succnt = (desc.errcode == NERR_Success ? 1 : 0);
 
4655
 
 
4656
        *rdata_len = desc.usedlen;
 
4657
 
 
4658
        *rparam_len = 8;
 
4659
        *rparam = smb_realloc_limit(*rparam,*rparam_len);
 
4660
        if (!*rparam) {
 
4661
                return False;
 
4662
        }
 
4663
        SSVALS(*rparam,0,desc.errcode);
 
4664
        SSVAL(*rparam,2,0);
 
4665
        SSVAL(*rparam,4,succnt);
 
4666
        SSVAL(*rparam,6,1);
 
4667
 
 
4668
        DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
 
4669
 
 
4670
        return True;
 
4671
}
 
4672
 
 
4673
/****************************************************************************
 
4674
 List open sessions
 
4675
 ****************************************************************************/
 
4676
 
 
4677
static bool api_RNetSessionEnum(connection_struct *conn, uint16 vuid,
 
4678
                                char *param, int tpscnt,
 
4679
                                char *data, int tdscnt,
 
4680
                                int mdrcnt,int mprcnt,
 
4681
                                char **rdata,char **rparam,
 
4682
                                int *rdata_len,int *rparam_len)
 
4683
 
 
4684
{
 
4685
        char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
 
4686
        char *str2 = skip_string(param,tpscnt,str1);
 
4687
        char *p = skip_string(param,tpscnt,str2);
 
4688
        int uLevel;
 
4689
        struct pack_desc desc;
 
4690
        struct sessionid *session_list;
 
4691
        int i, num_sessions;
 
4692
 
 
4693
        if (!str1 || !str2 || !p) {
 
4694
                return False;
 
4695
        }
 
4696
 
 
4697
        memset((char *)&desc,'\0',sizeof(desc));
 
4698
 
 
4699
        uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
 
4700
 
 
4701
        DEBUG(3,("RNetSessionEnum uLevel=%d\n",uLevel));
 
4702
        DEBUG(7,("RNetSessionEnum req string=%s\n",str1));
 
4703
        DEBUG(7,("RNetSessionEnum ret string=%s\n",str2));
 
4704
 
 
4705
        /* check it's a supported varient */
 
4706
        if (strcmp(str1,RAP_NetSessionEnum_REQ) != 0) {
 
4707
                return False;
 
4708
        }
 
4709
        if (uLevel != 2 || strcmp(str2,RAP_SESSION_INFO_L2) != 0) {
 
4710
                return False;
 
4711
        }
 
4712
 
 
4713
        num_sessions = list_sessions(talloc_tos(), &session_list);
 
4714
 
 
4715
        if (mdrcnt > 0) {
 
4716
                *rdata = smb_realloc_limit(*rdata,mdrcnt);
 
4717
                if (!*rdata) {
 
4718
                        return False;
 
4719
                }
 
4720
        }
 
4721
        memset((char *)&desc,'\0',sizeof(desc));
 
4722
        desc.base = *rdata;
 
4723
        desc.buflen = mdrcnt;
 
4724
        desc.format = str2;
 
4725
        if (!init_package(&desc,num_sessions,0)) {
 
4726
                return False;
 
4727
        }
 
4728
 
 
4729
        for(i=0; i<num_sessions; i++) {
 
4730
                PACKS(&desc, "z", session_list[i].remote_machine);
 
4731
                PACKS(&desc, "z", session_list[i].username);
 
4732
                PACKI(&desc, "W", 1); /* num conns */
 
4733
                PACKI(&desc, "W", 0); /* num opens */
 
4734
                PACKI(&desc, "W", 1); /* num users */
 
4735
                PACKI(&desc, "D", 0); /* session time */
 
4736
                PACKI(&desc, "D", 0); /* idle time */
 
4737
                PACKI(&desc, "D", 0); /* flags */
 
4738
                PACKS(&desc, "z", "Unknown Client"); /* client type string */
 
4739
        }
 
4740
 
 
4741
        *rdata_len = desc.usedlen;
 
4742
 
 
4743
        *rparam_len = 8;
 
4744
        *rparam = smb_realloc_limit(*rparam,*rparam_len);
 
4745
        if (!*rparam) {
 
4746
                return False;
 
4747
        }
 
4748
        SSVALS(*rparam,0,desc.errcode);
 
4749
        SSVAL(*rparam,2,0); /* converter */
 
4750
        SSVAL(*rparam,4,num_sessions); /* count */
 
4751
 
 
4752
        DEBUG(4,("RNetSessionEnum: errorcode %d\n",desc.errcode));
 
4753
 
 
4754
        return True;
 
4755
}
 
4756
 
 
4757
 
 
4758
/****************************************************************************
 
4759
 The buffer was too small.
 
4760
 ****************************************************************************/
 
4761
 
 
4762
static bool api_TooSmall(connection_struct *conn,uint16 vuid, char *param, char *data,
 
4763
                         int mdrcnt, int mprcnt,
 
4764
                         char **rdata, char **rparam,
 
4765
                         int *rdata_len, int *rparam_len)
 
4766
{
 
4767
        *rparam_len = MIN(*rparam_len,mprcnt);
 
4768
        *rparam = smb_realloc_limit(*rparam,*rparam_len);
 
4769
        if (!*rparam) {
 
4770
                return False;
 
4771
        }
 
4772
 
 
4773
        *rdata_len = 0;
 
4774
 
 
4775
        SSVAL(*rparam,0,NERR_BufTooSmall);
 
4776
 
 
4777
        DEBUG(3,("Supplied buffer too small in API command\n"));
 
4778
 
 
4779
        return True;
 
4780
}
 
4781
 
 
4782
/****************************************************************************
 
4783
 The request is not supported.
 
4784
 ****************************************************************************/
 
4785
 
 
4786
static bool api_Unsupported(connection_struct *conn, uint16 vuid,
 
4787
                                char *param, int tpscnt,
 
4788
                                char *data, int tdscnt,
 
4789
                                int mdrcnt, int mprcnt,
 
4790
                                char **rdata, char **rparam,
 
4791
                                int *rdata_len, int *rparam_len)
 
4792
{
 
4793
        *rparam_len = 4;
 
4794
        *rparam = smb_realloc_limit(*rparam,*rparam_len);
 
4795
        if (!*rparam) {
 
4796
                return False;
 
4797
        }
 
4798
 
 
4799
        *rdata_len = 0;
 
4800
 
 
4801
        SSVAL(*rparam,0,NERR_notsupported);
 
4802
        SSVAL(*rparam,2,0);             /* converter word */
 
4803
 
 
4804
        DEBUG(3,("Unsupported API command\n"));
 
4805
 
 
4806
        return True;
 
4807
}
 
4808
 
 
4809
static const struct {
 
4810
        const char *name;
 
4811
        int id;
 
4812
        bool (*fn)(connection_struct *, uint16,
 
4813
                        char *, int,
 
4814
                        char *, int,
 
4815
                        int,int,char **,char **,int *,int *);
 
4816
        bool auth_user;         /* Deny anonymous access? */
 
4817
} api_commands[] = {
 
4818
        {"RNetShareEnum",       RAP_WshareEnum,         api_RNetShareEnum, True},
 
4819
        {"RNetShareGetInfo",    RAP_WshareGetInfo,      api_RNetShareGetInfo},
 
4820
        {"RNetShareAdd",        RAP_WshareAdd,          api_RNetShareAdd},
 
4821
        {"RNetSessionEnum",     RAP_WsessionEnum,       api_RNetSessionEnum, True},
 
4822
        {"RNetServerGetInfo",   RAP_WserverGetInfo,     api_RNetServerGetInfo},
 
4823
        {"RNetGroupEnum",       RAP_WGroupEnum,         api_RNetGroupEnum, True},
 
4824
        {"RNetGroupGetUsers", RAP_WGroupGetUsers,       api_RNetGroupGetUsers, True},
 
4825
        {"RNetUserEnum",        RAP_WUserEnum,          api_RNetUserEnum, True},
 
4826
        {"RNetUserGetInfo",     RAP_WUserGetInfo,       api_RNetUserGetInfo},
 
4827
        {"NetUserGetGroups",    RAP_WUserGetGroups,     api_NetUserGetGroups},
 
4828
        {"NetWkstaGetInfo",     RAP_WWkstaGetInfo,      api_NetWkstaGetInfo},
 
4829
        {"DosPrintQEnum",       RAP_WPrintQEnum,        api_DosPrintQEnum, True},
 
4830
        {"DosPrintQGetInfo",    RAP_WPrintQGetInfo,     api_DosPrintQGetInfo},
 
4831
        {"WPrintQueuePause",  RAP_WPrintQPause, api_WPrintQueueCtrl},
 
4832
        {"WPrintQueueResume", RAP_WPrintQContinue,      api_WPrintQueueCtrl},
 
4833
        {"WPrintJobEnumerate",RAP_WPrintJobEnum,        api_WPrintJobEnumerate},
 
4834
        {"WPrintJobGetInfo",    RAP_WPrintJobGetInfo,   api_WPrintJobGetInfo},
 
4835
        {"RDosPrintJobDel",     RAP_WPrintJobDel,       api_RDosPrintJobDel},
 
4836
        {"RDosPrintJobPause",   RAP_WPrintJobPause,     api_RDosPrintJobDel},
 
4837
        {"RDosPrintJobResume",RAP_WPrintJobContinue,    api_RDosPrintJobDel},
 
4838
        {"WPrintDestEnum",      RAP_WPrintDestEnum,     api_WPrintDestEnum},
 
4839
        {"WPrintDestGetInfo",   RAP_WPrintDestGetInfo,  api_WPrintDestGetInfo},
 
4840
        {"NetRemoteTOD",        RAP_NetRemoteTOD,       api_NetRemoteTOD},
 
4841
        {"WPrintQueuePurge",    RAP_WPrintQPurge,       api_WPrintQueueCtrl},
 
4842
        {"NetServerEnum2",      RAP_NetServerEnum2,     api_RNetServerEnum2}, /* anon OK */
 
4843
        {"NetServerEnum3",      RAP_NetServerEnum3,     api_RNetServerEnum3}, /* anon OK */
 
4844
        {"WAccessGetUserPerms",RAP_WAccessGetUserPerms,api_WAccessGetUserPerms},
 
4845
        {"SetUserPassword",     RAP_WUserPasswordSet2,  api_SetUserPassword},
 
4846
        {"WWkstaUserLogon",     RAP_WWkstaUserLogon,    api_WWkstaUserLogon},
 
4847
        {"PrintJobInfo",        RAP_WPrintJobSetInfo,   api_PrintJobInfo},
 
4848
        {"WPrintDriverEnum",    RAP_WPrintDriverEnum,   api_WPrintDriverEnum},
 
4849
        {"WPrintQProcEnum",     RAP_WPrintQProcessorEnum,api_WPrintQProcEnum},
 
4850
        {"WPrintPortEnum",      RAP_WPrintPortEnum,     api_WPrintPortEnum},
 
4851
        {"SamOEMChangePassword",RAP_SamOEMChgPasswordUser2_P,api_SamOEMChangePassword}, /* anon OK */
 
4852
        {NULL,          -1,     api_Unsupported}
 
4853
        /*  The following RAP calls are not implemented by Samba:
 
4854
 
 
4855
        RAP_WFileEnum2 - anon not OK 
 
4856
        */
 
4857
};
 
4858
 
 
4859
 
 
4860
/****************************************************************************
 
4861
 Handle remote api calls.
 
4862
****************************************************************************/
 
4863
 
 
4864
void api_reply(connection_struct *conn, uint16 vuid,
 
4865
               struct smb_request *req,
 
4866
               char *data, char *params,
 
4867
               int tdscnt, int tpscnt,
 
4868
               int mdrcnt, int mprcnt)
 
4869
{
 
4870
        int api_command;
 
4871
        char *rdata = NULL;
 
4872
        char *rparam = NULL;
 
4873
        const char *name1 = NULL;
 
4874
        const char *name2 = NULL;
 
4875
        int rdata_len = 0;
 
4876
        int rparam_len = 0;
 
4877
        bool reply=False;
 
4878
        int i;
 
4879
 
 
4880
        if (!params) {
 
4881
                DEBUG(0,("ERROR: NULL params in api_reply()\n"));
 
4882
                reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
 
4883
                return;
 
4884
        }
 
4885
 
 
4886
        if (tpscnt < 2) {
 
4887
                reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
 
4888
                return;
 
4889
        }
 
4890
        api_command = SVAL(params,0);
 
4891
        /* Is there a string at position params+2 ? */
 
4892
        if (skip_string(params,tpscnt,params+2)) {
 
4893
                name1 = params + 2;
 
4894
        } else {
 
4895
                name1 = "";
 
4896
        }
 
4897
        name2 = skip_string(params,tpscnt,params+2);
 
4898
        if (!name2) {
 
4899
                name2 = "";
 
4900
        }
 
4901
 
 
4902
        DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
 
4903
                api_command,
 
4904
                name1,
 
4905
                name2,
 
4906
                tdscnt,tpscnt,mdrcnt,mprcnt));
 
4907
 
 
4908
        for (i=0;api_commands[i].name;i++) {
 
4909
                if (api_commands[i].id == api_command && api_commands[i].fn) {
 
4910
                        DEBUG(3,("Doing %s\n",api_commands[i].name));
 
4911
                        break;
 
4912
                }
 
4913
        }
 
4914
 
 
4915
        /* Check whether this api call can be done anonymously */
 
4916
 
 
4917
        if (api_commands[i].auth_user && lp_restrict_anonymous()) {
 
4918
                user_struct *user = get_valid_user_struct(vuid);
 
4919
 
 
4920
                if (!user || user->server_info->guest) {
 
4921
                        reply_nterror(req, NT_STATUS_ACCESS_DENIED);
 
4922
                        return;
 
4923
                }
 
4924
        }
 
4925
 
 
4926
        rdata = (char *)SMB_MALLOC(1024);
 
4927
        if (rdata) {
 
4928
                memset(rdata,'\0',1024);
 
4929
        }
 
4930
 
 
4931
        rparam = (char *)SMB_MALLOC(1024);
 
4932
        if (rparam) {
 
4933
                memset(rparam,'\0',1024);
 
4934
        }
 
4935
 
 
4936
        if(!rdata || !rparam) {
 
4937
                DEBUG(0,("api_reply: malloc fail !\n"));
 
4938
                SAFE_FREE(rdata);
 
4939
                SAFE_FREE(rparam);
 
4940
                reply_nterror(req, NT_STATUS_NO_MEMORY);
 
4941
                return;
 
4942
        }
 
4943
 
 
4944
        reply = api_commands[i].fn(conn,
 
4945
                                vuid,
 
4946
                                params,tpscnt,  /* params + length */
 
4947
                                data,tdscnt,    /* data + length */
 
4948
                                mdrcnt,mprcnt,
 
4949
                                &rdata,&rparam,&rdata_len,&rparam_len);
 
4950
 
 
4951
 
 
4952
        if (rdata_len > mdrcnt || rparam_len > mprcnt) {
 
4953
                reply = api_TooSmall(conn,vuid,params,data,mdrcnt,mprcnt,
 
4954
                                        &rdata,&rparam,&rdata_len,&rparam_len);
 
4955
        }
 
4956
 
 
4957
        /* if we get False back then it's actually unsupported */
 
4958
        if (!reply) {
 
4959
                reply = api_Unsupported(conn,vuid,params,tpscnt,data,tdscnt,mdrcnt,mprcnt,
 
4960
                        &rdata,&rparam,&rdata_len,&rparam_len);
 
4961
        }
 
4962
 
 
4963
        /* If api_Unsupported returns false we can't return anything. */
 
4964
        if (reply) {
 
4965
                send_trans_reply(conn, req, rparam, rparam_len,
 
4966
                                 rdata, rdata_len, False);
 
4967
        }
 
4968
 
 
4969
        SAFE_FREE(rdata);
 
4970
        SAFE_FREE(rparam);
 
4971
        return;
 
4972
}