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