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.
8 Copyright (C) John H Terpstra 1995-1998
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.
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.
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.
25 This file handles the named pipe and mailslot calls
26 in the SMBtrans protocol
31 extern struct current_user current_user
;
32 extern userdom_struct current_user_info
;
39 #define NERR_Success 0
40 #define NERR_badpass 86
41 #define NERR_notsupported 50
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)
48 #define ACCESS_READ 0x01
49 #define ACCESS_WRITE 0x02
50 #define ACCESS_CREATE 0x04
52 #define SHPWLEN 8 /* share password length */
54 static 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
);
61 static 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
);
67 static int CopyExpanded(connection_struct
*conn
,
68 int snum
, char **dst
, char *src
, int *n
)
73 if (!src
|| !dst
|| !n
|| !(*dst
)) {
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
,
84 l
= push_ascii(*dst
,buf
,*n
, STR_TERMINATE
);
90 static int CopyAndAdvance(char **dst
, char *src
, int *n
)
93 if (!src
|| !dst
|| !n
|| !(*dst
)) {
96 l
= push_ascii(*dst
,src
,*n
, STR_TERMINATE
);
102 static int StrlenExpanded(connection_struct
*conn
, int snum
, char *s
)
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
,
115 return strlen(buf
) + 1;
118 static char *Expand(connection_struct
*conn
, int snum
, char *s
)
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
,
134 /*******************************************************************
135 Check a API string for validity when we only need to check the prefix.
136 ******************************************************************/
138 static BOOL
prefix_ok(const char *str
, const char *prefix
)
140 return(strncmp(str
,prefix
,strlen(prefix
)) == 0);
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 */
158 static int get_counter(const char **p
)
164 if (!isdigit((int)**p
)) {
170 n
= 10 * n
+ (i
- '0');
178 static int getlen(const char *p
)
187 case 'W': /* word (2 byte) */
190 case 'K': /* status word? (2 byte) */
193 case 'N': /* count of substructures (word) at end */
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) */
201 case 'b': /* offset to data (with counter) (4 byte) */
205 case 'B': /* byte (with optional counter) */
206 n
+= get_counter(&p
);
213 static BOOL
init_package(struct pack_desc
*p
, int count
, int subcount
)
218 if (!p
->format
|| !p
->base
) {
222 i
= count
* getlen(p
->format
);
224 i
+= subcount
* getlen(p
->subformat
);
226 p
->structbuf
= p
->base
;
230 p
->curpos
= p
->format
;
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
241 p
->errcode
= ERRmoredata
;
243 p
->errcode
= ERRbuftoosmall
;
246 p
->errcode
= NERR_Success
;
250 p
->stringbuf
= p
->base
+ i
;
252 return (p
->errcode
== NERR_Success
);
255 static int package(struct pack_desc
*p
, ...)
258 int needed
=0, stringneeded
;
259 const char *str
=NULL
;
260 int is_string
=0, stringused
;
267 p
->curpos
= p
->format
;
269 p
->curpos
= p
->subformat
;
274 str
= va_arg(args
,char*);
275 SMB_ASSERT(strncmp(str
,p
->curpos
,strlen(str
)) == 0);
284 switch( *p
->curpos
++ ) {
285 case 'W': /* word (2 byte) */
287 temp
= va_arg(args
,int);
288 if (p
->buflen
>= needed
) {
289 SSVAL(p
->structbuf
,0,temp
);
292 case 'K': /* status word? (2 byte) */
294 temp
= va_arg(args
,int);
295 if (p
->buflen
>= needed
) {
296 SSVAL(p
->structbuf
,0,temp
);
299 case 'N': /* count of substructures (word) at end */
301 p
->subcount
= va_arg(args
,int);
302 if (p
->buflen
>= needed
) {
303 SSVAL(p
->structbuf
,0,p
->subcount
);
306 case 'D': /* double word (4 byte) */
308 temp
= va_arg(args
,int);
309 if (p
->buflen
>= needed
) {
310 SIVAL(p
->structbuf
,0,temp
);
313 case 'B': /* byte (with optional counter) */
314 needed
= get_counter(&p
->curpos
);
316 char *s
= va_arg(args
,char*);
317 if (p
->buflen
>= needed
) {
318 StrnCpy(p
->structbuf
,s
?s
:"",needed
-1);
322 case 'z': /* offset to zero terminated string (4 byte) */
323 str
= va_arg(args
,char*);
324 stringneeded
= (str
? strlen(str
)+1 : 0);
327 case 'l': /* offset to user data (4 byte) */
328 str
= va_arg(args
,char*);
329 stringneeded
= va_arg(args
,int);
332 case 'b': /* offset to data (with counter) (4 byte) */
333 str
= va_arg(args
,char*);
334 stringneeded
= get_counter(&p
->curpos
);
340 if (stringneeded
>= 0) {
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
;
351 SIVAL(p
->structbuf
,0,0);
353 SIVAL(p
->structbuf
,0,PTR_DIFF(p
->stringbuf
,p
->base
));
354 memcpy(p
->stringbuf
,str
?str
:"",stringused
);
356 p
->stringbuf
[stringused
-1] = '\0';
358 p
->stringbuf
+= stringused
;
359 p
->stringlen
-= stringused
;
360 p
->usedlen
+= stringused
;
363 p
->neededlen
+= stringneeded
;
366 p
->neededlen
+= needed
;
367 if (p
->buflen
>= needed
) {
368 p
->structbuf
+= needed
;
370 p
->usedlen
+= needed
;
372 if (p
->errcode
== NERR_Success
) {
373 p
->errcode
= ERRmoredata
;
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)
383 #define PACK(desc,t,v) package(desc,v)
384 #define PACKl(desc,t,v,l) package(desc,v,l)
387 static void PACKI(struct pack_desc
* desc
, const char *t
,int v
)
392 static void PACKS(struct pack_desc
* desc
,const char *t
,const char *v
)
397 /****************************************************************************
399 ****************************************************************************/
401 static void PackDriverData(struct pack_desc
* desc
)
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",-1, STR_TERMINATE
);
408 PACKl(desc
,"l",drivdata
,sizeof drivdata
); /* pDriverData */
411 static int check_printq_info(struct pack_desc
* desc
,
412 unsigned int uLevel
, char *id1
, char *id2
)
414 desc
->subformat
= NULL
;
417 desc
->format
= "B13";
420 desc
->format
= "B13BWWWzzzzzWW";
423 desc
->format
= "B13BWWWzzzzzWN";
424 desc
->subformat
= "WB21BB16B10zWWzDDz";
427 desc
->format
= "zWWWWzzzzWWzzl";
430 desc
->format
= "zWWWWzzzzWNzzl";
431 desc
->subformat
= "WWzWWDDzz";
440 desc
->format
= "WzzzzzzzzN";
441 desc
->subformat
= "z";
444 DEBUG(0,("check_printq_info: invalid level %d\n",
448 if (id1
== NULL
|| strcmp(desc
->format
,id1
) != 0) {
449 DEBUG(0,("check_printq_info: invalid format %s\n",
450 id1
? id1
: "<NULL>" ));
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>" ));
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
468 #define RAP_QUEUE_STATUS_PAUSED 1
469 #define RAP_QUEUE_STATUS_ERROR 2
471 /* turn a print job status into a on the wire status
473 static int printj_status(int v
)
477 return RAP_JOB_STATUS_QUEUED
;
479 return RAP_JOB_STATUS_PAUSED
;
481 return RAP_JOB_STATUS_SPOOLING
;
483 return RAP_JOB_STATUS_PRINTING
;
488 /* turn a print queue status into a on the wire status
490 static int printq_status(int v
)
496 return RAP_QUEUE_STATUS_PAUSED
;
498 return RAP_QUEUE_STATUS_ERROR
;
501 static void fill_printjob_info(connection_struct
*conn
, int snum
, int uLevel
,
502 struct pack_desc
*desc
,
503 print_queue_struct
*queue
, int n
)
505 time_t t
= queue
->time
;
507 /* the client expects localtime */
508 t
-= get_time_zone(t
);
510 PACKI(desc
,"W",pjobid_to_rap(lp_const_servicename(snum
),queue
->job
)); /* uJobId */
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 */
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 */
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 */
559 /********************************************************************
560 Return a driver name given an snum.
561 Returns True if from tdb, False otherwise.
562 ********************************************************************/
564 static BOOL
get_driver_name(int snum
, pstring drivername
)
566 NT_PRINTER_INFO_LEVEL
*info
= NULL
;
569 get_a_printer (NULL
, &info
, 2, lp_servicename(snum
));
571 pstrcpy( drivername
, info
->info_2
->drivername
);
573 free_a_printer(&info
, 2);
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 ********************************************************************/
583 static void fill_printq_info_52(connection_struct
*conn
, int snum
,
584 struct pack_desc
* desc
, int count
)
588 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
589 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
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
)));
599 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
,
602 DEBUG(3,("fill_printq_info_52: Failed to lookup driver [%s]\n",
603 printer
->info_2
->drivername
));
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);
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 */
617 fstrcpy(location
, "\\\\%L\\print$\\WIN40\\0");
618 standard_sub_basic( "", "", location
, sizeof(location
)-1 );
619 PACKS(desc
,"z", location
); /* share to retrieve files */
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 */
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 */
634 for ( i
=0; i
<count
&& driver
.info_3
->dependentfiles
&& *driver
.info_3
->dependentfiles
[i
]; i
++)
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
]));
643 DEBUG(3,("fill_printq_info_52: file count specified by client [%d] != number of dependent files [%i]\n",
646 DEBUG(3,("fill_printq_info on <%s> gave %d entries\n", SERVICE(snum
),i
));
648 desc
->errcode
=NERR_Success
;
652 DEBUG(3,("fill_printq_info: Can't supply driver files\n"));
653 desc
->errcode
=NERR_notsupported
;
657 free_a_printer( &printer
, 2 );
660 free_a_printer_driver( driver
, 3 );
664 static 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
)
672 PACKS(desc
,"B13",SERVICE(snum
));
677 PACKS(desc
,"z",Expand(conn
,snum
,SERVICE(snum
)));
680 PACKI(desc
,"K",printq_status(status
->status
));
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 */
694 PACKS(desc
,"z","UNKNOWN PRINTER");
695 PACKI(desc
,"W",LPSTAT_ERROR
);
697 else if (!status
|| !status
->message
[0]) {
698 PACKS(desc
,"z",Expand(conn
,snum
,lp_comment(snum
)));
699 PACKI(desc
,"W",LPSTAT_OK
); /* status */
701 PACKS(desc
,"z",status
->message
);
702 PACKI(desc
,"W",printq_status(status
->status
)); /* status */
704 PACKI(desc
,(uLevel
== 1 ? "W" : "N"),count
);
707 if (uLevel
== 3 || uLevel
== 4) {
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. */
721 PACKI(desc
,"W",LPSTAT_OK
); /* fsStatus */
723 PACKI(desc
,"W",printq_status(status
->status
)); /* fsStatus */
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 */
732 if (uLevel
== 2 || uLevel
== 4) {
734 for (i
=0;i
<count
;i
++)
735 fill_printjob_info(conn
,snum
,uLevel
== 2 ? 1 : 2,desc
,&queue
[i
],i
);
739 fill_printq_info_52( conn
, snum
, desc
, count
);
742 /* This function returns the number of files for a given driver */
743 static int get_printerdrivernumber(int snum
)
746 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
747 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
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
)));
757 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
,
760 DEBUG(3,("get_printerdrivernumber: Failed to lookup driver [%s]\n",
761 printer
->info_2
->drivername
));
765 /* count the number of files */
766 while ( driver
.info_3
->dependentfiles
&& *driver
.info_3
->dependentfiles
[result
] )
771 free_a_printer( &printer
, 2 );
774 free_a_printer_driver( driver
, 3 );
779 static 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
)
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
);
794 struct pack_desc desc
;
795 print_queue_struct
*queue
=NULL
;
796 print_status_struct status
;
799 if (!str1
|| !str2
|| !p
) {
802 memset((char *)&status
,'\0',sizeof(status
));
803 memset((char *)&desc
,'\0',sizeof(desc
));
805 p
= skip_string(param
,tpscnt
,p
);
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(). */
813 /* remove any trailing username */
814 if ((p
= strchr_m(QueueName
,'%')))
817 DEBUG(3,("api_DosPrintQGetInfo uLevel=%d name=%s\n",uLevel
,QueueName
));
819 /* check it's a supported varient */
820 if (!prefix_ok(str1
,"zWrLh"))
822 if (!check_printq_info(&desc
,uLevel
,str2
,str3
)) {
824 * Patch from Scott Moomaw <scott@bridgewater.edu>
825 * to return the 'invalid info level' error if an
826 * unknown level was requested.
830 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
834 SSVALS(*rparam
,0,ERRunknownlevel
);
840 snum
= find_service(QueueName
);
841 if ( !(lp_snum_ok(snum
) && lp_print_ok(snum
)) )
845 count
= get_printerdrivernumber(snum
);
846 DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count
));
848 count
= print_queue_status(snum
, &queue
,&status
);
852 *rdata
= SMB_REALLOC_LIMIT(*rdata
,mdrcnt
);
857 desc
.buflen
= mdrcnt
;
860 * Don't return data but need to get correct length
861 * init_package will return wrong size if buflen=0
863 desc
.buflen
= getlen(desc
.format
);
864 desc
.base
= tmpdata
= (char *) SMB_MALLOC (desc
.buflen
);
867 if (init_package(&desc
,1,count
)) {
868 desc
.subcount
= count
;
869 fill_printq_info(conn
,snum
,uLevel
,&desc
,count
,queue
,&status
);
872 *rdata_len
= desc
.usedlen
;
875 * We must set the return code to ERRbuftoosmall
876 * in order to support lanman style printing with Win NT/2k
879 if (!mdrcnt
&& lp_disable_spoolss())
880 desc
.errcode
= ERRbuftoosmall
;
882 *rdata_len
= desc
.usedlen
;
884 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
888 SSVALS(*rparam
,0,desc
.errcode
);
890 SSVAL(*rparam
,4,desc
.neededlen
);
892 DEBUG(4,("printqgetinfo: errorcode %d\n",desc
.errcode
));
900 /****************************************************************************
901 View list of all print jobs on all queues.
902 ****************************************************************************/
904 static 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
)
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();
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;
924 if (!param_format
|| !output_format1
|| !p
) {
928 memset((char *)&desc
,'\0',sizeof(desc
));
930 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel
));
932 if (!prefix_ok(param_format
,"WrLeh")) {
935 if (!check_printq_info(&desc
,uLevel
,output_format1
,output_format2
)) {
937 * Patch from Scott Moomaw <scott@bridgewater.edu>
938 * to return the 'invalid info level' error if an
939 * unknown level was requested.
943 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
947 SSVALS(*rparam
,0,ERRunknownlevel
);
953 for (i
= 0; i
< services
; i
++) {
954 if (lp_snum_ok(i
) && lp_print_ok(i
) && lp_browseable(i
)) {
959 if((queue
= SMB_MALLOC_ARRAY(print_queue_struct
*, queuecnt
)) == NULL
) {
960 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
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"));
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"));
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
];
985 *rdata
= SMB_REALLOC_LIMIT(*rdata
,mdrcnt
);
991 desc
.buflen
= mdrcnt
;
993 if (init_package(&desc
,queuecnt
,subcnt
)) {
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
]);
1000 if (desc
.errcode
== NERR_Success
) {
1007 SAFE_FREE(subcntarr
);
1009 *rdata_len
= desc
.usedlen
;
1011 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
1015 SSVALS(*rparam
,0,desc
.errcode
);
1017 SSVAL(*rparam
,4,succnt
);
1018 SSVAL(*rparam
,6,queuecnt
);
1020 for (i
= 0; i
< queuecnt
; i
++) {
1022 SAFE_FREE(queue
[i
]);
1033 SAFE_FREE(subcntarr
);
1034 for (i
= 0; i
< queuecnt
; i
++) {
1036 SAFE_FREE(queue
[i
]);
1045 /****************************************************************************
1046 Get info level for a server list query.
1047 ****************************************************************************/
1049 static BOOL
check_server_info(int uLevel
, char* id
)
1053 if (strcmp(id
,"B16") != 0) {
1058 if (strcmp(id
,"B16BBDz") != 0) {
1068 struct srv_info_struct
{
1076 /*******************************************************************
1077 Get server info lists from the files saved by nmbd. Return the
1079 ******************************************************************/
1081 static int get_server_info(uint32 servertype
,
1082 struct srv_info_struct
**servers
,
1088 BOOL local_list_only
;
1091 lines
= file_lines_load(lock_path(SERVER_LIST
), NULL
, 0);
1093 DEBUG(4,("Can't open %s - %s\n",lock_path(SERVER_LIST
),strerror(errno
)));
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
);
1102 local_list_only
= (servertype
& SV_TYPE_LOCAL_LIST_ONLY
);
1104 DEBUG(4,("Servertype search: %8x\n",servertype
));
1106 for (i
=0;lines
[i
];i
++) {
1108 struct srv_info_struct
*s
;
1109 const char *ptr
= lines
[i
];
1116 if (count
== alloced
) {
1118 *servers
= SMB_REALLOC_ARRAY(*servers
,struct srv_info_struct
, alloced
);
1120 DEBUG(0,("get_server_info: failed to enlarge servers info struct!\n"));
1121 file_lines_free(lines
);
1124 memset((char *)((*servers
)+count
),'\0',sizeof(**servers
)*(alloced
-count
));
1126 s
= &(*servers
)[count
];
1128 if (!next_token(&ptr
,s
->name
, NULL
, sizeof(s
->name
))) {
1131 if (!next_token(&ptr
,stype
, NULL
, sizeof(stype
))) {
1134 if (!next_token(&ptr
,s
->comment
, NULL
, sizeof(s
->comment
))) {
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());
1142 if (sscanf(stype
,"%X",&s
->type
) != 1) {
1143 DEBUG(4,("r:host file "));
1147 /* Filter the servers/domains we return based on what was asked for. */
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"));
1155 /* doesn't match up: don't want it */
1156 if (!(servertype
& s
->type
)) {
1157 DEBUG(4,("r:serv type "));
1161 if ((servertype
& SV_TYPE_DOMAIN_ENUM
) !=
1162 (s
->type
& SV_TYPE_DOMAIN_ENUM
)) {
1163 DEBUG(4,("s: dom mismatch "));
1167 if (!strequal(domain
, s
->domain
) && !(servertype
& SV_TYPE_DOMAIN_ENUM
)) {
1171 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
1172 s
->type
&= ~SV_TYPE_LOCAL_LIST_ONLY
;
1175 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
1176 s
->name
, s
->type
, s
->comment
, s
->domain
));
1177 s
->server_added
= True
;
1180 DEBUG(4,("%20s %8x %25s %15s\n",
1181 s
->name
, s
->type
, s
->comment
, s
->domain
));
1185 file_lines_free(lines
);
1189 /*******************************************************************
1190 Fill in a server info structure.
1191 ******************************************************************/
1193 static int fill_srv_info(struct srv_info_struct
*service
,
1194 int uLevel
, char **buf
, int *buflen
,
1195 char **stringbuf
, int *stringspace
, char *baseaddr
)
1218 len
= strlen(service
->comment
)+1;
1222 *buflen
= struct_len
;
1224 return struct_len
+ len
;
1229 if (*buflen
< struct_len
) {
1236 p2
= p
+ struct_len
;
1237 l2
= *buflen
- struct_len
;
1245 push_ascii(p
,service
->name
, MAX_NETBIOSNAME_LEN
, STR_TERMINATE
);
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
);
1257 *buf
= p
+ struct_len
;
1258 *buflen
-= struct_len
;
1269 static BOOL
srv_comp(struct srv_info_struct
*s1
,struct srv_info_struct
*s2
)
1271 return(strcmp(s1
->name
,s2
->name
));
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 ****************************************************************************/
1279 static 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
)
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);
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;
1298 BOOL domain_request
;
1301 if (!str1
|| !str2
|| !p
) {
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
1309 if (servertype
== SV_TYPE_ALL
) {
1310 servertype
&= ~(SV_TYPE_DOMAIN_ENUM
|SV_TYPE_LOCAL_LIST_ONLY
);
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. */
1319 if ((servertype
& SV_TYPE_LOCAL_LIST_ONLY
) && !(servertype
& SV_TYPE_DOMAIN_ENUM
)) {
1320 servertype
= SV_TYPE_ALL
& ~(SV_TYPE_DOMAIN_ENUM
);
1323 domain_request
= ((servertype
& SV_TYPE_DOMAIN_ENUM
) != 0);
1324 local_request
= ((servertype
& SV_TYPE_LOCAL_LIST_ONLY
) != 0);
1328 if (!prefix_ok(str1
,"WrLehD")) {
1331 if (!check_server_info(uLevel
,str2
)) {
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
)));
1339 if (strcmp(str1
, "WrLehDz") == 0) {
1340 if (skip_string(param
,tpscnt
,p
) == NULL
) {
1343 pull_ascii_fstring(domain
, p
);
1345 fstrcpy(domain
, lp_workgroup());
1348 if (lp_browse_list()) {
1349 total
= get_server_info(servertype
,&servers
,domain
);
1352 data_len
= fixed_len
= string_len
= 0;
1356 qsort(servers
,total
,sizeof(servers
[0]),QSORT_CAST srv_comp
);
1360 char *lastname
=NULL
;
1362 for (i
=0;i
<total
;i
++) {
1363 struct srv_info_struct
*s
= &servers
[i
];
1365 if (lastname
&& strequal(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
));
1373 if (data_len
<= buf_len
) {
1376 string_len
+= s_len
;
1383 *rdata_len
= fixed_len
+ string_len
;
1384 *rdata
= SMB_REALLOC_LIMIT(*rdata
,*rdata_len
);
1388 memset(*rdata
,'\0',*rdata_len
);
1390 p2
= (*rdata
) + fixed_len
; /* auxilliary data (strings) will go here */
1396 char *lastname
=NULL
;
1397 int count2
= counted
;
1399 for (i
= 0; i
< total
&& count2
;i
++) {
1400 struct srv_info_struct
*s
= &servers
[i
];
1402 if (lastname
&& strequal(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
));
1414 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
1418 SSVAL(*rparam
,0,(missed
== 0 ? NERR_Success
: ERRmoredata
));
1420 SSVAL(*rparam
,4,counted
);
1421 SSVAL(*rparam
,6,counted
+missed
);
1425 DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
1426 domain
,uLevel
,counted
,counted
+missed
));
1431 /****************************************************************************
1432 command 0x34 - suspected of being a "Lookup Names" stub api
1433 ****************************************************************************/
1435 static 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
)
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);
1449 if (!str1
|| !str2
|| !p
) {
1453 DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
1454 str1
, str2
, p
, uLevel
, buf_len
));
1456 if (!prefix_ok(str1
,"zWrLeh")) {
1463 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
1468 SSVAL(*rparam
,0,0x08AC); /* informational warning message */
1470 SSVAL(*rparam
,4,counted
);
1471 SSVAL(*rparam
,6,counted
+missed
);
1476 /****************************************************************************
1477 get info about a share
1478 ****************************************************************************/
1480 static BOOL
check_share_info(int uLevel
, char* id
)
1484 if (strcmp(id
,"B13") != 0) {
1489 if (strcmp(id
,"B13BWz") != 0) {
1494 if (strcmp(id
,"B13BWzWWWzB9B") != 0) {
1499 if (strcmp(id
,"B13BWzWWWzB9BB9BWzWWzWW") != 0) {
1509 static int fill_share_info(connection_struct
*conn
, int snum
, int uLevel
,
1510 char** buf
, int* buflen
,
1511 char** stringbuf
, int* stringspace
, char* baseaddr
)
1541 len
+= StrlenExpanded(conn
,snum
,lp_comment(snum
));
1544 len
+= strlen(lp_pathname(snum
)) + 1;
1547 *buflen
= struct_len
;
1552 return struct_len
+ len
;
1557 if ((*buflen
) < struct_len
) {
1565 p2
= p
+ struct_len
;
1566 l2
= (*buflen
) - struct_len
;
1573 push_ascii(p
,lp_servicename(snum
),13, STR_TERMINATE
);
1579 type
= STYPE_DISKTREE
;
1580 if (lp_print_ok(snum
)) {
1581 type
= STYPE_PRINTQ
;
1583 if (strequal("IPC",lp_fstype(snum
))) {
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
);
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 */
1601 memset(p
+40,0,SHPWLEN
+2);
1612 (*buf
) = p
+ struct_len
;
1613 (*buflen
) -= struct_len
;
1615 (*stringspace
) = l2
;
1624 static 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
)
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);
1638 if (!str1
|| !str2
|| !netname
|| !p
) {
1642 snum
= find_service(netname
);
1647 /* check it's a supported varient */
1648 if (!prefix_ok(str1
,"zWrLh")) {
1651 if (!check_share_info(uLevel
,str2
)) {
1655 *rdata
= SMB_REALLOC_LIMIT(*rdata
,mdrcnt
);
1660 *rdata_len
= fill_share_info(conn
,snum
,uLevel
,&p
,&mdrcnt
,0,0,0);
1661 if (*rdata_len
< 0) {
1666 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
1670 SSVAL(*rparam
,0,NERR_Success
);
1671 SSVAL(*rparam
,2,0); /* converter word */
1672 SSVAL(*rparam
,4,*rdata_len
);
1677 /****************************************************************************
1678 View the list of available shares.
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 ****************************************************************************/
1687 static BOOL
api_RNetShareEnum( connection_struct
*conn
, uint16 vuid
,
1688 char *param
, int tpscnt
,
1689 char *data
, int tdscnt
,
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);
1704 int total
=0,counted
=0;
1705 BOOL missed
= False
;
1707 int data_len
, fixed_len
, string_len
;
1708 int f_len
= 0, s_len
= 0;
1710 if (!str1
|| !str2
|| !p
) {
1714 if (!prefix_ok(str1
,"WrLeh")) {
1717 if (!check_share_info(uLevel
,str2
)) {
1721 /* Ensure all the usershares are loaded. */
1723 count
= load_usershare_shares();
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
))) {
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)) {
1736 data_len
+= fill_share_info(conn
,i
,uLevel
,0,&f_len
,0,&s_len
,0);
1737 if (data_len
<= buf_len
) {
1740 string_len
+= s_len
;
1747 *rdata_len
= fixed_len
+ string_len
;
1748 *rdata
= SMB_REALLOC_LIMIT(*rdata
,*rdata_len
);
1752 memset(*rdata
,0,*rdata_len
);
1754 p2
= (*rdata
) + fixed_len
; /* auxiliary data (strings) will go here */
1759 for( i
= 0; i
< count
; i
++ ) {
1760 fstring servicename_dos
;
1761 if (!(lp_browseable(i
) && lp_snum_ok(i
))) {
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) {
1774 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
1778 SSVAL(*rparam
,0,missed
? ERRmoredata
: NERR_Success
);
1780 SSVAL(*rparam
,4,counted
);
1781 SSVAL(*rparam
,6,total
);
1783 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
1784 counted
,total
,uLevel
,
1785 buf_len
,*rdata_len
,mdrcnt
));
1790 /****************************************************************************
1792 ****************************************************************************/
1794 static 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
)
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);
1808 char *command
, *cmdname
;
1809 unsigned int offset
;
1813 if (!str1
|| !str2
|| !p
) {
1817 /* check it's a supported varient */
1818 if (!prefix_ok(str1
,RAP_WShareAdd_REQ
)) {
1821 if (!check_share_info(uLevel
,str2
)) {
1828 /* Do we have a string ? */
1829 if (skip_string(data
,mdrcnt
,data
) == NULL
) {
1832 pull_ascii_fstring(sharename
,data
);
1833 snum
= find_service(sharename
);
1834 if (snum
>= 0) { /* already exists */
1843 /* only support disk share adds */
1844 if (SVAL(data
,14)!=STYPE_DISKTREE
) {
1848 offset
= IVAL(data
, 16);
1849 if (offset
>= mdrcnt
) {
1850 res
= ERRinvalidparam
;
1854 /* Do we have a string ? */
1855 if (skip_string(data
,mdrcnt
,data
+offset
) == NULL
) {
1858 pull_ascii_fstring(comment
, offset
? (data
+offset
) : "");
1860 offset
= IVAL(data
, 26);
1862 if (offset
>= mdrcnt
) {
1863 res
= ERRinvalidparam
;
1867 /* Do we have a string ? */
1868 if (skip_string(data
,mdrcnt
,data
+offset
) == NULL
) {
1871 pull_ascii_pstring(pathname
, offset
? (data
+offset
) : "");
1873 string_replace(sharename
, '"', ' ');
1874 string_replace(pathname
, '"', ' ');
1875 string_replace(comment
, '"', ' ');
1877 cmdname
= lp_add_share_cmd();
1879 if (!cmdname
|| *cmdname
== '\0') {
1883 asprintf(&command
, "%s \"%s\" \"%s\" \"%s\" \"%s\"",
1884 lp_add_share_cmd(), dyn_CONFIGFILE
, sharename
, pathname
, comment
);
1887 DEBUG(10,("api_RNetShareAdd: Running [%s]\n", command
));
1889 if ((res
= smbrun(command
, NULL
)) != 0) {
1890 DEBUG(1,("api_RNetShareAdd: Running [%s] returned (%d)\n", command
, res
));
1896 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED
, NULL
, 0, False
, NULL
);
1903 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
1907 SSVAL(*rparam
,0,NERR_Success
);
1908 SSVAL(*rparam
,2,0); /* converter word */
1909 SSVAL(*rparam
,4,*rdata_len
);
1917 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
1922 SSVAL(*rparam
,0,res
);
1927 /****************************************************************************
1928 view list of groups available
1929 ****************************************************************************/
1931 static 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
)
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
);
1945 struct pdb_search
*search
;
1946 struct samr_displayentry
*entries
;
1950 if (!str1
|| !str2
|| !p
) {
1954 if (strcmp(str1
,"WrLeh") != 0) {
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
1966 if (strcmp("B21",str2
) != 0) {
1970 /* get list of domain groups SID_DOMAIN_GRP=2 */
1972 search
= pdb_search_groups();
1975 if (search
== NULL
) {
1976 DEBUG(3,("api_RNetGroupEnum:failed to get group list"));
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
));
1986 num_entries
= pdb_search_entries(search
, resume_context
, 0xffffffff,
1990 *rdata_len
= cli_buf_size
;
1991 *rdata
= SMB_REALLOC_LIMIT(*rdata
,*rdata_len
);
1998 for(i
=0; i
<num_entries
; i
++) {
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
));
2006 p
+= 5; /* Both NT4 and W2k3SP1 do padding here.
2009 /* set overflow error */
2010 DEBUG(3,("overflow on entry %d group %s\n", i
, name
));
2016 pdb_search_destroy(search
);
2018 *rdata_len
= PTR_DIFF(p
,*rdata
);
2021 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
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?? */
2033 /*******************************************************************
2034 Get groups that a user is a member of.
2035 ******************************************************************/
2037 static 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
)
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
;
2051 struct samu
*sampw
= NULL
;
2059 enum lsa_SidType type
;
2060 TALLOC_CTX
*mem_ctx
;
2062 if (!str1
|| !str2
|| !UserName
|| !p
) {
2067 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
2072 /* check it's a supported varient */
2074 if ( strcmp(str1
,"zWrLeh") != 0 )
2079 level_string
= "B21";
2085 if (strcmp(level_string
,str2
) != 0)
2088 *rdata_len
= mdrcnt
+ 1024;
2089 *rdata
= SMB_REALLOC_LIMIT(*rdata
,*rdata_len
);
2093 SSVAL(*rparam
,0,NERR_Success
);
2094 SSVAL(*rparam
,2,0); /* converter word */
2098 mem_ctx
= talloc_new(NULL
);
2099 if (mem_ctx
== NULL
) {
2100 DEBUG(0, ("talloc_new failed\n"));
2104 if ( !(sampw
= samu_new(mem_ctx
)) ) {
2105 DEBUG(0, ("samu_new() failed!\n"));
2106 TALLOC_FREE(mem_ctx
);
2110 /* Lookup the user information; This should only be one of
2111 our accounts (not remote domains) */
2113 become_root(); /* ROOT BLOCK */
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
));
2121 if (type
!= SID_NAME_USER
) {
2122 DEBUG(10, ("%s is a %s, not a user\n", UserName
,
2123 sid_type_lookup(type
)));
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
));
2137 result
= pdb_enum_group_memberships(mem_ctx
, sampw
,
2138 &sids
, &gids
, &num_groups
);
2140 if (!NT_STATUS_IS_OK(result
)) {
2141 DEBUG(10, ("pdb_enum_group_memberships failed for %s\n",
2146 for (i
=0; i
<num_groups
; i
++) {
2148 const char *grp_name
;
2150 if ( lookup_sid(mem_ctx
, &sids
[i
], NULL
, &grp_name
, NULL
) ) {
2151 pstrcpy(p
, grp_name
);
2157 *rdata_len
= PTR_DIFF(p
,*rdata
);
2159 SSVAL(*rparam
,4,count
); /* is this right?? */
2160 SSVAL(*rparam
,6,count
); /* is this right?? */
2165 unbecome_root(); /* END ROOT BLOCK */
2167 TALLOC_FREE(mem_ctx
);
2172 /*******************************************************************
2174 ******************************************************************/
2176 static 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
)
2186 int i
, resume_context
, cli_buf_size
;
2187 struct pdb_search
*search
;
2188 struct samr_displayentry
*users
;
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
);
2194 if (!str1
|| !str2
|| !p
) {
2198 if (strcmp(str1
,"WrLeh") != 0)
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
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
));
2214 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
2219 /* check it's a supported varient */
2220 if (strcmp("B21",str2
) != 0)
2223 *rdata_len
= cli_buf_size
;
2224 *rdata
= SMB_REALLOC_LIMIT(*rdata
,*rdata_len
);
2232 search
= pdb_search_users(ACB_NORMAL
);
2234 if (search
== NULL
) {
2235 DEBUG(0, ("api_RNetUserEnum:unable to open sam database.\n"));
2240 num_users
= pdb_search_entries(search
, resume_context
, 0xffffffff,
2244 errflags
=NERR_Success
;
2246 for (i
=0; i
<num_users
; i
++) {
2247 const char *name
= users
[i
].account_name
;
2249 if(((PTR_DIFF(p
,*rdata
)+21)<=*rdata_len
)&&(strlen(name
)<=21)) {
2251 DEBUG(10,("api_RNetUserEnum:adding entry %d username "
2252 "%s\n",count_sent
,p
));
2256 /* set overflow error */
2257 DEBUG(10,("api_RNetUserEnum:overflow on entry %d "
2258 "username %s\n",count_sent
,name
));
2264 pdb_search_destroy(search
);
2266 *rdata_len
= PTR_DIFF(p
,*rdata
);
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?? */
2276 /****************************************************************************
2277 Get the time of day info.
2278 ****************************************************************************/
2280 static 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
)
2288 time_t unixdate
= time(NULL
);
2292 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
2298 *rdata
= SMB_REALLOC_LIMIT(*rdata
,*rdata_len
);
2303 SSVAL(*rparam
,0,NERR_Success
);
2304 SSVAL(*rparam
,2,0); /* converter word */
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 */
2312 /* the client expects to get localtime, not GMT, in this bit
2313 (I think, this needs testing) */
2314 t
= localtime(&unixdate
);
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
);
2334 /****************************************************************************
2335 Set the user password.
2336 *****************************************************************************/
2338 static 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
)
2345 char *np
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2348 fstring pass1
,pass2
;
2350 /* Skip 2 strings. */
2351 p
= skip_string(param
,tpscnt
,np
);
2352 p
= skip_string(param
,tpscnt
,p
);
2358 /* Do we have a string ? */
2359 if (skip_string(param
,tpscnt
,p
) == NULL
) {
2362 pull_ascii_fstring(user
,p
);
2364 p
= skip_string(param
,tpscnt
,p
);
2369 memset(pass1
,'\0',sizeof(pass1
));
2370 memset(pass2
,'\0',sizeof(pass2
));
2372 * We use 31 here not 32 as we're checking
2373 * the last byte we want to access is safe.
2375 if (!is_offset_safe(param
,tpscnt
,p
,31)) {
2379 memcpy(pass2
,p
+16,16);
2382 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
2389 SSVAL(*rparam
,0,NERR_badpass
);
2390 SSVAL(*rparam
,2,0); /* converter word */
2392 DEBUG(3,("Set password for <%s>\n",user
));
2395 * Attempt to verify the old password against smbpasswd entries
2396 * Win98 clients send old and new password in plaintext for this call.
2400 auth_serversupplied_info
*server_info
= NULL
;
2401 DATA_BLOB password
= data_blob(pass1
, strlen(pass1
)+1);
2403 if (NT_STATUS_IS_OK(check_plaintext_password(user
,password
,&server_info
))) {
2406 if (NT_STATUS_IS_OK(change_oem_password(server_info
->sam_account
, pass1
, pass2
, False
, NULL
))) {
2407 SSVAL(*rparam
,0,NERR_Success
);
2411 TALLOC_FREE(server_info
);
2413 data_blob_clear_free(&password
);
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
2426 if(SVAL(*rparam
,0) != NERR_Success
) {
2427 struct samu
*hnd
= NULL
;
2429 if (check_lanman_password(user
,(unsigned char *)pass1
,(unsigned char *)pass2
, &hnd
)) {
2431 if (change_lanman_password(hnd
,(uchar
*)pass2
)) {
2432 SSVAL(*rparam
,0,NERR_Success
);
2439 memset((char *)pass1
,'\0',sizeof(fstring
));
2440 memset((char *)pass2
,'\0',sizeof(fstring
));
2445 /****************************************************************************
2446 Set the user password (SamOEM version - gets plaintext).
2447 ****************************************************************************/
2449 static 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
)
2457 char *p
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2459 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
2469 SSVAL(*rparam
,0,NERR_badpass
);
2472 * Check the parameter definition is correct.
2475 /* Do we have a string ? */
2476 if (skip_string(param
,tpscnt
,p
) == 0) {
2479 if(!strequal(p
, "zsT")) {
2480 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", p
));
2483 p
= skip_string(param
, tpscnt
, p
);
2488 /* Do we have a string ? */
2489 if (skip_string(param
,tpscnt
,p
) == 0) {
2492 if(!strequal(p
, "B516B16")) {
2493 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p
));
2496 p
= skip_string(param
,tpscnt
,p
);
2500 /* Do we have a string ? */
2501 if (skip_string(param
,tpscnt
,p
) == 0) {
2504 p
+= pull_ascii_fstring(user
,p
);
2506 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user
));
2509 * Pass the user through the NT -> unix user mapping
2513 (void)map_username(user
);
2515 if (NT_STATUS_IS_OK(pass_oem_change(user
, (uchar
*) data
, (uchar
*)&data
[516], NULL
, NULL
, NULL
))) {
2516 SSVAL(*rparam
,0,NERR_Success
);
2522 /****************************************************************************
2525 ****************************************************************************/
2527 static 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
)
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
);
2542 WERROR werr
= WERR_OK
;
2544 if (!str1
|| !str2
|| !p
) {
2548 * We use 1 here not 2 as we're checking
2549 * the last byte we want to access is safe.
2551 if (!is_offset_safe(param
,tpscnt
,p
,1)) {
2554 if(!rap_to_pjobid(SVAL(p
,0), sharename
, &jobid
))
2557 /* check it's a supported varient */
2558 if (!(strcsequal(str1
,"W") && strcsequal(str2
,"")))
2562 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
2568 if (!print_job_exists(sharename
, jobid
)) {
2569 errcode
= NERR_JobNotFound
;
2573 snum
= lp_servicenumber( sharename
);
2575 errcode
= NERR_DestNotFound
;
2579 errcode
= NERR_notsupported
;
2582 case 81: /* delete */
2583 if (print_job_delete(¤t_user
, snum
, jobid
, &werr
))
2584 errcode
= NERR_Success
;
2586 case 82: /* pause */
2587 if (print_job_pause(¤t_user
, snum
, jobid
, &werr
))
2588 errcode
= NERR_Success
;
2590 case 83: /* resume */
2591 if (print_job_resume(¤t_user
, snum
, jobid
, &werr
))
2592 errcode
= NERR_Success
;
2596 if (!W_ERROR_IS_OK(werr
))
2597 errcode
= W_ERROR_V(werr
);
2600 SSVAL(*rparam
,0,errcode
);
2601 SSVAL(*rparam
,2,0); /* converter word */
2606 /****************************************************************************
2607 Purge a print queue - or pause or resume it.
2608 ****************************************************************************/
2610 static 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
)
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
;
2623 WERROR werr
= WERR_OK
;
2625 if (!str1
|| !str2
|| !QueueName
) {
2629 /* check it's a supported varient */
2630 if (!(strcsequal(str1
,"z") && strcsequal(str2
,"")))
2634 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
2640 if (skip_string(param
,tpscnt
,QueueName
) == NULL
) {
2643 snum
= print_queue_snum(QueueName
);
2646 errcode
= NERR_JobNotFound
;
2651 case 74: /* Pause queue */
2652 if (print_queue_pause(¤t_user
, snum
, &werr
)) errcode
= NERR_Success
;
2654 case 75: /* Resume queue */
2655 if (print_queue_resume(¤t_user
, snum
, &werr
)) errcode
= NERR_Success
;
2657 case 103: /* Purge */
2658 if (print_queue_purge(¤t_user
, snum
, &werr
)) errcode
= NERR_Success
;
2662 if (!W_ERROR_IS_OK(werr
)) errcode
= W_ERROR_V(werr
);
2665 SSVAL(*rparam
,0,errcode
);
2666 SSVAL(*rparam
,2,0); /* converter word */
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 ****************************************************************************/
2679 static int check_printjob_info(struct pack_desc
* desc
,
2680 int uLevel
, char* id
)
2682 desc
->subformat
= NULL
;
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;
2690 DEBUG(0,("check_printjob_info: invalid level %d\n",
2694 if (id
== NULL
|| strcmp(desc
->format
,id
) != 0) {
2695 DEBUG(0,("check_printjob_info: invalid format %s\n",
2696 id
? id
: "<NULL>" ));
2702 static 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
)
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
);
2715 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,2,-1);
2716 int function
= get_safe_SVAL(param
,tpscnt
,p
,4,-1);
2719 if (!str1
|| !str2
|| !p
) {
2723 * We use 1 here not 2 as we're checking
2724 * the last byte we want to access is safe.
2726 if (!is_offset_safe(param
,tpscnt
,p
,1)) {
2729 if(!rap_to_pjobid(SVAL(p
,0), sharename
, &jobid
))
2732 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
2737 if (!share_defined(sharename
)) {
2738 DEBUG(0,("api_PrintJobInfo: sharen [%s] not defined\n",
2745 /* check it's a supported varient */
2746 if ((strcmp(str1
,"WWsTP")) ||
2747 (!check_printjob_info(&desc
,uLevel
,str2
)))
2750 if (!print_job_exists(sharename
, jobid
)) {
2751 errcode
=NERR_JobNotFound
;
2755 errcode
= NERR_notsupported
;
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
;
2768 /* change print job name, data gives the name */
2769 if (print_job_set_name(sharename
, jobid
, data
)) {
2770 errcode
=NERR_Success
;
2779 SSVALS(*rparam
,0,errcode
);
2780 SSVAL(*rparam
,2,0); /* converter word */
2786 /****************************************************************************
2787 Get info about the server.
2788 ****************************************************************************/
2790 static 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
)
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);
2804 if (!str1
|| !str2
|| !p
) {
2808 DEBUG(4,("NetServerGetInfo level %d\n",uLevel
));
2810 /* check it's a supported varient */
2811 if (!prefix_ok(str1
,"WrLh")) {
2817 if (strcmp(str2
,"B16") != 0) {
2823 if (strcmp(str2
,"B16BBDz") != 0) {
2829 if (strcmp(str2
,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")!= 0) {
2835 if (strcmp(str2
,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz") != 0) {
2841 if (strcmp(str2
,"DN") != 0) {
2847 if (strcmp(str2
,"B16BBDzWWzzz") != 0) {
2856 *rdata_len
= mdrcnt
;
2857 *rdata
= SMB_REALLOC_LIMIT(*rdata
,*rdata_len
);
2863 p2
= p
+ struct_len
;
2865 srvstr_push(NULL
, p
,global_myname(),16,
2866 STR_ASCII
|STR_UPPER
|STR_TERMINATE
);
2870 struct srv_info_struct
*servers
=NULL
;
2873 uint32 servertype
= lp_default_server_announce();
2875 push_ascii(comment
,lp_serverstring(), MAX_SERVER_STRING_LENGTH
,STR_TERMINATE
);
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
);
2888 SCVAL(p
,0,lp_major_announce_version());
2889 SCVAL(p
,1,lp_minor_announce_version());
2890 SIVAL(p
,2,servertype
);
2892 if (mdrcnt
== struct_len
) {
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
);
2910 return False
; /* not yet implemented */
2913 *rdata_len
= PTR_DIFF(p2
,*rdata
);
2916 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
2920 SSVAL(*rparam
,0,NERR_Success
);
2921 SSVAL(*rparam
,2,0); /* converter word */
2922 SSVAL(*rparam
,4,*rdata_len
);
2927 /****************************************************************************
2928 Get info about the server.
2929 ****************************************************************************/
2931 static 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
)
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
);
2942 int level
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2944 if (!str1
|| !str2
|| !p
) {
2948 DEBUG(4,("NetWkstaGetInfo level %d\n",level
));
2951 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
2956 /* check it's a supported varient */
2957 if (!(level
==10 && strcsequal(str1
,"WrLh") && strcsequal(str2
,"zzzBBzz"))) {
2961 *rdata_len
= mdrcnt
+ 1024;
2962 *rdata
= SMB_REALLOC_LIMIT(*rdata
,*rdata_len
);
2967 SSVAL(*rparam
,0,NERR_Success
);
2968 SSVAL(*rparam
,2,0); /* converter word */
2971 p2
= get_safe_ptr(*rdata
,*rdata_len
,p
,22);
2976 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* host name */
2977 pstrcpy(p2
,get_local_machine_name());
2979 p2
= skip_string(*rdata
,*rdata_len
,p2
);
2985 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
));
2986 pstrcpy(p2
,current_user_info
.smb_name
);
2987 p2
= skip_string(*rdata
,*rdata_len
,p2
);
2993 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* login domain */
2994 pstrcpy(p2
,lp_workgroup());
2996 p2
= skip_string(*rdata
,*rdata_len
,p2
);
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 */
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
);
3014 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* don't know */
3016 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3022 *rdata_len
= PTR_DIFF(p2
,*rdata
);
3024 SSVAL(*rparam
,4,*rdata_len
);
3029 /****************************************************************************
3030 get info about a user
3032 struct user_info_11 {
3033 char usri11_name[21]; 0-20
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
3057 usri11_name specifies the user name for which information is retireved
3059 usri11_pad aligns the next data structure element to a word boundary
3061 usri11_comment is a null terminated ASCII comment
3063 usri11_user_comment is a null terminated ASCII comment about the user
3065 usri11_priv specifies the level of the privilege assigned to the user.
3066 The possible values are:
3068 Name Value Description
3069 USER_PRIV_GUEST 0 Guest privilege
3070 USER_PRIV_USER 1 User privilege
3071 USER_PRV_ADMIN 2 Administrator privilege
3073 usri11_auth_flags specifies the account operator privileges. The
3074 possible values are:
3076 Name Value Description
3077 AF_OP_PRINT 0 Print operator
3080 Leach, Naik [Page 28]
3084 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
3087 AF_OP_COMM 1 Communications operator
3088 AF_OP_SERVER 2 Server operator
3089 AF_OP_ACCOUNTS 3 Accounts operator
3092 usri11_password_age specifies how many seconds have elapsed since the
3093 password was last changed.
3095 usri11_home_dir points to a null terminated ASCII string that contains
3096 the path name of the user's home directory.
3098 usri11_parms points to a null terminated ASCII string that is set
3099 aside for use by applications.
3101 usri11_last_logon specifies the time when the user last logged on.
3102 This value is stored as the number of seconds elapsed since
3103 00:00:00, January 1, 1970.
3105 usri11_last_logoff specifies the time when the user last logged off.
3106 This value is stored as the number of seconds elapsed since
3107 00:00:00, January 1, 1970. A value of 0 means the last logoff
3110 usri11_bad_pw_count specifies the number of incorrect passwords
3111 entered since the last successful logon.
3113 usri11_log1_num_logons specifies the number of times this user has
3114 logged on. A value of -1 means the number of logons is unknown.
3116 usri11_logon_server points to a null terminated ASCII string that
3117 contains the name of the server to which logon requests are sent.
3118 A null string indicates logon requests should be sent to the
3121 usri11_country_code specifies the country code for the user's language
3124 usri11_workstations points to a null terminated ASCII string that
3125 contains the names of workstations the user may log on from.
3126 There may be up to 8 workstations, with the names separated by
3127 commas. A null strings indicates there are no restrictions.
3129 usri11_max_storage specifies the maximum amount of disk space the user
3130 can occupy. A value of 0xffffffff indicates there are no
3133 usri11_units_per_week specifies the equal number of time units into
3134 which a week is divided. This value must be equal to 168.
3136 usri11_logon_hours points to a 21 byte (168 bits) string that
3137 specifies the time during which the user can log on. Each bit
3138 represents one unique hour in a week. The first bit (bit 0, word
3139 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
3143 Leach, Naik [Page 29]
3147 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
3150 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
3151 are no restrictions.
3153 usri11_code_page specifies the code page for the user's language of
3156 All of the pointers in this data structure need to be treated
3157 specially. The pointer is a 32 bit pointer. The higher 16 bits need
3158 to be ignored. The converter word returned in the parameters section
3159 needs to be subtracted from the lower 16 bits to calculate an offset
3160 into the return buffer where this ASCII string resides.
3162 There is no auxiliary data in the response.
3164 ****************************************************************************/
3166 #define usri11_name 0
3167 #define usri11_pad 21
3168 #define usri11_comment 22
3169 #define usri11_usr_comment 26
3170 #define usri11_full_name 30
3171 #define usri11_priv 34
3172 #define usri11_auth_flags 36
3173 #define usri11_password_age 40
3174 #define usri11_homedir 44
3175 #define usri11_parms 48
3176 #define usri11_last_logon 52
3177 #define usri11_last_logoff 56
3178 #define usri11_bad_pw_count 60
3179 #define usri11_num_logons 62
3180 #define usri11_logon_server 64
3181 #define usri11_country_code 68
3182 #define usri11_workstations 70
3183 #define usri11_max_storage 74
3184 #define usri11_units_per_week 78
3185 #define usri11_logon_hours 80
3186 #define usri11_code_page 84
3187 #define usri11_end 86
3189 #define USER_PRIV_GUEST 0
3190 #define USER_PRIV_USER 1
3191 #define USER_PRIV_ADMIN 2
3193 #define AF_OP_PRINT 0
3194 #define AF_OP_COMM 1
3195 #define AF_OP_SERVER 2
3196 #define AF_OP_ACCOUNTS 3
3199 static BOOL
api_RNetUserGetInfo(connection_struct
*conn
, uint16 vuid
,
3200 char *param
, int tpscnt
,
3201 char *data
, int tdscnt
,
3202 int mdrcnt
,int mprcnt
,
3203 char **rdata
,char **rparam
,
3204 int *rdata_len
,int *rparam_len
)
3206 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3207 char *str2
= skip_string(param
,tpscnt
,str1
);
3208 char *UserName
= skip_string(param
,tpscnt
,str2
);
3209 char *p
= skip_string(param
,tpscnt
,UserName
);
3210 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3212 const char *level_string
;
3214 /* get NIS home of a previously validated user - simeon */
3215 /* With share level security vuid will always be zero.
3216 Don't depend on vuser being non-null !!. JRA */
3217 user_struct
*vuser
= get_valid_user_struct(vuid
);
3219 DEBUG(3,(" Username of UID %d is %s\n", (int)vuser
->uid
,
3220 vuser
->user
.unix_name
));
3223 if (!str1
|| !str2
|| !UserName
|| !p
) {
3228 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
3233 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel
));
3235 /* check it's a supported variant */
3236 if (strcmp(str1
,"zWrLh") != 0) {
3240 case 0: level_string
= "B21"; break;
3241 case 1: level_string
= "B21BB16DWzzWz"; break;
3242 case 2: level_string
= "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
3243 case 10: level_string
= "B21Bzzz"; break;
3244 case 11: level_string
= "B21BzzzWDDzzDDWWzWzDWb21W"; break;
3245 default: return False
;
3248 if (strcmp(level_string
,str2
) != 0) {
3252 *rdata_len
= mdrcnt
+ 1024;
3253 *rdata
= SMB_REALLOC_LIMIT(*rdata
,*rdata_len
);
3258 SSVAL(*rparam
,0,NERR_Success
);
3259 SSVAL(*rparam
,2,0); /* converter word */
3262 p2
= get_safe_ptr(*rdata
,*rdata_len
,p
,usri11_end
);
3268 fstrcpy(p
+usri11_name
,UserName
); /* 21 bytes - user name */
3271 SCVAL(p
,usri11_pad
,0); /* padding - 1 byte */
3276 SIVAL(p
,usri11_comment
,PTR_DIFF(p2
,p
)); /* comment */
3277 pstrcpy(p2
,"Comment");
3278 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3283 SIVAL(p
,usri11_usr_comment
,PTR_DIFF(p2
,p
)); /* user_comment */
3284 pstrcpy(p2
,"UserComment");
3285 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3290 /* EEK! the cifsrap.txt doesn't have this in!!!! */
3291 SIVAL(p
,usri11_full_name
,PTR_DIFF(p2
,p
)); /* full name */
3292 pstrcpy(p2
,((vuser
!= NULL
) ? vuser
->user
.full_name
: UserName
));
3293 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3300 /* modelled after NTAS 3.51 reply */
3301 SSVAL(p
,usri11_priv
,conn
->admin_user
?USER_PRIV_ADMIN
:USER_PRIV_USER
);
3302 SIVAL(p
,usri11_auth_flags
,AF_OP_PRINT
); /* auth flags */
3303 SIVALS(p
,usri11_password_age
,-1); /* password age */
3304 SIVAL(p
,usri11_homedir
,PTR_DIFF(p2
,p
)); /* home dir */
3305 pstrcpy(p2
, vuser
&& vuser
->homedir
? vuser
->homedir
: "");
3306 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3310 SIVAL(p
,usri11_parms
,PTR_DIFF(p2
,p
)); /* parms */
3312 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3316 SIVAL(p
,usri11_last_logon
,0); /* last logon */
3317 SIVAL(p
,usri11_last_logoff
,0); /* last logoff */
3318 SSVALS(p
,usri11_bad_pw_count
,-1); /* bad pw counts */
3319 SSVALS(p
,usri11_num_logons
,-1); /* num logons */
3320 SIVAL(p
,usri11_logon_server
,PTR_DIFF(p2
,p
)); /* logon server */
3321 pstrcpy(p2
,"\\\\*");
3322 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3326 SSVAL(p
,usri11_country_code
,0); /* country code */
3328 SIVAL(p
,usri11_workstations
,PTR_DIFF(p2
,p
)); /* workstations */
3330 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3335 SIVALS(p
,usri11_max_storage
,-1); /* max storage */
3336 SSVAL(p
,usri11_units_per_week
,168); /* units per week */
3337 SIVAL(p
,usri11_logon_hours
,PTR_DIFF(p2
,p
)); /* logon hours */
3339 /* a simple way to get logon hours at all times. */
3341 SCVAL(p2
,21,0); /* fix zero termination */
3342 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3347 SSVAL(p
,usri11_code_page
,0); /* code page */
3350 if (uLevel
== 1 || uLevel
== 2) {
3351 memset(p
+22,' ',16); /* password */
3352 SIVALS(p
,38,-1); /* password age */
3354 conn
->admin_user
?USER_PRIV_ADMIN
:USER_PRIV_USER
);
3355 SIVAL(p
,44,PTR_DIFF(p2
,*rdata
)); /* home dir */
3356 pstrcpy(p2
, vuser
&& vuser
->homedir
? vuser
->homedir
: "");
3357 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3361 SIVAL(p
,48,PTR_DIFF(p2
,*rdata
)); /* comment */
3363 SSVAL(p
,52,0); /* flags */
3364 SIVAL(p
,54,PTR_DIFF(p2
,*rdata
)); /* script_path */
3365 pstrcpy(p2
,vuser
&& vuser
->logon_script
? vuser
->logon_script
: "");
3366 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3371 SIVAL(p
,60,0); /* auth_flags */
3372 SIVAL(p
,64,PTR_DIFF(p2
,*rdata
)); /* full_name */
3373 pstrcpy(p2
,((vuser
!= NULL
) ? vuser
->user
.full_name
: UserName
));
3374 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3378 SIVAL(p
,68,0); /* urs_comment */
3379 SIVAL(p
,72,PTR_DIFF(p2
,*rdata
)); /* parms */
3381 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3385 SIVAL(p
,76,0); /* workstations */
3386 SIVAL(p
,80,0); /* last_logon */
3387 SIVAL(p
,84,0); /* last_logoff */
3388 SIVALS(p
,88,-1); /* acct_expires */
3389 SIVALS(p
,92,-1); /* max_storage */
3390 SSVAL(p
,96,168); /* units_per_week */
3391 SIVAL(p
,98,PTR_DIFF(p2
,*rdata
)); /* logon_hours */
3394 SSVALS(p
,102,-1); /* bad_pw_count */
3395 SSVALS(p
,104,-1); /* num_logons */
3396 SIVAL(p
,106,PTR_DIFF(p2
,*rdata
)); /* logon_server */
3399 pstrcpy(tmp
, "\\\\%L");
3400 standard_sub_basic("", "", tmp
, sizeof(tmp
));
3403 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3407 SSVAL(p
,110,49); /* country_code */
3408 SSVAL(p
,112,860); /* code page */
3412 *rdata_len
= PTR_DIFF(p2
,*rdata
);
3414 SSVAL(*rparam
,4,*rdata_len
); /* is this right?? */
3419 static BOOL
api_WWkstaUserLogon(connection_struct
*conn
,uint16 vuid
,
3420 char *param
, int tpscnt
,
3421 char *data
, int tdscnt
,
3422 int mdrcnt
,int mprcnt
,
3423 char **rdata
,char **rparam
,
3424 int *rdata_len
,int *rparam_len
)
3426 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3427 char *str2
= skip_string(param
,tpscnt
,str1
);
3428 char *p
= skip_string(param
,tpscnt
,str2
);
3430 struct pack_desc desc
;
3432 /* With share level security vuid will always be zero.
3433 Don't depend on vuser being non-null !!. JRA */
3434 user_struct
*vuser
= get_valid_user_struct(vuid
);
3436 if (!str1
|| !str2
|| !p
) {
3441 DEBUG(3,(" Username of UID %d is %s\n", (int)vuser
->uid
,
3442 vuser
->user
.unix_name
));
3445 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3446 name
= get_safe_str_ptr(param
,tpscnt
,p
,2);
3451 memset((char *)&desc
,'\0',sizeof(desc
));
3453 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel
,name
));
3455 /* check it's a supported varient */
3456 if (strcmp(str1
,"OOWb54WrLh") != 0) {
3459 if (uLevel
!= 1 || strcmp(str2
,"WB21BWDWWDDDDDDDzzzD") != 0) {
3463 *rdata
= SMB_REALLOC_LIMIT(*rdata
,mdrcnt
);
3470 desc
.buflen
= mdrcnt
;
3471 desc
.subformat
= NULL
;
3474 if (init_package(&desc
,1,0)) {
3475 PACKI(&desc
,"W",0); /* code */
3476 PACKS(&desc
,"B21",name
); /* eff. name */
3477 PACKS(&desc
,"B",""); /* pad */
3478 PACKI(&desc
,"W", conn
->admin_user
?USER_PRIV_ADMIN
:USER_PRIV_USER
);
3479 PACKI(&desc
,"D",0); /* auth flags XXX */
3480 PACKI(&desc
,"W",0); /* num logons */
3481 PACKI(&desc
,"W",0); /* bad pw count */
3482 PACKI(&desc
,"D",0); /* last logon */
3483 PACKI(&desc
,"D",-1); /* last logoff */
3484 PACKI(&desc
,"D",-1); /* logoff time */
3485 PACKI(&desc
,"D",-1); /* kickoff time */
3486 PACKI(&desc
,"D",0); /* password age */
3487 PACKI(&desc
,"D",0); /* password can change */
3488 PACKI(&desc
,"D",-1); /* password must change */
3492 fstrcpy(mypath
,"\\\\");
3493 fstrcat(mypath
,get_local_machine_name());
3495 PACKS(&desc
,"z",mypath
); /* computer */
3498 PACKS(&desc
,"z",lp_workgroup());/* domain */
3499 PACKS(&desc
,"z", vuser
&& vuser
->logon_script
? vuser
->logon_script
:""); /* script path */
3500 PACKI(&desc
,"D",0x00000000); /* reserved */
3503 *rdata_len
= desc
.usedlen
;
3505 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
3509 SSVALS(*rparam
,0,desc
.errcode
);
3511 SSVAL(*rparam
,4,desc
.neededlen
);
3513 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc
.errcode
));
3518 /****************************************************************************
3519 api_WAccessGetUserPerms
3520 ****************************************************************************/
3522 static BOOL
api_WAccessGetUserPerms(connection_struct
*conn
,uint16 vuid
,
3523 char *param
, int tpscnt
,
3524 char *data
, int tdscnt
,
3525 int mdrcnt
,int mprcnt
,
3526 char **rdata
,char **rparam
,
3527 int *rdata_len
,int *rparam_len
)
3529 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3530 char *str2
= skip_string(param
,tpscnt
,str1
);
3531 char *user
= skip_string(param
,tpscnt
,str2
);
3532 char *resource
= skip_string(param
,tpscnt
,user
);
3534 if (!str1
|| !str2
|| !user
|| !resource
) {
3538 if (skip_string(param
,tpscnt
,resource
) == NULL
) {
3541 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user
,resource
));
3543 /* check it's a supported varient */
3544 if (strcmp(str1
,"zzh") != 0) {
3547 if (strcmp(str2
,"") != 0) {
3552 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
3556 SSVALS(*rparam
,0,0); /* errorcode */
3557 SSVAL(*rparam
,2,0); /* converter word */
3558 SSVAL(*rparam
,4,0x7f); /* permission flags */
3563 /****************************************************************************
3564 api_WPrintJobEnumerate
3565 ****************************************************************************/
3567 static BOOL
api_WPrintJobGetInfo(connection_struct
*conn
, uint16 vuid
,
3568 char *param
, int tpscnt
,
3569 char *data
, int tdscnt
,
3570 int mdrcnt
,int mprcnt
,
3571 char **rdata
,char **rparam
,
3572 int *rdata_len
,int *rparam_len
)
3574 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3575 char *str2
= skip_string(param
,tpscnt
,str1
);
3576 char *p
= skip_string(param
,tpscnt
,str2
);
3583 struct pack_desc desc
;
3584 print_queue_struct
*queue
=NULL
;
3585 print_status_struct status
;
3588 if (!str1
|| !str2
|| !p
) {
3592 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,2,-1);
3594 memset((char *)&desc
,'\0',sizeof(desc
));
3595 memset((char *)&status
,'\0',sizeof(status
));
3597 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel
,SVAL(p
,0)));
3599 /* check it's a supported varient */
3600 if (strcmp(str1
,"WWrLh") != 0) {
3603 if (!check_printjob_info(&desc
,uLevel
,str2
)) {
3607 if(!rap_to_pjobid(SVAL(p
,0), sharename
, &jobid
)) {
3611 snum
= lp_servicenumber( sharename
);
3612 if (snum
< 0 || !VALID_SNUM(snum
)) {
3616 count
= print_queue_status(snum
,&queue
,&status
);
3617 for (i
= 0; i
< count
; i
++) {
3618 if (queue
[i
].job
== jobid
) {
3624 *rdata
= SMB_REALLOC_LIMIT(*rdata
,mdrcnt
);
3629 desc
.buflen
= mdrcnt
;
3632 * Don't return data but need to get correct length
3633 * init_package will return wrong size if buflen=0
3635 desc
.buflen
= getlen(desc
.format
);
3636 desc
.base
= tmpdata
= (char *)SMB_MALLOC( desc
.buflen
);
3639 if (init_package(&desc
,1,0)) {
3641 fill_printjob_info(conn
,snum
,uLevel
,&desc
,&queue
[i
],i
);
3642 *rdata_len
= desc
.usedlen
;
3644 desc
.errcode
= NERR_JobNotFound
;
3650 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
3654 SSVALS(*rparam
,0,desc
.errcode
);
3656 SSVAL(*rparam
,4,desc
.neededlen
);
3661 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc
.errcode
));
3666 static BOOL
api_WPrintJobEnumerate(connection_struct
*conn
, uint16 vuid
,
3667 char *param
, int tpscnt
,
3668 char *data
, int tdscnt
,
3669 int mdrcnt
,int mprcnt
,
3670 char **rdata
,char **rparam
,
3671 int *rdata_len
,int *rparam_len
)
3673 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3674 char *str2
= skip_string(param
,tpscnt
,str1
);
3675 char *p
= skip_string(param
,tpscnt
,str2
);
3681 struct pack_desc desc
;
3682 print_queue_struct
*queue
=NULL
;
3683 print_status_struct status
;
3685 if (!str1
|| !str2
|| !p
) {
3689 memset((char *)&desc
,'\0',sizeof(desc
));
3690 memset((char *)&status
,'\0',sizeof(status
));
3692 p
= skip_string(param
,tpscnt
,p
);
3696 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3698 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel
,name
));
3700 /* check it's a supported variant */
3701 if (strcmp(str1
,"zWrLeh") != 0) {
3706 return False
; /* defined only for uLevel 0,1,2 */
3709 if (!check_printjob_info(&desc
,uLevel
,str2
)) {
3713 snum
= find_service(name
);
3714 if ( !(lp_snum_ok(snum
) && lp_print_ok(snum
)) ) {
3718 count
= print_queue_status(snum
,&queue
,&status
);
3720 *rdata
= SMB_REALLOC_LIMIT(*rdata
,mdrcnt
);
3726 desc
.buflen
= mdrcnt
;
3728 if (init_package(&desc
,count
,0)) {
3730 for (i
= 0; i
< count
; i
++) {
3731 fill_printjob_info(conn
,snum
,uLevel
,&desc
,&queue
[i
],i
);
3732 if (desc
.errcode
== NERR_Success
) {
3738 *rdata_len
= desc
.usedlen
;
3741 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
3745 SSVALS(*rparam
,0,desc
.errcode
);
3747 SSVAL(*rparam
,4,succnt
);
3748 SSVAL(*rparam
,6,count
);
3752 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc
.errcode
));
3757 static int check_printdest_info(struct pack_desc
* desc
,
3758 int uLevel
, char* id
)
3760 desc
->subformat
= NULL
;
3763 desc
->format
= "B9";
3766 desc
->format
= "B9B21WWzW";
3772 desc
->format
= "zzzWWzzzWW";
3775 DEBUG(0,("check_printdest_info: invalid level %d\n",
3779 if (id
== NULL
|| strcmp(desc
->format
,id
) != 0) {
3780 DEBUG(0,("check_printdest_info: invalid string %s\n",
3781 id
? id
: "<NULL>" ));
3787 static void fill_printdest_info(connection_struct
*conn
, int snum
, int uLevel
,
3788 struct pack_desc
* desc
)
3792 strncpy(buf
,SERVICE(snum
),sizeof(buf
)-1);
3793 buf
[sizeof(buf
)-1] = 0;
3797 PACKS(desc
,"B9",buf
); /* szName */
3799 PACKS(desc
,"B21",""); /* szUserName */
3800 PACKI(desc
,"W",0); /* uJobId */
3801 PACKI(desc
,"W",0); /* fsStatus */
3802 PACKS(desc
,"z",""); /* pszStatus */
3803 PACKI(desc
,"W",0); /* time */
3807 if (uLevel
== 2 || uLevel
== 3) {
3808 PACKS(desc
,"z",buf
); /* pszPrinterName */
3810 PACKS(desc
,"z",""); /* pszUserName */
3811 PACKS(desc
,"z",""); /* pszLogAddr */
3812 PACKI(desc
,"W",0); /* uJobId */
3813 PACKI(desc
,"W",0); /* fsStatus */
3814 PACKS(desc
,"z",""); /* pszStatus */
3815 PACKS(desc
,"z",""); /* pszComment */
3816 PACKS(desc
,"z","NULL"); /* pszDrivers */
3817 PACKI(desc
,"W",0); /* time */
3818 PACKI(desc
,"W",0); /* pad1 */
3823 static BOOL
api_WPrintDestGetInfo(connection_struct
*conn
, uint16 vuid
,
3824 char *param
, int tpscnt
,
3825 char *data
, int tdscnt
,
3826 int mdrcnt
,int mprcnt
,
3827 char **rdata
,char **rparam
,
3828 int *rdata_len
,int *rparam_len
)
3830 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3831 char *str2
= skip_string(param
,tpscnt
,str1
);
3832 char *p
= skip_string(param
,tpscnt
,str2
);
3833 char* PrinterName
= p
;
3835 struct pack_desc desc
;
3839 if (!str1
|| !str2
|| !p
) {
3843 memset((char *)&desc
,'\0',sizeof(desc
));
3845 p
= skip_string(param
,tpscnt
,p
);
3849 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3851 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel
,PrinterName
));
3853 /* check it's a supported varient */
3854 if (strcmp(str1
,"zWrLh") != 0) {
3857 if (!check_printdest_info(&desc
,uLevel
,str2
)) {
3861 snum
= find_service(PrinterName
);
3862 if ( !(lp_snum_ok(snum
) && lp_print_ok(snum
)) ) {
3864 desc
.errcode
= NERR_DestNotFound
;
3868 *rdata
= SMB_REALLOC_LIMIT(*rdata
,mdrcnt
);
3873 desc
.buflen
= mdrcnt
;
3876 * Don't return data but need to get correct length
3877 * init_package will return wrong size if buflen=0
3879 desc
.buflen
= getlen(desc
.format
);
3880 desc
.base
= tmpdata
= (char *)SMB_MALLOC( desc
.buflen
);
3882 if (init_package(&desc
,1,0)) {
3883 fill_printdest_info(conn
,snum
,uLevel
,&desc
);
3885 *rdata_len
= desc
.usedlen
;
3889 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
3893 SSVALS(*rparam
,0,desc
.errcode
);
3895 SSVAL(*rparam
,4,desc
.neededlen
);
3897 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc
.errcode
));
3903 static BOOL
api_WPrintDestEnum(connection_struct
*conn
, uint16 vuid
,
3904 char *param
, int tpscnt
,
3905 char *data
, int tdscnt
,
3906 int mdrcnt
,int mprcnt
,
3907 char **rdata
,char **rparam
,
3908 int *rdata_len
,int *rparam_len
)
3910 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3911 char *str2
= skip_string(param
,tpscnt
,str1
);
3912 char *p
= skip_string(param
,tpscnt
,str2
);
3916 struct pack_desc desc
;
3917 int services
= lp_numservices();
3919 if (!str1
|| !str2
|| !p
) {
3923 memset((char *)&desc
,'\0',sizeof(desc
));
3925 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3927 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel
));
3929 /* check it's a supported varient */
3930 if (strcmp(str1
,"WrLeh") != 0) {
3933 if (!check_printdest_info(&desc
,uLevel
,str2
)) {
3938 for (i
= 0; i
< services
; i
++) {
3939 if (lp_snum_ok(i
) && lp_print_ok(i
) && lp_browseable(i
)) {
3945 *rdata
= SMB_REALLOC_LIMIT(*rdata
,mdrcnt
);
3952 desc
.buflen
= mdrcnt
;
3953 if (init_package(&desc
,queuecnt
,0)) {
3956 for (i
= 0; i
< services
; i
++) {
3957 if (lp_snum_ok(i
) && lp_print_ok(i
) && lp_browseable(i
)) {
3958 fill_printdest_info(conn
,i
,uLevel
,&desc
);
3960 if (desc
.errcode
== NERR_Success
) {
3967 *rdata_len
= desc
.usedlen
;
3970 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
3974 SSVALS(*rparam
,0,desc
.errcode
);
3976 SSVAL(*rparam
,4,succnt
);
3977 SSVAL(*rparam
,6,queuecnt
);
3979 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc
.errcode
));
3984 static BOOL
api_WPrintDriverEnum(connection_struct
*conn
, uint16 vuid
,
3985 char *param
, int tpscnt
,
3986 char *data
, int tdscnt
,
3987 int mdrcnt
,int mprcnt
,
3988 char **rdata
,char **rparam
,
3989 int *rdata_len
,int *rparam_len
)
3991 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3992 char *str2
= skip_string(param
,tpscnt
,str1
);
3993 char *p
= skip_string(param
,tpscnt
,str2
);
3996 struct pack_desc desc
;
3998 if (!str1
|| !str2
|| !p
) {
4002 memset((char *)&desc
,'\0',sizeof(desc
));
4004 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4006 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel
));
4008 /* check it's a supported varient */
4009 if (strcmp(str1
,"WrLeh") != 0) {
4012 if (uLevel
!= 0 || strcmp(str2
,"B41") != 0) {
4017 *rdata
= SMB_REALLOC_LIMIT(*rdata
,mdrcnt
);
4023 desc
.buflen
= mdrcnt
;
4024 if (init_package(&desc
,1,0)) {
4025 PACKS(&desc
,"B41","NULL");
4028 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
4030 *rdata_len
= desc
.usedlen
;
4033 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
4037 SSVALS(*rparam
,0,desc
.errcode
);
4039 SSVAL(*rparam
,4,succnt
);
4042 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc
.errcode
));
4047 static BOOL
api_WPrintQProcEnum(connection_struct
*conn
, uint16 vuid
,
4048 char *param
, int tpscnt
,
4049 char *data
, int tdscnt
,
4050 int mdrcnt
,int mprcnt
,
4051 char **rdata
,char **rparam
,
4052 int *rdata_len
,int *rparam_len
)
4054 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4055 char *str2
= skip_string(param
,tpscnt
,str1
);
4056 char *p
= skip_string(param
,tpscnt
,str2
);
4059 struct pack_desc desc
;
4061 if (!str1
|| !str2
|| !p
) {
4064 memset((char *)&desc
,'\0',sizeof(desc
));
4066 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4068 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel
));
4070 /* check it's a supported varient */
4071 if (strcmp(str1
,"WrLeh") != 0) {
4074 if (uLevel
!= 0 || strcmp(str2
,"B13") != 0) {
4079 *rdata
= SMB_REALLOC_LIMIT(*rdata
,mdrcnt
);
4085 desc
.buflen
= mdrcnt
;
4087 if (init_package(&desc
,1,0)) {
4088 PACKS(&desc
,"B13","lpd");
4091 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
4093 *rdata_len
= desc
.usedlen
;
4096 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
4100 SSVALS(*rparam
,0,desc
.errcode
);
4102 SSVAL(*rparam
,4,succnt
);
4105 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc
.errcode
));
4110 static BOOL
api_WPrintPortEnum(connection_struct
*conn
, uint16 vuid
,
4111 char *param
, int tpscnt
,
4112 char *data
, int tdscnt
,
4113 int mdrcnt
,int mprcnt
,
4114 char **rdata
,char **rparam
,
4115 int *rdata_len
,int *rparam_len
)
4117 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4118 char *str2
= skip_string(param
,tpscnt
,str1
);
4119 char *p
= skip_string(param
,tpscnt
,str2
);
4122 struct pack_desc desc
;
4124 if (!str1
|| !str2
|| !p
) {
4128 memset((char *)&desc
,'\0',sizeof(desc
));
4130 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4132 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel
));
4134 /* check it's a supported varient */
4135 if (strcmp(str1
,"WrLeh") != 0) {
4138 if (uLevel
!= 0 || strcmp(str2
,"B9") != 0) {
4143 *rdata
= SMB_REALLOC_LIMIT(*rdata
,mdrcnt
);
4148 memset((char *)&desc
,'\0',sizeof(desc
));
4150 desc
.buflen
= mdrcnt
;
4152 if (init_package(&desc
,1,0)) {
4153 PACKS(&desc
,"B13","lp0");
4156 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
4158 *rdata_len
= desc
.usedlen
;
4161 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
4165 SSVALS(*rparam
,0,desc
.errcode
);
4167 SSVAL(*rparam
,4,succnt
);
4170 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc
.errcode
));
4175 /****************************************************************************
4177 ****************************************************************************/
4179 static BOOL
api_RNetSessionEnum(connection_struct
*conn
, uint16 vuid
,
4180 char *param
, int tpscnt
,
4181 char *data
, int tdscnt
,
4182 int mdrcnt
,int mprcnt
,
4183 char **rdata
,char **rparam
,
4184 int *rdata_len
,int *rparam_len
)
4187 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4188 char *str2
= skip_string(param
,tpscnt
,str1
);
4189 char *p
= skip_string(param
,tpscnt
,str2
);
4191 struct pack_desc desc
;
4192 struct sessionid
*session_list
= NULL
;
4193 int i
, num_sessions
;
4195 if (!str1
|| !str2
|| !p
) {
4199 memset((char *)&desc
,'\0',sizeof(desc
));
4201 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4203 DEBUG(3,("RNetSessionEnum uLevel=%d\n",uLevel
));
4204 DEBUG(7,("RNetSessionEnum req string=%s\n",str1
));
4205 DEBUG(7,("RNetSessionEnum ret string=%s\n",str2
));
4207 /* check it's a supported varient */
4208 if (strcmp(str1
,RAP_NetSessionEnum_REQ
) != 0) {
4211 if (uLevel
!= 2 || strcmp(str2
,RAP_SESSION_INFO_L2
) != 0) {
4215 num_sessions
= list_sessions(&session_list
);
4218 *rdata
= SMB_REALLOC_LIMIT(*rdata
,mdrcnt
);
4220 SAFE_FREE(session_list
);
4224 memset((char *)&desc
,'\0',sizeof(desc
));
4226 desc
.buflen
= mdrcnt
;
4228 if (!init_package(&desc
,num_sessions
,0)) {
4229 SAFE_FREE(session_list
);
4233 for(i
=0; i
<num_sessions
; i
++) {
4234 PACKS(&desc
, "z", session_list
[i
].remote_machine
);
4235 PACKS(&desc
, "z", session_list
[i
].username
);
4236 PACKI(&desc
, "W", 1); /* num conns */
4237 PACKI(&desc
, "W", 0); /* num opens */
4238 PACKI(&desc
, "W", 1); /* num users */
4239 PACKI(&desc
, "D", 0); /* session time */
4240 PACKI(&desc
, "D", 0); /* idle time */
4241 PACKI(&desc
, "D", 0); /* flags */
4242 PACKS(&desc
, "z", "Unknown Client"); /* client type string */
4245 *rdata_len
= desc
.usedlen
;
4248 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
4250 SAFE_FREE(session_list
);
4253 SSVALS(*rparam
,0,desc
.errcode
);
4254 SSVAL(*rparam
,2,0); /* converter */
4255 SSVAL(*rparam
,4,num_sessions
); /* count */
4257 DEBUG(4,("RNetSessionEnum: errorcode %d\n",desc
.errcode
));
4259 SAFE_FREE(session_list
);
4264 /****************************************************************************
4265 The buffer was too small.
4266 ****************************************************************************/
4268 static BOOL
api_TooSmall(connection_struct
*conn
,uint16 vuid
, char *param
, char *data
,
4269 int mdrcnt
, int mprcnt
,
4270 char **rdata
, char **rparam
,
4271 int *rdata_len
, int *rparam_len
)
4273 *rparam_len
= MIN(*rparam_len
,mprcnt
);
4274 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
4281 SSVAL(*rparam
,0,NERR_BufTooSmall
);
4283 DEBUG(3,("Supplied buffer too small in API command\n"));
4288 /****************************************************************************
4289 The request is not supported.
4290 ****************************************************************************/
4292 static BOOL
api_Unsupported(connection_struct
*conn
, uint16 vuid
,
4293 char *param
, int tpscnt
,
4294 char *data
, int tdscnt
,
4295 int mdrcnt
, int mprcnt
,
4296 char **rdata
, char **rparam
,
4297 int *rdata_len
, int *rparam_len
)
4300 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
4307 SSVAL(*rparam
,0,NERR_notsupported
);
4308 SSVAL(*rparam
,2,0); /* converter word */
4310 DEBUG(3,("Unsupported API command\n"));
4315 static const struct {
4318 BOOL (*fn
)(connection_struct
*, uint16
,
4321 int,int,char **,char **,int *,int *);
4322 BOOL auth_user
; /* Deny anonymous access? */
4323 } api_commands
[] = {
4324 {"RNetShareEnum", RAP_WshareEnum
, api_RNetShareEnum
, True
},
4325 {"RNetShareGetInfo", RAP_WshareGetInfo
, api_RNetShareGetInfo
},
4326 {"RNetShareAdd", RAP_WshareAdd
, api_RNetShareAdd
},
4327 {"RNetSessionEnum", RAP_WsessionEnum
, api_RNetSessionEnum
, True
},
4328 {"RNetServerGetInfo", RAP_WserverGetInfo
, api_RNetServerGetInfo
},
4329 {"RNetGroupEnum", RAP_WGroupEnum
, api_RNetGroupEnum
, True
},
4330 {"RNetGroupGetUsers", RAP_WGroupGetUsers
, api_RNetGroupGetUsers
, True
},
4331 {"RNetUserEnum", RAP_WUserEnum
, api_RNetUserEnum
, True
},
4332 {"RNetUserGetInfo", RAP_WUserGetInfo
, api_RNetUserGetInfo
},
4333 {"NetUserGetGroups", RAP_WUserGetGroups
, api_NetUserGetGroups
},
4334 {"NetWkstaGetInfo", RAP_WWkstaGetInfo
, api_NetWkstaGetInfo
},
4335 {"DosPrintQEnum", RAP_WPrintQEnum
, api_DosPrintQEnum
, True
},
4336 {"DosPrintQGetInfo", RAP_WPrintQGetInfo
, api_DosPrintQGetInfo
},
4337 {"WPrintQueuePause", RAP_WPrintQPause
, api_WPrintQueueCtrl
},
4338 {"WPrintQueueResume", RAP_WPrintQContinue
, api_WPrintQueueCtrl
},
4339 {"WPrintJobEnumerate",RAP_WPrintJobEnum
, api_WPrintJobEnumerate
},
4340 {"WPrintJobGetInfo", RAP_WPrintJobGetInfo
, api_WPrintJobGetInfo
},
4341 {"RDosPrintJobDel", RAP_WPrintJobDel
, api_RDosPrintJobDel
},
4342 {"RDosPrintJobPause", RAP_WPrintJobPause
, api_RDosPrintJobDel
},
4343 {"RDosPrintJobResume",RAP_WPrintJobContinue
, api_RDosPrintJobDel
},
4344 {"WPrintDestEnum", RAP_WPrintDestEnum
, api_WPrintDestEnum
},
4345 {"WPrintDestGetInfo", RAP_WPrintDestGetInfo
, api_WPrintDestGetInfo
},
4346 {"NetRemoteTOD", RAP_NetRemoteTOD
, api_NetRemoteTOD
},
4347 {"WPrintQueuePurge", RAP_WPrintQPurge
, api_WPrintQueueCtrl
},
4348 {"NetServerEnum", RAP_NetServerEnum2
, api_RNetServerEnum
}, /* anon OK */
4349 {"WAccessGetUserPerms",RAP_WAccessGetUserPerms
,api_WAccessGetUserPerms
},
4350 {"SetUserPassword", RAP_WUserPasswordSet2
, api_SetUserPassword
},
4351 {"WWkstaUserLogon", RAP_WWkstaUserLogon
, api_WWkstaUserLogon
},
4352 {"PrintJobInfo", RAP_WPrintJobSetInfo
, api_PrintJobInfo
},
4353 {"WPrintDriverEnum", RAP_WPrintDriverEnum
, api_WPrintDriverEnum
},
4354 {"WPrintQProcEnum", RAP_WPrintQProcessorEnum
,api_WPrintQProcEnum
},
4355 {"WPrintPortEnum", RAP_WPrintPortEnum
, api_WPrintPortEnum
},
4356 {"SamOEMChangePassword",RAP_SamOEMChgPasswordUser2_P
,api_SamOEMChangePassword
}, /* anon OK */
4357 {NULL
, -1, api_Unsupported
}
4358 /* The following RAP calls are not implemented by Samba:
4360 RAP_WFileEnum2 - anon not OK
4365 /****************************************************************************
4366 Handle remote api calls
4367 ****************************************************************************/
4369 int api_reply(connection_struct
*conn
,uint16 vuid
,char *outbuf
,char *data
,char *params
,
4370 int tdscnt
,int tpscnt
,int mdrcnt
,int mprcnt
)
4374 char *rparam
= NULL
;
4375 const char *name1
= NULL
;
4376 const char *name2
= NULL
;
4383 DEBUG(0,("ERROR: NULL params in api_reply()\n"));
4390 api_command
= SVAL(params
,0);
4391 /* Is there a string at position params+2 ? */
4392 if (skip_string(params
,tpscnt
,params
+2)) {
4397 name2
= skip_string(params
,tpscnt
,params
+2);
4402 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
4406 tdscnt
,tpscnt
,mdrcnt
,mprcnt
));
4408 for (i
=0;api_commands
[i
].name
;i
++) {
4409 if (api_commands
[i
].id
== api_command
&& api_commands
[i
].fn
) {
4410 DEBUG(3,("Doing %s\n",api_commands
[i
].name
));
4415 /* Check whether this api call can be done anonymously */
4417 if (api_commands
[i
].auth_user
&& lp_restrict_anonymous()) {
4418 user_struct
*user
= get_valid_user_struct(vuid
);
4420 if (!user
|| user
->guest
) {
4421 return ERROR_NT(NT_STATUS_ACCESS_DENIED
);
4425 rdata
= (char *)SMB_MALLOC(1024);
4427 memset(rdata
,'\0',1024);
4430 rparam
= (char *)SMB_MALLOC(1024);
4432 memset(rparam
,'\0',1024);
4435 if(!rdata
|| !rparam
) {
4436 DEBUG(0,("api_reply: malloc fail !\n"));
4442 reply
= api_commands
[i
].fn(conn
,
4444 params
,tpscnt
, /* params + length */
4445 data
,tdscnt
, /* data + length */
4447 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
4450 if (rdata_len
> mdrcnt
|| rparam_len
> mprcnt
) {
4451 reply
= api_TooSmall(conn
,vuid
,params
,data
,mdrcnt
,mprcnt
,
4452 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
4455 /* if we get False back then it's actually unsupported */
4457 reply
= api_Unsupported(conn
,vuid
,params
,tpscnt
,data
,tdscnt
,mdrcnt
,mprcnt
,
4458 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
4461 /* If api_Unsupported returns false we can't return anything. */
4463 send_trans_reply(outbuf
, rparam
, rparam_len
, rdata
, rdata_len
, False
);