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

Last change on this file since 223 was 105, checked in by Paul Smedley, 18 years ago

Update source to 3.0.27a

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, sizeof(s->comment))) {
1141 continue;
1142 }
1143 if (!next_token(&ptr,s->domain, NULL, sizeof(s->domain))) {
1144 /* this allows us to cope with an old nmbd */
1145 fstrcpy(s->domain,lp_workgroup());
1146 }
1147
1148 if (sscanf(stype,"%X",&s->type) != 1) {
1149 DEBUG(4,("r:host file "));
1150 ok = False;
1151 }
1152
1153 /* Filter the servers/domains we return based on what was asked for. */
1154
1155 /* Check to see if we are being asked for a local list only. */
1156 if(local_list_only && ((s->type & SV_TYPE_LOCAL_LIST_ONLY) == 0)) {
1157 DEBUG(4,("r: local list only"));
1158 ok = False;
1159 }
1160
1161 /* doesn't match up: don't want it */
1162 if (!(servertype & s->type)) {
1163 DEBUG(4,("r:serv type "));
1164 ok = False;
1165 }
1166
1167 if ((servertype & SV_TYPE_DOMAIN_ENUM) !=
1168 (s->type & SV_TYPE_DOMAIN_ENUM)) {
1169 DEBUG(4,("s: dom mismatch "));
1170 ok = False;
1171 }
1172
1173 if (!strequal(domain, s->domain) && !(servertype & SV_TYPE_DOMAIN_ENUM)) {
1174 ok = False;
1175 }
1176
1177 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
1178 s->type &= ~SV_TYPE_LOCAL_LIST_ONLY;
1179
1180 if (ok) {
1181 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
1182 s->name, s->type, s->comment, s->domain));
1183 s->server_added = True;
1184 count++;
1185 } else {
1186 DEBUG(4,("%20s %8x %25s %15s\n",
1187 s->name, s->type, s->comment, s->domain));
1188 }
1189 }
1190
1191 file_lines_free(lines);
1192 return count;
1193}
1194
1195/*******************************************************************
1196 Fill in a server info structure.
1197******************************************************************/
1198
1199static int fill_srv_info(struct srv_info_struct *service,
1200 int uLevel, char **buf, int *buflen,
1201 char **stringbuf, int *stringspace, char *baseaddr)
1202{
1203 int struct_len;
1204 char* p;
1205 char* p2;
1206 int l2;
1207 int len;
1208
1209 switch (uLevel) {
1210 case 0:
1211 struct_len = 16;
1212 break;
1213 case 1:
1214 struct_len = 26;
1215 break;
1216 default:
1217 return -1;
1218 }
1219
1220 if (!buf) {
1221 len = 0;
1222 switch (uLevel) {
1223 case 1:
1224 len = strlen(service->comment)+1;
1225 break;
1226 }
1227
1228 *buflen = struct_len;
1229 *stringspace = len;
1230 return struct_len + len;
1231 }
1232
1233 len = struct_len;
1234 p = *buf;
1235 if (*buflen < struct_len) {
1236 return -1;
1237 }
1238 if (stringbuf) {
1239 p2 = *stringbuf;
1240 l2 = *stringspace;
1241 } else {
1242 p2 = p + struct_len;
1243 l2 = *buflen - struct_len;
1244 }
1245 if (!baseaddr) {
1246 baseaddr = p;
1247 }
1248
1249 switch (uLevel) {
1250 case 0:
1251 push_ascii(p,service->name, MAX_NETBIOSNAME_LEN, STR_TERMINATE);
1252 break;
1253
1254 case 1:
1255 push_ascii(p,service->name,MAX_NETBIOSNAME_LEN, STR_TERMINATE);
1256 SIVAL(p,18,service->type);
1257 SIVAL(p,22,PTR_DIFF(p2,baseaddr));
1258 len += CopyAndAdvance(&p2,service->comment,&l2);
1259 break;
1260 }
1261
1262 if (stringbuf) {
1263 *buf = p + struct_len;
1264 *buflen -= struct_len;
1265 *stringbuf = p2;
1266 *stringspace = l2;
1267 } else {
1268 *buf = p2;
1269 *buflen -= len;
1270 }
1271 return len;
1272}
1273
1274
1275static BOOL srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2)
1276{
1277 return(strcmp(s1->name,s2->name));
1278}
1279
1280/****************************************************************************
1281 View list of servers available (or possibly domains). The info is
1282 extracted from lists saved by nmbd on the local host.
1283****************************************************************************/
1284
1285static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid,
1286 char *param, int tpscnt,
1287 char *data, int tdscnt,
1288 int mdrcnt, int mprcnt, char **rdata,
1289 char **rparam, int *rdata_len, int *rparam_len)
1290{
1291 char *str1 = get_safe_str_ptr(param, tpscnt, param, 2);
1292 char *str2 = skip_string(param,tpscnt,str1);
1293 char *p = skip_string(param,tpscnt,str2);
1294 int uLevel = get_safe_SVAL(param, tpscnt, p, 0, -1);
1295 int buf_len = get_safe_SVAL(param,tpscnt, p, 2, 0);
1296 uint32 servertype = get_safe_IVAL(param,tpscnt,p,4, 0);
1297 char *p2;
1298 int data_len, fixed_len, string_len;
1299 int f_len = 0, s_len = 0;
1300 struct srv_info_struct *servers=NULL;
1301 int counted=0,total=0;
1302 int i,missed;
1303 fstring domain;
1304 BOOL domain_request;
1305 BOOL local_request;
1306
1307 if (!str1 || !str2 || !p) {
1308 return False;
1309 }
1310
1311 /* If someone sets all the bits they don't really mean to set
1312 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1313 known servers. */
1314
1315 if (servertype == SV_TYPE_ALL) {
1316 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1317 }
1318
1319 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1320 any other bit (they may just set this bit on it's own) they
1321 want all the locally seen servers. However this bit can be
1322 set on its own so set the requested servers to be
1323 ALL - DOMAIN_ENUM. */
1324
1325 if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) && !(servertype & SV_TYPE_DOMAIN_ENUM)) {
1326 servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM);
1327 }
1328
1329 domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
1330 local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0);
1331
1332 p += 8;
1333
1334 if (!prefix_ok(str1,"WrLehD")) {
1335 return False;
1336 }
1337 if (!check_server_info(uLevel,str2)) {
1338 return False;
1339 }
1340
1341 DEBUG(4, ("server request level: %s %8x ", str2, servertype));
1342 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
1343 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
1344
1345 if (strcmp(str1, "WrLehDz") == 0) {
1346 if (skip_string(param,tpscnt,p) == NULL) {
1347 return False;
1348 }
1349 pull_ascii_fstring(domain, p);
1350 } else {
1351 fstrcpy(domain, lp_workgroup());
1352 }
1353
1354 if (lp_browse_list()) {
1355 total = get_server_info(servertype,&servers,domain);
1356 }
1357
1358 data_len = fixed_len = string_len = 0;
1359 missed = 0;
1360
1361 if (total > 0) {
1362 qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp);
1363 }
1364
1365 {
1366 char *lastname=NULL;
1367
1368 for (i=0;i<total;i++) {
1369 struct srv_info_struct *s = &servers[i];
1370
1371 if (lastname && strequal(lastname,s->name)) {
1372 continue;
1373 }
1374 lastname = s->name;
1375 data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
1376 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1377 s->name, s->type, s->comment, s->domain));
1378
1379 if (data_len <= buf_len) {
1380 counted++;
1381 fixed_len += f_len;
1382 string_len += s_len;
1383 } else {
1384 missed++;
1385 }
1386 }
1387 }
1388
1389 *rdata_len = fixed_len + string_len;
1390 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
1391 if (!*rdata) {
1392 return False;
1393 }
1394 memset(*rdata,'\0',*rdata_len);
1395
1396 p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */
1397 p = *rdata;
1398 f_len = fixed_len;
1399 s_len = string_len;
1400
1401 {
1402 char *lastname=NULL;
1403 int count2 = counted;
1404
1405 for (i = 0; i < total && count2;i++) {
1406 struct srv_info_struct *s = &servers[i];
1407
1408 if (lastname && strequal(lastname,s->name)) {
1409 continue;
1410 }
1411 lastname = s->name;
1412 fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
1413 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1414 s->name, s->type, s->comment, s->domain));
1415 count2--;
1416 }
1417 }
1418
1419 *rparam_len = 8;
1420 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1421 if (!*rparam) {
1422 return False;
1423 }
1424 SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERRmoredata));
1425 SSVAL(*rparam,2,0);
1426 SSVAL(*rparam,4,counted);
1427 SSVAL(*rparam,6,counted+missed);
1428
1429 SAFE_FREE(servers);
1430
1431 DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
1432 domain,uLevel,counted,counted+missed));
1433
1434 return True;
1435}
1436
1437/****************************************************************************
1438 command 0x34 - suspected of being a "Lookup Names" stub api
1439 ****************************************************************************/
1440
1441static BOOL api_RNetGroupGetUsers(connection_struct *conn, uint16 vuid,
1442 char *param, int tpscnt,
1443 char *data, int tdscnt,
1444 int mdrcnt, int mprcnt, char **rdata,
1445 char **rparam, int *rdata_len, int *rparam_len)
1446{
1447 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
1448 char *str2 = skip_string(param,tpscnt,str1);
1449 char *p = skip_string(param,tpscnt,str2);
1450 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
1451 int buf_len = get_safe_SVAL(param,tpscnt,p,2,0);
1452 int counted=0;
1453 int missed=0;
1454
1455 if (!str1 || !str2 || !p) {
1456 return False;
1457 }
1458
1459 DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
1460 str1, str2, p, uLevel, buf_len));
1461
1462 if (!prefix_ok(str1,"zWrLeh")) {
1463 return False;
1464 }
1465
1466 *rdata_len = 0;
1467
1468 *rparam_len = 8;
1469 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1470 if (!*rparam) {
1471 return False;
1472 }
1473
1474 SSVAL(*rparam,0,0x08AC); /* informational warning message */
1475 SSVAL(*rparam,2,0);
1476 SSVAL(*rparam,4,counted);
1477 SSVAL(*rparam,6,counted+missed);
1478
1479 return True;
1480}
1481
1482/****************************************************************************
1483 get info about a share
1484 ****************************************************************************/
1485
1486static BOOL check_share_info(int uLevel, char* id)
1487{
1488 switch( uLevel ) {
1489 case 0:
1490 if (strcmp(id,"B13") != 0) {
1491 return False;
1492 }
1493 break;
1494 case 1:
1495 if (strcmp(id,"B13BWz") != 0) {
1496 return False;
1497 }
1498 break;
1499 case 2:
1500 if (strcmp(id,"B13BWzWWWzB9B") != 0) {
1501 return False;
1502 }
1503 break;
1504 case 91:
1505 if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) {
1506 return False;
1507 }
1508 break;
1509 default:
1510 return False;
1511 }
1512 return True;
1513}
1514
1515static int fill_share_info(connection_struct *conn, int snum, int uLevel,
1516 char** buf, int* buflen,
1517 char** stringbuf, int* stringspace, char* baseaddr)
1518{
1519 int struct_len;
1520 char* p;
1521 char* p2;
1522 int l2;
1523 int len;
1524
1525 switch( uLevel ) {
1526 case 0:
1527 struct_len = 13;
1528 break;
1529 case 1:
1530 struct_len = 20;
1531 break;
1532 case 2:
1533 struct_len = 40;
1534 break;
1535 case 91:
1536 struct_len = 68;
1537 break;
1538 default:
1539 return -1;
1540 }
1541
1542
1543 if (!buf) {
1544 len = 0;
1545
1546 if (uLevel > 0) {
1547 len += StrlenExpanded(conn,snum,lp_comment(snum));
1548 }
1549 if (uLevel > 1) {
1550 len += strlen(lp_pathname(snum)) + 1;
1551 }
1552 if (buflen) {
1553 *buflen = struct_len;
1554 }
1555 if (stringspace) {
1556 *stringspace = len;
1557 }
1558 return struct_len + len;
1559 }
1560
1561 len = struct_len;
1562 p = *buf;
1563 if ((*buflen) < struct_len) {
1564 return -1;
1565 }
1566
1567 if (stringbuf) {
1568 p2 = *stringbuf;
1569 l2 = *stringspace;
1570 } else {
1571 p2 = p + struct_len;
1572 l2 = (*buflen) - struct_len;
1573 }
1574
1575 if (!baseaddr) {
1576 baseaddr = p;
1577 }
1578
1579 push_ascii(p,lp_servicename(snum),13, STR_TERMINATE);
1580
1581 if (uLevel > 0) {
1582 int type;
1583
1584 SCVAL(p,13,0);
1585 type = STYPE_DISKTREE;
1586 if (lp_print_ok(snum)) {
1587 type = STYPE_PRINTQ;
1588 }
1589 if (strequal("IPC",lp_fstype(snum))) {
1590 type = STYPE_IPC;
1591 }
1592 SSVAL(p,14,type); /* device type */
1593 SIVAL(p,16,PTR_DIFF(p2,baseaddr));
1594 len += CopyExpanded(conn,snum,&p2,lp_comment(snum),&l2);
1595 }
1596
1597 if (uLevel > 1) {
1598 SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */
1599 SSVALS(p,22,-1); /* max uses */
1600 SSVAL(p,24,1); /* current uses */
1601 SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */
1602 len += CopyAndAdvance(&p2,lp_pathname(snum),&l2);
1603 memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */
1604 }
1605
1606 if (uLevel > 2) {
1607 memset(p+40,0,SHPWLEN+2);
1608 SSVAL(p,50,0);
1609 SIVAL(p,52,0);
1610 SSVAL(p,56,0);
1611 SSVAL(p,58,0);
1612 SIVAL(p,60,0);
1613 SSVAL(p,64,0);
1614 SSVAL(p,66,0);
1615 }
1616
1617 if (stringbuf) {
1618 (*buf) = p + struct_len;
1619 (*buflen) -= struct_len;
1620 (*stringbuf) = p2;
1621 (*stringspace) = l2;
1622 } else {
1623 (*buf) = p2;
1624 (*buflen) -= len;
1625 }
1626
1627 return len;
1628}
1629
1630static BOOL api_RNetShareGetInfo(connection_struct *conn,uint16 vuid,
1631 char *param, int tpscnt,
1632 char *data, int tdscnt,
1633 int mdrcnt,int mprcnt,
1634 char **rdata,char **rparam,
1635 int *rdata_len,int *rparam_len)
1636{
1637 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
1638 char *str2 = skip_string(param,tpscnt,str1);
1639 char *netname = skip_string(param,tpscnt,str2);
1640 char *p = skip_string(param,tpscnt,netname);
1641 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
1642 int snum;
1643
1644 if (!str1 || !str2 || !netname || !p) {
1645 return False;
1646 }
1647
1648 snum = find_service(netname);
1649 if (snum < 0) {
1650 return False;
1651 }
1652
1653 /* check it's a supported varient */
1654 if (!prefix_ok(str1,"zWrLh")) {
1655 return False;
1656 }
1657 if (!check_share_info(uLevel,str2)) {
1658 return False;
1659 }
1660
1661 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
1662 if (!*rdata) {
1663 return False;
1664 }
1665 p = *rdata;
1666 *rdata_len = fill_share_info(conn,snum,uLevel,&p,&mdrcnt,0,0,0);
1667 if (*rdata_len < 0) {
1668 return False;
1669 }
1670
1671 *rparam_len = 6;
1672 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1673 if (!*rparam) {
1674 return False;
1675 }
1676 SSVAL(*rparam,0,NERR_Success);
1677 SSVAL(*rparam,2,0); /* converter word */
1678 SSVAL(*rparam,4,*rdata_len);
1679
1680 return True;
1681}
1682
1683/****************************************************************************
1684 View the list of available shares.
1685
1686 This function is the server side of the NetShareEnum() RAP call.
1687 It fills the return buffer with share names and share comments.
1688 Note that the return buffer normally (in all known cases) allows only
1689 twelve byte strings for share names (plus one for a nul terminator).
1690 Share names longer than 12 bytes must be skipped.
1691 ****************************************************************************/
1692
1693static BOOL api_RNetShareEnum( connection_struct *conn, uint16 vuid,
1694 char *param, int tpscnt,
1695 char *data, int tdscnt,
1696 int mdrcnt,
1697 int mprcnt,
1698 char **rdata,
1699 char **rparam,
1700 int *rdata_len,
1701 int *rparam_len )
1702{
1703 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
1704 char *str2 = skip_string(param,tpscnt,str1);
1705 char *p = skip_string(param,tpscnt,str2);
1706 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
1707 int buf_len = get_safe_SVAL(param,tpscnt,p,2,0);
1708 char *p2;
1709 int count = 0;
1710 int total=0,counted=0;
1711 BOOL missed = False;
1712 int i;
1713 int data_len, fixed_len, string_len;
1714 int f_len = 0, s_len = 0;
1715
1716 if (!str1 || !str2 || !p) {
1717 return False;
1718 }
1719
1720 if (!prefix_ok(str1,"WrLeh")) {
1721 return False;
1722 }
1723 if (!check_share_info(uLevel,str2)) {
1724 return False;
1725 }
1726
1727 /* Ensure all the usershares are loaded. */
1728 become_root();
1729 count = load_usershare_shares();
1730 unbecome_root();
1731
1732 data_len = fixed_len = string_len = 0;
1733 for (i=0;i<count;i++) {
1734 fstring servicename_dos;
1735 if (!(lp_browseable(i) && lp_snum_ok(i))) {
1736 continue;
1737 }
1738 push_ascii_fstring(servicename_dos, lp_servicename(i));
1739 /* Maximum name length = 13. */
1740 if( lp_browseable( i ) && lp_snum_ok( i ) && (strlen(servicename_dos) < 13)) {
1741 total++;
1742 data_len += fill_share_info(conn,i,uLevel,0,&f_len,0,&s_len,0);
1743 if (data_len <= buf_len) {
1744 counted++;
1745 fixed_len += f_len;
1746 string_len += s_len;
1747 } else {
1748 missed = True;
1749 }
1750 }
1751 }
1752
1753 *rdata_len = fixed_len + string_len;
1754 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
1755 if (!*rdata) {
1756 return False;
1757 }
1758 memset(*rdata,0,*rdata_len);
1759
1760 p2 = (*rdata) + fixed_len; /* auxiliary data (strings) will go here */
1761 p = *rdata;
1762 f_len = fixed_len;
1763 s_len = string_len;
1764
1765 for( i = 0; i < count; i++ ) {
1766 fstring servicename_dos;
1767 if (!(lp_browseable(i) && lp_snum_ok(i))) {
1768 continue;
1769 }
1770
1771 push_ascii_fstring(servicename_dos, lp_servicename(i));
1772 if (lp_browseable(i) && lp_snum_ok(i) && (strlen(servicename_dos) < 13)) {
1773 if (fill_share_info( conn,i,uLevel,&p,&f_len,&p2,&s_len,*rdata ) < 0) {
1774 break;
1775 }
1776 }
1777 }
1778
1779 *rparam_len = 8;
1780 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1781 if (!*rparam) {
1782 return False;
1783 }
1784 SSVAL(*rparam,0,missed ? ERRmoredata : NERR_Success);
1785 SSVAL(*rparam,2,0);
1786 SSVAL(*rparam,4,counted);
1787 SSVAL(*rparam,6,total);
1788
1789 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
1790 counted,total,uLevel,
1791 buf_len,*rdata_len,mdrcnt));
1792
1793 return True;
1794}
1795
1796/****************************************************************************
1797 Add a share
1798 ****************************************************************************/
1799
1800static BOOL api_RNetShareAdd(connection_struct *conn,uint16 vuid,
1801 char *param, int tpscnt,
1802 char *data, int tdscnt,
1803 int mdrcnt,int mprcnt,
1804 char **rdata,char **rparam,
1805 int *rdata_len,int *rparam_len)
1806{
1807 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
1808 char *str2 = skip_string(param,tpscnt,str1);
1809 char *p = skip_string(param,tpscnt,str2);
1810 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
1811 fstring sharename;
1812 fstring comment;
1813 pstring pathname;
1814 char *command, *cmdname;
1815 unsigned int offset;
1816 int snum;
1817 int res = ERRunsup;
1818
1819 if (!str1 || !str2 || !p) {
1820 return False;
1821 }
1822
1823 /* check it's a supported varient */
1824 if (!prefix_ok(str1,RAP_WShareAdd_REQ)) {
1825 return False;
1826 }
1827 if (!check_share_info(uLevel,str2)) {
1828 return False;
1829 }
1830 if (uLevel != 2) {
1831 return False;
1832 }
1833
1834 /* Do we have a string ? */
1835 if (skip_string(data,mdrcnt,data) == NULL) {
1836 return False;
1837 }
1838 pull_ascii_fstring(sharename,data);
1839 snum = find_service(sharename);
1840 if (snum >= 0) { /* already exists */
1841 res = ERRfilexists;
1842 goto error_exit;
1843 }
1844
1845 if (mdrcnt < 28) {
1846 return False;
1847 }
1848
1849 /* only support disk share adds */
1850 if (SVAL(data,14)!=STYPE_DISKTREE) {
1851 return False;
1852 }
1853
1854 offset = IVAL(data, 16);
1855 if (offset >= mdrcnt) {
1856 res = ERRinvalidparam;
1857 goto error_exit;
1858 }
1859
1860 /* Do we have a string ? */
1861 if (skip_string(data,mdrcnt,data+offset) == NULL) {
1862 return False;
1863 }
1864 pull_ascii_fstring(comment, offset? (data+offset) : "");
1865
1866 offset = IVAL(data, 26);
1867
1868 if (offset >= mdrcnt) {
1869 res = ERRinvalidparam;
1870 goto error_exit;
1871 }
1872
1873 /* Do we have a string ? */
1874 if (skip_string(data,mdrcnt,data+offset) == NULL) {
1875 return False;
1876 }
1877 pull_ascii_pstring(pathname, offset? (data+offset) : "");
1878
1879 string_replace(sharename, '"', ' ');
1880 string_replace(pathname, '"', ' ');
1881 string_replace(comment, '"', ' ');
1882
1883 cmdname = lp_add_share_cmd();
1884
1885 if (!cmdname || *cmdname == '\0') {
1886 return False;
1887 }
1888
1889 asprintf(&command, "%s \"%s\" \"%s\" \"%s\" \"%s\"",
1890 lp_add_share_cmd(), dyn_CONFIGFILE, sharename, pathname, comment);
1891
1892 if (command) {
1893 DEBUG(10,("api_RNetShareAdd: Running [%s]\n", command ));
1894
1895 if ((res = smbrun(command, NULL)) != 0) {
1896 DEBUG(1,("api_RNetShareAdd: Running [%s] returned (%d)\n", command, res ));
1897 SAFE_FREE(command);
1898 res = ERRnoaccess;
1899 goto error_exit;
1900 } else {
1901 SAFE_FREE(command);
1902 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
1903 }
1904 } else {
1905 return False;
1906 }
1907
1908 *rparam_len = 6;
1909 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1910 if (!*rparam) {
1911 return False;
1912 }
1913 SSVAL(*rparam,0,NERR_Success);
1914 SSVAL(*rparam,2,0); /* converter word */
1915 SSVAL(*rparam,4,*rdata_len);
1916 *rdata_len = 0;
1917
1918 return True;
1919
1920 error_exit:
1921
1922 *rparam_len = 4;
1923 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1924 if (!*rparam) {
1925 return False;
1926 }
1927 *rdata_len = 0;
1928 SSVAL(*rparam,0,res);
1929 SSVAL(*rparam,2,0);
1930 return True;
1931}
1932
1933/****************************************************************************
1934 view list of groups available
1935 ****************************************************************************/
1936
1937static BOOL api_RNetGroupEnum(connection_struct *conn,uint16 vuid,
1938 char *param, int tpscnt,
1939 char *data, int tdscnt,
1940 int mdrcnt,int mprcnt,
1941 char **rdata,char **rparam,
1942 int *rdata_len,int *rparam_len)
1943{
1944 int i;
1945 int errflags=0;
1946 int resume_context, cli_buf_size;
1947 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
1948 char *str2 = skip_string(param,tpscnt,str1);
1949 char *p = skip_string(param,tpscnt,str2);
1950
1951 struct pdb_search *search;
1952 struct samr_displayentry *entries;
1953
1954 int num_entries;
1955
1956 if (!str1 || !str2 || !p) {
1957 return False;
1958 }
1959
1960 if (strcmp(str1,"WrLeh") != 0) {
1961 return False;
1962 }
1963
1964 /* parameters
1965 * W-> resume context (number of users to skip)
1966 * r -> return parameter pointer to receive buffer
1967 * L -> length of receive buffer
1968 * e -> return parameter number of entries
1969 * h -> return parameter total number of users
1970 */
1971
1972 if (strcmp("B21",str2) != 0) {
1973 return False;
1974 }
1975
1976 /* get list of domain groups SID_DOMAIN_GRP=2 */
1977 become_root();
1978 search = pdb_search_groups();
1979 unbecome_root();
1980
1981 if (search == NULL) {
1982 DEBUG(3,("api_RNetGroupEnum:failed to get group list"));
1983 return False;
1984 }
1985
1986 resume_context = get_safe_SVAL(param,tpscnt,p,0,-1);
1987 cli_buf_size= get_safe_SVAL(param,tpscnt,p,2,0);
1988 DEBUG(10,("api_RNetGroupEnum:resume context: %d, client buffer size: "
1989 "%d\n", resume_context, cli_buf_size));
1990
1991 become_root();
1992 num_entries = pdb_search_entries(search, resume_context, 0xffffffff,
1993 &entries);
1994 unbecome_root();
1995
1996 *rdata_len = cli_buf_size;
1997 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
1998 if (!*rdata) {
1999 return False;
2000 }
2001
2002 p = *rdata;
2003
2004 for(i=0; i<num_entries; i++) {
2005 fstring name;
2006 fstrcpy(name, entries[i].account_name);
2007 if( ((PTR_DIFF(p,*rdata)+21) <= *rdata_len) ) {
2008 /* truncate the name at 21 chars. */
2009 memcpy(p, name, 21);
2010 DEBUG(10,("adding entry %d group %s\n", i, p));
2011 p += 21;
2012 p += 5; /* Both NT4 and W2k3SP1 do padding here.
2013 No idea why... */
2014 } else {
2015 /* set overflow error */
2016 DEBUG(3,("overflow on entry %d group %s\n", i, name));
2017 errflags=234;
2018 break;
2019 }
2020 }
2021
2022 pdb_search_destroy(search);
2023
2024 *rdata_len = PTR_DIFF(p,*rdata);
2025
2026 *rparam_len = 8;
2027 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2028 if (!*rparam) {
2029 return False;
2030 }
2031 SSVAL(*rparam, 0, errflags);
2032 SSVAL(*rparam, 2, 0); /* converter word */
2033 SSVAL(*rparam, 4, i); /* is this right?? */
2034 SSVAL(*rparam, 6, resume_context+num_entries); /* is this right?? */
2035
2036 return(True);
2037}
2038
2039/*******************************************************************
2040 Get groups that a user is a member of.
2041******************************************************************/
2042
2043static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid,
2044 char *param, int tpscnt,
2045 char *data, int tdscnt,
2046 int mdrcnt,int mprcnt,
2047 char **rdata,char **rparam,
2048 int *rdata_len,int *rparam_len)
2049{
2050 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2051 char *str2 = skip_string(param,tpscnt,str1);
2052 char *UserName = skip_string(param,tpscnt,str2);
2053 char *p = skip_string(param,tpscnt,UserName);
2054 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
2055 const char *level_string;
2056 int count=0;
2057 struct samu *sampw = NULL;
2058 BOOL ret = False;
2059 DOM_SID *sids;
2060 gid_t *gids;
2061 size_t num_groups;
2062 size_t i;
2063 NTSTATUS result;
2064 DOM_SID user_sid;
2065 enum lsa_SidType type;
2066 TALLOC_CTX *mem_ctx;
2067
2068 if (!str1 || !str2 || !UserName || !p) {
2069 return False;
2070 }
2071
2072 *rparam_len = 8;
2073 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2074 if (!*rparam) {
2075 return False;
2076 }
2077
2078 /* check it's a supported varient */
2079
2080 if ( strcmp(str1,"zWrLeh") != 0 )
2081 return False;
2082
2083 switch( uLevel ) {
2084 case 0:
2085 level_string = "B21";
2086 break;
2087 default:
2088 return False;
2089 }
2090
2091 if (strcmp(level_string,str2) != 0)
2092 return False;
2093
2094 *rdata_len = mdrcnt + 1024;
2095 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
2096 if (!*rdata) {
2097 return False;
2098 }
2099 SSVAL(*rparam,0,NERR_Success);
2100 SSVAL(*rparam,2,0); /* converter word */
2101
2102 p = *rdata;
2103
2104 mem_ctx = talloc_new(NULL);
2105 if (mem_ctx == NULL) {
2106 DEBUG(0, ("talloc_new failed\n"));
2107 return False;
2108 }
2109
2110 if ( !(sampw = samu_new(mem_ctx)) ) {
2111 DEBUG(0, ("samu_new() failed!\n"));
2112 TALLOC_FREE(mem_ctx);
2113 return False;
2114 }
2115
2116 /* Lookup the user information; This should only be one of
2117 our accounts (not remote domains) */
2118
2119 become_root(); /* ROOT BLOCK */
2120
2121 if (!lookup_name(mem_ctx, UserName, LOOKUP_NAME_ALL,
2122 NULL, NULL, &user_sid, &type)) {
2123 DEBUG(10, ("lookup_name(%s) failed\n", UserName));
2124 goto done;
2125 }
2126
2127 if (type != SID_NAME_USER) {
2128 DEBUG(10, ("%s is a %s, not a user\n", UserName,
2129 sid_type_lookup(type)));
2130 goto done;
2131 }
2132
2133 if ( !pdb_getsampwsid(sampw, &user_sid) ) {
2134 DEBUG(10, ("pdb_getsampwsid(%s) failed for user %s\n",
2135 sid_string_static(&user_sid), UserName));
2136 goto done;
2137 }
2138
2139 gids = NULL;
2140 sids = NULL;
2141 num_groups = 0;
2142
2143 result = pdb_enum_group_memberships(mem_ctx, sampw,
2144 &sids, &gids, &num_groups);
2145
2146 if (!NT_STATUS_IS_OK(result)) {
2147 DEBUG(10, ("pdb_enum_group_memberships failed for %s\n",
2148 UserName));
2149 goto done;
2150 }
2151
2152 for (i=0; i<num_groups; i++) {
2153
2154 const char *grp_name;
2155
2156 if ( lookup_sid(mem_ctx, &sids[i], NULL, &grp_name, NULL) ) {
2157 pstrcpy(p, grp_name);
2158 p += 21;
2159 count++;
2160 }
2161 }
2162
2163 *rdata_len = PTR_DIFF(p,*rdata);
2164
2165 SSVAL(*rparam,4,count); /* is this right?? */
2166 SSVAL(*rparam,6,count); /* is this right?? */
2167
2168 ret = True;
2169
2170done:
2171 unbecome_root(); /* END ROOT BLOCK */
2172
2173 TALLOC_FREE(mem_ctx);
2174
2175 return ret;
2176}
2177
2178/*******************************************************************
2179 Get all users.
2180******************************************************************/
2181
2182static BOOL api_RNetUserEnum(connection_struct *conn, uint16 vuid,
2183 char *param, int tpscnt,
2184 char *data, int tdscnt,
2185 int mdrcnt,int mprcnt,
2186 char **rdata,char **rparam,
2187 int *rdata_len,int *rparam_len)
2188{
2189 int count_sent=0;
2190 int num_users=0;
2191 int errflags=0;
2192 int i, resume_context, cli_buf_size;
2193 struct pdb_search *search;
2194 struct samr_displayentry *users;
2195
2196 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2197 char *str2 = skip_string(param,tpscnt,str1);
2198 char *p = skip_string(param,tpscnt,str2);
2199
2200 if (!str1 || !str2 || !p) {
2201 return False;
2202 }
2203
2204 if (strcmp(str1,"WrLeh") != 0)
2205 return False;
2206 /* parameters
2207 * W-> resume context (number of users to skip)
2208 * r -> return parameter pointer to receive buffer
2209 * L -> length of receive buffer
2210 * e -> return parameter number of entries
2211 * h -> return parameter total number of users
2212 */
2213
2214 resume_context = get_safe_SVAL(param,tpscnt,p,0,-1);
2215 cli_buf_size= get_safe_SVAL(param,tpscnt,p,2,0);
2216 DEBUG(10,("api_RNetUserEnum:resume context: %d, client buffer size: %d\n",
2217 resume_context, cli_buf_size));
2218
2219 *rparam_len = 8;
2220 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2221 if (!*rparam) {
2222 return False;
2223 }
2224
2225 /* check it's a supported varient */
2226 if (strcmp("B21",str2) != 0)
2227 return False;
2228
2229 *rdata_len = cli_buf_size;
2230 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
2231 if (!*rdata) {
2232 return False;
2233 }
2234
2235 p = *rdata;
2236
2237 become_root();
2238 search = pdb_search_users(ACB_NORMAL);
2239 unbecome_root();
2240 if (search == NULL) {
2241 DEBUG(0, ("api_RNetUserEnum:unable to open sam database.\n"));
2242 return False;
2243 }
2244
2245 become_root();
2246 num_users = pdb_search_entries(search, resume_context, 0xffffffff,
2247 &users);
2248 unbecome_root();
2249
2250 errflags=NERR_Success;
2251
2252 for (i=0; i<num_users; i++) {
2253 const char *name = users[i].account_name;
2254
2255 if(((PTR_DIFF(p,*rdata)+21)<=*rdata_len)&&(strlen(name)<=21)) {
2256 pstrcpy(p,name);
2257 DEBUG(10,("api_RNetUserEnum:adding entry %d username "
2258 "%s\n",count_sent,p));
2259 p += 21;
2260 count_sent++;
2261 } else {
2262 /* set overflow error */
2263 DEBUG(10,("api_RNetUserEnum:overflow on entry %d "
2264 "username %s\n",count_sent,name));
2265 errflags=234;
2266 break;
2267 }
2268 }
2269
2270 pdb_search_destroy(search);
2271
2272 *rdata_len = PTR_DIFF(p,*rdata);
2273
2274 SSVAL(*rparam,0,errflags);
2275 SSVAL(*rparam,2,0); /* converter word */
2276 SSVAL(*rparam,4,count_sent); /* is this right?? */
2277 SSVAL(*rparam,6,num_users); /* is this right?? */
2278
2279 return True;
2280}
2281
2282/****************************************************************************
2283 Get the time of day info.
2284****************************************************************************/
2285
2286static BOOL api_NetRemoteTOD(connection_struct *conn,uint16 vuid,
2287 char *param, int tpscnt,
2288 char *data, int tdscnt,
2289 int mdrcnt,int mprcnt,
2290 char **rdata,char **rparam,
2291 int *rdata_len,int *rparam_len)
2292{
2293 struct tm *t;
2294 time_t unixdate = time(NULL);
2295 char *p;
2296
2297 *rparam_len = 4;
2298 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2299 if (!*rparam) {
2300 return False;
2301 }
2302
2303 *rdata_len = 21;
2304 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
2305 if (!*rdata) {
2306 return False;
2307 }
2308
2309 SSVAL(*rparam,0,NERR_Success);
2310 SSVAL(*rparam,2,0); /* converter word */
2311
2312 p = *rdata;
2313
2314 srv_put_dos_date3(p,0,unixdate); /* this is the time that is looked at
2315 by NT in a "net time" operation,
2316 it seems to ignore the one below */
2317
2318 /* the client expects to get localtime, not GMT, in this bit
2319 (I think, this needs testing) */
2320 t = localtime(&unixdate);
2321 if (!t) {
2322 return False;
2323 }
2324
2325 SIVAL(p,4,0); /* msecs ? */
2326 SCVAL(p,8,t->tm_hour);
2327 SCVAL(p,9,t->tm_min);
2328 SCVAL(p,10,t->tm_sec);
2329 SCVAL(p,11,0); /* hundredths of seconds */
2330 SSVALS(p,12,get_time_zone(unixdate)/60); /* timezone in minutes from GMT */
2331 SSVAL(p,14,10000); /* timer interval in 0.0001 of sec */
2332 SCVAL(p,16,t->tm_mday);
2333 SCVAL(p,17,t->tm_mon + 1);
2334 SSVAL(p,18,1900+t->tm_year);
2335 SCVAL(p,20,t->tm_wday);
2336
2337 return True;
2338}
2339
2340/****************************************************************************
2341 Set the user password.
2342*****************************************************************************/
2343
2344static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid,
2345 char *param, int tpscnt,
2346 char *data, int tdscnt,
2347 int mdrcnt,int mprcnt,
2348 char **rdata,char **rparam,
2349 int *rdata_len,int *rparam_len)
2350{
2351 char *np = get_safe_str_ptr(param,tpscnt,param,2);
2352 char *p = NULL;
2353 fstring user;
2354 fstring pass1,pass2;
2355
2356 /* Skip 2 strings. */
2357 p = skip_string(param,tpscnt,np);
2358 p = skip_string(param,tpscnt,p);
2359
2360 if (!np || !p) {
2361 return False;
2362 }
2363
2364 /* Do we have a string ? */
2365 if (skip_string(param,tpscnt,p) == NULL) {
2366 return False;
2367 }
2368 pull_ascii_fstring(user,p);
2369
2370 p = skip_string(param,tpscnt,p);
2371 if (!p) {
2372 return False;
2373 }
2374
2375 memset(pass1,'\0',sizeof(pass1));
2376 memset(pass2,'\0',sizeof(pass2));
2377 /*
2378 * We use 31 here not 32 as we're checking
2379 * the last byte we want to access is safe.
2380 */
2381 if (!is_offset_safe(param,tpscnt,p,31)) {
2382 return False;
2383 }
2384 memcpy(pass1,p,16);
2385 memcpy(pass2,p+16,16);
2386
2387 *rparam_len = 4;
2388 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2389 if (!*rparam) {
2390 return False;
2391 }
2392
2393 *rdata_len = 0;
2394
2395 SSVAL(*rparam,0,NERR_badpass);
2396 SSVAL(*rparam,2,0); /* converter word */
2397
2398 DEBUG(3,("Set password for <%s>\n",user));
2399
2400 /*
2401 * Attempt to verify the old password against smbpasswd entries
2402 * Win98 clients send old and new password in plaintext for this call.
2403 */
2404
2405 {
2406 auth_serversupplied_info *server_info = NULL;
2407 DATA_BLOB password = data_blob(pass1, strlen(pass1)+1);
2408
2409 if (NT_STATUS_IS_OK(check_plaintext_password(user,password,&server_info))) {
2410
2411 become_root();
2412 if (NT_STATUS_IS_OK(change_oem_password(server_info->sam_account, pass1, pass2, False, NULL))) {
2413 SSVAL(*rparam,0,NERR_Success);
2414 }
2415 unbecome_root();
2416
2417 TALLOC_FREE(server_info);
2418 }
2419 data_blob_clear_free(&password);
2420 }
2421
2422 /*
2423 * If the plaintext change failed, attempt
2424 * the old encrypted method. NT will generate this
2425 * after trying the samr method. Note that this
2426 * method is done as a last resort as this
2427 * password change method loses the NT password hash
2428 * and cannot change the UNIX password as no plaintext
2429 * is received.
2430 */
2431
2432 if(SVAL(*rparam,0) != NERR_Success) {
2433 struct samu *hnd = NULL;
2434
2435 if (check_lanman_password(user,(unsigned char *)pass1,(unsigned char *)pass2, &hnd)) {
2436 become_root();
2437 if (change_lanman_password(hnd,(uchar *)pass2)) {
2438 SSVAL(*rparam,0,NERR_Success);
2439 }
2440 unbecome_root();
2441 TALLOC_FREE(hnd);
2442 }
2443 }
2444
2445 memset((char *)pass1,'\0',sizeof(fstring));
2446 memset((char *)pass2,'\0',sizeof(fstring));
2447
2448 return(True);
2449}
2450
2451/****************************************************************************
2452 Set the user password (SamOEM version - gets plaintext).
2453****************************************************************************/
2454
2455static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid,
2456 char *param, int tpscnt,
2457 char *data, int tdscnt,
2458 int mdrcnt,int mprcnt,
2459 char **rdata,char **rparam,
2460 int *rdata_len,int *rparam_len)
2461{
2462 fstring user;
2463 char *p = get_safe_str_ptr(param,tpscnt,param,2);
2464 *rparam_len = 2;
2465 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2466 if (!*rparam) {
2467 return False;
2468 }
2469
2470 if (!p) {
2471 return False;
2472 }
2473 *rdata_len = 0;
2474
2475 SSVAL(*rparam,0,NERR_badpass);
2476
2477 /*
2478 * Check the parameter definition is correct.
2479 */
2480
2481 /* Do we have a string ? */
2482 if (skip_string(param,tpscnt,p) == 0) {
2483 return False;
2484 }
2485 if(!strequal(p, "zsT")) {
2486 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", p));
2487 return False;
2488 }
2489 p = skip_string(param, tpscnt, p);
2490 if (!p) {
2491 return False;
2492 }
2493
2494 /* Do we have a string ? */
2495 if (skip_string(param,tpscnt,p) == 0) {
2496 return False;
2497 }
2498 if(!strequal(p, "B516B16")) {
2499 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p));
2500 return False;
2501 }
2502 p = skip_string(param,tpscnt,p);
2503 if (!p) {
2504 return False;
2505 }
2506 /* Do we have a string ? */
2507 if (skip_string(param,tpscnt,p) == 0) {
2508 return False;
2509 }
2510 p += pull_ascii_fstring(user,p);
2511
2512 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user));
2513
2514 /*
2515 * Pass the user through the NT -> unix user mapping
2516 * function.
2517 */
2518
2519 (void)map_username(user);
2520
2521 if (NT_STATUS_IS_OK(pass_oem_change(user, (uchar*) data, (uchar *)&data[516], NULL, NULL, NULL))) {
2522 SSVAL(*rparam,0,NERR_Success);
2523 }
2524
2525 return(True);
2526}
2527
2528/****************************************************************************
2529 delete a print job
2530 Form: <W> <>
2531 ****************************************************************************/
2532
2533static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid,
2534 char *param, int tpscnt,
2535 char *data, int tdscnt,
2536 int mdrcnt,int mprcnt,
2537 char **rdata,char **rparam,
2538 int *rdata_len,int *rparam_len)
2539{
2540 int function = get_safe_SVAL(param,tpscnt,param,0,0);
2541 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2542 char *str2 = skip_string(param,tpscnt,str1);
2543 char *p = skip_string(param,tpscnt,str2);
2544 uint32 jobid;
2545 int snum;
2546 fstring sharename;
2547 int errcode;
2548 WERROR werr = WERR_OK;
2549
2550 if (!str1 || !str2 || !p) {
2551 return False;
2552 }
2553 /*
2554 * We use 1 here not 2 as we're checking
2555 * the last byte we want to access is safe.
2556 */
2557 if (!is_offset_safe(param,tpscnt,p,1)) {
2558 return False;
2559 }
2560 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid))
2561 return False;
2562
2563 /* check it's a supported varient */
2564 if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
2565 return(False);
2566
2567 *rparam_len = 4;
2568 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2569 if (!*rparam) {
2570 return False;
2571 }
2572 *rdata_len = 0;
2573
2574 if (!print_job_exists(sharename, jobid)) {
2575 errcode = NERR_JobNotFound;
2576 goto out;
2577 }
2578
2579 snum = lp_servicenumber( sharename);
2580 if (snum == -1) {
2581 errcode = NERR_DestNotFound;
2582 goto out;
2583 }
2584
2585 errcode = NERR_notsupported;
2586
2587 switch (function) {
2588 case 81: /* delete */
2589 if (print_job_delete(&current_user, snum, jobid, &werr))
2590 errcode = NERR_Success;
2591 break;
2592 case 82: /* pause */
2593 if (print_job_pause(&current_user, snum, jobid, &werr))
2594 errcode = NERR_Success;
2595 break;
2596 case 83: /* resume */
2597 if (print_job_resume(&current_user, snum, jobid, &werr))
2598 errcode = NERR_Success;
2599 break;
2600 }
2601
2602 if (!W_ERROR_IS_OK(werr))
2603 errcode = W_ERROR_V(werr);
2604
2605 out:
2606 SSVAL(*rparam,0,errcode);
2607 SSVAL(*rparam,2,0); /* converter word */
2608
2609 return(True);
2610}
2611
2612/****************************************************************************
2613 Purge a print queue - or pause or resume it.
2614 ****************************************************************************/
2615
2616static BOOL api_WPrintQueueCtrl(connection_struct *conn,uint16 vuid,
2617 char *param, int tpscnt,
2618 char *data, int tdscnt,
2619 int mdrcnt,int mprcnt,
2620 char **rdata,char **rparam,
2621 int *rdata_len,int *rparam_len)
2622{
2623 int function = get_safe_SVAL(param,tpscnt,param,0,0);
2624 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2625 char *str2 = skip_string(param,tpscnt,str1);
2626 char *QueueName = skip_string(param,tpscnt,str2);
2627 int errcode = NERR_notsupported;
2628 int snum;
2629 WERROR werr = WERR_OK;
2630
2631 if (!str1 || !str2 || !QueueName) {
2632 return False;
2633 }
2634
2635 /* check it's a supported varient */
2636 if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
2637 return(False);
2638
2639 *rparam_len = 4;
2640 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2641 if (!*rparam) {
2642 return False;
2643 }
2644 *rdata_len = 0;
2645
2646 if (skip_string(param,tpscnt,QueueName) == NULL) {
2647 return False;
2648 }
2649 snum = print_queue_snum(QueueName);
2650
2651 if (snum == -1) {
2652 errcode = NERR_JobNotFound;
2653 goto out;
2654 }
2655
2656 switch (function) {
2657 case 74: /* Pause queue */
2658 if (print_queue_pause(&current_user, snum, &werr)) errcode = NERR_Success;
2659 break;
2660 case 75: /* Resume queue */
2661 if (print_queue_resume(&current_user, snum, &werr)) errcode = NERR_Success;
2662 break;
2663 case 103: /* Purge */
2664 if (print_queue_purge(&current_user, snum, &werr)) errcode = NERR_Success;
2665 break;
2666 }
2667
2668 if (!W_ERROR_IS_OK(werr)) errcode = W_ERROR_V(werr);
2669
2670 out:
2671 SSVAL(*rparam,0,errcode);
2672 SSVAL(*rparam,2,0); /* converter word */
2673
2674 return(True);
2675}
2676
2677/****************************************************************************
2678 set the property of a print job (undocumented?)
2679 ? function = 0xb -> set name of print job
2680 ? function = 0x6 -> move print job up/down
2681 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
2682 or <WWsTP> <WB21BB16B10zWWzDDz>
2683****************************************************************************/
2684
2685static int check_printjob_info(struct pack_desc* desc,
2686 int uLevel, char* id)
2687{
2688 desc->subformat = NULL;
2689 switch( uLevel ) {
2690 case 0: desc->format = "W"; break;
2691 case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
2692 case 2: desc->format = "WWzWWDDzz"; break;
2693 case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
2694 case 4: desc->format = "WWzWWDDzzzzzDDDDDDD"; break;
2695 default:
2696 DEBUG(0,("check_printjob_info: invalid level %d\n",
2697 uLevel ));
2698 return False;
2699 }
2700 if (id == NULL || strcmp(desc->format,id) != 0) {
2701 DEBUG(0,("check_printjob_info: invalid format %s\n",
2702 id ? id : "<NULL>" ));
2703 return False;
2704 }
2705 return True;
2706}
2707
2708static BOOL api_PrintJobInfo(connection_struct *conn, uint16 vuid,
2709 char *param, int tpscnt,
2710 char *data, int tdscnt,
2711 int mdrcnt,int mprcnt,
2712 char **rdata,char **rparam,
2713 int *rdata_len,int *rparam_len)
2714{
2715 struct pack_desc desc;
2716 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2717 char *str2 = skip_string(param,tpscnt,str1);
2718 char *p = skip_string(param,tpscnt,str2);
2719 uint32 jobid;
2720 fstring sharename;
2721 int uLevel = get_safe_SVAL(param,tpscnt,p,2,-1);
2722 int function = get_safe_SVAL(param,tpscnt,p,4,-1);
2723 int place, errcode;
2724
2725 if (!str1 || !str2 || !p) {
2726 return False;
2727 }
2728 /*
2729 * We use 1 here not 2 as we're checking
2730 * the last byte we want to access is safe.
2731 */
2732 if (!is_offset_safe(param,tpscnt,p,1)) {
2733 return False;
2734 }
2735 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid))
2736 return False;
2737 *rparam_len = 4;
2738 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2739 if (!*rparam) {
2740 return False;
2741 }
2742
2743 if (!share_defined(sharename)) {
2744 DEBUG(0,("api_PrintJobInfo: sharen [%s] not defined\n",
2745 sharename));
2746 return False;
2747 }
2748
2749 *rdata_len = 0;
2750
2751 /* check it's a supported varient */
2752 if ((strcmp(str1,"WWsTP")) ||
2753 (!check_printjob_info(&desc,uLevel,str2)))
2754 return(False);
2755
2756 if (!print_job_exists(sharename, jobid)) {
2757 errcode=NERR_JobNotFound;
2758 goto out;
2759 }
2760
2761 errcode = NERR_notsupported;
2762
2763 switch (function) {
2764 case 0x6:
2765 /* change job place in the queue,
2766 data gives the new place */
2767 place = SVAL(data,0);
2768 if (print_job_set_place(sharename, jobid, place)) {
2769 errcode=NERR_Success;
2770 }
2771 break;
2772
2773 case 0xb:
2774 /* change print job name, data gives the name */
2775 if (print_job_set_name(sharename, jobid, data)) {
2776 errcode=NERR_Success;
2777 }
2778 break;
2779
2780 default:
2781 return False;
2782 }
2783
2784 out:
2785 SSVALS(*rparam,0,errcode);
2786 SSVAL(*rparam,2,0); /* converter word */
2787
2788 return(True);
2789}
2790
2791
2792/****************************************************************************
2793 Get info about the server.
2794****************************************************************************/
2795
2796static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid,
2797 char *param, int tpscnt,
2798 char *data, int tdscnt,
2799 int mdrcnt,int mprcnt,
2800 char **rdata,char **rparam,
2801 int *rdata_len,int *rparam_len)
2802{
2803 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2804 char *str2 = skip_string(param,tpscnt,str1);
2805 char *p = skip_string(param,tpscnt,str2);
2806 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
2807 char *p2;
2808 int struct_len;
2809
2810 if (!str1 || !str2 || !p) {
2811 return False;
2812 }
2813
2814 DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
2815
2816 /* check it's a supported varient */
2817 if (!prefix_ok(str1,"WrLh")) {
2818 return False;
2819 }
2820
2821 switch( uLevel ) {
2822 case 0:
2823 if (strcmp(str2,"B16") != 0) {
2824 return False;
2825 }
2826 struct_len = 16;
2827 break;
2828 case 1:
2829 if (strcmp(str2,"B16BBDz") != 0) {
2830 return False;
2831 }
2832 struct_len = 26;
2833 break;
2834 case 2:
2835 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")!= 0) {
2836 return False;
2837 }
2838 struct_len = 134;
2839 break;
2840 case 3:
2841 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz") != 0) {
2842 return False;
2843 }
2844 struct_len = 144;
2845 break;
2846 case 20:
2847 if (strcmp(str2,"DN") != 0) {
2848 return False;
2849 }
2850 struct_len = 6;
2851 break;
2852 case 50:
2853 if (strcmp(str2,"B16BBDzWWzzz") != 0) {
2854 return False;
2855 }
2856 struct_len = 42;
2857 break;
2858 default:
2859 return False;
2860 }
2861
2862 *rdata_len = mdrcnt;
2863 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
2864 if (!*rdata) {
2865 return False;
2866 }
2867
2868 p = *rdata;
2869 p2 = p + struct_len;
2870 if (uLevel != 20) {
2871 srvstr_push(NULL, p,global_myname(),16,
2872 STR_ASCII|STR_UPPER|STR_TERMINATE);
2873 }
2874 p += 16;
2875 if (uLevel > 0) {
2876 struct srv_info_struct *servers=NULL;
2877 int i,count;
2878 pstring comment;
2879 uint32 servertype= lp_default_server_announce();
2880
2881 push_ascii(comment,lp_serverstring(), MAX_SERVER_STRING_LENGTH,STR_TERMINATE);
2882
2883 if ((count=get_server_info(SV_TYPE_ALL,&servers,lp_workgroup()))>0) {
2884 for (i=0;i<count;i++) {
2885 if (strequal(servers[i].name,global_myname())) {
2886 servertype = servers[i].type;
2887 push_ascii(comment,servers[i].comment,sizeof(pstring),STR_TERMINATE);
2888 }
2889 }
2890 }
2891
2892 SAFE_FREE(servers);
2893
2894 SCVAL(p,0,lp_major_announce_version());
2895 SCVAL(p,1,lp_minor_announce_version());
2896 SIVAL(p,2,servertype);
2897
2898 if (mdrcnt == struct_len) {
2899 SIVAL(p,6,0);
2900 } else {
2901 SIVAL(p,6,PTR_DIFF(p2,*rdata));
2902 standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
2903 conn->connectpath, conn->gid,
2904 get_current_username(),
2905 current_user_info.domain,
2906 comment, sizeof(comment));
2907 StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0));
2908 p2 = skip_string(*rdata,*rdata_len,p2);
2909 if (!p2) {
2910 return False;
2911 }
2912 }
2913 }
2914
2915 if (uLevel > 1) {
2916 return False; /* not yet implemented */
2917 }
2918
2919 *rdata_len = PTR_DIFF(p2,*rdata);
2920
2921 *rparam_len = 6;
2922 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2923 if (!*rparam) {
2924 return False;
2925 }
2926 SSVAL(*rparam,0,NERR_Success);
2927 SSVAL(*rparam,2,0); /* converter word */
2928 SSVAL(*rparam,4,*rdata_len);
2929
2930 return True;
2931}
2932
2933/****************************************************************************
2934 Get info about the server.
2935****************************************************************************/
2936
2937static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid,
2938 char *param, int tpscnt,
2939 char *data, int tdscnt,
2940 int mdrcnt,int mprcnt,
2941 char **rdata,char **rparam,
2942 int *rdata_len,int *rparam_len)
2943{
2944 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2945 char *str2 = skip_string(param,tpscnt,str1);
2946 char *p = skip_string(param,tpscnt,str2);
2947 char *p2;
2948 int level = get_safe_SVAL(param,tpscnt,p,0,-1);
2949
2950 if (!str1 || !str2 || !p) {
2951 return False;
2952 }
2953
2954 DEBUG(4,("NetWkstaGetInfo level %d\n",level));
2955
2956 *rparam_len = 6;
2957 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2958 if (!*rparam) {
2959 return False;
2960 }
2961
2962 /* check it's a supported varient */
2963 if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz"))) {
2964 return False;
2965 }
2966
2967 *rdata_len = mdrcnt + 1024;
2968 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
2969 if (!*rdata) {
2970 return False;
2971 }
2972
2973 SSVAL(*rparam,0,NERR_Success);
2974 SSVAL(*rparam,2,0); /* converter word */
2975
2976 p = *rdata;
2977 p2 = get_safe_ptr(*rdata,*rdata_len,p,22);
2978 if (!p2) {
2979 return False;
2980 }
2981
2982 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */
2983 pstrcpy(p2,get_local_machine_name());
2984 strupper_m(p2);
2985 p2 = skip_string(*rdata,*rdata_len,p2);
2986 if (!p2) {
2987 return False;
2988 }
2989 p += 4;
2990
2991 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2992 pstrcpy(p2,current_user_info.smb_name);
2993 p2 = skip_string(*rdata,*rdata_len,p2);
2994 if (!p2) {
2995 return False;
2996 }
2997 p += 4;
2998
2999 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
3000 pstrcpy(p2,lp_workgroup());
3001 strupper_m(p2);
3002 p2 = skip_string(*rdata,*rdata_len,p2);
3003 if (!p2) {
3004 return False;
3005 }
3006 p += 4;
3007
3008 SCVAL(p,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
3009 SCVAL(p,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
3010 p += 2;
3011
3012 SIVAL(p,0,PTR_DIFF(p2,*rdata));
3013 pstrcpy(p2,lp_workgroup()); /* don't know. login domain?? */
3014 p2 = skip_string(*rdata,*rdata_len,p2);
3015 if (!p2) {
3016 return False;
3017 }
3018 p += 4;
3019
3020 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */
3021 pstrcpy(p2,"");
3022 p2 = skip_string(*rdata,*rdata_len,p2);
3023 if (!p2) {
3024 return False;
3025 }
3026 p += 4;
3027
3028 *rdata_len = PTR_DIFF(p2,*rdata);
3029
3030 SSVAL(*rparam,4,*rdata_len);
3031
3032 return True;
3033}
3034
3035/****************************************************************************
3036 get info about a user
3037
3038 struct user_info_11 {
3039 char usri11_name[21]; 0-20
3040 char usri11_pad; 21
3041 char *usri11_comment; 22-25
3042 char *usri11_usr_comment; 26-29
3043 unsigned short usri11_priv; 30-31
3044 unsigned long usri11_auth_flags; 32-35
3045 long usri11_password_age; 36-39
3046 char *usri11_homedir; 40-43
3047 char *usri11_parms; 44-47
3048 long usri11_last_logon; 48-51
3049 long usri11_last_logoff; 52-55
3050 unsigned short usri11_bad_pw_count; 56-57
3051 unsigned short usri11_num_logons; 58-59
3052 char *usri11_logon_server; 60-63
3053 unsigned short usri11_country_code; 64-65
3054 char *usri11_workstations; 66-69
3055 unsigned long usri11_max_storage; 70-73
3056 unsigned short usri11_units_per_week; 74-75
3057 unsigned char *usri11_logon_hours; 76-79
3058 unsigned short usri11_code_page; 80-81
3059 };
3060
3061where:
3062
3063 usri11_name specifies the user name for which information is retireved
3064
3065 usri11_pad aligns the next data structure element to a word boundary
3066
3067 usri11_comment is a null terminated ASCII comment
3068
3069 usri11_user_comment is a null terminated ASCII comment about the user
3070
3071 usri11_priv specifies the level of the privilege assigned to the user.
3072 The possible values are:
3073
3074Name Value Description
3075USER_PRIV_GUEST 0 Guest privilege
3076USER_PRIV_USER 1 User privilege
3077USER_PRV_ADMIN 2 Administrator privilege
3078
3079 usri11_auth_flags specifies the account operator privileges. The
3080 possible values are:
3081
3082Name Value Description
3083AF_OP_PRINT 0 Print operator
3084
3085
3086Leach, Naik [Page 28]
3087
3088
3089
3090
3091INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
3092
3093
3094AF_OP_COMM 1 Communications operator
3095AF_OP_SERVER 2 Server operator
3096AF_OP_ACCOUNTS 3 Accounts operator
3097
3098
3099 usri11_password_age specifies how many seconds have elapsed since the
3100 password was last changed.
3101
3102 usri11_home_dir points to a null terminated ASCII string that contains
3103 the path name of the user's home directory.
3104
3105 usri11_parms points to a null terminated ASCII string that is set
3106 aside for use by applications.
3107
3108 usri11_last_logon specifies the time when the user last logged on.
3109 This value is stored as the number of seconds elapsed since
3110 00:00:00, January 1, 1970.
3111
3112 usri11_last_logoff specifies the time when the user last logged off.
3113 This value is stored as the number of seconds elapsed since
3114 00:00:00, January 1, 1970. A value of 0 means the last logoff
3115 time is unknown.
3116
3117 usri11_bad_pw_count specifies the number of incorrect passwords
3118 entered since the last successful logon.
3119
3120 usri11_log1_num_logons specifies the number of times this user has
3121 logged on. A value of -1 means the number of logons is unknown.
3122
3123 usri11_logon_server points to a null terminated ASCII string that
3124 contains the name of the server to which logon requests are sent.
3125 A null string indicates logon requests should be sent to the
3126 domain controller.
3127
3128 usri11_country_code specifies the country code for the user's language
3129 of choice.
3130
3131 usri11_workstations points to a null terminated ASCII string that
3132 contains the names of workstations the user may log on from.
3133 There may be up to 8 workstations, with the names separated by
3134 commas. A null strings indicates there are no restrictions.
3135
3136 usri11_max_storage specifies the maximum amount of disk space the user
3137 can occupy. A value of 0xffffffff indicates there are no
3138 restrictions.
3139
3140 usri11_units_per_week specifies the equal number of time units into
3141 which a week is divided. This value must be equal to 168.
3142
3143 usri11_logon_hours points to a 21 byte (168 bits) string that
3144 specifies the time during which the user can log on. Each bit
3145 represents one unique hour in a week. The first bit (bit 0, word
3146 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
3147
3148
3149
3150Leach, Naik [Page 29]
3151
3152
3153
3154
3155INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
3156
3157
3158 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
3159 are no restrictions.
3160
3161 usri11_code_page specifies the code page for the user's language of
3162 choice
3163
3164All of the pointers in this data structure need to be treated
3165specially. The pointer is a 32 bit pointer. The higher 16 bits need
3166to be ignored. The converter word returned in the parameters section
3167needs to be subtracted from the lower 16 bits to calculate an offset
3168into the return buffer where this ASCII string resides.
3169
3170There is no auxiliary data in the response.
3171
3172 ****************************************************************************/
3173
3174#define usri11_name 0
3175#define usri11_pad 21
3176#define usri11_comment 22
3177#define usri11_usr_comment 26
3178#define usri11_full_name 30
3179#define usri11_priv 34
3180#define usri11_auth_flags 36
3181#define usri11_password_age 40
3182#define usri11_homedir 44
3183#define usri11_parms 48
3184#define usri11_last_logon 52
3185#define usri11_last_logoff 56
3186#define usri11_bad_pw_count 60
3187#define usri11_num_logons 62
3188#define usri11_logon_server 64
3189#define usri11_country_code 68
3190#define usri11_workstations 70
3191#define usri11_max_storage 74
3192#define usri11_units_per_week 78
3193#define usri11_logon_hours 80
3194#define usri11_code_page 84
3195#define usri11_end 86
3196
3197#define USER_PRIV_GUEST 0
3198#define USER_PRIV_USER 1
3199#define USER_PRIV_ADMIN 2
3200
3201#define AF_OP_PRINT 0
3202#define AF_OP_COMM 1
3203#define AF_OP_SERVER 2
3204#define AF_OP_ACCOUNTS 3
3205
3206
3207static BOOL api_RNetUserGetInfo(connection_struct *conn, uint16 vuid,
3208 char *param, int tpscnt,
3209 char *data, int tdscnt,
3210 int mdrcnt,int mprcnt,
3211 char **rdata,char **rparam,
3212 int *rdata_len,int *rparam_len)
3213{
3214 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3215 char *str2 = skip_string(param,tpscnt,str1);
3216 char *UserName = skip_string(param,tpscnt,str2);
3217 char *p = skip_string(param,tpscnt,UserName);
3218 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
3219 char *p2;
3220 const char *level_string;
3221
3222 /* get NIS home of a previously validated user - simeon */
3223 /* With share level security vuid will always be zero.
3224 Don't depend on vuser being non-null !!. JRA */
3225 user_struct *vuser = get_valid_user_struct(vuid);
3226 if(vuser != NULL) {
3227 DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->uid,
3228 vuser->user.unix_name));
3229 }
3230
3231 if (!str1 || !str2 || !UserName || !p) {
3232 return False;
3233 }
3234
3235 *rparam_len = 6;
3236 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3237 if (!*rparam) {
3238 return False;
3239 }
3240
3241 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel));
3242
3243 /* check it's a supported variant */
3244 if (strcmp(str1,"zWrLh") != 0) {
3245 return False;
3246 }
3247 switch( uLevel ) {
3248 case 0: level_string = "B21"; break;
3249 case 1: level_string = "B21BB16DWzzWz"; break;
3250 case 2: level_string = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
3251 case 10: level_string = "B21Bzzz"; break;
3252 case 11: level_string = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
3253 default: return False;
3254 }
3255
3256 if (strcmp(level_string,str2) != 0) {
3257 return False;
3258 }
3259
3260 *rdata_len = mdrcnt + 1024;
3261 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
3262 if (!*rdata) {
3263 return False;
3264 }
3265
3266 SSVAL(*rparam,0,NERR_Success);
3267 SSVAL(*rparam,2,0); /* converter word */
3268
3269 p = *rdata;
3270 p2 = get_safe_ptr(*rdata,*rdata_len,p,usri11_end);
3271 if (!p2) {
3272 return False;
3273 }
3274
3275 memset(p,0,21);
3276 fstrcpy(p+usri11_name,UserName); /* 21 bytes - user name */
3277
3278 if (uLevel > 0) {
3279 SCVAL(p,usri11_pad,0); /* padding - 1 byte */
3280 *p2 = 0;
3281 }
3282
3283 if (uLevel >= 10) {
3284 SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */
3285 pstrcpy(p2,"Comment");
3286 p2 = skip_string(*rdata,*rdata_len,p2);
3287 if (!p2) {
3288 return False;
3289 }
3290
3291 SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */
3292 pstrcpy(p2,"UserComment");
3293 p2 = skip_string(*rdata,*rdata_len,p2);
3294 if (!p2) {
3295 return False;
3296 }
3297
3298 /* EEK! the cifsrap.txt doesn't have this in!!!! */
3299 SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */
3300 pstrcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName));
3301 p2 = skip_string(*rdata,*rdata_len,p2);
3302 if (!p2) {
3303 return False;
3304 }
3305 }
3306
3307 if (uLevel == 11) {
3308 /* modelled after NTAS 3.51 reply */
3309 SSVAL(p,usri11_priv,conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
3310 SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */
3311 SIVALS(p,usri11_password_age,-1); /* password age */
3312 SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */
3313 pstrcpy(p2, vuser && vuser->homedir ? vuser->homedir : "");
3314 p2 = skip_string(*rdata,*rdata_len,p2);
3315 if (!p2) {
3316 return False;
3317 }
3318 SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */
3319 pstrcpy(p2,"");
3320 p2 = skip_string(*rdata,*rdata_len,p2);
3321 if (!p2) {
3322 return False;
3323 }
3324 SIVAL(p,usri11_last_logon,0); /* last logon */
3325 SIVAL(p,usri11_last_logoff,0); /* last logoff */
3326 SSVALS(p,usri11_bad_pw_count,-1); /* bad pw counts */
3327 SSVALS(p,usri11_num_logons,-1); /* num logons */
3328 SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */
3329 pstrcpy(p2,"\\\\*");
3330 p2 = skip_string(*rdata,*rdata_len,p2);
3331 if (!p2) {
3332 return False;
3333 }
3334 SSVAL(p,usri11_country_code,0); /* country code */
3335
3336 SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */
3337 pstrcpy(p2,"");
3338 p2 = skip_string(*rdata,*rdata_len,p2);
3339 if (!p2) {
3340 return False;
3341 }
3342
3343 SIVALS(p,usri11_max_storage,-1); /* max storage */
3344 SSVAL(p,usri11_units_per_week,168); /* units per week */
3345 SIVAL(p,usri11_logon_hours,PTR_DIFF(p2,p)); /* logon hours */
3346
3347 /* a simple way to get logon hours at all times. */
3348 memset(p2,0xff,21);
3349 SCVAL(p2,21,0); /* fix zero termination */
3350 p2 = skip_string(*rdata,*rdata_len,p2);
3351 if (!p2) {
3352 return False;
3353 }
3354
3355 SSVAL(p,usri11_code_page,0); /* code page */
3356 }
3357
3358 if (uLevel == 1 || uLevel == 2) {
3359 memset(p+22,' ',16); /* password */
3360 SIVALS(p,38,-1); /* password age */
3361 SSVAL(p,42,
3362 conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
3363 SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
3364 pstrcpy(p2, vuser && vuser->homedir ? vuser->homedir : "");
3365 p2 = skip_string(*rdata,*rdata_len,p2);
3366 if (!p2) {
3367 return False;
3368 }
3369 SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
3370 *p2++ = 0;
3371 SSVAL(p,52,0); /* flags */
3372 SIVAL(p,54,PTR_DIFF(p2,*rdata)); /* script_path */
3373 pstrcpy(p2,vuser && vuser->logon_script ? vuser->logon_script : "");
3374 p2 = skip_string(*rdata,*rdata_len,p2);
3375 if (!p2) {
3376 return False;
3377 }
3378 if (uLevel == 2) {
3379 SIVAL(p,60,0); /* auth_flags */
3380 SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
3381 pstrcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName));
3382 p2 = skip_string(*rdata,*rdata_len,p2);
3383 if (!p2) {
3384 return False;
3385 }
3386 SIVAL(p,68,0); /* urs_comment */
3387 SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
3388 pstrcpy(p2,"");
3389 p2 = skip_string(*rdata,*rdata_len,p2);
3390 if (!p2) {
3391 return False;
3392 }
3393 SIVAL(p,76,0); /* workstations */
3394 SIVAL(p,80,0); /* last_logon */
3395 SIVAL(p,84,0); /* last_logoff */
3396 SIVALS(p,88,-1); /* acct_expires */
3397 SIVALS(p,92,-1); /* max_storage */
3398 SSVAL(p,96,168); /* units_per_week */
3399 SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
3400 memset(p2,-1,21);
3401 p2 += 21;
3402 SSVALS(p,102,-1); /* bad_pw_count */
3403 SSVALS(p,104,-1); /* num_logons */
3404 SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
3405 {
3406 pstring tmp;
3407 pstrcpy(tmp, "\\\\%L");
3408 standard_sub_basic("", "", tmp, sizeof(tmp));
3409 pstrcpy(p2, tmp);
3410 }
3411 p2 = skip_string(*rdata,*rdata_len,p2);
3412 if (!p2) {
3413 return False;
3414 }
3415 SSVAL(p,110,49); /* country_code */
3416 SSVAL(p,112,860); /* code page */
3417 }
3418 }
3419
3420 *rdata_len = PTR_DIFF(p2,*rdata);
3421
3422 SSVAL(*rparam,4,*rdata_len); /* is this right?? */
3423
3424 return(True);
3425}
3426
3427static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid,
3428 char *param, int tpscnt,
3429 char *data, int tdscnt,
3430 int mdrcnt,int mprcnt,
3431 char **rdata,char **rparam,
3432 int *rdata_len,int *rparam_len)
3433{
3434 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3435 char *str2 = skip_string(param,tpscnt,str1);
3436 char *p = skip_string(param,tpscnt,str2);
3437 int uLevel;
3438 struct pack_desc desc;
3439 char* name;
3440 /* With share level security vuid will always be zero.
3441 Don't depend on vuser being non-null !!. JRA */
3442 user_struct *vuser = get_valid_user_struct(vuid);
3443
3444 if (!str1 || !str2 || !p) {
3445 return False;
3446 }
3447
3448 if(vuser != NULL) {
3449 DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->uid,
3450 vuser->user.unix_name));
3451 }
3452
3453 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
3454 name = get_safe_str_ptr(param,tpscnt,p,2);
3455 if (!name) {
3456 return False;
3457 }
3458
3459 memset((char *)&desc,'\0',sizeof(desc));
3460
3461 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
3462
3463 /* check it's a supported varient */
3464 if (strcmp(str1,"OOWb54WrLh") != 0) {
3465 return False;
3466 }
3467 if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) {
3468 return False;
3469 }
3470 if (mdrcnt > 0) {
3471 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3472 if (!*rdata) {
3473 return False;
3474 }
3475 }
3476
3477 desc.base = *rdata;
3478 desc.buflen = mdrcnt;
3479 desc.subformat = NULL;
3480 desc.format = str2;
3481
3482 if (init_package(&desc,1,0)) {
3483 PACKI(&desc,"W",0); /* code */
3484 PACKS(&desc,"B21",name); /* eff. name */
3485 PACKS(&desc,"B",""); /* pad */
3486 PACKI(&desc,"W", conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
3487 PACKI(&desc,"D",0); /* auth flags XXX */
3488 PACKI(&desc,"W",0); /* num logons */
3489 PACKI(&desc,"W",0); /* bad pw count */
3490 PACKI(&desc,"D",0); /* last logon */
3491 PACKI(&desc,"D",-1); /* last logoff */
3492 PACKI(&desc,"D",-1); /* logoff time */
3493 PACKI(&desc,"D",-1); /* kickoff time */
3494 PACKI(&desc,"D",0); /* password age */
3495 PACKI(&desc,"D",0); /* password can change */
3496 PACKI(&desc,"D",-1); /* password must change */
3497
3498 {
3499 fstring mypath;
3500 fstrcpy(mypath,"\\\\");
3501 fstrcat(mypath,get_local_machine_name());
3502 strupper_m(mypath);
3503 PACKS(&desc,"z",mypath); /* computer */
3504 }
3505
3506 PACKS(&desc,"z",lp_workgroup());/* domain */
3507 PACKS(&desc,"z", vuser && vuser->logon_script ? vuser->logon_script :""); /* script path */
3508 PACKI(&desc,"D",0x00000000); /* reserved */
3509 }
3510
3511 *rdata_len = desc.usedlen;
3512 *rparam_len = 6;
3513 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3514 if (!*rparam) {
3515 return False;
3516 }
3517 SSVALS(*rparam,0,desc.errcode);
3518 SSVAL(*rparam,2,0);
3519 SSVAL(*rparam,4,desc.neededlen);
3520
3521 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
3522
3523 return True;
3524}
3525
3526/****************************************************************************
3527 api_WAccessGetUserPerms
3528****************************************************************************/
3529
3530static BOOL api_WAccessGetUserPerms(connection_struct *conn,uint16 vuid,
3531 char *param, int tpscnt,
3532 char *data, int tdscnt,
3533 int mdrcnt,int mprcnt,
3534 char **rdata,char **rparam,
3535 int *rdata_len,int *rparam_len)
3536{
3537 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3538 char *str2 = skip_string(param,tpscnt,str1);
3539 char *user = skip_string(param,tpscnt,str2);
3540 char *resource = skip_string(param,tpscnt,user);
3541
3542 if (!str1 || !str2 || !user || !resource) {
3543 return False;
3544 }
3545
3546 if (skip_string(param,tpscnt,resource) == NULL) {
3547 return False;
3548 }
3549 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
3550
3551 /* check it's a supported varient */
3552 if (strcmp(str1,"zzh") != 0) {
3553 return False;
3554 }
3555 if (strcmp(str2,"") != 0) {
3556 return False;
3557 }
3558
3559 *rparam_len = 6;
3560 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3561 if (!*rparam) {
3562 return False;
3563 }
3564 SSVALS(*rparam,0,0); /* errorcode */
3565 SSVAL(*rparam,2,0); /* converter word */
3566 SSVAL(*rparam,4,0x7f); /* permission flags */
3567
3568 return True;
3569}
3570
3571/****************************************************************************
3572 api_WPrintJobEnumerate
3573 ****************************************************************************/
3574
3575static BOOL api_WPrintJobGetInfo(connection_struct *conn, uint16 vuid,
3576 char *param, int tpscnt,
3577 char *data, int tdscnt,
3578 int mdrcnt,int mprcnt,
3579 char **rdata,char **rparam,
3580 int *rdata_len,int *rparam_len)
3581{
3582 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3583 char *str2 = skip_string(param,tpscnt,str1);
3584 char *p = skip_string(param,tpscnt,str2);
3585 int uLevel;
3586 int count;
3587 int i;
3588 int snum;
3589 fstring sharename;
3590 uint32 jobid;
3591 struct pack_desc desc;
3592 print_queue_struct *queue=NULL;
3593 print_status_struct status;
3594 char *tmpdata=NULL;
3595
3596 if (!str1 || !str2 || !p) {
3597 return False;
3598 }
3599
3600 uLevel = get_safe_SVAL(param,tpscnt,p,2,-1);
3601
3602 memset((char *)&desc,'\0',sizeof(desc));
3603 memset((char *)&status,'\0',sizeof(status));
3604
3605 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,SVAL(p,0)));
3606
3607 /* check it's a supported varient */
3608 if (strcmp(str1,"WWrLh") != 0) {
3609 return False;
3610 }
3611 if (!check_printjob_info(&desc,uLevel,str2)) {
3612 return False;
3613 }
3614
3615 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid)) {
3616 return False;
3617 }
3618
3619 snum = lp_servicenumber( sharename);
3620 if (snum < 0 || !VALID_SNUM(snum)) {
3621 return(False);
3622 }
3623
3624 count = print_queue_status(snum,&queue,&status);
3625 for (i = 0; i < count; i++) {
3626 if (queue[i].job == jobid) {
3627 break;
3628 }
3629 }
3630
3631 if (mdrcnt > 0) {
3632 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3633 if (!*rdata) {
3634 return False;
3635 }
3636 desc.base = *rdata;
3637 desc.buflen = mdrcnt;
3638 } else {
3639 /*
3640 * Don't return data but need to get correct length
3641 * init_package will return wrong size if buflen=0
3642 */
3643 desc.buflen = getlen(desc.format);
3644 desc.base = tmpdata = (char *)SMB_MALLOC( desc.buflen );
3645 }
3646
3647 if (init_package(&desc,1,0)) {
3648 if (i < count) {
3649 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
3650 *rdata_len = desc.usedlen;
3651 } else {
3652 desc.errcode = NERR_JobNotFound;
3653 *rdata_len = 0;
3654 }
3655 }
3656
3657 *rparam_len = 6;
3658 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3659 if (!*rparam) {
3660 return False;
3661 }
3662 SSVALS(*rparam,0,desc.errcode);
3663 SSVAL(*rparam,2,0);
3664 SSVAL(*rparam,4,desc.neededlen);
3665
3666 SAFE_FREE(queue);
3667 SAFE_FREE(tmpdata);
3668
3669 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
3670
3671 return True;
3672}
3673
3674static BOOL api_WPrintJobEnumerate(connection_struct *conn, uint16 vuid,
3675 char *param, int tpscnt,
3676 char *data, int tdscnt,
3677 int mdrcnt,int mprcnt,
3678 char **rdata,char **rparam,
3679 int *rdata_len,int *rparam_len)
3680{
3681 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3682 char *str2 = skip_string(param,tpscnt,str1);
3683 char *p = skip_string(param,tpscnt,str2);
3684 char *name = p;
3685 int uLevel;
3686 int count;
3687 int i, succnt=0;
3688 int snum;
3689 struct pack_desc desc;
3690 print_queue_struct *queue=NULL;
3691 print_status_struct status;
3692
3693 if (!str1 || !str2 || !p) {
3694 return False;
3695 }
3696
3697 memset((char *)&desc,'\0',sizeof(desc));
3698 memset((char *)&status,'\0',sizeof(status));
3699
3700 p = skip_string(param,tpscnt,p);
3701 if (!p) {
3702 return False;
3703 }
3704 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
3705
3706 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
3707
3708 /* check it's a supported variant */
3709 if (strcmp(str1,"zWrLeh") != 0) {
3710 return False;
3711 }
3712
3713 if (uLevel > 2) {
3714 return False; /* defined only for uLevel 0,1,2 */
3715 }
3716
3717 if (!check_printjob_info(&desc,uLevel,str2)) {
3718 return False;
3719 }
3720
3721 snum = find_service(name);
3722 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) ) {
3723 return False;
3724 }
3725
3726 count = print_queue_status(snum,&queue,&status);
3727 if (mdrcnt > 0) {
3728 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3729 if (!*rdata) {
3730 return False;
3731 }
3732 }
3733 desc.base = *rdata;
3734 desc.buflen = mdrcnt;
3735
3736 if (init_package(&desc,count,0)) {
3737 succnt = 0;
3738 for (i = 0; i < count; i++) {
3739 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
3740 if (desc.errcode == NERR_Success) {
3741 succnt = i+1;
3742 }
3743 }
3744 }
3745
3746 *rdata_len = desc.usedlen;
3747
3748 *rparam_len = 8;
3749 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3750 if (!*rparam) {
3751 return False;
3752 }
3753 SSVALS(*rparam,0,desc.errcode);
3754 SSVAL(*rparam,2,0);
3755 SSVAL(*rparam,4,succnt);
3756 SSVAL(*rparam,6,count);
3757
3758 SAFE_FREE(queue);
3759
3760 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
3761
3762 return True;
3763}
3764
3765static int check_printdest_info(struct pack_desc* desc,
3766 int uLevel, char* id)
3767{
3768 desc->subformat = NULL;
3769 switch( uLevel ) {
3770 case 0:
3771 desc->format = "B9";
3772 break;
3773 case 1:
3774 desc->format = "B9B21WWzW";
3775 break;
3776 case 2:
3777 desc->format = "z";
3778 break;
3779 case 3:
3780 desc->format = "zzzWWzzzWW";
3781 break;
3782 default:
3783 DEBUG(0,("check_printdest_info: invalid level %d\n",
3784 uLevel));
3785 return False;
3786 }
3787 if (id == NULL || strcmp(desc->format,id) != 0) {
3788 DEBUG(0,("check_printdest_info: invalid string %s\n",
3789 id ? id : "<NULL>" ));
3790 return False;
3791 }
3792 return True;
3793}
3794
3795static void fill_printdest_info(connection_struct *conn, int snum, int uLevel,
3796 struct pack_desc* desc)
3797{
3798 char buf[100];
3799
3800 strncpy(buf,SERVICE(snum),sizeof(buf)-1);
3801 buf[sizeof(buf)-1] = 0;
3802 strupper_m(buf);
3803
3804 if (uLevel <= 1) {
3805 PACKS(desc,"B9",buf); /* szName */
3806 if (uLevel == 1) {
3807 PACKS(desc,"B21",""); /* szUserName */
3808 PACKI(desc,"W",0); /* uJobId */
3809 PACKI(desc,"W",0); /* fsStatus */
3810 PACKS(desc,"z",""); /* pszStatus */
3811 PACKI(desc,"W",0); /* time */
3812 }
3813 }
3814
3815 if (uLevel == 2 || uLevel == 3) {
3816 PACKS(desc,"z",buf); /* pszPrinterName */
3817 if (uLevel == 3) {
3818 PACKS(desc,"z",""); /* pszUserName */
3819 PACKS(desc,"z",""); /* pszLogAddr */
3820 PACKI(desc,"W",0); /* uJobId */
3821 PACKI(desc,"W",0); /* fsStatus */
3822 PACKS(desc,"z",""); /* pszStatus */
3823 PACKS(desc,"z",""); /* pszComment */
3824 PACKS(desc,"z","NULL"); /* pszDrivers */
3825 PACKI(desc,"W",0); /* time */
3826 PACKI(desc,"W",0); /* pad1 */
3827 }
3828 }
3829}
3830
3831static BOOL api_WPrintDestGetInfo(connection_struct *conn, uint16 vuid,
3832 char *param, int tpscnt,
3833 char *data, int tdscnt,
3834 int mdrcnt,int mprcnt,
3835 char **rdata,char **rparam,
3836 int *rdata_len,int *rparam_len)
3837{
3838 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3839 char *str2 = skip_string(param,tpscnt,str1);
3840 char *p = skip_string(param,tpscnt,str2);
3841 char* PrinterName = p;
3842 int uLevel;
3843 struct pack_desc desc;
3844 int snum;
3845 char *tmpdata=NULL;
3846
3847 if (!str1 || !str2 || !p) {
3848 return False;
3849 }
3850
3851 memset((char *)&desc,'\0',sizeof(desc));
3852
3853 p = skip_string(param,tpscnt,p);
3854 if (!p) {
3855 return False;
3856 }
3857 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
3858
3859 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
3860
3861 /* check it's a supported varient */
3862 if (strcmp(str1,"zWrLh") != 0) {
3863 return False;
3864 }
3865 if (!check_printdest_info(&desc,uLevel,str2)) {
3866 return False;
3867 }
3868
3869 snum = find_service(PrinterName);
3870 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) ) {
3871 *rdata_len = 0;
3872 desc.errcode = NERR_DestNotFound;
3873 desc.neededlen = 0;
3874 } else {
3875 if (mdrcnt > 0) {
3876 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3877 if (!*rdata) {
3878 return False;
3879 }
3880 desc.base = *rdata;
3881 desc.buflen = mdrcnt;
3882 } else {
3883 /*
3884 * Don't return data but need to get correct length
3885 * init_package will return wrong size if buflen=0
3886 */
3887 desc.buflen = getlen(desc.format);
3888 desc.base = tmpdata = (char *)SMB_MALLOC( desc.buflen );
3889 }
3890 if (init_package(&desc,1,0)) {
3891 fill_printdest_info(conn,snum,uLevel,&desc);
3892 }
3893 *rdata_len = desc.usedlen;
3894 }
3895
3896 *rparam_len = 6;
3897 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3898 if (!*rparam) {
3899 return False;
3900 }
3901 SSVALS(*rparam,0,desc.errcode);
3902 SSVAL(*rparam,2,0);
3903 SSVAL(*rparam,4,desc.neededlen);
3904
3905 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
3906 SAFE_FREE(tmpdata);
3907
3908 return True;
3909}
3910
3911static BOOL api_WPrintDestEnum(connection_struct *conn, uint16 vuid,
3912 char *param, int tpscnt,
3913 char *data, int tdscnt,
3914 int mdrcnt,int mprcnt,
3915 char **rdata,char **rparam,
3916 int *rdata_len,int *rparam_len)
3917{
3918 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3919 char *str2 = skip_string(param,tpscnt,str1);
3920 char *p = skip_string(param,tpscnt,str2);
3921 int uLevel;
3922 int queuecnt;
3923 int i, n, succnt=0;
3924 struct pack_desc desc;
3925 int services = lp_numservices();
3926
3927 if (!str1 || !str2 || !p) {
3928 return False;
3929 }
3930
3931 memset((char *)&desc,'\0',sizeof(desc));
3932
3933 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
3934
3935 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
3936
3937 /* check it's a supported varient */
3938 if (strcmp(str1,"WrLeh") != 0) {
3939 return False;
3940 }
3941 if (!check_printdest_info(&desc,uLevel,str2)) {
3942 return False;
3943 }
3944
3945 queuecnt = 0;
3946 for (i = 0; i < services; i++) {
3947 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
3948 queuecnt++;
3949 }
3950 }
3951
3952 if (mdrcnt > 0) {
3953 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3954 if (!*rdata) {
3955 return False;
3956 }
3957 }
3958
3959 desc.base = *rdata;
3960 desc.buflen = mdrcnt;
3961 if (init_package(&desc,queuecnt,0)) {
3962 succnt = 0;
3963 n = 0;
3964 for (i = 0; i < services; i++) {
3965 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
3966 fill_printdest_info(conn,i,uLevel,&desc);
3967 n++;
3968 if (desc.errcode == NERR_Success) {
3969 succnt = n;
3970 }
3971 }
3972 }
3973 }
3974
3975 *rdata_len = desc.usedlen;
3976
3977 *rparam_len = 8;
3978 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3979 if (!*rparam) {
3980 return False;
3981 }
3982 SSVALS(*rparam,0,desc.errcode);
3983 SSVAL(*rparam,2,0);
3984 SSVAL(*rparam,4,succnt);
3985 SSVAL(*rparam,6,queuecnt);
3986
3987 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
3988
3989 return True;
3990}
3991
3992static BOOL api_WPrintDriverEnum(connection_struct *conn, uint16 vuid,
3993 char *param, int tpscnt,
3994 char *data, int tdscnt,
3995 int mdrcnt,int mprcnt,
3996 char **rdata,char **rparam,
3997 int *rdata_len,int *rparam_len)
3998{
3999 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4000 char *str2 = skip_string(param,tpscnt,str1);
4001 char *p = skip_string(param,tpscnt,str2);
4002 int uLevel;
4003 int succnt;
4004 struct pack_desc desc;
4005
4006 if (!str1 || !str2 || !p) {
4007 return False;
4008 }
4009
4010 memset((char *)&desc,'\0',sizeof(desc));
4011
4012 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4013
4014 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
4015
4016 /* check it's a supported varient */
4017 if (strcmp(str1,"WrLeh") != 0) {
4018 return False;
4019 }
4020 if (uLevel != 0 || strcmp(str2,"B41") != 0) {
4021 return False;
4022 }
4023
4024 if (mdrcnt > 0) {
4025 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
4026 if (!*rdata) {
4027 return False;
4028 }
4029 }
4030 desc.base = *rdata;
4031 desc.buflen = mdrcnt;
4032 if (init_package(&desc,1,0)) {
4033 PACKS(&desc,"B41","NULL");
4034 }
4035
4036 succnt = (desc.errcode == NERR_Success ? 1 : 0);
4037
4038 *rdata_len = desc.usedlen;
4039
4040 *rparam_len = 8;
4041 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
4042 if (!*rparam) {
4043 return False;
4044 }
4045 SSVALS(*rparam,0,desc.errcode);
4046 SSVAL(*rparam,2,0);
4047 SSVAL(*rparam,4,succnt);
4048 SSVAL(*rparam,6,1);
4049
4050 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
4051
4052 return True;
4053}
4054
4055static BOOL api_WPrintQProcEnum(connection_struct *conn, uint16 vuid,
4056 char *param, int tpscnt,
4057 char *data, int tdscnt,
4058 int mdrcnt,int mprcnt,
4059 char **rdata,char **rparam,
4060 int *rdata_len,int *rparam_len)
4061{
4062 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4063 char *str2 = skip_string(param,tpscnt,str1);
4064 char *p = skip_string(param,tpscnt,str2);
4065 int uLevel;
4066 int succnt;
4067 struct pack_desc desc;
4068
4069 if (!str1 || !str2 || !p) {
4070 return False;
4071 }
4072 memset((char *)&desc,'\0',sizeof(desc));
4073
4074 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4075
4076 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
4077
4078 /* check it's a supported varient */
4079 if (strcmp(str1,"WrLeh") != 0) {
4080 return False;
4081 }
4082 if (uLevel != 0 || strcmp(str2,"B13") != 0) {
4083 return False;
4084 }
4085
4086 if (mdrcnt > 0) {
4087 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
4088 if (!*rdata) {
4089 return False;
4090 }
4091 }
4092 desc.base = *rdata;
4093 desc.buflen = mdrcnt;
4094 desc.format = str2;
4095 if (init_package(&desc,1,0)) {
4096 PACKS(&desc,"B13","lpd");
4097 }
4098
4099 succnt = (desc.errcode == NERR_Success ? 1 : 0);
4100
4101 *rdata_len = desc.usedlen;
4102
4103 *rparam_len = 8;
4104 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
4105 if (!*rparam) {
4106 return False;
4107 }
4108 SSVALS(*rparam,0,desc.errcode);
4109 SSVAL(*rparam,2,0);
4110 SSVAL(*rparam,4,succnt);
4111 SSVAL(*rparam,6,1);
4112
4113 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
4114
4115 return True;
4116}
4117
4118static BOOL api_WPrintPortEnum(connection_struct *conn, uint16 vuid,
4119 char *param, int tpscnt,
4120 char *data, int tdscnt,
4121 int mdrcnt,int mprcnt,
4122 char **rdata,char **rparam,
4123 int *rdata_len,int *rparam_len)
4124{
4125 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4126 char *str2 = skip_string(param,tpscnt,str1);
4127 char *p = skip_string(param,tpscnt,str2);
4128 int uLevel;
4129 int succnt;
4130 struct pack_desc desc;
4131
4132 if (!str1 || !str2 || !p) {
4133 return False;
4134 }
4135
4136 memset((char *)&desc,'\0',sizeof(desc));
4137
4138 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4139
4140 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
4141
4142 /* check it's a supported varient */
4143 if (strcmp(str1,"WrLeh") != 0) {
4144 return False;
4145 }
4146 if (uLevel != 0 || strcmp(str2,"B9") != 0) {
4147 return False;
4148 }
4149
4150 if (mdrcnt > 0) {
4151 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
4152 if (!*rdata) {
4153 return False;
4154 }
4155 }
4156 memset((char *)&desc,'\0',sizeof(desc));
4157 desc.base = *rdata;
4158 desc.buflen = mdrcnt;
4159 desc.format = str2;
4160 if (init_package(&desc,1,0)) {
4161 PACKS(&desc,"B13","lp0");
4162 }
4163
4164 succnt = (desc.errcode == NERR_Success ? 1 : 0);
4165
4166 *rdata_len = desc.usedlen;
4167
4168 *rparam_len = 8;
4169 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
4170 if (!*rparam) {
4171 return False;
4172 }
4173 SSVALS(*rparam,0,desc.errcode);
4174 SSVAL(*rparam,2,0);
4175 SSVAL(*rparam,4,succnt);
4176 SSVAL(*rparam,6,1);
4177
4178 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
4179
4180 return True;
4181}
4182
4183/****************************************************************************
4184 List open sessions
4185 ****************************************************************************/
4186
4187static BOOL api_RNetSessionEnum(connection_struct *conn, uint16 vuid,
4188 char *param, int tpscnt,
4189 char *data, int tdscnt,
4190 int mdrcnt,int mprcnt,
4191 char **rdata,char **rparam,
4192 int *rdata_len,int *rparam_len)
4193
4194{
4195 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4196 char *str2 = skip_string(param,tpscnt,str1);
4197 char *p = skip_string(param,tpscnt,str2);
4198 int uLevel;
4199 struct pack_desc desc;
4200 struct sessionid *session_list = NULL;
4201 int i, num_sessions;
4202
4203 if (!str1 || !str2 || !p) {
4204 return False;
4205 }
4206
4207 memset((char *)&desc,'\0',sizeof(desc));
4208
4209 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4210
4211 DEBUG(3,("RNetSessionEnum uLevel=%d\n",uLevel));
4212 DEBUG(7,("RNetSessionEnum req string=%s\n",str1));
4213 DEBUG(7,("RNetSessionEnum ret string=%s\n",str2));
4214
4215 /* check it's a supported varient */
4216 if (strcmp(str1,RAP_NetSessionEnum_REQ) != 0) {
4217 return False;
4218 }
4219 if (uLevel != 2 || strcmp(str2,RAP_SESSION_INFO_L2) != 0) {
4220 return False;
4221 }
4222
4223 num_sessions = list_sessions(&session_list);
4224
4225 if (mdrcnt > 0) {
4226 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
4227 if (!*rdata) {
4228 SAFE_FREE(session_list);
4229 return False;
4230 }
4231 }
4232 memset((char *)&desc,'\0',sizeof(desc));
4233 desc.base = *rdata;
4234 desc.buflen = mdrcnt;
4235 desc.format = str2;
4236 if (!init_package(&desc,num_sessions,0)) {
4237 SAFE_FREE(session_list);
4238 return False;
4239 }
4240
4241 for(i=0; i<num_sessions; i++) {
4242 PACKS(&desc, "z", session_list[i].remote_machine);
4243 PACKS(&desc, "z", session_list[i].username);
4244 PACKI(&desc, "W", 1); /* num conns */
4245 PACKI(&desc, "W", 0); /* num opens */
4246 PACKI(&desc, "W", 1); /* num users */
4247 PACKI(&desc, "D", 0); /* session time */
4248 PACKI(&desc, "D", 0); /* idle time */
4249 PACKI(&desc, "D", 0); /* flags */
4250 PACKS(&desc, "z", "Unknown Client"); /* client type string */
4251 }
4252
4253 *rdata_len = desc.usedlen;
4254
4255 *rparam_len = 8;
4256 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
4257 if (!*rparam) {
4258 SAFE_FREE(session_list);
4259 return False;
4260 }
4261 SSVALS(*rparam,0,desc.errcode);
4262 SSVAL(*rparam,2,0); /* converter */
4263 SSVAL(*rparam,4,num_sessions); /* count */
4264
4265 DEBUG(4,("RNetSessionEnum: errorcode %d\n",desc.errcode));
4266
4267 SAFE_FREE(session_list);
4268 return True;
4269}
4270
4271
4272/****************************************************************************
4273 The buffer was too small.
4274 ****************************************************************************/
4275
4276static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param, char *data,
4277 int mdrcnt, int mprcnt,
4278 char **rdata, char **rparam,
4279 int *rdata_len, int *rparam_len)
4280{
4281 *rparam_len = MIN(*rparam_len,mprcnt);
4282 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
4283 if (!*rparam) {
4284 return False;
4285 }
4286
4287 *rdata_len = 0;
4288
4289 SSVAL(*rparam,0,NERR_BufTooSmall);
4290
4291 DEBUG(3,("Supplied buffer too small in API command\n"));
4292
4293 return True;
4294}
4295
4296/****************************************************************************
4297 The request is not supported.
4298 ****************************************************************************/
4299
4300static BOOL api_Unsupported(connection_struct *conn, uint16 vuid,
4301 char *param, int tpscnt,
4302 char *data, int tdscnt,
4303 int mdrcnt, int mprcnt,
4304 char **rdata, char **rparam,
4305 int *rdata_len, int *rparam_len)
4306{
4307 *rparam_len = 4;
4308 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
4309 if (!*rparam) {
4310 return False;
4311 }
4312
4313 *rdata_len = 0;
4314
4315 SSVAL(*rparam,0,NERR_notsupported);
4316 SSVAL(*rparam,2,0); /* converter word */
4317
4318 DEBUG(3,("Unsupported API command\n"));
4319
4320 return True;
4321}
4322
4323static const struct {
4324 const char *name;
4325 int id;
4326 BOOL (*fn)(connection_struct *, uint16,
4327 char *, int,
4328 char *, int,
4329 int,int,char **,char **,int *,int *);
4330 BOOL auth_user; /* Deny anonymous access? */
4331} api_commands[] = {
4332 {"RNetShareEnum", RAP_WshareEnum, api_RNetShareEnum, True},
4333 {"RNetShareGetInfo", RAP_WshareGetInfo, api_RNetShareGetInfo},
4334 {"RNetShareAdd", RAP_WshareAdd, api_RNetShareAdd},
4335 {"RNetSessionEnum", RAP_WsessionEnum, api_RNetSessionEnum, True},
4336 {"RNetServerGetInfo", RAP_WserverGetInfo, api_RNetServerGetInfo},
4337 {"RNetGroupEnum", RAP_WGroupEnum, api_RNetGroupEnum, True},
4338 {"RNetGroupGetUsers", RAP_WGroupGetUsers, api_RNetGroupGetUsers, True},
4339 {"RNetUserEnum", RAP_WUserEnum, api_RNetUserEnum, True},
4340 {"RNetUserGetInfo", RAP_WUserGetInfo, api_RNetUserGetInfo},
4341 {"NetUserGetGroups", RAP_WUserGetGroups, api_NetUserGetGroups},
4342 {"NetWkstaGetInfo", RAP_WWkstaGetInfo, api_NetWkstaGetInfo},
4343 {"DosPrintQEnum", RAP_WPrintQEnum, api_DosPrintQEnum, True},
4344 {"DosPrintQGetInfo", RAP_WPrintQGetInfo, api_DosPrintQGetInfo},
4345 {"WPrintQueuePause", RAP_WPrintQPause, api_WPrintQueueCtrl},
4346 {"WPrintQueueResume", RAP_WPrintQContinue, api_WPrintQueueCtrl},
4347 {"WPrintJobEnumerate",RAP_WPrintJobEnum, api_WPrintJobEnumerate},
4348 {"WPrintJobGetInfo", RAP_WPrintJobGetInfo, api_WPrintJobGetInfo},
4349 {"RDosPrintJobDel", RAP_WPrintJobDel, api_RDosPrintJobDel},
4350 {"RDosPrintJobPause", RAP_WPrintJobPause, api_RDosPrintJobDel},
4351 {"RDosPrintJobResume",RAP_WPrintJobContinue, api_RDosPrintJobDel},
4352 {"WPrintDestEnum", RAP_WPrintDestEnum, api_WPrintDestEnum},
4353 {"WPrintDestGetInfo", RAP_WPrintDestGetInfo, api_WPrintDestGetInfo},
4354 {"NetRemoteTOD", RAP_NetRemoteTOD, api_NetRemoteTOD},
4355 {"WPrintQueuePurge", RAP_WPrintQPurge, api_WPrintQueueCtrl},
4356 {"NetServerEnum", RAP_NetServerEnum2, api_RNetServerEnum}, /* anon OK */
4357 {"WAccessGetUserPerms",RAP_WAccessGetUserPerms,api_WAccessGetUserPerms},
4358 {"SetUserPassword", RAP_WUserPasswordSet2, api_SetUserPassword},
4359 {"WWkstaUserLogon", RAP_WWkstaUserLogon, api_WWkstaUserLogon},
4360 {"PrintJobInfo", RAP_WPrintJobSetInfo, api_PrintJobInfo},
4361 {"WPrintDriverEnum", RAP_WPrintDriverEnum, api_WPrintDriverEnum},
4362 {"WPrintQProcEnum", RAP_WPrintQProcessorEnum,api_WPrintQProcEnum},
4363 {"WPrintPortEnum", RAP_WPrintPortEnum, api_WPrintPortEnum},
4364 {"SamOEMChangePassword",RAP_SamOEMChgPasswordUser2_P,api_SamOEMChangePassword}, /* anon OK */
4365 {NULL, -1, api_Unsupported}
4366 /* The following RAP calls are not implemented by Samba:
4367
4368 RAP_WFileEnum2 - anon not OK
4369 */
4370};
4371
4372
4373/****************************************************************************
4374 Handle remote api calls
4375 ****************************************************************************/
4376
4377int api_reply(connection_struct *conn,uint16 vuid,char *outbuf,char *data,char *params,
4378 int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
4379{
4380 int api_command;
4381 char *rdata = NULL;
4382 char *rparam = NULL;
4383 const char *name1 = NULL;
4384 const char *name2 = NULL;
4385 int rdata_len = 0;
4386 int rparam_len = 0;
4387 BOOL reply=False;
4388 int i;
4389
4390 if (!params) {
4391 DEBUG(0,("ERROR: NULL params in api_reply()\n"));
4392 return 0;
4393 }
4394
4395 if (tpscnt < 2) {
4396 return 0;
4397 }
4398 api_command = SVAL(params,0);
4399 /* Is there a string at position params+2 ? */
4400 if (skip_string(params,tpscnt,params+2)) {
4401 name1 = params + 2;
4402 } else {
4403 name1 = "";
4404 }
4405 name2 = skip_string(params,tpscnt,params+2);
4406 if (!name2) {
4407 name2 = "";
4408 }
4409
4410 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
4411 api_command,
4412 name1,
4413 name2,
4414 tdscnt,tpscnt,mdrcnt,mprcnt));
4415
4416 for (i=0;api_commands[i].name;i++) {
4417 if (api_commands[i].id == api_command && api_commands[i].fn) {
4418 DEBUG(3,("Doing %s\n",api_commands[i].name));
4419 break;
4420 }
4421 }
4422
4423 /* Check whether this api call can be done anonymously */
4424
4425 if (api_commands[i].auth_user && lp_restrict_anonymous()) {
4426 user_struct *user = get_valid_user_struct(vuid);
4427
4428 if (!user || user->guest) {
4429 return ERROR_NT(NT_STATUS_ACCESS_DENIED);
4430 }
4431 }
4432
4433 rdata = (char *)SMB_MALLOC(1024);
4434 if (rdata) {
4435 memset(rdata,'\0',1024);
4436 }
4437
4438 rparam = (char *)SMB_MALLOC(1024);
4439 if (rparam) {
4440 memset(rparam,'\0',1024);
4441 }
4442
4443 if(!rdata || !rparam) {
4444 DEBUG(0,("api_reply: malloc fail !\n"));
4445 SAFE_FREE(rdata);
4446 SAFE_FREE(rparam);
4447 return -1;
4448 }
4449
4450 reply = api_commands[i].fn(conn,
4451 vuid,
4452 params,tpscnt, /* params + length */
4453 data,tdscnt, /* data + length */
4454 mdrcnt,mprcnt,
4455 &rdata,&rparam,&rdata_len,&rparam_len);
4456
4457
4458 if (rdata_len > mdrcnt || rparam_len > mprcnt) {
4459 reply = api_TooSmall(conn,vuid,params,data,mdrcnt,mprcnt,
4460 &rdata,&rparam,&rdata_len,&rparam_len);
4461 }
4462
4463 /* if we get False back then it's actually unsupported */
4464 if (!reply) {
4465 reply = api_Unsupported(conn,vuid,params,tpscnt,data,tdscnt,mdrcnt,mprcnt,
4466 &rdata,&rparam,&rdata_len,&rparam_len);
4467 }
4468
4469 /* If api_Unsupported returns false we can't return anything. */
4470 if (reply) {
4471 send_trans_reply(outbuf, rparam, rparam_len, rdata, rdata_len, False);
4472 }
4473
4474 SAFE_FREE(rdata);
4475 SAFE_FREE(rparam);
4476 return -1;
4477}
Note: See TracBrowser for help on using the repository browser.