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