source: branches/samba-3.0/source/smbd/lanman.c@ 431

Last change on this file since 431 was 312, checked in by Herwig Bauernfeind, 16 years ago

Update 3.0 to final 3.0.36 (source)

File size: 114.5 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 2 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, write to the Free Software
22 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 */
24/*
25 This file handles the named pipe and mailslot calls
26 in the SMBtrans protocol
27 */
28
29#include "includes.h"
30
31extern struct current_user current_user;
32extern userdom_struct current_user_info;
33
34#ifdef CHECK_TYPES
35#undef CHECK_TYPES
36#endif
37#define CHECK_TYPES 0
38
39#define NERR_Success 0
40#define NERR_badpass 86
41#define NERR_notsupported 50
42
43#define NERR_BASE (2100)
44#define NERR_BufTooSmall (NERR_BASE+23)
45#define NERR_JobNotFound (NERR_BASE+51)
46#define NERR_DestNotFound (NERR_BASE+52)
47
48#define ACCESS_READ 0x01
49#define ACCESS_WRITE 0x02
50#define ACCESS_CREATE 0x04
51
52#define SHPWLEN 8 /* share password length */
53
54static BOOL api_Unsupported(connection_struct *conn, uint16 vuid,
55 char *param, int tpscnt,
56 char *data, int tdscnt,
57 int mdrcnt, int mprcnt,
58 char **rdata, char **rparam,
59 int *rdata_len, int *rparam_len);
60
61static BOOL api_TooSmall(connection_struct *conn, uint16 vuid, char *param, char *data,
62 int mdrcnt, int mprcnt,
63 char **rdata, char **rparam,
64 int *rdata_len, int *rparam_len);
65
66
67static int CopyExpanded(connection_struct *conn,
68 int snum, char **dst, char *src, int *n)
69{
70 pstring buf;
71 int l;
72
73 if (!src || !dst || !n || !(*dst)) {
74 return 0;
75 }
76
77 StrnCpy(buf,src,sizeof(buf)/2);
78 pstring_sub(buf,"%S",lp_servicename(snum));
79 standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
80 conn->connectpath, conn->gid,
81 get_current_username(),
82 current_user_info.domain,
83 buf, sizeof(buf));
84 l = push_ascii(*dst,buf,*n, STR_TERMINATE);
85 if (l == -1) {
86 return 0;
87 }
88 (*dst) += l;
89 (*n) -= l;
90 return l;
91}
92
93static int CopyAndAdvance(char **dst, char *src, int *n)
94{
95 int l;
96 if (!src || !dst || !n || !(*dst)) {
97 return 0;
98 }
99 l = push_ascii(*dst,src,*n, STR_TERMINATE);
100 if (l == -1) {
101 return 0;
102 }
103 (*dst) += l;
104 (*n) -= l;
105 return l;
106}
107
108static int StrlenExpanded(connection_struct *conn, int snum, char *s)
109{
110 pstring buf;
111 if (!s) {
112 return 0;
113 }
114 StrnCpy(buf,s,sizeof(buf)/2);
115 pstring_sub(buf,"%S",lp_servicename(snum));
116 standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
117 conn->connectpath, conn->gid,
118 get_current_username(),
119 current_user_info.domain,
120 buf, sizeof(buf));
121 return strlen(buf) + 1;
122}
123
124static char *Expand(connection_struct *conn, int snum, char *s)
125{
126 static pstring buf;
127 if (!s) {
128 return NULL;
129 }
130 StrnCpy(buf,s,sizeof(buf)/2);
131 pstring_sub(buf,"%S",lp_servicename(snum));
132 standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
133 conn->connectpath, conn->gid,
134 get_current_username(),
135 current_user_info.domain,
136 buf, sizeof(buf));
137 return &buf[0];
138}
139
140/*******************************************************************
141 Check a API string for validity when we only need to check the prefix.
142******************************************************************/
143
144static BOOL prefix_ok(const char *str, const char *prefix)
145{
146 return(strncmp(str,prefix,strlen(prefix)) == 0);
147}
148
149struct pack_desc {
150 const char *format; /* formatstring for structure */
151 const char *subformat; /* subformat for structure */
152 char *base; /* baseaddress of buffer */
153 int buflen; /* remaining size for fixed part; on init: length of base */
154 int subcount; /* count of substructures */
155 char *structbuf; /* pointer into buffer for remaining fixed part */
156 int stringlen; /* remaining size for variable part */
157 char *stringbuf; /* pointer into buffer for remaining variable part */
158 int neededlen; /* total needed size */
159 int usedlen; /* total used size (usedlen <= neededlen and usedlen <= buflen) */
160 const char *curpos; /* current position; pointer into format or subformat */
161 int errcode;
162};
163
164static int get_counter(const char **p)
165{
166 int i, n;
167 if (!p || !(*p)) {
168 return 1;
169 }
170 if (!isdigit((int)**p)) {
171 return 1;
172 }
173 for (n = 0;;) {
174 i = **p;
175 if (isdigit(i)) {
176 n = 10 * n + (i - '0');
177 } else {
178 return n;
179 }
180 (*p)++;
181 }
182}
183
184static int getlen(const char *p)
185{
186 int n = 0;
187 if (!p) {
188 return 0;
189 }
190
191 while (*p) {
192 switch( *p++ ) {
193 case 'W': /* word (2 byte) */
194 n += 2;
195 break;
196 case 'K': /* status word? (2 byte) */
197 n += 2;
198 break;
199 case 'N': /* count of substructures (word) at end */
200 n += 2;
201 break;
202 case 'D': /* double word (4 byte) */
203 case 'z': /* offset to zero terminated string (4 byte) */
204 case 'l': /* offset to user data (4 byte) */
205 n += 4;
206 break;
207 case 'b': /* offset to data (with counter) (4 byte) */
208 n += 4;
209 get_counter(&p);
210 break;
211 case 'B': /* byte (with optional counter) */
212 n += get_counter(&p);
213 break;
214 }
215 }
216 return n;
217}
218
219static BOOL init_package(struct pack_desc *p, int count, int subcount)
220{
221 int n = p->buflen;
222 int i;
223
224 if (!p->format || !p->base) {
225 return False;
226 }
227
228 i = count * getlen(p->format);
229 if (p->subformat) {
230 i += subcount * getlen(p->subformat);
231 }
232 p->structbuf = p->base;
233 p->neededlen = 0;
234 p->usedlen = 0;
235 p->subcount = 0;
236 p->curpos = p->format;
237 if (i > n) {
238 p->neededlen = i;
239 i = n = 0;
240#if 0
241 /*
242 * This is the old error code we used. Aparently
243 * WinNT/2k systems return ERRbuftoosmall (2123) and
244 * OS/2 needs this. I'm leaving this here so we can revert
245 * if needed. JRA.
246 */
247 p->errcode = ERRmoredata;
248#else
249 p->errcode = ERRbuftoosmall;
250#endif
251 } else {
252 p->errcode = NERR_Success;
253 }
254 p->buflen = i;
255 n -= i;
256 p->stringbuf = p->base + i;
257 p->stringlen = n;
258 return (p->errcode == NERR_Success);
259}
260
261static int package(struct pack_desc *p, ...)
262{
263 va_list args;
264 int needed=0, stringneeded;
265 const char *str=NULL;
266 int is_string=0, stringused;
267 int32 temp;
268
269 va_start(args,p);
270
271 if (!*p->curpos) {
272 if (!p->subcount) {
273 p->curpos = p->format;
274 } else {
275 p->curpos = p->subformat;
276 p->subcount--;
277 }
278 }
279#if CHECK_TYPES
280 str = va_arg(args,char*);
281 SMB_ASSERT(strncmp(str,p->curpos,strlen(str)) == 0);
282#endif
283 stringneeded = -1;
284
285 if (!p->curpos) {
286 va_end(args);
287 return 0;
288 }
289
290 switch( *p->curpos++ ) {
291 case 'W': /* word (2 byte) */
292 needed = 2;
293 temp = va_arg(args,int);
294 if (p->buflen >= needed) {
295 SSVAL(p->structbuf,0,temp);
296 }
297 break;
298 case 'K': /* status word? (2 byte) */
299 needed = 2;
300 temp = va_arg(args,int);
301 if (p->buflen >= needed) {
302 SSVAL(p->structbuf,0,temp);
303 }
304 break;
305 case 'N': /* count of substructures (word) at end */
306 needed = 2;
307 p->subcount = va_arg(args,int);
308 if (p->buflen >= needed) {
309 SSVAL(p->structbuf,0,p->subcount);
310 }
311 break;
312 case 'D': /* double word (4 byte) */
313 needed = 4;
314 temp = va_arg(args,int);
315 if (p->buflen >= needed) {
316 SIVAL(p->structbuf,0,temp);
317 }
318 break;
319 case 'B': /* byte (with optional counter) */
320 needed = get_counter(&p->curpos);
321 {
322 char *s = va_arg(args,char*);
323 if (p->buflen >= needed) {
324 StrnCpy(p->structbuf,s?s:"",needed-1);
325 }
326 }
327 break;
328 case 'z': /* offset to zero terminated string (4 byte) */
329 str = va_arg(args,char*);
330 stringneeded = (str ? strlen(str)+1 : 0);
331 is_string = 1;
332 break;
333 case 'l': /* offset to user data (4 byte) */
334 str = va_arg(args,char*);
335 stringneeded = va_arg(args,int);
336 is_string = 0;
337 break;
338 case 'b': /* offset to data (with counter) (4 byte) */
339 str = va_arg(args,char*);
340 stringneeded = get_counter(&p->curpos);
341 is_string = 0;
342 break;
343 }
344
345 va_end(args);
346 if (stringneeded >= 0) {
347 needed = 4;
348 if (p->buflen >= needed) {
349 stringused = stringneeded;
350 if (stringused > p->stringlen) {
351 stringused = (is_string ? p->stringlen : 0);
352 if (p->errcode == NERR_Success) {
353 p->errcode = ERRmoredata;
354 }
355 }
356 if (!stringused) {
357 SIVAL(p->structbuf,0,0);
358 } else {
359 SIVAL(p->structbuf,0,PTR_DIFF(p->stringbuf,p->base));
360 memcpy(p->stringbuf,str?str:"",stringused);
361 if (is_string) {
362 p->stringbuf[stringused-1] = '\0';
363 }
364 p->stringbuf += stringused;
365 p->stringlen -= stringused;
366 p->usedlen += stringused;
367 }
368 }
369 p->neededlen += stringneeded;
370 }
371
372 p->neededlen += needed;
373 if (p->buflen >= needed) {
374 p->structbuf += needed;
375 p->buflen -= needed;
376 p->usedlen += needed;
377 } else {
378 if (p->errcode == NERR_Success) {
379 p->errcode = ERRmoredata;
380 }
381 }
382 return 1;
383}
384
385#if CHECK_TYPES
386#define PACK(desc,t,v) package(desc,t,v,0,0,0,0)
387#define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0)
388#else
389#define PACK(desc,t,v) package(desc,v)
390#define PACKl(desc,t,v,l) package(desc,v,l)
391#endif
392
393static void PACKI(struct pack_desc* desc, const char *t,int v)
394{
395 PACK(desc,t,v);
396}
397
398static void PACKS(struct pack_desc* desc,const char *t,const char *v)
399{
400 PACK(desc,t,v);
401}
402
403/****************************************************************************
404 Get a print queue.
405****************************************************************************/
406
407static void PackDriverData(struct pack_desc* desc)
408{
409 char drivdata[4+4+32];
410 SIVAL(drivdata,0,sizeof drivdata); /* cb */
411 SIVAL(drivdata,4,1000); /* lVersion */
412 memset(drivdata+8,0,32); /* szDeviceName */
413 push_ascii(drivdata+8,"NULL",32, STR_TERMINATE);
414 PACKl(desc,"l",drivdata,sizeof drivdata); /* pDriverData */
415}
416
417static int check_printq_info(struct pack_desc* desc,
418 unsigned int uLevel, char *id1, char *id2)
419{
420 desc->subformat = NULL;
421 switch( uLevel ) {
422 case 0:
423 desc->format = "B13";
424 break;
425 case 1:
426 desc->format = "B13BWWWzzzzzWW";
427 break;
428 case 2:
429 desc->format = "B13BWWWzzzzzWN";
430 desc->subformat = "WB21BB16B10zWWzDDz";
431 break;
432 case 3:
433 desc->format = "zWWWWzzzzWWzzl";
434 break;
435 case 4:
436 desc->format = "zWWWWzzzzWNzzl";
437 desc->subformat = "WWzWWDDzz";
438 break;
439 case 5:
440 desc->format = "z";
441 break;
442 case 51:
443 desc->format = "K";
444 break;
445 case 52:
446 desc->format = "WzzzzzzzzN";
447 desc->subformat = "z";
448 break;
449 default:
450 DEBUG(0,("check_printq_info: invalid level %d\n",
451 uLevel ));
452 return False;
453 }
454 if (id1 == NULL || strcmp(desc->format,id1) != 0) {
455 DEBUG(0,("check_printq_info: invalid format %s\n",
456 id1 ? id1 : "<NULL>" ));
457 return False;
458 }
459 if (desc->subformat && (id2 == NULL || strcmp(desc->subformat,id2) != 0)) {
460 DEBUG(0,("check_printq_info: invalid subformat %s\n",
461 id2 ? id2 : "<NULL>" ));
462 return False;
463 }
464 return True;
465}
466
467
468#define RAP_JOB_STATUS_QUEUED 0
469#define RAP_JOB_STATUS_PAUSED 1
470#define RAP_JOB_STATUS_SPOOLING 2
471#define RAP_JOB_STATUS_PRINTING 3
472#define RAP_JOB_STATUS_PRINTED 4
473
474#define RAP_QUEUE_STATUS_PAUSED 1
475#define RAP_QUEUE_STATUS_ERROR 2
476
477/* turn a print job status into a on the wire status
478*/
479static int printj_status(int v)
480{
481 switch (v) {
482 case LPQ_QUEUED:
483 return RAP_JOB_STATUS_QUEUED;
484 case LPQ_PAUSED:
485 return RAP_JOB_STATUS_PAUSED;
486 case LPQ_SPOOLING:
487 return RAP_JOB_STATUS_SPOOLING;
488 case LPQ_PRINTING:
489 return RAP_JOB_STATUS_PRINTING;
490 }
491 return 0;
492}
493
494/* turn a print queue status into a on the wire status
495*/
496static int printq_status(int v)
497{
498 switch (v) {
499 case LPQ_QUEUED:
500 return 0;
501 case LPQ_PAUSED:
502 return RAP_QUEUE_STATUS_PAUSED;
503 }
504 return RAP_QUEUE_STATUS_ERROR;
505}
506
507static void fill_printjob_info(connection_struct *conn, int snum, int uLevel,
508 struct pack_desc *desc,
509 print_queue_struct *queue, int n)
510{
511 time_t t = queue->time;
512
513 /* the client expects localtime */
514 t -= get_time_zone(t);
515
516 PACKI(desc,"W",pjobid_to_rap(lp_const_servicename(snum),queue->job)); /* uJobId */
517 if (uLevel == 1) {
518 PACKS(desc,"B21",queue->fs_user); /* szUserName */
519 PACKS(desc,"B",""); /* pad */
520 PACKS(desc,"B16",""); /* szNotifyName */
521 PACKS(desc,"B10","PM_Q_RAW"); /* szDataType */
522 PACKS(desc,"z",""); /* pszParms */
523 PACKI(desc,"W",n+1); /* uPosition */
524 PACKI(desc,"W",printj_status(queue->status)); /* fsStatus */
525 PACKS(desc,"z",""); /* pszStatus */
526 PACKI(desc,"D",t); /* ulSubmitted */
527 PACKI(desc,"D",queue->size); /* ulSize */
528 PACKS(desc,"z",queue->fs_file); /* pszComment */
529 }
530 if (uLevel == 2 || uLevel == 3 || uLevel == 4) {
531 PACKI(desc,"W",queue->priority); /* uPriority */
532 PACKS(desc,"z",queue->fs_user); /* pszUserName */
533 PACKI(desc,"W",n+1); /* uPosition */
534 PACKI(desc,"W",printj_status(queue->status)); /* fsStatus */
535 PACKI(desc,"D",t); /* ulSubmitted */
536 PACKI(desc,"D",queue->size); /* ulSize */
537 PACKS(desc,"z","Samba"); /* pszComment */
538 PACKS(desc,"z",queue->fs_file); /* pszDocument */
539 if (uLevel == 3) {
540 PACKS(desc,"z",""); /* pszNotifyName */
541 PACKS(desc,"z","PM_Q_RAW"); /* pszDataType */
542 PACKS(desc,"z",""); /* pszParms */
543 PACKS(desc,"z",""); /* pszStatus */
544 PACKS(desc,"z",SERVICE(snum)); /* pszQueue */
545 PACKS(desc,"z","lpd"); /* pszQProcName */
546 PACKS(desc,"z",""); /* pszQProcParms */
547 PACKS(desc,"z","NULL"); /* pszDriverName */
548 PackDriverData(desc); /* pDriverData */
549 PACKS(desc,"z",""); /* pszPrinterName */
550 } else if (uLevel == 4) { /* OS2 */
551 PACKS(desc,"z",""); /* pszSpoolFileName */
552 PACKS(desc,"z",""); /* pszPortName */
553 PACKS(desc,"z",""); /* pszStatus */
554 PACKI(desc,"D",0); /* ulPagesSpooled */
555 PACKI(desc,"D",0); /* ulPagesSent */
556 PACKI(desc,"D",0); /* ulPagesPrinted */
557 PACKI(desc,"D",0); /* ulTimePrinted */
558 PACKI(desc,"D",0); /* ulExtendJobStatus */
559 PACKI(desc,"D",0); /* ulStartPage */
560 PACKI(desc,"D",0); /* ulEndPage */
561 }
562 }
563}
564
565/********************************************************************
566 Return a driver name given an snum.
567 Returns True if from tdb, False otherwise.
568 ********************************************************************/
569
570static BOOL get_driver_name(int snum, pstring drivername)
571{
572 NT_PRINTER_INFO_LEVEL *info = NULL;
573 BOOL in_tdb = False;
574
575 get_a_printer (NULL, &info, 2, lp_servicename(snum));
576 if (info != NULL) {
577 pstrcpy( drivername, info->info_2->drivername);
578 in_tdb = True;
579 free_a_printer(&info, 2);
580 }
581
582 return in_tdb;
583}
584
585/********************************************************************
586 Respond to the DosPrintQInfo command with a level of 52
587 This is used to get printer driver information for Win9x clients
588 ********************************************************************/
589static void fill_printq_info_52(connection_struct *conn, int snum,
590 struct pack_desc* desc, int count )
591{
592 int i;
593 fstring location;
594 NT_PRINTER_DRIVER_INFO_LEVEL driver;
595 NT_PRINTER_INFO_LEVEL *printer = NULL;
596
597 ZERO_STRUCT(driver);
598
599 if ( !W_ERROR_IS_OK(get_a_printer( NULL, &printer, 2, lp_servicename(snum))) ) {
600 DEBUG(3,("fill_printq_info_52: Failed to lookup printer [%s]\n",
601 lp_servicename(snum)));
602 goto err;
603 }
604
605 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername,
606 "Windows 4.0", 0)) )
607 {
608 DEBUG(3,("fill_printq_info_52: Failed to lookup driver [%s]\n",
609 printer->info_2->drivername));
610 goto err;
611 }
612
613 trim_string(driver.info_3->driverpath, "\\print$\\WIN40\\0\\", 0);
614 trim_string(driver.info_3->datafile, "\\print$\\WIN40\\0\\", 0);
615 trim_string(driver.info_3->helpfile, "\\print$\\WIN40\\0\\", 0);
616
617 PACKI(desc, "W", 0x0400); /* don't know */
618 PACKS(desc, "z", driver.info_3->name); /* long printer name */
619 PACKS(desc, "z", driver.info_3->driverpath); /* Driverfile Name */
620 PACKS(desc, "z", driver.info_3->datafile); /* Datafile name */
621 PACKS(desc, "z", driver.info_3->monitorname); /* language monitor */
622
623 fstrcpy(location, "\\\\%L\\print$\\WIN40\\0");
624 standard_sub_basic( "", "", location, sizeof(location)-1 );
625 PACKS(desc,"z", location); /* share to retrieve files */
626
627 PACKS(desc,"z", driver.info_3->defaultdatatype); /* default data type */
628 PACKS(desc,"z", driver.info_3->helpfile); /* helpfile name */
629 PACKS(desc,"z", driver.info_3->driverpath); /* driver name */
630
631 DEBUG(3,("Printer Driver Name: %s:\n",driver.info_3->name));
632 DEBUG(3,("Driver: %s:\n",driver.info_3->driverpath));
633 DEBUG(3,("Data File: %s:\n",driver.info_3->datafile));
634 DEBUG(3,("Language Monitor: %s:\n",driver.info_3->monitorname));
635 DEBUG(3,("Driver Location: %s:\n",location));
636 DEBUG(3,("Data Type: %s:\n",driver.info_3->defaultdatatype));
637 DEBUG(3,("Help File: %s:\n",driver.info_3->helpfile));
638 PACKI(desc,"N",count); /* number of files to copy */
639
640 for ( i=0; i<count && driver.info_3->dependentfiles && *driver.info_3->dependentfiles[i]; i++)
641 {
642 trim_string(driver.info_3->dependentfiles[i], "\\print$\\WIN40\\0\\", 0);
643 PACKS(desc,"z",driver.info_3->dependentfiles[i]); /* driver files to copy */
644 DEBUG(3,("Dependent File: %s:\n",driver.info_3->dependentfiles[i]));
645 }
646
647 /* sanity check */
648 if ( i != count )
649 DEBUG(3,("fill_printq_info_52: file count specified by client [%d] != number of dependent files [%i]\n",
650 count, i));
651
652 DEBUG(3,("fill_printq_info on <%s> gave %d entries\n", SERVICE(snum),i));
653
654 desc->errcode=NERR_Success;
655 goto done;
656
657err:
658 DEBUG(3,("fill_printq_info: Can't supply driver files\n"));
659 desc->errcode=NERR_notsupported;
660
661done:
662 if ( printer )
663 free_a_printer( &printer, 2 );
664
665 if ( driver.info_3 )
666 free_a_printer_driver( driver, 3 );
667}
668
669
670static void fill_printq_info(connection_struct *conn, int snum, int uLevel,
671 struct pack_desc* desc,
672 int count, print_queue_struct* queue,
673 print_status_struct* status)
674{
675 switch (uLevel) {
676 case 1:
677 case 2:
678 PACKS(desc,"B13",SERVICE(snum));
679 break;
680 case 3:
681 case 4:
682 case 5:
683 PACKS(desc,"z",Expand(conn,snum,SERVICE(snum)));
684 break;
685 case 51:
686 PACKI(desc,"K",printq_status(status->status));
687 break;
688 }
689
690 if (uLevel == 1 || uLevel == 2) {
691 PACKS(desc,"B",""); /* alignment */
692 PACKI(desc,"W",5); /* priority */
693 PACKI(desc,"W",0); /* start time */
694 PACKI(desc,"W",0); /* until time */
695 PACKS(desc,"z",""); /* pSepFile */
696 PACKS(desc,"z","lpd"); /* pPrProc */
697 PACKS(desc,"z",SERVICE(snum)); /* pDestinations */
698 PACKS(desc,"z",""); /* pParms */
699 if (snum < 0) {
700 PACKS(desc,"z","UNKNOWN PRINTER");
701 PACKI(desc,"W",LPSTAT_ERROR);
702 }
703 else if (!status || !status->message[0]) {
704 PACKS(desc,"z",Expand(conn,snum,lp_comment(snum)));
705 PACKI(desc,"W",LPSTAT_OK); /* status */
706 } else {
707 PACKS(desc,"z",status->message);
708 PACKI(desc,"W",printq_status(status->status)); /* status */
709 }
710 PACKI(desc,(uLevel == 1 ? "W" : "N"),count);
711 }
712
713 if (uLevel == 3 || uLevel == 4) {
714 pstring drivername;
715
716 PACKI(desc,"W",5); /* uPriority */
717 PACKI(desc,"W",0); /* uStarttime */
718 PACKI(desc,"W",0); /* uUntiltime */
719 PACKI(desc,"W",5); /* pad1 */
720 PACKS(desc,"z",""); /* pszSepFile */
721 PACKS(desc,"z","WinPrint"); /* pszPrProc */
722 PACKS(desc,"z",NULL); /* pszParms */
723 PACKS(desc,"z",NULL); /* pszComment - don't ask.... JRA */
724 /* "don't ask" that it's done this way to fix corrupted
725 Win9X/ME printer comments. */
726 if (!status) {
727 PACKI(desc,"W",LPSTAT_OK); /* fsStatus */
728 } else {
729 PACKI(desc,"W",printq_status(status->status)); /* fsStatus */
730 }
731 PACKI(desc,(uLevel == 3 ? "W" : "N"),count); /* cJobs */
732 PACKS(desc,"z",SERVICE(snum)); /* pszPrinters */
733 get_driver_name(snum,drivername);
734 PACKS(desc,"z",drivername); /* pszDriverName */
735 PackDriverData(desc); /* pDriverData */
736 }
737
738 if (uLevel == 2 || uLevel == 4) {
739 int i;
740 for (i=0;i<count;i++)
741 fill_printjob_info(conn,snum,uLevel == 2 ? 1 : 2,desc,&queue[i],i);
742 }
743
744 if (uLevel==52)
745 fill_printq_info_52( conn, snum, desc, count );
746}
747
748/* This function returns the number of files for a given driver */
749static int get_printerdrivernumber(int snum)
750{
751 int result = 0;
752 NT_PRINTER_DRIVER_INFO_LEVEL driver;
753 NT_PRINTER_INFO_LEVEL *printer = NULL;
754
755 ZERO_STRUCT(driver);
756
757 if ( !W_ERROR_IS_OK(get_a_printer( NULL, &printer, 2, lp_servicename(snum))) ) {
758 DEBUG(3,("get_printerdrivernumber: Failed to lookup printer [%s]\n",
759 lp_servicename(snum)));
760 goto done;
761 }
762
763 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername,
764 "Windows 4.0", 0)) )
765 {
766 DEBUG(3,("get_printerdrivernumber: Failed to lookup driver [%s]\n",
767 printer->info_2->drivername));
768 goto done;
769 }
770
771 /* count the number of files */
772 while ( driver.info_3->dependentfiles && *driver.info_3->dependentfiles[result] )
773 result++;
774 \
775 done:
776 if ( printer )
777 free_a_printer( &printer, 2 );
778
779 if ( driver.info_3 )
780 free_a_printer_driver( driver, 3 );
781
782 return result;
783}
784
785static BOOL api_DosPrintQGetInfo(connection_struct *conn, uint16 vuid,
786 char *param, int tpscnt,
787 char *data, int tdscnt,
788 int mdrcnt,int mprcnt,
789 char **rdata,char **rparam,
790 int *rdata_len,int *rparam_len)
791{
792 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
793 char *str2 = skip_string(param,tpscnt,str1);
794 char *p = skip_string(param,tpscnt,str2);
795 char *QueueName = p;
796 unsigned int uLevel;
797 int count=0;
798 int snum;
799 char *str3;
800 struct pack_desc desc;
801 print_queue_struct *queue=NULL;
802 print_status_struct status;
803 char* tmpdata=NULL;
804
805 if (!str1 || !str2 || !p) {
806 return False;
807 }
808 memset((char *)&status,'\0',sizeof(status));
809 memset((char *)&desc,'\0',sizeof(desc));
810
811 p = skip_string(param,tpscnt,p);
812 if (!p) {
813 return False;
814 }
815 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
816 str3 = get_safe_str_ptr(param,tpscnt,p,4);
817 /* str3 may be null here and is checked in check_printq_info(). */
818
819 /* remove any trailing username */
820 if ((p = strchr_m(QueueName,'%')))
821 *p = 0;
822
823 DEBUG(3,("api_DosPrintQGetInfo uLevel=%d name=%s\n",uLevel,QueueName));
824
825 /* check it's a supported varient */
826 if (!prefix_ok(str1,"zWrLh"))
827 return False;
828 if (!check_printq_info(&desc,uLevel,str2,str3)) {
829 /*
830 * Patch from Scott Moomaw <scott@bridgewater.edu>
831 * to return the 'invalid info level' error if an
832 * unknown level was requested.
833 */
834 *rdata_len = 0;
835 *rparam_len = 6;
836 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
837 if (!*rparam) {
838 return False;
839 }
840 SSVALS(*rparam,0,ERRunknownlevel);
841 SSVAL(*rparam,2,0);
842 SSVAL(*rparam,4,0);
843 return(True);
844 }
845
846 snum = find_service(QueueName);
847 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) )
848 return False;
849
850 if (uLevel==52) {
851 count = get_printerdrivernumber(snum);
852 DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count));
853 } else {
854 count = print_queue_status(snum, &queue,&status);
855 }
856
857 if (mdrcnt > 0) {
858 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
859 if (!*rdata) {
860 return False;
861 }
862 desc.base = *rdata;
863 desc.buflen = mdrcnt;
864 } else {
865 /*
866 * Don't return data but need to get correct length
867 * init_package will return wrong size if buflen=0
868 */
869 desc.buflen = getlen(desc.format);
870 desc.base = tmpdata = (char *) SMB_MALLOC (desc.buflen);
871 }
872
873 if (init_package(&desc,1,count)) {
874 desc.subcount = count;
875 fill_printq_info(conn,snum,uLevel,&desc,count,queue,&status);
876 }
877
878 *rdata_len = desc.usedlen;
879
880 /*
881 * We must set the return code to ERRbuftoosmall
882 * in order to support lanman style printing with Win NT/2k
883 * clients --jerry
884 */
885 if (!mdrcnt && lp_disable_spoolss())
886 desc.errcode = ERRbuftoosmall;
887
888 *rdata_len = desc.usedlen;
889 *rparam_len = 6;
890 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
891 if (!*rparam) {
892 return False;
893 }
894 SSVALS(*rparam,0,desc.errcode);
895 SSVAL(*rparam,2,0);
896 SSVAL(*rparam,4,desc.neededlen);
897
898 DEBUG(4,("printqgetinfo: errorcode %d\n",desc.errcode));
899
900 SAFE_FREE(queue);
901 SAFE_FREE(tmpdata);
902
903 return(True);
904}
905
906/****************************************************************************
907 View list of all print jobs on all queues.
908****************************************************************************/
909
910static BOOL api_DosPrintQEnum(connection_struct *conn, uint16 vuid,
911 char *param, int tpscnt,
912 char *data, int tdscnt,
913 int mdrcnt, int mprcnt,
914 char **rdata, char** rparam,
915 int *rdata_len, int *rparam_len)
916{
917 char *param_format = get_safe_str_ptr(param,tpscnt,param,2);
918 char *output_format1 = skip_string(param,tpscnt,param_format);
919 char *p = skip_string(param,tpscnt,output_format1);
920 unsigned int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
921 char *output_format2 = get_safe_str_ptr(param,tpscnt,p,4);
922 int services = lp_numservices();
923 int i, n;
924 struct pack_desc desc;
925 print_queue_struct **queue = NULL;
926 print_status_struct *status = NULL;
927 int *subcntarr = NULL;
928 int queuecnt = 0, subcnt = 0, succnt = 0;
929
930 if (!param_format || !output_format1 || !p) {
931 return False;
932 }
933
934 memset((char *)&desc,'\0',sizeof(desc));
935
936 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel));
937
938 if (!prefix_ok(param_format,"WrLeh")) {
939 return False;
940 }
941 if (!check_printq_info(&desc,uLevel,output_format1,output_format2)) {
942 /*
943 * Patch from Scott Moomaw <scott@bridgewater.edu>
944 * to return the 'invalid info level' error if an
945 * unknown level was requested.
946 */
947 *rdata_len = 0;
948 *rparam_len = 6;
949 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
950 if (!*rparam) {
951 return False;
952 }
953 SSVALS(*rparam,0,ERRunknownlevel);
954 SSVAL(*rparam,2,0);
955 SSVAL(*rparam,4,0);
956 return(True);
957 }
958
959 for (i = 0; i < services; i++) {
960 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
961 queuecnt++;
962 }
963 }
964
965 if((queue = SMB_MALLOC_ARRAY(print_queue_struct*, queuecnt)) == NULL) {
966 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
967 goto err;
968 }
969 memset(queue,0,queuecnt*sizeof(print_queue_struct*));
970 if((status = SMB_MALLOC_ARRAY(print_status_struct,queuecnt)) == NULL) {
971 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
972 goto err;
973 }
974 memset(status,0,queuecnt*sizeof(print_status_struct));
975 if((subcntarr = SMB_MALLOC_ARRAY(int,queuecnt)) == NULL) {
976 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
977 goto err;
978 }
979
980 subcnt = 0;
981 n = 0;
982 for (i = 0; i < services; i++) {
983 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
984 subcntarr[n] = print_queue_status(i, &queue[n],&status[n]);
985 subcnt += subcntarr[n];
986 n++;
987 }
988 }
989
990 if (mdrcnt > 0) {
991 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
992 if (!*rdata) {
993 goto err;
994 }
995 }
996 desc.base = *rdata;
997 desc.buflen = mdrcnt;
998
999 if (init_package(&desc,queuecnt,subcnt)) {
1000 n = 0;
1001 succnt = 0;
1002 for (i = 0; i < services; i++) {
1003 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
1004 fill_printq_info(conn,i,uLevel,&desc,subcntarr[n],queue[n],&status[n]);
1005 n++;
1006 if (desc.errcode == NERR_Success) {
1007 succnt = n;
1008 }
1009 }
1010 }
1011 }
1012
1013 SAFE_FREE(subcntarr);
1014
1015 *rdata_len = desc.usedlen;
1016 *rparam_len = 8;
1017 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1018 if (!*rparam) {
1019 goto err;
1020 }
1021 SSVALS(*rparam,0,desc.errcode);
1022 SSVAL(*rparam,2,0);
1023 SSVAL(*rparam,4,succnt);
1024 SSVAL(*rparam,6,queuecnt);
1025
1026 for (i = 0; i < queuecnt; i++) {
1027 if (queue) {
1028 SAFE_FREE(queue[i]);
1029 }
1030 }
1031
1032 SAFE_FREE(queue);
1033 SAFE_FREE(status);
1034
1035 return True;
1036
1037 err:
1038
1039 SAFE_FREE(subcntarr);
1040 for (i = 0; i < queuecnt; i++) {
1041 if (queue) {
1042 SAFE_FREE(queue[i]);
1043 }
1044 }
1045 SAFE_FREE(queue);
1046 SAFE_FREE(status);
1047
1048 return False;
1049}
1050
1051/****************************************************************************
1052 Get info level for a server list query.
1053****************************************************************************/
1054
1055static BOOL check_server_info(int uLevel, char* id)
1056{
1057 switch( uLevel ) {
1058 case 0:
1059 if (strcmp(id,"B16") != 0) {
1060 return False;
1061 }
1062 break;
1063 case 1:
1064 if (strcmp(id,"B16BBDz") != 0) {
1065 return False;
1066 }
1067 break;
1068 default:
1069 return False;
1070 }
1071 return True;
1072}
1073
1074struct srv_info_struct {
1075 fstring name;
1076 uint32 type;
1077 fstring comment;
1078 fstring domain;
1079 BOOL server_added;
1080};
1081
1082/*******************************************************************
1083 Get server info lists from the files saved by nmbd. Return the
1084 number of entries.
1085******************************************************************/
1086
1087static int get_server_info(uint32 servertype,
1088 struct srv_info_struct **servers,
1089 const char *domain)
1090{
1091 int count=0;
1092 int alloced=0;
1093 char **lines;
1094 BOOL local_list_only;
1095 int i;
1096
1097 lines = file_lines_load(lock_path(SERVER_LIST), NULL, 0);
1098 if (!lines) {
1099 DEBUG(4,("Can't open %s - %s\n",lock_path(SERVER_LIST),strerror(errno)));
1100 return 0;
1101 }
1102
1103 /* request for everything is code for request all servers */
1104 if (servertype == SV_TYPE_ALL) {
1105 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1106 }
1107
1108 local_list_only = (servertype & SV_TYPE_LOCAL_LIST_ONLY);
1109
1110 DEBUG(4,("Servertype search: %8x\n",servertype));
1111
1112 for (i=0;lines[i];i++) {
1113 fstring stype;
1114 struct srv_info_struct *s;
1115 const char *ptr = lines[i];
1116 BOOL ok = True;
1117
1118 if (!*ptr) {
1119 continue;
1120 }
1121
1122 if (count == alloced) {
1123 alloced += 10;
1124 *servers = SMB_REALLOC_ARRAY(*servers,struct srv_info_struct, alloced);
1125 if (!*servers) {
1126 DEBUG(0,("get_server_info: failed to enlarge servers info struct!\n"));
1127 file_lines_free(lines);
1128 return 0;
1129 }
1130 memset((char *)((*servers)+count),'\0',sizeof(**servers)*(alloced-count));
1131 }
1132 s = &(*servers)[count];
1133
1134 if (!next_token(&ptr,s->name, NULL, sizeof(s->name))) {
1135 continue;
1136 }
1137 if (!next_token(&ptr,stype, NULL, sizeof(stype))) {
1138 continue;
1139 }
1140 if (!next_token(&ptr,s->comment, NULL,
1141 MIN(sizeof(s->comment),
1142 MAX_SERVER_STRING_LENGTH))) {
1143 continue;
1144 }
1145 if (!next_token(&ptr,s->domain, NULL, sizeof(s->domain))) {
1146 /* this allows us to cope with an old nmbd */
1147 fstrcpy(s->domain,lp_workgroup());
1148 }
1149
1150 if (sscanf(stype,"%X",&s->type) != 1) {
1151 DEBUG(4,("r:host file "));
1152 ok = False;
1153 }
1154
1155 /* Filter the servers/domains we return based on what was asked for. */
1156
1157 /* Check to see if we are being asked for a local list only. */
1158 if(local_list_only && ((s->type & SV_TYPE_LOCAL_LIST_ONLY) == 0)) {
1159 DEBUG(4,("r: local list only"));
1160 ok = False;
1161 }
1162
1163 /* doesn't match up: don't want it */
1164 if (!(servertype & s->type)) {
1165 DEBUG(4,("r:serv type "));
1166 ok = False;
1167 }
1168
1169 if ((servertype & SV_TYPE_DOMAIN_ENUM) !=
1170 (s->type & SV_TYPE_DOMAIN_ENUM)) {
1171 DEBUG(4,("s: dom mismatch "));
1172 ok = False;
1173 }
1174
1175 if (!strequal(domain, s->domain) && !(servertype & SV_TYPE_DOMAIN_ENUM)) {
1176 ok = False;
1177 }
1178
1179 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
1180 s->type &= ~SV_TYPE_LOCAL_LIST_ONLY;
1181
1182 if (ok) {
1183 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
1184 s->name, s->type, s->comment, s->domain));
1185 s->server_added = True;
1186 count++;
1187 } else {
1188 DEBUG(4,("%20s %8x %25s %15s\n",
1189 s->name, s->type, s->comment, s->domain));
1190 }
1191 }
1192
1193 file_lines_free(lines);
1194 return count;
1195}
1196
1197/*******************************************************************
1198 Fill in a server info structure.
1199******************************************************************/
1200
1201static int fill_srv_info(struct srv_info_struct *service,
1202 int uLevel, char **buf, int *buflen,
1203 char **stringbuf, int *stringspace, char *baseaddr)
1204{
1205 int struct_len;
1206 char* p;
1207 char* p2;
1208 int l2;
1209 int len;
1210
1211 switch (uLevel) {
1212 case 0:
1213 struct_len = 16;
1214 break;
1215 case 1:
1216 struct_len = 26;
1217 break;
1218 default:
1219 return -1;
1220 }
1221
1222 if (!buf) {
1223 len = 0;
1224 switch (uLevel) {
1225 case 1:
1226 len = strlen(service->comment)+1;
1227 break;
1228 }
1229
1230 *buflen = struct_len;
1231 *stringspace = len;
1232 return struct_len + len;
1233 }
1234
1235 len = struct_len;
1236 p = *buf;
1237 if (*buflen < struct_len) {
1238 return -1;
1239 }
1240 if (stringbuf) {
1241 p2 = *stringbuf;
1242 l2 = *stringspace;
1243 } else {
1244 p2 = p + struct_len;
1245 l2 = *buflen - struct_len;
1246 }
1247 if (!baseaddr) {
1248 baseaddr = p;
1249 }
1250
1251 switch (uLevel) {
1252 case 0:
1253 push_ascii(p,service->name, MAX_NETBIOSNAME_LEN, STR_TERMINATE);
1254 break;
1255
1256 case 1:
1257 push_ascii(p,service->name,MAX_NETBIOSNAME_LEN, STR_TERMINATE);
1258 SIVAL(p,18,service->type);
1259 SIVAL(p,22,PTR_DIFF(p2,baseaddr));
1260 len += CopyAndAdvance(&p2,service->comment,&l2);
1261 break;
1262 }
1263
1264 if (stringbuf) {
1265 *buf = p + struct_len;
1266 *buflen -= struct_len;
1267 *stringbuf = p2;
1268 *stringspace = l2;
1269 } else {
1270 *buf = p2;
1271 *buflen -= len;
1272 }
1273 return len;
1274}
1275
1276
1277static BOOL srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2)
1278{
1279 return(strcmp(s1->name,s2->name));
1280}
1281
1282/****************************************************************************
1283 View list of servers available (or possibly domains). The info is
1284 extracted from lists saved by nmbd on the local host.
1285****************************************************************************/
1286
1287static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid,
1288 char *param, int tpscnt,
1289 char *data, int tdscnt,
1290 int mdrcnt, int mprcnt, char **rdata,
1291 char **rparam, int *rdata_len, int *rparam_len)
1292{
1293 char *str1 = get_safe_str_ptr(param, tpscnt, param, 2);
1294 char *str2 = skip_string(param,tpscnt,str1);
1295 char *p = skip_string(param,tpscnt,str2);
1296 int uLevel = get_safe_SVAL(param, tpscnt, p, 0, -1);
1297 int buf_len = get_safe_SVAL(param,tpscnt, p, 2, 0);
1298 uint32 servertype = get_safe_IVAL(param,tpscnt,p,4, 0);
1299 char *p2;
1300 int data_len, fixed_len, string_len;
1301 int f_len = 0, s_len = 0;
1302 struct srv_info_struct *servers=NULL;
1303 int counted=0,total=0;
1304 int i,missed;
1305 fstring domain;
1306 BOOL domain_request;
1307 BOOL local_request;
1308
1309 if (!str1 || !str2 || !p) {
1310 return False;
1311 }
1312
1313 /* If someone sets all the bits they don't really mean to set
1314 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1315 known servers. */
1316
1317 if (servertype == SV_TYPE_ALL) {
1318 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1319 }
1320
1321 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1322 any other bit (they may just set this bit on it's own) they
1323 want all the locally seen servers. However this bit can be
1324 set on its own so set the requested servers to be
1325 ALL - DOMAIN_ENUM. */
1326
1327 if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) && !(servertype & SV_TYPE_DOMAIN_ENUM)) {
1328 servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM);
1329 }
1330
1331 domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
1332 local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0);
1333
1334 p += 8;
1335
1336 if (!prefix_ok(str1,"WrLehD")) {
1337 return False;
1338 }
1339 if (!check_server_info(uLevel,str2)) {
1340 return False;
1341 }
1342
1343 DEBUG(4, ("server request level: %s %8x ", str2, servertype));
1344 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
1345 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
1346
1347 if (strcmp(str1, "WrLehDz") == 0) {
1348 if (skip_string(param,tpscnt,p) == NULL) {
1349 return False;
1350 }
1351 pull_ascii_fstring(domain, p);
1352 } else {
1353 fstrcpy(domain, lp_workgroup());
1354 }
1355
1356 if (lp_browse_list()) {
1357 total = get_server_info(servertype,&servers,domain);
1358 }
1359
1360 data_len = fixed_len = string_len = 0;
1361 missed = 0;
1362
1363 if (total > 0) {
1364 qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp);
1365 }
1366
1367 {
1368 char *lastname=NULL;
1369
1370 for (i=0;i<total;i++) {
1371 struct srv_info_struct *s = &servers[i];
1372
1373 if (lastname && strequal(lastname,s->name)) {
1374 continue;
1375 }
1376 lastname = s->name;
1377 data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
1378 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1379 s->name, s->type, s->comment, s->domain));
1380
1381 if (data_len <= buf_len) {
1382 counted++;
1383 fixed_len += f_len;
1384 string_len += s_len;
1385 } else {
1386 missed++;
1387 }
1388 }
1389 }
1390
1391 *rdata_len = fixed_len + string_len;
1392 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
1393 if (!*rdata) {
1394 return False;
1395 }
1396 memset(*rdata,'\0',*rdata_len);
1397
1398 p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */
1399 p = *rdata;
1400 f_len = fixed_len;
1401 s_len = string_len;
1402
1403 {
1404 char *lastname=NULL;
1405 int count2 = counted;
1406
1407 for (i = 0; i < total && count2;i++) {
1408 struct srv_info_struct *s = &servers[i];
1409
1410 if (lastname && strequal(lastname,s->name)) {
1411 continue;
1412 }
1413 lastname = s->name;
1414 fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
1415 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1416 s->name, s->type, s->comment, s->domain));
1417 count2--;
1418 }
1419 }
1420
1421 *rparam_len = 8;
1422 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1423 if (!*rparam) {
1424 return False;
1425 }
1426 SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERRmoredata));
1427 SSVAL(*rparam,2,0);
1428 SSVAL(*rparam,4,counted);
1429 SSVAL(*rparam,6,counted+missed);
1430
1431 SAFE_FREE(servers);
1432
1433 DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
1434 domain,uLevel,counted,counted+missed));
1435
1436 return True;
1437}
1438
1439/****************************************************************************
1440 command 0x34 - suspected of being a "Lookup Names" stub api
1441 ****************************************************************************/
1442
1443static BOOL api_RNetGroupGetUsers(connection_struct *conn, uint16 vuid,
1444 char *param, int tpscnt,
1445 char *data, int tdscnt,
1446 int mdrcnt, int mprcnt, char **rdata,
1447 char **rparam, int *rdata_len, int *rparam_len)
1448{
1449 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
1450 char *str2 = skip_string(param,tpscnt,str1);
1451 char *p = skip_string(param,tpscnt,str2);
1452 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
1453 int buf_len = get_safe_SVAL(param,tpscnt,p,2,0);
1454 int counted=0;
1455 int missed=0;
1456
1457 if (!str1 || !str2 || !p) {
1458 return False;
1459 }
1460
1461 DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
1462 str1, str2, p, uLevel, buf_len));
1463
1464 if (!prefix_ok(str1,"zWrLeh")) {
1465 return False;
1466 }
1467
1468 *rdata_len = 0;
1469
1470 *rparam_len = 8;
1471 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1472 if (!*rparam) {
1473 return False;
1474 }
1475
1476 SSVAL(*rparam,0,0x08AC); /* informational warning message */
1477 SSVAL(*rparam,2,0);
1478 SSVAL(*rparam,4,counted);
1479 SSVAL(*rparam,6,counted+missed);
1480
1481 return True;
1482}
1483
1484/****************************************************************************
1485 get info about a share
1486 ****************************************************************************/
1487
1488static BOOL check_share_info(int uLevel, char* id)
1489{
1490 switch( uLevel ) {
1491 case 0:
1492 if (strcmp(id,"B13") != 0) {
1493 return False;
1494 }
1495 break;
1496 case 1:
1497 if (strcmp(id,"B13BWz") != 0) {
1498 return False;
1499 }
1500 break;
1501 case 2:
1502 if (strcmp(id,"B13BWzWWWzB9B") != 0) {
1503 return False;
1504 }
1505 break;
1506 case 91:
1507 if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) {
1508 return False;
1509 }
1510 break;
1511 default:
1512 return False;
1513 }
1514 return True;
1515}
1516
1517static int fill_share_info(connection_struct *conn, int snum, int uLevel,
1518 char** buf, int* buflen,
1519 char** stringbuf, int* stringspace, char* baseaddr)
1520{
1521 int struct_len;
1522 char* p;
1523 char* p2;
1524 int l2;
1525 int len;
1526
1527 switch( uLevel ) {
1528 case 0:
1529 struct_len = 13;
1530 break;
1531 case 1:
1532 struct_len = 20;
1533 break;
1534 case 2:
1535 struct_len = 40;
1536 break;
1537 case 91:
1538 struct_len = 68;
1539 break;
1540 default:
1541 return -1;
1542 }
1543
1544
1545 if (!buf) {
1546 len = 0;
1547
1548 if (uLevel > 0) {
1549 len += StrlenExpanded(conn,snum,lp_comment(snum));
1550 }
1551 if (uLevel > 1) {
1552 len += strlen(lp_pathname(snum)) + 1;
1553 }
1554 if (buflen) {
1555 *buflen = struct_len;
1556 }
1557 if (stringspace) {
1558 *stringspace = len;
1559 }
1560 return struct_len + len;
1561 }
1562
1563 len = struct_len;
1564 p = *buf;
1565 if ((*buflen) < struct_len) {
1566 return -1;
1567 }
1568
1569 if (stringbuf) {
1570 p2 = *stringbuf;
1571 l2 = *stringspace;
1572 } else {
1573 p2 = p + struct_len;
1574 l2 = (*buflen) - struct_len;
1575 }
1576
1577 if (!baseaddr) {
1578 baseaddr = p;
1579 }
1580
1581 push_ascii(p,lp_servicename(snum),13, STR_TERMINATE);
1582
1583 if (uLevel > 0) {
1584 int type;
1585
1586 SCVAL(p,13,0);
1587 type = STYPE_DISKTREE;
1588 if (lp_print_ok(snum)) {
1589 type = STYPE_PRINTQ;
1590 }
1591 if (strequal("IPC",lp_fstype(snum))) {
1592 type = STYPE_IPC;
1593 }
1594 SSVAL(p,14,type); /* device type */
1595 SIVAL(p,16,PTR_DIFF(p2,baseaddr));
1596 len += CopyExpanded(conn,snum,&p2,lp_comment(snum),&l2);
1597 }
1598
1599 if (uLevel > 1) {
1600 SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */
1601 SSVALS(p,22,-1); /* max uses */
1602 SSVAL(p,24,1); /* current uses */
1603 SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */
1604 len += CopyAndAdvance(&p2,lp_pathname(snum),&l2);
1605 memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */
1606 }
1607
1608 if (uLevel > 2) {
1609 memset(p+40,0,SHPWLEN+2);
1610 SSVAL(p,50,0);
1611 SIVAL(p,52,0);
1612 SSVAL(p,56,0);
1613 SSVAL(p,58,0);
1614 SIVAL(p,60,0);
1615 SSVAL(p,64,0);
1616 SSVAL(p,66,0);
1617 }
1618
1619 if (stringbuf) {
1620 (*buf) = p + struct_len;
1621 (*buflen) -= struct_len;
1622 (*stringbuf) = p2;
1623 (*stringspace) = l2;
1624 } else {
1625 (*buf) = p2;
1626 (*buflen) -= len;
1627 }
1628
1629 return len;
1630}
1631
1632static BOOL api_RNetShareGetInfo(connection_struct *conn,uint16 vuid,
1633 char *param, int tpscnt,
1634 char *data, int tdscnt,
1635 int mdrcnt,int mprcnt,
1636 char **rdata,char **rparam,
1637 int *rdata_len,int *rparam_len)
1638{
1639 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
1640 char *str2 = skip_string(param,tpscnt,str1);
1641 char *netname = skip_string(param,tpscnt,str2);
1642 char *p = skip_string(param,tpscnt,netname);
1643 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
1644 int snum;
1645
1646 if (!str1 || !str2 || !netname || !p) {
1647 return False;
1648 }
1649
1650 snum = find_service(netname);
1651 if (snum < 0) {
1652 return False;
1653 }
1654
1655 /* check it's a supported varient */
1656 if (!prefix_ok(str1,"zWrLh")) {
1657 return False;
1658 }
1659 if (!check_share_info(uLevel,str2)) {
1660 return False;
1661 }
1662
1663 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
1664 if (!*rdata) {
1665 return False;
1666 }
1667 p = *rdata;
1668 *rdata_len = fill_share_info(conn,snum,uLevel,&p,&mdrcnt,0,0,0);
1669 if (*rdata_len < 0) {
1670 return False;
1671 }
1672
1673 *rparam_len = 6;
1674 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1675 if (!*rparam) {
1676 return False;
1677 }
1678 SSVAL(*rparam,0,NERR_Success);
1679 SSVAL(*rparam,2,0); /* converter word */
1680 SSVAL(*rparam,4,*rdata_len);
1681
1682 return True;
1683}
1684
1685/****************************************************************************
1686 View the list of available shares.
1687
1688 This function is the server side of the NetShareEnum() RAP call.
1689 It fills the return buffer with share names and share comments.
1690 Note that the return buffer normally (in all known cases) allows only
1691 twelve byte strings for share names (plus one for a nul terminator).
1692 Share names longer than 12 bytes must be skipped.
1693 ****************************************************************************/
1694
1695static BOOL api_RNetShareEnum( connection_struct *conn, uint16 vuid,
1696 char *param, int tpscnt,
1697 char *data, int tdscnt,
1698 int mdrcnt,
1699 int mprcnt,
1700 char **rdata,
1701 char **rparam,
1702 int *rdata_len,
1703 int *rparam_len )
1704{
1705 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
1706 char *str2 = skip_string(param,tpscnt,str1);
1707 char *p = skip_string(param,tpscnt,str2);
1708 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
1709 int buf_len = get_safe_SVAL(param,tpscnt,p,2,0);
1710 char *p2;
1711 int count = 0;
1712 int total=0,counted=0;
1713 BOOL missed = False;
1714 int i;
1715 int data_len, fixed_len, string_len;
1716 int f_len = 0, s_len = 0;
1717
1718 if (!str1 || !str2 || !p) {
1719 return False;
1720 }
1721
1722 if (!prefix_ok(str1,"WrLeh")) {
1723 return False;
1724 }
1725 if (!check_share_info(uLevel,str2)) {
1726 return False;
1727 }
1728
1729 /* Ensure all the usershares are loaded. */
1730 become_root();
1731 count = load_usershare_shares();
1732 unbecome_root();
1733
1734 data_len = fixed_len = string_len = 0;
1735 for (i=0;i<count;i++) {
1736 fstring servicename_dos;
1737 if (!(lp_browseable(i) && lp_snum_ok(i))) {
1738 continue;
1739 }
1740 push_ascii_fstring(servicename_dos, lp_servicename(i));
1741 /* Maximum name length = 13. */
1742 if( lp_browseable( i ) && lp_snum_ok( i ) && (strlen(servicename_dos) < 13)) {
1743 total++;
1744 data_len += fill_share_info(conn,i,uLevel,0,&f_len,0,&s_len,0);
1745 if (data_len <= buf_len) {
1746 counted++;
1747 fixed_len += f_len;
1748 string_len += s_len;
1749 } else {
1750 missed = True;
1751 }
1752 }
1753 }
1754
1755 *rdata_len = fixed_len + string_len;
1756 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
1757 if (!*rdata) {
1758 return False;
1759 }
1760 memset(*rdata,0,*rdata_len);
1761
1762 p2 = (*rdata) + fixed_len; /* auxiliary data (strings) will go here */
1763 p = *rdata;
1764 f_len = fixed_len;
1765 s_len = string_len;
1766
1767 for( i = 0; i < count; i++ ) {
1768 fstring servicename_dos;
1769 if (!(lp_browseable(i) && lp_snum_ok(i))) {
1770 continue;
1771 }
1772
1773 push_ascii_fstring(servicename_dos, lp_servicename(i));
1774 if (lp_browseable(i) && lp_snum_ok(i) && (strlen(servicename_dos) < 13)) {
1775 if (fill_share_info( conn,i,uLevel,&p,&f_len,&p2,&s_len,*rdata ) < 0) {
1776 break;
1777 }
1778 }
1779 }
1780
1781 *rparam_len = 8;
1782 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1783 if (!*rparam) {
1784 return False;
1785 }
1786 SSVAL(*rparam,0,missed ? ERRmoredata : NERR_Success);
1787 SSVAL(*rparam,2,0);
1788 SSVAL(*rparam,4,counted);
1789 SSVAL(*rparam,6,total);
1790
1791 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
1792 counted,total,uLevel,
1793 buf_len,*rdata_len,mdrcnt));
1794
1795 return True;
1796}
1797
1798/****************************************************************************
1799 Add a share
1800 ****************************************************************************/
1801
1802static BOOL api_RNetShareAdd(connection_struct *conn,uint16 vuid,
1803 char *param, int tpscnt,
1804 char *data, int tdscnt,
1805 int mdrcnt,int mprcnt,
1806 char **rdata,char **rparam,
1807 int *rdata_len,int *rparam_len)
1808{
1809 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
1810 char *str2 = skip_string(param,tpscnt,str1);
1811 char *p = skip_string(param,tpscnt,str2);
1812 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
1813 fstring sharename;
1814 fstring comment;
1815 pstring pathname;
1816 char *command, *cmdname;
1817 unsigned int offset;
1818 int snum;
1819 int res = ERRunsup;
1820
1821 if (!str1 || !str2 || !p) {
1822 return False;
1823 }
1824
1825 /* check it's a supported varient */
1826 if (!prefix_ok(str1,RAP_WShareAdd_REQ)) {
1827 return False;
1828 }
1829 if (!check_share_info(uLevel,str2)) {
1830 return False;
1831 }
1832 if (uLevel != 2) {
1833 return False;
1834 }
1835
1836 /* Do we have a string ? */
1837 if (skip_string(data,mdrcnt,data) == NULL) {
1838 return False;
1839 }
1840 pull_ascii_fstring(sharename,data);
1841 snum = find_service(sharename);
1842 if (snum >= 0) { /* already exists */
1843 res = ERRfilexists;
1844 goto error_exit;
1845 }
1846
1847 if (mdrcnt < 28) {
1848 return False;
1849 }
1850
1851 /* only support disk share adds */
1852 if (SVAL(data,14)!=STYPE_DISKTREE) {
1853 return False;
1854 }
1855
1856 offset = IVAL(data, 16);
1857 if (offset >= mdrcnt) {
1858 res = ERRinvalidparam;
1859 goto error_exit;
1860 }
1861
1862 /* Do we have a string ? */
1863 if (skip_string(data,mdrcnt,data+offset) == NULL) {
1864 return False;
1865 }
1866 pull_ascii_fstring(comment, offset? (data+offset) : "");
1867
1868 offset = IVAL(data, 26);
1869
1870 if (offset >= mdrcnt) {
1871 res = ERRinvalidparam;
1872 goto error_exit;
1873 }
1874
1875 /* Do we have a string ? */
1876 if (skip_string(data,mdrcnt,data+offset) == NULL) {
1877 return False;
1878 }
1879 pull_ascii_pstring(pathname, offset? (data+offset) : "");
1880
1881 string_replace(sharename, '"', ' ');
1882 string_replace(pathname, '"', ' ');
1883 string_replace(comment, '"', ' ');
1884
1885 cmdname = lp_add_share_cmd();
1886
1887 if (!cmdname || *cmdname == '\0') {
1888 return False;
1889 }
1890
1891 asprintf(&command, "%s \"%s\" \"%s\" \"%s\" \"%s\"",
1892 lp_add_share_cmd(), dyn_CONFIGFILE, sharename, pathname, comment);
1893
1894 if (command) {
1895 DEBUG(10,("api_RNetShareAdd: Running [%s]\n", command ));
1896
1897 if ((res = smbrun(command, NULL)) != 0) {
1898 DEBUG(1,("api_RNetShareAdd: Running [%s] returned (%d)\n", command, res ));
1899 SAFE_FREE(command);
1900 res = ERRnoaccess;
1901 goto error_exit;
1902 } else {
1903 SAFE_FREE(command);
1904 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
1905 }
1906 } else {
1907 return False;
1908 }
1909
1910 *rparam_len = 6;
1911 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1912 if (!*rparam) {
1913 return False;
1914 }
1915 SSVAL(*rparam,0,NERR_Success);
1916 SSVAL(*rparam,2,0); /* converter word */
1917 SSVAL(*rparam,4,*rdata_len);
1918 *rdata_len = 0;
1919
1920 return True;
1921
1922 error_exit:
1923
1924 *rparam_len = 4;
1925 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1926 if (!*rparam) {
1927 return False;
1928 }
1929 *rdata_len = 0;
1930 SSVAL(*rparam,0,res);
1931 SSVAL(*rparam,2,0);
1932 return True;
1933}
1934
1935/****************************************************************************
1936 view list of groups available
1937 ****************************************************************************/
1938
1939static BOOL api_RNetGroupEnum(connection_struct *conn,uint16 vuid,
1940 char *param, int tpscnt,
1941 char *data, int tdscnt,
1942 int mdrcnt,int mprcnt,
1943 char **rdata,char **rparam,
1944 int *rdata_len,int *rparam_len)
1945{
1946 int i;
1947 int errflags=0;
1948 int resume_context, cli_buf_size;
1949 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
1950 char *str2 = skip_string(param,tpscnt,str1);
1951 char *p = skip_string(param,tpscnt,str2);
1952
1953 struct pdb_search *search;
1954 struct samr_displayentry *entries;
1955
1956 int num_entries;
1957
1958 if (!str1 || !str2 || !p) {
1959 return False;
1960 }
1961
1962 if (strcmp(str1,"WrLeh") != 0) {
1963 return False;
1964 }
1965
1966 /* parameters
1967 * W-> resume context (number of users to skip)
1968 * r -> return parameter pointer to receive buffer
1969 * L -> length of receive buffer
1970 * e -> return parameter number of entries
1971 * h -> return parameter total number of users
1972 */
1973
1974 if (strcmp("B21",str2) != 0) {
1975 return False;
1976 }
1977
1978 /* get list of domain groups SID_DOMAIN_GRP=2 */
1979 become_root();
1980 search = pdb_search_groups();
1981 unbecome_root();
1982
1983 if (search == NULL) {
1984 DEBUG(3,("api_RNetGroupEnum:failed to get group list"));
1985 return False;
1986 }
1987
1988 resume_context = get_safe_SVAL(param,tpscnt,p,0,-1);
1989 cli_buf_size= get_safe_SVAL(param,tpscnt,p,2,0);
1990 DEBUG(10,("api_RNetGroupEnum:resume context: %d, client buffer size: "
1991 "%d\n", resume_context, cli_buf_size));
1992
1993 become_root();
1994 num_entries = pdb_search_entries(search, resume_context, 0xffffffff,
1995 &entries);
1996 unbecome_root();
1997
1998 *rdata_len = cli_buf_size;
1999 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
2000 if (!*rdata) {
2001 return False;
2002 }
2003
2004 p = *rdata;
2005
2006 for(i=0; i<num_entries; i++) {
2007 fstring name;
2008 fstrcpy(name, entries[i].account_name);
2009 if( ((PTR_DIFF(p,*rdata)+21) <= *rdata_len) ) {
2010 /* truncate the name at 21 chars. */
2011 memcpy(p, name, 21);
2012 DEBUG(10,("adding entry %d group %s\n", i, p));
2013 p += 21;
2014 p += 5; /* Both NT4 and W2k3SP1 do padding here.
2015 No idea why... */
2016 } else {
2017 /* set overflow error */
2018 DEBUG(3,("overflow on entry %d group %s\n", i, name));
2019 errflags=234;
2020 break;
2021 }
2022 }
2023
2024 pdb_search_destroy(search);
2025
2026 *rdata_len = PTR_DIFF(p,*rdata);
2027
2028 *rparam_len = 8;
2029 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2030 if (!*rparam) {
2031 return False;
2032 }
2033 SSVAL(*rparam, 0, errflags);
2034 SSVAL(*rparam, 2, 0); /* converter word */
2035 SSVAL(*rparam, 4, i); /* is this right?? */
2036 SSVAL(*rparam, 6, resume_context+num_entries); /* is this right?? */
2037
2038 return(True);
2039}
2040
2041/*******************************************************************
2042 Get groups that a user is a member of.
2043******************************************************************/
2044
2045static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid,
2046 char *param, int tpscnt,
2047 char *data, int tdscnt,
2048 int mdrcnt,int mprcnt,
2049 char **rdata,char **rparam,
2050 int *rdata_len,int *rparam_len)
2051{
2052 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2053 char *str2 = skip_string(param,tpscnt,str1);
2054 char *UserName = skip_string(param,tpscnt,str2);
2055 char *p = skip_string(param,tpscnt,UserName);
2056 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
2057 const char *level_string;
2058 int count=0;
2059 struct samu *sampw = NULL;
2060 BOOL ret = False;
2061 DOM_SID *sids;
2062 gid_t *gids;
2063 size_t num_groups;
2064 size_t i;
2065 NTSTATUS result;
2066 DOM_SID user_sid;
2067 enum lsa_SidType type;
2068 TALLOC_CTX *mem_ctx;
2069
2070 if (!str1 || !str2 || !UserName || !p) {
2071 return False;
2072 }
2073
2074 *rparam_len = 8;
2075 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2076 if (!*rparam) {
2077 return False;
2078 }
2079
2080 /* check it's a supported varient */
2081
2082 if ( strcmp(str1,"zWrLeh") != 0 )
2083 return False;
2084
2085 switch( uLevel ) {
2086 case 0:
2087 level_string = "B21";
2088 break;
2089 default:
2090 return False;
2091 }
2092
2093 if (strcmp(level_string,str2) != 0)
2094 return False;
2095
2096 *rdata_len = mdrcnt + 1024;
2097 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
2098 if (!*rdata) {
2099 return False;
2100 }
2101 SSVAL(*rparam,0,NERR_Success);
2102 SSVAL(*rparam,2,0); /* converter word */
2103
2104 p = *rdata;
2105
2106 mem_ctx = talloc_new(NULL);
2107 if (mem_ctx == NULL) {
2108 DEBUG(0, ("talloc_new failed\n"));
2109 return False;
2110 }
2111
2112 if ( !(sampw = samu_new(mem_ctx)) ) {
2113 DEBUG(0, ("samu_new() failed!\n"));
2114 TALLOC_FREE(mem_ctx);
2115 return False;
2116 }
2117
2118 /* Lookup the user information; This should only be one of
2119 our accounts (not remote domains) */
2120
2121 become_root(); /* ROOT BLOCK */
2122
2123 if (!lookup_name(mem_ctx, UserName, LOOKUP_NAME_ALL,
2124 NULL, NULL, &user_sid, &type)) {
2125 DEBUG(10, ("lookup_name(%s) failed\n", UserName));
2126 goto done;
2127 }
2128
2129 if (type != SID_NAME_USER) {
2130 DEBUG(10, ("%s is a %s, not a user\n", UserName,
2131 sid_type_lookup(type)));
2132 goto done;
2133 }
2134
2135 if ( !pdb_getsampwsid(sampw, &user_sid) ) {
2136 DEBUG(10, ("pdb_getsampwsid(%s) failed for user %s\n",
2137 sid_string_static(&user_sid), UserName));
2138 goto done;
2139 }
2140
2141 gids = NULL;
2142 sids = NULL;
2143 num_groups = 0;
2144
2145 result = pdb_enum_group_memberships(mem_ctx, sampw,
2146 &sids, &gids, &num_groups);
2147
2148 if (!NT_STATUS_IS_OK(result)) {
2149 DEBUG(10, ("pdb_enum_group_memberships failed for %s\n",
2150 UserName));
2151 goto done;
2152 }
2153
2154 for (i=0; i<num_groups; i++) {
2155
2156 const char *grp_name;
2157
2158 if ( lookup_sid(mem_ctx, &sids[i], NULL, &grp_name, NULL) ) {
2159 pstrcpy(p, grp_name);
2160 p += 21;
2161 count++;
2162 }
2163 }
2164
2165 *rdata_len = PTR_DIFF(p,*rdata);
2166
2167 SSVAL(*rparam,4,count); /* is this right?? */
2168 SSVAL(*rparam,6,count); /* is this right?? */
2169
2170 ret = True;
2171
2172done:
2173 unbecome_root(); /* END ROOT BLOCK */
2174
2175 TALLOC_FREE(mem_ctx);
2176
2177 return ret;
2178}
2179
2180/*******************************************************************
2181 Get all users.
2182******************************************************************/
2183
2184static BOOL api_RNetUserEnum(connection_struct *conn, uint16 vuid,
2185 char *param, int tpscnt,
2186 char *data, int tdscnt,
2187 int mdrcnt,int mprcnt,
2188 char **rdata,char **rparam,
2189 int *rdata_len,int *rparam_len)
2190{
2191 int count_sent=0;
2192 int num_users=0;
2193 int errflags=0;
2194 int i, resume_context, cli_buf_size;
2195 struct pdb_search *search;
2196 struct samr_displayentry *users;
2197
2198 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2199 char *str2 = skip_string(param,tpscnt,str1);
2200 char *p = skip_string(param,tpscnt,str2);
2201
2202 if (!str1 || !str2 || !p) {
2203 return False;
2204 }
2205
2206 if (strcmp(str1,"WrLeh") != 0)
2207 return False;
2208 /* parameters
2209 * W-> resume context (number of users to skip)
2210 * r -> return parameter pointer to receive buffer
2211 * L -> length of receive buffer
2212 * e -> return parameter number of entries
2213 * h -> return parameter total number of users
2214 */
2215
2216 resume_context = get_safe_SVAL(param,tpscnt,p,0,-1);
2217 cli_buf_size= get_safe_SVAL(param,tpscnt,p,2,0);
2218 DEBUG(10,("api_RNetUserEnum:resume context: %d, client buffer size: %d\n",
2219 resume_context, cli_buf_size));
2220
2221 *rparam_len = 8;
2222 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2223 if (!*rparam) {
2224 return False;
2225 }
2226
2227 /* check it's a supported varient */
2228 if (strcmp("B21",str2) != 0)
2229 return False;
2230
2231 *rdata_len = cli_buf_size;
2232 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
2233 if (!*rdata) {
2234 return False;
2235 }
2236
2237 p = *rdata;
2238
2239 become_root();
2240 search = pdb_search_users(ACB_NORMAL);
2241 unbecome_root();
2242 if (search == NULL) {
2243 DEBUG(0, ("api_RNetUserEnum:unable to open sam database.\n"));
2244 return False;
2245 }
2246
2247 become_root();
2248 num_users = pdb_search_entries(search, resume_context, 0xffffffff,
2249 &users);
2250 unbecome_root();
2251
2252 errflags=NERR_Success;
2253
2254 for (i=0; i<num_users; i++) {
2255 const char *name = users[i].account_name;
2256
2257 if(((PTR_DIFF(p,*rdata)+21)<=*rdata_len)&&(strlen(name)<=21)) {
2258 pstrcpy(p,name);
2259 DEBUG(10,("api_RNetUserEnum:adding entry %d username "
2260 "%s\n",count_sent,p));
2261 p += 21;
2262 count_sent++;
2263 } else {
2264 /* set overflow error */
2265 DEBUG(10,("api_RNetUserEnum:overflow on entry %d "
2266 "username %s\n",count_sent,name));
2267 errflags=234;
2268 break;
2269 }
2270 }
2271
2272 pdb_search_destroy(search);
2273
2274 *rdata_len = PTR_DIFF(p,*rdata);
2275
2276 SSVAL(*rparam,0,errflags);
2277 SSVAL(*rparam,2,0); /* converter word */
2278 SSVAL(*rparam,4,count_sent); /* is this right?? */
2279 SSVAL(*rparam,6,num_users); /* is this right?? */
2280
2281 return True;
2282}
2283
2284/****************************************************************************
2285 Get the time of day info.
2286****************************************************************************/
2287
2288static BOOL api_NetRemoteTOD(connection_struct *conn,uint16 vuid,
2289 char *param, int tpscnt,
2290 char *data, int tdscnt,
2291 int mdrcnt,int mprcnt,
2292 char **rdata,char **rparam,
2293 int *rdata_len,int *rparam_len)
2294{
2295 struct tm *t;
2296 time_t unixdate = time(NULL);
2297 char *p;
2298
2299 *rparam_len = 4;
2300 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2301 if (!*rparam) {
2302 return False;
2303 }
2304
2305 *rdata_len = 21;
2306 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
2307 if (!*rdata) {
2308 return False;
2309 }
2310
2311 SSVAL(*rparam,0,NERR_Success);
2312 SSVAL(*rparam,2,0); /* converter word */
2313
2314 p = *rdata;
2315
2316 srv_put_dos_date3(p,0,unixdate); /* this is the time that is looked at
2317 by NT in a "net time" operation,
2318 it seems to ignore the one below */
2319
2320 /* the client expects to get localtime, not GMT, in this bit
2321 (I think, this needs testing) */
2322 t = localtime(&unixdate);
2323 if (!t) {
2324 return False;
2325 }
2326
2327 SIVAL(p,4,0); /* msecs ? */
2328 SCVAL(p,8,t->tm_hour);
2329 SCVAL(p,9,t->tm_min);
2330 SCVAL(p,10,t->tm_sec);
2331 SCVAL(p,11,0); /* hundredths of seconds */
2332 SSVALS(p,12,get_time_zone(unixdate)/60); /* timezone in minutes from GMT */
2333 SSVAL(p,14,10000); /* timer interval in 0.0001 of sec */
2334 SCVAL(p,16,t->tm_mday);
2335 SCVAL(p,17,t->tm_mon + 1);
2336 SSVAL(p,18,1900+t->tm_year);
2337 SCVAL(p,20,t->tm_wday);
2338
2339 return True;
2340}
2341
2342/****************************************************************************
2343 Set the user password.
2344*****************************************************************************/
2345
2346static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid,
2347 char *param, int tpscnt,
2348 char *data, int tdscnt,
2349 int mdrcnt,int mprcnt,
2350 char **rdata,char **rparam,
2351 int *rdata_len,int *rparam_len)
2352{
2353 char *np = get_safe_str_ptr(param,tpscnt,param,2);
2354 char *p = NULL;
2355 fstring user;
2356 fstring pass1,pass2;
2357
2358 /* Skip 2 strings. */
2359 p = skip_string(param,tpscnt,np);
2360 p = skip_string(param,tpscnt,p);
2361
2362 if (!np || !p) {
2363 return False;
2364 }
2365
2366 /* Do we have a string ? */
2367 if (skip_string(param,tpscnt,p) == NULL) {
2368 return False;
2369 }
2370 pull_ascii_fstring(user,p);
2371
2372 p = skip_string(param,tpscnt,p);
2373 if (!p) {
2374 return False;
2375 }
2376
2377 memset(pass1,'\0',sizeof(pass1));
2378 memset(pass2,'\0',sizeof(pass2));
2379 /*
2380 * We use 31 here not 32 as we're checking
2381 * the last byte we want to access is safe.
2382 */
2383 if (!is_offset_safe(param,tpscnt,p,31)) {
2384 return False;
2385 }
2386 memcpy(pass1,p,16);
2387 memcpy(pass2,p+16,16);
2388
2389 *rparam_len = 4;
2390 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2391 if (!*rparam) {
2392 return False;
2393 }
2394
2395 *rdata_len = 0;
2396
2397 SSVAL(*rparam,0,NERR_badpass);
2398 SSVAL(*rparam,2,0); /* converter word */
2399
2400 DEBUG(3,("Set password for <%s>\n",user));
2401
2402 /*
2403 * Attempt to verify the old password against smbpasswd entries
2404 * Win98 clients send old and new password in plaintext for this call.
2405 */
2406
2407 {
2408 auth_serversupplied_info *server_info = NULL;
2409 DATA_BLOB password = data_blob(pass1, strlen(pass1)+1);
2410
2411 if (NT_STATUS_IS_OK(check_plaintext_password(user,password,&server_info))) {
2412
2413 become_root();
2414 if (NT_STATUS_IS_OK(change_oem_password(server_info->sam_account, pass1, pass2, False, NULL))) {
2415 SSVAL(*rparam,0,NERR_Success);
2416 }
2417 unbecome_root();
2418
2419 TALLOC_FREE(server_info);
2420 }
2421 data_blob_clear_free(&password);
2422 }
2423
2424 /*
2425 * If the plaintext change failed, attempt
2426 * the old encrypted method. NT will generate this
2427 * after trying the samr method. Note that this
2428 * method is done as a last resort as this
2429 * password change method loses the NT password hash
2430 * and cannot change the UNIX password as no plaintext
2431 * is received.
2432 */
2433
2434 if(SVAL(*rparam,0) != NERR_Success) {
2435 struct samu *hnd = NULL;
2436
2437 if (check_lanman_password(user,(unsigned char *)pass1,(unsigned char *)pass2, &hnd)) {
2438 become_root();
2439 if (change_lanman_password(hnd,(uchar *)pass2)) {
2440 SSVAL(*rparam,0,NERR_Success);
2441 }
2442 unbecome_root();
2443 TALLOC_FREE(hnd);
2444 }
2445 }
2446
2447 memset((char *)pass1,'\0',sizeof(fstring));
2448 memset((char *)pass2,'\0',sizeof(fstring));
2449
2450 return(True);
2451}
2452
2453/****************************************************************************
2454 Set the user password (SamOEM version - gets plaintext).
2455****************************************************************************/
2456
2457static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid,
2458 char *param, int tpscnt,
2459 char *data, int tdscnt,
2460 int mdrcnt,int mprcnt,
2461 char **rdata,char **rparam,
2462 int *rdata_len,int *rparam_len)
2463{
2464 fstring user;
2465 char *p = get_safe_str_ptr(param,tpscnt,param,2);
2466 *rparam_len = 2;
2467 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2468 if (!*rparam) {
2469 return False;
2470 }
2471
2472 if (!p) {
2473 return False;
2474 }
2475 *rdata_len = 0;
2476
2477 SSVAL(*rparam,0,NERR_badpass);
2478
2479 /*
2480 * Check the parameter definition is correct.
2481 */
2482
2483 /* Do we have a string ? */
2484 if (skip_string(param,tpscnt,p) == 0) {
2485 return False;
2486 }
2487 if(!strequal(p, "zsT")) {
2488 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", p));
2489 return False;
2490 }
2491 p = skip_string(param, tpscnt, p);
2492 if (!p) {
2493 return False;
2494 }
2495
2496 /* Do we have a string ? */
2497 if (skip_string(param,tpscnt,p) == 0) {
2498 return False;
2499 }
2500 if(!strequal(p, "B516B16")) {
2501 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p));
2502 return False;
2503 }
2504 p = skip_string(param,tpscnt,p);
2505 if (!p) {
2506 return False;
2507 }
2508 /* Do we have a string ? */
2509 if (skip_string(param,tpscnt,p) == 0) {
2510 return False;
2511 }
2512 p += pull_ascii_fstring(user,p);
2513
2514 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user));
2515
2516 /*
2517 * Pass the user through the NT -> unix user mapping
2518 * function.
2519 */
2520
2521 (void)map_username(user);
2522
2523 if (NT_STATUS_IS_OK(pass_oem_change(user, (uchar*) data, (uchar *)&data[516], NULL, NULL, NULL))) {
2524 SSVAL(*rparam,0,NERR_Success);
2525 }
2526
2527 return(True);
2528}
2529
2530/****************************************************************************
2531 delete a print job
2532 Form: <W> <>
2533 ****************************************************************************/
2534
2535static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid,
2536 char *param, int tpscnt,
2537 char *data, int tdscnt,
2538 int mdrcnt,int mprcnt,
2539 char **rdata,char **rparam,
2540 int *rdata_len,int *rparam_len)
2541{
2542 int function = get_safe_SVAL(param,tpscnt,param,0,0);
2543 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2544 char *str2 = skip_string(param,tpscnt,str1);
2545 char *p = skip_string(param,tpscnt,str2);
2546 uint32 jobid;
2547 int snum;
2548 fstring sharename;
2549 int errcode;
2550 WERROR werr = WERR_OK;
2551
2552 if (!str1 || !str2 || !p) {
2553 return False;
2554 }
2555 /*
2556 * We use 1 here not 2 as we're checking
2557 * the last byte we want to access is safe.
2558 */
2559 if (!is_offset_safe(param,tpscnt,p,1)) {
2560 return False;
2561 }
2562 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid))
2563 return False;
2564
2565 /* check it's a supported varient */
2566 if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
2567 return(False);
2568
2569 *rparam_len = 4;
2570 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2571 if (!*rparam) {
2572 return False;
2573 }
2574 *rdata_len = 0;
2575
2576 if (!print_job_exists(sharename, jobid)) {
2577 errcode = NERR_JobNotFound;
2578 goto out;
2579 }
2580
2581 snum = lp_servicenumber( sharename);
2582 if (snum == -1) {
2583 errcode = NERR_DestNotFound;
2584 goto out;
2585 }
2586
2587 errcode = NERR_notsupported;
2588
2589 switch (function) {
2590 case 81: /* delete */
2591 if (print_job_delete(&current_user, snum, jobid, &werr))
2592 errcode = NERR_Success;
2593 break;
2594 case 82: /* pause */
2595 if (print_job_pause(&current_user, snum, jobid, &werr))
2596 errcode = NERR_Success;
2597 break;
2598 case 83: /* resume */
2599 if (print_job_resume(&current_user, snum, jobid, &werr))
2600 errcode = NERR_Success;
2601 break;
2602 }
2603
2604 if (!W_ERROR_IS_OK(werr))
2605 errcode = W_ERROR_V(werr);
2606
2607 out:
2608 SSVAL(*rparam,0,errcode);
2609 SSVAL(*rparam,2,0); /* converter word */
2610
2611 return(True);
2612}
2613
2614/****************************************************************************
2615 Purge a print queue - or pause or resume it.
2616 ****************************************************************************/
2617
2618static BOOL api_WPrintQueueCtrl(connection_struct *conn,uint16 vuid,
2619 char *param, int tpscnt,
2620 char *data, int tdscnt,
2621 int mdrcnt,int mprcnt,
2622 char **rdata,char **rparam,
2623 int *rdata_len,int *rparam_len)
2624{
2625 int function = get_safe_SVAL(param,tpscnt,param,0,0);
2626 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2627 char *str2 = skip_string(param,tpscnt,str1);
2628 char *QueueName = skip_string(param,tpscnt,str2);
2629 int errcode = NERR_notsupported;
2630 int snum;
2631 WERROR werr = WERR_OK;
2632
2633 if (!str1 || !str2 || !QueueName) {
2634 return False;
2635 }
2636
2637 /* check it's a supported varient */
2638 if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
2639 return(False);
2640
2641 *rparam_len = 4;
2642 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2643 if (!*rparam) {
2644 return False;
2645 }
2646 *rdata_len = 0;
2647
2648 if (skip_string(param,tpscnt,QueueName) == NULL) {
2649 return False;
2650 }
2651 snum = print_queue_snum(QueueName);
2652
2653 if (snum == -1) {
2654 errcode = NERR_JobNotFound;
2655 goto out;
2656 }
2657
2658 switch (function) {
2659 case 74: /* Pause queue */
2660 if (print_queue_pause(&current_user, snum, &werr)) errcode = NERR_Success;
2661 break;
2662 case 75: /* Resume queue */
2663 if (print_queue_resume(&current_user, snum, &werr)) errcode = NERR_Success;
2664 break;
2665 case 103: /* Purge */
2666 if (print_queue_purge(&current_user, snum, &werr)) errcode = NERR_Success;
2667 break;
2668 }
2669
2670 if (!W_ERROR_IS_OK(werr)) errcode = W_ERROR_V(werr);
2671
2672 out:
2673 SSVAL(*rparam,0,errcode);
2674 SSVAL(*rparam,2,0); /* converter word */
2675
2676 return(True);
2677}
2678
2679/****************************************************************************
2680 set the property of a print job (undocumented?)
2681 ? function = 0xb -> set name of print job
2682 ? function = 0x6 -> move print job up/down
2683 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
2684 or <WWsTP> <WB21BB16B10zWWzDDz>
2685****************************************************************************/
2686
2687static int check_printjob_info(struct pack_desc* desc,
2688 int uLevel, char* id)
2689{
2690 desc->subformat = NULL;
2691 switch( uLevel ) {
2692 case 0: desc->format = "W"; break;
2693 case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
2694 case 2: desc->format = "WWzWWDDzz"; break;
2695 case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
2696 case 4: desc->format = "WWzWWDDzzzzzDDDDDDD"; break;
2697 default:
2698 DEBUG(0,("check_printjob_info: invalid level %d\n",
2699 uLevel ));
2700 return False;
2701 }
2702 if (id == NULL || strcmp(desc->format,id) != 0) {
2703 DEBUG(0,("check_printjob_info: invalid format %s\n",
2704 id ? id : "<NULL>" ));
2705 return False;
2706 }
2707 return True;
2708}
2709
2710static BOOL api_PrintJobInfo(connection_struct *conn, uint16 vuid,
2711 char *param, int tpscnt,
2712 char *data, int tdscnt,
2713 int mdrcnt,int mprcnt,
2714 char **rdata,char **rparam,
2715 int *rdata_len,int *rparam_len)
2716{
2717 struct pack_desc desc;
2718 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2719 char *str2 = skip_string(param,tpscnt,str1);
2720 char *p = skip_string(param,tpscnt,str2);
2721 uint32 jobid;
2722 fstring sharename;
2723 int uLevel = get_safe_SVAL(param,tpscnt,p,2,-1);
2724 int function = get_safe_SVAL(param,tpscnt,p,4,-1);
2725 int place, errcode;
2726
2727 if (!str1 || !str2 || !p) {
2728 return False;
2729 }
2730 /*
2731 * We use 1 here not 2 as we're checking
2732 * the last byte we want to access is safe.
2733 */
2734 if (!is_offset_safe(param,tpscnt,p,1)) {
2735 return False;
2736 }
2737 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid))
2738 return False;
2739 *rparam_len = 4;
2740 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2741 if (!*rparam) {
2742 return False;
2743 }
2744
2745 if (!share_defined(sharename)) {
2746 DEBUG(0,("api_PrintJobInfo: sharen [%s] not defined\n",
2747 sharename));
2748 return False;
2749 }
2750
2751 *rdata_len = 0;
2752
2753 /* check it's a supported varient */
2754 if ((strcmp(str1,"WWsTP")) ||
2755 (!check_printjob_info(&desc,uLevel,str2)))
2756 return(False);
2757
2758 if (!print_job_exists(sharename, jobid)) {
2759 errcode=NERR_JobNotFound;
2760 goto out;
2761 }
2762
2763 errcode = NERR_notsupported;
2764
2765 switch (function) {
2766 case 0x6:
2767 /* change job place in the queue,
2768 data gives the new place */
2769 place = SVAL(data,0);
2770 if (print_job_set_place(sharename, jobid, place)) {
2771 errcode=NERR_Success;
2772 }
2773 break;
2774
2775 case 0xb:
2776 /* change print job name, data gives the name */
2777 if (print_job_set_name(sharename, jobid, data)) {
2778 errcode=NERR_Success;
2779 }
2780 break;
2781
2782 default:
2783 return False;
2784 }
2785
2786 out:
2787 SSVALS(*rparam,0,errcode);
2788 SSVAL(*rparam,2,0); /* converter word */
2789
2790 return(True);
2791}
2792
2793
2794/****************************************************************************
2795 Get info about the server.
2796****************************************************************************/
2797
2798static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid,
2799 char *param, int tpscnt,
2800 char *data, int tdscnt,
2801 int mdrcnt,int mprcnt,
2802 char **rdata,char **rparam,
2803 int *rdata_len,int *rparam_len)
2804{
2805 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2806 char *str2 = skip_string(param,tpscnt,str1);
2807 char *p = skip_string(param,tpscnt,str2);
2808 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
2809 char *p2;
2810 int struct_len;
2811
2812 if (!str1 || !str2 || !p) {
2813 return False;
2814 }
2815
2816 DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
2817
2818 /* check it's a supported varient */
2819 if (!prefix_ok(str1,"WrLh")) {
2820 return False;
2821 }
2822
2823 switch( uLevel ) {
2824 case 0:
2825 if (strcmp(str2,"B16") != 0) {
2826 return False;
2827 }
2828 struct_len = 16;
2829 break;
2830 case 1:
2831 if (strcmp(str2,"B16BBDz") != 0) {
2832 return False;
2833 }
2834 struct_len = 26;
2835 break;
2836 case 2:
2837 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")!= 0) {
2838 return False;
2839 }
2840 struct_len = 134;
2841 break;
2842 case 3:
2843 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz") != 0) {
2844 return False;
2845 }
2846 struct_len = 144;
2847 break;
2848 case 20:
2849 if (strcmp(str2,"DN") != 0) {
2850 return False;
2851 }
2852 struct_len = 6;
2853 break;
2854 case 50:
2855 if (strcmp(str2,"B16BBDzWWzzz") != 0) {
2856 return False;
2857 }
2858 struct_len = 42;
2859 break;
2860 default:
2861 return False;
2862 }
2863
2864 *rdata_len = mdrcnt;
2865 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
2866 if (!*rdata) {
2867 return False;
2868 }
2869
2870 p = *rdata;
2871 p2 = p + struct_len;
2872 if (uLevel != 20) {
2873 srvstr_push(NULL, p,global_myname(),16,
2874 STR_ASCII|STR_UPPER|STR_TERMINATE);
2875 }
2876 p += 16;
2877 if (uLevel > 0) {
2878 struct srv_info_struct *servers=NULL;
2879 int i,count;
2880 pstring comment;
2881 uint32 servertype= lp_default_server_announce();
2882
2883 push_ascii(comment,lp_serverstring(), MAX_SERVER_STRING_LENGTH,STR_TERMINATE);
2884
2885 if ((count=get_server_info(SV_TYPE_ALL,&servers,lp_workgroup()))>0) {
2886 for (i=0;i<count;i++) {
2887 if (strequal(servers[i].name,global_myname())) {
2888 servertype = servers[i].type;
2889 push_ascii(comment,servers[i].comment,sizeof(pstring),STR_TERMINATE);
2890 }
2891 }
2892 }
2893
2894 SAFE_FREE(servers);
2895
2896 SCVAL(p,0,lp_major_announce_version());
2897 SCVAL(p,1,lp_minor_announce_version());
2898 SIVAL(p,2,servertype);
2899
2900 if (mdrcnt == struct_len) {
2901 SIVAL(p,6,0);
2902 } else {
2903 SIVAL(p,6,PTR_DIFF(p2,*rdata));
2904 standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
2905 conn->connectpath, conn->gid,
2906 get_current_username(),
2907 current_user_info.domain,
2908 comment, sizeof(comment));
2909 StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0));
2910 p2 = skip_string(*rdata,*rdata_len,p2);
2911 if (!p2) {
2912 return False;
2913 }
2914 }
2915 }
2916
2917 if (uLevel > 1) {
2918 return False; /* not yet implemented */
2919 }
2920
2921 *rdata_len = PTR_DIFF(p2,*rdata);
2922
2923 *rparam_len = 6;
2924 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2925 if (!*rparam) {
2926 return False;
2927 }
2928 SSVAL(*rparam,0,NERR_Success);
2929 SSVAL(*rparam,2,0); /* converter word */
2930 SSVAL(*rparam,4,*rdata_len);
2931
2932 return True;
2933}
2934
2935/****************************************************************************
2936 Get info about the server.
2937****************************************************************************/
2938
2939static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid,
2940 char *param, int tpscnt,
2941 char *data, int tdscnt,
2942 int mdrcnt,int mprcnt,
2943 char **rdata,char **rparam,
2944 int *rdata_len,int *rparam_len)
2945{
2946 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2947 char *str2 = skip_string(param,tpscnt,str1);
2948 char *p = skip_string(param,tpscnt,str2);
2949 char *p2;
2950 int level = get_safe_SVAL(param,tpscnt,p,0,-1);
2951
2952 if (!str1 || !str2 || !p) {
2953 return False;
2954 }
2955
2956 DEBUG(4,("NetWkstaGetInfo level %d\n",level));
2957
2958 *rparam_len = 6;
2959 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2960 if (!*rparam) {
2961 return False;
2962 }
2963
2964 /* check it's a supported varient */
2965 if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz"))) {
2966 return False;
2967 }
2968
2969 *rdata_len = mdrcnt + 1024;
2970 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
2971 if (!*rdata) {
2972 return False;
2973 }
2974
2975 SSVAL(*rparam,0,NERR_Success);
2976 SSVAL(*rparam,2,0); /* converter word */
2977
2978 p = *rdata;
2979 p2 = get_safe_ptr(*rdata,*rdata_len,p,22);
2980 if (!p2) {
2981 return False;
2982 }
2983
2984 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */
2985 pstrcpy(p2,get_local_machine_name());
2986 strupper_m(p2);
2987 p2 = skip_string(*rdata,*rdata_len,p2);
2988 if (!p2) {
2989 return False;
2990 }
2991 p += 4;
2992
2993 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2994 pstrcpy(p2,current_user_info.smb_name);
2995 p2 = skip_string(*rdata,*rdata_len,p2);
2996 if (!p2) {
2997 return False;
2998 }
2999 p += 4;
3000
3001 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
3002 pstrcpy(p2,lp_workgroup());
3003 strupper_m(p2);
3004 p2 = skip_string(*rdata,*rdata_len,p2);
3005 if (!p2) {
3006 return False;
3007 }
3008 p += 4;
3009
3010 SCVAL(p,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
3011 SCVAL(p,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
3012 p += 2;
3013
3014 SIVAL(p,0,PTR_DIFF(p2,*rdata));
3015 pstrcpy(p2,lp_workgroup()); /* don't know. login domain?? */
3016 p2 = skip_string(*rdata,*rdata_len,p2);
3017 if (!p2) {
3018 return False;
3019 }
3020 p += 4;
3021
3022 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */
3023 pstrcpy(p2,"");
3024 p2 = skip_string(*rdata,*rdata_len,p2);
3025 if (!p2) {
3026 return False;
3027 }
3028 p += 4;
3029
3030 *rdata_len = PTR_DIFF(p2,*rdata);
3031
3032 SSVAL(*rparam,4,*rdata_len);
3033
3034 return True;
3035}
3036
3037/****************************************************************************
3038 get info about a user
3039
3040 struct user_info_11 {
3041 char usri11_name[21]; 0-20
3042 char usri11_pad; 21
3043 char *usri11_comment; 22-25
3044 char *usri11_usr_comment; 26-29
3045 unsigned short usri11_priv; 30-31
3046 unsigned long usri11_auth_flags; 32-35
3047 long usri11_password_age; 36-39
3048 char *usri11_homedir; 40-43
3049 char *usri11_parms; 44-47
3050 long usri11_last_logon; 48-51
3051 long usri11_last_logoff; 52-55
3052 unsigned short usri11_bad_pw_count; 56-57
3053 unsigned short usri11_num_logons; 58-59
3054 char *usri11_logon_server; 60-63
3055 unsigned short usri11_country_code; 64-65
3056 char *usri11_workstations; 66-69
3057 unsigned long usri11_max_storage; 70-73
3058 unsigned short usri11_units_per_week; 74-75
3059 unsigned char *usri11_logon_hours; 76-79
3060 unsigned short usri11_code_page; 80-81
3061 };
3062
3063where:
3064
3065 usri11_name specifies the user name for which information is retireved
3066
3067 usri11_pad aligns the next data structure element to a word boundary
3068
3069 usri11_comment is a null terminated ASCII comment
3070
3071 usri11_user_comment is a null terminated ASCII comment about the user
3072
3073 usri11_priv specifies the level of the privilege assigned to the user.
3074 The possible values are:
3075
3076Name Value Description
3077USER_PRIV_GUEST 0 Guest privilege
3078USER_PRIV_USER 1 User privilege
3079USER_PRV_ADMIN 2 Administrator privilege
3080
3081 usri11_auth_flags specifies the account operator privileges. The
3082 possible values are:
3083
3084Name Value Description
3085AF_OP_PRINT 0 Print operator
3086
3087
3088Leach, Naik [Page 28]
3089
3090
3091
3092
3093INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
3094
3095
3096AF_OP_COMM 1 Communications operator
3097AF_OP_SERVER 2 Server operator
3098AF_OP_ACCOUNTS 3 Accounts operator
3099
3100
3101 usri11_password_age specifies how many seconds have elapsed since the
3102 password was last changed.
3103
3104 usri11_home_dir points to a null terminated ASCII string that contains
3105 the path name of the user's home directory.
3106
3107 usri11_parms points to a null terminated ASCII string that is set
3108 aside for use by applications.
3109
3110 usri11_last_logon specifies the time when the user last logged on.
3111 This value is stored as the number of seconds elapsed since
3112 00:00:00, January 1, 1970.
3113
3114 usri11_last_logoff specifies the time when the user last logged off.
3115 This value is stored as the number of seconds elapsed since
3116 00:00:00, January 1, 1970. A value of 0 means the last logoff
3117 time is unknown.
3118
3119 usri11_bad_pw_count specifies the number of incorrect passwords
3120 entered since the last successful logon.
3121
3122 usri11_log1_num_logons specifies the number of times this user has
3123 logged on. A value of -1 means the number of logons is unknown.
3124
3125 usri11_logon_server points to a null terminated ASCII string that
3126 contains the name of the server to which logon requests are sent.
3127 A null string indicates logon requests should be sent to the
3128 domain controller.
3129
3130 usri11_country_code specifies the country code for the user's language
3131 of choice.
3132
3133 usri11_workstations points to a null terminated ASCII string that
3134 contains the names of workstations the user may log on from.
3135 There may be up to 8 workstations, with the names separated by
3136 commas. A null strings indicates there are no restrictions.
3137
3138 usri11_max_storage specifies the maximum amount of disk space the user
3139 can occupy. A value of 0xffffffff indicates there are no
3140 restrictions.
3141
3142 usri11_units_per_week specifies the equal number of time units into
3143 which a week is divided. This value must be equal to 168.
3144
3145 usri11_logon_hours points to a 21 byte (168 bits) string that
3146 specifies the time during which the user can log on. Each bit
3147 represents one unique hour in a week. The first bit (bit 0, word
3148 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
3149
3150
3151
3152Leach, Naik [Page 29]
3153
3154
3155
3156
3157INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
3158
3159
3160 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
3161 are no restrictions.
3162
3163 usri11_code_page specifies the code page for the user's language of
3164 choice
3165
3166All of the pointers in this data structure need to be treated
3167specially. The pointer is a 32 bit pointer. The higher 16 bits need
3168to be ignored. The converter word returned in the parameters section
3169needs to be subtracted from the lower 16 bits to calculate an offset
3170into the return buffer where this ASCII string resides.
3171
3172There is no auxiliary data in the response.
3173
3174 ****************************************************************************/
3175
3176#define usri11_name 0
3177#define usri11_pad 21
3178#define usri11_comment 22
3179#define usri11_usr_comment 26
3180#define usri11_full_name 30
3181#define usri11_priv 34
3182#define usri11_auth_flags 36
3183#define usri11_password_age 40
3184#define usri11_homedir 44
3185#define usri11_parms 48
3186#define usri11_last_logon 52
3187#define usri11_last_logoff 56
3188#define usri11_bad_pw_count 60
3189#define usri11_num_logons 62
3190#define usri11_logon_server 64
3191#define usri11_country_code 68
3192#define usri11_workstations 70
3193#define usri11_max_storage 74
3194#define usri11_units_per_week 78
3195#define usri11_logon_hours 80
3196#define usri11_code_page 84
3197#define usri11_end 86
3198
3199#define USER_PRIV_GUEST 0
3200#define USER_PRIV_USER 1
3201#define USER_PRIV_ADMIN 2
3202
3203#define AF_OP_PRINT 0
3204#define AF_OP_COMM 1
3205#define AF_OP_SERVER 2
3206#define AF_OP_ACCOUNTS 3
3207
3208
3209static BOOL api_RNetUserGetInfo(connection_struct *conn, uint16 vuid,
3210 char *param, int tpscnt,
3211 char *data, int tdscnt,
3212 int mdrcnt,int mprcnt,
3213 char **rdata,char **rparam,
3214 int *rdata_len,int *rparam_len)
3215{
3216 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3217 char *str2 = skip_string(param,tpscnt,str1);
3218 char *UserName = skip_string(param,tpscnt,str2);
3219 char *p = skip_string(param,tpscnt,UserName);
3220 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
3221 char *p2;
3222 const char *level_string;
3223
3224 /* get NIS home of a previously validated user - simeon */
3225 /* With share level security vuid will always be zero.
3226 Don't depend on vuser being non-null !!. JRA */
3227 user_struct *vuser = get_valid_user_struct(vuid);
3228 if(vuser != NULL) {
3229 DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->uid,
3230 vuser->user.unix_name));
3231 }
3232
3233 if (!str1 || !str2 || !UserName || !p) {
3234 return False;
3235 }
3236
3237 *rparam_len = 6;
3238 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3239 if (!*rparam) {
3240 return False;
3241 }
3242
3243 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel));
3244
3245 /* check it's a supported variant */
3246 if (strcmp(str1,"zWrLh") != 0) {
3247 return False;
3248 }
3249 switch( uLevel ) {
3250 case 0: level_string = "B21"; break;
3251 case 1: level_string = "B21BB16DWzzWz"; break;
3252 case 2: level_string = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
3253 case 10: level_string = "B21Bzzz"; break;
3254 case 11: level_string = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
3255 default: return False;
3256 }
3257
3258 if (strcmp(level_string,str2) != 0) {
3259 return False;
3260 }
3261
3262 *rdata_len = mdrcnt + 1024;
3263 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
3264 if (!*rdata) {
3265 return False;
3266 }
3267
3268 SSVAL(*rparam,0,NERR_Success);
3269 SSVAL(*rparam,2,0); /* converter word */
3270
3271 p = *rdata;
3272 p2 = get_safe_ptr(*rdata,*rdata_len,p,usri11_end);
3273 if (!p2) {
3274 return False;
3275 }
3276
3277 memset(p,0,21);
3278 fstrcpy(p+usri11_name,UserName); /* 21 bytes - user name */
3279
3280 if (uLevel > 0) {
3281 SCVAL(p,usri11_pad,0); /* padding - 1 byte */
3282 *p2 = 0;
3283 }
3284
3285 if (uLevel >= 10) {
3286 SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */
3287 pstrcpy(p2,"Comment");
3288 p2 = skip_string(*rdata,*rdata_len,p2);
3289 if (!p2) {
3290 return False;
3291 }
3292
3293 SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */
3294 pstrcpy(p2,"UserComment");
3295 p2 = skip_string(*rdata,*rdata_len,p2);
3296 if (!p2) {
3297 return False;
3298 }
3299
3300 /* EEK! the cifsrap.txt doesn't have this in!!!! */
3301 SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */
3302 pstrcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName));
3303 p2 = skip_string(*rdata,*rdata_len,p2);
3304 if (!p2) {
3305 return False;
3306 }
3307 }
3308
3309 if (uLevel == 11) {
3310 /* modelled after NTAS 3.51 reply */
3311 SSVAL(p,usri11_priv,conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
3312 SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */
3313 SIVALS(p,usri11_password_age,-1); /* password age */
3314 SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */
3315 pstrcpy(p2, vuser && vuser->homedir ? vuser->homedir : "");
3316 p2 = skip_string(*rdata,*rdata_len,p2);
3317 if (!p2) {
3318 return False;
3319 }
3320 SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */
3321 pstrcpy(p2,"");
3322 p2 = skip_string(*rdata,*rdata_len,p2);
3323 if (!p2) {
3324 return False;
3325 }
3326 SIVAL(p,usri11_last_logon,0); /* last logon */
3327 SIVAL(p,usri11_last_logoff,0); /* last logoff */
3328 SSVALS(p,usri11_bad_pw_count,-1); /* bad pw counts */
3329 SSVALS(p,usri11_num_logons,-1); /* num logons */
3330 SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */
3331 pstrcpy(p2,"\\\\*");
3332 p2 = skip_string(*rdata,*rdata_len,p2);
3333 if (!p2) {
3334 return False;
3335 }
3336 SSVAL(p,usri11_country_code,0); /* country code */
3337
3338 SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */
3339 pstrcpy(p2,"");
3340 p2 = skip_string(*rdata,*rdata_len,p2);
3341 if (!p2) {
3342 return False;
3343 }
3344
3345 SIVALS(p,usri11_max_storage,-1); /* max storage */
3346 SSVAL(p,usri11_units_per_week,168); /* units per week */
3347 SIVAL(p,usri11_logon_hours,PTR_DIFF(p2,p)); /* logon hours */
3348
3349 /* a simple way to get logon hours at all times. */
3350 memset(p2,0xff,21);
3351 SCVAL(p2,21,0); /* fix zero termination */
3352 p2 = skip_string(*rdata,*rdata_len,p2);
3353 if (!p2) {
3354 return False;
3355 }
3356
3357 SSVAL(p,usri11_code_page,0); /* code page */
3358 }
3359
3360 if (uLevel == 1 || uLevel == 2) {
3361 memset(p+22,' ',16); /* password */
3362 SIVALS(p,38,-1); /* password age */
3363 SSVAL(p,42,
3364 conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
3365 SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
3366 pstrcpy(p2, vuser && vuser->homedir ? vuser->homedir : "");
3367 p2 = skip_string(*rdata,*rdata_len,p2);
3368 if (!p2) {
3369 return False;
3370 }
3371 SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
3372 *p2++ = 0;
3373 SSVAL(p,52,0); /* flags */
3374 SIVAL(p,54,PTR_DIFF(p2,*rdata)); /* script_path */
3375 pstrcpy(p2,vuser && vuser->logon_script ? vuser->logon_script : "");
3376 p2 = skip_string(*rdata,*rdata_len,p2);
3377 if (!p2) {
3378 return False;
3379 }
3380 if (uLevel == 2) {
3381 SIVAL(p,60,0); /* auth_flags */
3382 SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
3383 pstrcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName));
3384 p2 = skip_string(*rdata,*rdata_len,p2);
3385 if (!p2) {
3386 return False;
3387 }
3388 SIVAL(p,68,0); /* urs_comment */
3389 SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
3390 pstrcpy(p2,"");
3391 p2 = skip_string(*rdata,*rdata_len,p2);
3392 if (!p2) {
3393 return False;
3394 }
3395 SIVAL(p,76,0); /* workstations */
3396 SIVAL(p,80,0); /* last_logon */
3397 SIVAL(p,84,0); /* last_logoff */
3398 SIVALS(p,88,-1); /* acct_expires */
3399 SIVALS(p,92,-1); /* max_storage */
3400 SSVAL(p,96,168); /* units_per_week */
3401 SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
3402 memset(p2,-1,21);
3403 p2 += 21;
3404 SSVALS(p,102,-1); /* bad_pw_count */
3405 SSVALS(p,104,-1); /* num_logons */
3406 SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
3407 {
3408 pstring tmp;
3409 pstrcpy(tmp, "\\\\%L");
3410 standard_sub_basic("", "", tmp, sizeof(tmp));
3411 pstrcpy(p2, tmp);
3412 }
3413 p2 = skip_string(*rdata,*rdata_len,p2);
3414 if (!p2) {
3415 return False;
3416 }
3417 SSVAL(p,110,49); /* country_code */
3418 SSVAL(p,112,860); /* code page */
3419 }
3420 }
3421
3422 *rdata_len = PTR_DIFF(p2,*rdata);
3423
3424 SSVAL(*rparam,4,*rdata_len); /* is this right?? */
3425
3426 return(True);
3427}
3428
3429static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid,
3430 char *param, int tpscnt,
3431 char *data, int tdscnt,
3432 int mdrcnt,int mprcnt,
3433 char **rdata,char **rparam,
3434 int *rdata_len,int *rparam_len)
3435{
3436 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3437 char *str2 = skip_string(param,tpscnt,str1);
3438 char *p = skip_string(param,tpscnt,str2);
3439 int uLevel;
3440 struct pack_desc desc;
3441 char* name;
3442 /* With share level security vuid will always be zero.
3443 Don't depend on vuser being non-null !!. JRA */
3444 user_struct *vuser = get_valid_user_struct(vuid);
3445
3446 if (!str1 || !str2 || !p) {
3447 return False;
3448 }
3449
3450 if(vuser != NULL) {
3451 DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->uid,
3452 vuser->user.unix_name));
3453 }
3454
3455 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
3456 name = get_safe_str_ptr(param,tpscnt,p,2);
3457 if (!name) {
3458 return False;
3459 }
3460
3461 memset((char *)&desc,'\0',sizeof(desc));
3462
3463 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
3464
3465 /* check it's a supported varient */
3466 if (strcmp(str1,"OOWb54WrLh") != 0) {
3467 return False;
3468 }
3469 if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) {
3470 return False;
3471 }
3472 if (mdrcnt > 0) {
3473 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3474 if (!*rdata) {
3475 return False;
3476 }
3477 }
3478
3479 desc.base = *rdata;
3480 desc.buflen = mdrcnt;
3481 desc.subformat = NULL;
3482 desc.format = str2;
3483
3484 if (init_package(&desc,1,0)) {
3485 PACKI(&desc,"W",0); /* code */
3486 PACKS(&desc,"B21",name); /* eff. name */
3487 PACKS(&desc,"B",""); /* pad */
3488 PACKI(&desc,"W", conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
3489 PACKI(&desc,"D",0); /* auth flags XXX */
3490 PACKI(&desc,"W",0); /* num logons */
3491 PACKI(&desc,"W",0); /* bad pw count */
3492 PACKI(&desc,"D",0); /* last logon */
3493 PACKI(&desc,"D",-1); /* last logoff */
3494 PACKI(&desc,"D",-1); /* logoff time */
3495 PACKI(&desc,"D",-1); /* kickoff time */
3496 PACKI(&desc,"D",0); /* password age */
3497 PACKI(&desc,"D",0); /* password can change */
3498 PACKI(&desc,"D",-1); /* password must change */
3499
3500 {
3501 fstring mypath;
3502 fstrcpy(mypath,"\\\\");
3503 fstrcat(mypath,get_local_machine_name());
3504 strupper_m(mypath);
3505 PACKS(&desc,"z",mypath); /* computer */
3506 }
3507
3508 PACKS(&desc,"z",lp_workgroup());/* domain */
3509 PACKS(&desc,"z", vuser && vuser->logon_script ? vuser->logon_script :""); /* script path */
3510 PACKI(&desc,"D",0x00000000); /* reserved */
3511 }
3512
3513 *rdata_len = desc.usedlen;
3514 *rparam_len = 6;
3515 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3516 if (!*rparam) {
3517 return False;
3518 }
3519 SSVALS(*rparam,0,desc.errcode);
3520 SSVAL(*rparam,2,0);
3521 SSVAL(*rparam,4,desc.neededlen);
3522
3523 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
3524
3525 return True;
3526}
3527
3528/****************************************************************************
3529 api_WAccessGetUserPerms
3530****************************************************************************/
3531
3532static BOOL api_WAccessGetUserPerms(connection_struct *conn,uint16 vuid,
3533 char *param, int tpscnt,
3534 char *data, int tdscnt,
3535 int mdrcnt,int mprcnt,
3536 char **rdata,char **rparam,
3537 int *rdata_len,int *rparam_len)
3538{
3539 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3540 char *str2 = skip_string(param,tpscnt,str1);
3541 char *user = skip_string(param,tpscnt,str2);
3542 char *resource = skip_string(param,tpscnt,user);
3543
3544 if (!str1 || !str2 || !user || !resource) {
3545 return False;
3546 }
3547
3548 if (skip_string(param,tpscnt,resource) == NULL) {
3549 return False;
3550 }
3551 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
3552
3553 /* check it's a supported varient */
3554 if (strcmp(str1,"zzh") != 0) {
3555 return False;
3556 }
3557 if (strcmp(str2,"") != 0) {
3558 return False;
3559 }
3560
3561 *rparam_len = 6;
3562 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3563 if (!*rparam) {
3564 return False;
3565 }
3566 SSVALS(*rparam,0,0); /* errorcode */
3567 SSVAL(*rparam,2,0); /* converter word */
3568 SSVAL(*rparam,4,0x7f); /* permission flags */
3569
3570 return True;
3571}
3572
3573/****************************************************************************
3574 api_WPrintJobEnumerate
3575 ****************************************************************************/
3576
3577static BOOL api_WPrintJobGetInfo(connection_struct *conn, uint16 vuid,
3578 char *param, int tpscnt,
3579 char *data, int tdscnt,
3580 int mdrcnt,int mprcnt,
3581 char **rdata,char **rparam,
3582 int *rdata_len,int *rparam_len)
3583{
3584 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3585 char *str2 = skip_string(param,tpscnt,str1);
3586 char *p = skip_string(param,tpscnt,str2);
3587 int uLevel;
3588 int count;
3589 int i;
3590 int snum;
3591 fstring sharename;
3592 uint32 jobid;
3593 struct pack_desc desc;
3594 print_queue_struct *queue=NULL;
3595 print_status_struct status;
3596 char *tmpdata=NULL;
3597
3598 if (!str1 || !str2 || !p) {
3599 return False;
3600 }
3601
3602 uLevel = get_safe_SVAL(param,tpscnt,p,2,-1);
3603
3604 memset((char *)&desc,'\0',sizeof(desc));
3605 memset((char *)&status,'\0',sizeof(status));
3606
3607 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,SVAL(p,0)));
3608
3609 /* check it's a supported varient */
3610 if (strcmp(str1,"WWrLh") != 0) {
3611 return False;
3612 }
3613 if (!check_printjob_info(&desc,uLevel,str2)) {
3614 return False;
3615 }
3616
3617 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid)) {
3618 return False;
3619 }
3620
3621 snum = lp_servicenumber( sharename);
3622 if (snum < 0 || !VALID_SNUM(snum)) {
3623 return(False);
3624 }
3625
3626 count = print_queue_status(snum,&queue,&status);
3627 for (i = 0; i < count; i++) {
3628 if (queue[i].job == jobid) {
3629 break;
3630 }
3631 }
3632
3633 if (mdrcnt > 0) {
3634 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3635 if (!*rdata) {
3636 return False;
3637 }
3638 desc.base = *rdata;
3639 desc.buflen = mdrcnt;
3640 } else {
3641 /*
3642 * Don't return data but need to get correct length
3643 * init_package will return wrong size if buflen=0
3644 */
3645 desc.buflen = getlen(desc.format);
3646 desc.base = tmpdata = (char *)SMB_MALLOC( desc.buflen );
3647 }
3648
3649 if (init_package(&desc,1,0)) {
3650 if (i < count) {
3651 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
3652 *rdata_len = desc.usedlen;
3653 } else {
3654 desc.errcode = NERR_JobNotFound;
3655 *rdata_len = 0;
3656 }
3657 }
3658
3659 *rparam_len = 6;
3660 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3661 if (!*rparam) {
3662 return False;
3663 }
3664 SSVALS(*rparam,0,desc.errcode);
3665 SSVAL(*rparam,2,0);
3666 SSVAL(*rparam,4,desc.neededlen);
3667
3668 SAFE_FREE(queue);
3669 SAFE_FREE(tmpdata);
3670
3671 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
3672
3673 return True;
3674}
3675
3676static BOOL api_WPrintJobEnumerate(connection_struct *conn, uint16 vuid,
3677 char *param, int tpscnt,
3678 char *data, int tdscnt,
3679 int mdrcnt,int mprcnt,
3680 char **rdata,char **rparam,
3681 int *rdata_len,int *rparam_len)
3682{
3683 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3684 char *str2 = skip_string(param,tpscnt,str1);
3685 char *p = skip_string(param,tpscnt,str2);
3686 char *name = p;
3687 int uLevel;
3688 int count;
3689 int i, succnt=0;
3690 int snum;
3691 struct pack_desc desc;
3692 print_queue_struct *queue=NULL;
3693 print_status_struct status;
3694
3695 if (!str1 || !str2 || !p) {
3696 return False;
3697 }
3698
3699 memset((char *)&desc,'\0',sizeof(desc));
3700 memset((char *)&status,'\0',sizeof(status));
3701
3702 p = skip_string(param,tpscnt,p);
3703 if (!p) {
3704 return False;
3705 }
3706 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
3707
3708 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
3709
3710 /* check it's a supported variant */
3711 if (strcmp(str1,"zWrLeh") != 0) {
3712 return False;
3713 }
3714
3715 if (uLevel > 2) {
3716 return False; /* defined only for uLevel 0,1,2 */
3717 }
3718
3719 if (!check_printjob_info(&desc,uLevel,str2)) {
3720 return False;
3721 }
3722
3723 snum = find_service(name);
3724 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) ) {
3725 return False;
3726 }
3727
3728 count = print_queue_status(snum,&queue,&status);
3729 if (mdrcnt > 0) {
3730 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3731 if (!*rdata) {
3732 return False;
3733 }
3734 }
3735 desc.base = *rdata;
3736 desc.buflen = mdrcnt;
3737
3738 if (init_package(&desc,count,0)) {
3739 succnt = 0;
3740 for (i = 0; i < count; i++) {
3741 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
3742 if (desc.errcode == NERR_Success) {
3743 succnt = i+1;
3744 }
3745 }
3746 }
3747
3748 *rdata_len = desc.usedlen;
3749
3750 *rparam_len = 8;
3751 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3752 if (!*rparam) {
3753 return False;
3754 }
3755 SSVALS(*rparam,0,desc.errcode);
3756 SSVAL(*rparam,2,0);
3757 SSVAL(*rparam,4,succnt);
3758 SSVAL(*rparam,6,count);
3759
3760 SAFE_FREE(queue);
3761
3762 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
3763
3764 return True;
3765}
3766
3767static int check_printdest_info(struct pack_desc* desc,
3768 int uLevel, char* id)
3769{
3770 desc->subformat = NULL;
3771 switch( uLevel ) {
3772 case 0:
3773 desc->format = "B9";
3774 break;
3775 case 1:
3776 desc->format = "B9B21WWzW";
3777 break;
3778 case 2:
3779 desc->format = "z";
3780 break;
3781 case 3:
3782 desc->format = "zzzWWzzzWW";
3783 break;
3784 default:
3785 DEBUG(0,("check_printdest_info: invalid level %d\n",
3786 uLevel));
3787 return False;
3788 }
3789 if (id == NULL || strcmp(desc->format,id) != 0) {
3790 DEBUG(0,("check_printdest_info: invalid string %s\n",
3791 id ? id : "<NULL>" ));
3792 return False;
3793 }
3794 return True;
3795}
3796
3797static void fill_printdest_info(connection_struct *conn, int snum, int uLevel,
3798 struct pack_desc* desc)
3799{
3800 char buf[100];
3801
3802 strncpy(buf,SERVICE(snum),sizeof(buf)-1);
3803 buf[sizeof(buf)-1] = 0;
3804 strupper_m(buf);
3805
3806 if (uLevel <= 1) {
3807 PACKS(desc,"B9",buf); /* szName */
3808 if (uLevel == 1) {
3809 PACKS(desc,"B21",""); /* szUserName */
3810 PACKI(desc,"W",0); /* uJobId */
3811 PACKI(desc,"W",0); /* fsStatus */
3812 PACKS(desc,"z",""); /* pszStatus */
3813 PACKI(desc,"W",0); /* time */
3814 }
3815 }
3816
3817 if (uLevel == 2 || uLevel == 3) {
3818 PACKS(desc,"z",buf); /* pszPrinterName */
3819 if (uLevel == 3) {
3820 PACKS(desc,"z",""); /* pszUserName */
3821 PACKS(desc,"z",""); /* pszLogAddr */
3822 PACKI(desc,"W",0); /* uJobId */
3823 PACKI(desc,"W",0); /* fsStatus */
3824 PACKS(desc,"z",""); /* pszStatus */
3825 PACKS(desc,"z",""); /* pszComment */
3826 PACKS(desc,"z","NULL"); /* pszDrivers */
3827 PACKI(desc,"W",0); /* time */
3828 PACKI(desc,"W",0); /* pad1 */
3829 }
3830 }
3831}
3832
3833static BOOL api_WPrintDestGetInfo(connection_struct *conn, uint16 vuid,
3834 char *param, int tpscnt,
3835 char *data, int tdscnt,
3836 int mdrcnt,int mprcnt,
3837 char **rdata,char **rparam,
3838 int *rdata_len,int *rparam_len)
3839{
3840 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3841 char *str2 = skip_string(param,tpscnt,str1);
3842 char *p = skip_string(param,tpscnt,str2);
3843 char* PrinterName = p;
3844 int uLevel;
3845 struct pack_desc desc;
3846 int snum;
3847 char *tmpdata=NULL;
3848
3849 if (!str1 || !str2 || !p) {
3850 return False;
3851 }
3852
3853 memset((char *)&desc,'\0',sizeof(desc));
3854
3855 p = skip_string(param,tpscnt,p);
3856 if (!p) {
3857 return False;
3858 }
3859 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
3860
3861 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
3862
3863 /* check it's a supported varient */
3864 if (strcmp(str1,"zWrLh") != 0) {
3865 return False;
3866 }
3867 if (!check_printdest_info(&desc,uLevel,str2)) {
3868 return False;
3869 }
3870
3871 snum = find_service(PrinterName);
3872 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) ) {
3873 *rdata_len = 0;
3874 desc.errcode = NERR_DestNotFound;
3875 desc.neededlen = 0;
3876 } else {
3877 if (mdrcnt > 0) {
3878 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3879 if (!*rdata) {
3880 return False;
3881 }
3882 desc.base = *rdata;
3883 desc.buflen = mdrcnt;
3884 } else {
3885 /*
3886 * Don't return data but need to get correct length
3887 * init_package will return wrong size if buflen=0
3888 */
3889 desc.buflen = getlen(desc.format);
3890 desc.base = tmpdata = (char *)SMB_MALLOC( desc.buflen );
3891 }
3892 if (init_package(&desc,1,0)) {
3893 fill_printdest_info(conn,snum,uLevel,&desc);
3894 }
3895 *rdata_len = desc.usedlen;
3896 }
3897
3898 *rparam_len = 6;
3899 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3900 if (!*rparam) {
3901 return False;
3902 }
3903 SSVALS(*rparam,0,desc.errcode);
3904 SSVAL(*rparam,2,0);
3905 SSVAL(*rparam,4,desc.neededlen);
3906
3907 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
3908 SAFE_FREE(tmpdata);
3909
3910 return True;
3911}
3912
3913static BOOL api_WPrintDestEnum(connection_struct *conn, uint16 vuid,
3914 char *param, int tpscnt,
3915 char *data, int tdscnt,
3916 int mdrcnt,int mprcnt,
3917 char **rdata,char **rparam,
3918 int *rdata_len,int *rparam_len)
3919{
3920 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3921 char *str2 = skip_string(param,tpscnt,str1);
3922 char *p = skip_string(param,tpscnt,str2);
3923 int uLevel;
3924 int queuecnt;
3925 int i, n, succnt=0;
3926 struct pack_desc desc;
3927 int services = lp_numservices();
3928
3929 if (!str1 || !str2 || !p) {
3930 return False;
3931 }
3932
3933 memset((char *)&desc,'\0',sizeof(desc));
3934
3935 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
3936
3937 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
3938
3939 /* check it's a supported varient */
3940 if (strcmp(str1,"WrLeh") != 0) {
3941 return False;
3942 }
3943 if (!check_printdest_info(&desc,uLevel,str2)) {
3944 return False;
3945 }
3946
3947 queuecnt = 0;
3948 for (i = 0; i < services; i++) {
3949 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
3950 queuecnt++;
3951 }
3952 }
3953
3954 if (mdrcnt > 0) {
3955 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3956 if (!*rdata) {
3957 return False;
3958 }
3959 }
3960
3961 desc.base = *rdata;
3962 desc.buflen = mdrcnt;
3963 if (init_package(&desc,queuecnt,0)) {
3964 succnt = 0;
3965 n = 0;
3966 for (i = 0; i < services; i++) {
3967 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
3968 fill_printdest_info(conn,i,uLevel,&desc);
3969 n++;
3970 if (desc.errcode == NERR_Success) {
3971 succnt = n;
3972 }
3973 }
3974 }
3975 }
3976
3977 *rdata_len = desc.usedlen;
3978
3979 *rparam_len = 8;
3980 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3981 if (!*rparam) {
3982 return False;
3983 }
3984 SSVALS(*rparam,0,desc.errcode);
3985 SSVAL(*rparam,2,0);
3986 SSVAL(*rparam,4,succnt);
3987 SSVAL(*rparam,6,queuecnt);
3988
3989 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
3990
3991 return True;
3992}
3993
3994static BOOL api_WPrintDriverEnum(connection_struct *conn, uint16 vuid,
3995 char *param, int tpscnt,
3996 char *data, int tdscnt,
3997 int mdrcnt,int mprcnt,
3998 char **rdata,char **rparam,
3999 int *rdata_len,int *rparam_len)
4000{
4001 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4002 char *str2 = skip_string(param,tpscnt,str1);
4003 char *p = skip_string(param,tpscnt,str2);
4004 int uLevel;
4005 int succnt;
4006 struct pack_desc desc;
4007
4008 if (!str1 || !str2 || !p) {
4009 return False;
4010 }
4011
4012 memset((char *)&desc,'\0',sizeof(desc));
4013
4014 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4015
4016 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
4017
4018 /* check it's a supported varient */
4019 if (strcmp(str1,"WrLeh") != 0) {
4020 return False;
4021 }
4022 if (uLevel != 0 || strcmp(str2,"B41") != 0) {
4023 return False;
4024 }
4025
4026 if (mdrcnt > 0) {
4027 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
4028 if (!*rdata) {
4029 return False;
4030 }
4031 }
4032 desc.base = *rdata;
4033 desc.buflen = mdrcnt;
4034 if (init_package(&desc,1,0)) {
4035 PACKS(&desc,"B41","NULL");
4036 }
4037
4038 succnt = (desc.errcode == NERR_Success ? 1 : 0);
4039
4040 *rdata_len = desc.usedlen;
4041
4042 *rparam_len = 8;
4043 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
4044 if (!*rparam) {
4045 return False;
4046 }
4047 SSVALS(*rparam,0,desc.errcode);
4048 SSVAL(*rparam,2,0);
4049 SSVAL(*rparam,4,succnt);
4050 SSVAL(*rparam,6,1);
4051
4052 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
4053
4054 return True;
4055}
4056
4057static BOOL api_WPrintQProcEnum(connection_struct *conn, uint16 vuid,
4058 char *param, int tpscnt,
4059 char *data, int tdscnt,
4060 int mdrcnt,int mprcnt,
4061 char **rdata,char **rparam,
4062 int *rdata_len,int *rparam_len)
4063{
4064 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4065 char *str2 = skip_string(param,tpscnt,str1);
4066 char *p = skip_string(param,tpscnt,str2);
4067 int uLevel;
4068 int succnt;
4069 struct pack_desc desc;
4070
4071 if (!str1 || !str2 || !p) {
4072 return False;
4073 }
4074 memset((char *)&desc,'\0',sizeof(desc));
4075
4076 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4077
4078 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
4079
4080 /* check it's a supported varient */
4081 if (strcmp(str1,"WrLeh") != 0) {
4082 return False;
4083 }
4084 if (uLevel != 0 || strcmp(str2,"B13") != 0) {
4085 return False;
4086 }
4087
4088 if (mdrcnt > 0) {
4089 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
4090 if (!*rdata) {
4091 return False;
4092 }
4093 }
4094 desc.base = *rdata;
4095 desc.buflen = mdrcnt;
4096 desc.format = str2;
4097 if (init_package(&desc,1,0)) {
4098 PACKS(&desc,"B13","lpd");
4099 }
4100
4101 succnt = (desc.errcode == NERR_Success ? 1 : 0);
4102
4103 *rdata_len = desc.usedlen;
4104
4105 *rparam_len = 8;
4106 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
4107 if (!*rparam) {
4108 return False;
4109 }
4110 SSVALS(*rparam,0,desc.errcode);
4111 SSVAL(*rparam,2,0);
4112 SSVAL(*rparam,4,succnt);
4113 SSVAL(*rparam,6,1);
4114
4115 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
4116
4117 return True;
4118}
4119
4120static BOOL api_WPrintPortEnum(connection_struct *conn, uint16 vuid,
4121 char *param, int tpscnt,
4122 char *data, int tdscnt,
4123 int mdrcnt,int mprcnt,
4124 char **rdata,char **rparam,
4125 int *rdata_len,int *rparam_len)
4126{
4127 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4128 char *str2 = skip_string(param,tpscnt,str1);
4129 char *p = skip_string(param,tpscnt,str2);
4130 int uLevel;
4131 int succnt;
4132 struct pack_desc desc;
4133
4134 if (!str1 || !str2 || !p) {
4135 return False;
4136 }
4137
4138 memset((char *)&desc,'\0',sizeof(desc));
4139
4140 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4141
4142 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
4143
4144 /* check it's a supported varient */
4145 if (strcmp(str1,"WrLeh") != 0) {
4146 return False;
4147 }
4148 if (uLevel != 0 || strcmp(str2,"B9") != 0) {
4149 return False;
4150 }
4151
4152 if (mdrcnt > 0) {
4153 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
4154 if (!*rdata) {
4155 return False;
4156 }
4157 }
4158 memset((char *)&desc,'\0',sizeof(desc));
4159 desc.base = *rdata;
4160 desc.buflen = mdrcnt;
4161 desc.format = str2;
4162 if (init_package(&desc,1,0)) {
4163 PACKS(&desc,"B13","lp0");
4164 }
4165
4166 succnt = (desc.errcode == NERR_Success ? 1 : 0);
4167
4168 *rdata_len = desc.usedlen;
4169
4170 *rparam_len = 8;
4171 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
4172 if (!*rparam) {
4173 return False;
4174 }
4175 SSVALS(*rparam,0,desc.errcode);
4176 SSVAL(*rparam,2,0);
4177 SSVAL(*rparam,4,succnt);
4178 SSVAL(*rparam,6,1);
4179
4180 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
4181
4182 return True;
4183}
4184
4185/****************************************************************************
4186 List open sessions
4187 ****************************************************************************/
4188
4189static BOOL api_RNetSessionEnum(connection_struct *conn, uint16 vuid,
4190 char *param, int tpscnt,
4191 char *data, int tdscnt,
4192 int mdrcnt,int mprcnt,
4193 char **rdata,char **rparam,
4194 int *rdata_len,int *rparam_len)
4195
4196{
4197 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4198 char *str2 = skip_string(param,tpscnt,str1);
4199 char *p = skip_string(param,tpscnt,str2);
4200 int uLevel;
4201 struct pack_desc desc;
4202 struct sessionid *session_list = NULL;
4203 int i, num_sessions;
4204
4205 if (!str1 || !str2 || !p) {
4206 return False;
4207 }
4208
4209 memset((char *)&desc,'\0',sizeof(desc));
4210
4211 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4212
4213 DEBUG(3,("RNetSessionEnum uLevel=%d\n",uLevel));
4214 DEBUG(7,("RNetSessionEnum req string=%s\n",str1));
4215 DEBUG(7,("RNetSessionEnum ret string=%s\n",str2));
4216
4217 /* check it's a supported varient */
4218 if (strcmp(str1,RAP_NetSessionEnum_REQ) != 0) {
4219 return False;
4220 }
4221 if (uLevel != 2 || strcmp(str2,RAP_SESSION_INFO_L2) != 0) {
4222 return False;
4223 }
4224
4225 num_sessions = list_sessions(&session_list);
4226
4227 if (mdrcnt > 0) {
4228 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
4229 if (!*rdata) {
4230 SAFE_FREE(session_list);
4231 return False;
4232 }
4233 }
4234 memset((char *)&desc,'\0',sizeof(desc));
4235 desc.base = *rdata;
4236 desc.buflen = mdrcnt;
4237 desc.format = str2;
4238 if (!init_package(&desc,num_sessions,0)) {
4239 SAFE_FREE(session_list);
4240 return False;
4241 }
4242
4243 for(i=0; i<num_sessions; i++) {
4244 PACKS(&desc, "z", session_list[i].remote_machine);
4245 PACKS(&desc, "z", session_list[i].username);
4246 PACKI(&desc, "W", 1); /* num conns */
4247 PACKI(&desc, "W", 0); /* num opens */
4248 PACKI(&desc, "W", 1); /* num users */
4249 PACKI(&desc, "D", 0); /* session time */
4250 PACKI(&desc, "D", 0); /* idle time */
4251 PACKI(&desc, "D", 0); /* flags */
4252 PACKS(&desc, "z", "Unknown Client"); /* client type string */
4253 }
4254
4255 *rdata_len = desc.usedlen;
4256
4257 *rparam_len = 8;
4258 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
4259 if (!*rparam) {
4260 SAFE_FREE(session_list);
4261 return False;
4262 }
4263 SSVALS(*rparam,0,desc.errcode);
4264 SSVAL(*rparam,2,0); /* converter */
4265 SSVAL(*rparam,4,num_sessions); /* count */
4266
4267 DEBUG(4,("RNetSessionEnum: errorcode %d\n",desc.errcode));
4268
4269 SAFE_FREE(session_list);
4270 return True;
4271}
4272
4273
4274/****************************************************************************
4275 The buffer was too small.
4276 ****************************************************************************/
4277
4278static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param, char *data,
4279 int mdrcnt, int mprcnt,
4280 char **rdata, char **rparam,
4281 int *rdata_len, int *rparam_len)
4282{
4283 *rparam_len = MIN(*rparam_len,mprcnt);
4284 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
4285 if (!*rparam) {
4286 return False;
4287 }
4288
4289 *rdata_len = 0;
4290
4291 SSVAL(*rparam,0,NERR_BufTooSmall);
4292
4293 DEBUG(3,("Supplied buffer too small in API command\n"));
4294
4295 return True;
4296}
4297
4298/****************************************************************************
4299 The request is not supported.
4300 ****************************************************************************/
4301
4302static BOOL api_Unsupported(connection_struct *conn, uint16 vuid,
4303 char *param, int tpscnt,
4304 char *data, int tdscnt,
4305 int mdrcnt, int mprcnt,
4306 char **rdata, char **rparam,
4307 int *rdata_len, int *rparam_len)
4308{
4309 *rparam_len = 4;
4310 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
4311 if (!*rparam) {
4312 return False;
4313 }
4314
4315 *rdata_len = 0;
4316
4317 SSVAL(*rparam,0,NERR_notsupported);
4318 SSVAL(*rparam,2,0); /* converter word */
4319
4320 DEBUG(3,("Unsupported API command\n"));
4321
4322 return True;
4323}
4324
4325static const struct {
4326 const char *name;
4327 int id;
4328 BOOL (*fn)(connection_struct *, uint16,
4329 char *, int,
4330 char *, int,
4331 int,int,char **,char **,int *,int *);
4332 BOOL auth_user; /* Deny anonymous access? */
4333} api_commands[] = {
4334 {"RNetShareEnum", RAP_WshareEnum, api_RNetShareEnum, True},
4335 {"RNetShareGetInfo", RAP_WshareGetInfo, api_RNetShareGetInfo},
4336 {"RNetShareAdd", RAP_WshareAdd, api_RNetShareAdd},
4337 {"RNetSessionEnum", RAP_WsessionEnum, api_RNetSessionEnum, True},
4338 {"RNetServerGetInfo", RAP_WserverGetInfo, api_RNetServerGetInfo},
4339 {"RNetGroupEnum", RAP_WGroupEnum, api_RNetGroupEnum, True},
4340 {"RNetGroupGetUsers", RAP_WGroupGetUsers, api_RNetGroupGetUsers, True},
4341 {"RNetUserEnum", RAP_WUserEnum, api_RNetUserEnum, True},
4342 {"RNetUserGetInfo", RAP_WUserGetInfo, api_RNetUserGetInfo},
4343 {"NetUserGetGroups", RAP_WUserGetGroups, api_NetUserGetGroups},
4344 {"NetWkstaGetInfo", RAP_WWkstaGetInfo, api_NetWkstaGetInfo},
4345 {"DosPrintQEnum", RAP_WPrintQEnum, api_DosPrintQEnum, True},
4346 {"DosPrintQGetInfo", RAP_WPrintQGetInfo, api_DosPrintQGetInfo},
4347 {"WPrintQueuePause", RAP_WPrintQPause, api_WPrintQueueCtrl},
4348 {"WPrintQueueResume", RAP_WPrintQContinue, api_WPrintQueueCtrl},
4349 {"WPrintJobEnumerate",RAP_WPrintJobEnum, api_WPrintJobEnumerate},
4350 {"WPrintJobGetInfo", RAP_WPrintJobGetInfo, api_WPrintJobGetInfo},
4351 {"RDosPrintJobDel", RAP_WPrintJobDel, api_RDosPrintJobDel},
4352 {"RDosPrintJobPause", RAP_WPrintJobPause, api_RDosPrintJobDel},
4353 {"RDosPrintJobResume",RAP_WPrintJobContinue, api_RDosPrintJobDel},
4354 {"WPrintDestEnum", RAP_WPrintDestEnum, api_WPrintDestEnum},
4355 {"WPrintDestGetInfo", RAP_WPrintDestGetInfo, api_WPrintDestGetInfo},
4356 {"NetRemoteTOD", RAP_NetRemoteTOD, api_NetRemoteTOD},
4357 {"WPrintQueuePurge", RAP_WPrintQPurge, api_WPrintQueueCtrl},
4358 {"NetServerEnum", RAP_NetServerEnum2, api_RNetServerEnum}, /* anon OK */
4359 {"WAccessGetUserPerms",RAP_WAccessGetUserPerms,api_WAccessGetUserPerms},
4360 {"SetUserPassword", RAP_WUserPasswordSet2, api_SetUserPassword},
4361 {"WWkstaUserLogon", RAP_WWkstaUserLogon, api_WWkstaUserLogon},
4362 {"PrintJobInfo", RAP_WPrintJobSetInfo, api_PrintJobInfo},
4363 {"WPrintDriverEnum", RAP_WPrintDriverEnum, api_WPrintDriverEnum},
4364 {"WPrintQProcEnum", RAP_WPrintQProcessorEnum,api_WPrintQProcEnum},
4365 {"WPrintPortEnum", RAP_WPrintPortEnum, api_WPrintPortEnum},
4366 {"SamOEMChangePassword",RAP_SamOEMChgPasswordUser2_P,api_SamOEMChangePassword}, /* anon OK */
4367 {NULL, -1, api_Unsupported}
4368 /* The following RAP calls are not implemented by Samba:
4369
4370 RAP_WFileEnum2 - anon not OK
4371 */
4372};
4373
4374
4375/****************************************************************************
4376 Handle remote api calls
4377 ****************************************************************************/
4378
4379int api_reply(connection_struct *conn,uint16 vuid,char *outbuf,char *data,char *params,
4380 int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
4381{
4382 int api_command;
4383 char *rdata = NULL;
4384 char *rparam = NULL;
4385 const char *name1 = NULL;
4386 const char *name2 = NULL;
4387 int rdata_len = 0;
4388 int rparam_len = 0;
4389 BOOL reply=False;
4390 int i;
4391
4392 if (!params) {
4393 DEBUG(0,("ERROR: NULL params in api_reply()\n"));
4394 return 0;
4395 }
4396
4397 if (tpscnt < 2) {
4398 return 0;
4399 }
4400 api_command = SVAL(params,0);
4401 /* Is there a string at position params+2 ? */
4402 if (skip_string(params,tpscnt,params+2)) {
4403 name1 = params + 2;
4404 } else {
4405 name1 = "";
4406 }
4407 name2 = skip_string(params,tpscnt,params+2);
4408 if (!name2) {
4409 name2 = "";
4410 }
4411
4412 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
4413 api_command,
4414 name1,
4415 name2,
4416 tdscnt,tpscnt,mdrcnt,mprcnt));
4417
4418 for (i=0;api_commands[i].name;i++) {
4419 if (api_commands[i].id == api_command && api_commands[i].fn) {
4420 DEBUG(3,("Doing %s\n",api_commands[i].name));
4421 break;
4422 }
4423 }
4424
4425 /* Check whether this api call can be done anonymously */
4426
4427 if (api_commands[i].auth_user && lp_restrict_anonymous()) {
4428 user_struct *user = get_valid_user_struct(vuid);
4429
4430 if (!user || user->guest) {
4431 return ERROR_NT(NT_STATUS_ACCESS_DENIED);
4432 }
4433 }
4434
4435 rdata = (char *)SMB_MALLOC(1024);
4436 if (rdata) {
4437 memset(rdata,'\0',1024);
4438 }
4439
4440 rparam = (char *)SMB_MALLOC(1024);
4441 if (rparam) {
4442 memset(rparam,'\0',1024);
4443 }
4444
4445 if(!rdata || !rparam) {
4446 DEBUG(0,("api_reply: malloc fail !\n"));
4447 SAFE_FREE(rdata);
4448 SAFE_FREE(rparam);
4449 return -1;
4450 }
4451
4452 reply = api_commands[i].fn(conn,
4453 vuid,
4454 params,tpscnt, /* params + length */
4455 data,tdscnt, /* data + length */
4456 mdrcnt,mprcnt,
4457 &rdata,&rparam,&rdata_len,&rparam_len);
4458
4459
4460 if (rdata_len > mdrcnt || rparam_len > mprcnt) {
4461 reply = api_TooSmall(conn,vuid,params,data,mdrcnt,mprcnt,
4462 &rdata,&rparam,&rdata_len,&rparam_len);
4463 }
4464
4465 /* if we get False back then it's actually unsupported */
4466 if (!reply) {
4467 reply = api_Unsupported(conn,vuid,params,tpscnt,data,tdscnt,mdrcnt,mprcnt,
4468 &rdata,&rparam,&rdata_len,&rparam_len);
4469 }
4470
4471 /* If api_Unsupported returns false we can't return anything. */
4472 if (reply) {
4473 send_trans_reply(outbuf, rparam, rparam_len, rdata, rdata_len, False);
4474 }
4475
4476 SAFE_FREE(rdata);
4477 SAFE_FREE(rparam);
4478 return -1;
4479}
Note: See TracBrowser for help on using the repository browser.