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 load_registry_shares();
1724 count
= load_usershare_shares();
1727 data_len
= fixed_len
= string_len
= 0;
1728 for (i
=0;i
<count
;i
++) {
1729 fstring servicename_dos
;
1730 if (!(lp_browseable(i
) && lp_snum_ok(i
))) {
1733 push_ascii_fstring(servicename_dos
, lp_servicename(i
));
1734 /* Maximum name length = 13. */
1735 if( lp_browseable( i
) && lp_snum_ok( i
) && (strlen(servicename_dos
) < 13)) {
1737 data_len
+= fill_share_info(conn
,i
,uLevel
,0,&f_len
,0,&s_len
,0);
1738 if (data_len
<= buf_len
) {
1741 string_len
+= s_len
;
1748 *rdata_len
= fixed_len
+ string_len
;
1749 *rdata
= SMB_REALLOC_LIMIT(*rdata
,*rdata_len
);
1753 memset(*rdata
,0,*rdata_len
);
1755 p2
= (*rdata
) + fixed_len
; /* auxiliary data (strings) will go here */
1760 for( i
= 0; i
< count
; i
++ ) {
1761 fstring servicename_dos
;
1762 if (!(lp_browseable(i
) && lp_snum_ok(i
))) {
1766 push_ascii_fstring(servicename_dos
, lp_servicename(i
));
1767 if (lp_browseable(i
) && lp_snum_ok(i
) && (strlen(servicename_dos
) < 13)) {
1768 if (fill_share_info( conn
,i
,uLevel
,&p
,&f_len
,&p2
,&s_len
,*rdata
) < 0) {
1775 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
1779 SSVAL(*rparam
,0,missed
? ERRmoredata
: NERR_Success
);
1781 SSVAL(*rparam
,4,counted
);
1782 SSVAL(*rparam
,6,total
);
1784 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
1785 counted
,total
,uLevel
,
1786 buf_len
,*rdata_len
,mdrcnt
));
1791 /****************************************************************************
1793 ****************************************************************************/
1795 static BOOL
api_RNetShareAdd(connection_struct
*conn
,uint16 vuid
,
1796 char *param
, int tpscnt
,
1797 char *data
, int tdscnt
,
1798 int mdrcnt
,int mprcnt
,
1799 char **rdata
,char **rparam
,
1800 int *rdata_len
,int *rparam_len
)
1802 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
1803 char *str2
= skip_string(param
,tpscnt
,str1
);
1804 char *p
= skip_string(param
,tpscnt
,str2
);
1805 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
1809 char *command
, *cmdname
;
1810 unsigned int offset
;
1814 if (!str1
|| !str2
|| !p
) {
1818 /* check it's a supported varient */
1819 if (!prefix_ok(str1
,RAP_WShareAdd_REQ
)) {
1822 if (!check_share_info(uLevel
,str2
)) {
1829 /* Do we have a string ? */
1830 if (skip_string(data
,mdrcnt
,data
) == NULL
) {
1833 pull_ascii_fstring(sharename
,data
);
1834 snum
= find_service(sharename
);
1835 if (snum
>= 0) { /* already exists */
1844 /* only support disk share adds */
1845 if (SVAL(data
,14)!=STYPE_DISKTREE
) {
1849 offset
= IVAL(data
, 16);
1850 if (offset
>= mdrcnt
) {
1851 res
= ERRinvalidparam
;
1855 /* Do we have a string ? */
1856 if (skip_string(data
,mdrcnt
,data
+offset
) == NULL
) {
1859 pull_ascii_fstring(comment
, offset
? (data
+offset
) : "");
1861 offset
= IVAL(data
, 26);
1863 if (offset
>= mdrcnt
) {
1864 res
= ERRinvalidparam
;
1868 /* Do we have a string ? */
1869 if (skip_string(data
,mdrcnt
,data
+offset
) == NULL
) {
1872 pull_ascii_pstring(pathname
, offset
? (data
+offset
) : "");
1874 string_replace(sharename
, '"', ' ');
1875 string_replace(pathname
, '"', ' ');
1876 string_replace(comment
, '"', ' ');
1878 cmdname
= lp_add_share_cmd();
1880 if (!cmdname
|| *cmdname
== '\0') {
1884 asprintf(&command
, "%s \"%s\" \"%s\" \"%s\" \"%s\"",
1885 lp_add_share_cmd(), dyn_CONFIGFILE
, sharename
, pathname
, comment
);
1888 DEBUG(10,("api_RNetShareAdd: Running [%s]\n", command
));
1890 if ((res
= smbrun(command
, NULL
)) != 0) {
1891 DEBUG(1,("api_RNetShareAdd: Running [%s] returned (%d)\n", command
, res
));
1897 message_send_all(smbd_messaging_context(),
1898 MSG_SMB_CONF_UPDATED
, NULL
, 0, NULL
);
1905 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
1909 SSVAL(*rparam
,0,NERR_Success
);
1910 SSVAL(*rparam
,2,0); /* converter word */
1911 SSVAL(*rparam
,4,*rdata_len
);
1919 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
1924 SSVAL(*rparam
,0,res
);
1929 /****************************************************************************
1930 view list of groups available
1931 ****************************************************************************/
1933 static BOOL
api_RNetGroupEnum(connection_struct
*conn
,uint16 vuid
,
1934 char *param
, int tpscnt
,
1935 char *data
, int tdscnt
,
1936 int mdrcnt
,int mprcnt
,
1937 char **rdata
,char **rparam
,
1938 int *rdata_len
,int *rparam_len
)
1942 int resume_context
, cli_buf_size
;
1943 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
1944 char *str2
= skip_string(param
,tpscnt
,str1
);
1945 char *p
= skip_string(param
,tpscnt
,str2
);
1947 struct pdb_search
*search
;
1948 struct samr_displayentry
*entries
;
1952 if (!str1
|| !str2
|| !p
) {
1956 if (strcmp(str1
,"WrLeh") != 0) {
1961 * W-> resume context (number of users to skip)
1962 * r -> return parameter pointer to receive buffer
1963 * L -> length of receive buffer
1964 * e -> return parameter number of entries
1965 * h -> return parameter total number of users
1968 if (strcmp("B21",str2
) != 0) {
1972 /* get list of domain groups SID_DOMAIN_GRP=2 */
1974 search
= pdb_search_groups();
1977 if (search
== NULL
) {
1978 DEBUG(3,("api_RNetGroupEnum:failed to get group list"));
1982 resume_context
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
1983 cli_buf_size
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
1984 DEBUG(10,("api_RNetGroupEnum:resume context: %d, client buffer size: "
1985 "%d\n", resume_context
, cli_buf_size
));
1988 num_entries
= pdb_search_entries(search
, resume_context
, 0xffffffff,
1992 *rdata_len
= cli_buf_size
;
1993 *rdata
= SMB_REALLOC_LIMIT(*rdata
,*rdata_len
);
2000 for(i
=0; i
<num_entries
; i
++) {
2002 fstrcpy(name
, entries
[i
].account_name
);
2003 if( ((PTR_DIFF(p
,*rdata
)+21) <= *rdata_len
) ) {
2004 /* truncate the name at 21 chars. */
2005 memcpy(p
, name
, 21);
2006 DEBUG(10,("adding entry %d group %s\n", i
, p
));
2008 p
+= 5; /* Both NT4 and W2k3SP1 do padding here.
2011 /* set overflow error */
2012 DEBUG(3,("overflow on entry %d group %s\n", i
, name
));
2018 pdb_search_destroy(search
);
2020 *rdata_len
= PTR_DIFF(p
,*rdata
);
2023 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
2027 SSVAL(*rparam
, 0, errflags
);
2028 SSVAL(*rparam
, 2, 0); /* converter word */
2029 SSVAL(*rparam
, 4, i
); /* is this right?? */
2030 SSVAL(*rparam
, 6, resume_context
+num_entries
); /* is this right?? */
2035 /*******************************************************************
2036 Get groups that a user is a member of.
2037 ******************************************************************/
2039 static BOOL
api_NetUserGetGroups(connection_struct
*conn
,uint16 vuid
,
2040 char *param
, int tpscnt
,
2041 char *data
, int tdscnt
,
2042 int mdrcnt
,int mprcnt
,
2043 char **rdata
,char **rparam
,
2044 int *rdata_len
,int *rparam_len
)
2046 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2047 char *str2
= skip_string(param
,tpscnt
,str1
);
2048 char *UserName
= skip_string(param
,tpscnt
,str2
);
2049 char *p
= skip_string(param
,tpscnt
,UserName
);
2050 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2051 const char *level_string
;
2053 struct samu
*sampw
= NULL
;
2061 enum lsa_SidType type
;
2062 TALLOC_CTX
*mem_ctx
;
2064 if (!str1
|| !str2
|| !UserName
|| !p
) {
2069 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
2074 /* check it's a supported varient */
2076 if ( strcmp(str1
,"zWrLeh") != 0 )
2081 level_string
= "B21";
2087 if (strcmp(level_string
,str2
) != 0)
2090 *rdata_len
= mdrcnt
+ 1024;
2091 *rdata
= SMB_REALLOC_LIMIT(*rdata
,*rdata_len
);
2095 SSVAL(*rparam
,0,NERR_Success
);
2096 SSVAL(*rparam
,2,0); /* converter word */
2100 mem_ctx
= talloc_new(NULL
);
2101 if (mem_ctx
== NULL
) {
2102 DEBUG(0, ("talloc_new failed\n"));
2106 if ( !(sampw
= samu_new(mem_ctx
)) ) {
2107 DEBUG(0, ("samu_new() failed!\n"));
2108 TALLOC_FREE(mem_ctx
);
2112 /* Lookup the user information; This should only be one of
2113 our accounts (not remote domains) */
2115 become_root(); /* ROOT BLOCK */
2117 if (!lookup_name(mem_ctx
, UserName
, LOOKUP_NAME_ALL
,
2118 NULL
, NULL
, &user_sid
, &type
)) {
2119 DEBUG(10, ("lookup_name(%s) failed\n", UserName
));
2123 if (type
!= SID_NAME_USER
) {
2124 DEBUG(10, ("%s is a %s, not a user\n", UserName
,
2125 sid_type_lookup(type
)));
2129 if ( !pdb_getsampwsid(sampw
, &user_sid
) ) {
2130 DEBUG(10, ("pdb_getsampwsid(%s) failed for user %s\n",
2131 sid_string_static(&user_sid
), UserName
));
2139 result
= pdb_enum_group_memberships(mem_ctx
, sampw
,
2140 &sids
, &gids
, &num_groups
);
2142 if (!NT_STATUS_IS_OK(result
)) {
2143 DEBUG(10, ("pdb_enum_group_memberships failed for %s\n",
2148 for (i
=0; i
<num_groups
; i
++) {
2150 const char *grp_name
;
2152 if ( lookup_sid(mem_ctx
, &sids
[i
], NULL
, &grp_name
, NULL
) ) {
2153 pstrcpy(p
, grp_name
);
2159 *rdata_len
= PTR_DIFF(p
,*rdata
);
2161 SSVAL(*rparam
,4,count
); /* is this right?? */
2162 SSVAL(*rparam
,6,count
); /* is this right?? */
2167 unbecome_root(); /* END ROOT BLOCK */
2169 TALLOC_FREE(mem_ctx
);
2174 /*******************************************************************
2176 ******************************************************************/
2178 static BOOL
api_RNetUserEnum(connection_struct
*conn
, uint16 vuid
,
2179 char *param
, int tpscnt
,
2180 char *data
, int tdscnt
,
2181 int mdrcnt
,int mprcnt
,
2182 char **rdata
,char **rparam
,
2183 int *rdata_len
,int *rparam_len
)
2188 int i
, resume_context
, cli_buf_size
;
2189 struct pdb_search
*search
;
2190 struct samr_displayentry
*users
;
2192 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2193 char *str2
= skip_string(param
,tpscnt
,str1
);
2194 char *p
= skip_string(param
,tpscnt
,str2
);
2196 if (!str1
|| !str2
|| !p
) {
2200 if (strcmp(str1
,"WrLeh") != 0)
2203 * W-> resume context (number of users to skip)
2204 * r -> return parameter pointer to receive buffer
2205 * L -> length of receive buffer
2206 * e -> return parameter number of entries
2207 * h -> return parameter total number of users
2210 resume_context
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2211 cli_buf_size
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
2212 DEBUG(10,("api_RNetUserEnum:resume context: %d, client buffer size: %d\n",
2213 resume_context
, cli_buf_size
));
2216 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
2221 /* check it's a supported varient */
2222 if (strcmp("B21",str2
) != 0)
2225 *rdata_len
= cli_buf_size
;
2226 *rdata
= SMB_REALLOC_LIMIT(*rdata
,*rdata_len
);
2234 search
= pdb_search_users(ACB_NORMAL
);
2236 if (search
== NULL
) {
2237 DEBUG(0, ("api_RNetUserEnum:unable to open sam database.\n"));
2242 num_users
= pdb_search_entries(search
, resume_context
, 0xffffffff,
2246 errflags
=NERR_Success
;
2248 for (i
=0; i
<num_users
; i
++) {
2249 const char *name
= users
[i
].account_name
;
2251 if(((PTR_DIFF(p
,*rdata
)+21)<=*rdata_len
)&&(strlen(name
)<=21)) {
2253 DEBUG(10,("api_RNetUserEnum:adding entry %d username "
2254 "%s\n",count_sent
,p
));
2258 /* set overflow error */
2259 DEBUG(10,("api_RNetUserEnum:overflow on entry %d "
2260 "username %s\n",count_sent
,name
));
2266 pdb_search_destroy(search
);
2268 *rdata_len
= PTR_DIFF(p
,*rdata
);
2270 SSVAL(*rparam
,0,errflags
);
2271 SSVAL(*rparam
,2,0); /* converter word */
2272 SSVAL(*rparam
,4,count_sent
); /* is this right?? */
2273 SSVAL(*rparam
,6,num_users
); /* is this right?? */
2278 /****************************************************************************
2279 Get the time of day info.
2280 ****************************************************************************/
2282 static BOOL
api_NetRemoteTOD(connection_struct
*conn
,uint16 vuid
,
2283 char *param
, int tpscnt
,
2284 char *data
, int tdscnt
,
2285 int mdrcnt
,int mprcnt
,
2286 char **rdata
,char **rparam
,
2287 int *rdata_len
,int *rparam_len
)
2290 time_t unixdate
= time(NULL
);
2294 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
2300 *rdata
= SMB_REALLOC_LIMIT(*rdata
,*rdata_len
);
2305 SSVAL(*rparam
,0,NERR_Success
);
2306 SSVAL(*rparam
,2,0); /* converter word */
2310 srv_put_dos_date3(p
,0,unixdate
); /* this is the time that is looked at
2311 by NT in a "net time" operation,
2312 it seems to ignore the one below */
2314 /* the client expects to get localtime, not GMT, in this bit
2315 (I think, this needs testing) */
2316 t
= localtime(&unixdate
);
2321 SIVAL(p
,4,0); /* msecs ? */
2322 SCVAL(p
,8,t
->tm_hour
);
2323 SCVAL(p
,9,t
->tm_min
);
2324 SCVAL(p
,10,t
->tm_sec
);
2325 SCVAL(p
,11,0); /* hundredths of seconds */
2326 SSVALS(p
,12,get_time_zone(unixdate
)/60); /* timezone in minutes from GMT */
2327 SSVAL(p
,14,10000); /* timer interval in 0.0001 of sec */
2328 SCVAL(p
,16,t
->tm_mday
);
2329 SCVAL(p
,17,t
->tm_mon
+ 1);
2330 SSVAL(p
,18,1900+t
->tm_year
);
2331 SCVAL(p
,20,t
->tm_wday
);
2336 /****************************************************************************
2337 Set the user password.
2338 *****************************************************************************/
2340 static BOOL
api_SetUserPassword(connection_struct
*conn
,uint16 vuid
,
2341 char *param
, int tpscnt
,
2342 char *data
, int tdscnt
,
2343 int mdrcnt
,int mprcnt
,
2344 char **rdata
,char **rparam
,
2345 int *rdata_len
,int *rparam_len
)
2347 char *np
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2350 fstring pass1
,pass2
;
2352 /* Skip 2 strings. */
2353 p
= skip_string(param
,tpscnt
,np
);
2354 p
= skip_string(param
,tpscnt
,p
);
2360 /* Do we have a string ? */
2361 if (skip_string(param
,tpscnt
,p
) == NULL
) {
2364 pull_ascii_fstring(user
,p
);
2366 p
= skip_string(param
,tpscnt
,p
);
2371 memset(pass1
,'\0',sizeof(pass1
));
2372 memset(pass2
,'\0',sizeof(pass2
));
2374 * We use 31 here not 32 as we're checking
2375 * the last byte we want to access is safe.
2377 if (!is_offset_safe(param
,tpscnt
,p
,31)) {
2381 memcpy(pass2
,p
+16,16);
2384 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
2391 SSVAL(*rparam
,0,NERR_badpass
);
2392 SSVAL(*rparam
,2,0); /* converter word */
2394 DEBUG(3,("Set password for <%s>\n",user
));
2397 * Attempt to verify the old password against smbpasswd entries
2398 * Win98 clients send old and new password in plaintext for this call.
2402 auth_serversupplied_info
*server_info
= NULL
;
2403 DATA_BLOB password
= data_blob(pass1
, strlen(pass1
)+1);
2405 if (NT_STATUS_IS_OK(check_plaintext_password(user
,password
,&server_info
))) {
2408 if (NT_STATUS_IS_OK(change_oem_password(server_info
->sam_account
, pass1
, pass2
, False
, NULL
))) {
2409 SSVAL(*rparam
,0,NERR_Success
);
2413 TALLOC_FREE(server_info
);
2415 data_blob_clear_free(&password
);
2419 * If the plaintext change failed, attempt
2420 * the old encrypted method. NT will generate this
2421 * after trying the samr method. Note that this
2422 * method is done as a last resort as this
2423 * password change method loses the NT password hash
2424 * and cannot change the UNIX password as no plaintext
2428 if(SVAL(*rparam
,0) != NERR_Success
) {
2429 struct samu
*hnd
= NULL
;
2431 if (check_lanman_password(user
,(unsigned char *)pass1
,(unsigned char *)pass2
, &hnd
)) {
2433 if (change_lanman_password(hnd
,(uchar
*)pass2
)) {
2434 SSVAL(*rparam
,0,NERR_Success
);
2441 memset((char *)pass1
,'\0',sizeof(fstring
));
2442 memset((char *)pass2
,'\0',sizeof(fstring
));
2447 /****************************************************************************
2448 Set the user password (SamOEM version - gets plaintext).
2449 ****************************************************************************/
2451 static BOOL
api_SamOEMChangePassword(connection_struct
*conn
,uint16 vuid
,
2452 char *param
, int tpscnt
,
2453 char *data
, int tdscnt
,
2454 int mdrcnt
,int mprcnt
,
2455 char **rdata
,char **rparam
,
2456 int *rdata_len
,int *rparam_len
)
2459 char *p
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2461 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
2471 SSVAL(*rparam
,0,NERR_badpass
);
2474 * Check the parameter definition is correct.
2477 /* Do we have a string ? */
2478 if (skip_string(param
,tpscnt
,p
) == 0) {
2481 if(!strequal(p
, "zsT")) {
2482 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", p
));
2485 p
= skip_string(param
, tpscnt
, p
);
2490 /* Do we have a string ? */
2491 if (skip_string(param
,tpscnt
,p
) == 0) {
2494 if(!strequal(p
, "B516B16")) {
2495 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p
));
2498 p
= skip_string(param
,tpscnt
,p
);
2502 /* Do we have a string ? */
2503 if (skip_string(param
,tpscnt
,p
) == 0) {
2506 p
+= pull_ascii_fstring(user
,p
);
2508 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user
));
2511 * Pass the user through the NT -> unix user mapping
2515 (void)map_username(user
);
2517 if (NT_STATUS_IS_OK(pass_oem_change(user
, (uchar
*) data
, (uchar
*)&data
[516], NULL
, NULL
, NULL
))) {
2518 SSVAL(*rparam
,0,NERR_Success
);
2524 /****************************************************************************
2527 ****************************************************************************/
2529 static BOOL
api_RDosPrintJobDel(connection_struct
*conn
,uint16 vuid
,
2530 char *param
, int tpscnt
,
2531 char *data
, int tdscnt
,
2532 int mdrcnt
,int mprcnt
,
2533 char **rdata
,char **rparam
,
2534 int *rdata_len
,int *rparam_len
)
2536 int function
= get_safe_SVAL(param
,tpscnt
,param
,0,0);
2537 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2538 char *str2
= skip_string(param
,tpscnt
,str1
);
2539 char *p
= skip_string(param
,tpscnt
,str2
);
2544 WERROR werr
= WERR_OK
;
2546 if (!str1
|| !str2
|| !p
) {
2550 * We use 1 here not 2 as we're checking
2551 * the last byte we want to access is safe.
2553 if (!is_offset_safe(param
,tpscnt
,p
,1)) {
2556 if(!rap_to_pjobid(SVAL(p
,0), sharename
, &jobid
))
2559 /* check it's a supported varient */
2560 if (!(strcsequal(str1
,"W") && strcsequal(str2
,"")))
2564 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
2570 if (!print_job_exists(sharename
, jobid
)) {
2571 errcode
= NERR_JobNotFound
;
2575 snum
= lp_servicenumber( sharename
);
2577 errcode
= NERR_DestNotFound
;
2581 errcode
= NERR_notsupported
;
2584 case 81: /* delete */
2585 if (print_job_delete(¤t_user
, snum
, jobid
, &werr
))
2586 errcode
= NERR_Success
;
2588 case 82: /* pause */
2589 if (print_job_pause(¤t_user
, snum
, jobid
, &werr
))
2590 errcode
= NERR_Success
;
2592 case 83: /* resume */
2593 if (print_job_resume(¤t_user
, snum
, jobid
, &werr
))
2594 errcode
= NERR_Success
;
2598 if (!W_ERROR_IS_OK(werr
))
2599 errcode
= W_ERROR_V(werr
);
2602 SSVAL(*rparam
,0,errcode
);
2603 SSVAL(*rparam
,2,0); /* converter word */
2608 /****************************************************************************
2609 Purge a print queue - or pause or resume it.
2610 ****************************************************************************/
2612 static BOOL
api_WPrintQueueCtrl(connection_struct
*conn
,uint16 vuid
,
2613 char *param
, int tpscnt
,
2614 char *data
, int tdscnt
,
2615 int mdrcnt
,int mprcnt
,
2616 char **rdata
,char **rparam
,
2617 int *rdata_len
,int *rparam_len
)
2619 int function
= get_safe_SVAL(param
,tpscnt
,param
,0,0);
2620 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2621 char *str2
= skip_string(param
,tpscnt
,str1
);
2622 char *QueueName
= skip_string(param
,tpscnt
,str2
);
2623 int errcode
= NERR_notsupported
;
2625 WERROR werr
= WERR_OK
;
2627 if (!str1
|| !str2
|| !QueueName
) {
2631 /* check it's a supported varient */
2632 if (!(strcsequal(str1
,"z") && strcsequal(str2
,"")))
2636 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
2642 if (skip_string(param
,tpscnt
,QueueName
) == NULL
) {
2645 snum
= print_queue_snum(QueueName
);
2648 errcode
= NERR_JobNotFound
;
2653 case 74: /* Pause queue */
2654 if (print_queue_pause(¤t_user
, snum
, &werr
)) errcode
= NERR_Success
;
2656 case 75: /* Resume queue */
2657 if (print_queue_resume(¤t_user
, snum
, &werr
)) errcode
= NERR_Success
;
2659 case 103: /* Purge */
2660 if (print_queue_purge(¤t_user
, snum
, &werr
)) errcode
= NERR_Success
;
2664 if (!W_ERROR_IS_OK(werr
)) errcode
= W_ERROR_V(werr
);
2667 SSVAL(*rparam
,0,errcode
);
2668 SSVAL(*rparam
,2,0); /* converter word */
2673 /****************************************************************************
2674 set the property of a print job (undocumented?)
2675 ? function = 0xb -> set name of print job
2676 ? function = 0x6 -> move print job up/down
2677 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
2678 or <WWsTP> <WB21BB16B10zWWzDDz>
2679 ****************************************************************************/
2681 static int check_printjob_info(struct pack_desc
* desc
,
2682 int uLevel
, char* id
)
2684 desc
->subformat
= NULL
;
2686 case 0: desc
->format
= "W"; break;
2687 case 1: desc
->format
= "WB21BB16B10zWWzDDz"; break;
2688 case 2: desc
->format
= "WWzWWDDzz"; break;
2689 case 3: desc
->format
= "WWzWWDDzzzzzzzzzzlz"; break;
2690 case 4: desc
->format
= "WWzWWDDzzzzzDDDDDDD"; break;
2692 DEBUG(0,("check_printjob_info: invalid level %d\n",
2696 if (id
== NULL
|| strcmp(desc
->format
,id
) != 0) {
2697 DEBUG(0,("check_printjob_info: invalid format %s\n",
2698 id
? id
: "<NULL>" ));
2704 static BOOL
api_PrintJobInfo(connection_struct
*conn
, uint16 vuid
,
2705 char *param
, int tpscnt
,
2706 char *data
, int tdscnt
,
2707 int mdrcnt
,int mprcnt
,
2708 char **rdata
,char **rparam
,
2709 int *rdata_len
,int *rparam_len
)
2711 struct pack_desc desc
;
2712 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2713 char *str2
= skip_string(param
,tpscnt
,str1
);
2714 char *p
= skip_string(param
,tpscnt
,str2
);
2717 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,2,-1);
2718 int function
= get_safe_SVAL(param
,tpscnt
,p
,4,-1);
2721 if (!str1
|| !str2
|| !p
) {
2725 * We use 1 here not 2 as we're checking
2726 * the last byte we want to access is safe.
2728 if (!is_offset_safe(param
,tpscnt
,p
,1)) {
2731 if(!rap_to_pjobid(SVAL(p
,0), sharename
, &jobid
))
2734 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
2739 if (!share_defined(sharename
)) {
2740 DEBUG(0,("api_PrintJobInfo: sharen [%s] not defined\n",
2747 /* check it's a supported varient */
2748 if ((strcmp(str1
,"WWsTP")) ||
2749 (!check_printjob_info(&desc
,uLevel
,str2
)))
2752 if (!print_job_exists(sharename
, jobid
)) {
2753 errcode
=NERR_JobNotFound
;
2757 errcode
= NERR_notsupported
;
2761 /* change job place in the queue,
2762 data gives the new place */
2763 place
= SVAL(data
,0);
2764 if (print_job_set_place(sharename
, jobid
, place
)) {
2765 errcode
=NERR_Success
;
2770 /* change print job name, data gives the name */
2771 if (print_job_set_name(sharename
, jobid
, data
)) {
2772 errcode
=NERR_Success
;
2781 SSVALS(*rparam
,0,errcode
);
2782 SSVAL(*rparam
,2,0); /* converter word */
2788 /****************************************************************************
2789 Get info about the server.
2790 ****************************************************************************/
2792 static BOOL
api_RNetServerGetInfo(connection_struct
*conn
,uint16 vuid
,
2793 char *param
, int tpscnt
,
2794 char *data
, int tdscnt
,
2795 int mdrcnt
,int mprcnt
,
2796 char **rdata
,char **rparam
,
2797 int *rdata_len
,int *rparam_len
)
2799 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2800 char *str2
= skip_string(param
,tpscnt
,str1
);
2801 char *p
= skip_string(param
,tpscnt
,str2
);
2802 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2806 if (!str1
|| !str2
|| !p
) {
2810 DEBUG(4,("NetServerGetInfo level %d\n",uLevel
));
2812 /* check it's a supported varient */
2813 if (!prefix_ok(str1
,"WrLh")) {
2819 if (strcmp(str2
,"B16") != 0) {
2825 if (strcmp(str2
,"B16BBDz") != 0) {
2831 if (strcmp(str2
,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")!= 0) {
2837 if (strcmp(str2
,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz") != 0) {
2843 if (strcmp(str2
,"DN") != 0) {
2849 if (strcmp(str2
,"B16BBDzWWzzz") != 0) {
2858 *rdata_len
= mdrcnt
;
2859 *rdata
= SMB_REALLOC_LIMIT(*rdata
,*rdata_len
);
2865 p2
= p
+ struct_len
;
2867 srvstr_push(NULL
, p
,global_myname(),16,
2868 STR_ASCII
|STR_UPPER
|STR_TERMINATE
);
2872 struct srv_info_struct
*servers
=NULL
;
2875 uint32 servertype
= lp_default_server_announce();
2877 push_ascii(comment
,lp_serverstring(), MAX_SERVER_STRING_LENGTH
,STR_TERMINATE
);
2879 if ((count
=get_server_info(SV_TYPE_ALL
,&servers
,lp_workgroup()))>0) {
2880 for (i
=0;i
<count
;i
++) {
2881 if (strequal(servers
[i
].name
,global_myname())) {
2882 servertype
= servers
[i
].type
;
2883 push_ascii(comment
,servers
[i
].comment
,sizeof(pstring
),STR_TERMINATE
);
2890 SCVAL(p
,0,lp_major_announce_version());
2891 SCVAL(p
,1,lp_minor_announce_version());
2892 SIVAL(p
,2,servertype
);
2894 if (mdrcnt
== struct_len
) {
2897 SIVAL(p
,6,PTR_DIFF(p2
,*rdata
));
2898 standard_sub_advanced(lp_servicename(SNUM(conn
)), conn
->user
,
2899 conn
->connectpath
, conn
->gid
,
2900 get_current_username(),
2901 current_user_info
.domain
,
2902 comment
, sizeof(comment
));
2903 StrnCpy(p2
,comment
,MAX(mdrcnt
- struct_len
,0));
2904 p2
= skip_string(*rdata
,*rdata_len
,p2
);
2912 return False
; /* not yet implemented */
2915 *rdata_len
= PTR_DIFF(p2
,*rdata
);
2918 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
2922 SSVAL(*rparam
,0,NERR_Success
);
2923 SSVAL(*rparam
,2,0); /* converter word */
2924 SSVAL(*rparam
,4,*rdata_len
);
2929 /****************************************************************************
2930 Get info about the server.
2931 ****************************************************************************/
2933 static BOOL
api_NetWkstaGetInfo(connection_struct
*conn
,uint16 vuid
,
2934 char *param
, int tpscnt
,
2935 char *data
, int tdscnt
,
2936 int mdrcnt
,int mprcnt
,
2937 char **rdata
,char **rparam
,
2938 int *rdata_len
,int *rparam_len
)
2940 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2941 char *str2
= skip_string(param
,tpscnt
,str1
);
2942 char *p
= skip_string(param
,tpscnt
,str2
);
2944 int level
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2946 if (!str1
|| !str2
|| !p
) {
2950 DEBUG(4,("NetWkstaGetInfo level %d\n",level
));
2953 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
2958 /* check it's a supported varient */
2959 if (!(level
==10 && strcsequal(str1
,"WrLh") && strcsequal(str2
,"zzzBBzz"))) {
2963 *rdata_len
= mdrcnt
+ 1024;
2964 *rdata
= SMB_REALLOC_LIMIT(*rdata
,*rdata_len
);
2969 SSVAL(*rparam
,0,NERR_Success
);
2970 SSVAL(*rparam
,2,0); /* converter word */
2973 p2
= get_safe_ptr(*rdata
,*rdata_len
,p
,22);
2978 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* host name */
2979 pstrcpy(p2
,get_local_machine_name());
2981 p2
= skip_string(*rdata
,*rdata_len
,p2
);
2987 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
));
2988 pstrcpy(p2
,current_user_info
.smb_name
);
2989 p2
= skip_string(*rdata
,*rdata_len
,p2
);
2995 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* login domain */
2996 pstrcpy(p2
,lp_workgroup());
2998 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3004 SCVAL(p
,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
3005 SCVAL(p
,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
3008 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
));
3009 pstrcpy(p2
,lp_workgroup()); /* don't know. login domain?? */
3010 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3016 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* don't know */
3018 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3024 *rdata_len
= PTR_DIFF(p2
,*rdata
);
3026 SSVAL(*rparam
,4,*rdata_len
);
3031 /****************************************************************************
3032 get info about a user
3034 struct user_info_11 {
3035 char usri11_name[21]; 0-20
3037 char *usri11_comment; 22-25
3038 char *usri11_usr_comment; 26-29
3039 unsigned short usri11_priv; 30-31
3040 unsigned long usri11_auth_flags; 32-35
3041 long usri11_password_age; 36-39
3042 char *usri11_homedir; 40-43
3043 char *usri11_parms; 44-47
3044 long usri11_last_logon; 48-51
3045 long usri11_last_logoff; 52-55
3046 unsigned short usri11_bad_pw_count; 56-57
3047 unsigned short usri11_num_logons; 58-59
3048 char *usri11_logon_server; 60-63
3049 unsigned short usri11_country_code; 64-65
3050 char *usri11_workstations; 66-69
3051 unsigned long usri11_max_storage; 70-73
3052 unsigned short usri11_units_per_week; 74-75
3053 unsigned char *usri11_logon_hours; 76-79
3054 unsigned short usri11_code_page; 80-81
3059 usri11_name specifies the user name for which information is retireved
3061 usri11_pad aligns the next data structure element to a word boundary
3063 usri11_comment is a null terminated ASCII comment
3065 usri11_user_comment is a null terminated ASCII comment about the user
3067 usri11_priv specifies the level of the privilege assigned to the user.
3068 The possible values are:
3070 Name Value Description
3071 USER_PRIV_GUEST 0 Guest privilege
3072 USER_PRIV_USER 1 User privilege
3073 USER_PRV_ADMIN 2 Administrator privilege
3075 usri11_auth_flags specifies the account operator privileges. The
3076 possible values are:
3078 Name Value Description
3079 AF_OP_PRINT 0 Print operator
3082 Leach, Naik [Page 28]
3086 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
3089 AF_OP_COMM 1 Communications operator
3090 AF_OP_SERVER 2 Server operator
3091 AF_OP_ACCOUNTS 3 Accounts operator
3094 usri11_password_age specifies how many seconds have elapsed since the
3095 password was last changed.
3097 usri11_home_dir points to a null terminated ASCII string that contains
3098 the path name of the user's home directory.
3100 usri11_parms points to a null terminated ASCII string that is set
3101 aside for use by applications.
3103 usri11_last_logon specifies the time when the user last logged on.
3104 This value is stored as the number of seconds elapsed since
3105 00:00:00, January 1, 1970.
3107 usri11_last_logoff specifies the time when the user last logged off.
3108 This value is stored as the number of seconds elapsed since
3109 00:00:00, January 1, 1970. A value of 0 means the last logoff
3112 usri11_bad_pw_count specifies the number of incorrect passwords
3113 entered since the last successful logon.
3115 usri11_log1_num_logons specifies the number of times this user has
3116 logged on. A value of -1 means the number of logons is unknown.
3118 usri11_logon_server points to a null terminated ASCII string that
3119 contains the name of the server to which logon requests are sent.
3120 A null string indicates logon requests should be sent to the
3123 usri11_country_code specifies the country code for the user's language
3126 usri11_workstations points to a null terminated ASCII string that
3127 contains the names of workstations the user may log on from.
3128 There may be up to 8 workstations, with the names separated by
3129 commas. A null strings indicates there are no restrictions.
3131 usri11_max_storage specifies the maximum amount of disk space the user
3132 can occupy. A value of 0xffffffff indicates there are no
3135 usri11_units_per_week specifies the equal number of time units into
3136 which a week is divided. This value must be equal to 168.
3138 usri11_logon_hours points to a 21 byte (168 bits) string that
3139 specifies the time during which the user can log on. Each bit
3140 represents one unique hour in a week. The first bit (bit 0, word
3141 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
3145 Leach, Naik [Page 29]
3149 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
3152 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
3153 are no restrictions.
3155 usri11_code_page specifies the code page for the user's language of
3158 All of the pointers in this data structure need to be treated
3159 specially. The pointer is a 32 bit pointer. The higher 16 bits need
3160 to be ignored. The converter word returned in the parameters section
3161 needs to be subtracted from the lower 16 bits to calculate an offset
3162 into the return buffer where this ASCII string resides.
3164 There is no auxiliary data in the response.
3166 ****************************************************************************/
3168 #define usri11_name 0
3169 #define usri11_pad 21
3170 #define usri11_comment 22
3171 #define usri11_usr_comment 26
3172 #define usri11_full_name 30
3173 #define usri11_priv 34
3174 #define usri11_auth_flags 36
3175 #define usri11_password_age 40
3176 #define usri11_homedir 44
3177 #define usri11_parms 48
3178 #define usri11_last_logon 52
3179 #define usri11_last_logoff 56
3180 #define usri11_bad_pw_count 60
3181 #define usri11_num_logons 62
3182 #define usri11_logon_server 64
3183 #define usri11_country_code 68
3184 #define usri11_workstations 70
3185 #define usri11_max_storage 74
3186 #define usri11_units_per_week 78
3187 #define usri11_logon_hours 80
3188 #define usri11_code_page 84
3189 #define usri11_end 86
3191 #define USER_PRIV_GUEST 0
3192 #define USER_PRIV_USER 1
3193 #define USER_PRIV_ADMIN 2
3195 #define AF_OP_PRINT 0
3196 #define AF_OP_COMM 1
3197 #define AF_OP_SERVER 2
3198 #define AF_OP_ACCOUNTS 3
3201 static BOOL
api_RNetUserGetInfo(connection_struct
*conn
, uint16 vuid
,
3202 char *param
, int tpscnt
,
3203 char *data
, int tdscnt
,
3204 int mdrcnt
,int mprcnt
,
3205 char **rdata
,char **rparam
,
3206 int *rdata_len
,int *rparam_len
)
3208 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3209 char *str2
= skip_string(param
,tpscnt
,str1
);
3210 char *UserName
= skip_string(param
,tpscnt
,str2
);
3211 char *p
= skip_string(param
,tpscnt
,UserName
);
3212 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3214 const char *level_string
;
3216 /* get NIS home of a previously validated user - simeon */
3217 /* With share level security vuid will always be zero.
3218 Don't depend on vuser being non-null !!. JRA */
3219 user_struct
*vuser
= get_valid_user_struct(vuid
);
3221 DEBUG(3,(" Username of UID %d is %s\n", (int)vuser
->uid
,
3222 vuser
->user
.unix_name
));
3225 if (!str1
|| !str2
|| !UserName
|| !p
) {
3230 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
3235 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel
));
3237 /* check it's a supported variant */
3238 if (strcmp(str1
,"zWrLh") != 0) {
3242 case 0: level_string
= "B21"; break;
3243 case 1: level_string
= "B21BB16DWzzWz"; break;
3244 case 2: level_string
= "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
3245 case 10: level_string
= "B21Bzzz"; break;
3246 case 11: level_string
= "B21BzzzWDDzzDDWWzWzDWb21W"; break;
3247 default: return False
;
3250 if (strcmp(level_string
,str2
) != 0) {
3254 *rdata_len
= mdrcnt
+ 1024;
3255 *rdata
= SMB_REALLOC_LIMIT(*rdata
,*rdata_len
);
3260 SSVAL(*rparam
,0,NERR_Success
);
3261 SSVAL(*rparam
,2,0); /* converter word */
3264 p2
= get_safe_ptr(*rdata
,*rdata_len
,p
,usri11_end
);
3270 fstrcpy(p
+usri11_name
,UserName
); /* 21 bytes - user name */
3273 SCVAL(p
,usri11_pad
,0); /* padding - 1 byte */
3278 SIVAL(p
,usri11_comment
,PTR_DIFF(p2
,p
)); /* comment */
3279 pstrcpy(p2
,"Comment");
3280 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3285 SIVAL(p
,usri11_usr_comment
,PTR_DIFF(p2
,p
)); /* user_comment */
3286 pstrcpy(p2
,"UserComment");
3287 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3292 /* EEK! the cifsrap.txt doesn't have this in!!!! */
3293 SIVAL(p
,usri11_full_name
,PTR_DIFF(p2
,p
)); /* full name */
3294 pstrcpy(p2
,((vuser
!= NULL
) ? vuser
->user
.full_name
: UserName
));
3295 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3302 /* modelled after NTAS 3.51 reply */
3303 SSVAL(p
,usri11_priv
,conn
->admin_user
?USER_PRIV_ADMIN
:USER_PRIV_USER
);
3304 SIVAL(p
,usri11_auth_flags
,AF_OP_PRINT
); /* auth flags */
3305 SIVALS(p
,usri11_password_age
,-1); /* password age */
3306 SIVAL(p
,usri11_homedir
,PTR_DIFF(p2
,p
)); /* home dir */
3307 pstrcpy(p2
, vuser
&& vuser
->homedir
? vuser
->homedir
: "");
3308 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3312 SIVAL(p
,usri11_parms
,PTR_DIFF(p2
,p
)); /* parms */
3314 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3318 SIVAL(p
,usri11_last_logon
,0); /* last logon */
3319 SIVAL(p
,usri11_last_logoff
,0); /* last logoff */
3320 SSVALS(p
,usri11_bad_pw_count
,-1); /* bad pw counts */
3321 SSVALS(p
,usri11_num_logons
,-1); /* num logons */
3322 SIVAL(p
,usri11_logon_server
,PTR_DIFF(p2
,p
)); /* logon server */
3323 pstrcpy(p2
,"\\\\*");
3324 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3328 SSVAL(p
,usri11_country_code
,0); /* country code */
3330 SIVAL(p
,usri11_workstations
,PTR_DIFF(p2
,p
)); /* workstations */
3332 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3337 SIVALS(p
,usri11_max_storage
,-1); /* max storage */
3338 SSVAL(p
,usri11_units_per_week
,168); /* units per week */
3339 SIVAL(p
,usri11_logon_hours
,PTR_DIFF(p2
,p
)); /* logon hours */
3341 /* a simple way to get logon hours at all times. */
3343 SCVAL(p2
,21,0); /* fix zero termination */
3344 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3349 SSVAL(p
,usri11_code_page
,0); /* code page */
3352 if (uLevel
== 1 || uLevel
== 2) {
3353 memset(p
+22,' ',16); /* password */
3354 SIVALS(p
,38,-1); /* password age */
3356 conn
->admin_user
?USER_PRIV_ADMIN
:USER_PRIV_USER
);
3357 SIVAL(p
,44,PTR_DIFF(p2
,*rdata
)); /* home dir */
3358 pstrcpy(p2
, vuser
&& vuser
->homedir
? vuser
->homedir
: "");
3359 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3363 SIVAL(p
,48,PTR_DIFF(p2
,*rdata
)); /* comment */
3365 SSVAL(p
,52,0); /* flags */
3366 SIVAL(p
,54,PTR_DIFF(p2
,*rdata
)); /* script_path */
3367 pstrcpy(p2
,vuser
&& vuser
->logon_script
? vuser
->logon_script
: "");
3368 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3373 SIVAL(p
,60,0); /* auth_flags */
3374 SIVAL(p
,64,PTR_DIFF(p2
,*rdata
)); /* full_name */
3375 pstrcpy(p2
,((vuser
!= NULL
) ? vuser
->user
.full_name
: UserName
));
3376 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3380 SIVAL(p
,68,0); /* urs_comment */
3381 SIVAL(p
,72,PTR_DIFF(p2
,*rdata
)); /* parms */
3383 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3387 SIVAL(p
,76,0); /* workstations */
3388 SIVAL(p
,80,0); /* last_logon */
3389 SIVAL(p
,84,0); /* last_logoff */
3390 SIVALS(p
,88,-1); /* acct_expires */
3391 SIVALS(p
,92,-1); /* max_storage */
3392 SSVAL(p
,96,168); /* units_per_week */
3393 SIVAL(p
,98,PTR_DIFF(p2
,*rdata
)); /* logon_hours */
3396 SSVALS(p
,102,-1); /* bad_pw_count */
3397 SSVALS(p
,104,-1); /* num_logons */
3398 SIVAL(p
,106,PTR_DIFF(p2
,*rdata
)); /* logon_server */
3401 pstrcpy(tmp
, "\\\\%L");
3402 standard_sub_basic("", "", tmp
, sizeof(tmp
));
3405 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3409 SSVAL(p
,110,49); /* country_code */
3410 SSVAL(p
,112,860); /* code page */
3414 *rdata_len
= PTR_DIFF(p2
,*rdata
);
3416 SSVAL(*rparam
,4,*rdata_len
); /* is this right?? */
3421 static BOOL
api_WWkstaUserLogon(connection_struct
*conn
,uint16 vuid
,
3422 char *param
, int tpscnt
,
3423 char *data
, int tdscnt
,
3424 int mdrcnt
,int mprcnt
,
3425 char **rdata
,char **rparam
,
3426 int *rdata_len
,int *rparam_len
)
3428 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3429 char *str2
= skip_string(param
,tpscnt
,str1
);
3430 char *p
= skip_string(param
,tpscnt
,str2
);
3432 struct pack_desc desc
;
3434 /* With share level security vuid will always be zero.
3435 Don't depend on vuser being non-null !!. JRA */
3436 user_struct
*vuser
= get_valid_user_struct(vuid
);
3438 if (!str1
|| !str2
|| !p
) {
3443 DEBUG(3,(" Username of UID %d is %s\n", (int)vuser
->uid
,
3444 vuser
->user
.unix_name
));
3447 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3448 name
= get_safe_str_ptr(param
,tpscnt
,p
,2);
3453 memset((char *)&desc
,'\0',sizeof(desc
));
3455 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel
,name
));
3457 /* check it's a supported varient */
3458 if (strcmp(str1
,"OOWb54WrLh") != 0) {
3461 if (uLevel
!= 1 || strcmp(str2
,"WB21BWDWWDDDDDDDzzzD") != 0) {
3465 *rdata
= SMB_REALLOC_LIMIT(*rdata
,mdrcnt
);
3472 desc
.buflen
= mdrcnt
;
3473 desc
.subformat
= NULL
;
3476 if (init_package(&desc
,1,0)) {
3477 PACKI(&desc
,"W",0); /* code */
3478 PACKS(&desc
,"B21",name
); /* eff. name */
3479 PACKS(&desc
,"B",""); /* pad */
3480 PACKI(&desc
,"W", conn
->admin_user
?USER_PRIV_ADMIN
:USER_PRIV_USER
);
3481 PACKI(&desc
,"D",0); /* auth flags XXX */
3482 PACKI(&desc
,"W",0); /* num logons */
3483 PACKI(&desc
,"W",0); /* bad pw count */
3484 PACKI(&desc
,"D",0); /* last logon */
3485 PACKI(&desc
,"D",-1); /* last logoff */
3486 PACKI(&desc
,"D",-1); /* logoff time */
3487 PACKI(&desc
,"D",-1); /* kickoff time */
3488 PACKI(&desc
,"D",0); /* password age */
3489 PACKI(&desc
,"D",0); /* password can change */
3490 PACKI(&desc
,"D",-1); /* password must change */
3494 fstrcpy(mypath
,"\\\\");
3495 fstrcat(mypath
,get_local_machine_name());
3497 PACKS(&desc
,"z",mypath
); /* computer */
3500 PACKS(&desc
,"z",lp_workgroup());/* domain */
3501 PACKS(&desc
,"z", vuser
&& vuser
->logon_script
? vuser
->logon_script
:""); /* script path */
3502 PACKI(&desc
,"D",0x00000000); /* reserved */
3505 *rdata_len
= desc
.usedlen
;
3507 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
3511 SSVALS(*rparam
,0,desc
.errcode
);
3513 SSVAL(*rparam
,4,desc
.neededlen
);
3515 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc
.errcode
));
3520 /****************************************************************************
3521 api_WAccessGetUserPerms
3522 ****************************************************************************/
3524 static BOOL
api_WAccessGetUserPerms(connection_struct
*conn
,uint16 vuid
,
3525 char *param
, int tpscnt
,
3526 char *data
, int tdscnt
,
3527 int mdrcnt
,int mprcnt
,
3528 char **rdata
,char **rparam
,
3529 int *rdata_len
,int *rparam_len
)
3531 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3532 char *str2
= skip_string(param
,tpscnt
,str1
);
3533 char *user
= skip_string(param
,tpscnt
,str2
);
3534 char *resource
= skip_string(param
,tpscnt
,user
);
3536 if (!str1
|| !str2
|| !user
|| !resource
) {
3540 if (skip_string(param
,tpscnt
,resource
) == NULL
) {
3543 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user
,resource
));
3545 /* check it's a supported varient */
3546 if (strcmp(str1
,"zzh") != 0) {
3549 if (strcmp(str2
,"") != 0) {
3554 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
3558 SSVALS(*rparam
,0,0); /* errorcode */
3559 SSVAL(*rparam
,2,0); /* converter word */
3560 SSVAL(*rparam
,4,0x7f); /* permission flags */
3565 /****************************************************************************
3566 api_WPrintJobEnumerate
3567 ****************************************************************************/
3569 static BOOL
api_WPrintJobGetInfo(connection_struct
*conn
, uint16 vuid
,
3570 char *param
, int tpscnt
,
3571 char *data
, int tdscnt
,
3572 int mdrcnt
,int mprcnt
,
3573 char **rdata
,char **rparam
,
3574 int *rdata_len
,int *rparam_len
)
3576 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3577 char *str2
= skip_string(param
,tpscnt
,str1
);
3578 char *p
= skip_string(param
,tpscnt
,str2
);
3585 struct pack_desc desc
;
3586 print_queue_struct
*queue
=NULL
;
3587 print_status_struct status
;
3590 if (!str1
|| !str2
|| !p
) {
3594 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,2,-1);
3596 memset((char *)&desc
,'\0',sizeof(desc
));
3597 memset((char *)&status
,'\0',sizeof(status
));
3599 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel
,SVAL(p
,0)));
3601 /* check it's a supported varient */
3602 if (strcmp(str1
,"WWrLh") != 0) {
3605 if (!check_printjob_info(&desc
,uLevel
,str2
)) {
3609 if(!rap_to_pjobid(SVAL(p
,0), sharename
, &jobid
)) {
3613 snum
= lp_servicenumber( sharename
);
3614 if (snum
< 0 || !VALID_SNUM(snum
)) {
3618 count
= print_queue_status(snum
,&queue
,&status
);
3619 for (i
= 0; i
< count
; i
++) {
3620 if (queue
[i
].job
== jobid
) {
3626 *rdata
= SMB_REALLOC_LIMIT(*rdata
,mdrcnt
);
3631 desc
.buflen
= mdrcnt
;
3634 * Don't return data but need to get correct length
3635 * init_package will return wrong size if buflen=0
3637 desc
.buflen
= getlen(desc
.format
);
3638 desc
.base
= tmpdata
= (char *)SMB_MALLOC( desc
.buflen
);
3641 if (init_package(&desc
,1,0)) {
3643 fill_printjob_info(conn
,snum
,uLevel
,&desc
,&queue
[i
],i
);
3644 *rdata_len
= desc
.usedlen
;
3646 desc
.errcode
= NERR_JobNotFound
;
3652 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
3656 SSVALS(*rparam
,0,desc
.errcode
);
3658 SSVAL(*rparam
,4,desc
.neededlen
);
3663 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc
.errcode
));
3668 static BOOL
api_WPrintJobEnumerate(connection_struct
*conn
, uint16 vuid
,
3669 char *param
, int tpscnt
,
3670 char *data
, int tdscnt
,
3671 int mdrcnt
,int mprcnt
,
3672 char **rdata
,char **rparam
,
3673 int *rdata_len
,int *rparam_len
)
3675 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3676 char *str2
= skip_string(param
,tpscnt
,str1
);
3677 char *p
= skip_string(param
,tpscnt
,str2
);
3683 struct pack_desc desc
;
3684 print_queue_struct
*queue
=NULL
;
3685 print_status_struct status
;
3687 if (!str1
|| !str2
|| !p
) {
3691 memset((char *)&desc
,'\0',sizeof(desc
));
3692 memset((char *)&status
,'\0',sizeof(status
));
3694 p
= skip_string(param
,tpscnt
,p
);
3698 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3700 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel
,name
));
3702 /* check it's a supported variant */
3703 if (strcmp(str1
,"zWrLeh") != 0) {
3708 return False
; /* defined only for uLevel 0,1,2 */
3711 if (!check_printjob_info(&desc
,uLevel
,str2
)) {
3715 snum
= find_service(name
);
3716 if ( !(lp_snum_ok(snum
) && lp_print_ok(snum
)) ) {
3720 count
= print_queue_status(snum
,&queue
,&status
);
3722 *rdata
= SMB_REALLOC_LIMIT(*rdata
,mdrcnt
);
3728 desc
.buflen
= mdrcnt
;
3730 if (init_package(&desc
,count
,0)) {
3732 for (i
= 0; i
< count
; i
++) {
3733 fill_printjob_info(conn
,snum
,uLevel
,&desc
,&queue
[i
],i
);
3734 if (desc
.errcode
== NERR_Success
) {
3740 *rdata_len
= desc
.usedlen
;
3743 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
3747 SSVALS(*rparam
,0,desc
.errcode
);
3749 SSVAL(*rparam
,4,succnt
);
3750 SSVAL(*rparam
,6,count
);
3754 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc
.errcode
));
3759 static int check_printdest_info(struct pack_desc
* desc
,
3760 int uLevel
, char* id
)
3762 desc
->subformat
= NULL
;
3765 desc
->format
= "B9";
3768 desc
->format
= "B9B21WWzW";
3774 desc
->format
= "zzzWWzzzWW";
3777 DEBUG(0,("check_printdest_info: invalid level %d\n",
3781 if (id
== NULL
|| strcmp(desc
->format
,id
) != 0) {
3782 DEBUG(0,("check_printdest_info: invalid string %s\n",
3783 id
? id
: "<NULL>" ));
3789 static void fill_printdest_info(connection_struct
*conn
, int snum
, int uLevel
,
3790 struct pack_desc
* desc
)
3794 strncpy(buf
,SERVICE(snum
),sizeof(buf
)-1);
3795 buf
[sizeof(buf
)-1] = 0;
3799 PACKS(desc
,"B9",buf
); /* szName */
3801 PACKS(desc
,"B21",""); /* szUserName */
3802 PACKI(desc
,"W",0); /* uJobId */
3803 PACKI(desc
,"W",0); /* fsStatus */
3804 PACKS(desc
,"z",""); /* pszStatus */
3805 PACKI(desc
,"W",0); /* time */
3809 if (uLevel
== 2 || uLevel
== 3) {
3810 PACKS(desc
,"z",buf
); /* pszPrinterName */
3812 PACKS(desc
,"z",""); /* pszUserName */
3813 PACKS(desc
,"z",""); /* pszLogAddr */
3814 PACKI(desc
,"W",0); /* uJobId */
3815 PACKI(desc
,"W",0); /* fsStatus */
3816 PACKS(desc
,"z",""); /* pszStatus */
3817 PACKS(desc
,"z",""); /* pszComment */
3818 PACKS(desc
,"z","NULL"); /* pszDrivers */
3819 PACKI(desc
,"W",0); /* time */
3820 PACKI(desc
,"W",0); /* pad1 */
3825 static BOOL
api_WPrintDestGetInfo(connection_struct
*conn
, uint16 vuid
,
3826 char *param
, int tpscnt
,
3827 char *data
, int tdscnt
,
3828 int mdrcnt
,int mprcnt
,
3829 char **rdata
,char **rparam
,
3830 int *rdata_len
,int *rparam_len
)
3832 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3833 char *str2
= skip_string(param
,tpscnt
,str1
);
3834 char *p
= skip_string(param
,tpscnt
,str2
);
3835 char* PrinterName
= p
;
3837 struct pack_desc desc
;
3841 if (!str1
|| !str2
|| !p
) {
3845 memset((char *)&desc
,'\0',sizeof(desc
));
3847 p
= skip_string(param
,tpscnt
,p
);
3851 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3853 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel
,PrinterName
));
3855 /* check it's a supported varient */
3856 if (strcmp(str1
,"zWrLh") != 0) {
3859 if (!check_printdest_info(&desc
,uLevel
,str2
)) {
3863 snum
= find_service(PrinterName
);
3864 if ( !(lp_snum_ok(snum
) && lp_print_ok(snum
)) ) {
3866 desc
.errcode
= NERR_DestNotFound
;
3870 *rdata
= SMB_REALLOC_LIMIT(*rdata
,mdrcnt
);
3875 desc
.buflen
= mdrcnt
;
3878 * Don't return data but need to get correct length
3879 * init_package will return wrong size if buflen=0
3881 desc
.buflen
= getlen(desc
.format
);
3882 desc
.base
= tmpdata
= (char *)SMB_MALLOC( desc
.buflen
);
3884 if (init_package(&desc
,1,0)) {
3885 fill_printdest_info(conn
,snum
,uLevel
,&desc
);
3887 *rdata_len
= desc
.usedlen
;
3891 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
3895 SSVALS(*rparam
,0,desc
.errcode
);
3897 SSVAL(*rparam
,4,desc
.neededlen
);
3899 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc
.errcode
));
3905 static BOOL
api_WPrintDestEnum(connection_struct
*conn
, uint16 vuid
,
3906 char *param
, int tpscnt
,
3907 char *data
, int tdscnt
,
3908 int mdrcnt
,int mprcnt
,
3909 char **rdata
,char **rparam
,
3910 int *rdata_len
,int *rparam_len
)
3912 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3913 char *str2
= skip_string(param
,tpscnt
,str1
);
3914 char *p
= skip_string(param
,tpscnt
,str2
);
3918 struct pack_desc desc
;
3919 int services
= lp_numservices();
3921 if (!str1
|| !str2
|| !p
) {
3925 memset((char *)&desc
,'\0',sizeof(desc
));
3927 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3929 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel
));
3931 /* check it's a supported varient */
3932 if (strcmp(str1
,"WrLeh") != 0) {
3935 if (!check_printdest_info(&desc
,uLevel
,str2
)) {
3940 for (i
= 0; i
< services
; i
++) {
3941 if (lp_snum_ok(i
) && lp_print_ok(i
) && lp_browseable(i
)) {
3947 *rdata
= SMB_REALLOC_LIMIT(*rdata
,mdrcnt
);
3954 desc
.buflen
= mdrcnt
;
3955 if (init_package(&desc
,queuecnt
,0)) {
3958 for (i
= 0; i
< services
; i
++) {
3959 if (lp_snum_ok(i
) && lp_print_ok(i
) && lp_browseable(i
)) {
3960 fill_printdest_info(conn
,i
,uLevel
,&desc
);
3962 if (desc
.errcode
== NERR_Success
) {
3969 *rdata_len
= desc
.usedlen
;
3972 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
3976 SSVALS(*rparam
,0,desc
.errcode
);
3978 SSVAL(*rparam
,4,succnt
);
3979 SSVAL(*rparam
,6,queuecnt
);
3981 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc
.errcode
));
3986 static BOOL
api_WPrintDriverEnum(connection_struct
*conn
, uint16 vuid
,
3987 char *param
, int tpscnt
,
3988 char *data
, int tdscnt
,
3989 int mdrcnt
,int mprcnt
,
3990 char **rdata
,char **rparam
,
3991 int *rdata_len
,int *rparam_len
)
3993 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3994 char *str2
= skip_string(param
,tpscnt
,str1
);
3995 char *p
= skip_string(param
,tpscnt
,str2
);
3998 struct pack_desc desc
;
4000 if (!str1
|| !str2
|| !p
) {
4004 memset((char *)&desc
,'\0',sizeof(desc
));
4006 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4008 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel
));
4010 /* check it's a supported varient */
4011 if (strcmp(str1
,"WrLeh") != 0) {
4014 if (uLevel
!= 0 || strcmp(str2
,"B41") != 0) {
4019 *rdata
= SMB_REALLOC_LIMIT(*rdata
,mdrcnt
);
4025 desc
.buflen
= mdrcnt
;
4026 if (init_package(&desc
,1,0)) {
4027 PACKS(&desc
,"B41","NULL");
4030 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
4032 *rdata_len
= desc
.usedlen
;
4035 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
4039 SSVALS(*rparam
,0,desc
.errcode
);
4041 SSVAL(*rparam
,4,succnt
);
4044 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc
.errcode
));
4049 static BOOL
api_WPrintQProcEnum(connection_struct
*conn
, uint16 vuid
,
4050 char *param
, int tpscnt
,
4051 char *data
, int tdscnt
,
4052 int mdrcnt
,int mprcnt
,
4053 char **rdata
,char **rparam
,
4054 int *rdata_len
,int *rparam_len
)
4056 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4057 char *str2
= skip_string(param
,tpscnt
,str1
);
4058 char *p
= skip_string(param
,tpscnt
,str2
);
4061 struct pack_desc desc
;
4063 if (!str1
|| !str2
|| !p
) {
4066 memset((char *)&desc
,'\0',sizeof(desc
));
4068 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4070 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel
));
4072 /* check it's a supported varient */
4073 if (strcmp(str1
,"WrLeh") != 0) {
4076 if (uLevel
!= 0 || strcmp(str2
,"B13") != 0) {
4081 *rdata
= SMB_REALLOC_LIMIT(*rdata
,mdrcnt
);
4087 desc
.buflen
= mdrcnt
;
4089 if (init_package(&desc
,1,0)) {
4090 PACKS(&desc
,"B13","lpd");
4093 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
4095 *rdata_len
= desc
.usedlen
;
4098 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
4102 SSVALS(*rparam
,0,desc
.errcode
);
4104 SSVAL(*rparam
,4,succnt
);
4107 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc
.errcode
));
4112 static BOOL
api_WPrintPortEnum(connection_struct
*conn
, uint16 vuid
,
4113 char *param
, int tpscnt
,
4114 char *data
, int tdscnt
,
4115 int mdrcnt
,int mprcnt
,
4116 char **rdata
,char **rparam
,
4117 int *rdata_len
,int *rparam_len
)
4119 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4120 char *str2
= skip_string(param
,tpscnt
,str1
);
4121 char *p
= skip_string(param
,tpscnt
,str2
);
4124 struct pack_desc desc
;
4126 if (!str1
|| !str2
|| !p
) {
4130 memset((char *)&desc
,'\0',sizeof(desc
));
4132 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4134 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel
));
4136 /* check it's a supported varient */
4137 if (strcmp(str1
,"WrLeh") != 0) {
4140 if (uLevel
!= 0 || strcmp(str2
,"B9") != 0) {
4145 *rdata
= SMB_REALLOC_LIMIT(*rdata
,mdrcnt
);
4150 memset((char *)&desc
,'\0',sizeof(desc
));
4152 desc
.buflen
= mdrcnt
;
4154 if (init_package(&desc
,1,0)) {
4155 PACKS(&desc
,"B13","lp0");
4158 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
4160 *rdata_len
= desc
.usedlen
;
4163 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
4167 SSVALS(*rparam
,0,desc
.errcode
);
4169 SSVAL(*rparam
,4,succnt
);
4172 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc
.errcode
));
4177 /****************************************************************************
4179 ****************************************************************************/
4181 static BOOL
api_RNetSessionEnum(connection_struct
*conn
, uint16 vuid
,
4182 char *param
, int tpscnt
,
4183 char *data
, int tdscnt
,
4184 int mdrcnt
,int mprcnt
,
4185 char **rdata
,char **rparam
,
4186 int *rdata_len
,int *rparam_len
)
4189 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4190 char *str2
= skip_string(param
,tpscnt
,str1
);
4191 char *p
= skip_string(param
,tpscnt
,str2
);
4193 struct pack_desc desc
;
4194 struct sessionid
*session_list
;
4195 int i
, num_sessions
;
4197 if (!str1
|| !str2
|| !p
) {
4201 memset((char *)&desc
,'\0',sizeof(desc
));
4203 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4205 DEBUG(3,("RNetSessionEnum uLevel=%d\n",uLevel
));
4206 DEBUG(7,("RNetSessionEnum req string=%s\n",str1
));
4207 DEBUG(7,("RNetSessionEnum ret string=%s\n",str2
));
4209 /* check it's a supported varient */
4210 if (strcmp(str1
,RAP_NetSessionEnum_REQ
) != 0) {
4213 if (uLevel
!= 2 || strcmp(str2
,RAP_SESSION_INFO_L2
) != 0) {
4217 num_sessions
= list_sessions(tmp_talloc_ctx(), &session_list
);
4220 *rdata
= SMB_REALLOC_LIMIT(*rdata
,mdrcnt
);
4225 memset((char *)&desc
,'\0',sizeof(desc
));
4227 desc
.buflen
= mdrcnt
;
4229 if (!init_package(&desc
,num_sessions
,0)) {
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
);
4252 SSVALS(*rparam
,0,desc
.errcode
);
4253 SSVAL(*rparam
,2,0); /* converter */
4254 SSVAL(*rparam
,4,num_sessions
); /* count */
4256 DEBUG(4,("RNetSessionEnum: errorcode %d\n",desc
.errcode
));
4262 /****************************************************************************
4263 The buffer was too small.
4264 ****************************************************************************/
4266 static BOOL
api_TooSmall(connection_struct
*conn
,uint16 vuid
, char *param
, char *data
,
4267 int mdrcnt
, int mprcnt
,
4268 char **rdata
, char **rparam
,
4269 int *rdata_len
, int *rparam_len
)
4271 *rparam_len
= MIN(*rparam_len
,mprcnt
);
4272 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
4279 SSVAL(*rparam
,0,NERR_BufTooSmall
);
4281 DEBUG(3,("Supplied buffer too small in API command\n"));
4286 /****************************************************************************
4287 The request is not supported.
4288 ****************************************************************************/
4290 static BOOL
api_Unsupported(connection_struct
*conn
, uint16 vuid
,
4291 char *param
, int tpscnt
,
4292 char *data
, int tdscnt
,
4293 int mdrcnt
, int mprcnt
,
4294 char **rdata
, char **rparam
,
4295 int *rdata_len
, int *rparam_len
)
4298 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
4305 SSVAL(*rparam
,0,NERR_notsupported
);
4306 SSVAL(*rparam
,2,0); /* converter word */
4308 DEBUG(3,("Unsupported API command\n"));
4313 static const struct {
4316 BOOL (*fn
)(connection_struct
*, uint16
,
4319 int,int,char **,char **,int *,int *);
4320 BOOL auth_user
; /* Deny anonymous access? */
4321 } api_commands
[] = {
4322 {"RNetShareEnum", RAP_WshareEnum
, api_RNetShareEnum
, True
},
4323 {"RNetShareGetInfo", RAP_WshareGetInfo
, api_RNetShareGetInfo
},
4324 {"RNetShareAdd", RAP_WshareAdd
, api_RNetShareAdd
},
4325 {"RNetSessionEnum", RAP_WsessionEnum
, api_RNetSessionEnum
, True
},
4326 {"RNetServerGetInfo", RAP_WserverGetInfo
, api_RNetServerGetInfo
},
4327 {"RNetGroupEnum", RAP_WGroupEnum
, api_RNetGroupEnum
, True
},
4328 {"RNetGroupGetUsers", RAP_WGroupGetUsers
, api_RNetGroupGetUsers
, True
},
4329 {"RNetUserEnum", RAP_WUserEnum
, api_RNetUserEnum
, True
},
4330 {"RNetUserGetInfo", RAP_WUserGetInfo
, api_RNetUserGetInfo
},
4331 {"NetUserGetGroups", RAP_WUserGetGroups
, api_NetUserGetGroups
},
4332 {"NetWkstaGetInfo", RAP_WWkstaGetInfo
, api_NetWkstaGetInfo
},
4333 {"DosPrintQEnum", RAP_WPrintQEnum
, api_DosPrintQEnum
, True
},
4334 {"DosPrintQGetInfo", RAP_WPrintQGetInfo
, api_DosPrintQGetInfo
},
4335 {"WPrintQueuePause", RAP_WPrintQPause
, api_WPrintQueueCtrl
},
4336 {"WPrintQueueResume", RAP_WPrintQContinue
, api_WPrintQueueCtrl
},
4337 {"WPrintJobEnumerate",RAP_WPrintJobEnum
, api_WPrintJobEnumerate
},
4338 {"WPrintJobGetInfo", RAP_WPrintJobGetInfo
, api_WPrintJobGetInfo
},
4339 {"RDosPrintJobDel", RAP_WPrintJobDel
, api_RDosPrintJobDel
},
4340 {"RDosPrintJobPause", RAP_WPrintJobPause
, api_RDosPrintJobDel
},
4341 {"RDosPrintJobResume",RAP_WPrintJobContinue
, api_RDosPrintJobDel
},
4342 {"WPrintDestEnum", RAP_WPrintDestEnum
, api_WPrintDestEnum
},
4343 {"WPrintDestGetInfo", RAP_WPrintDestGetInfo
, api_WPrintDestGetInfo
},
4344 {"NetRemoteTOD", RAP_NetRemoteTOD
, api_NetRemoteTOD
},
4345 {"WPrintQueuePurge", RAP_WPrintQPurge
, api_WPrintQueueCtrl
},
4346 {"NetServerEnum", RAP_NetServerEnum2
, api_RNetServerEnum
}, /* anon OK */
4347 {"WAccessGetUserPerms",RAP_WAccessGetUserPerms
,api_WAccessGetUserPerms
},
4348 {"SetUserPassword", RAP_WUserPasswordSet2
, api_SetUserPassword
},
4349 {"WWkstaUserLogon", RAP_WWkstaUserLogon
, api_WWkstaUserLogon
},
4350 {"PrintJobInfo", RAP_WPrintJobSetInfo
, api_PrintJobInfo
},
4351 {"WPrintDriverEnum", RAP_WPrintDriverEnum
, api_WPrintDriverEnum
},
4352 {"WPrintQProcEnum", RAP_WPrintQProcessorEnum
,api_WPrintQProcEnum
},
4353 {"WPrintPortEnum", RAP_WPrintPortEnum
, api_WPrintPortEnum
},
4354 {"SamOEMChangePassword",RAP_SamOEMChgPasswordUser2_P
,api_SamOEMChangePassword
}, /* anon OK */
4355 {NULL
, -1, api_Unsupported
}
4356 /* The following RAP calls are not implemented by Samba:
4358 RAP_WFileEnum2 - anon not OK
4363 /****************************************************************************
4364 Handle remote api calls.
4365 ****************************************************************************/
4367 int api_reply(connection_struct
*conn
,
4380 char *rparam
= NULL
;
4381 const char *name1
= NULL
;
4382 const char *name2
= NULL
;
4389 DEBUG(0,("ERROR: NULL params in api_reply()\n"));
4396 api_command
= SVAL(params
,0);
4397 /* Is there a string at position params+2 ? */
4398 if (skip_string(params
,tpscnt
,params
+2)) {
4403 name2
= skip_string(params
,tpscnt
,params
+2);
4408 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
4412 tdscnt
,tpscnt
,mdrcnt
,mprcnt
));
4414 for (i
=0;api_commands
[i
].name
;i
++) {
4415 if (api_commands
[i
].id
== api_command
&& api_commands
[i
].fn
) {
4416 DEBUG(3,("Doing %s\n",api_commands
[i
].name
));
4421 /* Check whether this api call can be done anonymously */
4423 if (api_commands
[i
].auth_user
&& lp_restrict_anonymous()) {
4424 user_struct
*user
= get_valid_user_struct(vuid
);
4426 if (!user
|| user
->guest
) {
4427 return ERROR_NT(NT_STATUS_ACCESS_DENIED
);
4431 rdata
= (char *)SMB_MALLOC(1024);
4433 memset(rdata
,'\0',1024);
4436 rparam
= (char *)SMB_MALLOC(1024);
4438 memset(rparam
,'\0',1024);
4441 if(!rdata
|| !rparam
) {
4442 DEBUG(0,("api_reply: malloc fail !\n"));
4448 reply
= api_commands
[i
].fn(conn
,
4450 params
,tpscnt
, /* params + length */
4451 data
,tdscnt
, /* data + length */
4453 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
4456 if (rdata_len
> mdrcnt
|| rparam_len
> mprcnt
) {
4457 reply
= api_TooSmall(conn
,vuid
,params
,data
,mdrcnt
,mprcnt
,
4458 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
4461 /* if we get False back then it's actually unsupported */
4463 reply
= api_Unsupported(conn
,vuid
,params
,tpscnt
,data
,tdscnt
,mdrcnt
,mprcnt
,
4464 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
4467 /* If api_Unsupported returns false we can't return anything. */
4469 send_trans_reply(inbuf
,