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