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