s3: Remove an unused variable
[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 static bool api_RNetUserGetInfo(connection_struct *conn, uint16 vuid,
4014                                 char *param, int tpscnt,
4015                                 char *data, int tdscnt,
4016                                 int mdrcnt,int mprcnt,
4017                                 char **rdata,char **rparam,
4018                                 int *rdata_len,int *rparam_len)
4019 {
4020         char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4021         char *str2 = skip_string(param,tpscnt,str1);
4022         char *UserName = skip_string(param,tpscnt,str2);
4023         char *p = skip_string(param,tpscnt,UserName);
4024         int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4025         char *p2;
4026         char *endp;
4027         const char *level_string;
4028
4029         TALLOC_CTX *mem_ctx = talloc_tos();
4030         NTSTATUS status;
4031         struct rpc_pipe_client *cli = NULL;
4032         struct policy_handle connect_handle, domain_handle, user_handle;
4033         struct lsa_String domain_name;
4034         struct dom_sid2 *domain_sid;
4035         struct lsa_String names;
4036         struct samr_Ids rids;
4037         struct samr_Ids types;
4038         int errcode = W_ERROR_V(WERR_USER_NOT_FOUND);
4039         uint32_t rid;
4040         union samr_UserInfo *info;
4041
4042         if (!str1 || !str2 || !UserName || !p) {
4043                 return False;
4044         }
4045
4046         *rparam_len = 6;
4047         *rparam = smb_realloc_limit(*rparam,*rparam_len);
4048         if (!*rparam) {
4049                 return False;
4050         }
4051
4052         DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel));
4053
4054         /* check it's a supported variant */
4055         if (strcmp(str1,"zWrLh") != 0) {
4056                 return False;
4057         }
4058         switch( uLevel ) {
4059                 case 0: level_string = "B21"; break;
4060                 case 1: level_string = "B21BB16DWzzWz"; break;
4061                 case 2: level_string = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
4062                 case 10: level_string = "B21Bzzz"; break;
4063                 case 11: level_string = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
4064                 default: return False;
4065         }
4066
4067         if (strcmp(level_string,str2) != 0) {
4068                 return False;
4069         }
4070
4071         *rdata_len = mdrcnt + 1024;
4072         *rdata = smb_realloc_limit(*rdata,*rdata_len);
4073         if (!*rdata) {
4074                 return False;
4075         }
4076
4077         p = *rdata;
4078         endp = *rdata + *rdata_len;
4079         p2 = get_safe_ptr(*rdata,*rdata_len,p,usri11_end);
4080         if (!p2) {
4081                 return False;
4082         }
4083
4084         ZERO_STRUCT(connect_handle);
4085         ZERO_STRUCT(domain_handle);
4086         ZERO_STRUCT(user_handle);
4087
4088         status = rpc_pipe_open_internal(mem_ctx, &ndr_table_samr.syntax_id,
4089                                         rpc_samr_dispatch, conn->server_info,
4090                                         &cli);
4091         if (!NT_STATUS_IS_OK(status)) {
4092                 DEBUG(0,("api_RNetUserGetInfo: could not connect to samr: %s\n",
4093                           nt_errstr(status)));
4094                 errcode = W_ERROR_V(ntstatus_to_werror(status));
4095                 goto out;
4096         }
4097
4098         status = rpccli_samr_Connect2(cli, mem_ctx,
4099                                       global_myname(),
4100                                       SAMR_ACCESS_CONNECT_TO_SERVER |
4101                                       SAMR_ACCESS_ENUM_DOMAINS |
4102                                       SAMR_ACCESS_LOOKUP_DOMAIN,
4103                                       &connect_handle);
4104         if (!NT_STATUS_IS_OK(status)) {
4105                 errcode = W_ERROR_V(ntstatus_to_werror(status));
4106                 goto out;
4107         }
4108
4109         init_lsa_String(&domain_name, get_global_sam_name());
4110
4111         status = rpccli_samr_LookupDomain(cli, mem_ctx,
4112                                           &connect_handle,
4113                                           &domain_name,
4114                                           &domain_sid);
4115         if (!NT_STATUS_IS_OK(status)) {
4116                 errcode = W_ERROR_V(ntstatus_to_werror(status));
4117                 goto out;
4118         }
4119
4120         status = rpccli_samr_OpenDomain(cli, mem_ctx,
4121                                         &connect_handle,
4122                                         SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
4123                                         domain_sid,
4124                                         &domain_handle);
4125         if (!NT_STATUS_IS_OK(status)) {
4126                 errcode = W_ERROR_V(ntstatus_to_werror(status));
4127                 goto out;
4128         }
4129
4130         init_lsa_String(&names, UserName);
4131
4132         status = rpccli_samr_LookupNames(cli, mem_ctx,
4133                                          &domain_handle,
4134                                          1,
4135                                          &names,
4136                                          &rids,
4137                                          &types);
4138         if (!NT_STATUS_IS_OK(status)) {
4139                 errcode = W_ERROR_V(ntstatus_to_werror(status));
4140                 goto out;
4141         }
4142
4143         if (rids.count != 1) {
4144                 errcode = W_ERROR_V(WERR_NO_SUCH_USER);
4145                 goto out;
4146         }
4147         if (rids.count != types.count) {
4148                 errcode = W_ERROR_V(WERR_INVALID_PARAM);
4149                 goto out;
4150         }
4151         if (types.ids[0] != SID_NAME_USER) {
4152                 errcode = W_ERROR_V(WERR_INVALID_PARAM);
4153                 goto out;
4154         }
4155
4156         rid = rids.ids[0];
4157
4158         status = rpccli_samr_OpenUser(cli, mem_ctx,
4159                                       &domain_handle,
4160                                       SAMR_USER_ACCESS_GET_LOCALE |
4161                                       SAMR_USER_ACCESS_GET_LOGONINFO |
4162                                       SAMR_USER_ACCESS_GET_ATTRIBUTES |
4163                                       SAMR_USER_ACCESS_GET_GROUPS |
4164                                       SAMR_USER_ACCESS_GET_GROUP_MEMBERSHIP |
4165                                       SEC_STD_READ_CONTROL,
4166                                       rid,
4167                                       &user_handle);
4168         if (!NT_STATUS_IS_OK(status)) {
4169                 errcode = W_ERROR_V(ntstatus_to_werror(status));
4170                 goto out;
4171         }
4172
4173         status = rpccli_samr_QueryUserInfo2(cli, mem_ctx,
4174                                             &user_handle,
4175                                             UserAllInformation,
4176                                             &info);
4177         if (!NT_STATUS_IS_OK(status)) {
4178                 errcode = W_ERROR_V(ntstatus_to_werror(status));
4179                 goto out;
4180         }
4181
4182         memset(p,0,21);
4183         fstrcpy(p+usri11_name,UserName); /* 21 bytes - user name */
4184
4185         if (uLevel > 0) {
4186                 SCVAL(p,usri11_pad,0); /* padding - 1 byte */
4187                 *p2 = 0;
4188         }
4189
4190         if (uLevel >= 10) {
4191                 SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */
4192                 strlcpy(p2,"Comment",PTR_DIFF(endp,p2));
4193                 p2 = skip_string(*rdata,*rdata_len,p2);
4194                 if (!p2) {
4195                         return False;
4196                 }
4197
4198                 SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */
4199                 strlcpy(p2,"UserComment",PTR_DIFF(endp,p2));
4200                 p2 = skip_string(*rdata,*rdata_len,p2);
4201                 if (!p2) {
4202                         return False;
4203                 }
4204
4205                 /* EEK! the cifsrap.txt doesn't have this in!!!! */
4206                 SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */
4207                 strlcpy(p2,info->info21.full_name.string,PTR_DIFF(endp,p2));
4208                 p2 = skip_string(*rdata,*rdata_len,p2);
4209                 if (!p2) {
4210                         return False;
4211                 }
4212         }
4213
4214         if (uLevel == 11) {
4215                 const char *homedir = info->info21.home_directory.string;
4216                 /* modelled after NTAS 3.51 reply */
4217                 SSVAL(p,usri11_priv,
4218                         (get_current_uid(conn) == sec_initial_uid())?
4219                         USER_PRIV_ADMIN:USER_PRIV_USER);
4220                 SIVAL(p,usri11_auth_flags,AF_OP_PRINT);         /* auth flags */
4221                 SIVALS(p,usri11_password_age,-1);               /* password age */
4222                 SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */
4223                 strlcpy(p2, homedir, PTR_DIFF(endp,p2));
4224                 p2 = skip_string(*rdata,*rdata_len,p2);
4225                 if (!p2) {
4226                         return False;
4227                 }
4228                 SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */
4229                 strlcpy(p2,"",PTR_DIFF(endp,p2));
4230                 p2 = skip_string(*rdata,*rdata_len,p2);
4231                 if (!p2) {
4232                         return False;
4233                 }
4234                 SIVAL(p,usri11_last_logon,0);           /* last logon */
4235                 SIVAL(p,usri11_last_logoff,0);          /* last logoff */
4236                 SSVALS(p,usri11_bad_pw_count,-1);       /* bad pw counts */
4237                 SSVALS(p,usri11_num_logons,-1);         /* num logons */
4238                 SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */
4239                 strlcpy(p2,"\\\\*",PTR_DIFF(endp,p2));
4240                 p2 = skip_string(*rdata,*rdata_len,p2);
4241                 if (!p2) {
4242                         return False;
4243                 }
4244                 SSVAL(p,usri11_country_code,0);         /* country code */
4245
4246                 SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */
4247                 strlcpy(p2,"",PTR_DIFF(endp,p2));
4248                 p2 = skip_string(*rdata,*rdata_len,p2);
4249                 if (!p2) {
4250                         return False;
4251                 }
4252
4253                 SIVALS(p,usri11_max_storage,-1);                /* max storage */
4254                 SSVAL(p,usri11_units_per_week,168);             /* units per week */
4255                 SIVAL(p,usri11_logon_hours,PTR_DIFF(p2,p)); /* logon hours */
4256
4257                 /* a simple way to get logon hours at all times. */
4258                 memset(p2,0xff,21);
4259                 SCVAL(p2,21,0);           /* fix zero termination */
4260                 p2 = skip_string(*rdata,*rdata_len,p2);
4261                 if (!p2) {
4262                         return False;
4263                 }
4264
4265                 SSVAL(p,usri11_code_page,0);            /* code page */
4266         }
4267
4268         if (uLevel == 1 || uLevel == 2) {
4269                 memset(p+22,' ',16);    /* password */
4270                 SIVALS(p,38,-1);                /* password age */
4271                 SSVAL(p,42,
4272                         (get_current_uid(conn) == sec_initial_uid())?
4273                         USER_PRIV_ADMIN:USER_PRIV_USER);
4274                 SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
4275                 strlcpy(p2, info->info21.home_directory.string,
4276                         PTR_DIFF(endp,p2));
4277                 p2 = skip_string(*rdata,*rdata_len,p2);
4278                 if (!p2) {
4279                         return False;
4280                 }
4281                 SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
4282                 *p2++ = 0;
4283                 SSVAL(p,52,0);          /* flags */
4284                 SIVAL(p,54,PTR_DIFF(p2,*rdata));                /* script_path */
4285                 strlcpy(p2, info->info21.logon_script.string,
4286                         PTR_DIFF(endp,p2));
4287                 p2 = skip_string(*rdata,*rdata_len,p2);
4288                 if (!p2) {
4289                         return False;
4290                 }
4291                 if (uLevel == 2) {
4292                         SIVAL(p,60,0);          /* auth_flags */
4293                         SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
4294                         strlcpy(p2,info->info21.full_name.string,PTR_DIFF(endp,p2));
4295                         p2 = skip_string(*rdata,*rdata_len,p2);
4296                         if (!p2) {
4297                                 return False;
4298                         }
4299                         SIVAL(p,68,0);          /* urs_comment */
4300                         SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
4301                         strlcpy(p2,"",PTR_DIFF(endp,p2));
4302                         p2 = skip_string(*rdata,*rdata_len,p2);
4303                         if (!p2) {
4304                                 return False;
4305                         }
4306                         SIVAL(p,76,0);          /* workstations */
4307                         SIVAL(p,80,0);          /* last_logon */
4308                         SIVAL(p,84,0);          /* last_logoff */
4309                         SIVALS(p,88,-1);                /* acct_expires */
4310                         SIVALS(p,92,-1);                /* max_storage */
4311                         SSVAL(p,96,168);        /* units_per_week */
4312                         SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
4313                         memset(p2,-1,21);
4314                         p2 += 21;
4315                         SSVALS(p,102,-1);       /* bad_pw_count */
4316                         SSVALS(p,104,-1);       /* num_logons */
4317                         SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
4318                         {
4319                                 TALLOC_CTX *ctx = talloc_tos();
4320                                 int space_rem = *rdata_len - (p2 - *rdata);
4321                                 char *tmp;
4322
4323                                 if (space_rem <= 0) {
4324                                         return false;
4325                                 }
4326                                 tmp = talloc_strdup(ctx, "\\\\%L");
4327                                 if (!tmp) {
4328                                         return false;
4329                                 }
4330                                 tmp = talloc_sub_basic(ctx,
4331                                                 "",
4332                                                 "",
4333                                                 tmp);
4334                                 if (!tmp) {
4335                                         return false;
4336                                 }
4337
4338                                 push_ascii(p2,
4339                                         tmp,
4340                                         space_rem,
4341                                         STR_TERMINATE);
4342                         }
4343                         p2 = skip_string(*rdata,*rdata_len,p2);
4344                         if (!p2) {
4345                                 return False;
4346                         }
4347                         SSVAL(p,110,49);        /* country_code */
4348                         SSVAL(p,112,860);       /* code page */
4349                 }
4350         }
4351
4352         errcode = NERR_Success;
4353
4354  out:
4355         *rdata_len = PTR_DIFF(p2,*rdata);
4356
4357         if (cli && is_valid_policy_hnd(&user_handle)) {
4358                 rpccli_samr_Close(cli, mem_ctx, &user_handle);
4359         }
4360         if (cli && is_valid_policy_hnd(&domain_handle)) {
4361                 rpccli_samr_Close(cli, mem_ctx, &domain_handle);
4362         }
4363         if (cli && is_valid_policy_hnd(&connect_handle)) {
4364                 rpccli_samr_Close(cli, mem_ctx, &connect_handle);
4365         }
4366
4367         SSVAL(*rparam,0,errcode);
4368         SSVAL(*rparam,2,0);             /* converter word */
4369         SSVAL(*rparam,4,*rdata_len);    /* is this right?? */
4370
4371         return(True);
4372 }
4373
4374 static bool api_WWkstaUserLogon(connection_struct *conn,uint16 vuid,
4375                                 char *param, int tpscnt,
4376                                 char *data, int tdscnt,
4377                                 int mdrcnt,int mprcnt,
4378                                 char **rdata,char **rparam,
4379                                 int *rdata_len,int *rparam_len)
4380 {
4381         struct smbd_server_connection *sconn = smbd_server_conn;
4382         char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4383         char *str2 = skip_string(param,tpscnt,str1);
4384         char *p = skip_string(param,tpscnt,str2);
4385         int uLevel;
4386         struct pack_desc desc;
4387         char* name;
4388                 /* With share level security vuid will always be zero.
4389                    Don't depend on vuser being non-null !!. JRA */
4390         user_struct *vuser = get_valid_user_struct(sconn, vuid);
4391
4392         if (!str1 || !str2 || !p) {
4393                 return False;
4394         }
4395
4396         if(vuser != NULL) {
4397                 DEBUG(3,("  Username of UID %d is %s\n",
4398                          (int)vuser->server_info->utok.uid,
4399                          vuser->server_info->unix_name));
4400         }
4401
4402         uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4403         name = get_safe_str_ptr(param,tpscnt,p,2);
4404         if (!name) {
4405                 return False;
4406         }
4407
4408         memset((char *)&desc,'\0',sizeof(desc));
4409
4410         DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
4411
4412         /* check it's a supported varient */
4413         if (strcmp(str1,"OOWb54WrLh") != 0) {
4414                 return False;
4415         }
4416         if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) {
4417                 return False;
4418         }
4419         if (mdrcnt > 0) {
4420                 *rdata = smb_realloc_limit(*rdata,mdrcnt);
4421                 if (!*rdata) {
4422                         return False;
4423                 }
4424         }
4425
4426         desc.base = *rdata;
4427         desc.buflen = mdrcnt;
4428         desc.subformat = NULL;
4429         desc.format = str2;
4430
4431         if (init_package(&desc,1,0)) {
4432                 PACKI(&desc,"W",0);             /* code */
4433                 PACKS(&desc,"B21",name);        /* eff. name */
4434                 PACKS(&desc,"B","");            /* pad */
4435                 PACKI(&desc,"W",
4436                         (get_current_uid(conn) == sec_initial_uid())?
4437                         USER_PRIV_ADMIN:USER_PRIV_USER);
4438                 PACKI(&desc,"D",0);             /* auth flags XXX */
4439                 PACKI(&desc,"W",0);             /* num logons */
4440                 PACKI(&desc,"W",0);             /* bad pw count */
4441                 PACKI(&desc,"D",0);             /* last logon */
4442                 PACKI(&desc,"D",-1);            /* last logoff */
4443                 PACKI(&desc,"D",-1);            /* logoff time */
4444                 PACKI(&desc,"D",-1);            /* kickoff time */
4445                 PACKI(&desc,"D",0);             /* password age */
4446                 PACKI(&desc,"D",0);             /* password can change */
4447                 PACKI(&desc,"D",-1);            /* password must change */
4448
4449                 {
4450                         fstring mypath;
4451                         fstrcpy(mypath,"\\\\");
4452                         fstrcat(mypath,get_local_machine_name());
4453                         strupper_m(mypath);
4454                         PACKS(&desc,"z",mypath); /* computer */
4455                 }
4456
4457                 PACKS(&desc,"z",lp_workgroup());/* domain */
4458                 PACKS(&desc,"z", vuser ? pdb_get_logon_script(
4459                               vuser->server_info->sam_account) : ""); /* script path */
4460                 PACKI(&desc,"D",0x00000000);            /* reserved */
4461         }
4462
4463         *rdata_len = desc.usedlen;
4464         *rparam_len = 6;
4465         *rparam = smb_realloc_limit(*rparam,*rparam_len);
4466         if (!*rparam) {
4467                 return False;
4468         }
4469         SSVALS(*rparam,0,desc.errcode);
4470         SSVAL(*rparam,2,0);
4471         SSVAL(*rparam,4,desc.neededlen);
4472
4473         DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
4474
4475         return True;
4476 }
4477
4478 /****************************************************************************
4479  api_WAccessGetUserPerms
4480 ****************************************************************************/
4481
4482 static bool api_WAccessGetUserPerms(connection_struct *conn,uint16 vuid,
4483                                 char *param, int tpscnt,
4484                                 char *data, int tdscnt,
4485                                 int mdrcnt,int mprcnt,
4486                                 char **rdata,char **rparam,
4487                                 int *rdata_len,int *rparam_len)
4488 {
4489         char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4490         char *str2 = skip_string(param,tpscnt,str1);
4491         char *user = skip_string(param,tpscnt,str2);
4492         char *resource = skip_string(param,tpscnt,user);
4493
4494         if (!str1 || !str2 || !user || !resource) {
4495                 return False;
4496         }
4497
4498         if (skip_string(param,tpscnt,resource) == NULL) {
4499                 return False;
4500         }
4501         DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
4502
4503         /* check it's a supported varient */
4504         if (strcmp(str1,"zzh") != 0) {
4505                 return False;
4506         }
4507         if (strcmp(str2,"") != 0) {
4508                 return False;
4509         }
4510
4511         *rparam_len = 6;
4512         *rparam = smb_realloc_limit(*rparam,*rparam_len);
4513         if (!*rparam) {
4514                 return False;
4515         }
4516         SSVALS(*rparam,0,0);            /* errorcode */
4517         SSVAL(*rparam,2,0);             /* converter word */
4518         SSVAL(*rparam,4,0x7f);  /* permission flags */
4519
4520         return True;
4521 }
4522
4523 /****************************************************************************
4524   api_WPrintJobEnumerate
4525   ****************************************************************************/
4526
4527 static bool api_WPrintJobGetInfo(connection_struct *conn, uint16 vuid,
4528                                 char *param, int tpscnt,
4529                                 char *data, int tdscnt,
4530                                 int mdrcnt,int mprcnt,
4531                                 char **rdata,char **rparam,
4532                                 int *rdata_len,int *rparam_len)
4533 {
4534         char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4535         char *str2 = skip_string(param,tpscnt,str1);
4536         char *p = skip_string(param,tpscnt,str2);
4537         int uLevel;
4538         fstring sharename;
4539         uint32 jobid;
4540         struct pack_desc desc;
4541         char *tmpdata=NULL;
4542
4543         TALLOC_CTX *mem_ctx = talloc_tos();
4544         WERROR werr;
4545         NTSTATUS status;
4546         struct rpc_pipe_client *cli = NULL;
4547         struct policy_handle handle;
4548         struct spoolss_DevmodeContainer devmode_ctr;
4549         union spoolss_JobInfo info;
4550
4551         if (!str1 || !str2 || !p) {
4552                 return False;
4553         }
4554
4555         uLevel = get_safe_SVAL(param,tpscnt,p,2,-1);
4556
4557         memset((char *)&desc,'\0',sizeof(desc));
4558         memset((char *)&status,'\0',sizeof(status));
4559
4560         DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,SVAL(p,0)));
4561
4562         /* check it's a supported varient */
4563         if (strcmp(str1,"WWrLh") != 0) {
4564                 return False;
4565         }
4566         if (!check_printjob_info(&desc,uLevel,str2)) {
4567                 return False;
4568         }
4569
4570         if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid)) {
4571                 return False;
4572         }
4573
4574         ZERO_STRUCT(handle);
4575
4576         status = rpc_connect_spoolss_pipe(conn, &cli);
4577         if (!NT_STATUS_IS_OK(status)) {
4578                 DEBUG(0,("api_WPrintJobGetInfo: could not connect to spoolss: %s\n",
4579                           nt_errstr(status)));
4580                 desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
4581                 goto out;
4582         }
4583
4584         ZERO_STRUCT(devmode_ctr);
4585
4586         status = rpccli_spoolss_OpenPrinter(cli, mem_ctx,
4587                                             sharename,
4588                                             "RAW",
4589                                             devmode_ctr,
4590                                             PRINTER_ACCESS_USE,
4591                                             &handle,
4592                                             &werr);
4593         if (!NT_STATUS_IS_OK(status)) {
4594                 desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
4595                 goto out;
4596         }
4597         if (!W_ERROR_IS_OK(werr)) {
4598                 desc.errcode = W_ERROR_V(werr);
4599                 goto out;
4600         }
4601
4602         werr = rpccli_spoolss_getjob(cli, mem_ctx,
4603                                      &handle,
4604                                      jobid,
4605                                      2, /* level */
4606                                      0, /* offered */
4607                                      &info);
4608         if (!W_ERROR_IS_OK(werr)) {
4609                 desc.errcode = W_ERROR_V(werr);
4610                 goto out;
4611         }
4612
4613         if (mdrcnt > 0) {
4614                 *rdata = smb_realloc_limit(*rdata,mdrcnt);
4615                 if (!*rdata) {
4616                         return False;
4617                 }
4618                 desc.base = *rdata;
4619                 desc.buflen = mdrcnt;
4620         } else {
4621                 /*
4622                  * Don't return data but need to get correct length
4623                  *  init_package will return wrong size if buflen=0
4624                  */
4625                 desc.buflen = getlen(desc.format);
4626                 desc.base = tmpdata = (char *)SMB_MALLOC( desc.buflen );
4627         }
4628
4629         if (init_package(&desc,1,0)) {
4630                 fill_spoolss_printjob_info(uLevel, &desc, &info.info2, info.info2.position);
4631                 *rdata_len = desc.usedlen;
4632         } else {
4633                 desc.errcode = NERR_JobNotFound;
4634                 *rdata_len = 0;
4635         }
4636  out:
4637         if (cli && is_valid_policy_hnd(&handle)) {
4638                 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
4639         }
4640
4641         *rparam_len = 6;
4642         *rparam = smb_realloc_limit(*rparam,*rparam_len);
4643         if (!*rparam) {
4644                 return False;
4645         }
4646         SSVALS(*rparam,0,desc.errcode);
4647         SSVAL(*rparam,2,0);
4648         SSVAL(*rparam,4,desc.neededlen);
4649
4650         SAFE_FREE(tmpdata);
4651
4652         DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
4653
4654         return True;
4655 }
4656
4657 static bool api_WPrintJobEnumerate(connection_struct *conn, uint16 vuid,
4658                                 char *param, int tpscnt,
4659                                 char *data, int tdscnt,
4660                                 int mdrcnt,int mprcnt,
4661                                 char **rdata,char **rparam,
4662                                 int *rdata_len,int *rparam_len)
4663 {
4664         char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4665         char *str2 = skip_string(param,tpscnt,str1);
4666         char *p = skip_string(param,tpscnt,str2);
4667         char *name = p;
4668         int uLevel;
4669         int i, succnt=0;
4670         struct pack_desc desc;
4671
4672         TALLOC_CTX *mem_ctx = talloc_tos();
4673         WERROR werr;
4674         NTSTATUS status;
4675         struct rpc_pipe_client *cli = NULL;
4676         struct policy_handle handle;
4677         struct spoolss_DevmodeContainer devmode_ctr;
4678         uint32_t count;
4679         union spoolss_JobInfo *info;
4680
4681         if (!str1 || !str2 || !p) {
4682                 return False;
4683         }
4684
4685         memset((char *)&desc,'\0',sizeof(desc));
4686
4687         p = skip_string(param,tpscnt,p);
4688         if (!p) {
4689                 return False;
4690         }
4691         uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4692
4693         DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
4694
4695         /* check it's a supported variant */
4696         if (strcmp(str1,"zWrLeh") != 0) {
4697                 return False;
4698         }
4699
4700         if (uLevel > 2) {
4701                 return False;   /* defined only for uLevel 0,1,2 */
4702         }
4703
4704         if (!check_printjob_info(&desc,uLevel,str2)) { 
4705                 return False;
4706         }
4707
4708         ZERO_STRUCT(handle);
4709
4710         status = rpc_connect_spoolss_pipe(conn, &cli);
4711         if (!NT_STATUS_IS_OK(status)) {
4712                 DEBUG(0,("api_WPrintJobEnumerate: could not connect to spoolss: %s\n",
4713                           nt_errstr(status)));
4714                 desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
4715                 goto out;
4716         }
4717
4718         ZERO_STRUCT(devmode_ctr);
4719
4720         status = rpccli_spoolss_OpenPrinter(cli, mem_ctx,
4721                                             name,
4722                                             NULL,
4723                                             devmode_ctr,
4724                                             SEC_FLAG_MAXIMUM_ALLOWED,
4725                                             &handle,
4726                                             &werr);
4727         if (!NT_STATUS_IS_OK(status)) {
4728                 desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
4729                 goto out;
4730         }
4731         if (!W_ERROR_IS_OK(werr)) {
4732                 desc.errcode = W_ERROR_V(werr);
4733                 goto out;
4734         }
4735
4736         werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
4737                                        &handle,
4738                                        0, /* firstjob */
4739                                        0xff, /* numjobs */
4740                                        2, /* level */
4741                                        0, /* offered */
4742                                        &count,
4743                                        &info);
4744         if (!W_ERROR_IS_OK(werr)) {
4745                 desc.errcode = W_ERROR_V(werr);
4746                 goto out;
4747         }
4748
4749         if (mdrcnt > 0) {
4750                 *rdata = smb_realloc_limit(*rdata,mdrcnt);
4751                 if (!*rdata) {
4752                         return False;
4753                 }
4754         }
4755         desc.base = *rdata;
4756         desc.buflen = mdrcnt;
4757
4758         if (init_package(&desc,count,0)) {
4759                 succnt = 0;
4760                 for (i = 0; i < count; i++) {
4761                         fill_spoolss_printjob_info(uLevel, &desc, &info[i].info2, i);
4762                         if (desc.errcode == NERR_Success) {
4763                                 succnt = i+1;
4764                         }
4765                 }
4766         }
4767  out:
4768         if (cli && is_valid_policy_hnd(&handle)) {
4769                 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
4770         }
4771
4772         *rdata_len = desc.usedlen;
4773
4774         *rparam_len = 8;
4775         *rparam = smb_realloc_limit(*rparam,*rparam_len);
4776         if (!*rparam) {
4777                 return False;
4778         }
4779         SSVALS(*rparam,0,desc.errcode);
4780         SSVAL(*rparam,2,0);
4781         SSVAL(*rparam,4,succnt);
4782         SSVAL(*rparam,6,count);
4783
4784         DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
4785
4786         return True;
4787 }
4788
4789 static int check_printdest_info(struct pack_desc* desc,
4790                                 int uLevel, char* id)
4791 {
4792         desc->subformat = NULL;
4793         switch( uLevel ) {
4794                 case 0:
4795                         desc->format = "B9";
4796                         break;
4797                 case 1:
4798                         desc->format = "B9B21WWzW";
4799                         break;
4800                 case 2:
4801                         desc->format = "z";
4802                         break;
4803                 case 3:
4804                         desc->format = "zzzWWzzzWW";
4805                         break;
4806                 default:
4807                         DEBUG(0,("check_printdest_info: invalid level %d\n",
4808                                 uLevel));
4809                         return False;
4810         }
4811         if (id == NULL || strcmp(desc->format,id) != 0) {
4812                 DEBUG(0,("check_printdest_info: invalid string %s\n", 
4813                         id ? id : "<NULL>" ));
4814                 return False;
4815         }
4816         return True;
4817 }
4818
4819 static void fill_printdest_info(struct spoolss_PrinterInfo2 *info2, int uLevel,
4820                                 struct pack_desc* desc)
4821 {
4822         char buf[100];
4823
4824         strncpy(buf, info2->printername, sizeof(buf)-1);
4825         buf[sizeof(buf)-1] = 0;
4826         strupper_m(buf);
4827
4828         if (uLevel <= 1) {
4829                 PACKS(desc,"B9",buf);   /* szName */
4830                 if (uLevel == 1) {
4831                         PACKS(desc,"B21","");   /* szUserName */
4832                         PACKI(desc,"W",0);              /* uJobId */
4833                         PACKI(desc,"W",0);              /* fsStatus */
4834                         PACKS(desc,"z","");     /* pszStatus */
4835                         PACKI(desc,"W",0);              /* time */
4836                 }
4837         }
4838
4839         if (uLevel == 2 || uLevel == 3) {
4840                 PACKS(desc,"z",buf);            /* pszPrinterName */
4841                 if (uLevel == 3) {
4842                         PACKS(desc,"z","");     /* pszUserName */
4843                         PACKS(desc,"z","");     /* pszLogAddr */
4844                         PACKI(desc,"W",0);              /* uJobId */
4845                         PACKI(desc,"W",0);              /* fsStatus */
4846                         PACKS(desc,"z","");     /* pszStatus */
4847                         PACKS(desc,"z","");     /* pszComment */
4848                         PACKS(desc,"z","NULL"); /* pszDrivers */
4849                         PACKI(desc,"W",0);              /* time */
4850                         PACKI(desc,"W",0);              /* pad1 */
4851                 }
4852         }
4853 }
4854
4855 static bool api_WPrintDestGetInfo(connection_struct *conn, uint16 vuid,
4856                                 char *param, int tpscnt,
4857                                 char *data, int tdscnt,
4858                                 int mdrcnt,int mprcnt,
4859                                 char **rdata,char **rparam,
4860                                 int *rdata_len,int *rparam_len)
4861 {
4862         char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4863         char *str2 = skip_string(param,tpscnt,str1);
4864         char *p = skip_string(param,tpscnt,str2);
4865         char* PrinterName = p;
4866         int uLevel;
4867         struct pack_desc desc;
4868         char *tmpdata=NULL;
4869
4870         TALLOC_CTX *mem_ctx = talloc_tos();
4871         WERROR werr;
4872         NTSTATUS status;
4873         struct rpc_pipe_client *cli = NULL;
4874         struct policy_handle handle;
4875         struct spoolss_DevmodeContainer devmode_ctr;
4876         union spoolss_PrinterInfo info;
4877
4878         if (!str1 || !str2 || !p) {
4879                 return False;
4880         }
4881
4882         memset((char *)&desc,'\0',sizeof(desc));
4883
4884         p = skip_string(param,tpscnt,p);
4885         if (!p) {
4886                 return False;
4887         }
4888         uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4889
4890         DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
4891
4892         /* check it's a supported varient */
4893         if (strcmp(str1,"zWrLh") != 0) {
4894                 return False;
4895         }
4896         if (!check_printdest_info(&desc,uLevel,str2)) {
4897                 return False;
4898         }
4899
4900         ZERO_STRUCT(handle);
4901
4902         status = rpc_connect_spoolss_pipe(conn, &cli);
4903         if (!NT_STATUS_IS_OK(status)) {
4904                 DEBUG(0,("api_WPrintDestGetInfo: could not connect to spoolss: %s\n",
4905                           nt_errstr(status)));
4906                 desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
4907                 goto out;
4908         }
4909
4910         ZERO_STRUCT(devmode_ctr);
4911
4912         status = rpccli_spoolss_OpenPrinter(cli, mem_ctx,
4913                                             PrinterName,
4914                                             NULL,
4915                                             devmode_ctr,
4916                                             SEC_FLAG_MAXIMUM_ALLOWED,
4917                                             &handle,
4918                                             &werr);
4919         if (!NT_STATUS_IS_OK(status)) {
4920                 *rdata_len = 0;
4921                 desc.errcode = NERR_DestNotFound;
4922                 desc.neededlen = 0;
4923                 goto out;
4924         }
4925         if (!W_ERROR_IS_OK(werr)) {
4926                 *rdata_len = 0;
4927                 desc.errcode = NERR_DestNotFound;
4928                 desc.neededlen = 0;
4929                 goto out;
4930         }
4931
4932         werr = rpccli_spoolss_getprinter(cli, mem_ctx,
4933                                          &handle,
4934                                          2,
4935                                          0,
4936                                          &info);
4937         if (!W_ERROR_IS_OK(werr)) {
4938                 *rdata_len = 0;
4939                 desc.errcode = NERR_DestNotFound;
4940                 desc.neededlen = 0;
4941                 goto out;
4942         }
4943
4944         if (mdrcnt > 0) {
4945                 *rdata = smb_realloc_limit(*rdata,mdrcnt);
4946                 if (!*rdata) {
4947                         return False;
4948                 }
4949                 desc.base = *rdata;
4950                 desc.buflen = mdrcnt;
4951         } else {
4952                 /*
4953                  * Don't return data but need to get correct length
4954                  * init_package will return wrong size if buflen=0
4955                  */
4956                 desc.buflen = getlen(desc.format);
4957                 desc.base = tmpdata = (char *)SMB_MALLOC( desc.buflen );
4958         }
4959         if (init_package(&desc,1,0)) {
4960                 fill_printdest_info(&info.info2, uLevel,&desc);
4961         }
4962
4963  out:
4964         if (cli && is_valid_policy_hnd(&handle)) {
4965                 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
4966         }
4967
4968         *rdata_len = desc.usedlen;
4969
4970         *rparam_len = 6;
4971         *rparam = smb_realloc_limit(*rparam,*rparam_len);
4972         if (!*rparam) {
4973                 return False;
4974         }
4975         SSVALS(*rparam,0,desc.errcode);
4976         SSVAL(*rparam,2,0);
4977         SSVAL(*rparam,4,desc.neededlen);
4978
4979         DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
4980         SAFE_FREE(tmpdata);
4981
4982         return True;
4983 }
4984
4985 static bool api_WPrintDestEnum(connection_struct *conn, uint16 vuid,
4986                                 char *param, int tpscnt,
4987                                 char *data, int tdscnt,
4988                                 int mdrcnt,int mprcnt,
4989                                 char **rdata,char **rparam,
4990                                 int *rdata_len,int *rparam_len)
4991 {
4992         char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4993         char *str2 = skip_string(param,tpscnt,str1);
4994         char *p = skip_string(param,tpscnt,str2);
4995         int uLevel;
4996         int queuecnt;
4997         int i, n, succnt=0;
4998         struct pack_desc desc;
4999
5000         TALLOC_CTX *mem_ctx = talloc_tos();
5001         WERROR werr;
5002         NTSTATUS status;
5003         struct rpc_pipe_client *cli = NULL;
5004         union spoolss_PrinterInfo *info;
5005         uint32_t count;
5006
5007         if (!str1 || !str2 || !p) {
5008                 return False;
5009         }
5010
5011         memset((char *)&desc,'\0',sizeof(desc));
5012
5013         uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
5014
5015         DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
5016
5017         /* check it's a supported varient */
5018         if (strcmp(str1,"WrLeh") != 0) {
5019                 return False;
5020         }
5021         if (!check_printdest_info(&desc,uLevel,str2)) {
5022                 return False;
5023         }
5024
5025         queuecnt = 0;
5026
5027         status = rpc_connect_spoolss_pipe(conn, &cli);
5028         if (!NT_STATUS_IS_OK(status)) {
5029                 DEBUG(0,("api_WPrintDestEnum: could not connect to spoolss: %s\n",
5030                           nt_errstr(status)));
5031                 desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
5032                 goto out;
5033         }
5034
5035         werr = rpccli_spoolss_enumprinters(cli, mem_ctx,
5036                                            PRINTER_ENUM_LOCAL,
5037                                            cli->srv_name_slash,
5038                                            2,
5039                                            0,
5040                                            &count,
5041                                            &info);
5042         if (!W_ERROR_IS_OK(werr)) {
5043                 desc.errcode = W_ERROR_V(werr);
5044                 *rdata_len = 0;
5045                 desc.errcode = NERR_DestNotFound;
5046                 desc.neededlen = 0;
5047                 goto out;
5048         }
5049
5050         queuecnt = count;
5051
5052         if (mdrcnt > 0) {
5053                 *rdata = smb_realloc_limit(*rdata,mdrcnt);
5054                 if (!*rdata) {
5055                         return False;
5056                 }
5057         }
5058
5059         desc.base = *rdata;
5060         desc.buflen = mdrcnt;
5061         if (init_package(&desc,queuecnt,0)) {    
5062                 succnt = 0;
5063                 n = 0;
5064                 for (i = 0; i < count; i++) {
5065                         fill_printdest_info(&info[i].info2, uLevel,&desc);
5066                         n++;
5067                         if (desc.errcode == NERR_Success) {
5068                                 succnt = n;
5069                         }
5070                 }
5071         }
5072  out:
5073         *rdata_len = desc.usedlen;
5074
5075         *rparam_len = 8;
5076         *rparam = smb_realloc_limit(*rparam,*rparam_len);
5077         if (!*rparam) {
5078                 return False;
5079         }
5080         SSVALS(*rparam,0,desc.errcode);
5081         SSVAL(*rparam,2,0);
5082         SSVAL(*rparam,4,succnt);
5083         SSVAL(*rparam,6,queuecnt);
5084
5085         DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
5086
5087         return True;
5088 }
5089
5090 static bool api_WPrintDriverEnum(connection_struct *conn, uint16 vuid,
5091                                 char *param, int tpscnt,
5092                                 char *data, int tdscnt,
5093                                 int mdrcnt,int mprcnt,
5094                                 char **rdata,char **rparam,
5095                                 int *rdata_len,int *rparam_len)
5096 {
5097         char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
5098         char *str2 = skip_string(param,tpscnt,str1);
5099         char *p = skip_string(param,tpscnt,str2);
5100         int uLevel;
5101         int succnt;
5102         struct pack_desc desc;
5103
5104         if (!str1 || !str2 || !p) {
5105                 return False;
5106         }
5107
5108         memset((char *)&desc,'\0',sizeof(desc));
5109
5110         uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
5111
5112         DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
5113
5114         /* check it's a supported varient */
5115         if (strcmp(str1,"WrLeh") != 0) {
5116                 return False;
5117         }
5118         if (uLevel != 0 || strcmp(str2,"B41") != 0) {
5119                 return False;
5120         }
5121
5122         if (mdrcnt > 0) {
5123                 *rdata = smb_realloc_limit(*rdata,mdrcnt);
5124                 if (!*rdata) {
5125                         return False;
5126                 }
5127         }
5128         desc.base = *rdata;
5129         desc.buflen = mdrcnt;
5130         if (init_package(&desc,1,0)) {
5131                 PACKS(&desc,"B41","NULL");
5132         }
5133
5134         succnt = (desc.errcode == NERR_Success ? 1 : 0);
5135
5136         *rdata_len = desc.usedlen;
5137
5138         *rparam_len = 8;
5139         *rparam = smb_realloc_limit(*rparam,*rparam_len);
5140         if (!*rparam) {
5141                 return False;
5142         }
5143         SSVALS(*rparam,0,desc.errcode);
5144         SSVAL(*rparam,2,0);
5145         SSVAL(*rparam,4,succnt);
5146         SSVAL(*rparam,6,1);
5147
5148         DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
5149
5150         return True;
5151 }
5152
5153 static bool api_WPrintQProcEnum(connection_struct *conn, uint16 vuid,
5154                                 char *param, int tpscnt,
5155                                 char *data, int tdscnt,
5156                                 int mdrcnt,int mprcnt,
5157                                 char **rdata,char **rparam,
5158                                 int *rdata_len,int *rparam_len)
5159 {
5160         char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
5161         char *str2 = skip_string(param,tpscnt,str1);
5162         char *p = skip_string(param,tpscnt,str2);
5163         int uLevel;
5164         int succnt;
5165         struct pack_desc desc;
5166
5167         if (!str1 || !str2 || !p) {
5168                 return False;
5169         }
5170         memset((char *)&desc,'\0',sizeof(desc));
5171
5172         uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
5173
5174         DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
5175
5176         /* check it's a supported varient */
5177         if (strcmp(str1,"WrLeh") != 0) {
5178                 return False;
5179         }
5180         if (uLevel != 0 || strcmp(str2,"B13") != 0) {
5181                 return False;
5182         }
5183
5184         if (mdrcnt > 0) {
5185                 *rdata = smb_realloc_limit(*rdata,mdrcnt);
5186                 if (!*rdata) {
5187                         return False;
5188                 }
5189         }
5190         desc.base = *rdata;
5191         desc.buflen = mdrcnt;
5192         desc.format = str2;
5193         if (init_package(&desc,1,0)) {
5194                 PACKS(&desc,"B13","lpd");
5195         }
5196
5197         succnt = (desc.errcode == NERR_Success ? 1 : 0);
5198
5199         *rdata_len = desc.usedlen;
5200
5201         *rparam_len = 8;
5202         *rparam = smb_realloc_limit(*rparam,*rparam_len);
5203         if (!*rparam) {
5204                 return False;
5205         }
5206         SSVALS(*rparam,0,desc.errcode);
5207         SSVAL(*rparam,2,0);
5208         SSVAL(*rparam,4,succnt);
5209         SSVAL(*rparam,6,1);
5210
5211         DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
5212
5213         return True;
5214 }
5215
5216 static bool api_WPrintPortEnum(connection_struct *conn, uint16 vuid,
5217                                 char *param, int tpscnt,
5218                                 char *data, int tdscnt,
5219                                 int mdrcnt,int mprcnt,
5220                                 char **rdata,char **rparam,
5221                                 int *rdata_len,int *rparam_len)
5222 {
5223         char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
5224         char *str2 = skip_string(param,tpscnt,str1);
5225         char *p = skip_string(param,tpscnt,str2);
5226         int uLevel;
5227         int succnt;
5228         struct pack_desc desc;
5229
5230         if (!str1 || !str2 || !p) {
5231                 return False;
5232         }
5233
5234         memset((char *)&desc,'\0',sizeof(desc));
5235
5236         uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
5237
5238         DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
5239
5240         /* check it's a supported varient */
5241         if (strcmp(str1,"WrLeh") != 0) {
5242                 return False;
5243         }
5244         if (uLevel != 0 || strcmp(str2,"B9") != 0) {
5245                 return False;
5246         }
5247
5248         if (mdrcnt > 0) {
5249                 *rdata = smb_realloc_limit(*rdata,mdrcnt);
5250                 if (!*rdata) {
5251                         return False;
5252                 }
5253         }
5254         memset((char *)&desc,'\0',sizeof(desc));
5255         desc.base = *rdata;
5256         desc.buflen = mdrcnt;
5257         desc.format = str2;
5258         if (init_package(&desc,1,0)) {
5259                 PACKS(&desc,"B13","lp0");
5260         }
5261
5262         succnt = (desc.errcode == NERR_Success ? 1 : 0);
5263
5264         *rdata_len = desc.usedlen;
5265
5266         *rparam_len = 8;
5267         *rparam = smb_realloc_limit(*rparam,*rparam_len);
5268         if (!*rparam) {
5269                 return False;
5270         }
5271         SSVALS(*rparam,0,desc.errcode);
5272         SSVAL(*rparam,2,0);
5273         SSVAL(*rparam,4,succnt);
5274         SSVAL(*rparam,6,1);
5275
5276         DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
5277
5278         return True;
5279 }
5280
5281 /****************************************************************************
5282  List open sessions
5283  ****************************************************************************/
5284
5285 static bool api_RNetSessionEnum(connection_struct *conn, uint16 vuid,
5286                                 char *param, int tpscnt,
5287                                 char *data, int tdscnt,
5288                                 int mdrcnt,int mprcnt,
5289                                 char **rdata,char **rparam,
5290                                 int *rdata_len,int *rparam_len)
5291
5292 {
5293         char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
5294         char *str2 = skip_string(param,tpscnt,str1);
5295         char *p = skip_string(param,tpscnt,str2);
5296         int uLevel;
5297         struct pack_desc desc;
5298         struct sessionid *session_list;
5299         int i, num_sessions;
5300
5301         if (!str1 || !str2 || !p) {
5302                 return False;
5303         }
5304
5305         memset((char *)&desc,'\0',sizeof(desc));
5306
5307         uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
5308
5309         DEBUG(3,("RNetSessionEnum uLevel=%d\n",uLevel));
5310         DEBUG(7,("RNetSessionEnum req string=%s\n",str1));
5311         DEBUG(7,("RNetSessionEnum ret string=%s\n",str2));
5312
5313         /* check it's a supported varient */
5314         if (strcmp(str1,RAP_NetSessionEnum_REQ) != 0) {
5315                 return False;
5316         }
5317         if (uLevel != 2 || strcmp(str2,RAP_SESSION_INFO_L2) != 0) {
5318                 return False;
5319         }
5320
5321         num_sessions = list_sessions(talloc_tos(), &session_list);
5322
5323         if (mdrcnt > 0) {
5324                 *rdata = smb_realloc_limit(*rdata,mdrcnt);
5325                 if (!*rdata) {
5326                         return False;
5327                 }
5328         }
5329         memset((char *)&desc,'\0',sizeof(desc));
5330         desc.base = *rdata;
5331         desc.buflen = mdrcnt;
5332         desc.format = str2;
5333         if (!init_package(&desc,num_sessions,0)) {
5334                 return False;
5335         }
5336
5337         for(i=0; i<num_sessions; i++) {
5338                 PACKS(&desc, "z", session_list[i].remote_machine);
5339                 PACKS(&desc, "z", session_list[i].username);
5340                 PACKI(&desc, "W", 1); /* num conns */
5341                 PACKI(&desc, "W", 0); /* num opens */
5342                 PACKI(&desc, "W", 1); /* num users */
5343                 PACKI(&desc, "D", 0); /* session time */
5344                 PACKI(&desc, "D", 0); /* idle time */
5345                 PACKI(&desc, "D", 0); /* flags */
5346                 PACKS(&desc, "z", "Unknown Client"); /* client type string */
5347         }
5348
5349         *rdata_len = desc.usedlen;
5350
5351         *rparam_len = 8;
5352         *rparam = smb_realloc_limit(*rparam,*rparam_len);
5353         if (!*rparam) {
5354                 return False;
5355         }
5356         SSVALS(*rparam,0,desc.errcode);
5357         SSVAL(*rparam,2,0); /* converter */
5358         SSVAL(*rparam,4,num_sessions); /* count */
5359
5360         DEBUG(4,("RNetSessionEnum: errorcode %d\n",desc.errcode));
5361
5362         return True;
5363 }
5364
5365
5366 /****************************************************************************
5367  The buffer was too small.
5368  ****************************************************************************/
5369
5370 static bool api_TooSmall(connection_struct *conn,uint16 vuid, char *param, char *data,
5371                          int mdrcnt, int mprcnt,
5372                          char **rdata, char **rparam,
5373                          int *rdata_len, int *rparam_len)
5374 {
5375         *rparam_len = MIN(*rparam_len,mprcnt);
5376         *rparam = smb_realloc_limit(*rparam,*rparam_len);
5377         if (!*rparam) {
5378                 return False;
5379         }
5380
5381         *rdata_len = 0;
5382
5383         SSVAL(*rparam,0,NERR_BufTooSmall);
5384
5385         DEBUG(3,("Supplied buffer too small in API command\n"));
5386
5387         return True;
5388 }
5389
5390 /****************************************************************************
5391  The request is not supported.
5392  ****************************************************************************/
5393
5394 static bool api_Unsupported(connection_struct *conn, uint16 vuid,
5395                                 char *param, int tpscnt,
5396                                 char *data, int tdscnt,
5397                                 int mdrcnt, int mprcnt,
5398                                 char **rdata, char **rparam,
5399                                 int *rdata_len, int *rparam_len)
5400 {
5401         *rparam_len = 4;
5402         *rparam = smb_realloc_limit(*rparam,*rparam_len);
5403         if (!*rparam) {
5404                 return False;
5405         }
5406
5407         *rdata_len = 0;
5408
5409         SSVAL(*rparam,0,NERR_notsupported);
5410         SSVAL(*rparam,2,0);             /* converter word */
5411
5412         DEBUG(3,("Unsupported API command\n"));
5413
5414         return True;
5415 }
5416
5417 static const struct {
5418         const char *name;
5419         int id;
5420         bool (*fn)(connection_struct *, uint16,
5421                         char *, int,
5422                         char *, int,
5423                         int,int,char **,char **,int *,int *);
5424         bool auth_user;         /* Deny anonymous access? */
5425 } api_commands[] = {
5426         {"RNetShareEnum",       RAP_WshareEnum,         api_RNetShareEnum, True},
5427         {"RNetShareGetInfo",    RAP_WshareGetInfo,      api_RNetShareGetInfo},
5428         {"RNetShareAdd",        RAP_WshareAdd,          api_RNetShareAdd},
5429         {"RNetSessionEnum",     RAP_WsessionEnum,       api_RNetSessionEnum, True},
5430         {"RNetServerGetInfo",   RAP_WserverGetInfo,     api_RNetServerGetInfo},
5431         {"RNetGroupEnum",       RAP_WGroupEnum,         api_RNetGroupEnum, True},
5432         {"RNetGroupGetUsers", RAP_WGroupGetUsers,       api_RNetGroupGetUsers, True},
5433         {"RNetUserEnum",        RAP_WUserEnum,          api_RNetUserEnum, True},
5434         {"RNetUserGetInfo",     RAP_WUserGetInfo,       api_RNetUserGetInfo},
5435         {"NetUserGetGroups",    RAP_WUserGetGroups,     api_NetUserGetGroups},
5436         {"NetWkstaGetInfo",     RAP_WWkstaGetInfo,      api_NetWkstaGetInfo},
5437         {"DosPrintQEnum",       RAP_WPrintQEnum,        api_DosPrintQEnum, True},
5438         {"DosPrintQGetInfo",    RAP_WPrintQGetInfo,     api_DosPrintQGetInfo},
5439         {"WPrintQueuePause",  RAP_WPrintQPause, api_WPrintQueueCtrl},
5440         {"WPrintQueueResume", RAP_WPrintQContinue,      api_WPrintQueueCtrl},
5441         {"WPrintJobEnumerate",RAP_WPrintJobEnum,        api_WPrintJobEnumerate},
5442         {"WPrintJobGetInfo",    RAP_WPrintJobGetInfo,   api_WPrintJobGetInfo},
5443         {"RDosPrintJobDel",     RAP_WPrintJobDel,       api_RDosPrintJobDel},
5444         {"RDosPrintJobPause",   RAP_WPrintJobPause,     api_RDosPrintJobDel},
5445         {"RDosPrintJobResume",RAP_WPrintJobContinue,    api_RDosPrintJobDel},
5446         {"WPrintDestEnum",      RAP_WPrintDestEnum,     api_WPrintDestEnum},
5447         {"WPrintDestGetInfo",   RAP_WPrintDestGetInfo,  api_WPrintDestGetInfo},
5448         {"NetRemoteTOD",        RAP_NetRemoteTOD,       api_NetRemoteTOD},
5449         {"WPrintQueuePurge",    RAP_WPrintQPurge,       api_WPrintQueueCtrl},
5450         {"NetServerEnum2",      RAP_NetServerEnum2,     api_RNetServerEnum2}, /* anon OK */
5451         {"NetServerEnum3",      RAP_NetServerEnum3,     api_RNetServerEnum3}, /* anon OK */
5452         {"WAccessGetUserPerms",RAP_WAccessGetUserPerms,api_WAccessGetUserPerms},
5453         {"SetUserPassword",     RAP_WUserPasswordSet2,  api_SetUserPassword},
5454         {"WWkstaUserLogon",     RAP_WWkstaUserLogon,    api_WWkstaUserLogon},
5455         {"PrintJobInfo",        RAP_WPrintJobSetInfo,   api_PrintJobInfo},
5456         {"WPrintDriverEnum",    RAP_WPrintDriverEnum,   api_WPrintDriverEnum},
5457         {"WPrintQProcEnum",     RAP_WPrintQProcessorEnum,api_WPrintQProcEnum},
5458         {"WPrintPortEnum",      RAP_WPrintPortEnum,     api_WPrintPortEnum},
5459         {"SamOEMChangePassword",RAP_SamOEMChgPasswordUser2_P,api_SamOEMChangePassword}, /* anon OK */
5460         {NULL,          -1,     api_Unsupported}
5461         /*  The following RAP calls are not implemented by Samba:
5462
5463         RAP_WFileEnum2 - anon not OK 
5464         */
5465 };
5466
5467
5468 /****************************************************************************
5469  Handle remote api calls.
5470 ****************************************************************************/
5471
5472 void api_reply(connection_struct *conn, uint16 vuid,
5473                struct smb_request *req,
5474                char *data, char *params,
5475                int tdscnt, int tpscnt,
5476                int mdrcnt, int mprcnt)
5477 {
5478         struct smbd_server_connection *sconn = smbd_server_conn;
5479         int api_command;
5480         char *rdata = NULL;
5481         char *rparam = NULL;
5482         const char *name1 = NULL;
5483         const char *name2 = NULL;
5484         int rdata_len = 0;
5485         int rparam_len = 0;
5486         bool reply=False;
5487         int i;
5488
5489         if (!params) {
5490                 DEBUG(0,("ERROR: NULL params in api_reply()\n"));
5491                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5492                 return;
5493         }
5494
5495         if (tpscnt < 2) {
5496                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5497                 return;
5498         }
5499         api_command = SVAL(params,0);
5500         /* Is there a string at position params+2 ? */
5501         if (skip_string(params,tpscnt,params+2)) {
5502                 name1 = params + 2;
5503         } else {
5504                 name1 = "";
5505         }
5506         name2 = skip_string(params,tpscnt,params+2);
5507         if (!name2) {
5508                 name2 = "";
5509         }
5510
5511         DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
5512                 api_command,
5513                 name1,
5514                 name2,
5515                 tdscnt,tpscnt,mdrcnt,mprcnt));
5516
5517         for (i=0;api_commands[i].name;i++) {
5518                 if (api_commands[i].id == api_command && api_commands[i].fn) {
5519                         DEBUG(3,("Doing %s\n",api_commands[i].name));
5520                         break;
5521                 }
5522         }
5523
5524         /* Check whether this api call can be done anonymously */
5525
5526         if (api_commands[i].auth_user && lp_restrict_anonymous()) {
5527                 user_struct *user = get_valid_user_struct(sconn, vuid);
5528
5529                 if (!user || user->server_info->guest) {
5530                         reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5531                         return;
5532                 }
5533         }
5534
5535         rdata = (char *)SMB_MALLOC(1024);
5536         if (rdata) {
5537                 memset(rdata,'\0',1024);
5538         }
5539
5540         rparam = (char *)SMB_MALLOC(1024);
5541         if (rparam) {
5542                 memset(rparam,'\0',1024);
5543         }
5544
5545         if(!rdata || !rparam) {
5546                 DEBUG(0,("api_reply: malloc fail !\n"));
5547                 SAFE_FREE(rdata);
5548                 SAFE_FREE(rparam);
5549                 reply_nterror(req, NT_STATUS_NO_MEMORY);
5550                 return;
5551         }
5552
5553         reply = api_commands[i].fn(conn,
5554                                 vuid,
5555                                 params,tpscnt,  /* params + length */
5556                                 data,tdscnt,    /* data + length */
5557                                 mdrcnt,mprcnt,
5558                                 &rdata,&rparam,&rdata_len,&rparam_len);
5559
5560
5561         if (rdata_len > mdrcnt || rparam_len > mprcnt) {
5562                 reply = api_TooSmall(conn,vuid,params,data,mdrcnt,mprcnt,
5563                                         &rdata,&rparam,&rdata_len,&rparam_len);
5564         }
5565
5566         /* if we get False back then it's actually unsupported */
5567         if (!reply) {
5568                 reply = api_Unsupported(conn,vuid,params,tpscnt,data,tdscnt,mdrcnt,mprcnt,
5569                         &rdata,&rparam,&rdata_len,&rparam_len);
5570         }
5571
5572         /* If api_Unsupported returns false we can't return anything. */
5573         if (reply) {
5574                 send_trans_reply(conn, req, rparam, rparam_len,
5575                                  rdata, rdata_len, False);
5576         }
5577
5578         SAFE_FREE(rdata);
5579         SAFE_FREE(rparam);
5580         return;
5581 }