source: trunk-3.0/source/smbd/lanman.c@ 102

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

Update to 3.0.27

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