s3:smbd: rename api_RNetServerEnum => api_RNetServerEnum2
[ira/wip.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 #include "smbd/globals.h"
30 #include "../librpc/gen_ndr/cli_samr.h"
31 #include "../librpc/gen_ndr/srv_samr.h"
32
33 #ifdef CHECK_TYPES
34 #undef CHECK_TYPES
35 #endif
36 #define CHECK_TYPES 0
37
38 #define NERR_Success 0
39 #define NERR_badpass 86
40 #define NERR_notsupported 50
41
42 #define NERR_BASE (2100)
43 #define NERR_BufTooSmall (NERR_BASE+23)
44 #define NERR_JobNotFound (NERR_BASE+51)
45 #define NERR_DestNotFound (NERR_BASE+52)
46
47 #define ACCESS_READ 0x01
48 #define ACCESS_WRITE 0x02
49 #define ACCESS_CREATE 0x04
50
51 #define SHPWLEN 8               /* share password length */
52
53 /* Limit size of ipc replies */
54
55 static char *smb_realloc_limit(void *ptr, size_t size)
56 {
57         char *val;
58
59         size = MAX((size),4*1024);
60         val = (char *)SMB_REALLOC(ptr,size);
61         if (val) {
62                 memset(val,'\0',size);
63         }
64         return val;
65 }
66
67 static bool api_Unsupported(connection_struct *conn, uint16 vuid,
68                                 char *param, int tpscnt,
69                                 char *data, int tdscnt,
70                                 int mdrcnt, int mprcnt,
71                                 char **rdata, char **rparam,
72                                 int *rdata_len, int *rparam_len);
73
74 static bool api_TooSmall(connection_struct *conn, uint16 vuid, char *param, char *data,
75                          int mdrcnt, int mprcnt,
76                          char **rdata, char **rparam,
77                          int *rdata_len, int *rparam_len);
78
79
80 static int CopyExpanded(connection_struct *conn,
81                         int snum, char **dst, char *src, int *p_space_remaining)
82 {
83         TALLOC_CTX *ctx = talloc_tos();
84         char *buf = NULL;
85         int l;
86
87         if (!src || !dst || !p_space_remaining || !(*dst) ||
88                         *p_space_remaining <= 0) {
89                 return 0;
90         }
91
92         buf = talloc_strdup(ctx, src);
93         if (!buf) {
94                 *p_space_remaining = 0;
95                 return 0;
96         }
97         buf = talloc_string_sub(ctx, buf,"%S",lp_servicename(snum));
98         if (!buf) {
99                 *p_space_remaining = 0;
100                 return 0;
101         }
102         buf = talloc_sub_advanced(ctx,
103                                 lp_servicename(SNUM(conn)),
104                                 conn->server_info->unix_name,
105                                 conn->connectpath,
106                                 conn->server_info->utok.gid,
107                                 conn->server_info->sanitized_username,
108                                 pdb_get_domain(conn->server_info->sam_account),
109                                 buf);
110         if (!buf) {
111                 *p_space_remaining = 0;
112                 return 0;
113         }
114         l = push_ascii(*dst,buf,*p_space_remaining, STR_TERMINATE);
115         if (l == -1) {
116                 return 0;
117         }
118         (*dst) += l;
119         (*p_space_remaining) -= l;
120         return l;
121 }
122
123 static int CopyAndAdvance(char **dst, char *src, int *n)
124 {
125         int l;
126         if (!src || !dst || !n || !(*dst)) {
127                 return 0;
128         }
129         l = push_ascii(*dst,src,*n, STR_TERMINATE);
130         if (l == -1) {
131                 return 0;
132         }
133         (*dst) += l;
134         (*n) -= l;
135         return l;
136 }
137
138 static int StrlenExpanded(connection_struct *conn, int snum, char *s)
139 {
140         TALLOC_CTX *ctx = talloc_tos();
141         char *buf = NULL;
142         if (!s) {
143                 return 0;
144         }
145         buf = talloc_strdup(ctx,s);
146         if (!buf) {
147                 return 0;
148         }
149         buf = talloc_string_sub(ctx,buf,"%S",lp_servicename(snum));
150         if (!buf) {
151                 return 0;
152         }
153         buf = talloc_sub_advanced(ctx,
154                                 lp_servicename(SNUM(conn)),
155                                 conn->server_info->unix_name,
156                                 conn->connectpath,
157                                 conn->server_info->utok.gid,
158                                 conn->server_info->sanitized_username,
159                                 pdb_get_domain(conn->server_info->sam_account),
160                                 buf);
161         if (!buf) {
162                 return 0;
163         }
164         return strlen(buf) + 1;
165 }
166
167 static char *Expand(connection_struct *conn, int snum, char *s)
168 {
169         TALLOC_CTX *ctx = talloc_tos();
170         char *buf = NULL;
171
172         if (!s) {
173                 return NULL;
174         }
175         buf = talloc_strdup(ctx,s);
176         if (!buf) {
177                 return 0;
178         }
179         buf = talloc_string_sub(ctx,buf,"%S",lp_servicename(snum));
180         if (!buf) {
181                 return 0;
182         }
183         return talloc_sub_advanced(ctx,
184                                 lp_servicename(SNUM(conn)),
185                                 conn->server_info->unix_name,
186                                 conn->connectpath,
187                                 conn->server_info->utok.gid,
188                                 conn->server_info->sanitized_username,
189                                 pdb_get_domain(conn->server_info->sam_account),
190                                 buf);
191 }
192
193 /*******************************************************************
194  Check a API string for validity when we only need to check the prefix.
195 ******************************************************************/
196
197 static bool prefix_ok(const char *str, const char *prefix)
198 {
199         return(strncmp(str,prefix,strlen(prefix)) == 0);
200 }
201
202 struct pack_desc {
203         const char *format;         /* formatstring for structure */
204         const char *subformat;  /* subformat for structure */
205         char *base;         /* baseaddress of buffer */
206         int buflen;        /* remaining size for fixed part; on init: length of base */
207         int subcount;       /* count of substructures */
208         char *structbuf;  /* pointer into buffer for remaining fixed part */
209         int stringlen;    /* remaining size for variable part */                
210         char *stringbuf;  /* pointer into buffer for remaining variable part */
211         int neededlen;    /* total needed size */
212         int usedlen;        /* total used size (usedlen <= neededlen and usedlen <= buflen) */
213         const char *curpos;         /* current position; pointer into format or subformat */
214         int errcode;
215 };
216
217 static int get_counter(const char **p)
218 {
219         int i, n;
220         if (!p || !(*p)) {
221                 return 1;
222         }
223         if (!isdigit((int)**p)) {
224                 return 1;
225         }
226         for (n = 0;;) {
227                 i = **p;
228                 if (isdigit(i)) {
229                         n = 10 * n + (i - '0');
230                 } else {
231                         return n;
232                 }
233                 (*p)++;
234         }
235 }
236
237 static int getlen(const char *p)
238 {
239         int n = 0;
240         if (!p) {
241                 return 0;
242         }
243
244         while (*p) {
245                 switch( *p++ ) {
246                 case 'W':                       /* word (2 byte) */
247                         n += 2;
248                         break;
249                 case 'K':                       /* status word? (2 byte) */
250                         n += 2;
251                         break;
252                 case 'N':                       /* count of substructures (word) at end */
253                         n += 2;
254                         break;
255                 case 'D':                       /* double word (4 byte) */
256                 case 'z':                       /* offset to zero terminated string (4 byte) */
257                 case 'l':                       /* offset to user data (4 byte) */
258                         n += 4;
259                         break;
260                 case 'b':                       /* offset to data (with counter) (4 byte) */
261                         n += 4;
262                         get_counter(&p);
263                         break;
264                 case 'B':                       /* byte (with optional counter) */
265                         n += get_counter(&p);
266                         break;
267                 }
268         }
269         return n;
270 }
271
272 static bool init_package(struct pack_desc *p, int count, int subcount)
273 {
274         int n = p->buflen;
275         int i;
276
277         if (!p->format || !p->base) {
278                 return False;
279         }
280
281         i = count * getlen(p->format);
282         if (p->subformat) {
283                 i += subcount * getlen(p->subformat);
284         }
285         p->structbuf = p->base;
286         p->neededlen = 0;
287         p->usedlen = 0;
288         p->subcount = 0;
289         p->curpos = p->format;
290         if (i > n) {
291                 p->neededlen = i;
292                 i = n = 0;
293 #if 0
294                 /*
295                  * This is the old error code we used. Aparently
296                  * WinNT/2k systems return ERRbuftoosmall (2123) and
297                  * OS/2 needs this. I'm leaving this here so we can revert
298                  * if needed. JRA.
299                  */
300                 p->errcode = ERRmoredata;
301 #else
302                 p->errcode = ERRbuftoosmall;
303 #endif
304         } else {
305                 p->errcode = NERR_Success;
306         }
307         p->buflen = i;
308         n -= i;
309         p->stringbuf = p->base + i;
310         p->stringlen = n;
311         return (p->errcode == NERR_Success);
312 }
313
314 static int package(struct pack_desc *p, ...)
315 {
316         va_list args;
317         int needed=0, stringneeded;
318         const char *str=NULL;
319         int is_string=0, stringused;
320         int32 temp;
321
322         va_start(args,p);
323
324         if (!*p->curpos) {
325                 if (!p->subcount) {
326                         p->curpos = p->format;
327                 } else {
328                         p->curpos = p->subformat;
329                         p->subcount--;
330                 }
331         }
332 #if CHECK_TYPES
333         str = va_arg(args,char*);
334         SMB_ASSERT(strncmp(str,p->curpos,strlen(str)) == 0);
335 #endif
336         stringneeded = -1;
337
338         if (!p->curpos) {
339                 va_end(args);
340                 return 0;
341         }
342
343         switch( *p->curpos++ ) {
344                 case 'W':                       /* word (2 byte) */
345                         needed = 2;
346                         temp = va_arg(args,int);
347                         if (p->buflen >= needed) {
348                                 SSVAL(p->structbuf,0,temp);
349                         }
350                         break;
351                 case 'K':                       /* status word? (2 byte) */
352                         needed = 2;
353                         temp = va_arg(args,int);
354                         if (p->buflen >= needed) {
355                                 SSVAL(p->structbuf,0,temp);
356                         }
357                         break;
358                 case 'N':                       /* count of substructures (word) at end */
359                         needed = 2;
360                         p->subcount = va_arg(args,int);
361                         if (p->buflen >= needed) {
362                                 SSVAL(p->structbuf,0,p->subcount);
363                         }
364                         break;
365                 case 'D':                       /* double word (4 byte) */
366                         needed = 4;
367                         temp = va_arg(args,int);
368                         if (p->buflen >= needed) {
369                                 SIVAL(p->structbuf,0,temp);
370                         }
371                         break;
372                 case 'B':                       /* byte (with optional counter) */
373                         needed = get_counter(&p->curpos);
374                         {
375                                 char *s = va_arg(args,char*);
376                                 if (p->buflen >= needed) {
377                                         StrnCpy(p->structbuf,s?s:"",needed-1);
378                                 }
379                         }
380                         break;
381                 case 'z':                       /* offset to zero terminated string (4 byte) */
382                         str = va_arg(args,char*);
383                         stringneeded = (str ? strlen(str)+1 : 0);
384                         is_string = 1;
385                         break;
386                 case 'l':                       /* offset to user data (4 byte) */
387                         str = va_arg(args,char*);
388                         stringneeded = va_arg(args,int);
389                         is_string = 0;
390                         break;
391                 case 'b':                       /* offset to data (with counter) (4 byte) */
392                         str = va_arg(args,char*);
393                         stringneeded = get_counter(&p->curpos);
394                         is_string = 0;
395                         break;
396         }
397
398         va_end(args);
399         if (stringneeded >= 0) {
400                 needed = 4;
401                 if (p->buflen >= needed) {
402                         stringused = stringneeded;
403                         if (stringused > p->stringlen) {
404                                 stringused = (is_string ? p->stringlen : 0);
405                                 if (p->errcode == NERR_Success) {
406                                         p->errcode = ERRmoredata;
407                                 }
408                         }
409                         if (!stringused) {
410                                 SIVAL(p->structbuf,0,0);
411                         } else {
412                                 SIVAL(p->structbuf,0,PTR_DIFF(p->stringbuf,p->base));
413                                 memcpy(p->stringbuf,str?str:"",stringused);
414                                 if (is_string) {
415                                         p->stringbuf[stringused-1] = '\0';
416                                 }
417                                 p->stringbuf += stringused;
418                                 p->stringlen -= stringused;
419                                 p->usedlen += stringused;
420                         }
421                 }
422                 p->neededlen += stringneeded;
423         }
424
425         p->neededlen += needed;
426         if (p->buflen >= needed) {
427                 p->structbuf += needed;
428                 p->buflen -= needed;
429                 p->usedlen += needed;
430         } else {
431                 if (p->errcode == NERR_Success) {
432                         p->errcode = ERRmoredata;
433                 }
434         }
435         return 1;
436 }
437
438 #if CHECK_TYPES
439 #define PACK(desc,t,v) package(desc,t,v,0,0,0,0)
440 #define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0)
441 #else
442 #define PACK(desc,t,v) package(desc,v)
443 #define PACKl(desc,t,v,l) package(desc,v,l)
444 #endif
445
446 static void PACKI(struct pack_desc* desc, const char *t,int v)
447 {
448         PACK(desc,t,v);
449 }
450
451 static void PACKS(struct pack_desc* desc,const char *t,const char *v)
452 {
453         PACK(desc,t,v);
454 }
455
456 /****************************************************************************
457  Get a print queue.
458 ****************************************************************************/
459
460 static void PackDriverData(struct pack_desc* desc)
461 {
462         char drivdata[4+4+32];
463         SIVAL(drivdata,0,sizeof drivdata); /* cb */
464         SIVAL(drivdata,4,1000); /* lVersion */
465         memset(drivdata+8,0,32);        /* szDeviceName */
466         push_ascii(drivdata+8,"NULL",32, STR_TERMINATE);
467         PACKl(desc,"l",drivdata,sizeof drivdata); /* pDriverData */
468 }
469
470 static int check_printq_info(struct pack_desc* desc,
471                                 unsigned int uLevel, char *id1, char *id2)
472 {
473         desc->subformat = NULL;
474         switch( uLevel ) {
475                 case 0:
476                         desc->format = "B13";
477                         break;
478                 case 1:
479                         desc->format = "B13BWWWzzzzzWW";
480                         break;
481                 case 2:
482                         desc->format = "B13BWWWzzzzzWN";
483                         desc->subformat = "WB21BB16B10zWWzDDz";
484                         break;
485                 case 3:
486                         desc->format = "zWWWWzzzzWWzzl";
487                         break;
488                 case 4:
489                         desc->format = "zWWWWzzzzWNzzl";
490                         desc->subformat = "WWzWWDDzz";
491                         break;
492                 case 5:
493                         desc->format = "z";
494                         break;
495                 case 51:
496                         desc->format = "K";
497                         break;
498                 case 52:
499                         desc->format = "WzzzzzzzzN";
500                         desc->subformat = "z";
501                         break;
502                 default:
503                         DEBUG(0,("check_printq_info: invalid level %d\n",
504                                 uLevel ));
505                         return False;
506         }
507         if (id1 == NULL || strcmp(desc->format,id1) != 0) {
508                 DEBUG(0,("check_printq_info: invalid format %s\n",
509                         id1 ? id1 : "<NULL>" ));
510                 return False;
511         }
512         if (desc->subformat && (id2 == NULL || strcmp(desc->subformat,id2) != 0)) {
513                 DEBUG(0,("check_printq_info: invalid subformat %s\n",
514                         id2 ? id2 : "<NULL>" ));
515                 return False;
516         }
517         return True;
518 }
519
520
521 #define RAP_JOB_STATUS_QUEUED 0
522 #define RAP_JOB_STATUS_PAUSED 1
523 #define RAP_JOB_STATUS_SPOOLING 2
524 #define RAP_JOB_STATUS_PRINTING 3
525 #define RAP_JOB_STATUS_PRINTED 4
526
527 #define RAP_QUEUE_STATUS_PAUSED 1
528 #define RAP_QUEUE_STATUS_ERROR 2
529
530 /* turn a print job status into a on the wire status 
531 */
532 static int printj_status(int v)
533 {
534         switch (v) {
535         case LPQ_QUEUED:
536                 return RAP_JOB_STATUS_QUEUED;
537         case LPQ_PAUSED:
538                 return RAP_JOB_STATUS_PAUSED;
539         case LPQ_SPOOLING:
540                 return RAP_JOB_STATUS_SPOOLING;
541         case LPQ_PRINTING:
542                 return RAP_JOB_STATUS_PRINTING;
543         }
544         return 0;
545 }
546
547 /* turn a print queue status into a on the wire status 
548 */
549 static int printq_status(int v)
550 {
551         switch (v) {
552         case LPQ_QUEUED:
553                 return 0;
554         case LPQ_PAUSED:
555                 return RAP_QUEUE_STATUS_PAUSED;
556         }
557         return RAP_QUEUE_STATUS_ERROR;
558 }
559
560 static void fill_printjob_info(connection_struct *conn, int snum, int uLevel,
561                                struct pack_desc *desc,
562                                print_queue_struct *queue, int n)
563 {
564         time_t t = queue->time;
565
566         /* the client expects localtime */
567         t -= get_time_zone(t);
568
569         PACKI(desc,"W",pjobid_to_rap(lp_const_servicename(snum),queue->job)); /* uJobId */
570         if (uLevel == 1) {
571                 PACKS(desc,"B21",queue->fs_user); /* szUserName */
572                 PACKS(desc,"B","");             /* pad */
573                 PACKS(desc,"B16","");   /* szNotifyName */
574                 PACKS(desc,"B10","PM_Q_RAW"); /* szDataType */
575                 PACKS(desc,"z","");             /* pszParms */
576                 PACKI(desc,"W",n+1);            /* uPosition */
577                 PACKI(desc,"W",printj_status(queue->status)); /* fsStatus */
578                 PACKS(desc,"z","");             /* pszStatus */
579                 PACKI(desc,"D",t); /* ulSubmitted */
580                 PACKI(desc,"D",queue->size); /* ulSize */
581                 PACKS(desc,"z",queue->fs_file); /* pszComment */
582         }
583         if (uLevel == 2 || uLevel == 3 || uLevel == 4) {
584                 PACKI(desc,"W",queue->priority);                /* uPriority */
585                 PACKS(desc,"z",queue->fs_user); /* pszUserName */
586                 PACKI(desc,"W",n+1);            /* uPosition */
587                 PACKI(desc,"W",printj_status(queue->status)); /* fsStatus */
588                 PACKI(desc,"D",t); /* ulSubmitted */
589                 PACKI(desc,"D",queue->size); /* ulSize */
590                 PACKS(desc,"z","Samba");        /* pszComment */
591                 PACKS(desc,"z",queue->fs_file); /* pszDocument */
592                 if (uLevel == 3) {
593                         PACKS(desc,"z","");     /* pszNotifyName */
594                         PACKS(desc,"z","PM_Q_RAW"); /* pszDataType */
595                         PACKS(desc,"z","");     /* pszParms */
596                         PACKS(desc,"z","");     /* pszStatus */
597                         PACKS(desc,"z",SERVICE(snum)); /* pszQueue */
598                         PACKS(desc,"z","lpd");  /* pszQProcName */
599                         PACKS(desc,"z","");     /* pszQProcParms */
600                         PACKS(desc,"z","NULL"); /* pszDriverName */
601                         PackDriverData(desc);   /* pDriverData */
602                         PACKS(desc,"z","");     /* pszPrinterName */
603                 } else if (uLevel == 4) {   /* OS2 */
604                         PACKS(desc,"z","");       /* pszSpoolFileName  */
605                         PACKS(desc,"z","");       /* pszPortName       */
606                         PACKS(desc,"z","");       /* pszStatus         */
607                         PACKI(desc,"D",0);        /* ulPagesSpooled    */
608                         PACKI(desc,"D",0);        /* ulPagesSent       */
609                         PACKI(desc,"D",0);        /* ulPagesPrinted    */
610                         PACKI(desc,"D",0);        /* ulTimePrinted     */
611                         PACKI(desc,"D",0);        /* ulExtendJobStatus */
612                         PACKI(desc,"D",0);        /* ulStartPage       */
613                         PACKI(desc,"D",0);        /* ulEndPage         */
614                 }
615         }
616 }
617
618 /********************************************************************
619  Return a driver name given an snum.
620  Returns True if from tdb, False otherwise.
621  ********************************************************************/
622
623 static bool get_driver_name(int snum, char **pp_drivername)
624 {
625         NT_PRINTER_INFO_LEVEL *info = NULL;
626         bool in_tdb = false;
627
628         get_a_printer (NULL, &info, 2, lp_servicename(snum));
629         if (info != NULL) {
630                 *pp_drivername = talloc_strdup(talloc_tos(),
631                                         info->info_2->drivername);
632                 in_tdb = true;
633                 free_a_printer(&info, 2);
634                 if (!*pp_drivername) {
635                         return false;
636                 }
637         }
638
639         return in_tdb;
640 }
641
642 /********************************************************************
643  Respond to the DosPrintQInfo command with a level of 52
644  This is used to get printer driver information for Win9x clients
645  ********************************************************************/
646 static void fill_printq_info_52(connection_struct *conn, int snum, 
647                                 struct pack_desc* desc, int count )
648 {
649         int                             i;
650         fstring                         location;
651         struct spoolss_DriverInfo8 *driver = NULL;
652         NT_PRINTER_INFO_LEVEL           *printer = NULL;
653
654         if ( !W_ERROR_IS_OK(get_a_printer( NULL, &printer, 2, lp_servicename(snum))) ) {
655                 DEBUG(3,("fill_printq_info_52: Failed to lookup printer [%s]\n", 
656                         lp_servicename(snum)));
657                 goto err;
658         }
659
660         if (!W_ERROR_IS_OK(get_a_printer_driver(talloc_tos(), &driver, printer->info_2->drivername,
661                 "Windows 4.0", 0)) )
662         {
663                 DEBUG(3,("fill_printq_info_52: Failed to lookup driver [%s]\n", 
664                         printer->info_2->drivername));
665                 goto err;
666         }
667
668         trim_string((char *)driver->driver_path, "\\print$\\WIN40\\0\\", 0);
669         trim_string((char *)driver->data_file, "\\print$\\WIN40\\0\\", 0);
670         trim_string((char *)driver->help_file, "\\print$\\WIN40\\0\\", 0);
671
672         PACKI(desc, "W", 0x0400);                     /* don't know */
673         PACKS(desc, "z", driver->driver_name);        /* long printer name */
674         PACKS(desc, "z", driver->driver_path);  /* Driverfile Name */
675         PACKS(desc, "z", driver->data_file);    /* Datafile name */
676         PACKS(desc, "z", driver->monitor_name); /* language monitor */
677
678         fstrcpy(location, "\\\\%L\\print$\\WIN40\\0");
679         standard_sub_basic( "", "", location, sizeof(location)-1 );
680         PACKS(desc,"z", location);                          /* share to retrieve files */
681
682         PACKS(desc,"z", driver->default_datatype);    /* default data type */
683         PACKS(desc,"z", driver->help_file);           /* helpfile name */
684         PACKS(desc,"z", driver->driver_path);               /* driver name */
685
686         DEBUG(3,("Printer Driver Name: %s:\n",driver->driver_name));
687         DEBUG(3,("Driver: %s:\n",driver->driver_path));
688         DEBUG(3,("Data File: %s:\n",driver->data_file));
689         DEBUG(3,("Language Monitor: %s:\n",driver->monitor_name));
690         DEBUG(3,("Driver Location: %s:\n",location));
691         DEBUG(3,("Data Type: %s:\n",driver->default_datatype));
692         DEBUG(3,("Help File: %s:\n",driver->help_file));
693         PACKI(desc,"N",count);                     /* number of files to copy */
694
695         for ( i=0; i<count && driver->dependent_files && *driver->dependent_files[i]; i++)
696         {
697                 trim_string((char *)driver->dependent_files[i], "\\print$\\WIN40\\0\\", 0);
698                 PACKS(desc,"z",driver->dependent_files[i]);         /* driver files to copy */
699                 DEBUG(3,("Dependent File: %s:\n", driver->dependent_files[i]));
700         }
701
702         /* sanity check */
703         if ( i != count )
704                 DEBUG(3,("fill_printq_info_52: file count specified by client [%d] != number of dependent files [%i]\n",
705                         count, i));
706
707         DEBUG(3,("fill_printq_info on <%s> gave %d entries\n", SERVICE(snum),i));
708
709         desc->errcode=NERR_Success;
710         goto done;
711
712 err:
713         DEBUG(3,("fill_printq_info: Can't supply driver files\n"));
714         desc->errcode=NERR_notsupported;
715
716 done:
717         if ( printer )
718                 free_a_printer( &printer, 2 );
719
720         free_a_printer_driver(driver);
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         struct spoolss_DriverInfo8 *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(talloc_tos(), &driver, 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->dependent_files && *driver->dependent_files[result])
830                 result++;
831  done:
832         if ( printer )
833                 free_a_printer( &printer, 2 );
834
835         free_a_printer_driver(driver);
836
837         return result;
838 }
839
840 static bool api_DosPrintQGetInfo(connection_struct *conn, uint16 vuid,
841                                 char *param, int tpscnt,
842                                 char *data, int tdscnt,
843                                 int mdrcnt,int mprcnt,
844                                 char **rdata,char **rparam,
845                                 int *rdata_len,int *rparam_len)
846 {
847         char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
848         char *str2 = skip_string(param,tpscnt,str1);
849         char *p = skip_string(param,tpscnt,str2);
850         char *QueueName = p;
851         unsigned int uLevel;
852         int count=0;
853         int snum;
854         char *str3;
855         struct pack_desc desc;
856         print_queue_struct *queue=NULL;
857         print_status_struct status;
858         char* tmpdata=NULL;
859
860         if (!str1 || !str2 || !p) {
861                 return False;
862         }
863         memset((char *)&status,'\0',sizeof(status));
864         memset((char *)&desc,'\0',sizeof(desc));
865
866         p = skip_string(param,tpscnt,p);
867         if (!p) {
868                 return False;
869         }
870         uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
871         str3 = get_safe_str_ptr(param,tpscnt,p,4);
872         /* str3 may be null here and is checked in check_printq_info(). */
873
874         /* remove any trailing username */
875         if ((p = strchr_m(QueueName,'%')))
876                 *p = 0;
877
878         DEBUG(3,("api_DosPrintQGetInfo uLevel=%d name=%s\n",uLevel,QueueName));
879
880         /* check it's a supported varient */
881         if (!prefix_ok(str1,"zWrLh"))
882                 return False;
883         if (!check_printq_info(&desc,uLevel,str2,str3)) {
884                 /*
885                  * Patch from Scott Moomaw <scott@bridgewater.edu>
886                  * to return the 'invalid info level' error if an
887                  * unknown level was requested.
888                  */
889                 *rdata_len = 0;
890                 *rparam_len = 6;
891                 *rparam = smb_realloc_limit(*rparam,*rparam_len);
892                 if (!*rparam) {
893                         return False;
894                 }
895                 SSVALS(*rparam,0,ERRunknownlevel);
896                 SSVAL(*rparam,2,0);
897                 SSVAL(*rparam,4,0);
898                 return(True);
899         }
900
901         snum = find_service(QueueName);
902         if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) )
903                 return False;
904
905         if (uLevel==52) {
906                 count = get_printerdrivernumber(snum);
907                 DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count));
908         } else {
909                 count = print_queue_status(snum, &queue,&status);
910         }
911
912         if (mdrcnt > 0) {
913                 *rdata = smb_realloc_limit(*rdata,mdrcnt);
914                 if (!*rdata) {
915                         SAFE_FREE(queue);
916                         return False;
917                 }
918                 desc.base = *rdata;
919                 desc.buflen = mdrcnt;
920         } else {
921                 /*
922                  * Don't return data but need to get correct length
923                  * init_package will return wrong size if buflen=0
924                  */
925                 desc.buflen = getlen(desc.format);
926                 desc.base = tmpdata = (char *) SMB_MALLOC (desc.buflen);
927         }
928
929         if (init_package(&desc,1,count)) {
930                 desc.subcount = count;
931                 fill_printq_info(conn,snum,uLevel,&desc,count,queue,&status);
932         }
933
934         *rdata_len = desc.usedlen;
935
936         /*
937          * We must set the return code to ERRbuftoosmall
938          * in order to support lanman style printing with Win NT/2k
939          * clients       --jerry
940          */
941         if (!mdrcnt && lp_disable_spoolss())
942                 desc.errcode = ERRbuftoosmall;
943
944         *rdata_len = desc.usedlen;
945         *rparam_len = 6;
946         *rparam = smb_realloc_limit(*rparam,*rparam_len);
947         if (!*rparam) {
948                 SAFE_FREE(queue);
949                 SAFE_FREE(tmpdata);
950                 return False;
951         }
952         SSVALS(*rparam,0,desc.errcode);
953         SSVAL(*rparam,2,0);
954         SSVAL(*rparam,4,desc.neededlen);
955
956         DEBUG(4,("printqgetinfo: errorcode %d\n",desc.errcode));
957
958         SAFE_FREE(queue);
959         SAFE_FREE(tmpdata);
960
961         return(True);
962 }
963
964 /****************************************************************************
965  View list of all print jobs on all queues.
966 ****************************************************************************/
967
968 static bool api_DosPrintQEnum(connection_struct *conn, uint16 vuid,
969                                 char *param, int tpscnt,
970                                 char *data, int tdscnt,
971                                 int mdrcnt, int mprcnt,
972                                 char **rdata, char** rparam,
973                                 int *rdata_len, int *rparam_len)
974 {
975         char *param_format = get_safe_str_ptr(param,tpscnt,param,2);
976         char *output_format1 = skip_string(param,tpscnt,param_format);
977         char *p = skip_string(param,tpscnt,output_format1);
978         unsigned int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
979         char *output_format2 = get_safe_str_ptr(param,tpscnt,p,4);
980         int services = lp_numservices();
981         int i, n;
982         struct pack_desc desc;
983         print_queue_struct **queue = NULL;
984         print_status_struct *status = NULL;
985         int *subcntarr = NULL;
986         int queuecnt = 0, subcnt = 0, succnt = 0;
987
988         if (!param_format || !output_format1 || !p) {
989                 return False;
990         }
991
992         memset((char *)&desc,'\0',sizeof(desc));
993
994         DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel));
995
996         if (!prefix_ok(param_format,"WrLeh")) {
997                 return False;
998         }
999         if (!check_printq_info(&desc,uLevel,output_format1,output_format2)) {
1000                 /*
1001                  * Patch from Scott Moomaw <scott@bridgewater.edu>
1002                  * to return the 'invalid info level' error if an
1003                  * unknown level was requested.
1004                  */
1005                 *rdata_len = 0;
1006                 *rparam_len = 6;
1007                 *rparam = smb_realloc_limit(*rparam,*rparam_len);
1008                 if (!*rparam) {
1009                         return False;
1010                 }
1011                 SSVALS(*rparam,0,ERRunknownlevel);
1012                 SSVAL(*rparam,2,0);
1013                 SSVAL(*rparam,4,0);
1014                 return(True);
1015         }
1016
1017         for (i = 0; i < services; i++) {
1018                 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
1019                         queuecnt++;
1020                 }
1021         }
1022
1023         if((queue = SMB_MALLOC_ARRAY(print_queue_struct*, queuecnt)) == NULL) {
1024                 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
1025                 goto err;
1026         }
1027         memset(queue,0,queuecnt*sizeof(print_queue_struct*));
1028         if((status = SMB_MALLOC_ARRAY(print_status_struct,queuecnt)) == NULL) {
1029                 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
1030                 goto err;
1031         }
1032         memset(status,0,queuecnt*sizeof(print_status_struct));
1033         if((subcntarr = SMB_MALLOC_ARRAY(int,queuecnt)) == NULL) {
1034                 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
1035                 goto err;
1036         }
1037
1038         subcnt = 0;
1039         n = 0;
1040         for (i = 0; i < services; i++) {
1041                 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
1042                         subcntarr[n] = print_queue_status(i, &queue[n],&status[n]);
1043                         subcnt += subcntarr[n];
1044                         n++;
1045                 }
1046         }
1047
1048         if (mdrcnt > 0) {
1049                 *rdata = smb_realloc_limit(*rdata,mdrcnt);
1050                 if (!*rdata) {
1051                         goto err;
1052                 }
1053         }
1054         desc.base = *rdata;
1055         desc.buflen = mdrcnt;
1056
1057         if (init_package(&desc,queuecnt,subcnt)) {
1058                 n = 0;
1059                 succnt = 0;
1060                 for (i = 0; i < services; i++) {
1061                         if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
1062                                 fill_printq_info(conn,i,uLevel,&desc,subcntarr[n],queue[n],&status[n]);
1063                                 n++;
1064                                 if (desc.errcode == NERR_Success) {
1065                                         succnt = n;
1066                                 }
1067                         }
1068                 }
1069         }
1070
1071         SAFE_FREE(subcntarr);
1072
1073         *rdata_len = desc.usedlen;
1074         *rparam_len = 8;
1075         *rparam = smb_realloc_limit(*rparam,*rparam_len);
1076         if (!*rparam) {
1077                 goto err;
1078         }
1079         SSVALS(*rparam,0,desc.errcode);
1080         SSVAL(*rparam,2,0);
1081         SSVAL(*rparam,4,succnt);
1082         SSVAL(*rparam,6,queuecnt);
1083
1084         for (i = 0; i < queuecnt; i++) {
1085                 if (queue) {
1086                         SAFE_FREE(queue[i]);
1087                 }
1088         }
1089
1090         SAFE_FREE(queue);
1091         SAFE_FREE(status);
1092
1093         return True;
1094
1095   err:
1096
1097         SAFE_FREE(subcntarr);
1098         for (i = 0; i < queuecnt; i++) {
1099                 if (queue) {
1100                         SAFE_FREE(queue[i]);
1101                 }
1102         }
1103         SAFE_FREE(queue);
1104         SAFE_FREE(status);
1105
1106         return False;
1107 }
1108
1109 /****************************************************************************
1110  Get info level for a server list query.
1111 ****************************************************************************/
1112
1113 static bool check_server_info(int uLevel, char* id)
1114 {
1115         switch( uLevel ) {
1116                 case 0:
1117                         if (strcmp(id,"B16") != 0) {
1118                                 return False;
1119                         }
1120                         break;
1121                 case 1:
1122                         if (strcmp(id,"B16BBDz") != 0) {
1123                                 return False;
1124                         }
1125                         break;
1126                 default: 
1127                         return False;
1128         }
1129         return True;
1130 }
1131
1132 struct srv_info_struct {
1133         fstring name;
1134         uint32 type;
1135         fstring comment;
1136         fstring domain;
1137         bool server_added;
1138 };
1139
1140 /*******************************************************************
1141  Get server info lists from the files saved by nmbd. Return the
1142  number of entries.
1143 ******************************************************************/
1144
1145 static int get_server_info(uint32 servertype, 
1146                            struct srv_info_struct **servers,
1147                            const char *domain)
1148 {
1149         int count=0;
1150         int alloced=0;
1151         char **lines;
1152         bool local_list_only;
1153         int i;
1154
1155         lines = file_lines_load(cache_path(SERVER_LIST), NULL, 0, NULL);
1156         if (!lines) {
1157                 DEBUG(4,("Can't open %s - %s\n",cache_path(SERVER_LIST),strerror(errno)));
1158                 return 0;
1159         }
1160
1161         /* request for everything is code for request all servers */
1162         if (servertype == SV_TYPE_ALL) {
1163                 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1164         }
1165
1166         local_list_only = (servertype & SV_TYPE_LOCAL_LIST_ONLY);
1167
1168         DEBUG(4,("Servertype search: %8x\n",servertype));
1169
1170         for (i=0;lines[i];i++) {
1171                 fstring stype;
1172                 struct srv_info_struct *s;
1173                 const char *ptr = lines[i];
1174                 bool ok = True;
1175                 TALLOC_CTX *frame = NULL;
1176                 char *p;
1177
1178                 if (!*ptr) {
1179                         continue;
1180                 }
1181
1182                 if (count == alloced) {
1183                         alloced += 10;
1184                         *servers = SMB_REALLOC_ARRAY(*servers,struct srv_info_struct, alloced);
1185                         if (!*servers) {
1186                                 DEBUG(0,("get_server_info: failed to enlarge servers info struct!\n"));
1187                                 TALLOC_FREE(lines);
1188                                 return 0;
1189                         }
1190                         memset((char *)((*servers)+count),'\0',sizeof(**servers)*(alloced-count));
1191                 }
1192                 s = &(*servers)[count];
1193
1194                 frame = talloc_stackframe();
1195                 s->name[0] = '\0';
1196                 if (!next_token_talloc(frame,&ptr,&p, NULL)) {
1197                         TALLOC_FREE(frame);
1198                         continue;
1199                 }
1200                 fstrcpy(s->name, p);
1201
1202                 stype[0] = '\0';
1203                 if (!next_token_talloc(frame,&ptr, &p, NULL)) {
1204                         TALLOC_FREE(frame);
1205                         continue;
1206                 }
1207                 fstrcpy(stype, p);
1208
1209                 s->comment[0] = '\0';
1210                 if (!next_token_talloc(frame,&ptr, &p, NULL)) {
1211                         TALLOC_FREE(frame);
1212                         continue;
1213                 }
1214                 fstrcpy(s->comment, p);
1215                 string_truncate(s->comment, MAX_SERVER_STRING_LENGTH);
1216
1217                 s->domain[0] = '\0';
1218                 if (!next_token_talloc(frame,&ptr,&p, NULL)) {
1219                         /* this allows us to cope with an old nmbd */
1220                         fstrcpy(s->domain,lp_workgroup());
1221                 } else {
1222                         fstrcpy(s->domain, p);
1223                 }
1224                 TALLOC_FREE(frame);
1225
1226                 if (sscanf(stype,"%X",&s->type) != 1) {
1227                         DEBUG(4,("r:host file "));
1228                         ok = False;
1229                 }
1230
1231                 /* Filter the servers/domains we return based on what was asked for. */
1232
1233                 /* Check to see if we are being asked for a local list only. */
1234                 if(local_list_only && ((s->type & SV_TYPE_LOCAL_LIST_ONLY) == 0)) {
1235                         DEBUG(4,("r: local list only"));
1236                         ok = False;
1237                 }
1238
1239                 /* doesn't match up: don't want it */
1240                 if (!(servertype & s->type)) {
1241                         DEBUG(4,("r:serv type "));
1242                         ok = False;
1243                 }
1244
1245                 if ((servertype & SV_TYPE_DOMAIN_ENUM) != 
1246                                 (s->type & SV_TYPE_DOMAIN_ENUM)) {
1247                         DEBUG(4,("s: dom mismatch "));
1248                         ok = False;
1249                 }
1250
1251                 if (!strequal(domain, s->domain) && !(servertype & SV_TYPE_DOMAIN_ENUM)) {
1252                         ok = False;
1253                 }
1254
1255                 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
1256                 s->type &= ~SV_TYPE_LOCAL_LIST_ONLY;
1257
1258                 if (ok) {
1259                         DEBUG(4,("**SV** %20s %8x %25s %15s\n",
1260                                 s->name, s->type, s->comment, s->domain));
1261                         s->server_added = True;
1262                         count++;
1263                 } else {
1264                         DEBUG(4,("%20s %8x %25s %15s\n",
1265                                 s->name, s->type, s->comment, s->domain));
1266                 }
1267         }
1268
1269         TALLOC_FREE(lines);
1270         return count;
1271 }
1272
1273 /*******************************************************************
1274  Fill in a server info structure.
1275 ******************************************************************/
1276
1277 static int fill_srv_info(struct srv_info_struct *service, 
1278                          int uLevel, char **buf, int *buflen, 
1279                          char **stringbuf, int *stringspace, char *baseaddr)
1280 {
1281         int struct_len;
1282         char* p;
1283         char* p2;
1284         int l2;
1285         int len;
1286
1287         switch (uLevel) {
1288                 case 0:
1289                         struct_len = 16;
1290                         break;
1291                 case 1:
1292                         struct_len = 26;
1293                         break;
1294                 default:
1295                         return -1;
1296         }
1297
1298         if (!buf) {
1299                 len = 0;
1300                 switch (uLevel) {
1301                         case 1:
1302                                 len = strlen(service->comment)+1;
1303                                 break;
1304                 }
1305
1306                 *buflen = struct_len;
1307                 *stringspace = len;
1308                 return struct_len + len;
1309         }
1310
1311         len = struct_len;
1312         p = *buf;
1313         if (*buflen < struct_len) {
1314                 return -1;
1315         }
1316         if (stringbuf) {
1317                 p2 = *stringbuf;
1318                 l2 = *stringspace;
1319         } else {
1320                 p2 = p + struct_len;
1321                 l2 = *buflen - struct_len;
1322         }
1323         if (!baseaddr) {
1324                 baseaddr = p;
1325         }
1326
1327         switch (uLevel) {
1328                 case 0:
1329                         push_ascii(p,service->name, MAX_NETBIOSNAME_LEN, STR_TERMINATE);
1330                         break;
1331
1332                 case 1:
1333                         push_ascii(p,service->name,MAX_NETBIOSNAME_LEN, STR_TERMINATE);
1334                         SIVAL(p,18,service->type);
1335                         SIVAL(p,22,PTR_DIFF(p2,baseaddr));
1336                         len += CopyAndAdvance(&p2,service->comment,&l2);
1337                         break;
1338         }
1339
1340         if (stringbuf) {
1341                 *buf = p + struct_len;
1342                 *buflen -= struct_len;
1343                 *stringbuf = p2;
1344                 *stringspace = l2;
1345         } else {
1346                 *buf = p2;
1347                 *buflen -= len;
1348         }
1349         return len;
1350 }
1351
1352
1353 static bool srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2)
1354 {
1355         return(strcmp(s1->name,s2->name));
1356 }
1357
1358 /****************************************************************************
1359  View list of servers available (or possibly domains). The info is
1360  extracted from lists saved by nmbd on the local host.
1361 ****************************************************************************/
1362
1363 static bool api_RNetServerEnum2(connection_struct *conn, uint16 vuid,
1364                                 char *param, int tpscnt,
1365                                 char *data, int tdscnt,
1366                                 int mdrcnt, int mprcnt, char **rdata, 
1367                                 char **rparam, int *rdata_len, int *rparam_len)
1368 {
1369         char *str1 = get_safe_str_ptr(param, tpscnt, param, 2);
1370         char *str2 = skip_string(param,tpscnt,str1);
1371         char *p = skip_string(param,tpscnt,str2);
1372         int uLevel = get_safe_SVAL(param, tpscnt, p, 0, -1);
1373         int buf_len = get_safe_SVAL(param,tpscnt, p, 2, 0);
1374         uint32 servertype = get_safe_IVAL(param,tpscnt,p,4, 0);
1375         char *p2;
1376         int data_len, fixed_len, string_len;
1377         int f_len = 0, s_len = 0;
1378         struct srv_info_struct *servers=NULL;
1379         int counted=0,total=0;
1380         int i,missed;
1381         fstring domain;
1382         bool domain_request;
1383         bool local_request;
1384
1385         if (!str1 || !str2 || !p) {
1386                 return False;
1387         }
1388
1389         /* If someone sets all the bits they don't really mean to set
1390            DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1391            known servers. */
1392
1393         if (servertype == SV_TYPE_ALL) {
1394                 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1395         }
1396
1397         /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1398            any other bit (they may just set this bit on its own) they 
1399            want all the locally seen servers. However this bit can be 
1400            set on its own so set the requested servers to be 
1401            ALL - DOMAIN_ENUM. */
1402
1403         if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) && !(servertype & SV_TYPE_DOMAIN_ENUM)) {
1404                 servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM);
1405         }
1406
1407         domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
1408         local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0);
1409
1410         p += 8;
1411
1412         if (!prefix_ok(str1,"WrLehD")) {
1413                 return False;
1414         }
1415         if (!check_server_info(uLevel,str2)) {
1416                 return False;
1417         }
1418
1419         DEBUG(4, ("server request level: %s %8x ", str2, servertype));
1420         DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
1421         DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
1422
1423         if (strcmp(str1, "WrLehDz") == 0) {
1424                 if (skip_string(param,tpscnt,p) == NULL) {
1425                         return False;
1426                 }
1427                 pull_ascii_fstring(domain, p);
1428         } else {
1429                 fstrcpy(domain, lp_workgroup());
1430         }
1431
1432         if (lp_browse_list()) {
1433                 total = get_server_info(servertype,&servers,domain);
1434         }
1435
1436         data_len = fixed_len = string_len = 0;
1437         missed = 0;
1438
1439         if (total > 0) {
1440                 qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp);
1441         }
1442
1443         {
1444                 char *lastname=NULL;
1445
1446                 for (i=0;i<total;i++) {
1447                         struct srv_info_struct *s = &servers[i];
1448
1449                         if (lastname && strequal(lastname,s->name)) {
1450                                 continue;
1451                         }
1452                         lastname = s->name;
1453                         data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
1454                         DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1455                                 s->name, s->type, s->comment, s->domain));
1456
1457                         if (data_len <= buf_len) {
1458                                 counted++;
1459                                 fixed_len += f_len;
1460                                 string_len += s_len;
1461                         } else {
1462                                 missed++;
1463                         }
1464                 }
1465         }
1466
1467         *rdata_len = fixed_len + string_len;
1468         *rdata = smb_realloc_limit(*rdata,*rdata_len);
1469         if (!*rdata) {
1470                 return False;
1471         }
1472
1473         p2 = (*rdata) + fixed_len;      /* auxilliary data (strings) will go here */
1474         p = *rdata;
1475         f_len = fixed_len;
1476         s_len = string_len;
1477
1478         {
1479                 char *lastname=NULL;
1480                 int count2 = counted;
1481
1482                 for (i = 0; i < total && count2;i++) {
1483                         struct srv_info_struct *s = &servers[i];
1484
1485                         if (lastname && strequal(lastname,s->name)) {
1486                                 continue;
1487                         }
1488                         lastname = s->name;
1489                         fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
1490                         DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1491                                 s->name, s->type, s->comment, s->domain));
1492                         count2--;
1493                 }
1494         }
1495
1496         *rparam_len = 8;
1497         *rparam = smb_realloc_limit(*rparam,*rparam_len);
1498         if (!*rparam) {
1499                 return False;
1500         }
1501         SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERRmoredata));
1502         SSVAL(*rparam,2,0);
1503         SSVAL(*rparam,4,counted);
1504         SSVAL(*rparam,6,counted+missed);
1505
1506         SAFE_FREE(servers);
1507
1508         DEBUG(3,("NetServerEnum2 domain = %s uLevel=%d counted=%d total=%d\n",
1509                 domain,uLevel,counted,counted+missed));
1510
1511         return True;
1512 }
1513
1514 /****************************************************************************
1515   command 0x34 - suspected of being a "Lookup Names" stub api
1516   ****************************************************************************/
1517
1518 static bool api_RNetGroupGetUsers(connection_struct *conn, uint16 vuid,
1519                                 char *param, int tpscnt,
1520                                 char *data, int tdscnt,
1521                                 int mdrcnt, int mprcnt, char **rdata, 
1522                                 char **rparam, int *rdata_len, int *rparam_len)
1523 {
1524         char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
1525         char *str2 = skip_string(param,tpscnt,str1);
1526         char *p = skip_string(param,tpscnt,str2);
1527         int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
1528         int buf_len = get_safe_SVAL(param,tpscnt,p,2,0);
1529         int counted=0;
1530         int missed=0;
1531
1532         if (!str1 || !str2 || !p) {
1533                 return False;
1534         }
1535
1536         DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
1537                 str1, str2, p, uLevel, buf_len));
1538
1539         if (!prefix_ok(str1,"zWrLeh")) {
1540                 return False;
1541         }
1542
1543         *rdata_len = 0;
1544
1545         *rparam_len = 8;
1546         *rparam = smb_realloc_limit(*rparam,*rparam_len);
1547         if (!*rparam) {
1548                 return False;
1549         }
1550
1551         SSVAL(*rparam,0,0x08AC); /* informational warning message */
1552         SSVAL(*rparam,2,0);
1553         SSVAL(*rparam,4,counted);
1554         SSVAL(*rparam,6,counted+missed);
1555
1556         return True;
1557 }
1558
1559 /****************************************************************************
1560   get info about a share
1561   ****************************************************************************/
1562
1563 static bool check_share_info(int uLevel, char* id)
1564 {
1565         switch( uLevel ) {
1566                 case 0:
1567                         if (strcmp(id,"B13") != 0) {
1568                                 return False;
1569                         }
1570                         break;
1571                 case 1:
1572                         /* Level-2 descriptor is allowed (and ignored) */
1573                         if (strcmp(id,"B13BWz") != 0 &&
1574                             strcmp(id,"B13BWzWWWzB9B") != 0) {
1575                                 return False;
1576                         }
1577                         break;
1578                 case 2:
1579                         if (strcmp(id,"B13BWzWWWzB9B") != 0) {
1580                                 return False;
1581                         }
1582                         break;
1583                 case 91:
1584                         if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) {
1585                                 return False;
1586                         }
1587                         break;
1588                 default:
1589                         return False;
1590         }
1591         return True;
1592 }
1593
1594 static int fill_share_info(connection_struct *conn, int snum, int uLevel,
1595                            char** buf, int* buflen,
1596                            char** stringbuf, int* stringspace, char* baseaddr)
1597 {
1598         int struct_len;
1599         char* p;
1600         char* p2;
1601         int l2;
1602         int len;
1603
1604         switch( uLevel ) {
1605                 case 0:
1606                         struct_len = 13;
1607                         break;
1608                 case 1:
1609                         struct_len = 20;
1610                         break;
1611                 case 2:
1612                         struct_len = 40;
1613                         break;
1614                 case 91:
1615                         struct_len = 68;
1616                         break;
1617                 default:
1618                         return -1;
1619         }
1620
1621         if (!buf) {
1622                 len = 0;
1623
1624                 if (uLevel > 0) {
1625                         len += StrlenExpanded(conn,snum,lp_comment(snum));
1626                 }
1627                 if (uLevel > 1) {
1628                         len += strlen(lp_pathname(snum)) + 1;
1629                 }
1630                 if (buflen) {
1631                         *buflen = struct_len;
1632                 }
1633                 if (stringspace) {
1634                         *stringspace = len;
1635                 }
1636                 return struct_len + len;
1637         }
1638
1639         len = struct_len;
1640         p = *buf;
1641         if ((*buflen) < struct_len) {
1642                 return -1;
1643         }
1644
1645         if (stringbuf) {
1646                 p2 = *stringbuf;
1647                 l2 = *stringspace;
1648         } else {
1649                 p2 = p + struct_len;
1650                 l2 = (*buflen) - struct_len;
1651         }
1652
1653         if (!baseaddr) {
1654                 baseaddr = p;
1655         }
1656
1657         push_ascii(p,lp_servicename(snum),13, STR_TERMINATE);
1658
1659         if (uLevel > 0) {
1660                 int type;
1661
1662                 SCVAL(p,13,0);
1663                 type = STYPE_DISKTREE;
1664                 if (lp_print_ok(snum)) {
1665                         type = STYPE_PRINTQ;
1666                 }
1667                 if (strequal("IPC",lp_fstype(snum))) {
1668                         type = STYPE_IPC;
1669                 }
1670                 SSVAL(p,14,type);               /* device type */
1671                 SIVAL(p,16,PTR_DIFF(p2,baseaddr));
1672                 len += CopyExpanded(conn,snum,&p2,lp_comment(snum),&l2);
1673         }
1674
1675         if (uLevel > 1) {
1676                 SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */
1677                 SSVALS(p,22,-1);                /* max uses */
1678                 SSVAL(p,24,1); /* current uses */
1679                 SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */
1680                 len += CopyAndAdvance(&p2,lp_pathname(snum),&l2);
1681                 memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */
1682         }
1683
1684         if (uLevel > 2) {
1685                 memset(p+40,0,SHPWLEN+2);
1686                 SSVAL(p,50,0);
1687                 SIVAL(p,52,0);
1688                 SSVAL(p,56,0);
1689                 SSVAL(p,58,0);
1690                 SIVAL(p,60,0);
1691                 SSVAL(p,64,0);
1692                 SSVAL(p,66,0);
1693         }
1694
1695         if (stringbuf) {
1696                 (*buf) = p + struct_len;
1697                 (*buflen) -= struct_len;
1698                 (*stringbuf) = p2;
1699                 (*stringspace) = l2;
1700         } else {
1701                 (*buf) = p2;
1702                 (*buflen) -= len;
1703         }
1704
1705         return len;
1706 }
1707
1708 static bool api_RNetShareGetInfo(connection_struct *conn,uint16 vuid,
1709                                 char *param, int tpscnt,
1710                                 char *data, int tdscnt,
1711                                 int mdrcnt,int mprcnt,
1712                                 char **rdata,char **rparam,
1713                                 int *rdata_len,int *rparam_len)
1714 {
1715         char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
1716         char *str2 = skip_string(param,tpscnt,str1);
1717         char *netname = skip_string(param,tpscnt,str2);
1718         char *p = skip_string(param,tpscnt,netname);
1719         int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
1720         int snum;
1721
1722         if (!str1 || !str2 || !netname || !p) {
1723                 return False;
1724         }
1725
1726         snum = find_service(netname);
1727         if (snum < 0) {
1728                 return False;
1729         }
1730
1731         /* check it's a supported varient */
1732         if (!prefix_ok(str1,"zWrLh")) {
1733                 return False;
1734         }
1735         if (!check_share_info(uLevel,str2)) {
1736                 return False;
1737         }
1738
1739         *rdata = smb_realloc_limit(*rdata,mdrcnt);
1740         if (!*rdata) {
1741                 return False;
1742         }
1743         p = *rdata;
1744         *rdata_len = fill_share_info(conn,snum,uLevel,&p,&mdrcnt,0,0,0);
1745         if (*rdata_len < 0) {
1746                 return False;
1747         }
1748
1749         *rparam_len = 6;
1750         *rparam = smb_realloc_limit(*rparam,*rparam_len);
1751         if (!*rparam) {
1752                 return False;
1753         }
1754         SSVAL(*rparam,0,NERR_Success);
1755         SSVAL(*rparam,2,0);             /* converter word */
1756         SSVAL(*rparam,4,*rdata_len);
1757
1758         return True;
1759 }
1760
1761 /****************************************************************************
1762   View the list of available shares.
1763
1764   This function is the server side of the NetShareEnum() RAP call.
1765   It fills the return buffer with share names and share comments.
1766   Note that the return buffer normally (in all known cases) allows only
1767   twelve byte strings for share names (plus one for a nul terminator).
1768   Share names longer than 12 bytes must be skipped.
1769  ****************************************************************************/
1770
1771 static bool api_RNetShareEnum( connection_struct *conn, uint16 vuid,
1772                                 char *param, int tpscnt,
1773                                 char *data, int tdscnt,
1774                                 int                mdrcnt,
1775                                 int                mprcnt,
1776                                 char             **rdata,
1777                                 char             **rparam,
1778                                 int               *rdata_len,
1779                                 int               *rparam_len )
1780 {
1781         char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
1782         char *str2 = skip_string(param,tpscnt,str1);
1783         char *p = skip_string(param,tpscnt,str2);
1784         int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
1785         int buf_len = get_safe_SVAL(param,tpscnt,p,2,0);
1786         char *p2;
1787         int count = 0;
1788         int total=0,counted=0;
1789         bool missed = False;
1790         int i;
1791         int data_len, fixed_len, string_len;
1792         int f_len = 0, s_len = 0;
1793
1794         if (!str1 || !str2 || !p) {
1795                 return False;
1796         }
1797
1798         if (!prefix_ok(str1,"WrLeh")) {
1799                 return False;
1800         }
1801         if (!check_share_info(uLevel,str2)) {
1802                 return False;
1803         }
1804
1805         /* Ensure all the usershares are loaded. */
1806         become_root();
1807         load_registry_shares();
1808         count = load_usershare_shares();
1809         unbecome_root();
1810
1811         data_len = fixed_len = string_len = 0;
1812         for (i=0;i<count;i++) {
1813                 fstring servicename_dos;
1814                 if (!(lp_browseable(i) && lp_snum_ok(i))) {
1815                         continue;
1816                 }
1817                 push_ascii_fstring(servicename_dos, lp_servicename(i));
1818                 /* Maximum name length = 13. */
1819                 if( lp_browseable( i ) && lp_snum_ok( i ) && (strlen(servicename_dos) < 13)) {
1820                         total++;
1821                         data_len += fill_share_info(conn,i,uLevel,0,&f_len,0,&s_len,0);
1822                         if (data_len <= buf_len) {
1823                                 counted++;
1824                                 fixed_len += f_len;
1825                                 string_len += s_len;
1826                         } else {
1827                                 missed = True;
1828                         }
1829                 }
1830         }
1831
1832         *rdata_len = fixed_len + string_len;
1833         *rdata = smb_realloc_limit(*rdata,*rdata_len);
1834         if (!*rdata) {
1835                 return False;
1836         }
1837
1838         p2 = (*rdata) + fixed_len;      /* auxiliary data (strings) will go here */
1839         p = *rdata;
1840         f_len = fixed_len;
1841         s_len = string_len;
1842
1843         for( i = 0; i < count; i++ ) {
1844                 fstring servicename_dos;
1845                 if (!(lp_browseable(i) && lp_snum_ok(i))) {
1846                         continue;
1847                 }
1848
1849                 push_ascii_fstring(servicename_dos, lp_servicename(i));
1850                 if (lp_browseable(i) && lp_snum_ok(i) && (strlen(servicename_dos) < 13)) {
1851                         if (fill_share_info( conn,i,uLevel,&p,&f_len,&p2,&s_len,*rdata ) < 0) {
1852                                 break;
1853                         }
1854                 }
1855         }
1856
1857         *rparam_len = 8;
1858         *rparam = smb_realloc_limit(*rparam,*rparam_len);
1859         if (!*rparam) {
1860                 return False;
1861         }
1862         SSVAL(*rparam,0,missed ? ERRmoredata : NERR_Success);
1863         SSVAL(*rparam,2,0);
1864         SSVAL(*rparam,4,counted);
1865         SSVAL(*rparam,6,total);
1866
1867         DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
1868                 counted,total,uLevel,
1869                 buf_len,*rdata_len,mdrcnt));
1870
1871         return True;
1872 }
1873
1874 /****************************************************************************
1875   Add a share
1876   ****************************************************************************/
1877
1878 static bool api_RNetShareAdd(connection_struct *conn,uint16 vuid,
1879                                 char *param, int tpscnt,
1880                                 char *data, int tdscnt,
1881                                 int mdrcnt,int mprcnt,
1882                                 char **rdata,char **rparam,
1883                                 int *rdata_len,int *rparam_len)
1884 {
1885         char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
1886         char *str2 = skip_string(param,tpscnt,str1);
1887         char *p = skip_string(param,tpscnt,str2);
1888         int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
1889         fstring sharename;
1890         fstring comment;
1891         char *pathname = NULL;
1892         char *command, *cmdname;
1893         unsigned int offset;
1894         int snum;
1895         int res = ERRunsup;
1896         size_t converted_size;
1897
1898         if (!str1 || !str2 || !p) {
1899                 return False;
1900         }
1901
1902         /* check it's a supported varient */
1903         if (!prefix_ok(str1,RAP_WShareAdd_REQ)) {
1904                 return False;
1905         }
1906         if (!check_share_info(uLevel,str2)) {
1907                 return False;
1908         }
1909         if (uLevel != 2) {
1910                 return False;
1911         }
1912
1913         /* Do we have a string ? */
1914         if (skip_string(data,mdrcnt,data) == NULL) {
1915                 return False;
1916         }
1917         pull_ascii_fstring(sharename,data);
1918         snum = find_service(sharename);
1919         if (snum >= 0) { /* already exists */
1920                 res = ERRfilexists;
1921                 goto error_exit;
1922         }
1923
1924         if (mdrcnt < 28) {
1925                 return False;
1926         }
1927
1928         /* only support disk share adds */
1929         if (SVAL(data,14)!=STYPE_DISKTREE) {
1930                 return False;
1931         }
1932
1933         offset = IVAL(data, 16);
1934         if (offset >= mdrcnt) {
1935                 res = ERRinvalidparam;
1936                 goto error_exit;
1937         }
1938
1939         /* Do we have a string ? */
1940         if (skip_string(data,mdrcnt,data+offset) == NULL) {
1941                 return False;
1942         }
1943         pull_ascii_fstring(comment, offset? (data+offset) : "");
1944
1945         offset = IVAL(data, 26);
1946
1947         if (offset >= mdrcnt) {
1948                 res = ERRinvalidparam;
1949                 goto error_exit;
1950         }
1951
1952         /* Do we have a string ? */
1953         if (skip_string(data,mdrcnt,data+offset) == NULL) {
1954                 return False;
1955         }
1956
1957         if (!pull_ascii_talloc(talloc_tos(), &pathname,
1958                                offset ? (data+offset) : "", &converted_size))
1959         {
1960                 DEBUG(0,("api_RNetShareAdd: pull_ascii_talloc failed: %s",
1961                          strerror(errno)));
1962         }
1963
1964         if (!pathname) {
1965                 return false;
1966         }
1967
1968         string_replace(sharename, '"', ' ');
1969         string_replace(pathname, '"', ' ');
1970         string_replace(comment, '"', ' ');
1971
1972         cmdname = lp_add_share_cmd();
1973
1974         if (!cmdname || *cmdname == '\0') {
1975                 return False;
1976         }
1977
1978         if (asprintf(&command, "%s \"%s\" \"%s\" \"%s\" \"%s\"",
1979                      lp_add_share_cmd(), get_dyn_CONFIGFILE(), sharename,
1980                      pathname, comment) == -1) {
1981                 return false;
1982         }
1983
1984         DEBUG(10,("api_RNetShareAdd: Running [%s]\n", command ));
1985
1986         if ((res = smbrun(command, NULL)) != 0) {
1987                 DEBUG(1,("api_RNetShareAdd: Running [%s] returned (%d)\n",
1988                          command, res ));
1989                 SAFE_FREE(command);
1990                 res = ERRnoaccess;
1991                 goto error_exit;
1992         } else {
1993                 SAFE_FREE(command);
1994                 message_send_all(smbd_messaging_context(),
1995                                  MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
1996         }
1997
1998         *rparam_len = 6;
1999         *rparam = smb_realloc_limit(*rparam,*rparam_len);
2000         if (!*rparam) {
2001                 return False;
2002         }
2003         SSVAL(*rparam,0,NERR_Success);
2004         SSVAL(*rparam,2,0);             /* converter word */
2005         SSVAL(*rparam,4,*rdata_len);
2006         *rdata_len = 0;
2007
2008         return True;
2009
2010   error_exit:
2011
2012         *rparam_len = 4;
2013         *rparam = smb_realloc_limit(*rparam,*rparam_len);
2014         if (!*rparam) {
2015                 return False;
2016         }
2017         *rdata_len = 0;
2018         SSVAL(*rparam,0,res);
2019         SSVAL(*rparam,2,0);
2020         return True;
2021 }
2022
2023 /****************************************************************************
2024   view list of groups available
2025   ****************************************************************************/
2026
2027 static bool api_RNetGroupEnum(connection_struct *conn,uint16 vuid,
2028                                 char *param, int tpscnt,
2029                                 char *data, int tdscnt,
2030                                 int mdrcnt,int mprcnt,
2031                                 char **rdata,char **rparam,
2032                                 int *rdata_len,int *rparam_len)
2033 {
2034         int i;
2035         int errflags=0;
2036         int resume_context, cli_buf_size;
2037         char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2038         char *str2 = skip_string(param,tpscnt,str1);
2039         char *p = skip_string(param,tpscnt,str2);
2040
2041         uint32_t num_groups;
2042         uint32_t resume_handle;
2043         struct rpc_pipe_client *samr_pipe;
2044         struct policy_handle samr_handle, domain_handle;
2045         NTSTATUS status;
2046
2047         if (!str1 || !str2 || !p) {
2048                 return False;
2049         }
2050
2051         if (strcmp(str1,"WrLeh") != 0) {
2052                 return False;
2053         }
2054
2055         /* parameters  
2056          * W-> resume context (number of users to skip)
2057          * r -> return parameter pointer to receive buffer 
2058          * L -> length of receive buffer
2059          * e -> return parameter number of entries
2060          * h -> return parameter total number of users
2061          */
2062
2063         if (strcmp("B21",str2) != 0) {
2064                 return False;
2065         }
2066
2067         status = rpc_pipe_open_internal(
2068                 talloc_tos(), &ndr_table_samr.syntax_id, rpc_samr_dispatch,
2069                 conn->server_info, &samr_pipe);
2070         if (!NT_STATUS_IS_OK(status)) {
2071                 DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
2072                           nt_errstr(status)));
2073                 return false;
2074         }
2075
2076         status = rpccli_samr_Connect2(samr_pipe, talloc_tos(), global_myname(),
2077                                       SAMR_ACCESS_LOOKUP_DOMAIN, &samr_handle);
2078         if (!NT_STATUS_IS_OK(status)) {
2079                 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2080                           nt_errstr(status)));
2081                 return false;
2082         }
2083
2084         status = rpccli_samr_OpenDomain(samr_pipe, talloc_tos(), &samr_handle,
2085                                         SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS,
2086                                         get_global_sam_sid(), &domain_handle);
2087         if (!NT_STATUS_IS_OK(status)) {
2088                 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2089                           nt_errstr(status)));
2090                 rpccli_samr_Close(samr_pipe, talloc_tos(), &samr_handle);
2091                 return false;
2092         }
2093
2094         resume_context = get_safe_SVAL(param,tpscnt,p,0,-1);
2095         cli_buf_size= get_safe_SVAL(param,tpscnt,p,2,0);
2096         DEBUG(10,("api_RNetGroupEnum:resume context: %d, client buffer size: "
2097                   "%d\n", resume_context, cli_buf_size));
2098
2099         *rdata_len = cli_buf_size;
2100         *rdata = smb_realloc_limit(*rdata,*rdata_len);
2101         if (!*rdata) {
2102                 return False;
2103         }
2104
2105         p = *rdata;
2106
2107         errflags = NERR_Success;
2108         num_groups = 0;
2109         resume_handle = 0;
2110
2111         while (true) {
2112                 struct samr_SamArray *sam_entries;
2113                 uint32_t num_entries;
2114
2115                 status = rpccli_samr_EnumDomainGroups(samr_pipe, talloc_tos(),
2116                                                       &domain_handle,
2117                                                       &resume_handle,
2118                                                       &sam_entries, 1,
2119                                                       &num_entries);
2120                 if (!NT_STATUS_IS_OK(status)) {
2121                         DEBUG(10, ("rpccli_samr_EnumDomainGroups returned "
2122                                    "%s\n", nt_errstr(status)));
2123                         break;
2124                 }
2125
2126                 if (num_entries == 0) {
2127                         DEBUG(10, ("rpccli_samr_EnumDomainGroups returned "
2128                                    "no entries -- done\n"));
2129                         break;
2130                 }
2131
2132                 for(i=0; i<num_entries; i++) {
2133                         const char *name;
2134
2135                         name = sam_entries->entries[i].name.string;
2136
2137                         if( ((PTR_DIFF(p,*rdata)+21) > *rdata_len) ) {
2138                                 /* set overflow error */
2139                                 DEBUG(3,("overflow on entry %d group %s\n", i,
2140                                          name));
2141                                 errflags=234;
2142                                 break;
2143                         }
2144
2145                         /* truncate the name at 21 chars. */
2146                         memset(p, 0, 21);
2147                         strlcpy(p, name, 21);
2148                         DEBUG(10,("adding entry %d group %s\n", i, p));
2149                         p += 21;
2150                         p += 5; /* Both NT4 and W2k3SP1 do padding here.  No
2151                                  * idea why... */
2152                         num_groups += 1;
2153                 }
2154
2155                 if (errflags != NERR_Success) {
2156                         break;
2157                 }
2158
2159                 TALLOC_FREE(sam_entries);
2160         }
2161
2162         rpccli_samr_Close(samr_pipe, talloc_tos(), &domain_handle);
2163         rpccli_samr_Close(samr_pipe, talloc_tos(), &samr_handle);
2164
2165         *rdata_len = PTR_DIFF(p,*rdata);
2166
2167         *rparam_len = 8;
2168         *rparam = smb_realloc_limit(*rparam,*rparam_len);
2169         if (!*rparam) {
2170                 return False;
2171         }
2172         SSVAL(*rparam, 0, errflags);
2173         SSVAL(*rparam, 2, 0);           /* converter word */
2174         SSVAL(*rparam, 4, num_groups);  /* is this right?? */
2175         SSVAL(*rparam, 6, resume_context+num_groups);   /* is this right?? */
2176
2177         return(True);
2178 }
2179
2180 /*******************************************************************
2181  Get groups that a user is a member of.
2182 ******************************************************************/
2183
2184 static bool api_NetUserGetGroups(connection_struct *conn,uint16 vuid,
2185                                 char *param, int tpscnt,
2186                                 char *data, int tdscnt,
2187                                 int mdrcnt,int mprcnt,
2188                                 char **rdata,char **rparam,
2189                                 int *rdata_len,int *rparam_len)
2190 {
2191         char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2192         char *str2 = skip_string(param,tpscnt,str1);
2193         char *UserName = skip_string(param,tpscnt,str2);
2194         char *p = skip_string(param,tpscnt,UserName);
2195         int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
2196         const char *level_string;
2197         int count=0;
2198         bool ret = False;
2199         uint32_t i;
2200         char *endp = NULL;
2201
2202         struct rpc_pipe_client *samr_pipe;
2203         struct policy_handle samr_handle, domain_handle, user_handle;
2204         struct lsa_String name;
2205         struct lsa_Strings names;
2206         struct samr_Ids type, rid;
2207         struct samr_RidWithAttributeArray *rids;
2208         NTSTATUS status;
2209
2210         if (!str1 || !str2 || !UserName || !p) {
2211                 return False;
2212         }
2213
2214         *rparam_len = 8;
2215         *rparam = smb_realloc_limit(*rparam,*rparam_len);
2216         if (!*rparam) {
2217                 return False;
2218         }
2219
2220         /* check it's a supported varient */
2221
2222         if ( strcmp(str1,"zWrLeh") != 0 )
2223                 return False;
2224
2225         switch( uLevel ) {
2226                 case 0:
2227                         level_string = "B21";
2228                         break;
2229                 default:
2230                         return False;
2231         }
2232
2233         if (strcmp(level_string,str2) != 0)
2234                 return False;
2235
2236         *rdata_len = mdrcnt + 1024;
2237         *rdata = smb_realloc_limit(*rdata,*rdata_len);
2238         if (!*rdata) {
2239                 return False;
2240         }
2241
2242         SSVAL(*rparam,0,NERR_Success);
2243         SSVAL(*rparam,2,0);             /* converter word */
2244
2245         p = *rdata;
2246         endp = *rdata + *rdata_len;
2247
2248         status = rpc_pipe_open_internal(
2249                 talloc_tos(), &ndr_table_samr.syntax_id, rpc_samr_dispatch,
2250                 conn->server_info, &samr_pipe);
2251         if (!NT_STATUS_IS_OK(status)) {
2252                 DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
2253                           nt_errstr(status)));
2254                 return false;
2255         }
2256
2257         status = rpccli_samr_Connect2(samr_pipe, talloc_tos(), global_myname(),
2258                                       SAMR_ACCESS_LOOKUP_DOMAIN, &samr_handle);
2259         if (!NT_STATUS_IS_OK(status)) {
2260                 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2261                           nt_errstr(status)));
2262                 return false;
2263         }
2264
2265         status = rpccli_samr_OpenDomain(samr_pipe, talloc_tos(), &samr_handle,
2266                                         SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
2267                                         get_global_sam_sid(), &domain_handle);
2268         if (!NT_STATUS_IS_OK(status)) {
2269                 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2270                           nt_errstr(status)));
2271                 goto close_sam;
2272         }
2273
2274         name.string = UserName;
2275
2276         status = rpccli_samr_LookupNames(samr_pipe, talloc_tos(),
2277                                          &domain_handle, 1, &name,
2278                                          &rid, &type);
2279         if (!NT_STATUS_IS_OK(status)) {
2280                 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2281                           nt_errstr(status)));
2282                 goto close_domain;
2283         }
2284
2285         if (type.ids[0] != SID_NAME_USER) {
2286                 DEBUG(10, ("%s is a %s, not a user\n", UserName,
2287                            sid_type_lookup(type.ids[0])));
2288                 goto close_domain;
2289         }
2290
2291         status = rpccli_samr_OpenUser(samr_pipe, talloc_tos(),
2292                                       &domain_handle,
2293                                       SAMR_USER_ACCESS_GET_GROUPS,
2294                                       rid.ids[0], &user_handle);
2295         if (!NT_STATUS_IS_OK(status)) {
2296                 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2297                           nt_errstr(status)));
2298                 goto close_domain;
2299         }
2300
2301         status = rpccli_samr_GetGroupsForUser(samr_pipe, talloc_tos(),
2302                                               &user_handle, &rids);
2303         if (!NT_STATUS_IS_OK(status)) {
2304                 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2305                           nt_errstr(status)));
2306                 goto close_user;
2307         }
2308
2309         for (i=0; i<rids->count; i++) {
2310
2311                 status = rpccli_samr_LookupRids(samr_pipe, talloc_tos(),
2312                                                 &domain_handle,
2313                                                 1, &rids->rids[i].rid,
2314                                                 &names, &type);
2315                 if (NT_STATUS_IS_OK(status) && (names.count == 1)) {
2316                         strlcpy(p, names.names[0].string, PTR_DIFF(endp,p));
2317                         p += 21;
2318                         count++;
2319                 }
2320         }
2321
2322         *rdata_len = PTR_DIFF(p,*rdata);
2323
2324         SSVAL(*rparam,4,count); /* is this right?? */
2325         SSVAL(*rparam,6,count); /* is this right?? */
2326
2327         ret = True;
2328
2329  close_user:
2330         rpccli_samr_Close(samr_pipe, talloc_tos(), &user_handle);
2331  close_domain:
2332         rpccli_samr_Close(samr_pipe, talloc_tos(), &domain_handle);
2333  close_sam:
2334         rpccli_samr_Close(samr_pipe, talloc_tos(), &samr_handle);
2335
2336         return ret;
2337 }
2338
2339 /*******************************************************************
2340  Get all users.
2341 ******************************************************************/
2342
2343 static bool api_RNetUserEnum(connection_struct *conn, uint16 vuid,
2344                                 char *param, int tpscnt,
2345                                 char *data, int tdscnt,
2346                                 int mdrcnt,int mprcnt,
2347                                 char **rdata,char **rparam,
2348                                 int *rdata_len,int *rparam_len)
2349 {
2350         int count_sent=0;
2351         int num_users=0;
2352         int errflags=0;
2353         int i, resume_context, cli_buf_size;
2354         uint32_t resume_handle;
2355
2356         struct rpc_pipe_client *samr_pipe;
2357         struct policy_handle samr_handle, domain_handle;
2358         NTSTATUS status;
2359
2360         char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2361         char *str2 = skip_string(param,tpscnt,str1);
2362         char *p = skip_string(param,tpscnt,str2);
2363         char *endp = NULL;
2364
2365         if (!str1 || !str2 || !p) {
2366                 return False;
2367         }
2368
2369         if (strcmp(str1,"WrLeh") != 0)
2370                 return False;
2371         /* parameters
2372           * W-> resume context (number of users to skip)
2373           * r -> return parameter pointer to receive buffer
2374           * L -> length of receive buffer
2375           * e -> return parameter number of entries
2376           * h -> return parameter total number of users
2377           */
2378
2379         resume_context = get_safe_SVAL(param,tpscnt,p,0,-1);
2380         cli_buf_size= get_safe_SVAL(param,tpscnt,p,2,0);
2381         DEBUG(10,("api_RNetUserEnum:resume context: %d, client buffer size: %d\n",
2382                         resume_context, cli_buf_size));
2383
2384         *rparam_len = 8;
2385         *rparam = smb_realloc_limit(*rparam,*rparam_len);
2386         if (!*rparam) {
2387                 return False;
2388         }
2389
2390         /* check it's a supported varient */
2391         if (strcmp("B21",str2) != 0)
2392                 return False;
2393
2394         *rdata_len = cli_buf_size;
2395         *rdata = smb_realloc_limit(*rdata,*rdata_len);
2396         if (!*rdata) {
2397                 return False;
2398         }
2399
2400         p = *rdata;
2401         endp = *rdata + *rdata_len;
2402
2403         status = rpc_pipe_open_internal(
2404                 talloc_tos(), &ndr_table_samr.syntax_id, rpc_samr_dispatch,
2405                 conn->server_info, &samr_pipe);
2406         if (!NT_STATUS_IS_OK(status)) {
2407                 DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
2408                           nt_errstr(status)));
2409                 return false;
2410         }
2411
2412         status = rpccli_samr_Connect2(samr_pipe, talloc_tos(), global_myname(),
2413                                       SAMR_ACCESS_LOOKUP_DOMAIN, &samr_handle);
2414         if (!NT_STATUS_IS_OK(status)) {
2415                 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2416                           nt_errstr(status)));
2417                 return false;
2418         }
2419
2420         status = rpccli_samr_OpenDomain(samr_pipe, talloc_tos(), &samr_handle,
2421                                         SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS,
2422                                         get_global_sam_sid(), &domain_handle);
2423         if (!NT_STATUS_IS_OK(status)) {
2424                 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2425                           nt_errstr(status)));
2426                 rpccli_samr_Close(samr_pipe, talloc_tos(), &samr_handle);
2427                 return false;
2428         }
2429
2430         errflags=NERR_Success;
2431
2432         resume_handle = 0;
2433
2434         while (true) {
2435                 struct samr_SamArray *sam_entries;
2436                 uint32_t num_entries;
2437
2438                 status = rpccli_samr_EnumDomainUsers(samr_pipe, talloc_tos(),
2439                                                      &domain_handle,
2440                                                      &resume_handle,
2441                                                      0, &sam_entries, 1,
2442                                                      &num_entries);
2443
2444                 if (!NT_STATUS_IS_OK(status)) {
2445                         DEBUG(10, ("rpccli_samr_EnumDomainUsers returned "
2446                                    "%s\n", nt_errstr(status)));
2447                         break;
2448                 }
2449
2450                 if (num_entries == 0) {
2451                         DEBUG(10, ("rpccli_samr_EnumDomainUsers returned "
2452                                    "no entries -- done\n"));
2453                         break;
2454                 }
2455
2456                 for (i=0; i<num_entries; i++) {
2457                         const char *name;
2458
2459                         name = sam_entries->entries[i].name.string;
2460
2461                         if(((PTR_DIFF(p,*rdata)+21)<=*rdata_len)
2462                            &&(strlen(name)<=21)) {
2463                                 strlcpy(p,name,PTR_DIFF(endp,p));
2464                                 DEBUG(10,("api_RNetUserEnum:adding entry %d "
2465                                           "username %s\n",count_sent,p));
2466                                 p += 21;
2467                                 count_sent++;
2468                         } else {
2469                                 /* set overflow error */
2470                                 DEBUG(10,("api_RNetUserEnum:overflow on entry %d "
2471                                           "username %s\n",count_sent,name));
2472                                 errflags=234;
2473                                 break;
2474                         }
2475                 }
2476
2477                 if (errflags != NERR_Success) {
2478                         break;
2479                 }
2480
2481                 TALLOC_FREE(sam_entries);
2482         }
2483
2484         rpccli_samr_Close(samr_pipe, talloc_tos(), &domain_handle);
2485         rpccli_samr_Close(samr_pipe, talloc_tos(), &samr_handle);
2486
2487         *rdata_len = PTR_DIFF(p,*rdata);
2488
2489         SSVAL(*rparam,0,errflags);
2490         SSVAL(*rparam,2,0);           /* converter word */
2491         SSVAL(*rparam,4,count_sent);  /* is this right?? */
2492         SSVAL(*rparam,6,num_users); /* is this right?? */
2493
2494         return True;
2495 }
2496
2497 /****************************************************************************
2498  Get the time of day info.
2499 ****************************************************************************/
2500
2501 static bool api_NetRemoteTOD(connection_struct *conn,uint16 vuid,
2502                                 char *param, int tpscnt,
2503                                 char *data, int tdscnt,
2504                                 int mdrcnt,int mprcnt,
2505                                 char **rdata,char **rparam,
2506                                 int *rdata_len,int *rparam_len)
2507 {
2508         struct tm *t;
2509         time_t unixdate = time(NULL);
2510         char *p;
2511
2512         *rparam_len = 4;
2513         *rparam = smb_realloc_limit(*rparam,*rparam_len);
2514         if (!*rparam) {
2515                 return False;
2516         }
2517
2518         *rdata_len = 21;
2519         *rdata = smb_realloc_limit(*rdata,*rdata_len);
2520         if (!*rdata) {
2521                 return False;
2522         }
2523
2524         SSVAL(*rparam,0,NERR_Success);
2525         SSVAL(*rparam,2,0);             /* converter word */
2526
2527         p = *rdata;
2528
2529         srv_put_dos_date3(p,0,unixdate); /* this is the time that is looked at
2530                                             by NT in a "net time" operation,
2531                                             it seems to ignore the one below */
2532
2533         /* the client expects to get localtime, not GMT, in this bit 
2534                 (I think, this needs testing) */
2535         t = localtime(&unixdate);
2536         if (!t) {
2537                 return False;
2538         }
2539
2540         SIVAL(p,4,0);           /* msecs ? */
2541         SCVAL(p,8,t->tm_hour);
2542         SCVAL(p,9,t->tm_min);
2543         SCVAL(p,10,t->tm_sec);
2544         SCVAL(p,11,0);          /* hundredths of seconds */
2545         SSVALS(p,12,get_time_zone(unixdate)/60); /* timezone in minutes from GMT */
2546         SSVAL(p,14,10000);              /* timer interval in 0.0001 of sec */
2547         SCVAL(p,16,t->tm_mday);
2548         SCVAL(p,17,t->tm_mon + 1);
2549         SSVAL(p,18,1900+t->tm_year);
2550         SCVAL(p,20,t->tm_wday);
2551
2552         return True;
2553 }
2554
2555 /****************************************************************************
2556  Set the user password.
2557 *****************************************************************************/
2558
2559 static bool api_SetUserPassword(connection_struct *conn,uint16 vuid,
2560                                 char *param, int tpscnt,
2561                                 char *data, int tdscnt,
2562                                 int mdrcnt,int mprcnt,
2563                                 char **rdata,char **rparam,
2564                                 int *rdata_len,int *rparam_len)
2565 {
2566         char *np = get_safe_str_ptr(param,tpscnt,param,2);
2567         char *p = NULL;
2568         fstring user;
2569         fstring pass1,pass2;
2570
2571         /* Skip 2 strings. */
2572         p = skip_string(param,tpscnt,np);
2573         p = skip_string(param,tpscnt,p);
2574
2575         if (!np || !p) {
2576                 return False;
2577         }
2578
2579         /* Do we have a string ? */
2580         if (skip_string(param,tpscnt,p) == NULL) {
2581                 return False;
2582         }
2583         pull_ascii_fstring(user,p);
2584
2585         p = skip_string(param,tpscnt,p);
2586         if (!p) {
2587                 return False;
2588         }
2589
2590         memset(pass1,'\0',sizeof(pass1));
2591         memset(pass2,'\0',sizeof(pass2));
2592         /*
2593          * We use 31 here not 32 as we're checking
2594          * the last byte we want to access is safe.
2595          */
2596         if (!is_offset_safe(param,tpscnt,p,31)) {
2597                 return False;
2598         }
2599         memcpy(pass1,p,16);
2600         memcpy(pass2,p+16,16);
2601
2602         *rparam_len = 4;
2603         *rparam = smb_realloc_limit(*rparam,*rparam_len);
2604         if (!*rparam) {
2605                 return False;
2606         }
2607
2608         *rdata_len = 0;
2609
2610         SSVAL(*rparam,0,NERR_badpass);
2611         SSVAL(*rparam,2,0);             /* converter word */
2612
2613         DEBUG(3,("Set password for <%s>\n",user));
2614
2615         /*
2616          * Attempt to verify the old password against smbpasswd entries
2617          * Win98 clients send old and new password in plaintext for this call.
2618          */
2619
2620         {
2621                 struct auth_serversupplied_info *server_info = NULL;
2622                 DATA_BLOB password = data_blob(pass1, strlen(pass1)+1);
2623
2624                 if (NT_STATUS_IS_OK(check_plaintext_password(user,password,&server_info))) {
2625
2626                         become_root();
2627                         if (NT_STATUS_IS_OK(change_oem_password(server_info->sam_account, pass1, pass2, False, NULL))) {
2628                                 SSVAL(*rparam,0,NERR_Success);
2629                         }
2630                         unbecome_root();
2631
2632                         TALLOC_FREE(server_info);
2633                 }
2634                 data_blob_clear_free(&password);
2635         }
2636
2637         /*
2638          * If the plaintext change failed, attempt
2639          * the old encrypted method. NT will generate this
2640          * after trying the samr method. Note that this
2641          * method is done as a last resort as this
2642          * password change method loses the NT password hash
2643          * and cannot change the UNIX password as no plaintext
2644          * is received.
2645          */
2646
2647         if(SVAL(*rparam,0) != NERR_Success) {
2648                 struct samu *hnd = NULL;
2649
2650                 if (check_lanman_password(user,(unsigned char *)pass1,(unsigned char *)pass2, &hnd)) {
2651                         become_root();
2652                         if (change_lanman_password(hnd,(uchar *)pass2)) {
2653                                 SSVAL(*rparam,0,NERR_Success);
2654                         }
2655                         unbecome_root();
2656                         TALLOC_FREE(hnd);
2657                 }
2658         }
2659
2660         memset((char *)pass1,'\0',sizeof(fstring));
2661         memset((char *)pass2,'\0',sizeof(fstring));      
2662
2663         return(True);
2664 }
2665
2666 /****************************************************************************
2667   Set the user password (SamOEM version - gets plaintext).
2668 ****************************************************************************/
2669
2670 static bool api_SamOEMChangePassword(connection_struct *conn,uint16 vuid,
2671                                 char *param, int tpscnt,
2672                                 char *data, int tdscnt,
2673                                 int mdrcnt,int mprcnt,
2674                                 char **rdata,char **rparam,
2675                                 int *rdata_len,int *rparam_len)
2676 {
2677         struct smbd_server_connection *sconn = smbd_server_conn;
2678         fstring user;
2679         char *p = get_safe_str_ptr(param,tpscnt,param,2);
2680         *rparam_len = 2;
2681         *rparam = smb_realloc_limit(*rparam,*rparam_len);
2682         if (!*rparam) {
2683                 return False;
2684         }
2685
2686         if (!p) {
2687                 return False;
2688         }
2689         *rdata_len = 0;
2690
2691         SSVAL(*rparam,0,NERR_badpass);
2692
2693         /*
2694          * Check the parameter definition is correct.
2695          */
2696
2697         /* Do we have a string ? */
2698         if (skip_string(param,tpscnt,p) == 0) {
2699                 return False;
2700         }
2701         if(!strequal(p, "zsT")) {
2702                 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", p));
2703                 return False;
2704         }
2705         p = skip_string(param, tpscnt, p);
2706         if (!p) {
2707                 return False;
2708         }
2709
2710         /* Do we have a string ? */
2711         if (skip_string(param,tpscnt,p) == 0) {
2712                 return False;
2713         }
2714         if(!strequal(p, "B516B16")) {
2715                 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p));
2716                 return False;
2717         }
2718         p = skip_string(param,tpscnt,p);
2719         if (!p) {
2720                 return False;
2721         }
2722         /* Do we have a string ? */
2723         if (skip_string(param,tpscnt,p) == 0) {
2724                 return False;
2725         }
2726         p += pull_ascii_fstring(user,p);
2727
2728         DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user));
2729
2730         /*
2731          * Pass the user through the NT -> unix user mapping
2732          * function.
2733          */
2734
2735         (void)map_username(sconn, user);
2736
2737         if (NT_STATUS_IS_OK(pass_oem_change(user, (uchar*) data, (uchar *)&data[516], NULL, NULL, NULL))) {
2738                 SSVAL(*rparam,0,NERR_Success);
2739         }
2740
2741         return(True);
2742 }
2743
2744 /****************************************************************************
2745   delete a print job
2746   Form: <W> <> 
2747   ****************************************************************************/
2748
2749 static bool api_RDosPrintJobDel(connection_struct *conn,uint16 vuid,
2750                                 char *param, int tpscnt,
2751                                 char *data, int tdscnt,
2752                                 int mdrcnt,int mprcnt,
2753                                 char **rdata,char **rparam,
2754                                 int *rdata_len,int *rparam_len)
2755 {
2756         int function = get_safe_SVAL(param,tpscnt,param,0,0);
2757         char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2758         char *str2 = skip_string(param,tpscnt,str1);
2759         char *p = skip_string(param,tpscnt,str2);
2760         uint32 jobid;
2761         int snum;
2762         fstring sharename;
2763         int errcode;
2764         WERROR werr = WERR_OK;
2765
2766         if (!str1 || !str2 || !p) {
2767                 return False;
2768         }
2769         /*
2770          * We use 1 here not 2 as we're checking
2771          * the last byte we want to access is safe.
2772          */
2773         if (!is_offset_safe(param,tpscnt,p,1)) {
2774                 return False;
2775         }
2776         if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid))
2777                 return False;
2778
2779         /* check it's a supported varient */
2780         if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
2781                 return(False);
2782
2783         *rparam_len = 4;
2784         *rparam = smb_realloc_limit(*rparam,*rparam_len);
2785         if (!*rparam) {
2786                 return False;
2787         }
2788         *rdata_len = 0;
2789
2790         if (!print_job_exists(sharename, jobid)) {
2791                 errcode = NERR_JobNotFound;
2792                 goto out;
2793         }
2794
2795         snum = lp_servicenumber( sharename);
2796         if (snum == -1) {
2797                 errcode = NERR_DestNotFound;
2798                 goto out;
2799         }
2800
2801         errcode = NERR_notsupported;
2802
2803         switch (function) {
2804         case 81:                /* delete */ 
2805                 if (print_job_delete(conn->server_info, snum, jobid, &werr))
2806                         errcode = NERR_Success;
2807                 break;
2808         case 82:                /* pause */
2809                 if (print_job_pause(conn->server_info, snum, jobid, &werr))
2810                         errcode = NERR_Success;
2811                 break;
2812         case 83:                /* resume */
2813                 if (print_job_resume(conn->server_info, snum, jobid, &werr))
2814                         errcode = NERR_Success;
2815                 break;
2816         }
2817
2818         if (!W_ERROR_IS_OK(werr))
2819                 errcode = W_ERROR_V(werr);
2820
2821  out:
2822         SSVAL(*rparam,0,errcode);       
2823         SSVAL(*rparam,2,0);             /* converter word */
2824
2825         return(True);
2826 }
2827
2828 /****************************************************************************
2829   Purge a print queue - or pause or resume it.
2830   ****************************************************************************/
2831
2832 static bool api_WPrintQueueCtrl(connection_struct *conn,uint16 vuid,
2833                                 char *param, int tpscnt,
2834                                 char *data, int tdscnt,
2835                                 int mdrcnt,int mprcnt,
2836                                 char **rdata,char **rparam,
2837                                 int *rdata_len,int *rparam_len)
2838 {
2839         int function = get_safe_SVAL(param,tpscnt,param,0,0);
2840         char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2841         char *str2 = skip_string(param,tpscnt,str1);
2842         char *QueueName = skip_string(param,tpscnt,str2);
2843         int errcode = NERR_notsupported;
2844         int snum;
2845         WERROR werr = WERR_OK;
2846
2847         if (!str1 || !str2 || !QueueName) {
2848                 return False;
2849         }
2850
2851         /* check it's a supported varient */
2852         if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
2853                 return(False);
2854
2855         *rparam_len = 4;
2856         *rparam = smb_realloc_limit(*rparam,*rparam_len);
2857         if (!*rparam) {
2858                 return False;
2859         }
2860         *rdata_len = 0;
2861
2862         if (skip_string(param,tpscnt,QueueName) == NULL) {
2863                 return False;
2864         }
2865         snum = print_queue_snum(QueueName);
2866
2867         if (snum == -1) {
2868                 errcode = NERR_JobNotFound;
2869                 goto out;
2870         }
2871
2872         switch (function) {
2873         case 74: /* Pause queue */
2874                 werr = print_queue_pause(conn->server_info, snum);
2875                 break;
2876         case 75: /* Resume queue */
2877                 werr = print_queue_resume(conn->server_info, snum);
2878                 break;
2879         case 103: /* Purge */
2880                 werr = print_queue_purge(conn->server_info, snum);
2881                 break;
2882         default:
2883                 werr = WERR_NOT_SUPPORTED;
2884                 break;
2885         }
2886
2887         errcode = W_ERROR_V(werr);
2888
2889  out:
2890         SSVAL(*rparam,0,errcode);
2891         SSVAL(*rparam,2,0);             /* converter word */
2892
2893         return(True);
2894 }
2895
2896 /****************************************************************************
2897   set the property of a print job (undocumented?)
2898   ? function = 0xb -> set name of print job
2899   ? function = 0x6 -> move print job up/down
2900   Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz> 
2901   or   <WWsTP> <WB21BB16B10zWWzDDz> 
2902 ****************************************************************************/
2903
2904 static int check_printjob_info(struct pack_desc* desc,
2905                                int uLevel, char* id)
2906 {
2907         desc->subformat = NULL;
2908         switch( uLevel ) {
2909         case 0: desc->format = "W"; break;
2910         case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
2911         case 2: desc->format = "WWzWWDDzz"; break;
2912         case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
2913         case 4: desc->format = "WWzWWDDzzzzzDDDDDDD"; break;
2914         default:
2915                 DEBUG(0,("check_printjob_info: invalid level %d\n",
2916                         uLevel ));
2917                 return False;
2918         }
2919         if (id == NULL || strcmp(desc->format,id) != 0) {
2920                 DEBUG(0,("check_printjob_info: invalid format %s\n",
2921                         id ? id : "<NULL>" ));
2922                 return False;
2923         }
2924         return True;
2925 }
2926
2927 static bool api_PrintJobInfo(connection_struct *conn, uint16 vuid,
2928                                 char *param, int tpscnt,
2929                                 char *data, int tdscnt,
2930                                 int mdrcnt,int mprcnt,
2931                                 char **rdata,char **rparam,
2932                                 int *rdata_len,int *rparam_len)
2933 {
2934         struct pack_desc desc;
2935         char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2936         char *str2 = skip_string(param,tpscnt,str1);
2937         char *p = skip_string(param,tpscnt,str2);
2938         uint32 jobid;
2939         fstring sharename;
2940         int uLevel = get_safe_SVAL(param,tpscnt,p,2,-1);
2941         int function = get_safe_SVAL(param,tpscnt,p,4,-1);
2942         int place, errcode;
2943
2944         if (!str1 || !str2 || !p) {
2945                 return False;
2946         }
2947         /*
2948          * We use 1 here not 2 as we're checking
2949          * the last byte we want to access is safe.
2950          */
2951         if (!is_offset_safe(param,tpscnt,p,1)) {
2952                 return False;
2953         }
2954         if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid))
2955                 return False;
2956         *rparam_len = 4;
2957         *rparam = smb_realloc_limit(*rparam,*rparam_len);
2958         if (!*rparam) {
2959                 return False;
2960         }
2961
2962         if (!share_defined(sharename)) {
2963                 DEBUG(0,("api_PrintJobInfo: sharen [%s] not defined\n",
2964                          sharename));
2965                 return False;
2966         }
2967
2968         *rdata_len = 0;
2969
2970         /* check it's a supported varient */
2971         if ((strcmp(str1,"WWsTP")) || 
2972             (!check_printjob_info(&desc,uLevel,str2)))
2973                 return(False);
2974
2975         if (!print_job_exists(sharename, jobid)) {
2976                 errcode=NERR_JobNotFound;
2977                 goto out;
2978         }
2979
2980         errcode = NERR_notsupported;
2981
2982         switch (function) {
2983         case 0x6:
2984                 /* change job place in the queue, 
2985                    data gives the new place */
2986                 place = SVAL(data,0);
2987                 if (print_job_set_place(sharename, jobid, place)) {
2988                         errcode=NERR_Success;
2989                 }
2990                 break;
2991
2992         case 0xb:   
2993                 /* change print job name, data gives the name */
2994                 if (print_job_set_name(sharename, jobid, data)) {
2995                         errcode=NERR_Success;
2996                 }
2997                 break;
2998
2999         default:
3000                 return False;
3001         }
3002
3003  out:
3004         SSVALS(*rparam,0,errcode);
3005         SSVAL(*rparam,2,0);             /* converter word */
3006
3007         return(True);
3008 }
3009
3010
3011 /****************************************************************************
3012  Get info about the server.
3013 ****************************************************************************/
3014
3015 static bool api_RNetServerGetInfo(connection_struct *conn,uint16 vuid,
3016                                 char *param, int tpscnt,
3017                                 char *data, int tdscnt,
3018                                 int mdrcnt,int mprcnt,
3019                                 char **rdata,char **rparam,
3020                                 int *rdata_len,int *rparam_len)
3021 {
3022         char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3023         char *str2 = skip_string(param,tpscnt,str1);
3024         char *p = skip_string(param,tpscnt,str2);
3025         int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
3026         char *p2;
3027         int struct_len;
3028
3029         if (!str1 || !str2 || !p) {
3030                 return False;
3031         }
3032
3033         DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
3034
3035         /* check it's a supported varient */
3036         if (!prefix_ok(str1,"WrLh")) {
3037                 return False;
3038         }
3039
3040         switch( uLevel ) {
3041                 case 0:
3042                         if (strcmp(str2,"B16") != 0) {
3043                                 return False;
3044                         }
3045                         struct_len = 16;
3046                         break;
3047                 case 1:
3048                         if (strcmp(str2,"B16BBDz") != 0) {
3049                                 return False;
3050                         }
3051                         struct_len = 26;
3052                         break;
3053                 case 2:
3054                         if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")!= 0) {
3055                                 return False;
3056                         }
3057                         struct_len = 134;
3058                         break;
3059                 case 3:
3060                         if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz") != 0) {
3061                                 return False;
3062                         }
3063                         struct_len = 144;
3064                         break;
3065                 case 20:
3066                         if (strcmp(str2,"DN") != 0) {
3067                                 return False;
3068                         }
3069                         struct_len = 6;
3070                         break;
3071                 case 50:
3072                         if (strcmp(str2,"B16BBDzWWzzz") != 0) {
3073                                 return False;
3074                         }
3075                         struct_len = 42;
3076                         break;
3077                 default:
3078                         return False;
3079         }
3080
3081         *rdata_len = mdrcnt;
3082         *rdata = smb_realloc_limit(*rdata,*rdata_len);
3083         if (!*rdata) {
3084                 return False;
3085         }
3086
3087         p = *rdata;
3088         p2 = p + struct_len;
3089         if (uLevel != 20) {
3090                 srvstr_push(NULL, 0, p,global_myname(),16,
3091                         STR_ASCII|STR_UPPER|STR_TERMINATE);
3092         }
3093         p += 16;
3094         if (uLevel > 0) {
3095                 struct srv_info_struct *servers=NULL;
3096                 int i,count;
3097                 char *comment = NULL;
3098                 TALLOC_CTX *ctx = talloc_tos();
3099                 uint32 servertype= lp_default_server_announce();
3100
3101                 comment = talloc_strdup(ctx,lp_serverstring());
3102                 if (!comment) {
3103                         return false;
3104                 }
3105
3106                 if ((count=get_server_info(SV_TYPE_ALL,&servers,lp_workgroup()))>0) {
3107                         for (i=0;i<count;i++) {
3108                                 if (strequal(servers[i].name,global_myname())) {
3109                                         servertype = servers[i].type;
3110                                         TALLOC_FREE(comment);
3111                                         comment = talloc_strdup(ctx,
3112                                                         servers[i].comment);
3113                                         if (comment) {
3114                                                 return false;
3115                                         }
3116                                 }
3117                         }
3118                 }
3119
3120                 SAFE_FREE(servers);
3121
3122                 SCVAL(p,0,lp_major_announce_version());
3123                 SCVAL(p,1,lp_minor_announce_version());
3124                 SIVAL(p,2,servertype);
3125
3126                 if (mdrcnt == struct_len) {
3127                         SIVAL(p,6,0);
3128                 } else {
3129                         SIVAL(p,6,PTR_DIFF(p2,*rdata));
3130                         comment = talloc_sub_advanced(
3131                                 ctx,
3132                                 lp_servicename(SNUM(conn)),
3133                                 conn->server_info->unix_name,
3134                                 conn->connectpath,
3135                                 conn->server_info->utok.gid,
3136                                 conn->server_info->sanitized_username,
3137                                 pdb_get_domain(conn->server_info->sam_account),
3138                                 comment);
3139                         if (comment) {
3140                                 return false;
3141                         }
3142                         if (mdrcnt - struct_len <= 0) {
3143                                 return false;
3144                         }
3145                         push_ascii(p2,
3146                                 comment,
3147                                 MIN(mdrcnt - struct_len,
3148                                         MAX_SERVER_STRING_LENGTH),
3149                                 STR_TERMINATE);
3150                         p2 = skip_string(*rdata,*rdata_len,p2);
3151                         if (!p2) {
3152                                 return False;
3153                         }
3154                 }
3155         }
3156
3157         if (uLevel > 1) {
3158                 return False;           /* not yet implemented */
3159         }
3160
3161         *rdata_len = PTR_DIFF(p2,*rdata);
3162
3163         *rparam_len = 6;
3164         *rparam = smb_realloc_limit(*rparam,*rparam_len);
3165         if (!*rparam) {
3166                 return False;
3167         }
3168         SSVAL(*rparam,0,NERR_Success);
3169         SSVAL(*rparam,2,0);             /* converter word */
3170         SSVAL(*rparam,4,*rdata_len);
3171
3172         return True;
3173 }
3174
3175 /****************************************************************************
3176  Get info about the server.
3177 ****************************************************************************/
3178
3179 static bool api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid,
3180                                 char *param, int tpscnt,
3181                                 char *data, int tdscnt,
3182                                 int mdrcnt,int mprcnt,
3183                                 char **rdata,char **rparam,
3184                                 int *rdata_len,int *rparam_len)
3185 {
3186         char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3187         char *str2 = skip_string(param,tpscnt,str1);
3188         char *p = skip_string(param,tpscnt,str2);
3189         char *p2;
3190         char *endp;
3191         int level = get_safe_SVAL(param,tpscnt,p,0,-1);
3192
3193         if (!str1 || !str2 || !p) {
3194                 return False;
3195         }
3196
3197         DEBUG(4,("NetWkstaGetInfo level %d\n",level));
3198
3199         *rparam_len = 6;
3200         *rparam = smb_realloc_limit(*rparam,*rparam_len);
3201         if (!*rparam) {
3202                 return False;
3203         }
3204
3205         /* check it's a supported varient */
3206         if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz"))) {
3207                 return False;
3208         }
3209
3210         *rdata_len = mdrcnt + 1024;
3211         *rdata = smb_realloc_limit(*rdata,*rdata_len);
3212         if (!*rdata) {
3213                 return False;
3214         }
3215
3216         SSVAL(*rparam,0,NERR_Success);
3217         SSVAL(*rparam,2,0);             /* converter word */
3218
3219         p = *rdata;
3220         endp = *rdata + *rdata_len;