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