source: trunk/server/source3/smbd/lanman.c@ 902

Last change on this file since 902 was 874, checked in by Silvan Scherrer, 11 years ago

samba server 3.6: update trunk to 3.6.24

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