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
);
93 static int CopyAndAdvance(char **dst
, char *src
, int *n
)
96 if (!src
|| !dst
|| !n
|| !(*dst
)) {
99 l
= push_ascii(*dst
,src
,*n
, STR_TERMINATE
);
108 static int StrlenExpanded(connection_struct
*conn
, int snum
, char *s
)
114 StrnCpy(buf
,s
,sizeof(buf
)/2);
115 pstring_sub(buf
,"%S",lp_servicename(snum
));
116 standard_sub_advanced(lp_servicename(SNUM(conn
)), conn
->user
,
117 conn
->connectpath
, conn
->gid
,
118 get_current_username(),
119 current_user_info
.domain
,
121 return strlen(buf
) + 1;
124 static char *Expand(connection_struct
*conn
, int snum
, char *s
)
130 StrnCpy(buf
,s
,sizeof(buf
)/2);
131 pstring_sub(buf
,"%S",lp_servicename(snum
));
132 standard_sub_advanced(lp_servicename(SNUM(conn
)), conn
->user
,
133 conn
->connectpath
, conn
->gid
,
134 get_current_username(),
135 current_user_info
.domain
,
140 /*******************************************************************
141 Check a API string for validity when we only need to check the prefix.
142 ******************************************************************/
144 static BOOL
prefix_ok(const char *str
, const char *prefix
)
146 return(strncmp(str
,prefix
,strlen(prefix
)) == 0);
150 const char *format
; /* formatstring for structure */
151 const char *subformat
; /* subformat for structure */
152 char *base
; /* baseaddress of buffer */
153 int buflen
; /* remaining size for fixed part; on init: length of base */
154 int subcount
; /* count of substructures */
155 char *structbuf
; /* pointer into buffer for remaining fixed part */
156 int stringlen
; /* remaining size for variable part */
157 char *stringbuf
; /* pointer into buffer for remaining variable part */
158 int neededlen
; /* total needed size */
159 int usedlen
; /* total used size (usedlen <= neededlen and usedlen <= buflen) */
160 const char *curpos
; /* current position; pointer into format or subformat */
164 static int get_counter(const char **p
)
170 if (!isdigit((int)**p
)) {
176 n
= 10 * n
+ (i
- '0');
184 static int getlen(const char *p
)
193 case 'W': /* word (2 byte) */
196 case 'K': /* status word? (2 byte) */
199 case 'N': /* count of substructures (word) at end */
202 case 'D': /* double word (4 byte) */
203 case 'z': /* offset to zero terminated string (4 byte) */
204 case 'l': /* offset to user data (4 byte) */
207 case 'b': /* offset to data (with counter) (4 byte) */
211 case 'B': /* byte (with optional counter) */
212 n
+= get_counter(&p
);
219 static BOOL
init_package(struct pack_desc
*p
, int count
, int subcount
)
224 if (!p
->format
|| !p
->base
) {
228 i
= count
* getlen(p
->format
);
230 i
+= subcount
* getlen(p
->subformat
);
232 p
->structbuf
= p
->base
;
236 p
->curpos
= p
->format
;
242 * This is the old error code we used. Aparently
243 * WinNT/2k systems return ERRbuftoosmall (2123) and
244 * OS/2 needs this. I'm leaving this here so we can revert
247 p
->errcode
= ERRmoredata
;
249 p
->errcode
= ERRbuftoosmall
;
252 p
->errcode
= NERR_Success
;
256 p
->stringbuf
= p
->base
+ i
;
258 return (p
->errcode
== NERR_Success
);
261 static int package(struct pack_desc
*p
, ...)
264 int needed
=0, stringneeded
;
265 const char *str
=NULL
;
266 int is_string
=0, stringused
;
273 p
->curpos
= p
->format
;
275 p
->curpos
= p
->subformat
;
280 str
= va_arg(args
,char*);
281 SMB_ASSERT(strncmp(str
,p
->curpos
,strlen(str
)) == 0);
290 switch( *p
->curpos
++ ) {
291 case 'W': /* word (2 byte) */
293 temp
= va_arg(args
,int);
294 if (p
->buflen
>= needed
) {
295 SSVAL(p
->structbuf
,0,temp
);
298 case 'K': /* status word? (2 byte) */
300 temp
= va_arg(args
,int);
301 if (p
->buflen
>= needed
) {
302 SSVAL(p
->structbuf
,0,temp
);
305 case 'N': /* count of substructures (word) at end */
307 p
->subcount
= va_arg(args
,int);
308 if (p
->buflen
>= needed
) {
309 SSVAL(p
->structbuf
,0,p
->subcount
);
312 case 'D': /* double word (4 byte) */
314 temp
= va_arg(args
,int);
315 if (p
->buflen
>= needed
) {
316 SIVAL(p
->structbuf
,0,temp
);
319 case 'B': /* byte (with optional counter) */
320 needed
= get_counter(&p
->curpos
);
322 char *s
= va_arg(args
,char*);
323 if (p
->buflen
>= needed
) {
324 StrnCpy(p
->structbuf
,s
?s
:"",needed
-1);
328 case 'z': /* offset to zero terminated string (4 byte) */
329 str
= va_arg(args
,char*);
330 stringneeded
= (str
? strlen(str
)+1 : 0);
333 case 'l': /* offset to user data (4 byte) */
334 str
= va_arg(args
,char*);
335 stringneeded
= va_arg(args
,int);
338 case 'b': /* offset to data (with counter) (4 byte) */
339 str
= va_arg(args
,char*);
340 stringneeded
= get_counter(&p
->curpos
);
346 if (stringneeded
>= 0) {
348 if (p
->buflen
>= needed
) {
349 stringused
= stringneeded
;
350 if (stringused
> p
->stringlen
) {
351 stringused
= (is_string
? p
->stringlen
: 0);
352 if (p
->errcode
== NERR_Success
) {
353 p
->errcode
= ERRmoredata
;
357 SIVAL(p
->structbuf
,0,0);
359 SIVAL(p
->structbuf
,0,PTR_DIFF(p
->stringbuf
,p
->base
));
360 memcpy(p
->stringbuf
,str
?str
:"",stringused
);
362 p
->stringbuf
[stringused
-1] = '\0';
364 p
->stringbuf
+= stringused
;
365 p
->stringlen
-= stringused
;
366 p
->usedlen
+= stringused
;
369 p
->neededlen
+= stringneeded
;
372 p
->neededlen
+= needed
;
373 if (p
->buflen
>= needed
) {
374 p
->structbuf
+= needed
;
376 p
->usedlen
+= needed
;
378 if (p
->errcode
== NERR_Success
) {
379 p
->errcode
= ERRmoredata
;
386 #define PACK(desc,t,v) package(desc,t,v,0,0,0,0)
387 #define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0)
389 #define PACK(desc,t,v) package(desc,v)
390 #define PACKl(desc,t,v,l) package(desc,v,l)
393 static void PACKI(struct pack_desc
* desc
, const char *t
,int v
)
398 static void PACKS(struct pack_desc
* desc
,const char *t
,const char *v
)
403 /****************************************************************************
405 ****************************************************************************/
407 static void PackDriverData(struct pack_desc
* desc
)
409 char drivdata
[4+4+32];
410 SIVAL(drivdata
,0,sizeof drivdata
); /* cb */
411 SIVAL(drivdata
,4,1000); /* lVersion */
412 memset(drivdata
+8,0,32); /* szDeviceName */
413 push_ascii(drivdata
+8,"NULL",32, STR_TERMINATE
);
414 PACKl(desc
,"l",drivdata
,sizeof drivdata
); /* pDriverData */
417 static int check_printq_info(struct pack_desc
* desc
,
418 unsigned int uLevel
, char *id1
, char *id2
)
420 desc
->subformat
= NULL
;
423 desc
->format
= "B13";
426 desc
->format
= "B13BWWWzzzzzWW";
429 desc
->format
= "B13BWWWzzzzzWN";
430 desc
->subformat
= "WB21BB16B10zWWzDDz";
433 desc
->format
= "zWWWWzzzzWWzzl";
436 desc
->format
= "zWWWWzzzzWNzzl";
437 desc
->subformat
= "WWzWWDDzz";
446 desc
->format
= "WzzzzzzzzN";
447 desc
->subformat
= "z";
450 DEBUG(0,("check_printq_info: invalid level %d\n",
454 if (id1
== NULL
|| strcmp(desc
->format
,id1
) != 0) {
455 DEBUG(0,("check_printq_info: invalid format %s\n",
456 id1
? id1
: "<NULL>" ));
459 if (desc
->subformat
&& (id2
== NULL
|| strcmp(desc
->subformat
,id2
) != 0)) {
460 DEBUG(0,("check_printq_info: invalid subformat %s\n",
461 id2
? id2
: "<NULL>" ));
468 #define RAP_JOB_STATUS_QUEUED 0
469 #define RAP_JOB_STATUS_PAUSED 1
470 #define RAP_JOB_STATUS_SPOOLING 2
471 #define RAP_JOB_STATUS_PRINTING 3
472 #define RAP_JOB_STATUS_PRINTED 4
474 #define RAP_QUEUE_STATUS_PAUSED 1
475 #define RAP_QUEUE_STATUS_ERROR 2
477 /* turn a print job status into a on the wire status
479 static int printj_status(int v
)
483 return RAP_JOB_STATUS_QUEUED
;
485 return RAP_JOB_STATUS_PAUSED
;
487 return RAP_JOB_STATUS_SPOOLING
;
489 return RAP_JOB_STATUS_PRINTING
;
494 /* turn a print queue status into a on the wire status
496 static int printq_status(int v
)
502 return RAP_QUEUE_STATUS_PAUSED
;
504 return RAP_QUEUE_STATUS_ERROR
;
507 static void fill_printjob_info(connection_struct
*conn
, int snum
, int uLevel
,
508 struct pack_desc
*desc
,
509 print_queue_struct
*queue
, int n
)
511 time_t t
= queue
->time
;
513 /* the client expects localtime */
514 t
-= get_time_zone(t
);
516 PACKI(desc
,"W",pjobid_to_rap(lp_const_servicename(snum
),queue
->job
)); /* uJobId */
518 PACKS(desc
,"B21",queue
->fs_user
); /* szUserName */
519 PACKS(desc
,"B",""); /* pad */
520 PACKS(desc
,"B16",""); /* szNotifyName */
521 PACKS(desc
,"B10","PM_Q_RAW"); /* szDataType */
522 PACKS(desc
,"z",""); /* pszParms */
523 PACKI(desc
,"W",n
+1); /* uPosition */
524 PACKI(desc
,"W",printj_status(queue
->status
)); /* fsStatus */
525 PACKS(desc
,"z",""); /* pszStatus */
526 PACKI(desc
,"D",t
); /* ulSubmitted */
527 PACKI(desc
,"D",queue
->size
); /* ulSize */
528 PACKS(desc
,"z",queue
->fs_file
); /* pszComment */
530 if (uLevel
== 2 || uLevel
== 3 || uLevel
== 4) {
531 PACKI(desc
,"W",queue
->priority
); /* uPriority */
532 PACKS(desc
,"z",queue
->fs_user
); /* pszUserName */
533 PACKI(desc
,"W",n
+1); /* uPosition */
534 PACKI(desc
,"W",printj_status(queue
->status
)); /* fsStatus */
535 PACKI(desc
,"D",t
); /* ulSubmitted */
536 PACKI(desc
,"D",queue
->size
); /* ulSize */
537 PACKS(desc
,"z","Samba"); /* pszComment */
538 PACKS(desc
,"z",queue
->fs_file
); /* pszDocument */
540 PACKS(desc
,"z",""); /* pszNotifyName */
541 PACKS(desc
,"z","PM_Q_RAW"); /* pszDataType */
542 PACKS(desc
,"z",""); /* pszParms */
543 PACKS(desc
,"z",""); /* pszStatus */
544 PACKS(desc
,"z",SERVICE(snum
)); /* pszQueue */
545 PACKS(desc
,"z","lpd"); /* pszQProcName */
546 PACKS(desc
,"z",""); /* pszQProcParms */
547 PACKS(desc
,"z","NULL"); /* pszDriverName */
548 PackDriverData(desc
); /* pDriverData */
549 PACKS(desc
,"z",""); /* pszPrinterName */
550 } else if (uLevel
== 4) { /* OS2 */
551 PACKS(desc
,"z",""); /* pszSpoolFileName */
552 PACKS(desc
,"z",""); /* pszPortName */
553 PACKS(desc
,"z",""); /* pszStatus */
554 PACKI(desc
,"D",0); /* ulPagesSpooled */
555 PACKI(desc
,"D",0); /* ulPagesSent */
556 PACKI(desc
,"D",0); /* ulPagesPrinted */
557 PACKI(desc
,"D",0); /* ulTimePrinted */
558 PACKI(desc
,"D",0); /* ulExtendJobStatus */
559 PACKI(desc
,"D",0); /* ulStartPage */
560 PACKI(desc
,"D",0); /* ulEndPage */
565 /********************************************************************
566 Return a driver name given an snum.
567 Returns True if from tdb, False otherwise.
568 ********************************************************************/
570 static BOOL
get_driver_name(int snum
, pstring drivername
)
572 NT_PRINTER_INFO_LEVEL
*info
= NULL
;
575 get_a_printer (NULL
, &info
, 2, lp_servicename(snum
));
577 pstrcpy( drivername
, info
->info_2
->drivername
);
579 free_a_printer(&info
, 2);
585 /********************************************************************
586 Respond to the DosPrintQInfo command with a level of 52
587 This is used to get printer driver information for Win9x clients
588 ********************************************************************/
589 static void fill_printq_info_52(connection_struct
*conn
, int snum
,
590 struct pack_desc
* desc
, int count
)
594 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
595 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
599 if ( !W_ERROR_IS_OK(get_a_printer( NULL
, &printer
, 2, lp_servicename(snum
))) ) {
600 DEBUG(3,("fill_printq_info_52: Failed to lookup printer [%s]\n",
601 lp_servicename(snum
)));
605 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
,
608 DEBUG(3,("fill_printq_info_52: Failed to lookup driver [%s]\n",
609 printer
->info_2
->drivername
));
613 trim_string(driver
.info_3
->driverpath
, "\\print$\\WIN40\\0\\", 0);
614 trim_string(driver
.info_3
->datafile
, "\\print$\\WIN40\\0\\", 0);
615 trim_string(driver
.info_3
->helpfile
, "\\print$\\WIN40\\0\\", 0);
617 PACKI(desc
, "W", 0x0400); /* don't know */
618 PACKS(desc
, "z", driver
.info_3
->name
); /* long printer name */
619 PACKS(desc
, "z", driver
.info_3
->driverpath
); /* Driverfile Name */
620 PACKS(desc
, "z", driver
.info_3
->datafile
); /* Datafile name */
621 PACKS(desc
, "z", driver
.info_3
->monitorname
); /* language monitor */
623 fstrcpy(location
, "\\\\%L\\print$\\WIN40\\0");
624 standard_sub_basic( "", "", location
, sizeof(location
)-1 );
625 PACKS(desc
,"z", location
); /* share to retrieve files */
627 PACKS(desc
,"z", driver
.info_3
->defaultdatatype
); /* default data type */
628 PACKS(desc
,"z", driver
.info_3
->helpfile
); /* helpfile name */
629 PACKS(desc
,"z", driver
.info_3
->driverpath
); /* driver name */
631 DEBUG(3,("Printer Driver Name: %s:\n",driver
.info_3
->name
));
632 DEBUG(3,("Driver: %s:\n",driver
.info_3
->driverpath
));
633 DEBUG(3,("Data File: %s:\n",driver
.info_3
->datafile
));
634 DEBUG(3,("Language Monitor: %s:\n",driver
.info_3
->monitorname
));
635 DEBUG(3,("Driver Location: %s:\n",location
));
636 DEBUG(3,("Data Type: %s:\n",driver
.info_3
->defaultdatatype
));
637 DEBUG(3,("Help File: %s:\n",driver
.info_3
->helpfile
));
638 PACKI(desc
,"N",count
); /* number of files to copy */
640 for ( i
=0; i
<count
&& driver
.info_3
->dependentfiles
&& *driver
.info_3
->dependentfiles
[i
]; i
++)
642 trim_string(driver
.info_3
->dependentfiles
[i
], "\\print$\\WIN40\\0\\", 0);
643 PACKS(desc
,"z",driver
.info_3
->dependentfiles
[i
]); /* driver files to copy */
644 DEBUG(3,("Dependent File: %s:\n",driver
.info_3
->dependentfiles
[i
]));
649 DEBUG(3,("fill_printq_info_52: file count specified by client [%d] != number of dependent files [%i]\n",
652 DEBUG(3,("fill_printq_info on <%s> gave %d entries\n", SERVICE(snum
),i
));
654 desc
->errcode
=NERR_Success
;
658 DEBUG(3,("fill_printq_info: Can't supply driver files\n"));
659 desc
->errcode
=NERR_notsupported
;
663 free_a_printer( &printer
, 2 );
666 free_a_printer_driver( driver
, 3 );
670 static void fill_printq_info(connection_struct
*conn
, int snum
, int uLevel
,
671 struct pack_desc
* desc
,
672 int count
, print_queue_struct
* queue
,
673 print_status_struct
* status
)
678 PACKS(desc
,"B13",SERVICE(snum
));
683 PACKS(desc
,"z",Expand(conn
,snum
,SERVICE(snum
)));
686 PACKI(desc
,"K",printq_status(status
->status
));
690 if (uLevel
== 1 || uLevel
== 2) {
691 PACKS(desc
,"B",""); /* alignment */
692 PACKI(desc
,"W",5); /* priority */
693 PACKI(desc
,"W",0); /* start time */
694 PACKI(desc
,"W",0); /* until time */
695 PACKS(desc
,"z",""); /* pSepFile */
696 PACKS(desc
,"z","lpd"); /* pPrProc */
697 PACKS(desc
,"z",SERVICE(snum
)); /* pDestinations */
698 PACKS(desc
,"z",""); /* pParms */
700 PACKS(desc
,"z","UNKNOWN PRINTER");
701 PACKI(desc
,"W",LPSTAT_ERROR
);
703 else if (!status
|| !status
->message
[0]) {
704 PACKS(desc
,"z",Expand(conn
,snum
,lp_comment(snum
)));
705 PACKI(desc
,"W",LPSTAT_OK
); /* status */
707 PACKS(desc
,"z",status
->message
);
708 PACKI(desc
,"W",printq_status(status
->status
)); /* status */
710 PACKI(desc
,(uLevel
== 1 ? "W" : "N"),count
);
713 if (uLevel
== 3 || uLevel
== 4) {
716 PACKI(desc
,"W",5); /* uPriority */
717 PACKI(desc
,"W",0); /* uStarttime */
718 PACKI(desc
,"W",0); /* uUntiltime */
719 PACKI(desc
,"W",5); /* pad1 */
720 PACKS(desc
,"z",""); /* pszSepFile */
721 PACKS(desc
,"z","WinPrint"); /* pszPrProc */
722 PACKS(desc
,"z",NULL
); /* pszParms */
723 PACKS(desc
,"z",NULL
); /* pszComment - don't ask.... JRA */
724 /* "don't ask" that it's done this way to fix corrupted
725 Win9X/ME printer comments. */
727 PACKI(desc
,"W",LPSTAT_OK
); /* fsStatus */
729 PACKI(desc
,"W",printq_status(status
->status
)); /* fsStatus */
731 PACKI(desc
,(uLevel
== 3 ? "W" : "N"),count
); /* cJobs */
732 PACKS(desc
,"z",SERVICE(snum
)); /* pszPrinters */
733 get_driver_name(snum
,drivername
);
734 PACKS(desc
,"z",drivername
); /* pszDriverName */
735 PackDriverData(desc
); /* pDriverData */
738 if (uLevel
== 2 || uLevel
== 4) {
740 for (i
=0;i
<count
;i
++)
741 fill_printjob_info(conn
,snum
,uLevel
== 2 ? 1 : 2,desc
,&queue
[i
],i
);
745 fill_printq_info_52( conn
, snum
, desc
, count
);
748 /* This function returns the number of files for a given driver */
749 static int get_printerdrivernumber(int snum
)
752 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
753 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
757 if ( !W_ERROR_IS_OK(get_a_printer( NULL
, &printer
, 2, lp_servicename(snum
))) ) {
758 DEBUG(3,("get_printerdrivernumber: Failed to lookup printer [%s]\n",
759 lp_servicename(snum
)));
763 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
,
766 DEBUG(3,("get_printerdrivernumber: Failed to lookup driver [%s]\n",
767 printer
->info_2
->drivername
));
771 /* count the number of files */
772 while ( driver
.info_3
->dependentfiles
&& *driver
.info_3
->dependentfiles
[result
] )
777 free_a_printer( &printer
, 2 );
780 free_a_printer_driver( driver
, 3 );
785 static BOOL
api_DosPrintQGetInfo(connection_struct
*conn
, uint16 vuid
,
786 char *param
, int tpscnt
,
787 char *data
, int tdscnt
,
788 int mdrcnt
,int mprcnt
,
789 char **rdata
,char **rparam
,
790 int *rdata_len
,int *rparam_len
)
792 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
793 char *str2
= skip_string(param
,tpscnt
,str1
);
794 char *p
= skip_string(param
,tpscnt
,str2
);
800 struct pack_desc desc
;
801 print_queue_struct
*queue
=NULL
;
802 print_status_struct status
;
805 if (!str1
|| !str2
|| !p
) {
808 memset((char *)&status
,'\0',sizeof(status
));
809 memset((char *)&desc
,'\0',sizeof(desc
));
811 p
= skip_string(param
,tpscnt
,p
);
815 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
816 str3
= get_safe_str_ptr(param
,tpscnt
,p
,4);
817 /* str3 may be null here and is checked in check_printq_info(). */
819 /* remove any trailing username */
820 if ((p
= strchr_m(QueueName
,'%')))
823 DEBUG(3,("api_DosPrintQGetInfo uLevel=%d name=%s\n",uLevel
,QueueName
));
825 /* check it's a supported varient */
826 if (!prefix_ok(str1
,"zWrLh"))
828 if (!check_printq_info(&desc
,uLevel
,str2
,str3
)) {
830 * Patch from Scott Moomaw <scott@bridgewater.edu>
831 * to return the 'invalid info level' error if an
832 * unknown level was requested.
836 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
840 SSVALS(*rparam
,0,ERRunknownlevel
);
846 snum
= find_service(QueueName
);
847 if ( !(lp_snum_ok(snum
) && lp_print_ok(snum
)) )
851 count
= get_printerdrivernumber(snum
);
852 DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count
));
854 count
= print_queue_status(snum
, &queue
,&status
);
858 *rdata
= SMB_REALLOC_LIMIT(*rdata
,mdrcnt
);
863 desc
.buflen
= mdrcnt
;
866 * Don't return data but need to get correct length
867 * init_package will return wrong size if buflen=0
869 desc
.buflen
= getlen(desc
.format
);
870 desc
.base
= tmpdata
= (char *) SMB_MALLOC (desc
.buflen
);
873 if (init_package(&desc
,1,count
)) {
874 desc
.subcount
= count
;
875 fill_printq_info(conn
,snum
,uLevel
,&desc
,count
,queue
,&status
);
878 *rdata_len
= desc
.usedlen
;
881 * We must set the return code to ERRbuftoosmall
882 * in order to support lanman style printing with Win NT/2k
885 if (!mdrcnt
&& lp_disable_spoolss())
886 desc
.errcode
= ERRbuftoosmall
;
888 *rdata_len
= desc
.usedlen
;
890 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
894 SSVALS(*rparam
,0,desc
.errcode
);
896 SSVAL(*rparam
,4,desc
.neededlen
);
898 DEBUG(4,("printqgetinfo: errorcode %d\n",desc
.errcode
));
906 /****************************************************************************
907 View list of all print jobs on all queues.
908 ****************************************************************************/
910 static BOOL
api_DosPrintQEnum(connection_struct
*conn
, uint16 vuid
,
911 char *param
, int tpscnt
,
912 char *data
, int tdscnt
,
913 int mdrcnt
, int mprcnt
,
914 char **rdata
, char** rparam
,
915 int *rdata_len
, int *rparam_len
)
917 char *param_format
= get_safe_str_ptr(param
,tpscnt
,param
,2);
918 char *output_format1
= skip_string(param
,tpscnt
,param_format
);
919 char *p
= skip_string(param
,tpscnt
,output_format1
);
920 unsigned int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
921 char *output_format2
= get_safe_str_ptr(param
,tpscnt
,p
,4);
922 int services
= lp_numservices();
924 struct pack_desc desc
;
925 print_queue_struct
**queue
= NULL
;
926 print_status_struct
*status
= NULL
;
927 int *subcntarr
= NULL
;
928 int queuecnt
= 0, subcnt
= 0, succnt
= 0;
930 if (!param_format
|| !output_format1
|| !p
) {
934 memset((char *)&desc
,'\0',sizeof(desc
));
936 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel
));
938 if (!prefix_ok(param_format
,"WrLeh")) {
941 if (!check_printq_info(&desc
,uLevel
,output_format1
,output_format2
)) {
943 * Patch from Scott Moomaw <scott@bridgewater.edu>
944 * to return the 'invalid info level' error if an
945 * unknown level was requested.
949 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
953 SSVALS(*rparam
,0,ERRunknownlevel
);
959 for (i
= 0; i
< services
; i
++) {
960 if (lp_snum_ok(i
) && lp_print_ok(i
) && lp_browseable(i
)) {
965 if((queue
= SMB_MALLOC_ARRAY(print_queue_struct
*, queuecnt
)) == NULL
) {
966 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
969 memset(queue
,0,queuecnt
*sizeof(print_queue_struct
*));
970 if((status
= SMB_MALLOC_ARRAY(print_status_struct
,queuecnt
)) == NULL
) {
971 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
974 memset(status
,0,queuecnt
*sizeof(print_status_struct
));
975 if((subcntarr
= SMB_MALLOC_ARRAY(int,queuecnt
)) == NULL
) {
976 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
982 for (i
= 0; i
< services
; i
++) {
983 if (lp_snum_ok(i
) && lp_print_ok(i
) && lp_browseable(i
)) {
984 subcntarr
[n
] = print_queue_status(i
, &queue
[n
],&status
[n
]);
985 subcnt
+= subcntarr
[n
];
991 *rdata
= SMB_REALLOC_LIMIT(*rdata
,mdrcnt
);
997 desc
.buflen
= mdrcnt
;
999 if (init_package(&desc
,queuecnt
,subcnt
)) {
1002 for (i
= 0; i
< services
; i
++) {
1003 if (lp_snum_ok(i
) && lp_print_ok(i
) && lp_browseable(i
)) {
1004 fill_printq_info(conn
,i
,uLevel
,&desc
,subcntarr
[n
],queue
[n
],&status
[n
]);
1006 if (desc
.errcode
== NERR_Success
) {
1013 SAFE_FREE(subcntarr
);
1015 *rdata_len
= desc
.usedlen
;
1017 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
1021 SSVALS(*rparam
,0,desc
.errcode
);
1023 SSVAL(*rparam
,4,succnt
);
1024 SSVAL(*rparam
,6,queuecnt
);
1026 for (i
= 0; i
< queuecnt
; i
++) {
1028 SAFE_FREE(queue
[i
]);
1039 SAFE_FREE(subcntarr
);
1040 for (i
= 0; i
< queuecnt
; i
++) {
1042 SAFE_FREE(queue
[i
]);
1051 /****************************************************************************
1052 Get info level for a server list query.
1053 ****************************************************************************/
1055 static BOOL
check_server_info(int uLevel
, char* id
)
1059 if (strcmp(id
,"B16") != 0) {
1064 if (strcmp(id
,"B16BBDz") != 0) {
1074 struct srv_info_struct
{
1082 /*******************************************************************
1083 Get server info lists from the files saved by nmbd. Return the
1085 ******************************************************************/
1087 static int get_server_info(uint32 servertype
,
1088 struct srv_info_struct
**servers
,
1094 BOOL local_list_only
;
1097 lines
= file_lines_load(lock_path(SERVER_LIST
), NULL
, 0);
1099 DEBUG(4,("Can't open %s - %s\n",lock_path(SERVER_LIST
),strerror(errno
)));
1103 /* request for everything is code for request all servers */
1104 if (servertype
== SV_TYPE_ALL
) {
1105 servertype
&= ~(SV_TYPE_DOMAIN_ENUM
|SV_TYPE_LOCAL_LIST_ONLY
);
1108 local_list_only
= (servertype
& SV_TYPE_LOCAL_LIST_ONLY
);
1110 DEBUG(4,("Servertype search: %8x\n",servertype
));
1112 for (i
=0;lines
[i
];i
++) {
1114 struct srv_info_struct
*s
;
1115 const char *ptr
= lines
[i
];
1122 if (count
== alloced
) {
1124 *servers
= SMB_REALLOC_ARRAY(*servers
,struct srv_info_struct
, alloced
);
1126 DEBUG(0,("get_server_info: failed to enlarge servers info struct!\n"));
1127 file_lines_free(lines
);
1130 memset((char *)((*servers
)+count
),'\0',sizeof(**servers
)*(alloced
-count
));
1132 s
= &(*servers
)[count
];
1134 if (!next_token(&ptr
,s
->name
, NULL
, sizeof(s
->name
))) {
1137 if (!next_token(&ptr
,stype
, NULL
, sizeof(stype
))) {
1140 if (!next_token(&ptr
,s
->comment
, NULL
, sizeof(s
->comment
))) {
1143 if (!next_token(&ptr
,s
->domain
, NULL
, sizeof(s
->domain
))) {
1144 /* this allows us to cope with an old nmbd */
1145 fstrcpy(s
->domain
,lp_workgroup());
1148 if (sscanf(stype
,"%X",&s
->type
) != 1) {
1149 DEBUG(4,("r:host file "));
1153 /* Filter the servers/domains we return based on what was asked for. */
1155 /* Check to see if we are being asked for a local list only. */
1156 if(local_list_only
&& ((s
->type
& SV_TYPE_LOCAL_LIST_ONLY
) == 0)) {
1157 DEBUG(4,("r: local list only"));
1161 /* doesn't match up: don't want it */
1162 if (!(servertype
& s
->type
)) {
1163 DEBUG(4,("r:serv type "));
1167 if ((servertype
& SV_TYPE_DOMAIN_ENUM
) !=
1168 (s
->type
& SV_TYPE_DOMAIN_ENUM
)) {
1169 DEBUG(4,("s: dom mismatch "));
1173 if (!strequal(domain
, s
->domain
) && !(servertype
& SV_TYPE_DOMAIN_ENUM
)) {
1177 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
1178 s
->type
&= ~SV_TYPE_LOCAL_LIST_ONLY
;
1181 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
1182 s
->name
, s
->type
, s
->comment
, s
->domain
));
1183 s
->server_added
= True
;
1186 DEBUG(4,("%20s %8x %25s %15s\n",
1187 s
->name
, s
->type
, s
->comment
, s
->domain
));
1191 file_lines_free(lines
);
1195 /*******************************************************************
1196 Fill in a server info structure.
1197 ******************************************************************/
1199 static int fill_srv_info(struct srv_info_struct
*service
,
1200 int uLevel
, char **buf
, int *buflen
,
1201 char **stringbuf
, int *stringspace
, char *baseaddr
)
1224 len
= strlen(service
->comment
)+1;
1228 *buflen
= struct_len
;
1230 return struct_len
+ len
;
1235 if (*buflen
< struct_len
) {
1242 p2
= p
+ struct_len
;
1243 l2
= *buflen
- struct_len
;
1251 push_ascii(p
,service
->name
, MAX_NETBIOSNAME_LEN
, STR_TERMINATE
);
1255 push_ascii(p
,service
->name
,MAX_NETBIOSNAME_LEN
, STR_TERMINATE
);
1256 SIVAL(p
,18,service
->type
);
1257 SIVAL(p
,22,PTR_DIFF(p2
,baseaddr
));
1258 len
+= CopyAndAdvance(&p2
,service
->comment
,&l2
);
1263 *buf
= p
+ struct_len
;
1264 *buflen
-= struct_len
;
1275 static BOOL
srv_comp(struct srv_info_struct
*s1
,struct srv_info_struct
*s2
)
1277 return(strcmp(s1
->name
,s2
->name
));
1280 /****************************************************************************
1281 View list of servers available (or possibly domains). The info is
1282 extracted from lists saved by nmbd on the local host.
1283 ****************************************************************************/
1285 static BOOL
api_RNetServerEnum(connection_struct
*conn
, uint16 vuid
,
1286 char *param
, int tpscnt
,
1287 char *data
, int tdscnt
,
1288 int mdrcnt
, int mprcnt
, char **rdata
,
1289 char **rparam
, int *rdata_len
, int *rparam_len
)
1291 char *str1
= get_safe_str_ptr(param
, tpscnt
, param
, 2);
1292 char *str2
= skip_string(param
,tpscnt
,str1
);
1293 char *p
= skip_string(param
,tpscnt
,str2
);
1294 int uLevel
= get_safe_SVAL(param
, tpscnt
, p
, 0, -1);
1295 int buf_len
= get_safe_SVAL(param
,tpscnt
, p
, 2, 0);
1296 uint32 servertype
= get_safe_IVAL(param
,tpscnt
,p
,4, 0);
1298 int data_len
, fixed_len
, string_len
;
1299 int f_len
= 0, s_len
= 0;
1300 struct srv_info_struct
*servers
=NULL
;
1301 int counted
=0,total
=0;
1304 BOOL domain_request
;
1307 if (!str1
|| !str2
|| !p
) {
1311 /* If someone sets all the bits they don't really mean to set
1312 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1315 if (servertype
== SV_TYPE_ALL
) {
1316 servertype
&= ~(SV_TYPE_DOMAIN_ENUM
|SV_TYPE_LOCAL_LIST_ONLY
);
1319 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1320 any other bit (they may just set this bit on it's own) they
1321 want all the locally seen servers. However this bit can be
1322 set on its own so set the requested servers to be
1323 ALL - DOMAIN_ENUM. */
1325 if ((servertype
& SV_TYPE_LOCAL_LIST_ONLY
) && !(servertype
& SV_TYPE_DOMAIN_ENUM
)) {
1326 servertype
= SV_TYPE_ALL
& ~(SV_TYPE_DOMAIN_ENUM
);
1329 domain_request
= ((servertype
& SV_TYPE_DOMAIN_ENUM
) != 0);
1330 local_request
= ((servertype
& SV_TYPE_LOCAL_LIST_ONLY
) != 0);
1334 if (!prefix_ok(str1
,"WrLehD")) {
1337 if (!check_server_info(uLevel
,str2
)) {
1341 DEBUG(4, ("server request level: %s %8x ", str2
, servertype
));
1342 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request
)));
1343 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request
)));
1345 if (strcmp(str1
, "WrLehDz") == 0) {
1346 if (skip_string(param
,tpscnt
,p
) == NULL
) {
1349 pull_ascii_fstring(domain
, p
);
1351 fstrcpy(domain
, lp_workgroup());
1354 if (lp_browse_list()) {
1355 total
= get_server_info(servertype
,&servers
,domain
);
1358 data_len
= fixed_len
= string_len
= 0;
1362 qsort(servers
,total
,sizeof(servers
[0]),QSORT_CAST srv_comp
);
1366 char *lastname
=NULL
;
1368 for (i
=0;i
<total
;i
++) {
1369 struct srv_info_struct
*s
= &servers
[i
];
1371 if (lastname
&& strequal(lastname
,s
->name
)) {
1375 data_len
+= fill_srv_info(s
,uLevel
,0,&f_len
,0,&s_len
,0);
1376 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1377 s
->name
, s
->type
, s
->comment
, s
->domain
));
1379 if (data_len
<= buf_len
) {
1382 string_len
+= s_len
;
1389 *rdata_len
= fixed_len
+ string_len
;
1390 *rdata
= SMB_REALLOC_LIMIT(*rdata
,*rdata_len
);
1394 memset(*rdata
,'\0',*rdata_len
);
1396 p2
= (*rdata
) + fixed_len
; /* auxilliary data (strings) will go here */
1402 char *lastname
=NULL
;
1403 int count2
= counted
;
1405 for (i
= 0; i
< total
&& count2
;i
++) {
1406 struct srv_info_struct
*s
= &servers
[i
];
1408 if (lastname
&& strequal(lastname
,s
->name
)) {
1412 fill_srv_info(s
,uLevel
,&p
,&f_len
,&p2
,&s_len
,*rdata
);
1413 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1414 s
->name
, s
->type
, s
->comment
, s
->domain
));
1420 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
1424 SSVAL(*rparam
,0,(missed
== 0 ? NERR_Success
: ERRmoredata
));
1426 SSVAL(*rparam
,4,counted
);
1427 SSVAL(*rparam
,6,counted
+missed
);
1431 DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
1432 domain
,uLevel
,counted
,counted
+missed
));
1437 /****************************************************************************
1438 command 0x34 - suspected of being a "Lookup Names" stub api
1439 ****************************************************************************/
1441 static BOOL
api_RNetGroupGetUsers(connection_struct
*conn
, uint16 vuid
,
1442 char *param
, int tpscnt
,
1443 char *data
, int tdscnt
,
1444 int mdrcnt
, int mprcnt
, char **rdata
,
1445 char **rparam
, int *rdata_len
, int *rparam_len
)
1447 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
1448 char *str2
= skip_string(param
,tpscnt
,str1
);
1449 char *p
= skip_string(param
,tpscnt
,str2
);
1450 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
1451 int buf_len
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
1455 if (!str1
|| !str2
|| !p
) {
1459 DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
1460 str1
, str2
, p
, uLevel
, buf_len
));
1462 if (!prefix_ok(str1
,"zWrLeh")) {
1469 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
1474 SSVAL(*rparam
,0,0x08AC); /* informational warning message */
1476 SSVAL(*rparam
,4,counted
);
1477 SSVAL(*rparam
,6,counted
+missed
);
1482 /****************************************************************************
1483 get info about a share
1484 ****************************************************************************/
1486 static BOOL
check_share_info(int uLevel
, char* id
)
1490 if (strcmp(id
,"B13") != 0) {
1495 if (strcmp(id
,"B13BWz") != 0) {
1500 if (strcmp(id
,"B13BWzWWWzB9B") != 0) {
1505 if (strcmp(id
,"B13BWzWWWzB9BB9BWzWWzWW") != 0) {
1515 static int fill_share_info(connection_struct
*conn
, int snum
, int uLevel
,
1516 char** buf
, int* buflen
,
1517 char** stringbuf
, int* stringspace
, char* baseaddr
)
1547 len
+= StrlenExpanded(conn
,snum
,lp_comment(snum
));
1550 len
+= strlen(lp_pathname(snum
)) + 1;
1553 *buflen
= struct_len
;
1558 return struct_len
+ len
;
1563 if ((*buflen
) < struct_len
) {
1571 p2
= p
+ struct_len
;
1572 l2
= (*buflen
) - struct_len
;
1579 push_ascii(p
,lp_servicename(snum
),13, STR_TERMINATE
);
1585 type
= STYPE_DISKTREE
;
1586 if (lp_print_ok(snum
)) {
1587 type
= STYPE_PRINTQ
;
1589 if (strequal("IPC",lp_fstype(snum
))) {
1592 SSVAL(p
,14,type
); /* device type */
1593 SIVAL(p
,16,PTR_DIFF(p2
,baseaddr
));
1594 len
+= CopyExpanded(conn
,snum
,&p2
,lp_comment(snum
),&l2
);
1598 SSVAL(p
,20,ACCESS_READ
|ACCESS_WRITE
|ACCESS_CREATE
); /* permissions */
1599 SSVALS(p
,22,-1); /* max uses */
1600 SSVAL(p
,24,1); /* current uses */
1601 SIVAL(p
,26,PTR_DIFF(p2
,baseaddr
)); /* local pathname */
1602 len
+= CopyAndAdvance(&p2
,lp_pathname(snum
),&l2
);
1603 memset(p
+30,0,SHPWLEN
+2); /* passwd (reserved), pad field */
1607 memset(p
+40,0,SHPWLEN
+2);
1618 (*buf
) = p
+ struct_len
;
1619 (*buflen
) -= struct_len
;
1621 (*stringspace
) = l2
;
1630 static BOOL
api_RNetShareGetInfo(connection_struct
*conn
,uint16 vuid
,
1631 char *param
, int tpscnt
,
1632 char *data
, int tdscnt
,
1633 int mdrcnt
,int mprcnt
,
1634 char **rdata
,char **rparam
,
1635 int *rdata_len
,int *rparam_len
)
1637 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
1638 char *str2
= skip_string(param
,tpscnt
,str1
);
1639 char *netname
= skip_string(param
,tpscnt
,str2
);
1640 char *p
= skip_string(param
,tpscnt
,netname
);
1641 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
1644 if (!str1
|| !str2
|| !netname
|| !p
) {
1648 snum
= find_service(netname
);
1653 /* check it's a supported varient */
1654 if (!prefix_ok(str1
,"zWrLh")) {
1657 if (!check_share_info(uLevel
,str2
)) {
1661 *rdata
= SMB_REALLOC_LIMIT(*rdata
,mdrcnt
);
1666 *rdata_len
= fill_share_info(conn
,snum
,uLevel
,&p
,&mdrcnt
,0,0,0);
1667 if (*rdata_len
< 0) {
1672 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
1676 SSVAL(*rparam
,0,NERR_Success
);
1677 SSVAL(*rparam
,2,0); /* converter word */
1678 SSVAL(*rparam
,4,*rdata_len
);
1683 /****************************************************************************
1684 View the list of available shares.
1686 This function is the server side of the NetShareEnum() RAP call.
1687 It fills the return buffer with share names and share comments.
1688 Note that the return buffer normally (in all known cases) allows only
1689 twelve byte strings for share names (plus one for a nul terminator).
1690 Share names longer than 12 bytes must be skipped.
1691 ****************************************************************************/
1693 static BOOL
api_RNetShareEnum( connection_struct
*conn
, uint16 vuid
,
1694 char *param
, int tpscnt
,
1695 char *data
, int tdscnt
,
1703 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
1704 char *str2
= skip_string(param
,tpscnt
,str1
);
1705 char *p
= skip_string(param
,tpscnt
,str2
);
1706 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
1707 int buf_len
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
1710 int total
=0,counted
=0;
1711 BOOL missed
= False
;
1713 int data_len
, fixed_len
, string_len
;
1714 int f_len
= 0, s_len
= 0;
1716 if (!str1
|| !str2
|| !p
) {
1720 if (!prefix_ok(str1
,"WrLeh")) {
1723 if (!check_share_info(uLevel
,str2
)) {
1727 /* Ensure all the usershares are loaded. */
1729 count
= load_usershare_shares();
1732 data_len
= fixed_len
= string_len
= 0;
1733 for (i
=0;i
<count
;i
++) {
1734 fstring servicename_dos
;
1735 if (!(lp_browseable(i
) && lp_snum_ok(i
))) {
1738 push_ascii_fstring(servicename_dos
, lp_servicename(i
));
1739 /* Maximum name length = 13. */
1740 if( lp_browseable( i
) && lp_snum_ok( i
) && (strlen(servicename_dos
) < 13)) {
1742 data_len
+= fill_share_info(conn
,i
,uLevel
,0,&f_len
,0,&s_len
,0);
1743 if (data_len
<= buf_len
) {
1746 string_len
+= s_len
;
1753 *rdata_len
= fixed_len
+ string_len
;
1754 *rdata
= SMB_REALLOC_LIMIT(*rdata
,*rdata_len
);
1758 memset(*rdata
,0,*rdata_len
);
1760 p2
= (*rdata
) + fixed_len
; /* auxiliary data (strings) will go here */
1765 for( i
= 0; i
< count
; i
++ ) {
1766 fstring servicename_dos
;
1767 if (!(lp_browseable(i
) && lp_snum_ok(i
))) {
1771 push_ascii_fstring(servicename_dos
, lp_servicename(i
));
1772 if (lp_browseable(i
) && lp_snum_ok(i
) && (strlen(servicename_dos
) < 13)) {
1773 if (fill_share_info( conn
,i
,uLevel
,&p
,&f_len
,&p2
,&s_len
,*rdata
) < 0) {
1780 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
1784 SSVAL(*rparam
,0,missed
? ERRmoredata
: NERR_Success
);
1786 SSVAL(*rparam
,4,counted
);
1787 SSVAL(*rparam
,6,total
);
1789 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
1790 counted
,total
,uLevel
,
1791 buf_len
,*rdata_len
,mdrcnt
));
1796 /****************************************************************************
1798 ****************************************************************************/
1800 static BOOL
api_RNetShareAdd(connection_struct
*conn
,uint16 vuid
,
1801 char *param
, int tpscnt
,
1802 char *data
, int tdscnt
,
1803 int mdrcnt
,int mprcnt
,
1804 char **rdata
,char **rparam
,
1805 int *rdata_len
,int *rparam_len
)
1807 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
1808 char *str2
= skip_string(param
,tpscnt
,str1
);
1809 char *p
= skip_string(param
,tpscnt
,str2
);
1810 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
1814 char *command
, *cmdname
;
1815 unsigned int offset
;
1819 if (!str1
|| !str2
|| !p
) {
1823 /* check it's a supported varient */
1824 if (!prefix_ok(str1
,RAP_WShareAdd_REQ
)) {
1827 if (!check_share_info(uLevel
,str2
)) {
1834 /* Do we have a string ? */
1835 if (skip_string(data
,mdrcnt
,data
) == NULL
) {
1838 pull_ascii_fstring(sharename
,data
);
1839 snum
= find_service(sharename
);
1840 if (snum
>= 0) { /* already exists */
1849 /* only support disk share adds */
1850 if (SVAL(data
,14)!=STYPE_DISKTREE
) {
1854 offset
= IVAL(data
, 16);
1855 if (offset
>= mdrcnt
) {
1856 res
= ERRinvalidparam
;
1860 /* Do we have a string ? */
1861 if (skip_string(data
,mdrcnt
,data
+offset
) == NULL
) {
1864 pull_ascii_fstring(comment
, offset
? (data
+offset
) : "");
1866 offset
= IVAL(data
, 26);
1868 if (offset
>= mdrcnt
) {
1869 res
= ERRinvalidparam
;
1873 /* Do we have a string ? */
1874 if (skip_string(data
,mdrcnt
,data
+offset
) == NULL
) {
1877 pull_ascii_pstring(pathname
, offset
? (data
+offset
) : "");
1879 string_replace(sharename
, '"', ' ');
1880 string_replace(pathname
, '"', ' ');
1881 string_replace(comment
, '"', ' ');
1883 cmdname
= lp_add_share_cmd();
1885 if (!cmdname
|| *cmdname
== '\0') {
1889 asprintf(&command
, "%s \"%s\" \"%s\" \"%s\" \"%s\"",
1890 lp_add_share_cmd(), dyn_CONFIGFILE
, sharename
, pathname
, comment
);
1893 DEBUG(10,("api_RNetShareAdd: Running [%s]\n", command
));
1895 if ((res
= smbrun(command
, NULL
)) != 0) {
1896 DEBUG(1,("api_RNetShareAdd: Running [%s] returned (%d)\n", command
, res
));
1902 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED
, NULL
, 0, False
, NULL
);
1909 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
1913 SSVAL(*rparam
,0,NERR_Success
);
1914 SSVAL(*rparam
,2,0); /* converter word */
1915 SSVAL(*rparam
,4,*rdata_len
);
1923 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
1928 SSVAL(*rparam
,0,res
);
1933 /****************************************************************************
1934 view list of groups available
1935 ****************************************************************************/
1937 static BOOL
api_RNetGroupEnum(connection_struct
*conn
,uint16 vuid
,
1938 char *param
, int tpscnt
,
1939 char *data
, int tdscnt
,
1940 int mdrcnt
,int mprcnt
,
1941 char **rdata
,char **rparam
,
1942 int *rdata_len
,int *rparam_len
)
1946 int resume_context
, cli_buf_size
;
1947 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
1948 char *str2
= skip_string(param
,tpscnt
,str1
);
1949 char *p
= skip_string(param
,tpscnt
,str2
);
1951 struct pdb_search
*search
;
1952 struct samr_displayentry
*entries
;
1956 if (!str1
|| !str2
|| !p
) {
1960 if (strcmp(str1
,"WrLeh") != 0) {
1965 * W-> resume context (number of users to skip)
1966 * r -> return parameter pointer to receive buffer
1967 * L -> length of receive buffer
1968 * e -> return parameter number of entries
1969 * h -> return parameter total number of users
1972 if (strcmp("B21",str2
) != 0) {
1976 /* get list of domain groups SID_DOMAIN_GRP=2 */
1978 search
= pdb_search_groups();
1981 if (search
== NULL
) {
1982 DEBUG(3,("api_RNetGroupEnum:failed to get group list"));
1986 resume_context
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
1987 cli_buf_size
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
1988 DEBUG(10,("api_RNetGroupEnum:resume context: %d, client buffer size: "
1989 "%d\n", resume_context
, cli_buf_size
));
1992 num_entries
= pdb_search_entries(search
, resume_context
, 0xffffffff,
1996 *rdata_len
= cli_buf_size
;
1997 *rdata
= SMB_REALLOC_LIMIT(*rdata
,*rdata_len
);
2004 for(i
=0; i
<num_entries
; i
++) {
2006 fstrcpy(name
, entries
[i
].account_name
);
2007 if( ((PTR_DIFF(p
,*rdata
)+21) <= *rdata_len
) ) {
2008 /* truncate the name at 21 chars. */
2009 memcpy(p
, name
, 21);
2010 DEBUG(10,("adding entry %d group %s\n", i
, p
));
2012 p
+= 5; /* Both NT4 and W2k3SP1 do padding here.
2015 /* set overflow error */
2016 DEBUG(3,("overflow on entry %d group %s\n", i
, name
));
2022 pdb_search_destroy(search
);
2024 *rdata_len
= PTR_DIFF(p
,*rdata
);
2027 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
2031 SSVAL(*rparam
, 0, errflags
);
2032 SSVAL(*rparam
, 2, 0); /* converter word */
2033 SSVAL(*rparam
, 4, i
); /* is this right?? */
2034 SSVAL(*rparam
, 6, resume_context
+num_entries
); /* is this right?? */
2039 /*******************************************************************
2040 Get groups that a user is a member of.
2041 ******************************************************************/
2043 static BOOL
api_NetUserGetGroups(connection_struct
*conn
,uint16 vuid
,
2044 char *param
, int tpscnt
,
2045 char *data
, int tdscnt
,
2046 int mdrcnt
,int mprcnt
,
2047 char **rdata
,char **rparam
,
2048 int *rdata_len
,int *rparam_len
)
2050 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2051 char *str2
= skip_string(param
,tpscnt
,str1
);
2052 char *UserName
= skip_string(param
,tpscnt
,str2
);
2053 char *p
= skip_string(param
,tpscnt
,UserName
);
2054 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2055 const char *level_string
;
2057 struct samu
*sampw
= NULL
;
2065 enum lsa_SidType type
;
2066 TALLOC_CTX
*mem_ctx
;
2068 if (!str1
|| !str2
|| !UserName
|| !p
) {
2073 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
2078 /* check it's a supported varient */
2080 if ( strcmp(str1
,"zWrLeh") != 0 )
2085 level_string
= "B21";
2091 if (strcmp(level_string
,str2
) != 0)
2094 *rdata_len
= mdrcnt
+ 1024;
2095 *rdata
= SMB_REALLOC_LIMIT(*rdata
,*rdata_len
);
2099 SSVAL(*rparam
,0,NERR_Success
);
2100 SSVAL(*rparam
,2,0); /* converter word */
2104 mem_ctx
= talloc_new(NULL
);
2105 if (mem_ctx
== NULL
) {
2106 DEBUG(0, ("talloc_new failed\n"));
2110 if ( !(sampw
= samu_new(mem_ctx
)) ) {
2111 DEBUG(0, ("samu_new() failed!\n"));
2112 TALLOC_FREE(mem_ctx
);
2116 /* Lookup the user information; This should only be one of
2117 our accounts (not remote domains) */
2119 become_root(); /* ROOT BLOCK */
2121 if (!lookup_name(mem_ctx
, UserName
, LOOKUP_NAME_ALL
,
2122 NULL
, NULL
, &user_sid
, &type
)) {
2123 DEBUG(10, ("lookup_name(%s) failed\n", UserName
));
2127 if (type
!= SID_NAME_USER
) {
2128 DEBUG(10, ("%s is a %s, not a user\n", UserName
,
2129 sid_type_lookup(type
)));
2133 if ( !pdb_getsampwsid(sampw
, &user_sid
) ) {
2134 DEBUG(10, ("pdb_getsampwsid(%s) failed for user %s\n",
2135 sid_string_static(&user_sid
), UserName
));
2143 result
= pdb_enum_group_memberships(mem_ctx
, sampw
,
2144 &sids
, &gids
, &num_groups
);
2146 if (!NT_STATUS_IS_OK(result
)) {
2147 DEBUG(10, ("pdb_enum_group_memberships failed for %s\n",
2152 for (i
=0; i
<num_groups
; i
++) {
2154 const char *grp_name
;
2156 if ( lookup_sid(mem_ctx
, &sids
[i
], NULL
, &grp_name
, NULL
) ) {
2157 pstrcpy(p
, grp_name
);
2163 *rdata_len
= PTR_DIFF(p
,*rdata
);
2165 SSVAL(*rparam
,4,count
); /* is this right?? */
2166 SSVAL(*rparam
,6,count
); /* is this right?? */
2171 unbecome_root(); /* END ROOT BLOCK */
2173 TALLOC_FREE(mem_ctx
);
2178 /*******************************************************************
2180 ******************************************************************/
2182 static BOOL
api_RNetUserEnum(connection_struct
*conn
, uint16 vuid
,
2183 char *param
, int tpscnt
,
2184 char *data
, int tdscnt
,
2185 int mdrcnt
,int mprcnt
,
2186 char **rdata
,char **rparam
,
2187 int *rdata_len
,int *rparam_len
)
2192 int i
, resume_context
, cli_buf_size
;
2193 struct pdb_search
*search
;
2194 struct samr_displayentry
*users
;
2196 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2197 char *str2
= skip_string(param
,tpscnt
,str1
);
2198 char *p
= skip_string(param
,tpscnt
,str2
);
2200 if (!str1
|| !str2
|| !p
) {
2204 if (strcmp(str1
,"WrLeh") != 0)
2207 * W-> resume context (number of users to skip)
2208 * r -> return parameter pointer to receive buffer
2209 * L -> length of receive buffer
2210 * e -> return parameter number of entries
2211 * h -> return parameter total number of users
2214 resume_context
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2215 cli_buf_size
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
2216 DEBUG(10,("api_RNetUserEnum:resume context: %d, client buffer size: %d\n",
2217 resume_context
, cli_buf_size
));
2220 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
2225 /* check it's a supported varient */
2226 if (strcmp("B21",str2
) != 0)
2229 *rdata_len
= cli_buf_size
;
2230 *rdata
= SMB_REALLOC_LIMIT(*rdata
,*rdata_len
);
2238 search
= pdb_search_users(ACB_NORMAL
);
2240 if (search
== NULL
) {
2241 DEBUG(0, ("api_RNetUserEnum:unable to open sam database.\n"));
2246 num_users
= pdb_search_entries(search
, resume_context
, 0xffffffff,
2250 errflags
=NERR_Success
;
2252 for (i
=0; i
<num_users
; i
++) {
2253 const char *name
= users
[i
].account_name
;
2255 if(((PTR_DIFF(p
,*rdata
)+21)<=*rdata_len
)&&(strlen(name
)<=21)) {
2257 DEBUG(10,("api_RNetUserEnum:adding entry %d username "
2258 "%s\n",count_sent
,p
));
2262 /* set overflow error */
2263 DEBUG(10,("api_RNetUserEnum:overflow on entry %d "
2264 "username %s\n",count_sent
,name
));
2270 pdb_search_destroy(search
);
2272 *rdata_len
= PTR_DIFF(p
,*rdata
);
2274 SSVAL(*rparam
,0,errflags
);
2275 SSVAL(*rparam
,2,0); /* converter word */
2276 SSVAL(*rparam
,4,count_sent
); /* is this right?? */
2277 SSVAL(*rparam
,6,num_users
); /* is this right?? */
2282 /****************************************************************************
2283 Get the time of day info.
2284 ****************************************************************************/
2286 static BOOL
api_NetRemoteTOD(connection_struct
*conn
,uint16 vuid
,
2287 char *param
, int tpscnt
,
2288 char *data
, int tdscnt
,
2289 int mdrcnt
,int mprcnt
,
2290 char **rdata
,char **rparam
,
2291 int *rdata_len
,int *rparam_len
)
2294 time_t unixdate
= time(NULL
);
2298 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
2304 *rdata
= SMB_REALLOC_LIMIT(*rdata
,*rdata_len
);
2309 SSVAL(*rparam
,0,NERR_Success
);
2310 SSVAL(*rparam
,2,0); /* converter word */
2314 srv_put_dos_date3(p
,0,unixdate
); /* this is the time that is looked at
2315 by NT in a "net time" operation,
2316 it seems to ignore the one below */
2318 /* the client expects to get localtime, not GMT, in this bit
2319 (I think, this needs testing) */
2320 t
= localtime(&unixdate
);
2325 SIVAL(p
,4,0); /* msecs ? */
2326 SCVAL(p
,8,t
->tm_hour
);
2327 SCVAL(p
,9,t
->tm_min
);
2328 SCVAL(p
,10,t
->tm_sec
);
2329 SCVAL(p
,11,0); /* hundredths of seconds */
2330 SSVALS(p
,12,get_time_zone(unixdate
)/60); /* timezone in minutes from GMT */
2331 SSVAL(p
,14,10000); /* timer interval in 0.0001 of sec */
2332 SCVAL(p
,16,t
->tm_mday
);
2333 SCVAL(p
,17,t
->tm_mon
+ 1);
2334 SSVAL(p
,18,1900+t
->tm_year
);
2335 SCVAL(p
,20,t
->tm_wday
);
2340 /****************************************************************************
2341 Set the user password.
2342 *****************************************************************************/
2344 static BOOL
api_SetUserPassword(connection_struct
*conn
,uint16 vuid
,
2345 char *param
, int tpscnt
,
2346 char *data
, int tdscnt
,
2347 int mdrcnt
,int mprcnt
,
2348 char **rdata
,char **rparam
,
2349 int *rdata_len
,int *rparam_len
)
2351 char *np
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2354 fstring pass1
,pass2
;
2356 /* Skip 2 strings. */
2357 p
= skip_string(param
,tpscnt
,np
);
2358 p
= skip_string(param
,tpscnt
,p
);
2364 /* Do we have a string ? */
2365 if (skip_string(param
,tpscnt
,p
) == NULL
) {
2368 pull_ascii_fstring(user
,p
);
2370 p
= skip_string(param
,tpscnt
,p
);
2375 memset(pass1
,'\0',sizeof(pass1
));
2376 memset(pass2
,'\0',sizeof(pass2
));
2378 * We use 31 here not 32 as we're checking
2379 * the last byte we want to access is safe.
2381 if (!is_offset_safe(param
,tpscnt
,p
,31)) {
2385 memcpy(pass2
,p
+16,16);
2388 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
2395 SSVAL(*rparam
,0,NERR_badpass
);
2396 SSVAL(*rparam
,2,0); /* converter word */
2398 DEBUG(3,("Set password for <%s>\n",user
));
2401 * Attempt to verify the old password against smbpasswd entries
2402 * Win98 clients send old and new password in plaintext for this call.
2406 auth_serversupplied_info
*server_info
= NULL
;
2407 DATA_BLOB password
= data_blob(pass1
, strlen(pass1
)+1);
2409 if (NT_STATUS_IS_OK(check_plaintext_password(user
,password
,&server_info
))) {
2412 if (NT_STATUS_IS_OK(change_oem_password(server_info
->sam_account
, pass1
, pass2
, False
, NULL
))) {
2413 SSVAL(*rparam
,0,NERR_Success
);
2417 TALLOC_FREE(server_info
);
2419 data_blob_clear_free(&password
);
2423 * If the plaintext change failed, attempt
2424 * the old encrypted method. NT will generate this
2425 * after trying the samr method. Note that this
2426 * method is done as a last resort as this
2427 * password change method loses the NT password hash
2428 * and cannot change the UNIX password as no plaintext
2432 if(SVAL(*rparam
,0) != NERR_Success
) {
2433 struct samu
*hnd
= NULL
;
2435 if (check_lanman_password(user
,(unsigned char *)pass1
,(unsigned char *)pass2
, &hnd
)) {
2437 if (change_lanman_password(hnd
,(uchar
*)pass2
)) {
2438 SSVAL(*rparam
,0,NERR_Success
);
2445 memset((char *)pass1
,'\0',sizeof(fstring
));
2446 memset((char *)pass2
,'\0',sizeof(fstring
));
2451 /****************************************************************************
2452 Set the user password (SamOEM version - gets plaintext).
2453 ****************************************************************************/
2455 static BOOL
api_SamOEMChangePassword(connection_struct
*conn
,uint16 vuid
,
2456 char *param
, int tpscnt
,
2457 char *data
, int tdscnt
,
2458 int mdrcnt
,int mprcnt
,
2459 char **rdata
,char **rparam
,
2460 int *rdata_len
,int *rparam_len
)
2463 char *p
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2465 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
2475 SSVAL(*rparam
,0,NERR_badpass
);
2478 * Check the parameter definition is correct.
2481 /* Do we have a string ? */
2482 if (skip_string(param
,tpscnt
,p
) == 0) {
2485 if(!strequal(p
, "zsT")) {
2486 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", p
));
2489 p
= skip_string(param
, tpscnt
, p
);
2494 /* Do we have a string ? */
2495 if (skip_string(param
,tpscnt
,p
) == 0) {
2498 if(!strequal(p
, "B516B16")) {
2499 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p
));
2502 p
= skip_string(param
,tpscnt
,p
);
2506 /* Do we have a string ? */
2507 if (skip_string(param
,tpscnt
,p
) == 0) {
2510 p
+= pull_ascii_fstring(user
,p
);
2512 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user
));
2515 * Pass the user through the NT -> unix user mapping
2519 (void)map_username(user
);
2521 if (NT_STATUS_IS_OK(pass_oem_change(user
, (uchar
*) data
, (uchar
*)&data
[516], NULL
, NULL
, NULL
))) {
2522 SSVAL(*rparam
,0,NERR_Success
);
2528 /****************************************************************************
2531 ****************************************************************************/
2533 static BOOL
api_RDosPrintJobDel(connection_struct
*conn
,uint16 vuid
,
2534 char *param
, int tpscnt
,
2535 char *data
, int tdscnt
,
2536 int mdrcnt
,int mprcnt
,
2537 char **rdata
,char **rparam
,
2538 int *rdata_len
,int *rparam_len
)
2540 int function
= get_safe_SVAL(param
,tpscnt
,param
,0,0);
2541 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2542 char *str2
= skip_string(param
,tpscnt
,str1
);
2543 char *p
= skip_string(param
,tpscnt
,str2
);
2548 WERROR werr
= WERR_OK
;
2550 if (!str1
|| !str2
|| !p
) {
2554 * We use 1 here not 2 as we're checking
2555 * the last byte we want to access is safe.
2557 if (!is_offset_safe(param
,tpscnt
,p
,1)) {
2560 if(!rap_to_pjobid(SVAL(p
,0), sharename
, &jobid
))
2563 /* check it's a supported varient */
2564 if (!(strcsequal(str1
,"W") && strcsequal(str2
,"")))
2568 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
2574 if (!print_job_exists(sharename
, jobid
)) {
2575 errcode
= NERR_JobNotFound
;
2579 snum
= lp_servicenumber( sharename
);
2581 errcode
= NERR_DestNotFound
;
2585 errcode
= NERR_notsupported
;
2588 case 81: /* delete */
2589 if (print_job_delete(¤t_user
, snum
, jobid
, &werr
))
2590 errcode
= NERR_Success
;
2592 case 82: /* pause */
2593 if (print_job_pause(¤t_user
, snum
, jobid
, &werr
))
2594 errcode
= NERR_Success
;
2596 case 83: /* resume */
2597 if (print_job_resume(¤t_user
, snum
, jobid
, &werr
))
2598 errcode
= NERR_Success
;
2602 if (!W_ERROR_IS_OK(werr
))
2603 errcode
= W_ERROR_V(werr
);
2606 SSVAL(*rparam
,0,errcode
);
2607 SSVAL(*rparam
,2,0); /* converter word */
2612 /****************************************************************************
2613 Purge a print queue - or pause or resume it.
2614 ****************************************************************************/
2616 static BOOL
api_WPrintQueueCtrl(connection_struct
*conn
,uint16 vuid
,
2617 char *param
, int tpscnt
,
2618 char *data
, int tdscnt
,
2619 int mdrcnt
,int mprcnt
,
2620 char **rdata
,char **rparam
,
2621 int *rdata_len
,int *rparam_len
)
2623 int function
= get_safe_SVAL(param
,tpscnt
,param
,0,0);
2624 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2625 char *str2
= skip_string(param
,tpscnt
,str1
);
2626 char *QueueName
= skip_string(param
,tpscnt
,str2
);
2627 int errcode
= NERR_notsupported
;
2629 WERROR werr
= WERR_OK
;
2631 if (!str1
|| !str2
|| !QueueName
) {
2635 /* check it's a supported varient */
2636 if (!(strcsequal(str1
,"z") && strcsequal(str2
,"")))
2640 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
2646 if (skip_string(param
,tpscnt
,QueueName
) == NULL
) {
2649 snum
= print_queue_snum(QueueName
);
2652 errcode
= NERR_JobNotFound
;
2657 case 74: /* Pause queue */
2658 if (print_queue_pause(¤t_user
, snum
, &werr
)) errcode
= NERR_Success
;
2660 case 75: /* Resume queue */
2661 if (print_queue_resume(¤t_user
, snum
, &werr
)) errcode
= NERR_Success
;
2663 case 103: /* Purge */
2664 if (print_queue_purge(¤t_user
, snum
, &werr
)) errcode
= NERR_Success
;
2668 if (!W_ERROR_IS_OK(werr
)) errcode
= W_ERROR_V(werr
);
2671 SSVAL(*rparam
,0,errcode
);
2672 SSVAL(*rparam
,2,0); /* converter word */
2677 /****************************************************************************
2678 set the property of a print job (undocumented?)
2679 ? function = 0xb -> set name of print job
2680 ? function = 0x6 -> move print job up/down
2681 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
2682 or <WWsTP> <WB21BB16B10zWWzDDz>
2683 ****************************************************************************/
2685 static int check_printjob_info(struct pack_desc
* desc
,
2686 int uLevel
, char* id
)
2688 desc
->subformat
= NULL
;
2690 case 0: desc
->format
= "W"; break;
2691 case 1: desc
->format
= "WB21BB16B10zWWzDDz"; break;
2692 case 2: desc
->format
= "WWzWWDDzz"; break;
2693 case 3: desc
->format
= "WWzWWDDzzzzzzzzzzlz"; break;
2694 case 4: desc
->format
= "WWzWWDDzzzzzDDDDDDD"; break;
2696 DEBUG(0,("check_printjob_info: invalid level %d\n",
2700 if (id
== NULL
|| strcmp(desc
->format
,id
) != 0) {
2701 DEBUG(0,("check_printjob_info: invalid format %s\n",
2702 id
? id
: "<NULL>" ));
2708 static BOOL
api_PrintJobInfo(connection_struct
*conn
, uint16 vuid
,
2709 char *param
, int tpscnt
,
2710 char *data
, int tdscnt
,
2711 int mdrcnt
,int mprcnt
,
2712 char **rdata
,char **rparam
,
2713 int *rdata_len
,int *rparam_len
)
2715 struct pack_desc desc
;
2716 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2717 char *str2
= skip_string(param
,tpscnt
,str1
);
2718 char *p
= skip_string(param
,tpscnt
,str2
);
2721 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,2,-1);
2722 int function
= get_safe_SVAL(param
,tpscnt
,p
,4,-1);
2725 if (!str1
|| !str2
|| !p
) {
2729 * We use 1 here not 2 as we're checking
2730 * the last byte we want to access is safe.
2732 if (!is_offset_safe(param
,tpscnt
,p
,1)) {
2735 if(!rap_to_pjobid(SVAL(p
,0), sharename
, &jobid
))
2738 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
2743 if (!share_defined(sharename
)) {
2744 DEBUG(0,("api_PrintJobInfo: sharen [%s] not defined\n",
2751 /* check it's a supported varient */
2752 if ((strcmp(str1
,"WWsTP")) ||
2753 (!check_printjob_info(&desc
,uLevel
,str2
)))
2756 if (!print_job_exists(sharename
, jobid
)) {
2757 errcode
=NERR_JobNotFound
;
2761 errcode
= NERR_notsupported
;
2765 /* change job place in the queue,
2766 data gives the new place */
2767 place
= SVAL(data
,0);
2768 if (print_job_set_place(sharename
, jobid
, place
)) {
2769 errcode
=NERR_Success
;
2774 /* change print job name, data gives the name */
2775 if (print_job_set_name(sharename
, jobid
, data
)) {
2776 errcode
=NERR_Success
;
2785 SSVALS(*rparam
,0,errcode
);
2786 SSVAL(*rparam
,2,0); /* converter word */
2792 /****************************************************************************
2793 Get info about the server.
2794 ****************************************************************************/
2796 static BOOL
api_RNetServerGetInfo(connection_struct
*conn
,uint16 vuid
,
2797 char *param
, int tpscnt
,
2798 char *data
, int tdscnt
,
2799 int mdrcnt
,int mprcnt
,
2800 char **rdata
,char **rparam
,
2801 int *rdata_len
,int *rparam_len
)
2803 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2804 char *str2
= skip_string(param
,tpscnt
,str1
);
2805 char *p
= skip_string(param
,tpscnt
,str2
);
2806 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2810 if (!str1
|| !str2
|| !p
) {
2814 DEBUG(4,("NetServerGetInfo level %d\n",uLevel
));
2816 /* check it's a supported varient */
2817 if (!prefix_ok(str1
,"WrLh")) {
2823 if (strcmp(str2
,"B16") != 0) {
2829 if (strcmp(str2
,"B16BBDz") != 0) {
2835 if (strcmp(str2
,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")!= 0) {
2841 if (strcmp(str2
,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz") != 0) {
2847 if (strcmp(str2
,"DN") != 0) {
2853 if (strcmp(str2
,"B16BBDzWWzzz") != 0) {
2862 *rdata_len
= mdrcnt
;
2863 *rdata
= SMB_REALLOC_LIMIT(*rdata
,*rdata_len
);
2869 p2
= p
+ struct_len
;
2871 srvstr_push(NULL
, p
,global_myname(),16,
2872 STR_ASCII
|STR_UPPER
|STR_TERMINATE
);
2876 struct srv_info_struct
*servers
=NULL
;
2879 uint32 servertype
= lp_default_server_announce();
2881 push_ascii(comment
,lp_serverstring(), MAX_SERVER_STRING_LENGTH
,STR_TERMINATE
);
2883 if ((count
=get_server_info(SV_TYPE_ALL
,&servers
,lp_workgroup()))>0) {
2884 for (i
=0;i
<count
;i
++) {
2885 if (strequal(servers
[i
].name
,global_myname())) {
2886 servertype
= servers
[i
].type
;
2887 push_ascii(comment
,servers
[i
].comment
,sizeof(pstring
),STR_TERMINATE
);
2894 SCVAL(p
,0,lp_major_announce_version());
2895 SCVAL(p
,1,lp_minor_announce_version());
2896 SIVAL(p
,2,servertype
);
2898 if (mdrcnt
== struct_len
) {
2901 SIVAL(p
,6,PTR_DIFF(p2
,*rdata
));
2902 standard_sub_advanced(lp_servicename(SNUM(conn
)), conn
->user
,
2903 conn
->connectpath
, conn
->gid
,
2904 get_current_username(),
2905 current_user_info
.domain
,
2906 comment
, sizeof(comment
));
2907 StrnCpy(p2
,comment
,MAX(mdrcnt
- struct_len
,0));
2908 p2
= skip_string(*rdata
,*rdata_len
,p2
);
2916 return False
; /* not yet implemented */
2919 *rdata_len
= PTR_DIFF(p2
,*rdata
);
2922 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
2926 SSVAL(*rparam
,0,NERR_Success
);
2927 SSVAL(*rparam
,2,0); /* converter word */
2928 SSVAL(*rparam
,4,*rdata_len
);
2933 /****************************************************************************
2934 Get info about the server.
2935 ****************************************************************************/
2937 static BOOL
api_NetWkstaGetInfo(connection_struct
*conn
,uint16 vuid
,
2938 char *param
, int tpscnt
,
2939 char *data
, int tdscnt
,
2940 int mdrcnt
,int mprcnt
,
2941 char **rdata
,char **rparam
,
2942 int *rdata_len
,int *rparam_len
)
2944 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2945 char *str2
= skip_string(param
,tpscnt
,str1
);
2946 char *p
= skip_string(param
,tpscnt
,str2
);
2948 int level
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2950 if (!str1
|| !str2
|| !p
) {
2954 DEBUG(4,("NetWkstaGetInfo level %d\n",level
));
2957 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
2962 /* check it's a supported varient */
2963 if (!(level
==10 && strcsequal(str1
,"WrLh") && strcsequal(str2
,"zzzBBzz"))) {
2967 *rdata_len
= mdrcnt
+ 1024;
2968 *rdata
= SMB_REALLOC_LIMIT(*rdata
,*rdata_len
);
2973 SSVAL(*rparam
,0,NERR_Success
);
2974 SSVAL(*rparam
,2,0); /* converter word */
2977 p2
= get_safe_ptr(*rdata
,*rdata_len
,p
,22);
2982 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* host name */
2983 pstrcpy(p2
,get_local_machine_name());
2985 p2
= skip_string(*rdata
,*rdata_len
,p2
);
2991 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
));
2992 pstrcpy(p2
,current_user_info
.smb_name
);
2993 p2
= skip_string(*rdata
,*rdata_len
,p2
);
2999 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* login domain */
3000 pstrcpy(p2
,lp_workgroup());
3002 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3008 SCVAL(p
,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
3009 SCVAL(p
,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
3012 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
));
3013 pstrcpy(p2
,lp_workgroup()); /* don't know. login domain?? */
3014 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3020 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* don't know */
3022 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3028 *rdata_len
= PTR_DIFF(p2
,*rdata
);
3030 SSVAL(*rparam
,4,*rdata_len
);
3035 /****************************************************************************
3036 get info about a user
3038 struct user_info_11 {
3039 char usri11_name[21]; 0-20
3041 char *usri11_comment; 22-25
3042 char *usri11_usr_comment; 26-29
3043 unsigned short usri11_priv; 30-31
3044 unsigned long usri11_auth_flags; 32-35
3045 long usri11_password_age; 36-39
3046 char *usri11_homedir; 40-43
3047 char *usri11_parms; 44-47
3048 long usri11_last_logon; 48-51
3049 long usri11_last_logoff; 52-55
3050 unsigned short usri11_bad_pw_count; 56-57
3051 unsigned short usri11_num_logons; 58-59
3052 char *usri11_logon_server; 60-63
3053 unsigned short usri11_country_code; 64-65
3054 char *usri11_workstations; 66-69
3055 unsigned long usri11_max_storage; 70-73
3056 unsigned short usri11_units_per_week; 74-75
3057 unsigned char *usri11_logon_hours; 76-79
3058 unsigned short usri11_code_page; 80-81
3063 usri11_name specifies the user name for which information is retireved
3065 usri11_pad aligns the next data structure element to a word boundary
3067 usri11_comment is a null terminated ASCII comment
3069 usri11_user_comment is a null terminated ASCII comment about the user
3071 usri11_priv specifies the level of the privilege assigned to the user.
3072 The possible values are:
3074 Name Value Description
3075 USER_PRIV_GUEST 0 Guest privilege
3076 USER_PRIV_USER 1 User privilege
3077 USER_PRV_ADMIN 2 Administrator privilege
3079 usri11_auth_flags specifies the account operator privileges. The
3080 possible values are:
3082 Name Value Description
3083 AF_OP_PRINT 0 Print operator
3086 Leach, Naik [Page 28]
3090 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
3093 AF_OP_COMM 1 Communications operator
3094 AF_OP_SERVER 2 Server operator
3095 AF_OP_ACCOUNTS 3 Accounts operator
3098 usri11_password_age specifies how many seconds have elapsed since the
3099 password was last changed.
3101 usri11_home_dir points to a null terminated ASCII string that contains
3102 the path name of the user's home directory.
3104 usri11_parms points to a null terminated ASCII string that is set
3105 aside for use by applications.
3107 usri11_last_logon specifies the time when the user last logged on.
3108 This value is stored as the number of seconds elapsed since
3109 00:00:00, January 1, 1970.
3111 usri11_last_logoff specifies the time when the user last logged off.
3112 This value is stored as the number of seconds elapsed since
3113 00:00:00, January 1, 1970. A value of 0 means the last logoff
3116 usri11_bad_pw_count specifies the number of incorrect passwords
3117 entered since the last successful logon.
3119 usri11_log1_num_logons specifies the number of times this user has
3120 logged on. A value of -1 means the number of logons is unknown.
3122 usri11_logon_server points to a null terminated ASCII string that
3123 contains the name of the server to which logon requests are sent.
3124 A null string indicates logon requests should be sent to the
3127 usri11_country_code specifies the country code for the user's language
3130 usri11_workstations points to a null terminated ASCII string that
3131 contains the names of workstations the user may log on from.
3132 There may be up to 8 workstations, with the names separated by
3133 commas. A null strings indicates there are no restrictions.
3135 usri11_max_storage specifies the maximum amount of disk space the user
3136 can occupy. A value of 0xffffffff indicates there are no
3139 usri11_units_per_week specifies the equal number of time units into
3140 which a week is divided. This value must be equal to 168.
3142 usri11_logon_hours points to a 21 byte (168 bits) string that
3143 specifies the time during which the user can log on. Each bit
3144 represents one unique hour in a week. The first bit (bit 0, word
3145 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
3149 Leach, Naik [Page 29]
3153 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
3156 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
3157 are no restrictions.
3159 usri11_code_page specifies the code page for the user's language of
3162 All of the pointers in this data structure need to be treated
3163 specially. The pointer is a 32 bit pointer. The higher 16 bits need
3164 to be ignored. The converter word returned in the parameters section
3165 needs to be subtracted from the lower 16 bits to calculate an offset
3166 into the return buffer where this ASCII string resides.
3168 There is no auxiliary data in the response.
3170 ****************************************************************************/
3172 #define usri11_name 0
3173 #define usri11_pad 21
3174 #define usri11_comment 22
3175 #define usri11_usr_comment 26
3176 #define usri11_full_name 30
3177 #define usri11_priv 34
3178 #define usri11_auth_flags 36
3179 #define usri11_password_age 40
3180 #define usri11_homedir 44
3181 #define usri11_parms 48
3182 #define usri11_last_logon 52
3183 #define usri11_last_logoff 56
3184 #define usri11_bad_pw_count 60
3185 #define usri11_num_logons 62
3186 #define usri11_logon_server 64
3187 #define usri11_country_code 68
3188 #define usri11_workstations 70
3189 #define usri11_max_storage 74
3190 #define usri11_units_per_week 78
3191 #define usri11_logon_hours 80
3192 #define usri11_code_page 84
3193 #define usri11_end 86
3195 #define USER_PRIV_GUEST 0
3196 #define USER_PRIV_USER 1
3197 #define USER_PRIV_ADMIN 2
3199 #define AF_OP_PRINT 0
3200 #define AF_OP_COMM 1
3201 #define AF_OP_SERVER 2
3202 #define AF_OP_ACCOUNTS 3
3205 static BOOL
api_RNetUserGetInfo(connection_struct
*conn
, uint16 vuid
,
3206 char *param
, int tpscnt
,
3207 char *data
, int tdscnt
,
3208 int mdrcnt
,int mprcnt
,
3209 char **rdata
,char **rparam
,
3210 int *rdata_len
,int *rparam_len
)
3212 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3213 char *str2
= skip_string(param
,tpscnt
,str1
);
3214 char *UserName
= skip_string(param
,tpscnt
,str2
);
3215 char *p
= skip_string(param
,tpscnt
,UserName
);
3216 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3218 const char *level_string
;
3220 /* get NIS home of a previously validated user - simeon */
3221 /* With share level security vuid will always be zero.
3222 Don't depend on vuser being non-null !!. JRA */
3223 user_struct
*vuser
= get_valid_user_struct(vuid
);
3225 DEBUG(3,(" Username of UID %d is %s\n", (int)vuser
->uid
,
3226 vuser
->user
.unix_name
));
3229 if (!str1
|| !str2
|| !UserName
|| !p
) {
3234 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
3239 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel
));
3241 /* check it's a supported variant */
3242 if (strcmp(str1
,"zWrLh") != 0) {
3246 case 0: level_string
= "B21"; break;
3247 case 1: level_string
= "B21BB16DWzzWz"; break;
3248 case 2: level_string
= "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
3249 case 10: level_string
= "B21Bzzz"; break;
3250 case 11: level_string
= "B21BzzzWDDzzDDWWzWzDWb21W"; break;
3251 default: return False
;
3254 if (strcmp(level_string
,str2
) != 0) {
3258 *rdata_len
= mdrcnt
+ 1024;
3259 *rdata
= SMB_REALLOC_LIMIT(*rdata
,*rdata_len
);
3264 SSVAL(*rparam
,0,NERR_Success
);
3265 SSVAL(*rparam
,2,0); /* converter word */
3268 p2
= get_safe_ptr(*rdata
,*rdata_len
,p
,usri11_end
);
3274 fstrcpy(p
+usri11_name
,UserName
); /* 21 bytes - user name */
3277 SCVAL(p
,usri11_pad
,0); /* padding - 1 byte */
3282 SIVAL(p
,usri11_comment
,PTR_DIFF(p2
,p
)); /* comment */
3283 pstrcpy(p2
,"Comment");
3284 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3289 SIVAL(p
,usri11_usr_comment
,PTR_DIFF(p2
,p
)); /* user_comment */
3290 pstrcpy(p2
,"UserComment");
3291 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3296 /* EEK! the cifsrap.txt doesn't have this in!!!! */
3297 SIVAL(p
,usri11_full_name
,PTR_DIFF(p2
,p
)); /* full name */
3298 pstrcpy(p2
,((vuser
!= NULL
) ? vuser
->user
.full_name
: UserName
));
3299 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3306 /* modelled after NTAS 3.51 reply */
3307 SSVAL(p
,usri11_priv
,conn
->admin_user
?USER_PRIV_ADMIN
:USER_PRIV_USER
);
3308 SIVAL(p
,usri11_auth_flags
,AF_OP_PRINT
); /* auth flags */
3309 SIVALS(p
,usri11_password_age
,-1); /* password age */
3310 SIVAL(p
,usri11_homedir
,PTR_DIFF(p2
,p
)); /* home dir */
3311 pstrcpy(p2
, vuser
&& vuser
->homedir
? vuser
->homedir
: "");
3312 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3316 SIVAL(p
,usri11_parms
,PTR_DIFF(p2
,p
)); /* parms */
3318 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3322 SIVAL(p
,usri11_last_logon
,0); /* last logon */
3323 SIVAL(p
,usri11_last_logoff
,0); /* last logoff */
3324 SSVALS(p
,usri11_bad_pw_count
,-1); /* bad pw counts */
3325 SSVALS(p
,usri11_num_logons
,-1); /* num logons */
3326 SIVAL(p
,usri11_logon_server
,PTR_DIFF(p2
,p
)); /* logon server */
3327 pstrcpy(p2
,"\\\\*");
3328 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3332 SSVAL(p
,usri11_country_code
,0); /* country code */
3334 SIVAL(p
,usri11_workstations
,PTR_DIFF(p2
,p
)); /* workstations */
3336 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3341 SIVALS(p
,usri11_max_storage
,-1); /* max storage */
3342 SSVAL(p
,usri11_units_per_week
,168); /* units per week */
3343 SIVAL(p
,usri11_logon_hours
,PTR_DIFF(p2
,p
)); /* logon hours */
3345 /* a simple way to get logon hours at all times. */
3347 SCVAL(p2
,21,0); /* fix zero termination */
3348 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3353 SSVAL(p
,usri11_code_page
,0); /* code page */
3356 if (uLevel
== 1 || uLevel
== 2) {
3357 memset(p
+22,' ',16); /* password */
3358 SIVALS(p
,38,-1); /* password age */
3360 conn
->admin_user
?USER_PRIV_ADMIN
:USER_PRIV_USER
);
3361 SIVAL(p
,44,PTR_DIFF(p2
,*rdata
)); /* home dir */
3362 pstrcpy(p2
, vuser
&& vuser
->homedir
? vuser
->homedir
: "");
3363 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3367 SIVAL(p
,48,PTR_DIFF(p2
,*rdata
)); /* comment */
3369 SSVAL(p
,52,0); /* flags */
3370 SIVAL(p
,54,PTR_DIFF(p2
,*rdata
)); /* script_path */
3371 pstrcpy(p2
,vuser
&& vuser
->logon_script
? vuser
->logon_script
: "");
3372 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3377 SIVAL(p
,60,0); /* auth_flags */
3378 SIVAL(p
,64,PTR_DIFF(p2
,*rdata
)); /* full_name */
3379 pstrcpy(p2
,((vuser
!= NULL
) ? vuser
->user
.full_name
: UserName
));
3380 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3384 SIVAL(p
,68,0); /* urs_comment */
3385 SIVAL(p
,72,PTR_DIFF(p2
,*rdata
)); /* parms */
3387 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3391 SIVAL(p
,76,0); /* workstations */
3392 SIVAL(p
,80,0); /* last_logon */
3393 SIVAL(p
,84,0); /* last_logoff */
3394 SIVALS(p
,88,-1); /* acct_expires */
3395 SIVALS(p
,92,-1); /* max_storage */
3396 SSVAL(p
,96,168); /* units_per_week */
3397 SIVAL(p
,98,PTR_DIFF(p2
,*rdata
)); /* logon_hours */
3400 SSVALS(p
,102,-1); /* bad_pw_count */
3401 SSVALS(p
,104,-1); /* num_logons */
3402 SIVAL(p
,106,PTR_DIFF(p2
,*rdata
)); /* logon_server */
3405 pstrcpy(tmp
, "\\\\%L");
3406 standard_sub_basic("", "", tmp
, sizeof(tmp
));
3409 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3413 SSVAL(p
,110,49); /* country_code */
3414 SSVAL(p
,112,860); /* code page */
3418 *rdata_len
= PTR_DIFF(p2
,*rdata
);
3420 SSVAL(*rparam
,4,*rdata_len
); /* is this right?? */
3425 static BOOL
api_WWkstaUserLogon(connection_struct
*conn
,uint16 vuid
,
3426 char *param
, int tpscnt
,
3427 char *data
, int tdscnt
,
3428 int mdrcnt
,int mprcnt
,
3429 char **rdata
,char **rparam
,
3430 int *rdata_len
,int *rparam_len
)
3432 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3433 char *str2
= skip_string(param
,tpscnt
,str1
);
3434 char *p
= skip_string(param
,tpscnt
,str2
);
3436 struct pack_desc desc
;
3438 /* With share level security vuid will always be zero.
3439 Don't depend on vuser being non-null !!. JRA */
3440 user_struct
*vuser
= get_valid_user_struct(vuid
);
3442 if (!str1
|| !str2
|| !p
) {
3447 DEBUG(3,(" Username of UID %d is %s\n", (int)vuser
->uid
,
3448 vuser
->user
.unix_name
));
3451 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3452 name
= get_safe_str_ptr(param
,tpscnt
,p
,2);
3457 memset((char *)&desc
,'\0',sizeof(desc
));
3459 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel
,name
));
3461 /* check it's a supported varient */
3462 if (strcmp(str1
,"OOWb54WrLh") != 0) {
3465 if (uLevel
!= 1 || strcmp(str2
,"WB21BWDWWDDDDDDDzzzD") != 0) {
3469 *rdata
= SMB_REALLOC_LIMIT(*rdata
,mdrcnt
);
3476 desc
.buflen
= mdrcnt
;
3477 desc
.subformat
= NULL
;
3480 if (init_package(&desc
,1,0)) {
3481 PACKI(&desc
,"W",0); /* code */
3482 PACKS(&desc
,"B21",name
); /* eff. name */
3483 PACKS(&desc
,"B",""); /* pad */
3484 PACKI(&desc
,"W", conn
->admin_user
?USER_PRIV_ADMIN
:USER_PRIV_USER
);
3485 PACKI(&desc
,"D",0); /* auth flags XXX */
3486 PACKI(&desc
,"W",0); /* num logons */
3487 PACKI(&desc
,"W",0); /* bad pw count */
3488 PACKI(&desc
,"D",0); /* last logon */
3489 PACKI(&desc
,"D",-1); /* last logoff */
3490 PACKI(&desc
,"D",-1); /* logoff time */
3491 PACKI(&desc
,"D",-1); /* kickoff time */
3492 PACKI(&desc
,"D",0); /* password age */
3493 PACKI(&desc
,"D",0); /* password can change */
3494 PACKI(&desc
,"D",-1); /* password must change */
3498 fstrcpy(mypath
,"\\\\");
3499 fstrcat(mypath
,get_local_machine_name());
3501 PACKS(&desc
,"z",mypath
); /* computer */
3504 PACKS(&desc
,"z",lp_workgroup());/* domain */
3505 PACKS(&desc
,"z", vuser
&& vuser
->logon_script
? vuser
->logon_script
:""); /* script path */
3506 PACKI(&desc
,"D",0x00000000); /* reserved */
3509 *rdata_len
= desc
.usedlen
;
3511 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
3515 SSVALS(*rparam
,0,desc
.errcode
);
3517 SSVAL(*rparam
,4,desc
.neededlen
);
3519 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc
.errcode
));
3524 /****************************************************************************
3525 api_WAccessGetUserPerms
3526 ****************************************************************************/
3528 static BOOL
api_WAccessGetUserPerms(connection_struct
*conn
,uint16 vuid
,
3529 char *param
, int tpscnt
,
3530 char *data
, int tdscnt
,
3531 int mdrcnt
,int mprcnt
,
3532 char **rdata
,char **rparam
,
3533 int *rdata_len
,int *rparam_len
)
3535 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3536 char *str2
= skip_string(param
,tpscnt
,str1
);
3537 char *user
= skip_string(param
,tpscnt
,str2
);
3538 char *resource
= skip_string(param
,tpscnt
,user
);
3540 if (!str1
|| !str2
|| !user
|| !resource
) {
3544 if (skip_string(param
,tpscnt
,resource
) == NULL
) {
3547 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user
,resource
));
3549 /* check it's a supported varient */
3550 if (strcmp(str1
,"zzh") != 0) {
3553 if (strcmp(str2
,"") != 0) {
3558 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
3562 SSVALS(*rparam
,0,0); /* errorcode */
3563 SSVAL(*rparam
,2,0); /* converter word */
3564 SSVAL(*rparam
,4,0x7f); /* permission flags */
3569 /****************************************************************************
3570 api_WPrintJobEnumerate
3571 ****************************************************************************/
3573 static BOOL
api_WPrintJobGetInfo(connection_struct
*conn
, uint16 vuid
,
3574 char *param
, int tpscnt
,
3575 char *data
, int tdscnt
,
3576 int mdrcnt
,int mprcnt
,
3577 char **rdata
,char **rparam
,
3578 int *rdata_len
,int *rparam_len
)
3580 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3581 char *str2
= skip_string(param
,tpscnt
,str1
);
3582 char *p
= skip_string(param
,tpscnt
,str2
);
3589 struct pack_desc desc
;
3590 print_queue_struct
*queue
=NULL
;
3591 print_status_struct status
;
3594 if (!str1
|| !str2
|| !p
) {
3598 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,2,-1);
3600 memset((char *)&desc
,'\0',sizeof(desc
));
3601 memset((char *)&status
,'\0',sizeof(status
));
3603 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel
,SVAL(p
,0)));
3605 /* check it's a supported varient */
3606 if (strcmp(str1
,"WWrLh") != 0) {
3609 if (!check_printjob_info(&desc
,uLevel
,str2
)) {
3613 if(!rap_to_pjobid(SVAL(p
,0), sharename
, &jobid
)) {
3617 snum
= lp_servicenumber( sharename
);
3618 if (snum
< 0 || !VALID_SNUM(snum
)) {
3622 count
= print_queue_status(snum
,&queue
,&status
);
3623 for (i
= 0; i
< count
; i
++) {
3624 if (queue
[i
].job
== jobid
) {
3630 *rdata
= SMB_REALLOC_LIMIT(*rdata
,mdrcnt
);
3635 desc
.buflen
= mdrcnt
;
3638 * Don't return data but need to get correct length
3639 * init_package will return wrong size if buflen=0
3641 desc
.buflen
= getlen(desc
.format
);
3642 desc
.base
= tmpdata
= (char *)SMB_MALLOC( desc
.buflen
);
3645 if (init_package(&desc
,1,0)) {
3647 fill_printjob_info(conn
,snum
,uLevel
,&desc
,&queue
[i
],i
);
3648 *rdata_len
= desc
.usedlen
;
3650 desc
.errcode
= NERR_JobNotFound
;
3656 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
3660 SSVALS(*rparam
,0,desc
.errcode
);
3662 SSVAL(*rparam
,4,desc
.neededlen
);
3667 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc
.errcode
));
3672 static BOOL
api_WPrintJobEnumerate(connection_struct
*conn
, uint16 vuid
,
3673 char *param
, int tpscnt
,
3674 char *data
, int tdscnt
,
3675 int mdrcnt
,int mprcnt
,
3676 char **rdata
,char **rparam
,
3677 int *rdata_len
,int *rparam_len
)
3679 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3680 char *str2
= skip_string(param
,tpscnt
,str1
);
3681 char *p
= skip_string(param
,tpscnt
,str2
);
3687 struct pack_desc desc
;
3688 print_queue_struct
*queue
=NULL
;
3689 print_status_struct status
;
3691 if (!str1
|| !str2
|| !p
) {
3695 memset((char *)&desc
,'\0',sizeof(desc
));
3696 memset((char *)&status
,'\0',sizeof(status
));
3698 p
= skip_string(param
,tpscnt
,p
);
3702 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3704 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel
,name
));
3706 /* check it's a supported variant */
3707 if (strcmp(str1
,"zWrLeh") != 0) {
3712 return False
; /* defined only for uLevel 0,1,2 */
3715 if (!check_printjob_info(&desc
,uLevel
,str2
)) {
3719 snum
= find_service(name
);
3720 if ( !(lp_snum_ok(snum
) && lp_print_ok(snum
)) ) {
3724 count
= print_queue_status(snum
,&queue
,&status
);
3726 *rdata
= SMB_REALLOC_LIMIT(*rdata
,mdrcnt
);
3732 desc
.buflen
= mdrcnt
;
3734 if (init_package(&desc
,count
,0)) {
3736 for (i
= 0; i
< count
; i
++) {
3737 fill_printjob_info(conn
,snum
,uLevel
,&desc
,&queue
[i
],i
);
3738 if (desc
.errcode
== NERR_Success
) {
3744 *rdata_len
= desc
.usedlen
;
3747 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
3751 SSVALS(*rparam
,0,desc
.errcode
);
3753 SSVAL(*rparam
,4,succnt
);
3754 SSVAL(*rparam
,6,count
);
3758 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc
.errcode
));
3763 static int check_printdest_info(struct pack_desc
* desc
,
3764 int uLevel
, char* id
)
3766 desc
->subformat
= NULL
;
3769 desc
->format
= "B9";
3772 desc
->format
= "B9B21WWzW";
3778 desc
->format
= "zzzWWzzzWW";
3781 DEBUG(0,("check_printdest_info: invalid level %d\n",
3785 if (id
== NULL
|| strcmp(desc
->format
,id
) != 0) {
3786 DEBUG(0,("check_printdest_info: invalid string %s\n",
3787 id
? id
: "<NULL>" ));
3793 static void fill_printdest_info(connection_struct
*conn
, int snum
, int uLevel
,
3794 struct pack_desc
* desc
)
3798 strncpy(buf
,SERVICE(snum
),sizeof(buf
)-1);
3799 buf
[sizeof(buf
)-1] = 0;
3803 PACKS(desc
,"B9",buf
); /* szName */
3805 PACKS(desc
,"B21",""); /* szUserName */
3806 PACKI(desc
,"W",0); /* uJobId */
3807 PACKI(desc
,"W",0); /* fsStatus */
3808 PACKS(desc
,"z",""); /* pszStatus */
3809 PACKI(desc
,"W",0); /* time */
3813 if (uLevel
== 2 || uLevel
== 3) {
3814 PACKS(desc
,"z",buf
); /* pszPrinterName */
3816 PACKS(desc
,"z",""); /* pszUserName */
3817 PACKS(desc
,"z",""); /* pszLogAddr */
3818 PACKI(desc
,"W",0); /* uJobId */
3819 PACKI(desc
,"W",0); /* fsStatus */
3820 PACKS(desc
,"z",""); /* pszStatus */
3821 PACKS(desc
,"z",""); /* pszComment */
3822 PACKS(desc
,"z","NULL"); /* pszDrivers */
3823 PACKI(desc
,"W",0); /* time */
3824 PACKI(desc
,"W",0); /* pad1 */
3829 static BOOL
api_WPrintDestGetInfo(connection_struct
*conn
, uint16 vuid
,
3830 char *param
, int tpscnt
,
3831 char *data
, int tdscnt
,
3832 int mdrcnt
,int mprcnt
,
3833 char **rdata
,char **rparam
,
3834 int *rdata_len
,int *rparam_len
)
3836 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3837 char *str2
= skip_string(param
,tpscnt
,str1
);
3838 char *p
= skip_string(param
,tpscnt
,str2
);
3839 char* PrinterName
= p
;
3841 struct pack_desc desc
;
3845 if (!str1
|| !str2
|| !p
) {
3849 memset((char *)&desc
,'\0',sizeof(desc
));
3851 p
= skip_string(param
,tpscnt
,p
);
3855 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3857 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel
,PrinterName
));
3859 /* check it's a supported varient */
3860 if (strcmp(str1
,"zWrLh") != 0) {
3863 if (!check_printdest_info(&desc
,uLevel
,str2
)) {
3867 snum
= find_service(PrinterName
);
3868 if ( !(lp_snum_ok(snum
) && lp_print_ok(snum
)) ) {
3870 desc
.errcode
= NERR_DestNotFound
;
3874 *rdata
= SMB_REALLOC_LIMIT(*rdata
,mdrcnt
);
3879 desc
.buflen
= mdrcnt
;
3882 * Don't return data but need to get correct length
3883 * init_package will return wrong size if buflen=0
3885 desc
.buflen
= getlen(desc
.format
);
3886 desc
.base
= tmpdata
= (char *)SMB_MALLOC( desc
.buflen
);
3888 if (init_package(&desc
,1,0)) {
3889 fill_printdest_info(conn
,snum
,uLevel
,&desc
);
3891 *rdata_len
= desc
.usedlen
;
3895 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
3899 SSVALS(*rparam
,0,desc
.errcode
);
3901 SSVAL(*rparam
,4,desc
.neededlen
);
3903 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc
.errcode
));
3909 static BOOL
api_WPrintDestEnum(connection_struct
*conn
, uint16 vuid
,
3910 char *param
, int tpscnt
,
3911 char *data
, int tdscnt
,
3912 int mdrcnt
,int mprcnt
,
3913 char **rdata
,char **rparam
,
3914 int *rdata_len
,int *rparam_len
)
3916 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3917 char *str2
= skip_string(param
,tpscnt
,str1
);
3918 char *p
= skip_string(param
,tpscnt
,str2
);
3922 struct pack_desc desc
;
3923 int services
= lp_numservices();
3925 if (!str1
|| !str2
|| !p
) {
3929 memset((char *)&desc
,'\0',sizeof(desc
));
3931 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3933 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel
));
3935 /* check it's a supported varient */
3936 if (strcmp(str1
,"WrLeh") != 0) {
3939 if (!check_printdest_info(&desc
,uLevel
,str2
)) {
3944 for (i
= 0; i
< services
; i
++) {
3945 if (lp_snum_ok(i
) && lp_print_ok(i
) && lp_browseable(i
)) {
3951 *rdata
= SMB_REALLOC_LIMIT(*rdata
,mdrcnt
);
3958 desc
.buflen
= mdrcnt
;
3959 if (init_package(&desc
,queuecnt
,0)) {
3962 for (i
= 0; i
< services
; i
++) {
3963 if (lp_snum_ok(i
) && lp_print_ok(i
) && lp_browseable(i
)) {
3964 fill_printdest_info(conn
,i
,uLevel
,&desc
);
3966 if (desc
.errcode
== NERR_Success
) {
3973 *rdata_len
= desc
.usedlen
;
3976 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
3980 SSVALS(*rparam
,0,desc
.errcode
);
3982 SSVAL(*rparam
,4,succnt
);
3983 SSVAL(*rparam
,6,queuecnt
);
3985 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc
.errcode
));
3990 static BOOL
api_WPrintDriverEnum(connection_struct
*conn
, uint16 vuid
,
3991 char *param
, int tpscnt
,
3992 char *data
, int tdscnt
,
3993 int mdrcnt
,int mprcnt
,
3994 char **rdata
,char **rparam
,
3995 int *rdata_len
,int *rparam_len
)
3997 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3998 char *str2
= skip_string(param
,tpscnt
,str1
);
3999 char *p
= skip_string(param
,tpscnt
,str2
);
4002 struct pack_desc desc
;
4004 if (!str1
|| !str2
|| !p
) {
4008 memset((char *)&desc
,'\0',sizeof(desc
));
4010 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4012 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel
));
4014 /* check it's a supported varient */
4015 if (strcmp(str1
,"WrLeh") != 0) {
4018 if (uLevel
!= 0 || strcmp(str2
,"B41") != 0) {
4023 *rdata
= SMB_REALLOC_LIMIT(*rdata
,mdrcnt
);
4029 desc
.buflen
= mdrcnt
;
4030 if (init_package(&desc
,1,0)) {
4031 PACKS(&desc
,"B41","NULL");
4034 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
4036 *rdata_len
= desc
.usedlen
;
4039 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
4043 SSVALS(*rparam
,0,desc
.errcode
);
4045 SSVAL(*rparam
,4,succnt
);
4048 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc
.errcode
));
4053 static BOOL
api_WPrintQProcEnum(connection_struct
*conn
, uint16 vuid
,
4054 char *param
, int tpscnt
,
4055 char *data
, int tdscnt
,
4056 int mdrcnt
,int mprcnt
,
4057 char **rdata
,char **rparam
,
4058 int *rdata_len
,int *rparam_len
)
4060 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4061 char *str2
= skip_string(param
,tpscnt
,str1
);
4062 char *p
= skip_string(param
,tpscnt
,str2
);
4065 struct pack_desc desc
;
4067 if (!str1
|| !str2
|| !p
) {
4070 memset((char *)&desc
,'\0',sizeof(desc
));
4072 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4074 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel
));
4076 /* check it's a supported varient */
4077 if (strcmp(str1
,"WrLeh") != 0) {
4080 if (uLevel
!= 0 || strcmp(str2
,"B13") != 0) {
4085 *rdata
= SMB_REALLOC_LIMIT(*rdata
,mdrcnt
);
4091 desc
.buflen
= mdrcnt
;
4093 if (init_package(&desc
,1,0)) {
4094 PACKS(&desc
,"B13","lpd");
4097 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
4099 *rdata_len
= desc
.usedlen
;
4102 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
4106 SSVALS(*rparam
,0,desc
.errcode
);
4108 SSVAL(*rparam
,4,succnt
);
4111 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc
.errcode
));
4116 static BOOL
api_WPrintPortEnum(connection_struct
*conn
, uint16 vuid
,
4117 char *param
, int tpscnt
,
4118 char *data
, int tdscnt
,
4119 int mdrcnt
,int mprcnt
,
4120 char **rdata
,char **rparam
,
4121 int *rdata_len
,int *rparam_len
)
4123 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4124 char *str2
= skip_string(param
,tpscnt
,str1
);
4125 char *p
= skip_string(param
,tpscnt
,str2
);
4128 struct pack_desc desc
;
4130 if (!str1
|| !str2
|| !p
) {
4134 memset((char *)&desc
,'\0',sizeof(desc
));
4136 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4138 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel
));
4140 /* check it's a supported varient */
4141 if (strcmp(str1
,"WrLeh") != 0) {
4144 if (uLevel
!= 0 || strcmp(str2
,"B9") != 0) {
4149 *rdata
= SMB_REALLOC_LIMIT(*rdata
,mdrcnt
);
4154 memset((char *)&desc
,'\0',sizeof(desc
));
4156 desc
.buflen
= mdrcnt
;
4158 if (init_package(&desc
,1,0)) {
4159 PACKS(&desc
,"B13","lp0");
4162 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
4164 *rdata_len
= desc
.usedlen
;
4167 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
4171 SSVALS(*rparam
,0,desc
.errcode
);
4173 SSVAL(*rparam
,4,succnt
);
4176 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc
.errcode
));
4181 /****************************************************************************
4183 ****************************************************************************/
4185 static BOOL
api_RNetSessionEnum(connection_struct
*conn
, uint16 vuid
,
4186 char *param
, int tpscnt
,
4187 char *data
, int tdscnt
,
4188 int mdrcnt
,int mprcnt
,
4189 char **rdata
,char **rparam
,
4190 int *rdata_len
,int *rparam_len
)
4193 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4194 char *str2
= skip_string(param
,tpscnt
,str1
);
4195 char *p
= skip_string(param
,tpscnt
,str2
);
4197 struct pack_desc desc
;
4198 struct sessionid
*session_list
= NULL
;
4199 int i
, num_sessions
;
4201 if (!str1
|| !str2
|| !p
) {
4205 memset((char *)&desc
,'\0',sizeof(desc
));
4207 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4209 DEBUG(3,("RNetSessionEnum uLevel=%d\n",uLevel
));
4210 DEBUG(7,("RNetSessionEnum req string=%s\n",str1
));
4211 DEBUG(7,("RNetSessionEnum ret string=%s\n",str2
));
4213 /* check it's a supported varient */
4214 if (strcmp(str1
,RAP_NetSessionEnum_REQ
) != 0) {
4217 if (uLevel
!= 2 || strcmp(str2
,RAP_SESSION_INFO_L2
) != 0) {
4221 num_sessions
= list_sessions(&session_list
);
4224 *rdata
= SMB_REALLOC_LIMIT(*rdata
,mdrcnt
);
4226 SAFE_FREE(session_list
);
4230 memset((char *)&desc
,'\0',sizeof(desc
));
4232 desc
.buflen
= mdrcnt
;
4234 if (!init_package(&desc
,num_sessions
,0)) {
4235 SAFE_FREE(session_list
);
4239 for(i
=0; i
<num_sessions
; i
++) {
4240 PACKS(&desc
, "z", session_list
[i
].remote_machine
);
4241 PACKS(&desc
, "z", session_list
[i
].username
);
4242 PACKI(&desc
, "W", 1); /* num conns */
4243 PACKI(&desc
, "W", 0); /* num opens */
4244 PACKI(&desc
, "W", 1); /* num users */
4245 PACKI(&desc
, "D", 0); /* session time */
4246 PACKI(&desc
, "D", 0); /* idle time */
4247 PACKI(&desc
, "D", 0); /* flags */
4248 PACKS(&desc
, "z", "Unknown Client"); /* client type string */
4251 *rdata_len
= desc
.usedlen
;
4254 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
4256 SAFE_FREE(session_list
);
4259 SSVALS(*rparam
,0,desc
.errcode
);
4260 SSVAL(*rparam
,2,0); /* converter */
4261 SSVAL(*rparam
,4,num_sessions
); /* count */
4263 DEBUG(4,("RNetSessionEnum: errorcode %d\n",desc
.errcode
));
4265 SAFE_FREE(session_list
);
4270 /****************************************************************************
4271 The buffer was too small.
4272 ****************************************************************************/
4274 static BOOL
api_TooSmall(connection_struct
*conn
,uint16 vuid
, char *param
, char *data
,
4275 int mdrcnt
, int mprcnt
,
4276 char **rdata
, char **rparam
,
4277 int *rdata_len
, int *rparam_len
)
4279 *rparam_len
= MIN(*rparam_len
,mprcnt
);
4280 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
4287 SSVAL(*rparam
,0,NERR_BufTooSmall
);
4289 DEBUG(3,("Supplied buffer too small in API command\n"));
4294 /****************************************************************************
4295 The request is not supported.
4296 ****************************************************************************/
4298 static BOOL
api_Unsupported(connection_struct
*conn
, uint16 vuid
,
4299 char *param
, int tpscnt
,
4300 char *data
, int tdscnt
,
4301 int mdrcnt
, int mprcnt
,
4302 char **rdata
, char **rparam
,
4303 int *rdata_len
, int *rparam_len
)
4306 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
4313 SSVAL(*rparam
,0,NERR_notsupported
);
4314 SSVAL(*rparam
,2,0); /* converter word */
4316 DEBUG(3,("Unsupported API command\n"));
4321 static const struct {
4324 BOOL (*fn
)(connection_struct
*, uint16
,
4327 int,int,char **,char **,int *,int *);
4328 BOOL auth_user
; /* Deny anonymous access? */
4329 } api_commands
[] = {
4330 {"RNetShareEnum", RAP_WshareEnum
, api_RNetShareEnum
, True
},
4331 {"RNetShareGetInfo", RAP_WshareGetInfo
, api_RNetShareGetInfo
},
4332 {"RNetShareAdd", RAP_WshareAdd
, api_RNetShareAdd
},
4333 {"RNetSessionEnum", RAP_WsessionEnum
, api_RNetSessionEnum
, True
},
4334 {"RNetServerGetInfo", RAP_WserverGetInfo
, api_RNetServerGetInfo
},
4335 {"RNetGroupEnum", RAP_WGroupEnum
, api_RNetGroupEnum
, True
},
4336 {"RNetGroupGetUsers", RAP_WGroupGetUsers
, api_RNetGroupGetUsers
, True
},
4337 {"RNetUserEnum", RAP_WUserEnum
, api_RNetUserEnum
, True
},
4338 {"RNetUserGetInfo", RAP_WUserGetInfo
, api_RNetUserGetInfo
},
4339 {"NetUserGetGroups", RAP_WUserGetGroups
, api_NetUserGetGroups
},
4340 {"NetWkstaGetInfo", RAP_WWkstaGetInfo
, api_NetWkstaGetInfo
},
4341 {"DosPrintQEnum", RAP_WPrintQEnum
, api_DosPrintQEnum
, True
},
4342 {"DosPrintQGetInfo", RAP_WPrintQGetInfo
, api_DosPrintQGetInfo
},
4343 {"WPrintQueuePause", RAP_WPrintQPause
, api_WPrintQueueCtrl
},
4344 {"WPrintQueueResume", RAP_WPrintQContinue
, api_WPrintQueueCtrl
},
4345 {"WPrintJobEnumerate",RAP_WPrintJobEnum
, api_WPrintJobEnumerate
},
4346 {"WPrintJobGetInfo", RAP_WPrintJobGetInfo
, api_WPrintJobGetInfo
},
4347 {"RDosPrintJobDel", RAP_WPrintJobDel
, api_RDosPrintJobDel
},
4348 {"RDosPrintJobPause", RAP_WPrintJobPause
, api_RDosPrintJobDel
},
4349 {"RDosPrintJobResume",RAP_WPrintJobContinue
, api_RDosPrintJobDel
},
4350 {"WPrintDestEnum", RAP_WPrintDestEnum
, api_WPrintDestEnum
},
4351 {"WPrintDestGetInfo", RAP_WPrintDestGetInfo
, api_WPrintDestGetInfo
},
4352 {"NetRemoteTOD", RAP_NetRemoteTOD
, api_NetRemoteTOD
},
4353 {"WPrintQueuePurge", RAP_WPrintQPurge
, api_WPrintQueueCtrl
},
4354 {"NetServerEnum", RAP_NetServerEnum2
, api_RNetServerEnum
}, /* anon OK */
4355 {"WAccessGetUserPerms",RAP_WAccessGetUserPerms
,api_WAccessGetUserPerms
},
4356 {"SetUserPassword", RAP_WUserPasswordSet2
, api_SetUserPassword
},
4357 {"WWkstaUserLogon", RAP_WWkstaUserLogon
, api_WWkstaUserLogon
},
4358 {"PrintJobInfo", RAP_WPrintJobSetInfo
, api_PrintJobInfo
},
4359 {"WPrintDriverEnum", RAP_WPrintDriverEnum
, api_WPrintDriverEnum
},
4360 {"WPrintQProcEnum", RAP_WPrintQProcessorEnum
,api_WPrintQProcEnum
},
4361 {"WPrintPortEnum", RAP_WPrintPortEnum
, api_WPrintPortEnum
},
4362 {"SamOEMChangePassword",RAP_SamOEMChgPasswordUser2_P
,api_SamOEMChangePassword
}, /* anon OK */
4363 {NULL
, -1, api_Unsupported
}
4364 /* The following RAP calls are not implemented by Samba:
4366 RAP_WFileEnum2 - anon not OK
4371 /****************************************************************************
4372 Handle remote api calls
4373 ****************************************************************************/
4375 int api_reply(connection_struct
*conn
,uint16 vuid
,char *outbuf
,char *data
,char *params
,
4376 int tdscnt
,int tpscnt
,int mdrcnt
,int mprcnt
)
4380 char *rparam
= NULL
;
4381 const char *name1
= NULL
;
4382 const char *name2
= NULL
;
4389 DEBUG(0,("ERROR: NULL params in api_reply()\n"));
4396 api_command
= SVAL(params
,0);
4397 /* Is there a string at position params+2 ? */
4398 if (skip_string(params
,tpscnt
,params
+2)) {
4403 name2
= skip_string(params
,tpscnt
,params
+2);
4408 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
4412 tdscnt
,tpscnt
,mdrcnt
,mprcnt
));
4414 for (i
=0;api_commands
[i
].name
;i
++) {
4415 if (api_commands
[i
].id
== api_command
&& api_commands
[i
].fn
) {
4416 DEBUG(3,("Doing %s\n",api_commands
[i
].name
));
4421 /* Check whether this api call can be done anonymously */
4423 if (api_commands
[i
].auth_user
&& lp_restrict_anonymous()) {
4424 user_struct
*user
= get_valid_user_struct(vuid
);
4426 if (!user
|| user
->guest
) {
4427 return ERROR_NT(NT_STATUS_ACCESS_DENIED
);
4431 rdata
= (char *)SMB_MALLOC(1024);
4433 memset(rdata
,'\0',1024);
4436 rparam
= (char *)SMB_MALLOC(1024);
4438 memset(rparam
,'\0',1024);
4441 if(!rdata
|| !rparam
) {
4442 DEBUG(0,("api_reply: malloc fail !\n"));
4448 reply
= api_commands
[i
].fn(conn
,
4450 params
,tpscnt
, /* params + length */
4451 data
,tdscnt
, /* data + length */
4453 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
4456 if (rdata_len
> mdrcnt
|| rparam_len
> mprcnt
) {
4457 reply
= api_TooSmall(conn
,vuid
,params
,data
,mdrcnt
,mprcnt
,
4458 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
4461 /* if we get False back then it's actually unsupported */
4463 reply
= api_Unsupported(conn
,vuid
,params
,tpscnt
,data
,tdscnt
,mdrcnt
,mprcnt
,
4464 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
4467 /* If api_Unsupported returns false we can't return anything. */
4469 send_trans_reply(outbuf
, rparam
, rparam_len
, rdata
, rdata_len
, False
);