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