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