source: vendor/current/source3/smbd/lanman.c

Last change on this file was 988, checked in by Silvan Scherrer, 9 years ago

Samba Server: update vendor to version 4.4.3

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