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";
446 if (strcmp(desc
->format
,id1
) != 0) {
449 if (desc
->subformat
&& strcmp(desc
->subformat
,id2
) != 0) {
456 #define RAP_JOB_STATUS_QUEUED 0
457 #define RAP_JOB_STATUS_PAUSED 1
458 #define RAP_JOB_STATUS_SPOOLING 2
459 #define RAP_JOB_STATUS_PRINTING 3
460 #define RAP_JOB_STATUS_PRINTED 4
462 #define RAP_QUEUE_STATUS_PAUSED 1
463 #define RAP_QUEUE_STATUS_ERROR 2
465 /* turn a print job status into a on the wire status
467 static int printj_status(int v
)
471 return RAP_JOB_STATUS_QUEUED
;
473 return RAP_JOB_STATUS_PAUSED
;
475 return RAP_JOB_STATUS_SPOOLING
;
477 return RAP_JOB_STATUS_PRINTING
;
482 /* turn a print queue status into a on the wire status
484 static int printq_status(int v
)
490 return RAP_QUEUE_STATUS_PAUSED
;
492 return RAP_QUEUE_STATUS_ERROR
;
495 static void fill_printjob_info(connection_struct
*conn
, int snum
, int uLevel
,
496 struct pack_desc
*desc
,
497 print_queue_struct
*queue
, int n
)
499 time_t t
= queue
->time
;
501 /* the client expects localtime */
502 t
-= get_time_zone(t
);
504 PACKI(desc
,"W",pjobid_to_rap(lp_const_servicename(snum
),queue
->job
)); /* uJobId */
506 PACKS(desc
,"B21",queue
->fs_user
); /* szUserName */
507 PACKS(desc
,"B",""); /* pad */
508 PACKS(desc
,"B16",""); /* szNotifyName */
509 PACKS(desc
,"B10","PM_Q_RAW"); /* szDataType */
510 PACKS(desc
,"z",""); /* pszParms */
511 PACKI(desc
,"W",n
+1); /* uPosition */
512 PACKI(desc
,"W",printj_status(queue
->status
)); /* fsStatus */
513 PACKS(desc
,"z",""); /* pszStatus */
514 PACKI(desc
,"D",t
); /* ulSubmitted */
515 PACKI(desc
,"D",queue
->size
); /* ulSize */
516 PACKS(desc
,"z",queue
->fs_file
); /* pszComment */
518 if (uLevel
== 2 || uLevel
== 3 || uLevel
== 4) {
519 PACKI(desc
,"W",queue
->priority
); /* uPriority */
520 PACKS(desc
,"z",queue
->fs_user
); /* pszUserName */
521 PACKI(desc
,"W",n
+1); /* uPosition */
522 PACKI(desc
,"W",printj_status(queue
->status
)); /* fsStatus */
523 PACKI(desc
,"D",t
); /* ulSubmitted */
524 PACKI(desc
,"D",queue
->size
); /* ulSize */
525 PACKS(desc
,"z","Samba"); /* pszComment */
526 PACKS(desc
,"z",queue
->fs_file
); /* pszDocument */
528 PACKS(desc
,"z",""); /* pszNotifyName */
529 PACKS(desc
,"z","PM_Q_RAW"); /* pszDataType */
530 PACKS(desc
,"z",""); /* pszParms */
531 PACKS(desc
,"z",""); /* pszStatus */
532 PACKS(desc
,"z",SERVICE(snum
)); /* pszQueue */
533 PACKS(desc
,"z","lpd"); /* pszQProcName */
534 PACKS(desc
,"z",""); /* pszQProcParms */
535 PACKS(desc
,"z","NULL"); /* pszDriverName */
536 PackDriverData(desc
); /* pDriverData */
537 PACKS(desc
,"z",""); /* pszPrinterName */
538 } else if (uLevel
== 4) { /* OS2 */
539 PACKS(desc
,"z",""); /* pszSpoolFileName */
540 PACKS(desc
,"z",""); /* pszPortName */
541 PACKS(desc
,"z",""); /* pszStatus */
542 PACKI(desc
,"D",0); /* ulPagesSpooled */
543 PACKI(desc
,"D",0); /* ulPagesSent */
544 PACKI(desc
,"D",0); /* ulPagesPrinted */
545 PACKI(desc
,"D",0); /* ulTimePrinted */
546 PACKI(desc
,"D",0); /* ulExtendJobStatus */
547 PACKI(desc
,"D",0); /* ulStartPage */
548 PACKI(desc
,"D",0); /* ulEndPage */
553 /********************************************************************
554 Return a driver name given an snum.
555 Returns True if from tdb, False otherwise.
556 ********************************************************************/
558 static BOOL
get_driver_name(int snum
, pstring drivername
)
560 NT_PRINTER_INFO_LEVEL
*info
= NULL
;
563 get_a_printer (NULL
, &info
, 2, lp_servicename(snum
));
565 pstrcpy( drivername
, info
->info_2
->drivername
);
567 free_a_printer(&info
, 2);
573 /********************************************************************
574 Respond to the DosPrintQInfo command with a level of 52
575 This is used to get printer driver information for Win9x clients
576 ********************************************************************/
577 static void fill_printq_info_52(connection_struct
*conn
, int snum
,
578 struct pack_desc
* desc
, int count
)
582 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
583 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
587 if ( !W_ERROR_IS_OK(get_a_printer( NULL
, &printer
, 2, lp_servicename(snum
))) ) {
588 DEBUG(3,("fill_printq_info_52: Failed to lookup printer [%s]\n",
589 lp_servicename(snum
)));
593 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
,
596 DEBUG(3,("fill_printq_info_52: Failed to lookup driver [%s]\n",
597 printer
->info_2
->drivername
));
601 trim_string(driver
.info_3
->driverpath
, "\\print$\\WIN40\\0\\", 0);
602 trim_string(driver
.info_3
->datafile
, "\\print$\\WIN40\\0\\", 0);
603 trim_string(driver
.info_3
->helpfile
, "\\print$\\WIN40\\0\\", 0);
605 PACKI(desc
, "W", 0x0400); /* don't know */
606 PACKS(desc
, "z", driver
.info_3
->name
); /* long printer name */
607 PACKS(desc
, "z", driver
.info_3
->driverpath
); /* Driverfile Name */
608 PACKS(desc
, "z", driver
.info_3
->datafile
); /* Datafile name */
609 PACKS(desc
, "z", driver
.info_3
->monitorname
); /* language monitor */
611 fstrcpy(location
, "\\\\%L\\print$\\WIN40\\0");
612 standard_sub_basic( "", "", location
, sizeof(location
)-1 );
613 PACKS(desc
,"z", location
); /* share to retrieve files */
615 PACKS(desc
,"z", driver
.info_3
->defaultdatatype
); /* default data type */
616 PACKS(desc
,"z", driver
.info_3
->helpfile
); /* helpfile name */
617 PACKS(desc
,"z", driver
.info_3
->driverpath
); /* driver name */
619 DEBUG(3,("Printer Driver Name: %s:\n",driver
.info_3
->name
));
620 DEBUG(3,("Driver: %s:\n",driver
.info_3
->driverpath
));
621 DEBUG(3,("Data File: %s:\n",driver
.info_3
->datafile
));
622 DEBUG(3,("Language Monitor: %s:\n",driver
.info_3
->monitorname
));
623 DEBUG(3,("Driver Location: %s:\n",location
));
624 DEBUG(3,("Data Type: %s:\n",driver
.info_3
->defaultdatatype
));
625 DEBUG(3,("Help File: %s:\n",driver
.info_3
->helpfile
));
626 PACKI(desc
,"N",count
); /* number of files to copy */
628 for ( i
=0; i
<count
&& driver
.info_3
->dependentfiles
&& *driver
.info_3
->dependentfiles
[i
]; i
++)
630 trim_string(driver
.info_3
->dependentfiles
[i
], "\\print$\\WIN40\\0\\", 0);
631 PACKS(desc
,"z",driver
.info_3
->dependentfiles
[i
]); /* driver files to copy */
632 DEBUG(3,("Dependent File: %s:\n",driver
.info_3
->dependentfiles
[i
]));
637 DEBUG(3,("fill_printq_info_52: file count specified by client [%d] != number of dependent files [%i]\n",
640 DEBUG(3,("fill_printq_info on <%s> gave %d entries\n", SERVICE(snum
),i
));
642 desc
->errcode
=NERR_Success
;
646 DEBUG(3,("fill_printq_info: Can't supply driver files\n"));
647 desc
->errcode
=NERR_notsupported
;
651 free_a_printer( &printer
, 2 );
654 free_a_printer_driver( driver
, 3 );
658 static void fill_printq_info(connection_struct
*conn
, int snum
, int uLevel
,
659 struct pack_desc
* desc
,
660 int count
, print_queue_struct
* queue
,
661 print_status_struct
* status
)
666 PACKS(desc
,"B13",SERVICE(snum
));
671 PACKS(desc
,"z",Expand(conn
,snum
,SERVICE(snum
)));
674 PACKI(desc
,"K",printq_status(status
->status
));
678 if (uLevel
== 1 || uLevel
== 2) {
679 PACKS(desc
,"B",""); /* alignment */
680 PACKI(desc
,"W",5); /* priority */
681 PACKI(desc
,"W",0); /* start time */
682 PACKI(desc
,"W",0); /* until time */
683 PACKS(desc
,"z",""); /* pSepFile */
684 PACKS(desc
,"z","lpd"); /* pPrProc */
685 PACKS(desc
,"z",SERVICE(snum
)); /* pDestinations */
686 PACKS(desc
,"z",""); /* pParms */
688 PACKS(desc
,"z","UNKNOWN PRINTER");
689 PACKI(desc
,"W",LPSTAT_ERROR
);
691 else if (!status
|| !status
->message
[0]) {
692 PACKS(desc
,"z",Expand(conn
,snum
,lp_comment(snum
)));
693 PACKI(desc
,"W",LPSTAT_OK
); /* status */
695 PACKS(desc
,"z",status
->message
);
696 PACKI(desc
,"W",printq_status(status
->status
)); /* status */
698 PACKI(desc
,(uLevel
== 1 ? "W" : "N"),count
);
701 if (uLevel
== 3 || uLevel
== 4) {
704 PACKI(desc
,"W",5); /* uPriority */
705 PACKI(desc
,"W",0); /* uStarttime */
706 PACKI(desc
,"W",0); /* uUntiltime */
707 PACKI(desc
,"W",5); /* pad1 */
708 PACKS(desc
,"z",""); /* pszSepFile */
709 PACKS(desc
,"z","WinPrint"); /* pszPrProc */
710 PACKS(desc
,"z",NULL
); /* pszParms */
711 PACKS(desc
,"z",NULL
); /* pszComment - don't ask.... JRA */
712 /* "don't ask" that it's done this way to fix corrupted
713 Win9X/ME printer comments. */
715 PACKI(desc
,"W",LPSTAT_OK
); /* fsStatus */
717 PACKI(desc
,"W",printq_status(status
->status
)); /* fsStatus */
719 PACKI(desc
,(uLevel
== 3 ? "W" : "N"),count
); /* cJobs */
720 PACKS(desc
,"z",SERVICE(snum
)); /* pszPrinters */
721 get_driver_name(snum
,drivername
);
722 PACKS(desc
,"z",drivername
); /* pszDriverName */
723 PackDriverData(desc
); /* pDriverData */
726 if (uLevel
== 2 || uLevel
== 4) {
728 for (i
=0;i
<count
;i
++)
729 fill_printjob_info(conn
,snum
,uLevel
== 2 ? 1 : 2,desc
,&queue
[i
],i
);
733 fill_printq_info_52( conn
, snum
, desc
, count
);
736 /* This function returns the number of files for a given driver */
737 static int get_printerdrivernumber(int snum
)
740 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
741 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
745 if ( !W_ERROR_IS_OK(get_a_printer( NULL
, &printer
, 2, lp_servicename(snum
))) ) {
746 DEBUG(3,("get_printerdrivernumber: Failed to lookup printer [%s]\n",
747 lp_servicename(snum
)));
751 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
,
754 DEBUG(3,("get_printerdrivernumber: Failed to lookup driver [%s]\n",
755 printer
->info_2
->drivername
));
759 /* count the number of files */
760 while ( driver
.info_3
->dependentfiles
&& *driver
.info_3
->dependentfiles
[result
] )
765 free_a_printer( &printer
, 2 );
768 free_a_printer_driver( driver
, 3 );
773 static BOOL
api_DosPrintQGetInfo(connection_struct
*conn
, uint16 vuid
,
774 char *param
, int tpscnt
,
775 char *data
, int tdscnt
,
776 int mdrcnt
,int mprcnt
,
777 char **rdata
,char **rparam
,
778 int *rdata_len
,int *rparam_len
)
780 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
781 char *str2
= skip_string(param
,tpscnt
,str1
,1);
782 char *p
= skip_string(param
,tpscnt
,str2
,1);
788 struct pack_desc desc
;
789 print_queue_struct
*queue
=NULL
;
790 print_status_struct status
;
793 if (!str1
|| !str2
|| !p
) {
796 memset((char *)&status
,'\0',sizeof(status
));
797 memset((char *)&desc
,'\0',sizeof(desc
));
799 p
= skip_string(param
,tpscnt
,p
,1);
803 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
804 str3
= get_safe_str_ptr(param
,tpscnt
,p
,4);
809 /* remove any trailing username */
810 if ((p
= strchr_m(QueueName
,'%')))
813 DEBUG(3,("api_DosPrintQGetInfo uLevel=%d name=%s\n",uLevel
,QueueName
));
815 /* check it's a supported varient */
816 if (!prefix_ok(str1
,"zWrLh"))
818 if (!check_printq_info(&desc
,uLevel
,str2
,str3
)) {
820 * Patch from Scott Moomaw <scott@bridgewater.edu>
821 * to return the 'invalid info level' error if an
822 * unknown level was requested.
826 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
830 SSVALS(*rparam
,0,ERRunknownlevel
);
836 snum
= find_service(QueueName
);
837 if ( !(lp_snum_ok(snum
) && lp_print_ok(snum
)) )
841 count
= get_printerdrivernumber(snum
);
842 DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count
));
844 count
= print_queue_status(snum
, &queue
,&status
);
848 *rdata
= SMB_REALLOC_LIMIT(*rdata
,mdrcnt
);
853 desc
.buflen
= mdrcnt
;
856 * Don't return data but need to get correct length
857 * init_package will return wrong size if buflen=0
859 desc
.buflen
= getlen(desc
.format
);
860 desc
.base
= tmpdata
= (char *) SMB_MALLOC (desc
.buflen
);
863 if (init_package(&desc
,1,count
)) {
864 desc
.subcount
= count
;
865 fill_printq_info(conn
,snum
,uLevel
,&desc
,count
,queue
,&status
);
868 *rdata_len
= desc
.usedlen
;
871 * We must set the return code to ERRbuftoosmall
872 * in order to support lanman style printing with Win NT/2k
875 if (!mdrcnt
&& lp_disable_spoolss())
876 desc
.errcode
= ERRbuftoosmall
;
878 *rdata_len
= desc
.usedlen
;
880 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
884 SSVALS(*rparam
,0,desc
.errcode
);
886 SSVAL(*rparam
,4,desc
.neededlen
);
888 DEBUG(4,("printqgetinfo: errorcode %d\n",desc
.errcode
));
896 /****************************************************************************
897 View list of all print jobs on all queues.
898 ****************************************************************************/
900 static BOOL
api_DosPrintQEnum(connection_struct
*conn
, uint16 vuid
,
901 char *param
, int tpscnt
,
902 char *data
, int tdscnt
,
903 int mdrcnt
, int mprcnt
,
904 char **rdata
, char** rparam
,
905 int *rdata_len
, int *rparam_len
)
907 char *param_format
= get_safe_str_ptr(param
,tpscnt
,param
,2);
908 char *output_format1
= skip_string(param
,tpscnt
,param_format
,1);
909 char *p
= skip_string(param
,tpscnt
,output_format1
,1);
910 unsigned int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
911 char *output_format2
= get_safe_str_ptr(param
,tpscnt
,p
,4);
912 int services
= lp_numservices();
914 struct pack_desc desc
;
915 print_queue_struct
**queue
= NULL
;
916 print_status_struct
*status
= NULL
;
917 int *subcntarr
= NULL
;
918 int queuecnt
= 0, subcnt
= 0, succnt
= 0;
920 if (!param_format
|| !output_format1
|| !p
|| !output_format2
) {
924 memset((char *)&desc
,'\0',sizeof(desc
));
926 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel
));
928 if (!prefix_ok(param_format
,"WrLeh")) {
931 if (!check_printq_info(&desc
,uLevel
,output_format1
,output_format2
)) {
933 * Patch from Scott Moomaw <scott@bridgewater.edu>
934 * to return the 'invalid info level' error if an
935 * unknown level was requested.
939 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
943 SSVALS(*rparam
,0,ERRunknownlevel
);
949 for (i
= 0; i
< services
; i
++) {
950 if (lp_snum_ok(i
) && lp_print_ok(i
) && lp_browseable(i
)) {
955 if((queue
= SMB_MALLOC_ARRAY(print_queue_struct
*, queuecnt
)) == NULL
) {
956 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
959 memset(queue
,0,queuecnt
*sizeof(print_queue_struct
*));
960 if((status
= SMB_MALLOC_ARRAY(print_status_struct
,queuecnt
)) == NULL
) {
961 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
964 memset(status
,0,queuecnt
*sizeof(print_status_struct
));
965 if((subcntarr
= SMB_MALLOC_ARRAY(int,queuecnt
)) == NULL
) {
966 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
972 for (i
= 0; i
< services
; i
++) {
973 if (lp_snum_ok(i
) && lp_print_ok(i
) && lp_browseable(i
)) {
974 subcntarr
[n
] = print_queue_status(i
, &queue
[n
],&status
[n
]);
975 subcnt
+= subcntarr
[n
];
981 *rdata
= SMB_REALLOC_LIMIT(*rdata
,mdrcnt
);
987 desc
.buflen
= mdrcnt
;
989 if (init_package(&desc
,queuecnt
,subcnt
)) {
992 for (i
= 0; i
< services
; i
++) {
993 if (lp_snum_ok(i
) && lp_print_ok(i
) && lp_browseable(i
)) {
994 fill_printq_info(conn
,i
,uLevel
,&desc
,subcntarr
[n
],queue
[n
],&status
[n
]);
996 if (desc
.errcode
== NERR_Success
) {
1003 SAFE_FREE(subcntarr
);
1005 *rdata_len
= desc
.usedlen
;
1007 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
1011 SSVALS(*rparam
,0,desc
.errcode
);
1013 SSVAL(*rparam
,4,succnt
);
1014 SSVAL(*rparam
,6,queuecnt
);
1016 for (i
= 0; i
< queuecnt
; i
++) {
1018 SAFE_FREE(queue
[i
]);
1029 SAFE_FREE(subcntarr
);
1030 for (i
= 0; i
< queuecnt
; i
++) {
1032 SAFE_FREE(queue
[i
]);
1041 /****************************************************************************
1042 Get info level for a server list query.
1043 ****************************************************************************/
1045 static BOOL
check_server_info(int uLevel
, char* id
)
1049 if (strcmp(id
,"B16") != 0) {
1054 if (strcmp(id
,"B16BBDz") != 0) {
1064 struct srv_info_struct
{
1072 /*******************************************************************
1073 Get server info lists from the files saved by nmbd. Return the
1075 ******************************************************************/
1077 static int get_server_info(uint32 servertype
,
1078 struct srv_info_struct
**servers
,
1084 BOOL local_list_only
;
1087 lines
= file_lines_load(lock_path(SERVER_LIST
), NULL
, 0);
1089 DEBUG(4,("Can't open %s - %s\n",lock_path(SERVER_LIST
),strerror(errno
)));
1093 /* request for everything is code for request all servers */
1094 if (servertype
== SV_TYPE_ALL
) {
1095 servertype
&= ~(SV_TYPE_DOMAIN_ENUM
|SV_TYPE_LOCAL_LIST_ONLY
);
1098 local_list_only
= (servertype
& SV_TYPE_LOCAL_LIST_ONLY
);
1100 DEBUG(4,("Servertype search: %8x\n",servertype
));
1102 for (i
=0;lines
[i
];i
++) {
1104 struct srv_info_struct
*s
;
1105 const char *ptr
= lines
[i
];
1112 if (count
== alloced
) {
1114 *servers
= SMB_REALLOC_ARRAY(*servers
,struct srv_info_struct
, alloced
);
1116 DEBUG(0,("get_server_info: failed to enlarge servers info struct!\n"));
1117 file_lines_free(lines
);
1120 memset((char *)((*servers
)+count
),'\0',sizeof(**servers
)*(alloced
-count
));
1122 s
= &(*servers
)[count
];
1124 if (!next_token(&ptr
,s
->name
, NULL
, sizeof(s
->name
))) {
1127 if (!next_token(&ptr
,stype
, NULL
, sizeof(stype
))) {
1130 if (!next_token(&ptr
,s
->comment
, NULL
, sizeof(s
->comment
))) {
1133 if (!next_token(&ptr
,s
->domain
, NULL
, sizeof(s
->domain
))) {
1134 /* this allows us to cope with an old nmbd */
1135 fstrcpy(s
->domain
,lp_workgroup());
1138 if (sscanf(stype
,"%X",&s
->type
) != 1) {
1139 DEBUG(4,("r:host file "));
1143 /* Filter the servers/domains we return based on what was asked for. */
1145 /* Check to see if we are being asked for a local list only. */
1146 if(local_list_only
&& ((s
->type
& SV_TYPE_LOCAL_LIST_ONLY
) == 0)) {
1147 DEBUG(4,("r: local list only"));
1151 /* doesn't match up: don't want it */
1152 if (!(servertype
& s
->type
)) {
1153 DEBUG(4,("r:serv type "));
1157 if ((servertype
& SV_TYPE_DOMAIN_ENUM
) !=
1158 (s
->type
& SV_TYPE_DOMAIN_ENUM
)) {
1159 DEBUG(4,("s: dom mismatch "));
1163 if (!strequal(domain
, s
->domain
) && !(servertype
& SV_TYPE_DOMAIN_ENUM
)) {
1167 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
1168 s
->type
&= ~SV_TYPE_LOCAL_LIST_ONLY
;
1171 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
1172 s
->name
, s
->type
, s
->comment
, s
->domain
));
1173 s
->server_added
= True
;
1176 DEBUG(4,("%20s %8x %25s %15s\n",
1177 s
->name
, s
->type
, s
->comment
, s
->domain
));
1181 file_lines_free(lines
);
1185 /*******************************************************************
1186 Fill in a server info structure.
1187 ******************************************************************/
1189 static int fill_srv_info(struct srv_info_struct
*service
,
1190 int uLevel
, char **buf
, int *buflen
,
1191 char **stringbuf
, int *stringspace
, char *baseaddr
)
1214 len
= strlen(service
->comment
)+1;
1218 *buflen
= struct_len
;
1220 return struct_len
+ len
;
1225 if (*buflen
< struct_len
) {
1232 p2
= p
+ struct_len
;
1233 l2
= *buflen
- struct_len
;
1241 push_ascii(p
,service
->name
, MAX_NETBIOSNAME_LEN
, STR_TERMINATE
);
1245 push_ascii(p
,service
->name
,MAX_NETBIOSNAME_LEN
, STR_TERMINATE
);
1246 SIVAL(p
,18,service
->type
);
1247 SIVAL(p
,22,PTR_DIFF(p2
,baseaddr
));
1248 len
+= CopyAndAdvance(&p2
,service
->comment
,&l2
);
1253 *buf
= p
+ struct_len
;
1254 *buflen
-= struct_len
;
1265 static BOOL
srv_comp(struct srv_info_struct
*s1
,struct srv_info_struct
*s2
)
1267 return(strcmp(s1
->name
,s2
->name
));
1270 /****************************************************************************
1271 View list of servers available (or possibly domains). The info is
1272 extracted from lists saved by nmbd on the local host.
1273 ****************************************************************************/
1275 static BOOL
api_RNetServerEnum(connection_struct
*conn
, uint16 vuid
,
1276 char *param
, int tpscnt
,
1277 char *data
, int tdscnt
,
1278 int mdrcnt
, int mprcnt
, char **rdata
,
1279 char **rparam
, int *rdata_len
, int *rparam_len
)
1281 char *str1
= get_safe_str_ptr(param
, tpscnt
, param
, 2);
1282 char *str2
= skip_string(param
,tpscnt
,str1
,1);
1283 char *p
= skip_string(param
,tpscnt
,str2
,1);
1284 int uLevel
= get_safe_SVAL(param
, tpscnt
, p
, 0, -1);
1285 int buf_len
= get_safe_SVAL(param
,tpscnt
, p
, 2, 0);
1286 uint32 servertype
= get_safe_IVAL(param
,tpscnt
,p
,4, 0);
1288 int data_len
, fixed_len
, string_len
;
1289 int f_len
= 0, s_len
= 0;
1290 struct srv_info_struct
*servers
=NULL
;
1291 int counted
=0,total
=0;
1294 BOOL domain_request
;
1297 if (!str1
|| !str2
|| !p
) {
1301 /* If someone sets all the bits they don't really mean to set
1302 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1305 if (servertype
== SV_TYPE_ALL
) {
1306 servertype
&= ~(SV_TYPE_DOMAIN_ENUM
|SV_TYPE_LOCAL_LIST_ONLY
);
1309 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1310 any other bit (they may just set this bit on it's own) they
1311 want all the locally seen servers. However this bit can be
1312 set on its own so set the requested servers to be
1313 ALL - DOMAIN_ENUM. */
1315 if ((servertype
& SV_TYPE_LOCAL_LIST_ONLY
) && !(servertype
& SV_TYPE_DOMAIN_ENUM
)) {
1316 servertype
= SV_TYPE_ALL
& ~(SV_TYPE_DOMAIN_ENUM
);
1319 domain_request
= ((servertype
& SV_TYPE_DOMAIN_ENUM
) != 0);
1320 local_request
= ((servertype
& SV_TYPE_LOCAL_LIST_ONLY
) != 0);
1324 if (!prefix_ok(str1
,"WrLehD")) {
1327 if (!check_server_info(uLevel
,str2
)) {
1331 DEBUG(4, ("server request level: %s %8x ", str2
, servertype
));
1332 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request
)));
1333 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request
)));
1335 if (strcmp(str1
, "WrLehDz") == 0) {
1336 if (skip_string(param
,tpscnt
,p
,1) == NULL
) {
1339 pull_ascii_fstring(domain
, p
);
1341 fstrcpy(domain
, lp_workgroup());
1344 if (lp_browse_list()) {
1345 total
= get_server_info(servertype
,&servers
,domain
);
1348 data_len
= fixed_len
= string_len
= 0;
1352 qsort(servers
,total
,sizeof(servers
[0]),QSORT_CAST srv_comp
);
1356 char *lastname
=NULL
;
1358 for (i
=0;i
<total
;i
++) {
1359 struct srv_info_struct
*s
= &servers
[i
];
1361 if (lastname
&& strequal(lastname
,s
->name
)) {
1365 data_len
+= fill_srv_info(s
,uLevel
,0,&f_len
,0,&s_len
,0);
1366 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1367 s
->name
, s
->type
, s
->comment
, s
->domain
));
1369 if (data_len
<= buf_len
) {
1372 string_len
+= s_len
;
1379 *rdata_len
= fixed_len
+ string_len
;
1380 *rdata
= SMB_REALLOC_LIMIT(*rdata
,*rdata_len
);
1384 memset(*rdata
,'\0',*rdata_len
);
1386 p2
= (*rdata
) + fixed_len
; /* auxilliary data (strings) will go here */
1392 char *lastname
=NULL
;
1393 int count2
= counted
;
1395 for (i
= 0; i
< total
&& count2
;i
++) {
1396 struct srv_info_struct
*s
= &servers
[i
];
1398 if (lastname
&& strequal(lastname
,s
->name
)) {
1402 fill_srv_info(s
,uLevel
,&p
,&f_len
,&p2
,&s_len
,*rdata
);
1403 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1404 s
->name
, s
->type
, s
->comment
, s
->domain
));
1410 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
1414 SSVAL(*rparam
,0,(missed
== 0 ? NERR_Success
: ERRmoredata
));
1416 SSVAL(*rparam
,4,counted
);
1417 SSVAL(*rparam
,6,counted
+missed
);
1421 DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
1422 domain
,uLevel
,counted
,counted
+missed
));
1427 /****************************************************************************
1428 command 0x34 - suspected of being a "Lookup Names" stub api
1429 ****************************************************************************/
1431 static BOOL
api_RNetGroupGetUsers(connection_struct
*conn
, uint16 vuid
,
1432 char *param
, int tpscnt
,
1433 char *data
, int tdscnt
,
1434 int mdrcnt
, int mprcnt
, char **rdata
,
1435 char **rparam
, int *rdata_len
, int *rparam_len
)
1437 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
1438 char *str2
= skip_string(param
,tpscnt
,str1
,1);
1439 char *p
= skip_string(param
,tpscnt
,str2
,1);
1440 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
1441 int buf_len
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
1445 if (!str1
|| !str2
|| !p
) {
1449 DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
1450 str1
, str2
, p
, uLevel
, buf_len
));
1452 if (!prefix_ok(str1
,"zWrLeh")) {
1459 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
1464 SSVAL(*rparam
,0,0x08AC); /* informational warning message */
1466 SSVAL(*rparam
,4,counted
);
1467 SSVAL(*rparam
,6,counted
+missed
);
1472 /****************************************************************************
1473 get info about a share
1474 ****************************************************************************/
1476 static BOOL
check_share_info(int uLevel
, char* id
)
1480 if (strcmp(id
,"B13") != 0) {
1485 if (strcmp(id
,"B13BWz") != 0) {
1490 if (strcmp(id
,"B13BWzWWWzB9B") != 0) {
1495 if (strcmp(id
,"B13BWzWWWzB9BB9BWzWWzWW") != 0) {
1505 static int fill_share_info(connection_struct
*conn
, int snum
, int uLevel
,
1506 char** buf
, int* buflen
,
1507 char** stringbuf
, int* stringspace
, char* baseaddr
)
1537 len
+= StrlenExpanded(conn
,snum
,lp_comment(snum
));
1540 len
+= strlen(lp_pathname(snum
)) + 1;
1543 *buflen
= struct_len
;
1548 return struct_len
+ len
;
1553 if ((*buflen
) < struct_len
) {
1561 p2
= p
+ struct_len
;
1562 l2
= (*buflen
) - struct_len
;
1569 push_ascii(p
,lp_servicename(snum
),13, STR_TERMINATE
);
1575 type
= STYPE_DISKTREE
;
1576 if (lp_print_ok(snum
)) {
1577 type
= STYPE_PRINTQ
;
1579 if (strequal("IPC",lp_fstype(snum
))) {
1582 SSVAL(p
,14,type
); /* device type */
1583 SIVAL(p
,16,PTR_DIFF(p2
,baseaddr
));
1584 len
+= CopyExpanded(conn
,snum
,&p2
,lp_comment(snum
),&l2
);
1588 SSVAL(p
,20,ACCESS_READ
|ACCESS_WRITE
|ACCESS_CREATE
); /* permissions */
1589 SSVALS(p
,22,-1); /* max uses */
1590 SSVAL(p
,24,1); /* current uses */
1591 SIVAL(p
,26,PTR_DIFF(p2
,baseaddr
)); /* local pathname */
1592 len
+= CopyAndAdvance(&p2
,lp_pathname(snum
),&l2
);
1593 memset(p
+30,0,SHPWLEN
+2); /* passwd (reserved), pad field */
1597 memset(p
+40,0,SHPWLEN
+2);
1608 (*buf
) = p
+ struct_len
;
1609 (*buflen
) -= struct_len
;
1611 (*stringspace
) = l2
;
1620 static BOOL
api_RNetShareGetInfo(connection_struct
*conn
,uint16 vuid
,
1621 char *param
, int tpscnt
,
1622 char *data
, int tdscnt
,
1623 int mdrcnt
,int mprcnt
,
1624 char **rdata
,char **rparam
,
1625 int *rdata_len
,int *rparam_len
)
1627 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
1628 char *str2
= skip_string(param
,tpscnt
,str1
,1);
1629 char *netname
= skip_string(param
,tpscnt
,str2
,1);
1630 char *p
= skip_string(param
,tpscnt
,netname
,1);
1631 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
1634 if (!str1
|| !str2
|| !netname
|| !p
) {
1638 snum
= find_service(netname
);
1643 /* check it's a supported varient */
1644 if (!prefix_ok(str1
,"zWrLh")) {
1647 if (!check_share_info(uLevel
,str2
)) {
1651 *rdata
= SMB_REALLOC_LIMIT(*rdata
,mdrcnt
);
1656 *rdata_len
= fill_share_info(conn
,snum
,uLevel
,&p
,&mdrcnt
,0,0,0);
1657 if (*rdata_len
< 0) {
1662 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
1666 SSVAL(*rparam
,0,NERR_Success
);
1667 SSVAL(*rparam
,2,0); /* converter word */
1668 SSVAL(*rparam
,4,*rdata_len
);
1673 /****************************************************************************
1674 View the list of available shares.
1676 This function is the server side of the NetShareEnum() RAP call.
1677 It fills the return buffer with share names and share comments.
1678 Note that the return buffer normally (in all known cases) allows only
1679 twelve byte strings for share names (plus one for a nul terminator).
1680 Share names longer than 12 bytes must be skipped.
1681 ****************************************************************************/
1683 static BOOL
api_RNetShareEnum( connection_struct
*conn
, uint16 vuid
,
1684 char *param
, int tpscnt
,
1685 char *data
, int tdscnt
,
1693 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
1694 char *str2
= skip_string(param
,tpscnt
,str1
,1);
1695 char *p
= skip_string(param
,tpscnt
,str2
,1);
1696 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
1697 int buf_len
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
1700 int total
=0,counted
=0;
1701 BOOL missed
= False
;
1703 int data_len
, fixed_len
, string_len
;
1704 int f_len
= 0, s_len
= 0;
1706 if (!str1
|| !str2
|| !p
) {
1710 if (!prefix_ok(str1
,"WrLeh")) {
1713 if (!check_share_info(uLevel
,str2
)) {
1717 /* Ensure all the usershares are loaded. */
1719 load_registry_shares();
1720 count
= load_usershare_shares();
1723 data_len
= fixed_len
= string_len
= 0;
1724 for (i
=0;i
<count
;i
++) {
1725 fstring servicename_dos
;
1726 if (!(lp_browseable(i
) && lp_snum_ok(i
))) {
1729 push_ascii_fstring(servicename_dos
, lp_servicename(i
));
1730 /* Maximum name length = 13. */
1731 if( lp_browseable( i
) && lp_snum_ok( i
) && (strlen(servicename_dos
) < 13)) {
1733 data_len
+= fill_share_info(conn
,i
,uLevel
,0,&f_len
,0,&s_len
,0);
1734 if (data_len
<= buf_len
) {
1737 string_len
+= s_len
;
1744 *rdata_len
= fixed_len
+ string_len
;
1745 *rdata
= SMB_REALLOC_LIMIT(*rdata
,*rdata_len
);
1749 memset(*rdata
,0,*rdata_len
);
1751 p2
= (*rdata
) + fixed_len
; /* auxiliary data (strings) will go here */
1756 for( i
= 0; i
< count
; i
++ ) {
1757 fstring servicename_dos
;
1758 if (!(lp_browseable(i
) && lp_snum_ok(i
))) {
1762 push_ascii_fstring(servicename_dos
, lp_servicename(i
));
1763 if (lp_browseable(i
) && lp_snum_ok(i
) && (strlen(servicename_dos
) < 13)) {
1764 if (fill_share_info( conn
,i
,uLevel
,&p
,&f_len
,&p2
,&s_len
,*rdata
) < 0) {
1771 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
1775 SSVAL(*rparam
,0,missed
? ERRmoredata
: NERR_Success
);
1777 SSVAL(*rparam
,4,counted
);
1778 SSVAL(*rparam
,6,total
);
1780 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
1781 counted
,total
,uLevel
,
1782 buf_len
,*rdata_len
,mdrcnt
));
1787 /****************************************************************************
1789 ****************************************************************************/
1791 static BOOL
api_RNetShareAdd(connection_struct
*conn
,uint16 vuid
,
1792 char *param
, int tpscnt
,
1793 char *data
, int tdscnt
,
1794 int mdrcnt
,int mprcnt
,
1795 char **rdata
,char **rparam
,
1796 int *rdata_len
,int *rparam_len
)
1798 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
1799 char *str2
= skip_string(param
,tpscnt
,str1
,1);
1800 char *p
= skip_string(param
,tpscnt
,str2
,1);
1801 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
1805 char *command
, *cmdname
;
1806 unsigned int offset
;
1810 if (!str1
|| !str2
|| !p
) {
1814 /* check it's a supported varient */
1815 if (!prefix_ok(str1
,RAP_WShareAdd_REQ
)) {
1818 if (!check_share_info(uLevel
,str2
)) {
1825 /* Do we have a string ? */
1826 if (skip_string(data
,mdrcnt
,data
,1) == NULL
) {
1829 pull_ascii_fstring(sharename
,data
);
1830 snum
= find_service(sharename
);
1831 if (snum
>= 0) { /* already exists */
1840 /* only support disk share adds */
1841 if (SVAL(data
,14)!=STYPE_DISKTREE
) {
1845 offset
= IVAL(data
, 16);
1846 if (offset
>= mdrcnt
) {
1847 res
= ERRinvalidparam
;
1851 /* Do we have a string ? */
1852 if (skip_string(data
,mdrcnt
,data
+offset
,1) == NULL
) {
1855 pull_ascii_fstring(comment
, offset
? (data
+offset
) : "");
1857 offset
= IVAL(data
, 26);
1859 if (offset
>= mdrcnt
) {
1860 res
= ERRinvalidparam
;
1864 /* Do we have a string ? */
1865 if (skip_string(data
,mdrcnt
,data
+offset
,1) == NULL
) {
1868 pull_ascii_pstring(pathname
, offset
? (data
+offset
) : "");
1870 string_replace(sharename
, '"', ' ');
1871 string_replace(pathname
, '"', ' ');
1872 string_replace(comment
, '"', ' ');
1874 cmdname
= lp_add_share_cmd();
1876 if (!cmdname
|| *cmdname
== '\0') {
1880 asprintf(&command
, "%s \"%s\" \"%s\" \"%s\" \"%s\"",
1881 lp_add_share_cmd(), dyn_CONFIGFILE
, sharename
, pathname
, comment
);
1884 DEBUG(10,("api_RNetShareAdd: Running [%s]\n", command
));
1886 if ((res
= smbrun(command
, NULL
)) != 0) {
1887 DEBUG(1,("api_RNetShareAdd: Running [%s] returned (%d)\n", command
, res
));
1893 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED
, NULL
, 0, False
, NULL
);
1900 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
1904 SSVAL(*rparam
,0,NERR_Success
);
1905 SSVAL(*rparam
,2,0); /* converter word */
1906 SSVAL(*rparam
,4,*rdata_len
);
1914 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
1919 SSVAL(*rparam
,0,res
);
1924 /****************************************************************************
1925 view list of groups available
1926 ****************************************************************************/
1928 static BOOL
api_RNetGroupEnum(connection_struct
*conn
,uint16 vuid
,
1929 char *param
, int tpscnt
,
1930 char *data
, int tdscnt
,
1931 int mdrcnt
,int mprcnt
,
1932 char **rdata
,char **rparam
,
1933 int *rdata_len
,int *rparam_len
)
1937 int resume_context
, cli_buf_size
;
1938 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
1939 char *str2
= skip_string(param
,tpscnt
,str1
,1);
1940 char *p
= skip_string(param
,tpscnt
,str2
,1);
1942 struct pdb_search
*search
;
1943 struct samr_displayentry
*entries
;
1947 if (!str1
|| !str2
|| !p
) {
1951 if (strcmp(str1
,"WrLeh") != 0) {
1956 * W-> resume context (number of users to skip)
1957 * r -> return parameter pointer to receive buffer
1958 * L -> length of receive buffer
1959 * e -> return parameter number of entries
1960 * h -> return parameter total number of users
1963 if (strcmp("B21",str2
) != 0) {
1967 /* get list of domain groups SID_DOMAIN_GRP=2 */
1969 search
= pdb_search_groups();
1972 if (search
== NULL
) {
1973 DEBUG(3,("api_RNetGroupEnum:failed to get group list"));
1977 resume_context
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
1978 cli_buf_size
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
1979 DEBUG(10,("api_RNetGroupEnum:resume context: %d, client buffer size: "
1980 "%d\n", resume_context
, cli_buf_size
));
1983 num_entries
= pdb_search_entries(search
, resume_context
, 0xffffffff,
1987 *rdata_len
= cli_buf_size
;
1988 *rdata
= SMB_REALLOC_LIMIT(*rdata
,*rdata_len
);
1995 for(i
=0; i
<num_entries
; i
++) {
1997 fstrcpy(name
, entries
[i
].account_name
);
1998 if( ((PTR_DIFF(p
,*rdata
)+21) <= *rdata_len
) ) {
1999 /* truncate the name at 21 chars. */
2000 memcpy(p
, name
, 21);
2001 DEBUG(10,("adding entry %d group %s\n", i
, p
));
2003 p
+= 5; /* Both NT4 and W2k3SP1 do padding here.
2006 /* set overflow error */
2007 DEBUG(3,("overflow on entry %d group %s\n", i
, name
));
2013 pdb_search_destroy(search
);
2015 *rdata_len
= PTR_DIFF(p
,*rdata
);
2018 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
2022 SSVAL(*rparam
, 0, errflags
);
2023 SSVAL(*rparam
, 2, 0); /* converter word */
2024 SSVAL(*rparam
, 4, i
); /* is this right?? */
2025 SSVAL(*rparam
, 6, resume_context
+num_entries
); /* is this right?? */
2030 /*******************************************************************
2031 Get groups that a user is a member of.
2032 ******************************************************************/
2034 static BOOL
api_NetUserGetGroups(connection_struct
*conn
,uint16 vuid
,
2035 char *param
, int tpscnt
,
2036 char *data
, int tdscnt
,
2037 int mdrcnt
,int mprcnt
,
2038 char **rdata
,char **rparam
,
2039 int *rdata_len
,int *rparam_len
)
2041 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2042 char *str2
= skip_string(param
,tpscnt
,str1
,1);
2043 char *UserName
= skip_string(param
,tpscnt
,str2
,1);
2044 char *p
= skip_string(param
,tpscnt
,UserName
,1);
2045 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2046 const char *level_string
;
2048 struct samu
*sampw
= NULL
;
2056 enum lsa_SidType type
;
2057 TALLOC_CTX
*mem_ctx
;
2059 if (!str1
|| !str2
|| !UserName
|| !p
) {
2064 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
2069 /* check it's a supported varient */
2071 if ( strcmp(str1
,"zWrLeh") != 0 )
2076 level_string
= "B21";
2082 if (strcmp(level_string
,str2
) != 0)
2085 *rdata_len
= mdrcnt
+ 1024;
2086 *rdata
= SMB_REALLOC_LIMIT(*rdata
,*rdata_len
);
2090 SSVAL(*rparam
,0,NERR_Success
);
2091 SSVAL(*rparam
,2,0); /* converter word */
2095 mem_ctx
= talloc_new(NULL
);
2096 if (mem_ctx
== NULL
) {
2097 DEBUG(0, ("talloc_new failed\n"));
2101 if ( !(sampw
= samu_new(mem_ctx
)) ) {
2102 DEBUG(0, ("samu_new() failed!\n"));
2103 TALLOC_FREE(mem_ctx
);
2107 /* Lookup the user information; This should only be one of
2108 our accounts (not remote domains) */
2110 become_root(); /* ROOT BLOCK */
2112 if (!lookup_name(mem_ctx
, UserName
, LOOKUP_NAME_ALL
,
2113 NULL
, NULL
, &user_sid
, &type
)) {
2114 DEBUG(10, ("lookup_name(%s) failed\n", UserName
));
2118 if (type
!= SID_NAME_USER
) {
2119 DEBUG(10, ("%s is a %s, not a user\n", UserName
,
2120 sid_type_lookup(type
)));
2124 if ( !pdb_getsampwsid(sampw
, &user_sid
) ) {
2125 DEBUG(10, ("pdb_getsampwsid(%s) failed for user %s\n",
2126 sid_string_static(&user_sid
), UserName
));
2134 result
= pdb_enum_group_memberships(mem_ctx
, sampw
,
2135 &sids
, &gids
, &num_groups
);
2137 if (!NT_STATUS_IS_OK(result
)) {
2138 DEBUG(10, ("pdb_enum_group_memberships failed for %s\n",
2143 for (i
=0; i
<num_groups
; i
++) {
2145 const char *grp_name
;
2147 if ( lookup_sid(mem_ctx
, &sids
[i
], NULL
, &grp_name
, NULL
) ) {
2148 pstrcpy(p
, grp_name
);
2154 *rdata_len
= PTR_DIFF(p
,*rdata
);
2156 SSVAL(*rparam
,4,count
); /* is this right?? */
2157 SSVAL(*rparam
,6,count
); /* is this right?? */
2162 unbecome_root(); /* END ROOT BLOCK */
2164 TALLOC_FREE(mem_ctx
);
2169 /*******************************************************************
2171 ******************************************************************/
2173 static BOOL
api_RNetUserEnum(connection_struct
*conn
, uint16 vuid
,
2174 char *param
, int tpscnt
,
2175 char *data
, int tdscnt
,
2176 int mdrcnt
,int mprcnt
,
2177 char **rdata
,char **rparam
,
2178 int *rdata_len
,int *rparam_len
)
2183 int i
, resume_context
, cli_buf_size
;
2184 struct pdb_search
*search
;
2185 struct samr_displayentry
*users
;
2187 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2188 char *str2
= skip_string(param
,tpscnt
,str1
,1);
2189 char *p
= skip_string(param
,tpscnt
,str2
,1);
2191 if (!str1
|| !str2
|| !p
) {
2195 if (strcmp(str1
,"WrLeh") != 0)
2198 * W-> resume context (number of users to skip)
2199 * r -> return parameter pointer to receive buffer
2200 * L -> length of receive buffer
2201 * e -> return parameter number of entries
2202 * h -> return parameter total number of users
2205 resume_context
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2206 cli_buf_size
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
2207 DEBUG(10,("api_RNetUserEnum:resume context: %d, client buffer size: %d\n",
2208 resume_context
, cli_buf_size
));
2211 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
2216 /* check it's a supported varient */
2217 if (strcmp("B21",str2
) != 0)
2220 *rdata_len
= cli_buf_size
;
2221 *rdata
= SMB_REALLOC_LIMIT(*rdata
,*rdata_len
);
2229 search
= pdb_search_users(ACB_NORMAL
);
2231 if (search
== NULL
) {
2232 DEBUG(0, ("api_RNetUserEnum:unable to open sam database.\n"));
2237 num_users
= pdb_search_entries(search
, resume_context
, 0xffffffff,
2241 errflags
=NERR_Success
;
2243 for (i
=0; i
<num_users
; i
++) {
2244 const char *name
= users
[i
].account_name
;
2246 if(((PTR_DIFF(p
,*rdata
)+21)<=*rdata_len
)&&(strlen(name
)<=21)) {
2248 DEBUG(10,("api_RNetUserEnum:adding entry %d username "
2249 "%s\n",count_sent
,p
));
2253 /* set overflow error */
2254 DEBUG(10,("api_RNetUserEnum:overflow on entry %d "
2255 "username %s\n",count_sent
,name
));
2261 pdb_search_destroy(search
);
2263 *rdata_len
= PTR_DIFF(p
,*rdata
);
2265 SSVAL(*rparam
,0,errflags
);
2266 SSVAL(*rparam
,2,0); /* converter word */
2267 SSVAL(*rparam
,4,count_sent
); /* is this right?? */
2268 SSVAL(*rparam
,6,num_users
); /* is this right?? */
2273 /****************************************************************************
2274 Get the time of day info.
2275 ****************************************************************************/
2277 static BOOL
api_NetRemoteTOD(connection_struct
*conn
,uint16 vuid
,
2278 char *param
, int tpscnt
,
2279 char *data
, int tdscnt
,
2280 int mdrcnt
,int mprcnt
,
2281 char **rdata
,char **rparam
,
2282 int *rdata_len
,int *rparam_len
)
2285 time_t unixdate
= time(NULL
);
2289 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
2295 *rdata
= SMB_REALLOC_LIMIT(*rdata
,*rdata_len
);
2300 SSVAL(*rparam
,0,NERR_Success
);
2301 SSVAL(*rparam
,2,0); /* converter word */
2305 srv_put_dos_date3(p
,0,unixdate
); /* this is the time that is looked at
2306 by NT in a "net time" operation,
2307 it seems to ignore the one below */
2309 /* the client expects to get localtime, not GMT, in this bit
2310 (I think, this needs testing) */
2311 t
= localtime(&unixdate
);
2316 SIVAL(p
,4,0); /* msecs ? */
2317 SCVAL(p
,8,t
->tm_hour
);
2318 SCVAL(p
,9,t
->tm_min
);
2319 SCVAL(p
,10,t
->tm_sec
);
2320 SCVAL(p
,11,0); /* hundredths of seconds */
2321 SSVALS(p
,12,get_time_zone(unixdate
)/60); /* timezone in minutes from GMT */
2322 SSVAL(p
,14,10000); /* timer interval in 0.0001 of sec */
2323 SCVAL(p
,16,t
->tm_mday
);
2324 SCVAL(p
,17,t
->tm_mon
+ 1);
2325 SSVAL(p
,18,1900+t
->tm_year
);
2326 SCVAL(p
,20,t
->tm_wday
);
2331 /****************************************************************************
2332 Set the user password.
2333 *****************************************************************************/
2335 static BOOL
api_SetUserPassword(connection_struct
*conn
,uint16 vuid
,
2336 char *param
, int tpscnt
,
2337 char *data
, int tdscnt
,
2338 int mdrcnt
,int mprcnt
,
2339 char **rdata
,char **rparam
,
2340 int *rdata_len
,int *rparam_len
)
2342 char *np
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2343 char *p
= skip_string(param
,tpscnt
,skip_string(param
,tpscnt
,np
,1),1);
2345 fstring pass1
,pass2
;
2351 /* Do we have a string ? */
2352 if (skip_string(param
,tpscnt
,p
,1) == NULL
) {
2355 pull_ascii_fstring(user
,p
);
2357 p
= skip_string(param
,tpscnt
,p
,1);
2362 memset(pass1
,'\0',sizeof(pass1
));
2363 memset(pass2
,'\0',sizeof(pass2
));
2364 if (!is_offset_safe(param
,tpscnt
,p
,32)) {
2368 memcpy(pass2
,p
+16,16);
2371 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
2378 SSVAL(*rparam
,0,NERR_badpass
);
2379 SSVAL(*rparam
,2,0); /* converter word */
2381 DEBUG(3,("Set password for <%s>\n",user
));
2384 * Attempt to verify the old password against smbpasswd entries
2385 * Win98 clients send old and new password in plaintext for this call.
2389 auth_serversupplied_info
*server_info
= NULL
;
2390 DATA_BLOB password
= data_blob(pass1
, strlen(pass1
)+1);
2392 if (NT_STATUS_IS_OK(check_plaintext_password(user
,password
,&server_info
))) {
2395 if (NT_STATUS_IS_OK(change_oem_password(server_info
->sam_account
, pass1
, pass2
, False
, NULL
))) {
2396 SSVAL(*rparam
,0,NERR_Success
);
2400 TALLOC_FREE(server_info
);
2402 data_blob_clear_free(&password
);
2406 * If the plaintext change failed, attempt
2407 * the old encrypted method. NT will generate this
2408 * after trying the samr method. Note that this
2409 * method is done as a last resort as this
2410 * password change method loses the NT password hash
2411 * and cannot change the UNIX password as no plaintext
2415 if(SVAL(*rparam
,0) != NERR_Success
) {
2416 struct samu
*hnd
= NULL
;
2418 if (check_lanman_password(user
,(unsigned char *)pass1
,(unsigned char *)pass2
, &hnd
)) {
2420 if (change_lanman_password(hnd
,(uchar
*)pass2
)) {
2421 SSVAL(*rparam
,0,NERR_Success
);
2428 memset((char *)pass1
,'\0',sizeof(fstring
));
2429 memset((char *)pass2
,'\0',sizeof(fstring
));
2434 /****************************************************************************
2435 Set the user password (SamOEM version - gets plaintext).
2436 ****************************************************************************/
2438 static BOOL
api_SamOEMChangePassword(connection_struct
*conn
,uint16 vuid
,
2439 char *param
, int tpscnt
,
2440 char *data
, int tdscnt
,
2441 int mdrcnt
,int mprcnt
,
2442 char **rdata
,char **rparam
,
2443 int *rdata_len
,int *rparam_len
)
2446 char *p
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2448 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
2458 SSVAL(*rparam
,0,NERR_badpass
);
2461 * Check the parameter definition is correct.
2464 /* Do we have a string ? */
2465 if (skip_string(param
,tpscnt
,p
,1) == 0) {
2468 if(!strequal(p
, "zsT")) {
2469 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", p
));
2472 p
= skip_string(param
, tpscnt
, p
, 1);
2477 /* Do we have a string ? */
2478 if (skip_string(param
,tpscnt
,p
,1) == 0) {
2481 if(!strequal(p
, "B516B16")) {
2482 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p
));
2485 p
= skip_string(param
,tpscnt
,p
,1);
2489 /* Do we have a string ? */
2490 if (skip_string(param
,tpscnt
,p
,1) == 0) {
2493 p
+= pull_ascii_fstring(user
,p
);
2495 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user
));
2498 * Pass the user through the NT -> unix user mapping
2502 (void)map_username(user
);
2504 if (NT_STATUS_IS_OK(pass_oem_change(user
, (uchar
*) data
, (uchar
*)&data
[516], NULL
, NULL
, NULL
))) {
2505 SSVAL(*rparam
,0,NERR_Success
);
2511 /****************************************************************************
2514 ****************************************************************************/
2516 static BOOL
api_RDosPrintJobDel(connection_struct
*conn
,uint16 vuid
,
2517 char *param
, int tpscnt
,
2518 char *data
, int tdscnt
,
2519 int mdrcnt
,int mprcnt
,
2520 char **rdata
,char **rparam
,
2521 int *rdata_len
,int *rparam_len
)
2523 int function
= get_safe_SVAL(param
,tpscnt
,param
,0,0);
2524 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2525 char *str2
= skip_string(param
,tpscnt
,str1
,1);
2526 char *p
= skip_string(param
,tpscnt
,str2
,1);
2531 WERROR werr
= WERR_OK
;
2533 if (!str1
|| !str2
|| !p
) {
2536 if (!is_offset_safe(param
,tpscnt
,p
,2)) {
2539 if(!rap_to_pjobid(SVAL(p
,0), sharename
, &jobid
))
2542 /* check it's a supported varient */
2543 if (!(strcsequal(str1
,"W") && strcsequal(str2
,"")))
2547 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
2553 if (!print_job_exists(sharename
, jobid
)) {
2554 errcode
= NERR_JobNotFound
;
2558 snum
= lp_servicenumber( sharename
);
2560 errcode
= NERR_DestNotFound
;
2564 errcode
= NERR_notsupported
;
2567 case 81: /* delete */
2568 if (print_job_delete(¤t_user
, snum
, jobid
, &werr
))
2569 errcode
= NERR_Success
;
2571 case 82: /* pause */
2572 if (print_job_pause(¤t_user
, snum
, jobid
, &werr
))
2573 errcode
= NERR_Success
;
2575 case 83: /* resume */
2576 if (print_job_resume(¤t_user
, snum
, jobid
, &werr
))
2577 errcode
= NERR_Success
;
2581 if (!W_ERROR_IS_OK(werr
))
2582 errcode
= W_ERROR_V(werr
);
2585 SSVAL(*rparam
,0,errcode
);
2586 SSVAL(*rparam
,2,0); /* converter word */
2591 /****************************************************************************
2592 Purge a print queue - or pause or resume it.
2593 ****************************************************************************/
2595 static BOOL
api_WPrintQueueCtrl(connection_struct
*conn
,uint16 vuid
,
2596 char *param
, int tpscnt
,
2597 char *data
, int tdscnt
,
2598 int mdrcnt
,int mprcnt
,
2599 char **rdata
,char **rparam
,
2600 int *rdata_len
,int *rparam_len
)
2602 int function
= get_safe_SVAL(param
,tpscnt
,param
,0,0);
2603 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2604 char *str2
= skip_string(param
,tpscnt
,str1
,1);
2605 char *QueueName
= skip_string(param
,tpscnt
,str2
,1);
2606 int errcode
= NERR_notsupported
;
2608 WERROR werr
= WERR_OK
;
2610 if (!str1
|| !str2
|| !QueueName
) {
2614 /* check it's a supported varient */
2615 if (!(strcsequal(str1
,"z") && strcsequal(str2
,"")))
2619 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
2625 if (skip_string(param
,tpscnt
,QueueName
,1) == NULL
) {
2628 snum
= print_queue_snum(QueueName
);
2631 errcode
= NERR_JobNotFound
;
2636 case 74: /* Pause queue */
2637 if (print_queue_pause(¤t_user
, snum
, &werr
)) errcode
= NERR_Success
;
2639 case 75: /* Resume queue */
2640 if (print_queue_resume(¤t_user
, snum
, &werr
)) errcode
= NERR_Success
;
2642 case 103: /* Purge */
2643 if (print_queue_purge(¤t_user
, snum
, &werr
)) errcode
= NERR_Success
;
2647 if (!W_ERROR_IS_OK(werr
)) errcode
= W_ERROR_V(werr
);
2650 SSVAL(*rparam
,0,errcode
);
2651 SSVAL(*rparam
,2,0); /* converter word */
2656 /****************************************************************************
2657 set the property of a print job (undocumented?)
2658 ? function = 0xb -> set name of print job
2659 ? function = 0x6 -> move print job up/down
2660 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
2661 or <WWsTP> <WB21BB16B10zWWzDDz>
2662 ****************************************************************************/
2664 static int check_printjob_info(struct pack_desc
* desc
,
2665 int uLevel
, char* id
)
2667 desc
->subformat
= NULL
;
2669 case 0: desc
->format
= "W"; break;
2670 case 1: desc
->format
= "WB21BB16B10zWWzDDz"; break;
2671 case 2: desc
->format
= "WWzWWDDzz"; break;
2672 case 3: desc
->format
= "WWzWWDDzzzzzzzzzzlz"; break;
2673 case 4: desc
->format
= "WWzWWDDzzzzzDDDDDDD"; break;
2674 default: return False
;
2676 if (strcmp(desc
->format
,id
) != 0) return False
;
2680 static BOOL
api_PrintJobInfo(connection_struct
*conn
, uint16 vuid
,
2681 char *param
, int tpscnt
,
2682 char *data
, int tdscnt
,
2683 int mdrcnt
,int mprcnt
,
2684 char **rdata
,char **rparam
,
2685 int *rdata_len
,int *rparam_len
)
2687 struct pack_desc desc
;
2688 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2689 char *str2
= skip_string(param
,tpscnt
,str1
,1);
2690 char *p
= skip_string(param
,tpscnt
,str2
,1);
2693 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,2,-1);
2694 int function
= get_safe_SVAL(param
,tpscnt
,p
,4,-1);
2697 if (!str1
|| !str2
|| !p
) {
2700 if (!is_offset_safe(param
,tpscnt
,p
,2)) {
2703 if(!rap_to_pjobid(SVAL(p
,0), sharename
, &jobid
))
2706 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
2711 if (!share_defined(sharename
)) {
2712 DEBUG(0,("api_PrintJobInfo: sharen [%s] not defined\n",
2719 /* check it's a supported varient */
2720 if ((strcmp(str1
,"WWsTP")) ||
2721 (!check_printjob_info(&desc
,uLevel
,str2
)))
2724 if (!print_job_exists(sharename
, jobid
)) {
2725 errcode
=NERR_JobNotFound
;
2729 errcode
= NERR_notsupported
;
2733 /* change job place in the queue,
2734 data gives the new place */
2735 place
= SVAL(data
,0);
2736 if (print_job_set_place(sharename
, jobid
, place
)) {
2737 errcode
=NERR_Success
;
2742 /* change print job name, data gives the name */
2743 if (print_job_set_name(sharename
, jobid
, data
)) {
2744 errcode
=NERR_Success
;
2753 SSVALS(*rparam
,0,errcode
);
2754 SSVAL(*rparam
,2,0); /* converter word */
2760 /****************************************************************************
2761 Get info about the server.
2762 ****************************************************************************/
2764 static BOOL
api_RNetServerGetInfo(connection_struct
*conn
,uint16 vuid
,
2765 char *param
, int tpscnt
,
2766 char *data
, int tdscnt
,
2767 int mdrcnt
,int mprcnt
,
2768 char **rdata
,char **rparam
,
2769 int *rdata_len
,int *rparam_len
)
2771 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2772 char *str2
= skip_string(param
,tpscnt
,str1
,1);
2773 char *p
= skip_string(param
,tpscnt
,str2
,1);
2774 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2778 if (!str1
|| !str2
|| !p
) {
2782 DEBUG(4,("NetServerGetInfo level %d\n",uLevel
));
2784 /* check it's a supported varient */
2785 if (!prefix_ok(str1
,"WrLh")) {
2791 if (strcmp(str2
,"B16") != 0) {
2797 if (strcmp(str2
,"B16BBDz") != 0) {
2803 if (strcmp(str2
,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")!= 0) {
2809 if (strcmp(str2
,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz") != 0) {
2815 if (strcmp(str2
,"DN") != 0) {
2821 if (strcmp(str2
,"B16BBDzWWzzz") != 0) {
2830 *rdata_len
= mdrcnt
;
2831 *rdata
= SMB_REALLOC_LIMIT(*rdata
,*rdata_len
);
2837 p2
= p
+ struct_len
;
2839 srvstr_push(NULL
, p
,global_myname(),16,
2840 STR_ASCII
|STR_UPPER
|STR_TERMINATE
);
2844 struct srv_info_struct
*servers
=NULL
;
2847 uint32 servertype
= lp_default_server_announce();
2849 push_ascii(comment
,lp_serverstring(), MAX_SERVER_STRING_LENGTH
,STR_TERMINATE
);
2851 if ((count
=get_server_info(SV_TYPE_ALL
,&servers
,lp_workgroup()))>0) {
2852 for (i
=0;i
<count
;i
++) {
2853 if (strequal(servers
[i
].name
,global_myname())) {
2854 servertype
= servers
[i
].type
;
2855 push_ascii(comment
,servers
[i
].comment
,sizeof(pstring
),STR_TERMINATE
);
2862 SCVAL(p
,0,lp_major_announce_version());
2863 SCVAL(p
,1,lp_minor_announce_version());
2864 SIVAL(p
,2,servertype
);
2866 if (mdrcnt
== struct_len
) {
2869 SIVAL(p
,6,PTR_DIFF(p2
,*rdata
));
2870 standard_sub_advanced(lp_servicename(SNUM(conn
)), conn
->user
,
2871 conn
->connectpath
, conn
->gid
,
2872 get_current_username(),
2873 current_user_info
.domain
,
2874 comment
, sizeof(comment
));
2875 StrnCpy(p2
,comment
,MAX(mdrcnt
- struct_len
,0));
2876 p2
= skip_string(*rdata
,*rdata_len
,p2
,1);
2884 return False
; /* not yet implemented */
2887 *rdata_len
= PTR_DIFF(p2
,*rdata
);
2890 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
2894 SSVAL(*rparam
,0,NERR_Success
);
2895 SSVAL(*rparam
,2,0); /* converter word */
2896 SSVAL(*rparam
,4,*rdata_len
);
2901 /****************************************************************************
2902 Get info about the server.
2903 ****************************************************************************/
2905 static BOOL
api_NetWkstaGetInfo(connection_struct
*conn
,uint16 vuid
,
2906 char *param
, int tpscnt
,
2907 char *data
, int tdscnt
,
2908 int mdrcnt
,int mprcnt
,
2909 char **rdata
,char **rparam
,
2910 int *rdata_len
,int *rparam_len
)
2912 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2913 char *str2
= skip_string(param
,tpscnt
,str1
,1);
2914 char *p
= skip_string(param
,tpscnt
,str2
,1);
2916 int level
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2918 if (!str1
|| !str2
|| !p
) {
2922 DEBUG(4,("NetWkstaGetInfo level %d\n",level
));
2925 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
2930 /* check it's a supported varient */
2931 if (!(level
==10 && strcsequal(str1
,"WrLh") && strcsequal(str2
,"zzzBBzz"))) {
2935 *rdata_len
= mdrcnt
+ 1024;
2936 *rdata
= SMB_REALLOC_LIMIT(*rdata
,*rdata_len
);
2941 SSVAL(*rparam
,0,NERR_Success
);
2942 SSVAL(*rparam
,2,0); /* converter word */
2945 p2
= get_safe_ptr(*rdata
,*rdata_len
,p
,22);
2950 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* host name */
2951 pstrcpy(p2
,get_local_machine_name());
2953 p2
= skip_string(*rdata
,*rdata_len
,p2
,1);
2959 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
));
2960 pstrcpy(p2
,current_user_info
.smb_name
);
2961 p2
= skip_string(*rdata
,*rdata_len
,p2
,1);
2967 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* login domain */
2968 pstrcpy(p2
,lp_workgroup());
2970 p2
= skip_string(*rdata
,*rdata_len
,p2
,1);
2976 SCVAL(p
,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
2977 SCVAL(p
,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
2980 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
));
2981 pstrcpy(p2
,lp_workgroup()); /* don't know. login domain?? */
2982 p2
= skip_string(*rdata
,*rdata_len
,p2
,1);
2988 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* don't know */
2990 p2
= skip_string(*rdata
,*rdata_len
,p2
,1);
2996 *rdata_len
= PTR_DIFF(p2
,*rdata
);
2998 SSVAL(*rparam
,4,*rdata_len
);
3003 /****************************************************************************
3004 get info about a user
3006 struct user_info_11 {
3007 char usri11_name[21]; 0-20
3009 char *usri11_comment; 22-25
3010 char *usri11_usr_comment; 26-29
3011 unsigned short usri11_priv; 30-31
3012 unsigned long usri11_auth_flags; 32-35
3013 long usri11_password_age; 36-39
3014 char *usri11_homedir; 40-43
3015 char *usri11_parms; 44-47
3016 long usri11_last_logon; 48-51
3017 long usri11_last_logoff; 52-55
3018 unsigned short usri11_bad_pw_count; 56-57
3019 unsigned short usri11_num_logons; 58-59
3020 char *usri11_logon_server; 60-63
3021 unsigned short usri11_country_code; 64-65
3022 char *usri11_workstations; 66-69
3023 unsigned long usri11_max_storage; 70-73
3024 unsigned short usri11_units_per_week; 74-75
3025 unsigned char *usri11_logon_hours; 76-79
3026 unsigned short usri11_code_page; 80-81
3031 usri11_name specifies the user name for which information is retireved
3033 usri11_pad aligns the next data structure element to a word boundary
3035 usri11_comment is a null terminated ASCII comment
3037 usri11_user_comment is a null terminated ASCII comment about the user
3039 usri11_priv specifies the level of the privilege assigned to the user.
3040 The possible values are:
3042 Name Value Description
3043 USER_PRIV_GUEST 0 Guest privilege
3044 USER_PRIV_USER 1 User privilege
3045 USER_PRV_ADMIN 2 Administrator privilege
3047 usri11_auth_flags specifies the account operator privileges. The
3048 possible values are:
3050 Name Value Description
3051 AF_OP_PRINT 0 Print operator
3054 Leach, Naik [Page 28]
3058 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
3061 AF_OP_COMM 1 Communications operator
3062 AF_OP_SERVER 2 Server operator
3063 AF_OP_ACCOUNTS 3 Accounts operator
3066 usri11_password_age specifies how many seconds have elapsed since the
3067 password was last changed.
3069 usri11_home_dir points to a null terminated ASCII string that contains
3070 the path name of the user's home directory.
3072 usri11_parms points to a null terminated ASCII string that is set
3073 aside for use by applications.
3075 usri11_last_logon specifies the time when the user last logged on.
3076 This value is stored as the number of seconds elapsed since
3077 00:00:00, January 1, 1970.
3079 usri11_last_logoff specifies the time when the user last logged off.
3080 This value is stored as the number of seconds elapsed since
3081 00:00:00, January 1, 1970. A value of 0 means the last logoff
3084 usri11_bad_pw_count specifies the number of incorrect passwords
3085 entered since the last successful logon.
3087 usri11_log1_num_logons specifies the number of times this user has
3088 logged on. A value of -1 means the number of logons is unknown.
3090 usri11_logon_server points to a null terminated ASCII string that
3091 contains the name of the server to which logon requests are sent.
3092 A null string indicates logon requests should be sent to the
3095 usri11_country_code specifies the country code for the user's language
3098 usri11_workstations points to a null terminated ASCII string that
3099 contains the names of workstations the user may log on from.
3100 There may be up to 8 workstations, with the names separated by
3101 commas. A null strings indicates there are no restrictions.
3103 usri11_max_storage specifies the maximum amount of disk space the user
3104 can occupy. A value of 0xffffffff indicates there are no
3107 usri11_units_per_week specifies the equal number of time units into
3108 which a week is divided. This value must be equal to 168.
3110 usri11_logon_hours points to a 21 byte (168 bits) string that
3111 specifies the time during which the user can log on. Each bit
3112 represents one unique hour in a week. The first bit (bit 0, word
3113 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
3117 Leach, Naik [Page 29]
3121 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
3124 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
3125 are no restrictions.
3127 usri11_code_page specifies the code page for the user's language of
3130 All of the pointers in this data structure need to be treated
3131 specially. The pointer is a 32 bit pointer. The higher 16 bits need
3132 to be ignored. The converter word returned in the parameters section
3133 needs to be subtracted from the lower 16 bits to calculate an offset
3134 into the return buffer where this ASCII string resides.
3136 There is no auxiliary data in the response.
3138 ****************************************************************************/
3140 #define usri11_name 0
3141 #define usri11_pad 21
3142 #define usri11_comment 22
3143 #define usri11_usr_comment 26
3144 #define usri11_full_name 30
3145 #define usri11_priv 34
3146 #define usri11_auth_flags 36
3147 #define usri11_password_age 40
3148 #define usri11_homedir 44
3149 #define usri11_parms 48
3150 #define usri11_last_logon 52
3151 #define usri11_last_logoff 56
3152 #define usri11_bad_pw_count 60
3153 #define usri11_num_logons 62
3154 #define usri11_logon_server 64
3155 #define usri11_country_code 68
3156 #define usri11_workstations 70
3157 #define usri11_max_storage 74
3158 #define usri11_units_per_week 78
3159 #define usri11_logon_hours 80
3160 #define usri11_code_page 84
3161 #define usri11_end 86
3163 #define USER_PRIV_GUEST 0
3164 #define USER_PRIV_USER 1
3165 #define USER_PRIV_ADMIN 2
3167 #define AF_OP_PRINT 0
3168 #define AF_OP_COMM 1
3169 #define AF_OP_SERVER 2
3170 #define AF_OP_ACCOUNTS 3
3173 static BOOL
api_RNetUserGetInfo(connection_struct
*conn
, uint16 vuid
,
3174 char *param
, int tpscnt
,
3175 char *data
, int tdscnt
,
3176 int mdrcnt
,int mprcnt
,
3177 char **rdata
,char **rparam
,
3178 int *rdata_len
,int *rparam_len
)
3180 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3181 char *str2
= skip_string(param
,tpscnt
,str1
,1);
3182 char *UserName
= skip_string(param
,tpscnt
,str2
,1);
3183 char *p
= skip_string(param
,tpscnt
,UserName
,1);
3184 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3186 const char *level_string
;
3188 /* get NIS home of a previously validated user - simeon */
3189 /* With share level security vuid will always be zero.
3190 Don't depend on vuser being non-null !!. JRA */
3191 user_struct
*vuser
= get_valid_user_struct(vuid
);
3193 DEBUG(3,(" Username of UID %d is %s\n", (int)vuser
->uid
,
3194 vuser
->user
.unix_name
));
3197 if (!str1
|| !str2
|| !UserName
|| !p
) {
3202 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
3207 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel
));
3209 /* check it's a supported variant */
3210 if (strcmp(str1
,"zWrLh") != 0) {
3214 case 0: level_string
= "B21"; break;
3215 case 1: level_string
= "B21BB16DWzzWz"; break;
3216 case 2: level_string
= "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
3217 case 10: level_string
= "B21Bzzz"; break;
3218 case 11: level_string
= "B21BzzzWDDzzDDWWzWzDWb21W"; break;
3219 default: return False
;
3222 if (strcmp(level_string
,str2
) != 0) {
3226 *rdata_len
= mdrcnt
+ 1024;
3227 *rdata
= SMB_REALLOC_LIMIT(*rdata
,*rdata_len
);
3232 SSVAL(*rparam
,0,NERR_Success
);
3233 SSVAL(*rparam
,2,0); /* converter word */
3236 p2
= get_safe_ptr(*rdata
,*rdata_len
,p
,usri11_end
);
3242 fstrcpy(p
+usri11_name
,UserName
); /* 21 bytes - user name */
3245 SCVAL(p
,usri11_pad
,0); /* padding - 1 byte */
3250 SIVAL(p
,usri11_comment
,PTR_DIFF(p2
,p
)); /* comment */
3251 pstrcpy(p2
,"Comment");
3252 p2
= skip_string(*rdata
,*rdata_len
,p2
,1);
3257 SIVAL(p
,usri11_usr_comment
,PTR_DIFF(p2
,p
)); /* user_comment */
3258 pstrcpy(p2
,"UserComment");
3259 p2
= skip_string(*rdata
,*rdata_len
,p2
,1);
3264 /* EEK! the cifsrap.txt doesn't have this in!!!! */
3265 SIVAL(p
,usri11_full_name
,PTR_DIFF(p2
,p
)); /* full name */
3266 pstrcpy(p2
,((vuser
!= NULL
) ? vuser
->user
.full_name
: UserName
));
3267 p2
= skip_string(*rdata
,*rdata_len
,p2
,1);
3274 /* modelled after NTAS 3.51 reply */
3275 SSVAL(p
,usri11_priv
,conn
->admin_user
?USER_PRIV_ADMIN
:USER_PRIV_USER
);
3276 SIVAL(p
,usri11_auth_flags
,AF_OP_PRINT
); /* auth flags */
3277 SIVALS(p
,usri11_password_age
,-1); /* password age */
3278 SIVAL(p
,usri11_homedir
,PTR_DIFF(p2
,p
)); /* home dir */
3279 pstrcpy(p2
, vuser
&& vuser
->homedir
? vuser
->homedir
: "");
3280 p2
= skip_string(*rdata
,*rdata_len
,p2
,1);
3284 SIVAL(p
,usri11_parms
,PTR_DIFF(p2
,p
)); /* parms */
3286 p2
= skip_string(*rdata
,*rdata_len
,p2
,1);
3290 SIVAL(p
,usri11_last_logon
,0); /* last logon */
3291 SIVAL(p
,usri11_last_logoff
,0); /* last logoff */
3292 SSVALS(p
,usri11_bad_pw_count
,-1); /* bad pw counts */
3293 SSVALS(p
,usri11_num_logons
,-1); /* num logons */
3294 SIVAL(p
,usri11_logon_server
,PTR_DIFF(p2
,p
)); /* logon server */
3295 pstrcpy(p2
,"\\\\*");
3296 p2
= skip_string(*rdata
,*rdata_len
,p2
,1);
3300 SSVAL(p
,usri11_country_code
,0); /* country code */
3302 SIVAL(p
,usri11_workstations
,PTR_DIFF(p2
,p
)); /* workstations */
3304 p2
= skip_string(*rdata
,*rdata_len
,p2
,1);
3309 SIVALS(p
,usri11_max_storage
,-1); /* max storage */
3310 SSVAL(p
,usri11_units_per_week
,168); /* units per week */
3311 SIVAL(p
,usri11_logon_hours
,PTR_DIFF(p2
,p
)); /* logon hours */
3313 /* a simple way to get logon hours at all times. */
3315 SCVAL(p2
,21,0); /* fix zero termination */
3316 p2
= skip_string(*rdata
,*rdata_len
,p2
,1);
3321 SSVAL(p
,usri11_code_page
,0); /* code page */
3324 if (uLevel
== 1 || uLevel
== 2) {
3325 memset(p
+22,' ',16); /* password */
3326 SIVALS(p
,38,-1); /* password age */
3328 conn
->admin_user
?USER_PRIV_ADMIN
:USER_PRIV_USER
);
3329 SIVAL(p
,44,PTR_DIFF(p2
,*rdata
)); /* home dir */
3330 pstrcpy(p2
, vuser
&& vuser
->homedir
? vuser
->homedir
: "");
3331 p2
= skip_string(*rdata
,*rdata_len
,p2
,1);
3335 SIVAL(p
,48,PTR_DIFF(p2
,*rdata
)); /* comment */
3337 SSVAL(p
,52,0); /* flags */
3338 SIVAL(p
,54,PTR_DIFF(p2
,*rdata
)); /* script_path */
3339 pstrcpy(p2
,vuser
&& vuser
->logon_script
? vuser
->logon_script
: "");
3340 p2
= skip_string(*rdata
,*rdata_len
,p2
,1);
3345 SIVAL(p
,60,0); /* auth_flags */
3346 SIVAL(p
,64,PTR_DIFF(p2
,*rdata
)); /* full_name */
3347 pstrcpy(p2
,((vuser
!= NULL
) ? vuser
->user
.full_name
: UserName
));
3348 p2
= skip_string(*rdata
,*rdata_len
,p2
,1);
3352 SIVAL(p
,68,0); /* urs_comment */
3353 SIVAL(p
,72,PTR_DIFF(p2
,*rdata
)); /* parms */
3355 p2
= skip_string(*rdata
,*rdata_len
,p2
,1);
3359 SIVAL(p
,76,0); /* workstations */
3360 SIVAL(p
,80,0); /* last_logon */
3361 SIVAL(p
,84,0); /* last_logoff */
3362 SIVALS(p
,88,-1); /* acct_expires */
3363 SIVALS(p
,92,-1); /* max_storage */
3364 SSVAL(p
,96,168); /* units_per_week */
3365 SIVAL(p
,98,PTR_DIFF(p2
,*rdata
)); /* logon_hours */
3368 SSVALS(p
,102,-1); /* bad_pw_count */
3369 SSVALS(p
,104,-1); /* num_logons */
3370 SIVAL(p
,106,PTR_DIFF(p2
,*rdata
)); /* logon_server */
3373 pstrcpy(tmp
, "\\\\%L");
3374 standard_sub_basic("", "", tmp
, sizeof(tmp
));
3377 p2
= skip_string(*rdata
,*rdata_len
,p2
,1);
3381 SSVAL(p
,110,49); /* country_code */
3382 SSVAL(p
,112,860); /* code page */
3386 *rdata_len
= PTR_DIFF(p2
,*rdata
);
3388 SSVAL(*rparam
,4,*rdata_len
); /* is this right?? */
3393 static BOOL
api_WWkstaUserLogon(connection_struct
*conn
,uint16 vuid
,
3394 char *param
, int tpscnt
,
3395 char *data
, int tdscnt
,
3396 int mdrcnt
,int mprcnt
,
3397 char **rdata
,char **rparam
,
3398 int *rdata_len
,int *rparam_len
)
3400 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3401 char *str2
= skip_string(param
,tpscnt
,str1
,1);
3402 char *p
= skip_string(param
,tpscnt
,str2
,1);
3404 struct pack_desc desc
;
3406 /* With share level security vuid will always be zero.
3407 Don't depend on vuser being non-null !!. JRA */
3408 user_struct
*vuser
= get_valid_user_struct(vuid
);
3410 if (!str1
|| !str2
|| !p
) {
3415 DEBUG(3,(" Username of UID %d is %s\n", (int)vuser
->uid
,
3416 vuser
->user
.unix_name
));
3419 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3420 name
= get_safe_str_ptr(param
,tpscnt
,p
,2);
3425 memset((char *)&desc
,'\0',sizeof(desc
));
3427 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel
,name
));
3429 /* check it's a supported varient */
3430 if (strcmp(str1
,"OOWb54WrLh") != 0) {
3433 if (uLevel
!= 1 || strcmp(str2
,"WB21BWDWWDDDDDDDzzzD") != 0) {
3437 *rdata
= SMB_REALLOC_LIMIT(*rdata
,mdrcnt
);
3444 desc
.buflen
= mdrcnt
;
3445 desc
.subformat
= NULL
;
3448 if (init_package(&desc
,1,0)) {
3449 PACKI(&desc
,"W",0); /* code */
3450 PACKS(&desc
,"B21",name
); /* eff. name */
3451 PACKS(&desc
,"B",""); /* pad */
3452 PACKI(&desc
,"W", conn
->admin_user
?USER_PRIV_ADMIN
:USER_PRIV_USER
);
3453 PACKI(&desc
,"D",0); /* auth flags XXX */
3454 PACKI(&desc
,"W",0); /* num logons */
3455 PACKI(&desc
,"W",0); /* bad pw count */
3456 PACKI(&desc
,"D",0); /* last logon */
3457 PACKI(&desc
,"D",-1); /* last logoff */
3458 PACKI(&desc
,"D",-1); /* logoff time */
3459 PACKI(&desc
,"D",-1); /* kickoff time */
3460 PACKI(&desc
,"D",0); /* password age */
3461 PACKI(&desc
,"D",0); /* password can change */
3462 PACKI(&desc
,"D",-1); /* password must change */
3466 fstrcpy(mypath
,"\\\\");
3467 fstrcat(mypath
,get_local_machine_name());
3469 PACKS(&desc
,"z",mypath
); /* computer */
3472 PACKS(&desc
,"z",lp_workgroup());/* domain */
3473 PACKS(&desc
,"z", vuser
&& vuser
->logon_script
? vuser
->logon_script
:""); /* script path */
3474 PACKI(&desc
,"D",0x00000000); /* reserved */
3477 *rdata_len
= desc
.usedlen
;
3479 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
3483 SSVALS(*rparam
,0,desc
.errcode
);
3485 SSVAL(*rparam
,4,desc
.neededlen
);
3487 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc
.errcode
));
3492 /****************************************************************************
3493 api_WAccessGetUserPerms
3494 ****************************************************************************/
3496 static BOOL
api_WAccessGetUserPerms(connection_struct
*conn
,uint16 vuid
,
3497 char *param
, int tpscnt
,
3498 char *data
, int tdscnt
,
3499 int mdrcnt
,int mprcnt
,
3500 char **rdata
,char **rparam
,
3501 int *rdata_len
,int *rparam_len
)
3503 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3504 char *str2
= skip_string(param
,tpscnt
,str1
,1);
3505 char *user
= skip_string(param
,tpscnt
,str2
,1);
3506 char *resource
= skip_string(param
,tpscnt
,user
,1);
3508 if (!str1
|| !str2
|| !user
|| !resource
) {
3512 if (skip_string(param
,tpscnt
,resource
,1) == NULL
) {
3515 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user
,resource
));
3517 /* check it's a supported varient */
3518 if (strcmp(str1
,"zzh") != 0) {
3521 if (strcmp(str2
,"") != 0) {
3526 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
3530 SSVALS(*rparam
,0,0); /* errorcode */
3531 SSVAL(*rparam
,2,0); /* converter word */
3532 SSVAL(*rparam
,4,0x7f); /* permission flags */
3537 /****************************************************************************
3538 api_WPrintJobEnumerate
3539 ****************************************************************************/
3541 static BOOL
api_WPrintJobGetInfo(connection_struct
*conn
, uint16 vuid
,
3542 char *param
, int tpscnt
,
3543 char *data
, int tdscnt
,
3544 int mdrcnt
,int mprcnt
,
3545 char **rdata
,char **rparam
,
3546 int *rdata_len
,int *rparam_len
)
3548 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3549 char *str2
= skip_string(param
,tpscnt
,str1
,1);
3550 char *p
= skip_string(param
,tpscnt
,str2
,1);
3557 struct pack_desc desc
;
3558 print_queue_struct
*queue
=NULL
;
3559 print_status_struct status
;
3562 if (!str1
|| !str2
|| !p
) {
3566 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,2,-1);
3568 memset((char *)&desc
,'\0',sizeof(desc
));
3569 memset((char *)&status
,'\0',sizeof(status
));
3571 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel
,SVAL(p
,0)));
3573 /* check it's a supported varient */
3574 if (strcmp(str1
,"WWrLh") != 0) {
3577 if (!check_printjob_info(&desc
,uLevel
,str2
)) {
3581 if(!rap_to_pjobid(SVAL(p
,0), sharename
, &jobid
)) {
3585 snum
= lp_servicenumber( sharename
);
3586 if (snum
< 0 || !VALID_SNUM(snum
)) {
3590 count
= print_queue_status(snum
,&queue
,&status
);
3591 for (i
= 0; i
< count
; i
++) {
3592 if (queue
[i
].job
== jobid
) {
3598 *rdata
= SMB_REALLOC_LIMIT(*rdata
,mdrcnt
);
3603 desc
.buflen
= mdrcnt
;
3606 * Don't return data but need to get correct length
3607 * init_package will return wrong size if buflen=0
3609 desc
.buflen
= getlen(desc
.format
);
3610 desc
.base
= tmpdata
= (char *)SMB_MALLOC( desc
.buflen
);
3613 if (init_package(&desc
,1,0)) {
3615 fill_printjob_info(conn
,snum
,uLevel
,&desc
,&queue
[i
],i
);
3616 *rdata_len
= desc
.usedlen
;
3618 desc
.errcode
= NERR_JobNotFound
;
3624 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
3628 SSVALS(*rparam
,0,desc
.errcode
);
3630 SSVAL(*rparam
,4,desc
.neededlen
);
3635 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc
.errcode
));
3640 static BOOL
api_WPrintJobEnumerate(connection_struct
*conn
, uint16 vuid
,
3641 char *param
, int tpscnt
,
3642 char *data
, int tdscnt
,
3643 int mdrcnt
,int mprcnt
,
3644 char **rdata
,char **rparam
,
3645 int *rdata_len
,int *rparam_len
)
3647 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3648 char *str2
= skip_string(param
,tpscnt
,str1
,1);
3649 char *p
= skip_string(param
,tpscnt
,str2
,1);
3655 struct pack_desc desc
;
3656 print_queue_struct
*queue
=NULL
;
3657 print_status_struct status
;
3659 if (!str1
|| !str2
|| !p
) {
3663 memset((char *)&desc
,'\0',sizeof(desc
));
3664 memset((char *)&status
,'\0',sizeof(status
));
3666 p
= skip_string(param
,tpscnt
,p
,1);
3670 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3672 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel
,name
));
3674 /* check it's a supported variant */
3675 if (strcmp(str1
,"zWrLeh") != 0) {
3680 return False
; /* defined only for uLevel 0,1,2 */
3683 if (!check_printjob_info(&desc
,uLevel
,str2
)) {
3687 snum
= find_service(name
);
3688 if ( !(lp_snum_ok(snum
) && lp_print_ok(snum
)) ) {
3692 count
= print_queue_status(snum
,&queue
,&status
);
3694 *rdata
= SMB_REALLOC_LIMIT(*rdata
,mdrcnt
);
3700 desc
.buflen
= mdrcnt
;
3702 if (init_package(&desc
,count
,0)) {
3704 for (i
= 0; i
< count
; i
++) {
3705 fill_printjob_info(conn
,snum
,uLevel
,&desc
,&queue
[i
],i
);
3706 if (desc
.errcode
== NERR_Success
) {
3712 *rdata_len
= desc
.usedlen
;
3715 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
3719 SSVALS(*rparam
,0,desc
.errcode
);
3721 SSVAL(*rparam
,4,succnt
);
3722 SSVAL(*rparam
,6,count
);
3726 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc
.errcode
));
3731 static int check_printdest_info(struct pack_desc
* desc
,
3732 int uLevel
, char* id
)
3734 desc
->subformat
= NULL
;
3737 desc
->format
= "B9";
3740 desc
->format
= "B9B21WWzW";
3746 desc
->format
= "zzzWWzzzWW";
3751 if (strcmp(desc
->format
,id
) != 0) {
3757 static void fill_printdest_info(connection_struct
*conn
, int snum
, int uLevel
,
3758 struct pack_desc
* desc
)
3762 strncpy(buf
,SERVICE(snum
),sizeof(buf
)-1);
3763 buf
[sizeof(buf
)-1] = 0;
3767 PACKS(desc
,"B9",buf
); /* szName */
3769 PACKS(desc
,"B21",""); /* szUserName */
3770 PACKI(desc
,"W",0); /* uJobId */
3771 PACKI(desc
,"W",0); /* fsStatus */
3772 PACKS(desc
,"z",""); /* pszStatus */
3773 PACKI(desc
,"W",0); /* time */
3777 if (uLevel
== 2 || uLevel
== 3) {
3778 PACKS(desc
,"z",buf
); /* pszPrinterName */
3780 PACKS(desc
,"z",""); /* pszUserName */
3781 PACKS(desc
,"z",""); /* pszLogAddr */
3782 PACKI(desc
,"W",0); /* uJobId */
3783 PACKI(desc
,"W",0); /* fsStatus */
3784 PACKS(desc
,"z",""); /* pszStatus */
3785 PACKS(desc
,"z",""); /* pszComment */
3786 PACKS(desc
,"z","NULL"); /* pszDrivers */
3787 PACKI(desc
,"W",0); /* time */
3788 PACKI(desc
,"W",0); /* pad1 */
3793 static BOOL
api_WPrintDestGetInfo(connection_struct
*conn
, uint16 vuid
,
3794 char *param
, int tpscnt
,
3795 char *data
, int tdscnt
,
3796 int mdrcnt
,int mprcnt
,
3797 char **rdata
,char **rparam
,
3798 int *rdata_len
,int *rparam_len
)
3800 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3801 char *str2
= skip_string(param
,tpscnt
,str1
,1);
3802 char *p
= skip_string(param
,tpscnt
,str2
,1);
3803 char* PrinterName
= p
;
3805 struct pack_desc desc
;
3809 if (!str1
|| !str2
|| !p
) {
3813 memset((char *)&desc
,'\0',sizeof(desc
));
3815 p
= skip_string(param
,tpscnt
,p
,1);
3819 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3821 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel
,PrinterName
));
3823 /* check it's a supported varient */
3824 if (strcmp(str1
,"zWrLh") != 0) {
3827 if (!check_printdest_info(&desc
,uLevel
,str2
)) {
3831 snum
= find_service(PrinterName
);
3832 if ( !(lp_snum_ok(snum
) && lp_print_ok(snum
)) ) {
3834 desc
.errcode
= NERR_DestNotFound
;
3838 *rdata
= SMB_REALLOC_LIMIT(*rdata
,mdrcnt
);
3843 desc
.buflen
= mdrcnt
;
3846 * Don't return data but need to get correct length
3847 * init_package will return wrong size if buflen=0
3849 desc
.buflen
= getlen(desc
.format
);
3850 desc
.base
= tmpdata
= (char *)SMB_MALLOC( desc
.buflen
);
3852 if (init_package(&desc
,1,0)) {
3853 fill_printdest_info(conn
,snum
,uLevel
,&desc
);
3855 *rdata_len
= desc
.usedlen
;
3859 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
3863 SSVALS(*rparam
,0,desc
.errcode
);
3865 SSVAL(*rparam
,4,desc
.neededlen
);
3867 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc
.errcode
));
3873 static BOOL
api_WPrintDestEnum(connection_struct
*conn
, uint16 vuid
,
3874 char *param
, int tpscnt
,
3875 char *data
, int tdscnt
,
3876 int mdrcnt
,int mprcnt
,
3877 char **rdata
,char **rparam
,
3878 int *rdata_len
,int *rparam_len
)
3880 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3881 char *str2
= skip_string(param
,tpscnt
,str1
,1);
3882 char *p
= skip_string(param
,tpscnt
,str2
,1);
3886 struct pack_desc desc
;
3887 int services
= lp_numservices();
3889 if (!str1
|| !str2
|| !p
) {
3893 memset((char *)&desc
,'\0',sizeof(desc
));
3895 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3897 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel
));
3899 /* check it's a supported varient */
3900 if (strcmp(str1
,"WrLeh") != 0) {
3903 if (!check_printdest_info(&desc
,uLevel
,str2
)) {
3908 for (i
= 0; i
< services
; i
++) {
3909 if (lp_snum_ok(i
) && lp_print_ok(i
) && lp_browseable(i
)) {
3915 *rdata
= SMB_REALLOC_LIMIT(*rdata
,mdrcnt
);
3922 desc
.buflen
= mdrcnt
;
3923 if (init_package(&desc
,queuecnt
,0)) {
3926 for (i
= 0; i
< services
; i
++) {
3927 if (lp_snum_ok(i
) && lp_print_ok(i
) && lp_browseable(i
)) {
3928 fill_printdest_info(conn
,i
,uLevel
,&desc
);
3930 if (desc
.errcode
== NERR_Success
) {
3937 *rdata_len
= desc
.usedlen
;
3940 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
3944 SSVALS(*rparam
,0,desc
.errcode
);
3946 SSVAL(*rparam
,4,succnt
);
3947 SSVAL(*rparam
,6,queuecnt
);
3949 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc
.errcode
));
3954 static BOOL
api_WPrintDriverEnum(connection_struct
*conn
, uint16 vuid
,
3955 char *param
, int tpscnt
,
3956 char *data
, int tdscnt
,
3957 int mdrcnt
,int mprcnt
,
3958 char **rdata
,char **rparam
,
3959 int *rdata_len
,int *rparam_len
)
3961 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3962 char *str2
= skip_string(param
,tpscnt
,str1
,1);
3963 char *p
= skip_string(param
,tpscnt
,str2
,1);
3966 struct pack_desc desc
;
3968 if (!str1
|| !str2
|| !p
) {
3972 memset((char *)&desc
,'\0',sizeof(desc
));
3974 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3976 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel
));
3978 /* check it's a supported varient */
3979 if (strcmp(str1
,"WrLeh") != 0) {
3982 if (uLevel
!= 0 || strcmp(str2
,"B41") != 0) {
3987 *rdata
= SMB_REALLOC_LIMIT(*rdata
,mdrcnt
);
3993 desc
.buflen
= mdrcnt
;
3994 if (init_package(&desc
,1,0)) {
3995 PACKS(&desc
,"B41","NULL");
3998 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
4000 *rdata_len
= desc
.usedlen
;
4003 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
4007 SSVALS(*rparam
,0,desc
.errcode
);
4009 SSVAL(*rparam
,4,succnt
);
4012 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc
.errcode
));
4017 static BOOL
api_WPrintQProcEnum(connection_struct
*conn
, uint16 vuid
,
4018 char *param
, int tpscnt
,
4019 char *data
, int tdscnt
,
4020 int mdrcnt
,int mprcnt
,
4021 char **rdata
,char **rparam
,
4022 int *rdata_len
,int *rparam_len
)
4024 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4025 char *str2
= skip_string(param
,tpscnt
,str1
,1);
4026 char *p
= skip_string(param
,tpscnt
,str2
,1);
4029 struct pack_desc desc
;
4031 if (!str1
|| !str2
|| !p
) {
4034 memset((char *)&desc
,'\0',sizeof(desc
));
4036 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4038 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel
));
4040 /* check it's a supported varient */
4041 if (strcmp(str1
,"WrLeh") != 0) {
4044 if (uLevel
!= 0 || strcmp(str2
,"B13") != 0) {
4049 *rdata
= SMB_REALLOC_LIMIT(*rdata
,mdrcnt
);
4055 desc
.buflen
= mdrcnt
;
4057 if (init_package(&desc
,1,0)) {
4058 PACKS(&desc
,"B13","lpd");
4061 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
4063 *rdata_len
= desc
.usedlen
;
4066 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
4070 SSVALS(*rparam
,0,desc
.errcode
);
4072 SSVAL(*rparam
,4,succnt
);
4075 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc
.errcode
));
4080 static BOOL
api_WPrintPortEnum(connection_struct
*conn
, uint16 vuid
,
4081 char *param
, int tpscnt
,
4082 char *data
, int tdscnt
,
4083 int mdrcnt
,int mprcnt
,
4084 char **rdata
,char **rparam
,
4085 int *rdata_len
,int *rparam_len
)
4087 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4088 char *str2
= skip_string(param
,tpscnt
,str1
,1);
4089 char *p
= skip_string(param
,tpscnt
,str2
,1);
4092 struct pack_desc desc
;
4094 if (!str1
|| !str2
|| !p
) {
4098 memset((char *)&desc
,'\0',sizeof(desc
));
4100 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4102 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel
));
4104 /* check it's a supported varient */
4105 if (strcmp(str1
,"WrLeh") != 0) {
4108 if (uLevel
!= 0 || strcmp(str2
,"B9") != 0) {
4113 *rdata
= SMB_REALLOC_LIMIT(*rdata
,mdrcnt
);
4118 memset((char *)&desc
,'\0',sizeof(desc
));
4120 desc
.buflen
= mdrcnt
;
4122 if (init_package(&desc
,1,0)) {
4123 PACKS(&desc
,"B13","lp0");
4126 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
4128 *rdata_len
= desc
.usedlen
;
4131 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
4135 SSVALS(*rparam
,0,desc
.errcode
);
4137 SSVAL(*rparam
,4,succnt
);
4140 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc
.errcode
));
4145 /****************************************************************************
4147 ****************************************************************************/
4149 static BOOL
api_RNetSessionEnum(connection_struct
*conn
, uint16 vuid
,
4150 char *param
, int tpscnt
,
4151 char *data
, int tdscnt
,
4152 int mdrcnt
,int mprcnt
,
4153 char **rdata
,char **rparam
,
4154 int *rdata_len
,int *rparam_len
)
4157 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4158 char *str2
= skip_string(param
,tpscnt
,str1
,1);
4159 char *p
= skip_string(param
,tpscnt
,str2
,1);
4161 struct pack_desc desc
;
4162 struct sessionid
*session_list
;
4163 int i
, num_sessions
;
4165 if (!str1
|| !str2
|| !p
) {
4169 memset((char *)&desc
,'\0',sizeof(desc
));
4171 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4173 DEBUG(3,("RNetSessionEnum uLevel=%d\n",uLevel
));
4174 DEBUG(7,("RNetSessionEnum req string=%s\n",str1
));
4175 DEBUG(7,("RNetSessionEnum ret string=%s\n",str2
));
4177 /* check it's a supported varient */
4178 if (strcmp(str1
,RAP_NetSessionEnum_REQ
) != 0) {
4181 if (uLevel
!= 2 || strcmp(str2
,RAP_SESSION_INFO_L2
) != 0) {
4185 num_sessions
= list_sessions(&session_list
);
4188 *rdata
= SMB_REALLOC_LIMIT(*rdata
,mdrcnt
);
4193 memset((char *)&desc
,'\0',sizeof(desc
));
4195 desc
.buflen
= mdrcnt
;
4197 if (!init_package(&desc
,num_sessions
,0)) {
4201 for(i
=0; i
<num_sessions
; i
++) {
4202 PACKS(&desc
, "z", session_list
[i
].remote_machine
);
4203 PACKS(&desc
, "z", session_list
[i
].username
);
4204 PACKI(&desc
, "W", 1); /* num conns */
4205 PACKI(&desc
, "W", 0); /* num opens */
4206 PACKI(&desc
, "W", 1); /* num users */
4207 PACKI(&desc
, "D", 0); /* session time */
4208 PACKI(&desc
, "D", 0); /* idle time */
4209 PACKI(&desc
, "D", 0); /* flags */
4210 PACKS(&desc
, "z", "Unknown Client"); /* client type string */
4213 *rdata_len
= desc
.usedlen
;
4216 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
4220 SSVALS(*rparam
,0,desc
.errcode
);
4221 SSVAL(*rparam
,2,0); /* converter */
4222 SSVAL(*rparam
,4,num_sessions
); /* count */
4224 DEBUG(4,("RNetSessionEnum: errorcode %d\n",desc
.errcode
));
4230 /****************************************************************************
4231 The buffer was too small.
4232 ****************************************************************************/
4234 static BOOL
api_TooSmall(connection_struct
*conn
,uint16 vuid
, char *param
, char *data
,
4235 int mdrcnt
, int mprcnt
,
4236 char **rdata
, char **rparam
,
4237 int *rdata_len
, int *rparam_len
)
4239 *rparam_len
= MIN(*rparam_len
,mprcnt
);
4240 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
4247 SSVAL(*rparam
,0,NERR_BufTooSmall
);
4249 DEBUG(3,("Supplied buffer too small in API command\n"));
4254 /****************************************************************************
4255 The request is not supported.
4256 ****************************************************************************/
4258 static BOOL
api_Unsupported(connection_struct
*conn
, uint16 vuid
,
4259 char *param
, int tpscnt
,
4260 char *data
, int tdscnt
,
4261 int mdrcnt
, int mprcnt
,
4262 char **rdata
, char **rparam
,
4263 int *rdata_len
, int *rparam_len
)
4266 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
4273 SSVAL(*rparam
,0,NERR_notsupported
);
4274 SSVAL(*rparam
,2,0); /* converter word */
4276 DEBUG(3,("Unsupported API command\n"));
4281 static const struct {
4284 BOOL (*fn
)(connection_struct
*, uint16
,
4287 int,int,char **,char **,int *,int *);
4288 BOOL auth_user
; /* Deny anonymous access? */
4289 } api_commands
[] = {
4290 {"RNetShareEnum", RAP_WshareEnum
, api_RNetShareEnum
, True
},
4291 {"RNetShareGetInfo", RAP_WshareGetInfo
, api_RNetShareGetInfo
},
4292 {"RNetShareAdd", RAP_WshareAdd
, api_RNetShareAdd
},
4293 {"RNetSessionEnum", RAP_WsessionEnum
, api_RNetSessionEnum
, True
},
4294 {"RNetServerGetInfo", RAP_WserverGetInfo
, api_RNetServerGetInfo
},
4295 {"RNetGroupEnum", RAP_WGroupEnum
, api_RNetGroupEnum
, True
},
4296 {"RNetGroupGetUsers", RAP_WGroupGetUsers
, api_RNetGroupGetUsers
, True
},
4297 {"RNetUserEnum", RAP_WUserEnum
, api_RNetUserEnum
, True
},
4298 {"RNetUserGetInfo", RAP_WUserGetInfo
, api_RNetUserGetInfo
},
4299 {"NetUserGetGroups", RAP_WUserGetGroups
, api_NetUserGetGroups
},
4300 {"NetWkstaGetInfo", RAP_WWkstaGetInfo
, api_NetWkstaGetInfo
},
4301 {"DosPrintQEnum", RAP_WPrintQEnum
, api_DosPrintQEnum
, True
},
4302 {"DosPrintQGetInfo", RAP_WPrintQGetInfo
, api_DosPrintQGetInfo
},
4303 {"WPrintQueuePause", RAP_WPrintQPause
, api_WPrintQueueCtrl
},
4304 {"WPrintQueueResume", RAP_WPrintQContinue
, api_WPrintQueueCtrl
},
4305 {"WPrintJobEnumerate",RAP_WPrintJobEnum
, api_WPrintJobEnumerate
},
4306 {"WPrintJobGetInfo", RAP_WPrintJobGetInfo
, api_WPrintJobGetInfo
},
4307 {"RDosPrintJobDel", RAP_WPrintJobDel
, api_RDosPrintJobDel
},
4308 {"RDosPrintJobPause", RAP_WPrintJobPause
, api_RDosPrintJobDel
},
4309 {"RDosPrintJobResume",RAP_WPrintJobContinue
, api_RDosPrintJobDel
},
4310 {"WPrintDestEnum", RAP_WPrintDestEnum
, api_WPrintDestEnum
},
4311 {"WPrintDestGetInfo", RAP_WPrintDestGetInfo
, api_WPrintDestGetInfo
},
4312 {"NetRemoteTOD", RAP_NetRemoteTOD
, api_NetRemoteTOD
},
4313 {"WPrintQueuePurge", RAP_WPrintQPurge
, api_WPrintQueueCtrl
},
4314 {"NetServerEnum", RAP_NetServerEnum2
, api_RNetServerEnum
}, /* anon OK */
4315 {"WAccessGetUserPerms",RAP_WAccessGetUserPerms
,api_WAccessGetUserPerms
},
4316 {"SetUserPassword", RAP_WUserPasswordSet2
, api_SetUserPassword
},
4317 {"WWkstaUserLogon", RAP_WWkstaUserLogon
, api_WWkstaUserLogon
},
4318 {"PrintJobInfo", RAP_WPrintJobSetInfo
, api_PrintJobInfo
},
4319 {"WPrintDriverEnum", RAP_WPrintDriverEnum
, api_WPrintDriverEnum
},
4320 {"WPrintQProcEnum", RAP_WPrintQProcessorEnum
,api_WPrintQProcEnum
},
4321 {"WPrintPortEnum", RAP_WPrintPortEnum
, api_WPrintPortEnum
},
4322 {"SamOEMChangePassword",RAP_SamOEMChgPasswordUser2_P
,api_SamOEMChangePassword
}, /* anon OK */
4323 {NULL
, -1, api_Unsupported
}
4324 /* The following RAP calls are not implemented by Samba:
4326 RAP_WFileEnum2 - anon not OK
4331 /****************************************************************************
4332 Handle remote api calls
4333 ****************************************************************************/
4335 int api_reply(connection_struct
*conn
,uint16 vuid
,char *outbuf
,char *data
,char *params
,
4336 int tdscnt
,int tpscnt
,int mdrcnt
,int mprcnt
)
4340 char *rparam
= NULL
;
4341 const char *name1
= NULL
;
4342 const char *name2
= NULL
;
4349 DEBUG(0,("ERROR: NULL params in api_reply()\n"));
4356 api_command
= SVAL(params
,0);
4357 /* Is there a string at position params+2 ? */
4358 if (skip_string(params
,tpscnt
,params
+2,1)) {
4363 name2
= skip_string(params
,tpscnt
,params
+2,1);
4368 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
4372 tdscnt
,tpscnt
,mdrcnt
,mprcnt
));
4374 for (i
=0;api_commands
[i
].name
;i
++) {
4375 if (api_commands
[i
].id
== api_command
&& api_commands
[i
].fn
) {
4376 DEBUG(3,("Doing %s\n",api_commands
[i
].name
));
4381 /* Check whether this api call can be done anonymously */
4383 if (api_commands
[i
].auth_user
&& lp_restrict_anonymous()) {
4384 user_struct
*user
= get_valid_user_struct(vuid
);
4386 if (!user
|| user
->guest
) {
4387 return ERROR_NT(NT_STATUS_ACCESS_DENIED
);
4391 rdata
= (char *)SMB_MALLOC(1024);
4393 memset(rdata
,'\0',1024);
4396 rparam
= (char *)SMB_MALLOC(1024);
4398 memset(rparam
,'\0',1024);
4401 if(!rdata
|| !rparam
) {
4402 DEBUG(0,("api_reply: malloc fail !\n"));
4408 reply
= api_commands
[i
].fn(conn
,
4410 params
,tpscnt
, /* params + length */
4411 data
,tdscnt
, /* data + length */
4413 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
4416 if (rdata_len
> mdrcnt
|| rparam_len
> mprcnt
) {
4417 reply
= api_TooSmall(conn
,vuid
,params
,data
,mdrcnt
,mprcnt
,
4418 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
4421 /* if we get False back then it's actually unsupported */
4423 reply
= api_Unsupported(conn
,vuid
,params
,tpscnt
,data
,tdscnt
,mdrcnt
,mprcnt
,
4424 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
4427 /* If api_Unsupported returns false we can't return anything. */
4429 send_trans_reply(outbuf
, rparam
, rparam_len
, rdata
, rdata_len
, False
);