source: trunk/samba/source/smbd/lanman.c @ 39

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

Upgrade source to 3.0.25a

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