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