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

Last change on this file since 751 was 751, checked in by Silvan Scherrer, 13 years ago

Samba Server: updated trunk to 3.6.9

File size: 151.4 KB
Line 
1/*
2 Unix SMB/CIFS implementation.
3 Inter-process communication and named pipe handling
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Jeremy Allison 2007.
6
7 SMB Version handling
8 Copyright (C) John H Terpstra 1995-1998
9
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3 of the License, or
13 (at your option) any later version.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 */
23/*
24 This file handles the named pipe and mailslot calls
25 in the SMBtrans protocol
26 */
27
28#include "includes.h"
29#include "smbd/smbd.h"
30#include "smbd/globals.h"
31#include "rpc_client/rpc_client.h"
32#include "../librpc/gen_ndr/ndr_samr_c.h"
33#include "../librpc/gen_ndr/ndr_spoolss_c.h"
34#include "rpc_client/cli_spoolss.h"
35#include "rpc_client/init_spoolss.h"
36#include "../librpc/gen_ndr/ndr_srvsvc_c.h"
37#include "../librpc/gen_ndr/rap.h"
38#include "../lib/util/binsearch.h"
39#include "../libcli/auth/libcli_auth.h"
40#include "rpc_client/init_lsa.h"
41#include "../libcli/security/security.h"
42#include "printing.h"
43#include "passdb/machine_sid.h"
44#include "auth.h"
45#include "rpc_server/rpc_ncacn_np.h"
46
47#ifdef CHECK_TYPES
48#undef CHECK_TYPES
49#endif
50#define CHECK_TYPES 0
51
52#define NERR_Success 0
53#define NERR_badpass 86
54#define NERR_notsupported 50
55
56#define NERR_BASE (2100)
57#define NERR_BufTooSmall (NERR_BASE+23)
58#define NERR_JobNotFound (NERR_BASE+51)
59#define NERR_DestNotFound (NERR_BASE+52)
60
61#define ACCESS_READ 0x01
62#define ACCESS_WRITE 0x02
63#define ACCESS_CREATE 0x04
64
65#define SHPWLEN 8 /* share password length */
66
67/* Limit size of ipc replies */
68
69static char *smb_realloc_limit(void *ptr, size_t size)
70{
71 char *val;
72
73 size = MAX((size),4*1024);
74 val = (char *)SMB_REALLOC(ptr,size);
75 if (val) {
76 memset(val,'\0',size);
77 }
78 return val;
79}
80
81static bool api_Unsupported(struct smbd_server_connection *sconn,
82 connection_struct *conn, 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 == -1) {
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 == -1) {
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
2632 if (type.ids[0] != SID_NAME_USER) {
2633 DEBUG(10, ("%s is a %s, not a user\n", UserName,
2634 sid_type_lookup(type.ids[0])));
2635 goto close_domain;
2636 }
2637
2638 status = dcerpc_samr_OpenUser(b, talloc_tos(),
2639 &domain_handle,
2640 SAMR_USER_ACCESS_GET_GROUPS,
2641 rid.ids[0], &user_handle,
2642 &result);
2643 if (!NT_STATUS_IS_OK(status)) {
2644 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2645 nt_errstr(status)));
2646 goto close_domain;
2647 }
2648 if (!NT_STATUS_IS_OK(result)) {
2649 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2650 nt_errstr(result)));
2651 goto close_domain;
2652 }
2653
2654 status = dcerpc_samr_GetGroupsForUser(b, talloc_tos(),
2655 &user_handle, &rids,
2656 &result);
2657 if (!NT_STATUS_IS_OK(status)) {
2658 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2659 nt_errstr(status)));
2660 goto close_user;
2661 }
2662 if (!NT_STATUS_IS_OK(result)) {
2663 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2664 nt_errstr(result)));
2665 goto close_user;
2666 }
2667
2668 for (i=0; i<rids->count; i++) {
2669
2670 status = dcerpc_samr_LookupRids(b, talloc_tos(),
2671 &domain_handle,
2672 1, &rids->rids[i].rid,
2673 &names, &type,
2674 &result);
2675 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result) && (names.count == 1)) {
2676 strlcpy(p, names.names[0].string, PTR_DIFF(endp,p));
2677 p += 21;
2678 count++;
2679 }
2680 }
2681
2682 *rdata_len = PTR_DIFF(p,*rdata);
2683
2684 SSVAL(*rparam,4,count); /* is this right?? */
2685 SSVAL(*rparam,6,count); /* is this right?? */
2686
2687 ret = True;
2688
2689 close_user:
2690 dcerpc_samr_Close(b, talloc_tos(), &user_handle, &result);
2691 close_domain:
2692 dcerpc_samr_Close(b, talloc_tos(), &domain_handle, &result);
2693 close_sam:
2694 dcerpc_samr_Close(b, talloc_tos(), &samr_handle, &result);
2695
2696 return ret;
2697}
2698
2699/*******************************************************************
2700 Get all users.
2701******************************************************************/
2702
2703static bool api_RNetUserEnum(struct smbd_server_connection *sconn,
2704 connection_struct *conn, uint16 vuid,
2705 char *param, int tpscnt,
2706 char *data, int tdscnt,
2707 int mdrcnt,int mprcnt,
2708 char **rdata,char **rparam,
2709 int *rdata_len,int *rparam_len)
2710{
2711 int count_sent=0;
2712 int num_users=0;
2713 int errflags=0;
2714 int i, resume_context, cli_buf_size;
2715 uint32_t resume_handle;
2716
2717 struct rpc_pipe_client *samr_pipe;
2718 struct policy_handle samr_handle, domain_handle;
2719 NTSTATUS status, result;
2720
2721 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2722 char *str2 = skip_string(param,tpscnt,str1);
2723 char *p = skip_string(param,tpscnt,str2);
2724 char *endp = NULL;
2725
2726 struct dcerpc_binding_handle *b;
2727
2728 if (!str1 || !str2 || !p) {
2729 return False;
2730 }
2731
2732 if (strcmp(str1,"WrLeh") != 0)
2733 return False;
2734 /* parameters
2735 * W-> resume context (number of users to skip)
2736 * r -> return parameter pointer to receive buffer
2737 * L -> length of receive buffer
2738 * e -> return parameter number of entries
2739 * h -> return parameter total number of users
2740 */
2741
2742 resume_context = get_safe_SVAL(param,tpscnt,p,0,-1);
2743 cli_buf_size= get_safe_SVAL(param,tpscnt,p,2,0);
2744 DEBUG(10,("api_RNetUserEnum:resume context: %d, client buffer size: %d\n",
2745 resume_context, cli_buf_size));
2746
2747 *rparam_len = 8;
2748 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2749 if (!*rparam) {
2750 return False;
2751 }
2752
2753 /* check it's a supported varient */
2754 if (strcmp("B21",str2) != 0)
2755 return False;
2756
2757 *rdata_len = cli_buf_size;
2758 *rdata = smb_realloc_limit(*rdata,*rdata_len);
2759 if (!*rdata) {
2760 return False;
2761 }
2762
2763 p = *rdata;
2764 endp = *rdata + *rdata_len;
2765
2766 status = rpc_pipe_open_interface(
2767 talloc_tos(), &ndr_table_samr.syntax_id,
2768 conn->session_info, &conn->sconn->client_id,
2769 conn->sconn->msg_ctx, &samr_pipe);
2770 if (!NT_STATUS_IS_OK(status)) {
2771 DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
2772 nt_errstr(status)));
2773 return false;
2774 }
2775
2776 b = samr_pipe->binding_handle;
2777
2778 status = dcerpc_samr_Connect2(b, talloc_tos(), global_myname(),
2779 SAMR_ACCESS_LOOKUP_DOMAIN, &samr_handle,
2780 &result);
2781 if (!NT_STATUS_IS_OK(status)) {
2782 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2783 nt_errstr(status)));
2784 return false;
2785 }
2786 if (!NT_STATUS_IS_OK(result)) {
2787 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2788 nt_errstr(result)));
2789 return false;
2790 }
2791
2792 status = dcerpc_samr_OpenDomain(b, talloc_tos(), &samr_handle,
2793 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS,
2794 get_global_sam_sid(), &domain_handle,
2795 &result);
2796 if (!NT_STATUS_IS_OK(status)) {
2797 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2798 nt_errstr(status)));
2799 dcerpc_samr_Close(b, talloc_tos(), &samr_handle, &result);
2800 return false;
2801 }
2802 if (!NT_STATUS_IS_OK(result)) {
2803 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2804 nt_errstr(result)));
2805 dcerpc_samr_Close(b, talloc_tos(), &samr_handle, &result);
2806 return false;
2807 }
2808
2809 errflags=NERR_Success;
2810
2811 resume_handle = 0;
2812
2813 while (true) {
2814 struct samr_SamArray *sam_entries;
2815 uint32_t num_entries;
2816
2817 status = dcerpc_samr_EnumDomainUsers(b, talloc_tos(),
2818 &domain_handle,
2819 &resume_handle,
2820 0, &sam_entries, 1,
2821 &num_entries,
2822 &result);
2823
2824 if (!NT_STATUS_IS_OK(status)) {
2825 DEBUG(10, ("dcerpc_samr_EnumDomainUsers returned "
2826 "%s\n", nt_errstr(status)));
2827 break;
2828 }
2829 if (!NT_STATUS_IS_OK(result)) {
2830 DEBUG(10, ("dcerpc_samr_EnumDomainUsers returned "
2831 "%s\n", nt_errstr(result)));
2832 break;
2833 }
2834
2835 if (num_entries == 0) {
2836 DEBUG(10, ("dcerpc_samr_EnumDomainUsers returned "
2837 "no entries -- done\n"));
2838 break;
2839 }
2840
2841 for (i=0; i<num_entries; i++) {
2842 const char *name;
2843
2844 name = sam_entries->entries[i].name.string;
2845
2846 if(((PTR_DIFF(p,*rdata)+21)<=*rdata_len)
2847 &&(strlen(name)<=21)) {
2848 strlcpy(p,name,PTR_DIFF(endp,p));
2849 DEBUG(10,("api_RNetUserEnum:adding entry %d "
2850 "username %s\n",count_sent,p));
2851 p += 21;
2852 count_sent++;
2853 } else {
2854 /* set overflow error */
2855 DEBUG(10,("api_RNetUserEnum:overflow on entry %d "
2856 "username %s\n",count_sent,name));
2857 errflags=234;
2858 break;
2859 }
2860 }
2861
2862 if (errflags != NERR_Success) {
2863 break;
2864 }
2865
2866 TALLOC_FREE(sam_entries);
2867 }
2868
2869 dcerpc_samr_Close(b, talloc_tos(), &domain_handle, &result);
2870 dcerpc_samr_Close(b, talloc_tos(), &samr_handle, &result);
2871
2872 *rdata_len = PTR_DIFF(p,*rdata);
2873
2874 SSVAL(*rparam,0,errflags);
2875 SSVAL(*rparam,2,0); /* converter word */
2876 SSVAL(*rparam,4,count_sent); /* is this right?? */
2877 SSVAL(*rparam,6,num_users); /* is this right?? */
2878
2879 return True;
2880}
2881
2882/****************************************************************************
2883 Get the time of day info.
2884****************************************************************************/
2885
2886static bool api_NetRemoteTOD(struct smbd_server_connection *sconn,
2887 connection_struct *conn,uint16 vuid,
2888 char *param, int tpscnt,
2889 char *data, int tdscnt,
2890 int mdrcnt,int mprcnt,
2891 char **rdata,char **rparam,
2892 int *rdata_len,int *rparam_len)
2893{
2894 struct tm *t;
2895 time_t unixdate = time(NULL);
2896 char *p;
2897
2898 *rparam_len = 4;
2899 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2900 if (!*rparam) {
2901 return False;
2902 }
2903
2904 *rdata_len = 21;
2905 *rdata = smb_realloc_limit(*rdata,*rdata_len);
2906 if (!*rdata) {
2907 return False;
2908 }
2909
2910 SSVAL(*rparam,0,NERR_Success);
2911 SSVAL(*rparam,2,0); /* converter word */
2912
2913 p = *rdata;
2914
2915 srv_put_dos_date3(p,0,unixdate); /* this is the time that is looked at
2916 by NT in a "net time" operation,
2917 it seems to ignore the one below */
2918
2919 /* the client expects to get localtime, not GMT, in this bit
2920 (I think, this needs testing) */
2921 t = localtime(&unixdate);
2922 if (!t) {
2923 return False;
2924 }
2925
2926 SIVAL(p,4,0); /* msecs ? */
2927 SCVAL(p,8,t->tm_hour);
2928 SCVAL(p,9,t->tm_min);
2929 SCVAL(p,10,t->tm_sec);
2930 SCVAL(p,11,0); /* hundredths of seconds */
2931 SSVALS(p,12,get_time_zone(unixdate)/60); /* timezone in minutes from GMT */
2932 SSVAL(p,14,10000); /* timer interval in 0.0001 of sec */
2933 SCVAL(p,16,t->tm_mday);
2934 SCVAL(p,17,t->tm_mon + 1);
2935 SSVAL(p,18,1900+t->tm_year);
2936 SCVAL(p,20,t->tm_wday);
2937
2938 return True;
2939}
2940
2941/****************************************************************************
2942 Set the user password.
2943*****************************************************************************/
2944
2945static bool api_SetUserPassword(struct smbd_server_connection *sconn,
2946 connection_struct *conn,uint16 vuid,
2947 char *param, int tpscnt,
2948 char *data, int tdscnt,
2949 int mdrcnt,int mprcnt,
2950 char **rdata,char **rparam,
2951 int *rdata_len,int *rparam_len)
2952{
2953 char *np = get_safe_str_ptr(param,tpscnt,param,2);
2954 char *p = NULL;
2955 fstring user;
2956 fstring pass1,pass2;
2957 TALLOC_CTX *mem_ctx = talloc_tos();
2958 NTSTATUS status, result;
2959 struct rpc_pipe_client *cli = NULL;
2960 struct policy_handle connect_handle, domain_handle, user_handle;
2961 struct lsa_String domain_name;
2962 struct dom_sid2 *domain_sid;
2963 struct lsa_String names;
2964 struct samr_Ids rids;
2965 struct samr_Ids types;
2966 struct samr_Password old_lm_hash;
2967 struct samr_Password new_lm_hash;
2968 int errcode = NERR_badpass;
2969 uint32_t rid;
2970 int encrypted;
2971 int min_pwd_length;
2972 struct dcerpc_binding_handle *b = NULL;
2973
2974 /* Skip 2 strings. */
2975 p = skip_string(param,tpscnt,np);
2976 p = skip_string(param,tpscnt,p);
2977
2978 if (!np || !p) {
2979 return False;
2980 }
2981
2982 /* Do we have a string ? */
2983 if (skip_string(param,tpscnt,p) == NULL) {
2984 return False;
2985 }
2986 pull_ascii_fstring(user,p);
2987
2988 p = skip_string(param,tpscnt,p);
2989 if (!p) {
2990 return False;
2991 }
2992
2993 memset(pass1,'\0',sizeof(pass1));
2994 memset(pass2,'\0',sizeof(pass2));
2995 /*
2996 * We use 31 here not 32 as we're checking
2997 * the last byte we want to access is safe.
2998 */
2999 if (!is_offset_safe(param,tpscnt,p,31)) {
3000 return False;
3001 }
3002 memcpy(pass1,p,16);
3003 memcpy(pass2,p+16,16);
3004
3005 encrypted = get_safe_SVAL(param,tpscnt,p+32,0,-1);
3006 if (encrypted == -1) {
3007 errcode = W_ERROR_V(WERR_INVALID_PARAM);
3008 goto out;
3009 }
3010
3011 min_pwd_length = get_safe_SVAL(param,tpscnt,p+34,0,-1);
3012 if (min_pwd_length == -1) {
3013 errcode = W_ERROR_V(WERR_INVALID_PARAM);
3014 goto out;
3015 }
3016
3017 *rparam_len = 4;
3018 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3019 if (!*rparam) {
3020 return False;
3021 }
3022
3023 *rdata_len = 0;
3024
3025 DEBUG(3,("Set password for <%s> (encrypted: %d, min_pwd_length: %d)\n",
3026 user, encrypted, min_pwd_length));
3027
3028 ZERO_STRUCT(connect_handle);
3029 ZERO_STRUCT(domain_handle);
3030 ZERO_STRUCT(user_handle);
3031
3032 status = rpc_pipe_open_interface(mem_ctx, &ndr_table_samr.syntax_id,
3033 conn->session_info,
3034 &conn->sconn->client_id,
3035 conn->sconn->msg_ctx,
3036 &cli);
3037 if (!NT_STATUS_IS_OK(status)) {
3038 DEBUG(0,("api_SetUserPassword: could not connect to samr: %s\n",
3039 nt_errstr(status)));
3040 errcode = W_ERROR_V(ntstatus_to_werror(status));
3041 goto out;
3042 }
3043
3044 b = cli->binding_handle;
3045
3046 status = dcerpc_samr_Connect2(b, mem_ctx,
3047 global_myname(),
3048 SAMR_ACCESS_CONNECT_TO_SERVER |
3049 SAMR_ACCESS_ENUM_DOMAINS |
3050 SAMR_ACCESS_LOOKUP_DOMAIN,
3051 &connect_handle,
3052 &result);
3053 if (!NT_STATUS_IS_OK(status)) {
3054 errcode = W_ERROR_V(ntstatus_to_werror(status));
3055 goto out;
3056 }
3057 if (!NT_STATUS_IS_OK(result)) {
3058 errcode = W_ERROR_V(ntstatus_to_werror(result));
3059 goto out;
3060 }
3061
3062 init_lsa_String(&domain_name, get_global_sam_name());
3063
3064 status = dcerpc_samr_LookupDomain(b, mem_ctx,
3065 &connect_handle,
3066 &domain_name,
3067 &domain_sid,
3068 &result);
3069 if (!NT_STATUS_IS_OK(status)) {
3070 errcode = W_ERROR_V(ntstatus_to_werror(status));
3071 goto out;
3072 }
3073 if (!NT_STATUS_IS_OK(result)) {
3074 errcode = W_ERROR_V(ntstatus_to_werror(result));
3075 goto out;
3076 }
3077
3078 status = dcerpc_samr_OpenDomain(b, mem_ctx,
3079 &connect_handle,
3080 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
3081 domain_sid,
3082 &domain_handle,
3083 &result);
3084 if (!NT_STATUS_IS_OK(status)) {
3085 errcode = W_ERROR_V(ntstatus_to_werror(status));
3086 goto out;
3087 }
3088 if (!NT_STATUS_IS_OK(result)) {
3089 errcode = W_ERROR_V(ntstatus_to_werror(result));
3090 goto out;
3091 }
3092
3093 init_lsa_String(&names, user);
3094
3095 status = dcerpc_samr_LookupNames(b, mem_ctx,
3096 &domain_handle,
3097 1,
3098 &names,
3099 &rids,
3100 &types,
3101 &result);
3102 if (!NT_STATUS_IS_OK(status)) {
3103 errcode = W_ERROR_V(ntstatus_to_werror(status));
3104 goto out;
3105 }
3106 if (!NT_STATUS_IS_OK(result)) {
3107 errcode = W_ERROR_V(ntstatus_to_werror(result));
3108 goto out;
3109 }
3110
3111 if (rids.count != 1) {
3112 errcode = W_ERROR_V(WERR_NO_SUCH_USER);
3113 goto out;
3114 }
3115 if (rids.count != types.count) {
3116 errcode = W_ERROR_V(WERR_INVALID_PARAM);
3117 goto out;
3118 }
3119 if (types.ids[0] != SID_NAME_USER) {
3120 errcode = W_ERROR_V(WERR_INVALID_PARAM);
3121 goto out;
3122 }
3123
3124 rid = rids.ids[0];
3125
3126 status = dcerpc_samr_OpenUser(b, mem_ctx,
3127 &domain_handle,
3128 SAMR_USER_ACCESS_CHANGE_PASSWORD,
3129 rid,
3130 &user_handle,
3131 &result);
3132 if (!NT_STATUS_IS_OK(status)) {
3133 errcode = W_ERROR_V(ntstatus_to_werror(status));
3134 goto out;
3135 }
3136 if (!NT_STATUS_IS_OK(result)) {
3137 errcode = W_ERROR_V(ntstatus_to_werror(result));
3138 goto out;
3139 }
3140
3141 if (encrypted == 0) {
3142 E_deshash(pass1, old_lm_hash.hash);
3143 E_deshash(pass2, new_lm_hash.hash);
3144 } else {
3145 ZERO_STRUCT(old_lm_hash);
3146 ZERO_STRUCT(new_lm_hash);
3147 memcpy(old_lm_hash.hash, pass1, MIN(strlen(pass1), 16));
3148 memcpy(new_lm_hash.hash, pass1, MIN(strlen(pass2), 16));
3149 }
3150
3151 status = dcerpc_samr_ChangePasswordUser(b, mem_ctx,
3152 &user_handle,
3153 true, /* lm_present */
3154 &old_lm_hash,
3155 &new_lm_hash,
3156 false, /* nt_present */
3157 NULL, /* old_nt_crypted */
3158 NULL, /* new_nt_crypted */
3159 false, /* cross1_present */
3160 NULL, /* nt_cross */
3161 false, /* cross2_present */
3162 NULL, /* lm_cross */
3163 &result);
3164 if (!NT_STATUS_IS_OK(status)) {
3165 errcode = W_ERROR_V(ntstatus_to_werror(status));
3166 goto out;
3167 }
3168 if (!NT_STATUS_IS_OK(result)) {
3169 errcode = W_ERROR_V(ntstatus_to_werror(result));
3170 goto out;
3171 }
3172
3173 errcode = NERR_Success;
3174 out:
3175
3176 if (b && is_valid_policy_hnd(&user_handle)) {
3177 dcerpc_samr_Close(b, mem_ctx, &user_handle, &result);
3178 }
3179 if (b && is_valid_policy_hnd(&domain_handle)) {
3180 dcerpc_samr_Close(b, mem_ctx, &domain_handle, &result);
3181 }
3182 if (b && is_valid_policy_hnd(&connect_handle)) {
3183 dcerpc_samr_Close(b, mem_ctx, &connect_handle, &result);
3184 }
3185
3186 memset((char *)pass1,'\0',sizeof(fstring));
3187 memset((char *)pass2,'\0',sizeof(fstring));
3188
3189 SSVAL(*rparam,0,errcode);
3190 SSVAL(*rparam,2,0); /* converter word */
3191 return(True);
3192}
3193
3194/****************************************************************************
3195 Set the user password (SamOEM version - gets plaintext).
3196****************************************************************************/
3197
3198static bool api_SamOEMChangePassword(struct smbd_server_connection *sconn,
3199 connection_struct *conn,uint16 vuid,
3200 char *param, int tpscnt,
3201 char *data, int tdscnt,
3202 int mdrcnt,int mprcnt,
3203 char **rdata,char **rparam,
3204 int *rdata_len,int *rparam_len)
3205{
3206 fstring user;
3207 char *p = get_safe_str_ptr(param,tpscnt,param,2);
3208
3209 TALLOC_CTX *mem_ctx = talloc_tos();
3210 NTSTATUS status, result;
3211 struct rpc_pipe_client *cli = NULL;
3212 struct lsa_AsciiString server, account;
3213 struct samr_CryptPassword password;
3214 struct samr_Password hash;
3215 int errcode = NERR_badpass;
3216 int bufsize;
3217 struct dcerpc_binding_handle *b;
3218
3219 *rparam_len = 4;
3220 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3221 if (!*rparam) {
3222 return False;
3223 }
3224
3225 if (!p) {
3226 return False;
3227 }
3228 *rdata_len = 0;
3229
3230 SSVAL(*rparam,0,NERR_badpass);
3231
3232 /*
3233 * Check the parameter definition is correct.
3234 */
3235
3236 /* Do we have a string ? */
3237 if (skip_string(param,tpscnt,p) == 0) {
3238 return False;
3239 }
3240 if(!strequal(p, "zsT")) {
3241 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", p));
3242 return False;
3243 }
3244 p = skip_string(param, tpscnt, p);
3245 if (!p) {
3246 return False;
3247 }
3248
3249 /* Do we have a string ? */
3250 if (skip_string(param,tpscnt,p) == 0) {
3251 return False;
3252 }
3253 if(!strequal(p, "B516B16")) {
3254 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p));
3255 return False;
3256 }
3257 p = skip_string(param,tpscnt,p);
3258 if (!p) {
3259 return False;
3260 }
3261 /* Do we have a string ? */
3262 if (skip_string(param,tpscnt,p) == 0) {
3263 return False;
3264 }
3265 p += pull_ascii_fstring(user,p);
3266
3267 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user));
3268
3269 if (tdscnt != 532) {
3270 errcode = W_ERROR_V(WERR_INVALID_PARAM);
3271 goto out;
3272 }
3273
3274 bufsize = get_safe_SVAL(param,tpscnt,p,0,-1);
3275 if (bufsize != 532) {
3276 errcode = W_ERROR_V(WERR_INVALID_PARAM);
3277 goto out;
3278 }
3279
3280 memcpy(password.data, data, 516);
3281 memcpy(hash.hash, data+516, 16);
3282
3283 status = rpc_pipe_open_interface(mem_ctx, &ndr_table_samr.syntax_id,
3284 conn->session_info,
3285 &conn->sconn->client_id,
3286 conn->sconn->msg_ctx,
3287 &cli);
3288 if (!NT_STATUS_IS_OK(status)) {
3289 DEBUG(0,("api_SamOEMChangePassword: could not connect to samr: %s\n",
3290 nt_errstr(status)));
3291 errcode = W_ERROR_V(ntstatus_to_werror(status));
3292 goto out;
3293 }
3294
3295 b = cli->binding_handle;
3296
3297 init_lsa_AsciiString(&server, global_myname());
3298 init_lsa_AsciiString(&account, user);
3299
3300 status = dcerpc_samr_OemChangePasswordUser2(b, mem_ctx,
3301 &server,
3302 &account,
3303 &password,
3304 &hash,
3305 &result);
3306 if (!NT_STATUS_IS_OK(status)) {
3307 errcode = W_ERROR_V(ntstatus_to_werror(status));
3308 goto out;
3309 }
3310 if (!NT_STATUS_IS_OK(result)) {
3311 errcode = W_ERROR_V(ntstatus_to_werror(result));
3312 goto out;
3313 }
3314
3315 errcode = NERR_Success;
3316 out:
3317 SSVAL(*rparam,0,errcode);
3318 SSVAL(*rparam,2,0); /* converter word */
3319
3320 return(True);
3321}
3322
3323/****************************************************************************
3324 delete a print job
3325 Form: <W> <>
3326 ****************************************************************************/
3327
3328static bool api_RDosPrintJobDel(struct smbd_server_connection *sconn,
3329 connection_struct *conn,uint16 vuid,
3330 char *param, int tpscnt,
3331 char *data, int tdscnt,
3332 int mdrcnt,int mprcnt,
3333 char **rdata,char **rparam,
3334 int *rdata_len,int *rparam_len)
3335{
3336 int function = get_safe_SVAL(param,tpscnt,param,0,0);
3337 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3338 char *str2 = skip_string(param,tpscnt,str1);
3339 char *p = skip_string(param,tpscnt,str2);
3340 uint32 jobid;
3341 fstring sharename;
3342 int errcode;
3343 WERROR werr = WERR_OK;
3344
3345 TALLOC_CTX *mem_ctx = talloc_tos();
3346 NTSTATUS status;
3347 struct rpc_pipe_client *cli = NULL;
3348 struct dcerpc_binding_handle *b = NULL;
3349 struct policy_handle handle;
3350 struct spoolss_DevmodeContainer devmode_ctr;
3351 enum spoolss_JobControl command;
3352
3353 if (!str1 || !str2 || !p) {
3354 return False;
3355 }
3356 /*
3357 * We use 1 here not 2 as we're checking
3358 * the last byte we want to access is safe.
3359 */
3360 if (!is_offset_safe(param,tpscnt,p,1)) {
3361 return False;
3362 }
3363 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid))
3364 return False;
3365
3366 /* check it's a supported varient */
3367 if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
3368 return(False);
3369
3370 *rparam_len = 4;
3371 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3372 if (!*rparam) {
3373 return False;
3374 }
3375 *rdata_len = 0;
3376
3377 ZERO_STRUCT(handle);
3378
3379 status = rpc_pipe_open_interface(conn,
3380 &ndr_table_spoolss.syntax_id,
3381 conn->session_info,
3382 &conn->sconn->client_id,
3383 conn->sconn->msg_ctx,
3384 &cli);
3385 if (!NT_STATUS_IS_OK(status)) {
3386 DEBUG(0,("api_RDosPrintJobDel: could not connect to spoolss: %s\n",
3387 nt_errstr(status)));
3388 errcode = W_ERROR_V(ntstatus_to_werror(status));
3389 goto out;
3390 }
3391 b = cli->binding_handle;
3392
3393 ZERO_STRUCT(devmode_ctr);
3394
3395 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
3396 sharename,
3397 "RAW",
3398 devmode_ctr,
3399 JOB_ACCESS_ADMINISTER,
3400 &handle,
3401 &werr);
3402 if (!NT_STATUS_IS_OK(status)) {
3403 errcode = W_ERROR_V(ntstatus_to_werror(status));
3404 goto out;
3405 }
3406 if (!W_ERROR_IS_OK(werr)) {
3407 errcode = W_ERROR_V(werr);
3408 goto out;
3409 }
3410
3411 /* FIXME: formerly NERR_JobNotFound was returned if job did not exist
3412 * and NERR_DestNotFound if share did not exist */
3413
3414 errcode = NERR_Success;
3415
3416 switch (function) {
3417 case 81: /* delete */
3418 command = SPOOLSS_JOB_CONTROL_DELETE;
3419 break;
3420 case 82: /* pause */
3421 command = SPOOLSS_JOB_CONTROL_PAUSE;
3422 break;
3423 case 83: /* resume */
3424 command = SPOOLSS_JOB_CONTROL_RESUME;
3425 break;
3426 default:
3427 errcode = NERR_notsupported;
3428 goto out;
3429 }
3430
3431 status = dcerpc_spoolss_SetJob(b, mem_ctx,
3432 &handle,
3433 jobid,
3434 NULL, /* unique ptr ctr */
3435 command,
3436 &werr);
3437 if (!NT_STATUS_IS_OK(status)) {
3438 errcode = W_ERROR_V(ntstatus_to_werror(status));
3439 goto out;
3440 }
3441 if (!W_ERROR_IS_OK(werr)) {
3442 errcode = W_ERROR_V(werr);
3443 goto out;
3444 }
3445
3446 out:
3447 if (b && is_valid_policy_hnd(&handle)) {
3448 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
3449 }
3450
3451 SSVAL(*rparam,0,errcode);
3452 SSVAL(*rparam,2,0); /* converter word */
3453
3454 return(True);
3455}
3456
3457/****************************************************************************
3458 Purge a print queue - or pause or resume it.
3459 ****************************************************************************/
3460
3461static bool api_WPrintQueueCtrl(struct smbd_server_connection *sconn,
3462 connection_struct *conn,uint16 vuid,
3463 char *param, int tpscnt,
3464 char *data, int tdscnt,
3465 int mdrcnt,int mprcnt,
3466 char **rdata,char **rparam,
3467 int *rdata_len,int *rparam_len)
3468{
3469 int function = get_safe_SVAL(param,tpscnt,param,0,0);
3470 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3471 char *str2 = skip_string(param,tpscnt,str1);
3472 char *QueueName = skip_string(param,tpscnt,str2);
3473 int errcode = NERR_notsupported;
3474 WERROR werr = WERR_OK;
3475 NTSTATUS status;
3476
3477 TALLOC_CTX *mem_ctx = talloc_tos();
3478 struct rpc_pipe_client *cli = NULL;
3479 struct dcerpc_binding_handle *b = NULL;
3480 struct policy_handle handle;
3481 struct spoolss_SetPrinterInfoCtr info_ctr;
3482 struct spoolss_DevmodeContainer devmode_ctr;
3483 struct sec_desc_buf secdesc_ctr;
3484 enum spoolss_PrinterControl command;
3485
3486 if (!str1 || !str2 || !QueueName) {
3487 return False;
3488 }
3489
3490 /* check it's a supported varient */
3491 if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
3492 return(False);
3493
3494 *rparam_len = 4;
3495 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3496 if (!*rparam) {
3497 return False;
3498 }
3499 *rdata_len = 0;
3500
3501 if (skip_string(param,tpscnt,QueueName) == NULL) {
3502 return False;
3503 }
3504
3505 ZERO_STRUCT(handle);
3506
3507 status = rpc_pipe_open_interface(conn,
3508 &ndr_table_spoolss.syntax_id,
3509 conn->session_info,
3510 &conn->sconn->client_id,
3511 conn->sconn->msg_ctx,
3512 &cli);
3513 if (!NT_STATUS_IS_OK(status)) {
3514 DEBUG(0,("api_WPrintQueueCtrl: could not connect to spoolss: %s\n",
3515 nt_errstr(status)));
3516 errcode = W_ERROR_V(ntstatus_to_werror(status));
3517 goto out;
3518 }
3519 b = cli->binding_handle;
3520
3521 ZERO_STRUCT(devmode_ctr);
3522
3523 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
3524 QueueName,
3525 NULL,
3526 devmode_ctr,
3527 PRINTER_ACCESS_ADMINISTER,
3528 &handle,
3529 &werr);
3530 if (!NT_STATUS_IS_OK(status)) {
3531 errcode = W_ERROR_V(ntstatus_to_werror(status));
3532 goto out;
3533 }
3534 if (!W_ERROR_IS_OK(werr)) {
3535 errcode = W_ERROR_V(werr);
3536 goto out;
3537 }
3538
3539 switch (function) {
3540 case 74: /* Pause queue */
3541 command = SPOOLSS_PRINTER_CONTROL_PAUSE;
3542 break;
3543 case 75: /* Resume queue */
3544 command = SPOOLSS_PRINTER_CONTROL_RESUME;
3545 break;
3546 case 103: /* Purge */
3547 command = SPOOLSS_PRINTER_CONTROL_PURGE;
3548 break;
3549 default:
3550 werr = WERR_NOT_SUPPORTED;
3551 break;
3552 }
3553
3554 if (!W_ERROR_IS_OK(werr)) {
3555 errcode = W_ERROR_V(werr);
3556 goto out;
3557 }
3558
3559 ZERO_STRUCT(info_ctr);
3560 ZERO_STRUCT(secdesc_ctr);
3561
3562 status = dcerpc_spoolss_SetPrinter(b, mem_ctx,
3563 &handle,
3564 &info_ctr,
3565 &devmode_ctr,
3566 &secdesc_ctr,
3567 command,
3568 &werr);
3569 if (!NT_STATUS_IS_OK(status)) {
3570 errcode = W_ERROR_V(ntstatus_to_werror(status));
3571 goto out;
3572 }
3573 if (!W_ERROR_IS_OK(werr)) {
3574 errcode = W_ERROR_V(werr);
3575 goto out;
3576 }
3577
3578 errcode = W_ERROR_V(werr);
3579
3580 out:
3581
3582 if (b && is_valid_policy_hnd(&handle)) {
3583 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
3584 }
3585
3586 SSVAL(*rparam,0,errcode);
3587 SSVAL(*rparam,2,0); /* converter word */
3588
3589 return(True);
3590}
3591
3592/****************************************************************************
3593 set the property of a print job (undocumented?)
3594 ? function = 0xb -> set name of print job
3595 ? function = 0x6 -> move print job up/down
3596 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
3597 or <WWsTP> <WB21BB16B10zWWzDDz>
3598****************************************************************************/
3599
3600static int check_printjob_info(struct pack_desc* desc,
3601 int uLevel, char* id)
3602{
3603 desc->subformat = NULL;
3604 switch( uLevel ) {
3605 case 0: desc->format = "W"; break;
3606 case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
3607 case 2: desc->format = "WWzWWDDzz"; break;
3608 case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
3609 case 4: desc->format = "WWzWWDDzzzzzDDDDDDD"; break;
3610 default:
3611 DEBUG(0,("check_printjob_info: invalid level %d\n",
3612 uLevel ));
3613 return False;
3614 }
3615 if (id == NULL || strcmp(desc->format,id) != 0) {
3616 DEBUG(0,("check_printjob_info: invalid format %s\n",
3617 id ? id : "<NULL>" ));
3618 return False;
3619 }
3620 return True;
3621}
3622
3623static bool api_PrintJobInfo(struct smbd_server_connection *sconn,
3624 connection_struct *conn, uint16 vuid,
3625 char *param, int tpscnt,
3626 char *data, int tdscnt,
3627 int mdrcnt,int mprcnt,
3628 char **rdata,char **rparam,
3629 int *rdata_len,int *rparam_len)
3630{
3631 struct pack_desc desc;
3632 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3633 char *str2 = skip_string(param,tpscnt,str1);
3634 char *p = skip_string(param,tpscnt,str2);
3635 uint32 jobid;
3636 fstring sharename;
3637 int uLevel = get_safe_SVAL(param,tpscnt,p,2,-1);
3638 int function = get_safe_SVAL(param,tpscnt,p,4,-1);
3639 int errcode;
3640
3641 TALLOC_CTX *mem_ctx = talloc_tos();
3642 WERROR werr;
3643 NTSTATUS status;
3644 struct rpc_pipe_client *cli = NULL;
3645 struct dcerpc_binding_handle *b = NULL;
3646 struct policy_handle handle;
3647 struct spoolss_DevmodeContainer devmode_ctr;
3648 struct spoolss_JobInfoContainer ctr;
3649 union spoolss_JobInfo info;
3650 struct spoolss_SetJobInfo1 info1;
3651
3652 if (!str1 || !str2 || !p) {
3653 return False;
3654 }
3655 /*
3656 * We use 1 here not 2 as we're checking
3657 * the last byte we want to access is safe.
3658 */
3659 if (!is_offset_safe(param,tpscnt,p,1)) {
3660 return False;
3661 }
3662 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid))
3663 return False;
3664 *rparam_len = 4;
3665 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3666 if (!*rparam) {
3667 return False;
3668 }
3669
3670 *rdata_len = 0;
3671
3672 /* check it's a supported varient */
3673 if ((strcmp(str1,"WWsTP")) ||
3674 (!check_printjob_info(&desc,uLevel,str2)))
3675 return(False);
3676
3677 errcode = NERR_notsupported;
3678
3679 switch (function) {
3680 case 0xb:
3681 /* change print job name, data gives the name */
3682 break;
3683 default:
3684 goto out;
3685 }
3686
3687 ZERO_STRUCT(handle);
3688
3689 status = rpc_pipe_open_interface(conn,
3690 &ndr_table_spoolss.syntax_id,
3691 conn->session_info,
3692 &conn->sconn->client_id,
3693 conn->sconn->msg_ctx,
3694 &cli);
3695 if (!NT_STATUS_IS_OK(status)) {
3696 DEBUG(0,("api_PrintJobInfo: could not connect to spoolss: %s\n",
3697 nt_errstr(status)));
3698 errcode = W_ERROR_V(ntstatus_to_werror(status));
3699 goto out;
3700 }
3701 b = cli->binding_handle;
3702
3703 ZERO_STRUCT(devmode_ctr);
3704
3705 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
3706 sharename,
3707 "RAW",
3708 devmode_ctr,
3709 PRINTER_ACCESS_USE,
3710 &handle,
3711 &werr);
3712 if (!NT_STATUS_IS_OK(status)) {
3713 errcode = W_ERROR_V(ntstatus_to_werror(status));
3714 goto out;
3715 }
3716 if (!W_ERROR_IS_OK(werr)) {
3717 errcode = W_ERROR_V(werr);
3718 goto out;
3719 }
3720
3721 werr = rpccli_spoolss_getjob(cli, mem_ctx,
3722 &handle,
3723 jobid,
3724 1, /* level */
3725 0, /* offered */
3726 &info);
3727 if (!W_ERROR_IS_OK(werr)) {
3728 errcode = W_ERROR_V(werr);
3729 goto out;
3730 }
3731
3732 ZERO_STRUCT(ctr);
3733
3734 info1.job_id = info.info1.job_id;
3735 info1.printer_name = info.info1.printer_name;
3736 info1.user_name = info.info1.user_name;
3737 info1.document_name = data;
3738 info1.data_type = info.info1.data_type;
3739 info1.text_status = info.info1.text_status;
3740 info1.status = info.info1.status;
3741 info1.priority = info.info1.priority;
3742 info1.position = info.info1.position;
3743 info1.total_pages = info.info1.total_pages;
3744 info1.pages_printed = info.info1.pages_printed;
3745 info1.submitted = info.info1.submitted;
3746
3747 ctr.level = 1;
3748 ctr.info.info1 = &info1;
3749
3750 status = dcerpc_spoolss_SetJob(b, mem_ctx,
3751 &handle,
3752 jobid,
3753 &ctr,
3754 0,
3755 &werr);
3756 if (!NT_STATUS_IS_OK(status)) {
3757 errcode = W_ERROR_V(ntstatus_to_werror(status));
3758 goto out;
3759 }
3760 if (!W_ERROR_IS_OK(werr)) {
3761 errcode = W_ERROR_V(werr);
3762 goto out;
3763 }
3764
3765 errcode = NERR_Success;
3766 out:
3767
3768 if (b && is_valid_policy_hnd(&handle)) {
3769 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
3770 }
3771
3772 SSVALS(*rparam,0,errcode);
3773 SSVAL(*rparam,2,0); /* converter word */
3774
3775 return(True);
3776}
3777
3778
3779/****************************************************************************
3780 Get info about the server.
3781****************************************************************************/
3782
3783static bool api_RNetServerGetInfo(struct smbd_server_connection *sconn,
3784 connection_struct *conn,uint16 vuid,
3785 char *param, int tpscnt,
3786 char *data, int tdscnt,
3787 int mdrcnt,int mprcnt,
3788 char **rdata,char **rparam,
3789 int *rdata_len,int *rparam_len)
3790{
3791 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3792 char *str2 = skip_string(param,tpscnt,str1);
3793 char *p = skip_string(param,tpscnt,str2);
3794 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
3795 char *p2;
3796 int struct_len;
3797
3798 NTSTATUS status;
3799 WERROR werr;
3800 TALLOC_CTX *mem_ctx = talloc_tos();
3801 struct rpc_pipe_client *cli = NULL;
3802 union srvsvc_NetSrvInfo info;
3803 int errcode;
3804 struct dcerpc_binding_handle *b;
3805
3806 if (!str1 || !str2 || !p) {
3807 return False;
3808 }
3809
3810 DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
3811
3812 /* check it's a supported varient */
3813 if (!prefix_ok(str1,"WrLh")) {
3814 return False;
3815 }
3816
3817 switch( uLevel ) {
3818 case 0:
3819 if (strcmp(str2,"B16") != 0) {
3820 return False;
3821 }
3822 struct_len = 16;
3823 break;
3824 case 1:
3825 if (strcmp(str2,"B16BBDz") != 0) {
3826 return False;
3827 }
3828 struct_len = 26;
3829 break;
3830 case 2:
3831 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")!= 0) {
3832 return False;
3833 }
3834 struct_len = 134;
3835 break;
3836 case 3:
3837 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz") != 0) {
3838 return False;
3839 }
3840 struct_len = 144;
3841 break;
3842 case 20:
3843 if (strcmp(str2,"DN") != 0) {
3844 return False;
3845 }
3846 struct_len = 6;
3847 break;
3848 case 50:
3849 if (strcmp(str2,"B16BBDzWWzzz") != 0) {
3850 return False;
3851 }
3852 struct_len = 42;
3853 break;
3854 default:
3855 return False;
3856 }
3857
3858 *rdata_len = mdrcnt;
3859 *rdata = smb_realloc_limit(*rdata,*rdata_len);
3860 if (!*rdata) {
3861 return False;
3862 }
3863
3864 p = *rdata;
3865 p2 = p + struct_len;
3866
3867 status = rpc_pipe_open_interface(mem_ctx, &ndr_table_srvsvc.syntax_id,
3868 conn->session_info,
3869 &conn->sconn->client_id,
3870 conn->sconn->msg_ctx,
3871 &cli);
3872 if (!NT_STATUS_IS_OK(status)) {
3873 DEBUG(0,("api_RNetServerGetInfo: could not connect to srvsvc: %s\n",
3874 nt_errstr(status)));
3875 errcode = W_ERROR_V(ntstatus_to_werror(status));
3876 goto out;
3877 }
3878
3879 b = cli->binding_handle;
3880
3881 status = dcerpc_srvsvc_NetSrvGetInfo(b, mem_ctx,
3882 NULL,
3883 101,
3884 &info,
3885 &werr);
3886 if (!NT_STATUS_IS_OK(status)) {
3887 errcode = W_ERROR_V(ntstatus_to_werror(status));
3888 goto out;
3889 }
3890 if (!W_ERROR_IS_OK(werr)) {
3891 errcode = W_ERROR_V(werr);
3892 goto out;
3893 }
3894
3895 if (info.info101 == NULL) {
3896 errcode = W_ERROR_V(WERR_INVALID_PARAM);
3897 goto out;
3898 }
3899
3900 if (uLevel != 20) {
3901 srvstr_push(NULL, 0, p, info.info101->server_name, 16,
3902 STR_ASCII|STR_UPPER|STR_TERMINATE);
3903 }
3904 p += 16;
3905 if (uLevel > 0) {
3906 SCVAL(p,0,info.info101->version_major);
3907 SCVAL(p,1,info.info101->version_minor);
3908 SIVAL(p,2,info.info101->server_type);
3909
3910 if (mdrcnt == struct_len) {
3911 SIVAL(p,6,0);
3912 } else {
3913 SIVAL(p,6,PTR_DIFF(p2,*rdata));
3914 if (mdrcnt - struct_len <= 0) {
3915 return false;
3916 }
3917 push_ascii(p2,
3918 info.info101->comment,
3919 MIN(mdrcnt - struct_len,
3920 MAX_SERVER_STRING_LENGTH),
3921 STR_TERMINATE);
3922 p2 = skip_string(*rdata,*rdata_len,p2);
3923 if (!p2) {
3924 return False;
3925 }
3926 }
3927 }
3928
3929 if (uLevel > 1) {
3930 return False; /* not yet implemented */
3931 }
3932
3933 errcode = NERR_Success;
3934
3935 out:
3936
3937 *rdata_len = PTR_DIFF(p2,*rdata);
3938
3939 *rparam_len = 6;
3940 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3941 if (!*rparam) {
3942 return False;
3943 }
3944 SSVAL(*rparam,0,errcode);
3945 SSVAL(*rparam,2,0); /* converter word */
3946 SSVAL(*rparam,4,*rdata_len);
3947
3948 return True;
3949}
3950
3951/****************************************************************************
3952 Get info about the server.
3953****************************************************************************/
3954
3955static bool api_NetWkstaGetInfo(struct smbd_server_connection *sconn,
3956 connection_struct *conn,uint16 vuid,
3957 char *param, int tpscnt,
3958 char *data, int tdscnt,
3959 int mdrcnt,int mprcnt,
3960 char **rdata,char **rparam,
3961 int *rdata_len,int *rparam_len)
3962{
3963 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3964 char *str2 = skip_string(param,tpscnt,str1);
3965 char *p = skip_string(param,tpscnt,str2);
3966 char *p2;
3967 char *endp;
3968 int level = get_safe_SVAL(param,tpscnt,p,0,-1);
3969
3970 if (!str1 || !str2 || !p) {
3971 return False;
3972 }
3973
3974 DEBUG(4,("NetWkstaGetInfo level %d\n",level));
3975
3976 *rparam_len = 6;
3977 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3978 if (!*rparam) {
3979 return False;
3980 }
3981
3982 /* check it's a supported varient */
3983 if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz"))) {
3984 return False;
3985 }
3986
3987 *rdata_len = mdrcnt + 1024;
3988 *rdata = smb_realloc_limit(*rdata,*rdata_len);
3989 if (!*rdata) {
3990 return False;
3991 }
3992
3993 SSVAL(*rparam,0,NERR_Success);
3994 SSVAL(*rparam,2,0); /* converter word */
3995
3996 p = *rdata;
3997 endp = *rdata + *rdata_len;
3998
3999 p2 = get_safe_ptr(*rdata,*rdata_len,p,22);
4000 if (!p2) {
4001 return False;
4002 }
4003
4004 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */
4005 strlcpy(p2,get_local_machine_name(),PTR_DIFF(endp,p2));
4006 strupper_m(p2);
4007 p2 = skip_string(*rdata,*rdata_len,p2);
4008 if (!p2) {
4009 return False;
4010 }
4011 p += 4;
4012
4013 SIVAL(p,0,PTR_DIFF(p2,*rdata));
4014 strlcpy(p2,conn->session_info->sanitized_username,PTR_DIFF(endp,p2));
4015 p2 = skip_string(*rdata,*rdata_len,p2);
4016 if (!p2) {
4017 return False;
4018 }
4019 p += 4;
4020
4021 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
4022 strlcpy(p2,lp_workgroup(),PTR_DIFF(endp,p2));
4023 strupper_m(p2);
4024 p2 = skip_string(*rdata,*rdata_len,p2);
4025 if (!p2) {
4026 return False;
4027 }
4028 p += 4;
4029
4030 SCVAL(p,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
4031 SCVAL(p,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
4032 p += 2;
4033
4034 SIVAL(p,0,PTR_DIFF(p2,*rdata));
4035 strlcpy(p2,lp_workgroup(),PTR_DIFF(endp,p2)); /* don't know. login domain?? */
4036 p2 = skip_string(*rdata,*rdata_len,p2);
4037 if (!p2) {
4038 return False;
4039 }
4040 p += 4;
4041
4042 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */
4043 strlcpy(p2,"",PTR_DIFF(endp,p2));
4044 p2 = skip_string(*rdata,*rdata_len,p2);
4045 if (!p2) {
4046 return False;
4047 }
4048 p += 4;
4049
4050 *rdata_len = PTR_DIFF(p2,*rdata);
4051
4052 SSVAL(*rparam,4,*rdata_len);
4053
4054 return True;
4055}
4056
4057/****************************************************************************
4058 get info about a user
4059
4060 struct user_info_11 {
4061 char usri11_name[21]; 0-20
4062 char usri11_pad; 21
4063 char *usri11_comment; 22-25
4064 char *usri11_usr_comment; 26-29
4065 unsigned short usri11_priv; 30-31
4066 unsigned long usri11_auth_flags; 32-35
4067 long usri11_password_age; 36-39
4068 char *usri11_homedir; 40-43
4069 char *usri11_parms; 44-47
4070 long usri11_last_logon; 48-51
4071 long usri11_last_logoff; 52-55
4072 unsigned short usri11_bad_pw_count; 56-57
4073 unsigned short usri11_num_logons; 58-59
4074 char *usri11_logon_server; 60-63
4075 unsigned short usri11_country_code; 64-65
4076 char *usri11_workstations; 66-69
4077 unsigned long usri11_max_storage; 70-73
4078 unsigned short usri11_units_per_week; 74-75
4079 unsigned char *usri11_logon_hours; 76-79
4080 unsigned short usri11_code_page; 80-81
4081 };
4082
4083where:
4084
4085 usri11_name specifies the user name for which information is retrieved
4086
4087 usri11_pad aligns the next data structure element to a word boundary
4088
4089 usri11_comment is a null terminated ASCII comment
4090
4091 usri11_user_comment is a null terminated ASCII comment about the user
4092
4093 usri11_priv specifies the level of the privilege assigned to the user.
4094 The possible values are:
4095
4096Name Value Description
4097USER_PRIV_GUEST 0 Guest privilege
4098USER_PRIV_USER 1 User privilege
4099USER_PRV_ADMIN 2 Administrator privilege
4100
4101 usri11_auth_flags specifies the account operator privileges. The
4102 possible values are:
4103
4104Name Value Description
4105AF_OP_PRINT 0 Print operator
4106
4107
4108Leach, Naik [Page 28]
4109
4110
4111
4112
4113INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
4114
4115
4116AF_OP_COMM 1 Communications operator
4117AF_OP_SERVER 2 Server operator
4118AF_OP_ACCOUNTS 3 Accounts operator
4119
4120
4121 usri11_password_age specifies how many seconds have elapsed since the
4122 password was last changed.
4123
4124 usri11_home_dir points to a null terminated ASCII string that contains
4125 the path name of the user's home directory.
4126
4127 usri11_parms points to a null terminated ASCII string that is set
4128 aside for use by applications.
4129
4130 usri11_last_logon specifies the time when the user last logged on.
4131 This value is stored as the number of seconds elapsed since
4132 00:00:00, January 1, 1970.
4133
4134 usri11_last_logoff specifies the time when the user last logged off.
4135 This value is stored as the number of seconds elapsed since
4136 00:00:00, January 1, 1970. A value of 0 means the last logoff
4137 time is unknown.
4138
4139 usri11_bad_pw_count specifies the number of incorrect passwords
4140 entered since the last successful logon.
4141
4142 usri11_log1_num_logons specifies the number of times this user has
4143 logged on. A value of -1 means the number of logons is unknown.
4144
4145 usri11_logon_server points to a null terminated ASCII string that
4146 contains the name of the server to which logon requests are sent.
4147 A null string indicates logon requests should be sent to the
4148 domain controller.
4149
4150 usri11_country_code specifies the country code for the user's language
4151 of choice.
4152
4153 usri11_workstations points to a null terminated ASCII string that
4154 contains the names of workstations the user may log on from.
4155 There may be up to 8 workstations, with the names separated by
4156 commas. A null strings indicates there are no restrictions.
4157
4158 usri11_max_storage specifies the maximum amount of disk space the user
4159 can occupy. A value of 0xffffffff indicates there are no
4160 restrictions.
4161
4162 usri11_units_per_week specifies the equal number of time units into
4163 which a week is divided. This value must be equal to 168.
4164
4165 usri11_logon_hours points to a 21 byte (168 bits) string that
4166 specifies the time during which the user can log on. Each bit
4167 represents one unique hour in a week. The first bit (bit 0, word
4168 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
4169
4170
4171
4172Leach, Naik [Page 29]
4173
4174
4175
4176
4177INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
4178
4179
4180 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
4181 are no restrictions.
4182
4183 usri11_code_page specifies the code page for the user's language of
4184 choice
4185
4186All of the pointers in this data structure need to be treated
4187specially. The pointer is a 32 bit pointer. The higher 16 bits need
4188to be ignored. The converter word returned in the parameters section
4189needs to be subtracted from the lower 16 bits to calculate an offset
4190into the return buffer where this ASCII string resides.
4191
4192There is no auxiliary data in the response.
4193
4194 ****************************************************************************/
4195
4196#define usri11_name 0
4197#define usri11_pad 21
4198#define usri11_comment 22
4199#define usri11_usr_comment 26
4200#define usri11_full_name 30
4201#define usri11_priv 34
4202#define usri11_auth_flags 36
4203#define usri11_password_age 40
4204#define usri11_homedir 44
4205#define usri11_parms 48
4206#define usri11_last_logon 52
4207#define usri11_last_logoff 56
4208#define usri11_bad_pw_count 60
4209#define usri11_num_logons 62
4210#define usri11_logon_server 64
4211#define usri11_country_code 68
4212#define usri11_workstations 70
4213#define usri11_max_storage 74
4214#define usri11_units_per_week 78
4215#define usri11_logon_hours 80
4216#define usri11_code_page 84
4217#define usri11_end 86
4218
4219static bool api_RNetUserGetInfo(struct smbd_server_connection *sconn,
4220 connection_struct *conn, uint16 vuid,
4221 char *param, int tpscnt,
4222 char *data, int tdscnt,
4223 int mdrcnt,int mprcnt,
4224 char **rdata,char **rparam,
4225 int *rdata_len,int *rparam_len)
4226{
4227 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4228 char *str2 = skip_string(param,tpscnt,str1);
4229 char *UserName = skip_string(param,tpscnt,str2);
4230 char *p = skip_string(param,tpscnt,UserName);
4231 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4232 char *p2;
4233 char *endp;
4234 const char *level_string;
4235
4236 TALLOC_CTX *mem_ctx = talloc_tos();
4237 NTSTATUS status, result;
4238 struct rpc_pipe_client *cli = NULL;
4239 struct policy_handle connect_handle, domain_handle, user_handle;
4240 struct lsa_String domain_name;
4241 struct dom_sid2 *domain_sid;
4242 struct lsa_String names;
4243 struct samr_Ids rids;
4244 struct samr_Ids types;
4245 int errcode = W_ERROR_V(WERR_USER_NOT_FOUND);
4246 uint32_t rid;
4247 union samr_UserInfo *info;
4248 struct dcerpc_binding_handle *b = NULL;
4249
4250 if (!str1 || !str2 || !UserName || !p) {
4251 return False;
4252 }
4253
4254 *rparam_len = 6;
4255 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4256 if (!*rparam) {
4257 return False;
4258 }
4259
4260 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel));
4261
4262 /* check it's a supported variant */
4263 if (strcmp(str1,"zWrLh") != 0) {
4264 return False;
4265 }
4266 switch( uLevel ) {
4267 case 0: level_string = "B21"; break;
4268 case 1: level_string = "B21BB16DWzzWz"; break;
4269 case 2: level_string = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
4270 case 10: level_string = "B21Bzzz"; break;
4271 case 11: level_string = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
4272 default: return False;
4273 }
4274
4275 if (strcmp(level_string,str2) != 0) {
4276 return False;
4277 }
4278
4279 *rdata_len = mdrcnt + 1024;
4280 *rdata = smb_realloc_limit(*rdata,*rdata_len);
4281 if (!*rdata) {
4282 return False;
4283 }
4284
4285 p = *rdata;
4286 endp = *rdata + *rdata_len;
4287 p2 = get_safe_ptr(*rdata,*rdata_len,p,usri11_end);
4288 if (!p2) {
4289 return False;
4290 }
4291
4292 ZERO_STRUCT(connect_handle);
4293 ZERO_STRUCT(domain_handle);
4294 ZERO_STRUCT(user_handle);
4295
4296 status = rpc_pipe_open_interface(mem_ctx, &ndr_table_samr.syntax_id,
4297 conn->session_info,
4298 &conn->sconn->client_id,
4299 conn->sconn->msg_ctx,
4300 &cli);
4301 if (!NT_STATUS_IS_OK(status)) {
4302 DEBUG(0,("api_RNetUserGetInfo: could not connect to samr: %s\n",
4303 nt_errstr(status)));
4304 errcode = W_ERROR_V(ntstatus_to_werror(status));
4305 goto out;
4306 }
4307
4308 b = cli->binding_handle;
4309
4310 status = dcerpc_samr_Connect2(b, mem_ctx,
4311 global_myname(),
4312 SAMR_ACCESS_CONNECT_TO_SERVER |
4313 SAMR_ACCESS_ENUM_DOMAINS |
4314 SAMR_ACCESS_LOOKUP_DOMAIN,
4315 &connect_handle,
4316 &result);
4317 if (!NT_STATUS_IS_OK(status)) {
4318 errcode = W_ERROR_V(ntstatus_to_werror(status));
4319 goto out;
4320 }
4321 if (!NT_STATUS_IS_OK(result)) {
4322 errcode = W_ERROR_V(ntstatus_to_werror(result));
4323 goto out;
4324 }
4325
4326 init_lsa_String(&domain_name, get_global_sam_name());
4327
4328 status = dcerpc_samr_LookupDomain(b, mem_ctx,
4329 &connect_handle,
4330 &domain_name,
4331 &domain_sid,
4332 &result);
4333 if (!NT_STATUS_IS_OK(status)) {
4334 errcode = W_ERROR_V(ntstatus_to_werror(status));
4335 goto out;
4336 }
4337 if (!NT_STATUS_IS_OK(result)) {
4338 errcode = W_ERROR_V(ntstatus_to_werror(result));
4339 goto out;
4340 }
4341
4342 status = dcerpc_samr_OpenDomain(b, mem_ctx,
4343 &connect_handle,
4344 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
4345 domain_sid,
4346 &domain_handle,
4347 &result);
4348 if (!NT_STATUS_IS_OK(status)) {
4349 errcode = W_ERROR_V(ntstatus_to_werror(status));
4350 goto out;
4351 }
4352 if (!NT_STATUS_IS_OK(result)) {
4353 errcode = W_ERROR_V(ntstatus_to_werror(result));
4354 goto out;
4355 }
4356
4357 init_lsa_String(&names, UserName);
4358
4359 status = dcerpc_samr_LookupNames(b, mem_ctx,
4360 &domain_handle,
4361 1,
4362 &names,
4363 &rids,
4364 &types,
4365 &result);
4366 if (!NT_STATUS_IS_OK(status)) {
4367 errcode = W_ERROR_V(ntstatus_to_werror(status));
4368 goto out;
4369 }
4370 if (!NT_STATUS_IS_OK(result)) {
4371 errcode = W_ERROR_V(ntstatus_to_werror(result));
4372 goto out;
4373 }
4374
4375 if (rids.count != 1) {
4376 errcode = W_ERROR_V(WERR_NO_SUCH_USER);
4377 goto out;
4378 }
4379 if (rids.count != types.count) {
4380 errcode = W_ERROR_V(WERR_INVALID_PARAM);
4381 goto out;
4382 }
4383 if (types.ids[0] != SID_NAME_USER) {
4384 errcode = W_ERROR_V(WERR_INVALID_PARAM);
4385 goto out;
4386 }
4387
4388 rid = rids.ids[0];
4389
4390 status = dcerpc_samr_OpenUser(b, mem_ctx,
4391 &domain_handle,
4392 SAMR_USER_ACCESS_GET_LOCALE |
4393 SAMR_USER_ACCESS_GET_LOGONINFO |
4394 SAMR_USER_ACCESS_GET_ATTRIBUTES |
4395 SAMR_USER_ACCESS_GET_GROUPS |
4396 SAMR_USER_ACCESS_GET_GROUP_MEMBERSHIP |
4397 SEC_STD_READ_CONTROL,
4398 rid,
4399 &user_handle,
4400 &result);
4401 if (!NT_STATUS_IS_OK(status)) {
4402 errcode = W_ERROR_V(ntstatus_to_werror(status));
4403 goto out;
4404 }
4405 if (!NT_STATUS_IS_OK(result)) {
4406 errcode = W_ERROR_V(ntstatus_to_werror(result));
4407 goto out;
4408 }
4409
4410 status = dcerpc_samr_QueryUserInfo2(b, mem_ctx,
4411 &user_handle,
4412 UserAllInformation,
4413 &info,
4414 &result);
4415 if (!NT_STATUS_IS_OK(status)) {
4416 errcode = W_ERROR_V(ntstatus_to_werror(status));
4417 goto out;
4418 }
4419 if (!NT_STATUS_IS_OK(result)) {
4420 errcode = W_ERROR_V(ntstatus_to_werror(result));
4421 goto out;
4422 }
4423
4424 memset(p,0,21);
4425 fstrcpy(p+usri11_name,UserName); /* 21 bytes - user name */
4426
4427 if (uLevel > 0) {
4428 SCVAL(p,usri11_pad,0); /* padding - 1 byte */
4429 *p2 = 0;
4430 }
4431
4432 if (uLevel >= 10) {
4433 SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */
4434 strlcpy(p2,"Comment",PTR_DIFF(endp,p2));
4435 p2 = skip_string(*rdata,*rdata_len,p2);
4436 if (!p2) {
4437 return False;
4438 }
4439
4440 SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */
4441 strlcpy(p2,"UserComment",PTR_DIFF(endp,p2));
4442 p2 = skip_string(*rdata,*rdata_len,p2);
4443 if (!p2) {
4444 return False;
4445 }
4446
4447 /* EEK! the cifsrap.txt doesn't have this in!!!! */
4448 SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */
4449 strlcpy(p2,info->info21.full_name.string,PTR_DIFF(endp,p2));
4450 p2 = skip_string(*rdata,*rdata_len,p2);
4451 if (!p2) {
4452 return False;
4453 }
4454 }
4455
4456 if (uLevel == 11) {
4457 const char *homedir = info->info21.home_directory.string;
4458 /* modelled after NTAS 3.51 reply */
4459 SSVAL(p,usri11_priv,
4460 (get_current_uid(conn) == sec_initial_uid())?
4461 USER_PRIV_ADMIN:USER_PRIV_USER);
4462 SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */
4463 SIVALS(p,usri11_password_age,-1); /* password age */
4464 SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */
4465 strlcpy(p2, homedir, PTR_DIFF(endp,p2));
4466 p2 = skip_string(*rdata,*rdata_len,p2);
4467 if (!p2) {
4468 return False;
4469 }
4470 SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */
4471 strlcpy(p2,"",PTR_DIFF(endp,p2));
4472 p2 = skip_string(*rdata,*rdata_len,p2);
4473 if (!p2) {
4474 return False;
4475 }
4476 SIVAL(p,usri11_last_logon,0); /* last logon */
4477 SIVAL(p,usri11_last_logoff,0); /* last logoff */
4478 SSVALS(p,usri11_bad_pw_count,-1); /* bad pw counts */
4479 SSVALS(p,usri11_num_logons,-1); /* num logons */
4480 SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */
4481 strlcpy(p2,"\\\\*",PTR_DIFF(endp,p2));
4482 p2 = skip_string(*rdata,*rdata_len,p2);
4483 if (!p2) {
4484 return False;
4485 }
4486 SSVAL(p,usri11_country_code,0); /* country code */
4487
4488 SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */
4489 strlcpy(p2,"",PTR_DIFF(endp,p2));
4490 p2 = skip_string(*rdata,*rdata_len,p2);
4491 if (!p2) {
4492 return False;
4493 }
4494
4495 SIVALS(p,usri11_max_storage,-1); /* max storage */
4496 SSVAL(p,usri11_units_per_week,168); /* units per week */
4497 SIVAL(p,usri11_logon_hours,PTR_DIFF(p2,p)); /* logon hours */
4498
4499 /* a simple way to get logon hours at all times. */
4500 memset(p2,0xff,21);
4501 SCVAL(p2,21,0); /* fix zero termination */
4502 p2 = skip_string(*rdata,*rdata_len,p2);
4503 if (!p2) {
4504 return False;
4505 }
4506
4507 SSVAL(p,usri11_code_page,0); /* code page */
4508 }
4509
4510 if (uLevel == 1 || uLevel == 2) {
4511 memset(p+22,' ',16); /* password */
4512 SIVALS(p,38,-1); /* password age */
4513 SSVAL(p,42,
4514 (get_current_uid(conn) == sec_initial_uid())?
4515 USER_PRIV_ADMIN:USER_PRIV_USER);
4516 SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
4517 strlcpy(p2, info->info21.home_directory.string,
4518 PTR_DIFF(endp,p2));
4519 p2 = skip_string(*rdata,*rdata_len,p2);
4520 if (!p2) {
4521 return False;
4522 }
4523 SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
4524 *p2++ = 0;
4525 SSVAL(p,52,0); /* flags */
4526 SIVAL(p,54,PTR_DIFF(p2,*rdata)); /* script_path */
4527 strlcpy(p2, info->info21.logon_script.string,
4528 PTR_DIFF(endp,p2));
4529 p2 = skip_string(*rdata,*rdata_len,p2);
4530 if (!p2) {
4531 return False;
4532 }
4533 if (uLevel == 2) {
4534 SIVAL(p,58,0); /* auth_flags */
4535 SIVAL(p,62,PTR_DIFF(p2,*rdata)); /* full_name */
4536 strlcpy(p2,info->info21.full_name.string,PTR_DIFF(endp,p2));
4537 p2 = skip_string(*rdata,*rdata_len,p2);
4538 if (!p2) {
4539 return False;
4540 }
4541 SIVAL(p,66,0); /* urs_comment */
4542 SIVAL(p,70,PTR_DIFF(p2,*rdata)); /* parms */
4543 strlcpy(p2,"",PTR_DIFF(endp,p2));
4544 p2 = skip_string(*rdata,*rdata_len,p2);
4545 if (!p2) {
4546 return False;
4547 }
4548 SIVAL(p,74,0); /* workstations */
4549 SIVAL(p,78,0); /* last_logon */
4550 SIVAL(p,82,0); /* last_logoff */
4551 SIVALS(p,86,-1); /* acct_expires */
4552 SIVALS(p,90,-1); /* max_storage */
4553 SSVAL(p,94,168); /* units_per_week */
4554 SIVAL(p,96,PTR_DIFF(p2,*rdata)); /* logon_hours */
4555 memset(p2,-1,21);
4556 p2 += 21;
4557 SSVALS(p,100,-1); /* bad_pw_count */
4558 SSVALS(p,102,-1); /* num_logons */
4559 SIVAL(p,104,PTR_DIFF(p2,*rdata)); /* logon_server */
4560 {
4561 TALLOC_CTX *ctx = talloc_tos();
4562 int space_rem = *rdata_len - (p2 - *rdata);
4563 char *tmp;
4564
4565 if (space_rem <= 0) {
4566 return false;
4567 }
4568 tmp = talloc_strdup(ctx, "\\\\%L");
4569 if (!tmp) {
4570 return false;
4571 }
4572 tmp = talloc_sub_basic(ctx,
4573 "",
4574 "",
4575 tmp);
4576 if (!tmp) {
4577 return false;
4578 }
4579
4580 push_ascii(p2,
4581 tmp,
4582 space_rem,
4583 STR_TERMINATE);
4584 }
4585 p2 = skip_string(*rdata,*rdata_len,p2);
4586 if (!p2) {
4587 return False;
4588 }
4589 SSVAL(p,108,49); /* country_code */
4590 SSVAL(p,110,860); /* code page */
4591 }
4592 }
4593
4594 errcode = NERR_Success;
4595
4596 out:
4597 *rdata_len = PTR_DIFF(p2,*rdata);
4598
4599 if (b && is_valid_policy_hnd(&user_handle)) {
4600 dcerpc_samr_Close(b, mem_ctx, &user_handle, &result);
4601 }
4602 if (b && is_valid_policy_hnd(&domain_handle)) {
4603 dcerpc_samr_Close(b, mem_ctx, &domain_handle, &result);
4604 }
4605 if (b && is_valid_policy_hnd(&connect_handle)) {
4606 dcerpc_samr_Close(b, mem_ctx, &connect_handle, &result);
4607 }
4608
4609 SSVAL(*rparam,0,errcode);
4610 SSVAL(*rparam,2,0); /* converter word */
4611 SSVAL(*rparam,4,*rdata_len); /* is this right?? */
4612
4613 return(True);
4614}
4615
4616static bool api_WWkstaUserLogon(struct smbd_server_connection *sconn,
4617 connection_struct *conn,uint16 vuid,
4618 char *param, int tpscnt,
4619 char *data, int tdscnt,
4620 int mdrcnt,int mprcnt,
4621 char **rdata,char **rparam,
4622 int *rdata_len,int *rparam_len)
4623{
4624 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4625 char *str2 = skip_string(param,tpscnt,str1);
4626 char *p = skip_string(param,tpscnt,str2);
4627 int uLevel;
4628 struct pack_desc desc;
4629 char* name;
4630 /* With share level security vuid will always be zero.
4631 Don't depend on vuser being non-null !!. JRA */
4632 user_struct *vuser = get_valid_user_struct(sconn, vuid);
4633
4634 if (!str1 || !str2 || !p) {
4635 return False;
4636 }
4637
4638 if(vuser != NULL) {
4639 DEBUG(3,(" Username of UID %d is %s\n",
4640 (int)vuser->session_info->utok.uid,
4641 vuser->session_info->unix_name));
4642 }
4643
4644 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4645 name = get_safe_str_ptr(param,tpscnt,p,2);
4646 if (!name) {
4647 return False;
4648 }
4649
4650 memset((char *)&desc,'\0',sizeof(desc));
4651
4652 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
4653
4654 /* check it's a supported varient */
4655 if (strcmp(str1,"OOWb54WrLh") != 0) {
4656 return False;
4657 }
4658 if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) {
4659 return False;
4660 }
4661 if (mdrcnt > 0) {
4662 *rdata = smb_realloc_limit(*rdata,mdrcnt);
4663 if (!*rdata) {
4664 return False;
4665 }
4666 }
4667
4668 desc.base = *rdata;
4669 desc.buflen = mdrcnt;
4670 desc.subformat = NULL;
4671 desc.format = str2;
4672
4673 if (init_package(&desc,1,0)) {
4674 PACKI(&desc,"W",0); /* code */
4675 PACKS(&desc,"B21",name); /* eff. name */
4676 PACKS(&desc,"B",""); /* pad */
4677 PACKI(&desc,"W",
4678 (get_current_uid(conn) == sec_initial_uid())?
4679 USER_PRIV_ADMIN:USER_PRIV_USER);
4680 PACKI(&desc,"D",0); /* auth flags XXX */
4681 PACKI(&desc,"W",0); /* num logons */
4682 PACKI(&desc,"W",0); /* bad pw count */
4683 PACKI(&desc,"D",0); /* last logon */
4684 PACKI(&desc,"D",-1); /* last logoff */
4685 PACKI(&desc,"D",-1); /* logoff time */
4686 PACKI(&desc,"D",-1); /* kickoff time */
4687 PACKI(&desc,"D",0); /* password age */
4688 PACKI(&desc,"D",0); /* password can change */
4689 PACKI(&desc,"D",-1); /* password must change */
4690
4691 {
4692 fstring mypath;
4693 fstrcpy(mypath,"\\\\");
4694 fstrcat(mypath,get_local_machine_name());
4695 strupper_m(mypath);
4696 PACKS(&desc,"z",mypath); /* computer */
4697 }
4698
4699 PACKS(&desc,"z",lp_workgroup());/* domain */
4700 PACKS(&desc,"z", vuser ?
4701 vuser->session_info->info3->base.logon_script.string
4702 : ""); /* script path */
4703 PACKI(&desc,"D",0x00000000); /* reserved */
4704 }
4705
4706 *rdata_len = desc.usedlen;
4707 *rparam_len = 6;
4708 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4709 if (!*rparam) {
4710 return False;
4711 }
4712 SSVALS(*rparam,0,desc.errcode);
4713 SSVAL(*rparam,2,0);
4714 SSVAL(*rparam,4,desc.neededlen);
4715
4716 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
4717
4718 return True;
4719}
4720
4721/****************************************************************************
4722 api_WAccessGetUserPerms
4723****************************************************************************/
4724
4725static bool api_WAccessGetUserPerms(struct smbd_server_connection *sconn,
4726 connection_struct *conn,uint16 vuid,
4727 char *param, int tpscnt,
4728 char *data, int tdscnt,
4729 int mdrcnt,int mprcnt,
4730 char **rdata,char **rparam,
4731 int *rdata_len,int *rparam_len)
4732{
4733 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4734 char *str2 = skip_string(param,tpscnt,str1);
4735 char *user = skip_string(param,tpscnt,str2);
4736 char *resource = skip_string(param,tpscnt,user);
4737
4738 if (!str1 || !str2 || !user || !resource) {
4739 return False;
4740 }
4741
4742 if (skip_string(param,tpscnt,resource) == NULL) {
4743 return False;
4744 }
4745 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
4746
4747 /* check it's a supported varient */
4748 if (strcmp(str1,"zzh") != 0) {
4749 return False;
4750 }
4751 if (strcmp(str2,"") != 0) {
4752 return False;
4753 }
4754
4755 *rparam_len = 6;
4756 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4757 if (!*rparam) {
4758 return False;
4759 }
4760 SSVALS(*rparam,0,0); /* errorcode */
4761 SSVAL(*rparam,2,0); /* converter word */
4762 SSVAL(*rparam,4,0x7f); /* permission flags */
4763
4764 return True;
4765}
4766
4767/****************************************************************************
4768 api_WPrintJobEnumerate
4769 ****************************************************************************/
4770
4771static bool api_WPrintJobGetInfo(struct smbd_server_connection *sconn,
4772 connection_struct *conn, uint16 vuid,
4773 char *param, int tpscnt,
4774 char *data, int tdscnt,
4775 int mdrcnt,int mprcnt,
4776 char **rdata,char **rparam,
4777 int *rdata_len,int *rparam_len)
4778{
4779 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4780 char *str2 = skip_string(param,tpscnt,str1);
4781 char *p = skip_string(param,tpscnt,str2);
4782 int uLevel;
4783 fstring sharename;
4784 uint32 jobid;
4785 struct pack_desc desc;
4786 char *tmpdata=NULL;
4787
4788 TALLOC_CTX *mem_ctx = talloc_tos();
4789 WERROR werr;
4790 NTSTATUS status;
4791 struct rpc_pipe_client *cli = NULL;
4792 struct dcerpc_binding_handle *b = NULL;
4793 struct policy_handle handle;
4794 struct spoolss_DevmodeContainer devmode_ctr;
4795 union spoolss_JobInfo info;
4796
4797 if (!str1 || !str2 || !p) {
4798 return False;
4799 }
4800
4801 uLevel = get_safe_SVAL(param,tpscnt,p,2,-1);
4802
4803 memset((char *)&desc,'\0',sizeof(desc));
4804 memset((char *)&status,'\0',sizeof(status));
4805
4806 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,SVAL(p,0)));
4807
4808 /* check it's a supported varient */
4809 if (strcmp(str1,"WWrLh") != 0) {
4810 return False;
4811 }
4812 if (!check_printjob_info(&desc,uLevel,str2)) {
4813 return False;
4814 }
4815
4816 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid)) {
4817 return False;
4818 }
4819
4820 ZERO_STRUCT(handle);
4821
4822 status = rpc_pipe_open_interface(conn,
4823 &ndr_table_spoolss.syntax_id,
4824 conn->session_info,
4825 &conn->sconn->client_id,
4826 conn->sconn->msg_ctx,
4827 &cli);
4828 if (!NT_STATUS_IS_OK(status)) {
4829 DEBUG(0,("api_WPrintJobGetInfo: could not connect to spoolss: %s\n",
4830 nt_errstr(status)));
4831 desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
4832 goto out;
4833 }
4834 b = cli->binding_handle;
4835
4836 ZERO_STRUCT(devmode_ctr);
4837
4838 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
4839 sharename,
4840 "RAW",
4841 devmode_ctr,
4842 PRINTER_ACCESS_USE,
4843 &handle,
4844 &werr);
4845 if (!NT_STATUS_IS_OK(status)) {
4846 desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
4847 goto out;
4848 }
4849 if (!W_ERROR_IS_OK(werr)) {
4850 desc.errcode = W_ERROR_V(werr);
4851 goto out;
4852 }
4853
4854 werr = rpccli_spoolss_getjob(cli, mem_ctx,
4855 &handle,
4856 jobid,
4857 2, /* level */
4858 0, /* offered */
4859 &info);
4860 if (!W_ERROR_IS_OK(werr)) {
4861 desc.errcode = W_ERROR_V(werr);
4862 goto out;
4863 }
4864
4865 if (mdrcnt > 0) {
4866 *rdata = smb_realloc_limit(*rdata,mdrcnt);
4867 if (!*rdata) {
4868 return False;
4869 }
4870 desc.base = *rdata;
4871 desc.buflen = mdrcnt;
4872 } else {
4873 /*
4874 * Don't return data but need to get correct length
4875 * init_package will return wrong size if buflen=0
4876 */
4877 desc.buflen = getlen(desc.format);
4878 desc.base = tmpdata = (char *)SMB_MALLOC( desc.buflen );
4879 }
4880
4881 if (init_package(&desc,1,0)) {
4882 fill_spoolss_printjob_info(uLevel, &desc, &info.info2, info.info2.position);
4883 *rdata_len = desc.usedlen;
4884 } else {
4885 desc.errcode = NERR_JobNotFound;
4886 *rdata_len = 0;
4887 }
4888 out:
4889 if (b && is_valid_policy_hnd(&handle)) {
4890 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
4891 }
4892
4893 *rparam_len = 6;
4894 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4895 if (!*rparam) {
4896 return False;
4897 }
4898 SSVALS(*rparam,0,desc.errcode);
4899 SSVAL(*rparam,2,0);
4900 SSVAL(*rparam,4,desc.neededlen);
4901
4902 SAFE_FREE(tmpdata);
4903
4904 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
4905
4906 return True;
4907}
4908
4909static bool api_WPrintJobEnumerate(struct smbd_server_connection *sconn,
4910 connection_struct *conn, uint16 vuid,
4911 char *param, int tpscnt,
4912 char *data, int tdscnt,
4913 int mdrcnt,int mprcnt,
4914 char **rdata,char **rparam,
4915 int *rdata_len,int *rparam_len)
4916{
4917 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4918 char *str2 = skip_string(param,tpscnt,str1);
4919 char *p = skip_string(param,tpscnt,str2);
4920 char *name = p;
4921 int uLevel;
4922 int i, succnt=0;
4923 struct pack_desc desc;
4924
4925 TALLOC_CTX *mem_ctx = talloc_tos();
4926 WERROR werr;
4927 NTSTATUS status;
4928 struct rpc_pipe_client *cli = NULL;
4929 struct dcerpc_binding_handle *b = NULL;
4930 struct policy_handle handle;
4931 struct spoolss_DevmodeContainer devmode_ctr;
4932 uint32_t count = 0;
4933 union spoolss_JobInfo *info;
4934
4935 if (!str1 || !str2 || !p) {
4936 return False;
4937 }
4938
4939 memset((char *)&desc,'\0',sizeof(desc));
4940
4941 p = skip_string(param,tpscnt,p);
4942 if (!p) {
4943 return False;
4944 }
4945 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4946
4947 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
4948
4949 /* check it's a supported variant */
4950 if (strcmp(str1,"zWrLeh") != 0) {
4951 return False;
4952 }
4953
4954 if (uLevel > 2) {
4955 return False; /* defined only for uLevel 0,1,2 */
4956 }
4957
4958 if (!check_printjob_info(&desc,uLevel,str2)) {
4959 return False;
4960 }
4961
4962 ZERO_STRUCT(handle);
4963
4964 status = rpc_pipe_open_interface(conn,
4965 &ndr_table_spoolss.syntax_id,
4966 conn->session_info,
4967 &conn->sconn->client_id,
4968 conn->sconn->msg_ctx,
4969 &cli);
4970 if (!NT_STATUS_IS_OK(status)) {
4971 DEBUG(0,("api_WPrintJobEnumerate: could not connect to spoolss: %s\n",
4972 nt_errstr(status)));
4973 desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
4974 goto out;
4975 }
4976 b = cli->binding_handle;
4977
4978 ZERO_STRUCT(devmode_ctr);
4979
4980 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
4981 name,
4982 NULL,
4983 devmode_ctr,
4984 PRINTER_ACCESS_USE,
4985 &handle,
4986 &werr);
4987 if (!NT_STATUS_IS_OK(status)) {
4988 desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
4989 goto out;
4990 }
4991 if (!W_ERROR_IS_OK(werr)) {
4992 desc.errcode = W_ERROR_V(werr);
4993 goto out;
4994 }
4995
4996 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
4997 &handle,
4998 0, /* firstjob */
4999 0xff, /* numjobs */
5000 2, /* level */
5001 0, /* offered */
5002 &count,
5003 &info);
5004 if (!W_ERROR_IS_OK(werr)) {
5005 desc.errcode = W_ERROR_V(werr);
5006 goto out;
5007 }
5008
5009 if (mdrcnt > 0) {
5010 *rdata = smb_realloc_limit(*rdata,mdrcnt);
5011 if (!*rdata) {
5012 return False;
5013 }
5014 }
5015 desc.base = *rdata;
5016 desc.buflen = mdrcnt;
5017
5018 if (init_package(&desc,count,0)) {
5019 succnt = 0;
5020 for (i = 0; i < count; i++) {
5021 fill_spoolss_printjob_info(uLevel, &desc, &info[i].info2, i);
5022 if (desc.errcode == NERR_Success) {
5023 succnt = i+1;
5024 }
5025 }
5026 }
5027 out:
5028 if (b && is_valid_policy_hnd(&handle)) {
5029 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
5030 }
5031
5032 *rdata_len = desc.usedlen;
5033
5034 *rparam_len = 8;
5035 *rparam = smb_realloc_limit(*rparam,*rparam_len);
5036 if (!*rparam) {
5037 return False;
5038 }
5039 SSVALS(*rparam,0,desc.errcode);
5040 SSVAL(*rparam,2,0);
5041 SSVAL(*rparam,4,succnt);
5042 SSVAL(*rparam,6,count);
5043
5044 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
5045
5046 return True;
5047}
5048
5049static int check_printdest_info(struct pack_desc* desc,
5050 int uLevel, char* id)
5051{
5052 desc->subformat = NULL;
5053 switch( uLevel ) {
5054 case 0:
5055 desc->format = "B9";
5056 break;
5057 case 1:
5058 desc->format = "B9B21WWzW";
5059 break;
5060 case 2:
5061 desc->format = "z";
5062 break;
5063 case 3:
5064 desc->format = "zzzWWzzzWW";
5065 break;
5066 default:
5067 DEBUG(0,("check_printdest_info: invalid level %d\n",
5068 uLevel));
5069 return False;
5070 }
5071 if (id == NULL || strcmp(desc->format,id) != 0) {
5072 DEBUG(0,("check_printdest_info: invalid string %s\n",
5073 id ? id : "<NULL>" ));
5074 return False;
5075 }
5076 return True;
5077}
5078
5079static void fill_printdest_info(struct spoolss_PrinterInfo2 *info2, int uLevel,
5080 struct pack_desc* desc)
5081{
5082 char buf[100];
5083
5084 strncpy(buf, info2->printername, sizeof(buf)-1);
5085 buf[sizeof(buf)-1] = 0;
5086 strupper_m(buf);
5087
5088 if (uLevel <= 1) {
5089 PACKS(desc,"B9",buf); /* szName */
5090 if (uLevel == 1) {
5091 PACKS(desc,"B21",""); /* szUserName */
5092 PACKI(desc,"W",0); /* uJobId */
5093 PACKI(desc,"W",0); /* fsStatus */
5094 PACKS(desc,"z",""); /* pszStatus */
5095 PACKI(desc,"W",0); /* time */
5096 }
5097 }
5098
5099 if (uLevel == 2 || uLevel == 3) {
5100 PACKS(desc,"z",buf); /* pszPrinterName */
5101 if (uLevel == 3) {
5102 PACKS(desc,"z",""); /* pszUserName */
5103 PACKS(desc,"z",""); /* pszLogAddr */
5104 PACKI(desc,"W",0); /* uJobId */
5105 PACKI(desc,"W",0); /* fsStatus */
5106 PACKS(desc,"z",""); /* pszStatus */
5107 PACKS(desc,"z",""); /* pszComment */
5108 PACKS(desc,"z","NULL"); /* pszDrivers */
5109 PACKI(desc,"W",0); /* time */
5110 PACKI(desc,"W",0); /* pad1 */
5111 }
5112 }
5113}
5114
5115static bool api_WPrintDestGetInfo(struct smbd_server_connection *sconn,
5116 connection_struct *conn, uint16 vuid,
5117 char *param, int tpscnt,
5118 char *data, int tdscnt,
5119 int mdrcnt,int mprcnt,
5120 char **rdata,char **rparam,
5121 int *rdata_len,int *rparam_len)
5122{
5123 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
5124 char *str2 = skip_string(param,tpscnt,str1);
5125 char *p = skip_string(param,tpscnt,str2);
5126 char* PrinterName = p;
5127 int uLevel;
5128 struct pack_desc desc;
5129 char *tmpdata=NULL;
5130
5131 TALLOC_CTX *mem_ctx = talloc_tos();
5132 WERROR werr;
5133 NTSTATUS status;
5134 struct rpc_pipe_client *cli = NULL;
5135 struct dcerpc_binding_handle *b = NULL;
5136 struct policy_handle handle;
5137 struct spoolss_DevmodeContainer devmode_ctr;
5138 union spoolss_PrinterInfo info;
5139
5140 if (!str1 || !str2 || !p) {
5141 return False;
5142 }
5143
5144 memset((char *)&desc,'\0',sizeof(desc));
5145
5146 p = skip_string(param,tpscnt,p);
5147 if (!p) {
5148 return False;
5149 }
5150 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
5151
5152 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
5153
5154 /* check it's a supported varient */
5155 if (strcmp(str1,"zWrLh") != 0) {
5156 return False;
5157 }
5158 if (!check_printdest_info(&desc,uLevel,str2)) {
5159 return False;
5160 }
5161
5162 ZERO_STRUCT(handle);
5163
5164 status = rpc_pipe_open_interface(conn,
5165 &ndr_table_spoolss.syntax_id,
5166 conn->session_info,
5167 &conn->sconn->client_id,
5168 conn->sconn->msg_ctx,
5169 &cli);
5170 if (!NT_STATUS_IS_OK(status)) {
5171 DEBUG(0,("api_WPrintDestGetInfo: could not connect to spoolss: %s\n",
5172 nt_errstr(status)));
5173 desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
5174 goto out;
5175 }
5176 b = cli->binding_handle;
5177
5178 ZERO_STRUCT(devmode_ctr);
5179
5180 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
5181 PrinterName,
5182 NULL,
5183 devmode_ctr,
5184 PRINTER_ACCESS_USE,
5185 &handle,
5186 &werr);
5187 if (!NT_STATUS_IS_OK(status)) {
5188 *rdata_len = 0;
5189 desc.errcode = NERR_DestNotFound;
5190 desc.neededlen = 0;
5191 goto out;
5192 }
5193 if (!W_ERROR_IS_OK(werr)) {
5194 *rdata_len = 0;
5195 desc.errcode = NERR_DestNotFound;
5196 desc.neededlen = 0;
5197 goto out;
5198 }
5199
5200 werr = rpccli_spoolss_getprinter(cli, mem_ctx,
5201 &handle,
5202 2,
5203 0,
5204 &info);
5205 if (!W_ERROR_IS_OK(werr)) {
5206 *rdata_len = 0;
5207 desc.errcode = NERR_DestNotFound;
5208 desc.neededlen = 0;
5209 goto out;
5210 }
5211
5212 if (mdrcnt > 0) {
5213 *rdata = smb_realloc_limit(*rdata,mdrcnt);
5214 if (!*rdata) {
5215 return False;
5216 }
5217 desc.base = *rdata;
5218 desc.buflen = mdrcnt;
5219 } else {
5220 /*
5221 * Don't return data but need to get correct length
5222 * init_package will return wrong size if buflen=0
5223 */
5224 desc.buflen = getlen(desc.format);
5225 desc.base = tmpdata = (char *)SMB_MALLOC( desc.buflen );
5226 }
5227 if (init_package(&desc,1,0)) {
5228 fill_printdest_info(&info.info2, uLevel,&desc);
5229 }
5230
5231 out:
5232 if (b && is_valid_policy_hnd(&handle)) {
5233 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
5234 }
5235
5236 *rdata_len = desc.usedlen;
5237
5238 *rparam_len = 6;
5239 *rparam = smb_realloc_limit(*rparam,*rparam_len);
5240 if (!*rparam) {
5241 return False;
5242 }
5243 SSVALS(*rparam,0,desc.errcode);
5244 SSVAL(*rparam,2,0);
5245 SSVAL(*rparam,4,desc.neededlen);
5246
5247 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
5248 SAFE_FREE(tmpdata);
5249
5250 return True;
5251}
5252
5253static bool api_WPrintDestEnum(struct smbd_server_connection *sconn,
5254 connection_struct *conn, uint16 vuid,
5255 char *param, int tpscnt,
5256 char *data, int tdscnt,
5257 int mdrcnt,int mprcnt,
5258 char **rdata,char **rparam,
5259 int *rdata_len,int *rparam_len)
5260{
5261 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
5262 char *str2 = skip_string(param,tpscnt,str1);
5263 char *p = skip_string(param,tpscnt,str2);
5264 int uLevel;
5265 int queuecnt;
5266 int i, n, succnt=0;
5267 struct pack_desc desc;
5268
5269 TALLOC_CTX *mem_ctx = talloc_tos();
5270 WERROR werr;
5271 NTSTATUS status;
5272 struct rpc_pipe_client *cli = NULL;
5273 union spoolss_PrinterInfo *info;
5274 uint32_t count;
5275
5276 if (!str1 || !str2 || !p) {
5277 return False;
5278 }
5279
5280 memset((char *)&desc,'\0',sizeof(desc));
5281
5282 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
5283
5284 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
5285
5286 /* check it's a supported varient */
5287 if (strcmp(str1,"WrLeh") != 0) {
5288 return False;
5289 }
5290 if (!check_printdest_info(&desc,uLevel,str2)) {
5291 return False;
5292 }
5293
5294 queuecnt = 0;
5295
5296 status = rpc_pipe_open_interface(conn,
5297 &ndr_table_spoolss.syntax_id,
5298 conn->session_info,
5299 &conn->sconn->client_id,
5300 conn->sconn->msg_ctx,
5301 &cli);
5302 if (!NT_STATUS_IS_OK(status)) {
5303 DEBUG(0,("api_WPrintDestEnum: could not connect to spoolss: %s\n",
5304 nt_errstr(status)));
5305 desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
5306 goto out;
5307 }
5308
5309 werr = rpccli_spoolss_enumprinters(cli, mem_ctx,
5310 PRINTER_ENUM_LOCAL,
5311 cli->srv_name_slash,
5312 2,
5313 0,
5314 &count,
5315 &info);
5316 if (!W_ERROR_IS_OK(werr)) {
5317 desc.errcode = W_ERROR_V(werr);
5318 *rdata_len = 0;
5319 desc.errcode = NERR_DestNotFound;
5320 desc.neededlen = 0;
5321 goto out;
5322 }
5323
5324 queuecnt = count;
5325
5326 if (mdrcnt > 0) {
5327 *rdata = smb_realloc_limit(*rdata,mdrcnt);
5328 if (!*rdata) {
5329 return False;
5330 }
5331 }
5332
5333 desc.base = *rdata;
5334 desc.buflen = mdrcnt;
5335 if (init_package(&desc,queuecnt,0)) {
5336 succnt = 0;
5337 n = 0;
5338 for (i = 0; i < count; i++) {
5339 fill_printdest_info(&info[i].info2, uLevel,&desc);
5340 n++;
5341 if (desc.errcode == NERR_Success) {
5342 succnt = n;
5343 }
5344 }
5345 }
5346 out:
5347 *rdata_len = desc.usedlen;
5348
5349 *rparam_len = 8;
5350 *rparam = smb_realloc_limit(*rparam,*rparam_len);
5351 if (!*rparam) {
5352 return False;
5353 }
5354 SSVALS(*rparam,0,desc.errcode);
5355 SSVAL(*rparam,2,0);
5356 SSVAL(*rparam,4,succnt);
5357 SSVAL(*rparam,6,queuecnt);
5358
5359 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
5360
5361 return True;
5362}
5363
5364static bool api_WPrintDriverEnum(struct smbd_server_connection *sconn,
5365 connection_struct *conn, uint16 vuid,
5366 char *param, int tpscnt,
5367 char *data, int tdscnt,
5368 int mdrcnt,int mprcnt,
5369 char **rdata,char **rparam,
5370 int *rdata_len,int *rparam_len)
5371{
5372 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
5373 char *str2 = skip_string(param,tpscnt,str1);
5374 char *p = skip_string(param,tpscnt,str2);
5375 int uLevel;
5376 int succnt;
5377 struct pack_desc desc;
5378
5379 if (!str1 || !str2 || !p) {
5380 return False;
5381 }
5382
5383 memset((char *)&desc,'\0',sizeof(desc));
5384
5385 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
5386
5387 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
5388
5389 /* check it's a supported varient */
5390 if (strcmp(str1,"WrLeh") != 0) {
5391 return False;
5392 }
5393 if (uLevel != 0 || strcmp(str2,"B41") != 0) {
5394 return False;
5395 }
5396
5397 if (mdrcnt > 0) {
5398 *rdata = smb_realloc_limit(*rdata,mdrcnt);
5399 if (!*rdata) {
5400 return False;
5401 }
5402 }
5403 desc.base = *rdata;
5404 desc.buflen = mdrcnt;
5405 if (init_package(&desc,1,0)) {
5406 PACKS(&desc,"B41","NULL");
5407 }
5408
5409 succnt = (desc.errcode == NERR_Success ? 1 : 0);
5410
5411 *rdata_len = desc.usedlen;
5412
5413 *rparam_len = 8;
5414 *rparam = smb_realloc_limit(*rparam,*rparam_len);
5415 if (!*rparam) {
5416 return False;
5417 }
5418 SSVALS(*rparam,0,desc.errcode);
5419 SSVAL(*rparam,2,0);
5420 SSVAL(*rparam,4,succnt);
5421 SSVAL(*rparam,6,1);
5422
5423 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
5424
5425 return True;
5426}
5427
5428static bool api_WPrintQProcEnum(struct smbd_server_connection *sconn,
5429 connection_struct *conn, uint16 vuid,
5430 char *param, int tpscnt,
5431 char *data, int tdscnt,
5432 int mdrcnt,int mprcnt,
5433 char **rdata,char **rparam,
5434 int *rdata_len,int *rparam_len)
5435{
5436 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
5437 char *str2 = skip_string(param,tpscnt,str1);
5438 char *p = skip_string(param,tpscnt,str2);
5439 int uLevel;
5440 int succnt;
5441 struct pack_desc desc;
5442
5443 if (!str1 || !str2 || !p) {
5444 return False;
5445 }
5446 memset((char *)&desc,'\0',sizeof(desc));
5447
5448 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
5449
5450 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
5451
5452 /* check it's a supported varient */
5453 if (strcmp(str1,"WrLeh") != 0) {
5454 return False;
5455 }
5456 if (uLevel != 0 || strcmp(str2,"B13") != 0) {
5457 return False;
5458 }
5459
5460 if (mdrcnt > 0) {
5461 *rdata = smb_realloc_limit(*rdata,mdrcnt);
5462 if (!*rdata) {
5463 return False;
5464 }
5465 }
5466 desc.base = *rdata;
5467 desc.buflen = mdrcnt;
5468 desc.format = str2;
5469 if (init_package(&desc,1,0)) {
5470 PACKS(&desc,"B13","lpd");
5471 }
5472
5473 succnt = (desc.errcode == NERR_Success ? 1 : 0);
5474
5475 *rdata_len = desc.usedlen;
5476
5477 *rparam_len = 8;
5478 *rparam = smb_realloc_limit(*rparam,*rparam_len);
5479 if (!*rparam) {
5480 return False;
5481 }
5482 SSVALS(*rparam,0,desc.errcode);
5483 SSVAL(*rparam,2,0);
5484 SSVAL(*rparam,4,succnt);
5485 SSVAL(*rparam,6,1);
5486
5487 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
5488
5489 return True;
5490}
5491
5492static bool api_WPrintPortEnum(struct smbd_server_connection *sconn,
5493 connection_struct *conn, uint16 vuid,
5494 char *param, int tpscnt,
5495 char *data, int tdscnt,
5496 int mdrcnt,int mprcnt,
5497 char **rdata,char **rparam,
5498 int *rdata_len,int *rparam_len)
5499{
5500 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
5501 char *str2 = skip_string(param,tpscnt,str1);
5502 char *p = skip_string(param,tpscnt,str2);
5503 int uLevel;
5504 int succnt;
5505 struct pack_desc desc;
5506
5507 if (!str1 || !str2 || !p) {
5508 return False;
5509 }
5510
5511 memset((char *)&desc,'\0',sizeof(desc));
5512
5513 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
5514
5515 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
5516
5517 /* check it's a supported varient */
5518 if (strcmp(str1,"WrLeh") != 0) {
5519 return False;
5520 }
5521 if (uLevel != 0 || strcmp(str2,"B9") != 0) {
5522 return False;
5523 }
5524
5525 if (mdrcnt > 0) {
5526 *rdata = smb_realloc_limit(*rdata,mdrcnt);
5527 if (!*rdata) {
5528 return False;
5529 }
5530 }
5531 memset((char *)&desc,'\0',sizeof(desc));
5532 desc.base = *rdata;
5533 desc.buflen = mdrcnt;
5534 desc.format = str2;
5535 if (init_package(&desc,1,0)) {
5536 PACKS(&desc,"B13","lp0");
5537 }
5538
5539 succnt = (desc.errcode == NERR_Success ? 1 : 0);
5540
5541 *rdata_len = desc.usedlen;
5542
5543 *rparam_len = 8;
5544 *rparam = smb_realloc_limit(*rparam,*rparam_len);
5545 if (!*rparam) {
5546 return False;
5547 }
5548 SSVALS(*rparam,0,desc.errcode);
5549 SSVAL(*rparam,2,0);
5550 SSVAL(*rparam,4,succnt);
5551 SSVAL(*rparam,6,1);
5552
5553 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
5554
5555 return True;
5556}
5557
5558/****************************************************************************
5559 List open sessions
5560 ****************************************************************************/
5561
5562static bool api_RNetSessionEnum(struct smbd_server_connection *sconn,
5563 connection_struct *conn, uint16 vuid,
5564 char *param, int tpscnt,
5565 char *data, int tdscnt,
5566 int mdrcnt,int mprcnt,
5567 char **rdata,char **rparam,
5568 int *rdata_len,int *rparam_len)
5569
5570{
5571 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
5572 char *str2 = skip_string(param,tpscnt,str1);
5573 char *p = skip_string(param,tpscnt,str2);
5574 int uLevel;
5575 struct pack_desc desc;
5576 int i;
5577
5578 TALLOC_CTX *mem_ctx = talloc_tos();
5579 WERROR werr;
5580 NTSTATUS status;
5581 struct rpc_pipe_client *cli = NULL;
5582 struct dcerpc_binding_handle *b = NULL;
5583 struct srvsvc_NetSessInfoCtr info_ctr;
5584 uint32_t totalentries, resume_handle = 0;
5585 uint32_t count = 0;
5586
5587 if (!str1 || !str2 || !p) {
5588 return False;
5589 }
5590
5591 ZERO_STRUCT(desc);
5592
5593 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
5594
5595 DEBUG(3,("RNetSessionEnum uLevel=%d\n",uLevel));
5596 DEBUG(7,("RNetSessionEnum req string=%s\n",str1));
5597 DEBUG(7,("RNetSessionEnum ret string=%s\n",str2));
5598
5599 /* check it's a supported varient */
5600 if (strcmp(str1,RAP_NetSessionEnum_REQ) != 0) {
5601 return False;
5602 }
5603 if (uLevel != 2 || strcmp(str2,RAP_SESSION_INFO_L2) != 0) {
5604 return False;
5605 }
5606
5607 status = rpc_pipe_open_interface(conn,
5608 &ndr_table_srvsvc.syntax_id,
5609 conn->session_info,
5610 &conn->sconn->client_id,
5611 conn->sconn->msg_ctx,
5612 &cli);
5613 if (!NT_STATUS_IS_OK(status)) {
5614 DEBUG(0,("RNetSessionEnum: could not connect to srvsvc: %s\n",
5615 nt_errstr(status)));
5616 desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
5617 goto out;
5618 }
5619 b = cli->binding_handle;
5620
5621 info_ctr.level = 1;
5622 info_ctr.ctr.ctr1 = talloc_zero(talloc_tos(), struct srvsvc_NetSessCtr1);
5623 if (info_ctr.ctr.ctr1 == NULL) {
5624 desc.errcode = W_ERROR_V(WERR_NOMEM);
5625 goto out;
5626 }
5627
5628 status = dcerpc_srvsvc_NetSessEnum(b, mem_ctx,
5629 cli->srv_name_slash,
5630 NULL, /* client */
5631 NULL, /* user */
5632 &info_ctr,
5633 (uint32_t)-1, /* max_buffer */
5634 &totalentries,
5635 &resume_handle,
5636 &werr);
5637 if (!NT_STATUS_IS_OK(status)) {
5638 DEBUG(0,("RNetSessionEnum: dcerpc_srvsvc_NetSessEnum failed: %s\n",
5639 nt_errstr(status)));
5640 desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
5641 goto out;
5642 }
5643
5644 if (!W_ERROR_IS_OK(werr)) {
5645 DEBUG(0,("RNetSessionEnum: dcerpc_srvsvc_NetSessEnum failed: %s\n",
5646 win_errstr(werr)));
5647 desc.errcode = W_ERROR_V(werr);
5648 goto out;
5649 }
5650
5651 count = info_ctr.ctr.ctr1->count;
5652
5653 out:
5654 if (mdrcnt > 0) {
5655 *rdata = smb_realloc_limit(*rdata,mdrcnt);
5656 if (!*rdata) {
5657 return False;
5658 }
5659 }
5660
5661 desc.base = *rdata;
5662 desc.buflen = mdrcnt;
5663 desc.format = str2;
5664 if (!init_package(&desc, count,0)) {
5665 return False;
5666 }
5667
5668 for(i=0; i < count; i++) {
5669 PACKS(&desc, "z", info_ctr.ctr.ctr1->array[i].client);
5670 PACKS(&desc, "z", info_ctr.ctr.ctr1->array[i].user);
5671 PACKI(&desc, "W", 1); /* num conns */
5672 PACKI(&desc, "W", info_ctr.ctr.ctr1->array[i].num_open);
5673 PACKI(&desc, "W", 1); /* num users */
5674 PACKI(&desc, "D", 0); /* session time */
5675 PACKI(&desc, "D", 0); /* idle time */
5676 PACKI(&desc, "D", 0); /* flags */
5677 PACKS(&desc, "z", "Unknown Client"); /* client type string */
5678 }
5679
5680 *rdata_len = desc.usedlen;
5681
5682 *rparam_len = 8;
5683 *rparam = smb_realloc_limit(*rparam,*rparam_len);
5684 if (!*rparam) {
5685 return False;
5686 }
5687 SSVALS(*rparam,0,desc.errcode);
5688 SSVAL(*rparam,2,0); /* converter */
5689 SSVAL(*rparam,4, count); /* count */
5690
5691 DEBUG(4,("RNetSessionEnum: errorcode %d\n",desc.errcode));
5692
5693 return True;
5694}
5695
5696
5697/****************************************************************************
5698 The buffer was too small.
5699 ****************************************************************************/
5700
5701static bool api_TooSmall(struct smbd_server_connection *sconn,
5702 connection_struct *conn,uint16 vuid, char *param, char *data,
5703 int mdrcnt, int mprcnt,
5704 char **rdata, char **rparam,
5705 int *rdata_len, int *rparam_len)
5706{
5707 *rparam_len = MIN(*rparam_len,mprcnt);
5708 *rparam = smb_realloc_limit(*rparam,*rparam_len);
5709 if (!*rparam) {
5710 return False;
5711 }
5712
5713 *rdata_len = 0;
5714
5715 SSVAL(*rparam,0,NERR_BufTooSmall);
5716
5717 DEBUG(3,("Supplied buffer too small in API command\n"));
5718
5719 return True;
5720}
5721
5722/****************************************************************************
5723 The request is not supported.
5724 ****************************************************************************/
5725
5726static bool api_Unsupported(struct smbd_server_connection *sconn,
5727 connection_struct *conn, uint16 vuid,
5728 char *param, int tpscnt,
5729 char *data, int tdscnt,
5730 int mdrcnt, int mprcnt,
5731 char **rdata, char **rparam,
5732 int *rdata_len, int *rparam_len)
5733{
5734 *rparam_len = 4;
5735 *rparam = smb_realloc_limit(*rparam,*rparam_len);
5736 if (!*rparam) {
5737 return False;
5738 }
5739
5740 *rdata_len = 0;
5741
5742 SSVAL(*rparam,0,NERR_notsupported);
5743 SSVAL(*rparam,2,0); /* converter word */
5744
5745 DEBUG(3,("Unsupported API command\n"));
5746
5747 return True;
5748}
5749
5750static const struct {
5751 const char *name;
5752 int id;
5753 bool (*fn)(struct smbd_server_connection *sconn,
5754 connection_struct *, uint16,
5755 char *, int,
5756 char *, int,
5757 int,int,char **,char **,int *,int *);
5758 bool auth_user; /* Deny anonymous access? */
5759} api_commands[] = {
5760 {"RNetShareEnum", RAP_WshareEnum, api_RNetShareEnum, True},
5761 {"RNetShareGetInfo", RAP_WshareGetInfo, api_RNetShareGetInfo},
5762 {"RNetShareAdd", RAP_WshareAdd, api_RNetShareAdd},
5763 {"RNetSessionEnum", RAP_WsessionEnum, api_RNetSessionEnum, True},
5764 {"RNetServerGetInfo", RAP_WserverGetInfo, api_RNetServerGetInfo},
5765 {"RNetGroupEnum", RAP_WGroupEnum, api_RNetGroupEnum, True},
5766 {"RNetGroupGetUsers", RAP_WGroupGetUsers, api_RNetGroupGetUsers, True},
5767 {"RNetUserEnum", RAP_WUserEnum, api_RNetUserEnum, True},
5768 {"RNetUserGetInfo", RAP_WUserGetInfo, api_RNetUserGetInfo},
5769 {"NetUserGetGroups", RAP_WUserGetGroups, api_NetUserGetGroups},
5770 {"NetWkstaGetInfo", RAP_WWkstaGetInfo, api_NetWkstaGetInfo},
5771 {"DosPrintQEnum", RAP_WPrintQEnum, api_DosPrintQEnum, True},
5772 {"DosPrintQGetInfo", RAP_WPrintQGetInfo, api_DosPrintQGetInfo},
5773 {"WPrintQueuePause", RAP_WPrintQPause, api_WPrintQueueCtrl},
5774 {"WPrintQueueResume", RAP_WPrintQContinue, api_WPrintQueueCtrl},
5775 {"WPrintJobEnumerate",RAP_WPrintJobEnum, api_WPrintJobEnumerate},
5776 {"WPrintJobGetInfo", RAP_WPrintJobGetInfo, api_WPrintJobGetInfo},
5777 {"RDosPrintJobDel", RAP_WPrintJobDel, api_RDosPrintJobDel},
5778 {"RDosPrintJobPause", RAP_WPrintJobPause, api_RDosPrintJobDel},
5779 {"RDosPrintJobResume",RAP_WPrintJobContinue, api_RDosPrintJobDel},
5780 {"WPrintDestEnum", RAP_WPrintDestEnum, api_WPrintDestEnum},
5781 {"WPrintDestGetInfo", RAP_WPrintDestGetInfo, api_WPrintDestGetInfo},
5782 {"NetRemoteTOD", RAP_NetRemoteTOD, api_NetRemoteTOD},
5783 {"WPrintQueuePurge", RAP_WPrintQPurge, api_WPrintQueueCtrl},
5784 {"NetServerEnum2", RAP_NetServerEnum2, api_RNetServerEnum2}, /* anon OK */
5785 {"NetServerEnum3", RAP_NetServerEnum3, api_RNetServerEnum3}, /* anon OK */
5786 {"WAccessGetUserPerms",RAP_WAccessGetUserPerms,api_WAccessGetUserPerms},
5787 {"SetUserPassword", RAP_WUserPasswordSet2, api_SetUserPassword},
5788 {"WWkstaUserLogon", RAP_WWkstaUserLogon, api_WWkstaUserLogon},
5789 {"PrintJobInfo", RAP_WPrintJobSetInfo, api_PrintJobInfo},
5790 {"WPrintDriverEnum", RAP_WPrintDriverEnum, api_WPrintDriverEnum},
5791 {"WPrintQProcEnum", RAP_WPrintQProcessorEnum,api_WPrintQProcEnum},
5792 {"WPrintPortEnum", RAP_WPrintPortEnum, api_WPrintPortEnum},
5793 {"SamOEMChangePassword",RAP_SamOEMChgPasswordUser2_P,api_SamOEMChangePassword}, /* anon OK */
5794 {NULL, -1, api_Unsupported}
5795 /* The following RAP calls are not implemented by Samba:
5796
5797 RAP_WFileEnum2 - anon not OK
5798 */
5799};
5800
5801
5802/****************************************************************************
5803 Handle remote api calls.
5804****************************************************************************/
5805
5806void api_reply(connection_struct *conn, uint16 vuid,
5807 struct smb_request *req,
5808 char *data, char *params,
5809 int tdscnt, int tpscnt,
5810 int mdrcnt, int mprcnt)
5811{
5812 int api_command;
5813 char *rdata = NULL;
5814 char *rparam = NULL;
5815 const char *name1 = NULL;
5816 const char *name2 = NULL;
5817 int rdata_len = 0;
5818 int rparam_len = 0;
5819 bool reply=False;
5820 int i;
5821
5822 if (!params) {
5823 DEBUG(0,("ERROR: NULL params in api_reply()\n"));
5824 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5825 return;
5826 }
5827
5828 if (tpscnt < 2) {
5829 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5830 return;
5831 }
5832 api_command = SVAL(params,0);
5833 /* Is there a string at position params+2 ? */
5834 if (skip_string(params,tpscnt,params+2)) {
5835 name1 = params + 2;
5836 } else {
5837 name1 = "";
5838 }
5839 name2 = skip_string(params,tpscnt,params+2);
5840 if (!name2) {
5841 name2 = "";
5842 }
5843
5844 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
5845 api_command,
5846 name1,
5847 name2,
5848 tdscnt,tpscnt,mdrcnt,mprcnt));
5849
5850 for (i=0;api_commands[i].name;i++) {
5851 if (api_commands[i].id == api_command && api_commands[i].fn) {
5852 DEBUG(3,("Doing %s\n",api_commands[i].name));
5853 break;
5854 }
5855 }
5856
5857 /* Check whether this api call can be done anonymously */
5858
5859 if (api_commands[i].auth_user && lp_restrict_anonymous()) {
5860 user_struct *user = get_valid_user_struct(req->sconn, vuid);
5861
5862 if (!user || user->session_info->guest) {
5863 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5864 return;
5865 }
5866 }
5867
5868 rdata = (char *)SMB_MALLOC(1024);
5869 if (rdata) {
5870 memset(rdata,'\0',1024);
5871 }
5872
5873 rparam = (char *)SMB_MALLOC(1024);
5874 if (rparam) {
5875 memset(rparam,'\0',1024);
5876 }
5877
5878 if(!rdata || !rparam) {
5879 DEBUG(0,("api_reply: malloc fail !\n"));
5880 SAFE_FREE(rdata);
5881 SAFE_FREE(rparam);
5882 reply_nterror(req, NT_STATUS_NO_MEMORY);
5883 return;
5884 }
5885
5886 reply = api_commands[i].fn(req->sconn, conn,
5887 vuid,
5888 params,tpscnt, /* params + length */
5889 data,tdscnt, /* data + length */
5890 mdrcnt,mprcnt,
5891 &rdata,&rparam,&rdata_len,&rparam_len);
5892
5893
5894 if (rdata_len > mdrcnt || rparam_len > mprcnt) {
5895 reply = api_TooSmall(req->sconn,conn,vuid,params,data,
5896 mdrcnt,mprcnt,
5897 &rdata,&rparam,&rdata_len,&rparam_len);
5898 }
5899
5900 /* if we get False back then it's actually unsupported */
5901 if (!reply) {
5902 reply = api_Unsupported(req->sconn,conn,vuid,params,tpscnt,
5903 data,
5904 tdscnt,mdrcnt,mprcnt,
5905 &rdata,&rparam,&rdata_len,&rparam_len);
5906 }
5907
5908 /* If api_Unsupported returns false we can't return anything. */
5909 if (reply) {
5910 send_trans_reply(conn, req, rparam, rparam_len,
5911 rdata, rdata_len, False);
5912 }
5913
5914 SAFE_FREE(rdata);
5915 SAFE_FREE(rparam);
5916 return;
5917}
Note: See TracBrowser for help on using the repository browser.