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