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 3 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, see <http://www.gnu.org/licenses/>.
24 This file handles the named pipe and mailslot calls
25 in the SMBtrans protocol
30 extern struct current_user current_user
;
31 extern userdom_struct current_user_info
;
38 #define NERR_Success 0
39 #define NERR_badpass 86
40 #define NERR_notsupported 50
42 #define NERR_BASE (2100)
43 #define NERR_BufTooSmall (NERR_BASE+23)
44 #define NERR_JobNotFound (NERR_BASE+51)
45 #define NERR_DestNotFound (NERR_BASE+52)
47 #define ACCESS_READ 0x01
48 #define ACCESS_WRITE 0x02
49 #define ACCESS_CREATE 0x04
51 #define SHPWLEN 8 /* share password length */
53 static BOOL
api_Unsupported(connection_struct
*conn
, uint16 vuid
,
54 char *param
, int tpscnt
,
55 char *data
, int tdscnt
,
56 int mdrcnt
, int mprcnt
,
57 char **rdata
, char **rparam
,
58 int *rdata_len
, int *rparam_len
);
60 static BOOL
api_TooSmall(connection_struct
*conn
, uint16 vuid
, char *param
, char *data
,
61 int mdrcnt
, int mprcnt
,
62 char **rdata
, char **rparam
,
63 int *rdata_len
, int *rparam_len
);
66 static int CopyExpanded(connection_struct
*conn
,
67 int snum
, char **dst
, char *src
, int *n
)
72 if (!src
|| !dst
|| !n
|| !(*dst
)) {
76 StrnCpy(buf
,src
,sizeof(buf
)/2);
77 pstring_sub(buf
,"%S",lp_servicename(snum
));
78 standard_sub_advanced(lp_servicename(SNUM(conn
)), conn
->user
,
79 conn
->connectpath
, conn
->gid
,
80 get_current_username(),
81 current_user_info
.domain
,
83 l
= push_ascii(*dst
,buf
,*n
, STR_TERMINATE
);
89 static int CopyAndAdvance(char **dst
, char *src
, int *n
)
92 if (!src
|| !dst
|| !n
|| !(*dst
)) {
95 l
= push_ascii(*dst
,src
,*n
, STR_TERMINATE
);
101 static int StrlenExpanded(connection_struct
*conn
, int snum
, char *s
)
107 StrnCpy(buf
,s
,sizeof(buf
)/2);
108 pstring_sub(buf
,"%S",lp_servicename(snum
));
109 standard_sub_advanced(lp_servicename(SNUM(conn
)), conn
->user
,
110 conn
->connectpath
, conn
->gid
,
111 get_current_username(),
112 current_user_info
.domain
,
114 return strlen(buf
) + 1;
117 static char *Expand(connection_struct
*conn
, int snum
, char *s
)
123 StrnCpy(buf
,s
,sizeof(buf
)/2);
124 pstring_sub(buf
,"%S",lp_servicename(snum
));
125 standard_sub_advanced(lp_servicename(SNUM(conn
)), conn
->user
,
126 conn
->connectpath
, conn
->gid
,
127 get_current_username(),
128 current_user_info
.domain
,
133 /*******************************************************************
134 Check a API string for validity when we only need to check the prefix.
135 ******************************************************************/
137 static BOOL
prefix_ok(const char *str
, const char *prefix
)
139 return(strncmp(str
,prefix
,strlen(prefix
)) == 0);
143 const char *format
; /* formatstring for structure */
144 const char *subformat
; /* subformat for structure */
145 char *base
; /* baseaddress of buffer */
146 int buflen
; /* remaining size for fixed part; on init: length of base */
147 int subcount
; /* count of substructures */
148 char *structbuf
; /* pointer into buffer for remaining fixed part */
149 int stringlen
; /* remaining size for variable part */
150 char *stringbuf
; /* pointer into buffer for remaining variable part */
151 int neededlen
; /* total needed size */
152 int usedlen
; /* total used size (usedlen <= neededlen and usedlen <= buflen) */
153 const char *curpos
; /* current position; pointer into format or subformat */
157 static int get_counter(const char **p
)
163 if (!isdigit((int)**p
)) {
169 n
= 10 * n
+ (i
- '0');
177 static int getlen(const char *p
)
186 case 'W': /* word (2 byte) */
189 case 'K': /* status word? (2 byte) */
192 case 'N': /* count of substructures (word) at end */
195 case 'D': /* double word (4 byte) */
196 case 'z': /* offset to zero terminated string (4 byte) */
197 case 'l': /* offset to user data (4 byte) */
200 case 'b': /* offset to data (with counter) (4 byte) */
204 case 'B': /* byte (with optional counter) */
205 n
+= get_counter(&p
);
212 static BOOL
init_package(struct pack_desc
*p
, int count
, int subcount
)
217 if (!p
->format
|| !p
->base
) {
221 i
= count
* getlen(p
->format
);
223 i
+= subcount
* getlen(p
->subformat
);
225 p
->structbuf
= p
->base
;
229 p
->curpos
= p
->format
;
235 * This is the old error code we used. Aparently
236 * WinNT/2k systems return ERRbuftoosmall (2123) and
237 * OS/2 needs this. I'm leaving this here so we can revert
240 p
->errcode
= ERRmoredata
;
242 p
->errcode
= ERRbuftoosmall
;
245 p
->errcode
= NERR_Success
;
249 p
->stringbuf
= p
->base
+ i
;
251 return (p
->errcode
== NERR_Success
);
254 static int package(struct pack_desc
*p
, ...)
257 int needed
=0, stringneeded
;
258 const char *str
=NULL
;
259 int is_string
=0, stringused
;
266 p
->curpos
= p
->format
;
268 p
->curpos
= p
->subformat
;
273 str
= va_arg(args
,char*);
274 SMB_ASSERT(strncmp(str
,p
->curpos
,strlen(str
)) == 0);
283 switch( *p
->curpos
++ ) {
284 case 'W': /* word (2 byte) */
286 temp
= va_arg(args
,int);
287 if (p
->buflen
>= needed
) {
288 SSVAL(p
->structbuf
,0,temp
);
291 case 'K': /* status word? (2 byte) */
293 temp
= va_arg(args
,int);
294 if (p
->buflen
>= needed
) {
295 SSVAL(p
->structbuf
,0,temp
);
298 case 'N': /* count of substructures (word) at end */
300 p
->subcount
= va_arg(args
,int);
301 if (p
->buflen
>= needed
) {
302 SSVAL(p
->structbuf
,0,p
->subcount
);
305 case 'D': /* double word (4 byte) */
307 temp
= va_arg(args
,int);
308 if (p
->buflen
>= needed
) {
309 SIVAL(p
->structbuf
,0,temp
);
312 case 'B': /* byte (with optional counter) */
313 needed
= get_counter(&p
->curpos
);
315 char *s
= va_arg(args
,char*);
316 if (p
->buflen
>= needed
) {
317 StrnCpy(p
->structbuf
,s
?s
:"",needed
-1);
321 case 'z': /* offset to zero terminated string (4 byte) */
322 str
= va_arg(args
,char*);
323 stringneeded
= (str
? strlen(str
)+1 : 0);
326 case 'l': /* offset to user data (4 byte) */
327 str
= va_arg(args
,char*);
328 stringneeded
= va_arg(args
,int);
331 case 'b': /* offset to data (with counter) (4 byte) */
332 str
= va_arg(args
,char*);
333 stringneeded
= get_counter(&p
->curpos
);
339 if (stringneeded
>= 0) {
341 if (p
->buflen
>= needed
) {
342 stringused
= stringneeded
;
343 if (stringused
> p
->stringlen
) {
344 stringused
= (is_string
? p
->stringlen
: 0);
345 if (p
->errcode
== NERR_Success
) {
346 p
->errcode
= ERRmoredata
;
350 SIVAL(p
->structbuf
,0,0);
352 SIVAL(p
->structbuf
,0,PTR_DIFF(p
->stringbuf
,p
->base
));
353 memcpy(p
->stringbuf
,str
?str
:"",stringused
);
355 p
->stringbuf
[stringused
-1] = '\0';
357 p
->stringbuf
+= stringused
;
358 p
->stringlen
-= stringused
;
359 p
->usedlen
+= stringused
;
362 p
->neededlen
+= stringneeded
;
365 p
->neededlen
+= needed
;
366 if (p
->buflen
>= needed
) {
367 p
->structbuf
+= needed
;
369 p
->usedlen
+= needed
;
371 if (p
->errcode
== NERR_Success
) {
372 p
->errcode
= ERRmoredata
;
379 #define PACK(desc,t,v) package(desc,t,v,0,0,0,0)
380 #define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0)
382 #define PACK(desc,t,v) package(desc,v)
383 #define PACKl(desc,t,v,l) package(desc,v,l)
386 static void PACKI(struct pack_desc
* desc
, const char *t
,int v
)
391 static void PACKS(struct pack_desc
* desc
,const char *t
,const char *v
)
396 /****************************************************************************
398 ****************************************************************************/
400 static void PackDriverData(struct pack_desc
* desc
)
402 char drivdata
[4+4+32];
403 SIVAL(drivdata
,0,sizeof drivdata
); /* cb */
404 SIVAL(drivdata
,4,1000); /* lVersion */
405 memset(drivdata
+8,0,32); /* szDeviceName */
406 push_ascii(drivdata
+8,"NULL",-1, STR_TERMINATE
);
407 PACKl(desc
,"l",drivdata
,sizeof drivdata
); /* pDriverData */
410 static int check_printq_info(struct pack_desc
* desc
,
411 unsigned int uLevel
, char *id1
, char *id2
)
413 desc
->subformat
= NULL
;
416 desc
->format
= "B13";
419 desc
->format
= "B13BWWWzzzzzWW";
422 desc
->format
= "B13BWWWzzzzzWN";
423 desc
->subformat
= "WB21BB16B10zWWzDDz";
426 desc
->format
= "zWWWWzzzzWWzzl";
429 desc
->format
= "zWWWWzzzzWNzzl";
430 desc
->subformat
= "WWzWWDDzz";
439 desc
->format
= "WzzzzzzzzN";
440 desc
->subformat
= "z";
443 DEBUG(0,("check_printq_info: invalid level %d\n",
447 if (id1
== NULL
|| strcmp(desc
->format
,id1
) != 0) {
448 DEBUG(0,("check_printq_info: invalid format %s\n",
449 id1
? id1
: "<NULL>" ));
452 if (desc
->subformat
&& (id2
== NULL
|| strcmp(desc
->subformat
,id2
) != 0)) {
453 DEBUG(0,("check_printq_info: invalid subformat %s\n",
454 id2
? id2
: "<NULL>" ));
461 #define RAP_JOB_STATUS_QUEUED 0
462 #define RAP_JOB_STATUS_PAUSED 1
463 #define RAP_JOB_STATUS_SPOOLING 2
464 #define RAP_JOB_STATUS_PRINTING 3
465 #define RAP_JOB_STATUS_PRINTED 4
467 #define RAP_QUEUE_STATUS_PAUSED 1
468 #define RAP_QUEUE_STATUS_ERROR 2
470 /* turn a print job status into a on the wire status
472 static int printj_status(int v
)
476 return RAP_JOB_STATUS_QUEUED
;
478 return RAP_JOB_STATUS_PAUSED
;
480 return RAP_JOB_STATUS_SPOOLING
;
482 return RAP_JOB_STATUS_PRINTING
;
487 /* turn a print queue status into a on the wire status
489 static int printq_status(int v
)
495 return RAP_QUEUE_STATUS_PAUSED
;
497 return RAP_QUEUE_STATUS_ERROR
;
500 static void fill_printjob_info(connection_struct
*conn
, int snum
, int uLevel
,
501 struct pack_desc
*desc
,
502 print_queue_struct
*queue
, int n
)
504 time_t t
= queue
->time
;
506 /* the client expects localtime */
507 t
-= get_time_zone(t
);
509 PACKI(desc
,"W",pjobid_to_rap(lp_const_servicename(snum
),queue
->job
)); /* uJobId */
511 PACKS(desc
,"B21",queue
->fs_user
); /* szUserName */
512 PACKS(desc
,"B",""); /* pad */
513 PACKS(desc
,"B16",""); /* szNotifyName */
514 PACKS(desc
,"B10","PM_Q_RAW"); /* szDataType */
515 PACKS(desc
,"z",""); /* pszParms */
516 PACKI(desc
,"W",n
+1); /* uPosition */
517 PACKI(desc
,"W",printj_status(queue
->status
)); /* fsStatus */
518 PACKS(desc
,"z",""); /* pszStatus */
519 PACKI(desc
,"D",t
); /* ulSubmitted */
520 PACKI(desc
,"D",queue
->size
); /* ulSize */
521 PACKS(desc
,"z",queue
->fs_file
); /* pszComment */
523 if (uLevel
== 2 || uLevel
== 3 || uLevel
== 4) {
524 PACKI(desc
,"W",queue
->priority
); /* uPriority */
525 PACKS(desc
,"z",queue
->fs_user
); /* pszUserName */
526 PACKI(desc
,"W",n
+1); /* uPosition */
527 PACKI(desc
,"W",printj_status(queue
->status
)); /* fsStatus */
528 PACKI(desc
,"D",t
); /* ulSubmitted */
529 PACKI(desc
,"D",queue
->size
); /* ulSize */
530 PACKS(desc
,"z","Samba"); /* pszComment */
531 PACKS(desc
,"z",queue
->fs_file
); /* pszDocument */
533 PACKS(desc
,"z",""); /* pszNotifyName */
534 PACKS(desc
,"z","PM_Q_RAW"); /* pszDataType */
535 PACKS(desc
,"z",""); /* pszParms */
536 PACKS(desc
,"z",""); /* pszStatus */
537 PACKS(desc
,"z",SERVICE(snum
)); /* pszQueue */
538 PACKS(desc
,"z","lpd"); /* pszQProcName */
539 PACKS(desc
,"z",""); /* pszQProcParms */
540 PACKS(desc
,"z","NULL"); /* pszDriverName */
541 PackDriverData(desc
); /* pDriverData */
542 PACKS(desc
,"z",""); /* pszPrinterName */
543 } else if (uLevel
== 4) { /* OS2 */
544 PACKS(desc
,"z",""); /* pszSpoolFileName */
545 PACKS(desc
,"z",""); /* pszPortName */
546 PACKS(desc
,"z",""); /* pszStatus */
547 PACKI(desc
,"D",0); /* ulPagesSpooled */
548 PACKI(desc
,"D",0); /* ulPagesSent */
549 PACKI(desc
,"D",0); /* ulPagesPrinted */
550 PACKI(desc
,"D",0); /* ulTimePrinted */
551 PACKI(desc
,"D",0); /* ulExtendJobStatus */
552 PACKI(desc
,"D",0); /* ulStartPage */
553 PACKI(desc
,"D",0); /* ulEndPage */
558 /********************************************************************
559 Return a driver name given an snum.
560 Returns True if from tdb, False otherwise.
561 ********************************************************************/
563 static BOOL
get_driver_name(int snum
, pstring drivername
)
565 NT_PRINTER_INFO_LEVEL
*info
= NULL
;
568 get_a_printer (NULL
, &info
, 2, lp_servicename(snum
));
570 pstrcpy( drivername
, info
->info_2
->drivername
);
572 free_a_printer(&info
, 2);
578 /********************************************************************
579 Respond to the DosPrintQInfo command with a level of 52
580 This is used to get printer driver information for Win9x clients
581 ********************************************************************/
582 static void fill_printq_info_52(connection_struct
*conn
, int snum
,
583 struct pack_desc
* desc
, int count
)
587 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
588 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
592 if ( !W_ERROR_IS_OK(get_a_printer( NULL
, &printer
, 2, lp_servicename(snum
))) ) {
593 DEBUG(3,("fill_printq_info_52: Failed to lookup printer [%s]\n",
594 lp_servicename(snum
)));
598 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
,
601 DEBUG(3,("fill_printq_info_52: Failed to lookup driver [%s]\n",
602 printer
->info_2
->drivername
));
606 trim_string(driver
.info_3
->driverpath
, "\\print$\\WIN40\\0\\", 0);
607 trim_string(driver
.info_3
->datafile
, "\\print$\\WIN40\\0\\", 0);
608 trim_string(driver
.info_3
->helpfile
, "\\print$\\WIN40\\0\\", 0);
610 PACKI(desc
, "W", 0x0400); /* don't know */
611 PACKS(desc
, "z", driver
.info_3
->name
); /* long printer name */
612 PACKS(desc
, "z", driver
.info_3
->driverpath
); /* Driverfile Name */
613 PACKS(desc
, "z", driver
.info_3
->datafile
); /* Datafile name */
614 PACKS(desc
, "z", driver
.info_3
->monitorname
); /* language monitor */
616 fstrcpy(location
, "\\\\%L\\print$\\WIN40\\0");
617 standard_sub_basic( "", "", location
, sizeof(location
)-1 );
618 PACKS(desc
,"z", location
); /* share to retrieve files */
620 PACKS(desc
,"z", driver
.info_3
->defaultdatatype
); /* default data type */
621 PACKS(desc
,"z", driver
.info_3
->helpfile
); /* helpfile name */
622 PACKS(desc
,"z", driver
.info_3
->driverpath
); /* driver name */
624 DEBUG(3,("Printer Driver Name: %s:\n",driver
.info_3
->name
));
625 DEBUG(3,("Driver: %s:\n",driver
.info_3
->driverpath
));
626 DEBUG(3,("Data File: %s:\n",driver
.info_3
->datafile
));
627 DEBUG(3,("Language Monitor: %s:\n",driver
.info_3
->monitorname
));
628 DEBUG(3,("Driver Location: %s:\n",location
));
629 DEBUG(3,("Data Type: %s:\n",driver
.info_3
->defaultdatatype
));
630 DEBUG(3,("Help File: %s:\n",driver
.info_3
->helpfile
));
631 PACKI(desc
,"N",count
); /* number of files to copy */
633 for ( i
=0; i
<count
&& driver
.info_3
->dependentfiles
&& *driver
.info_3
->dependentfiles
[i
]; i
++)
635 trim_string(driver
.info_3
->dependentfiles
[i
], "\\print$\\WIN40\\0\\", 0);
636 PACKS(desc
,"z",driver
.info_3
->dependentfiles
[i
]); /* driver files to copy */
637 DEBUG(3,("Dependent File: %s:\n",driver
.info_3
->dependentfiles
[i
]));
642 DEBUG(3,("fill_printq_info_52: file count specified by client [%d] != number of dependent files [%i]\n",
645 DEBUG(3,("fill_printq_info on <%s> gave %d entries\n", SERVICE(snum
),i
));
647 desc
->errcode
=NERR_Success
;
651 DEBUG(3,("fill_printq_info: Can't supply driver files\n"));
652 desc
->errcode
=NERR_notsupported
;
656 free_a_printer( &printer
, 2 );
659 free_a_printer_driver( driver
, 3 );
663 static void fill_printq_info(connection_struct
*conn
, int snum
, int uLevel
,
664 struct pack_desc
* desc
,
665 int count
, print_queue_struct
* queue
,
666 print_status_struct
* status
)
671 PACKS(desc
,"B13",SERVICE(snum
));
676 PACKS(desc
,"z",Expand(conn
,snum
,SERVICE(snum
)));
679 PACKI(desc
,"K",printq_status(status
->status
));
683 if (uLevel
== 1 || uLevel
== 2) {
684 PACKS(desc
,"B",""); /* alignment */
685 PACKI(desc
,"W",5); /* priority */
686 PACKI(desc
,"W",0); /* start time */
687 PACKI(desc
,"W",0); /* until time */
688 PACKS(desc
,"z",""); /* pSepFile */
689 PACKS(desc
,"z","lpd"); /* pPrProc */
690 PACKS(desc
,"z",SERVICE(snum
)); /* pDestinations */
691 PACKS(desc
,"z",""); /* pParms */
693 PACKS(desc
,"z","UNKNOWN PRINTER");
694 PACKI(desc
,"W",LPSTAT_ERROR
);
696 else if (!status
|| !status
->message
[0]) {
697 PACKS(desc
,"z",Expand(conn
,snum
,lp_comment(snum
)));
698 PACKI(desc
,"W",LPSTAT_OK
); /* status */
700 PACKS(desc
,"z",status
->message
);
701 PACKI(desc
,"W",printq_status(status
->status
)); /* status */
703 PACKI(desc
,(uLevel
== 1 ? "W" : "N"),count
);
706 if (uLevel
== 3 || uLevel
== 4) {
709 PACKI(desc
,"W",5); /* uPriority */
710 PACKI(desc
,"W",0); /* uStarttime */
711 PACKI(desc
,"W",0); /* uUntiltime */
712 PACKI(desc
,"W",5); /* pad1 */
713 PACKS(desc
,"z",""); /* pszSepFile */
714 PACKS(desc
,"z","WinPrint"); /* pszPrProc */
715 PACKS(desc
,"z",NULL
); /* pszParms */
716 PACKS(desc
,"z",NULL
); /* pszComment - don't ask.... JRA */
717 /* "don't ask" that it's done this way to fix corrupted
718 Win9X/ME printer comments. */
720 PACKI(desc
,"W",LPSTAT_OK
); /* fsStatus */
722 PACKI(desc
,"W",printq_status(status
->status
)); /* fsStatus */
724 PACKI(desc
,(uLevel
== 3 ? "W" : "N"),count
); /* cJobs */
725 PACKS(desc
,"z",SERVICE(snum
)); /* pszPrinters */
726 get_driver_name(snum
,drivername
);
727 PACKS(desc
,"z",drivername
); /* pszDriverName */
728 PackDriverData(desc
); /* pDriverData */
731 if (uLevel
== 2 || uLevel
== 4) {
733 for (i
=0;i
<count
;i
++)
734 fill_printjob_info(conn
,snum
,uLevel
== 2 ? 1 : 2,desc
,&queue
[i
],i
);
738 fill_printq_info_52( conn
, snum
, desc
, count
);
741 /* This function returns the number of files for a given driver */
742 static int get_printerdrivernumber(int snum
)
745 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
746 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
750 if ( !W_ERROR_IS_OK(get_a_printer( NULL
, &printer
, 2, lp_servicename(snum
))) ) {
751 DEBUG(3,("get_printerdrivernumber: Failed to lookup printer [%s]\n",
752 lp_servicename(snum
)));
756 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
,
759 DEBUG(3,("get_printerdrivernumber: Failed to lookup driver [%s]\n",
760 printer
->info_2
->drivername
));
764 /* count the number of files */
765 while ( driver
.info_3
->dependentfiles
&& *driver
.info_3
->dependentfiles
[result
] )
770 free_a_printer( &printer
, 2 );
773 free_a_printer_driver( driver
, 3 );
778 static BOOL
api_DosPrintQGetInfo(connection_struct
*conn
, uint16 vuid
,
779 char *param
, int tpscnt
,
780 char *data
, int tdscnt
,
781 int mdrcnt
,int mprcnt
,
782 char **rdata
,char **rparam
,
783 int *rdata_len
,int *rparam_len
)
785 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
786 char *str2
= skip_string(param
,tpscnt
,str1
);
787 char *p
= skip_string(param
,tpscnt
,str2
);
793 struct pack_desc desc
;
794 print_queue_struct
*queue
=NULL
;
795 print_status_struct status
;
798 if (!str1
|| !str2
|| !p
) {
801 memset((char *)&status
,'\0',sizeof(status
));
802 memset((char *)&desc
,'\0',sizeof(desc
));
804 p
= skip_string(param
,tpscnt
,p
);
808 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
809 str3
= get_safe_str_ptr(param
,tpscnt
,p
,4);
810 /* str3 may be null here and is checked in check_printq_info(). */
812 /* remove any trailing username */
813 if ((p
= strchr_m(QueueName
,'%')))
816 DEBUG(3,("api_DosPrintQGetInfo uLevel=%d name=%s\n",uLevel
,QueueName
));
818 /* check it's a supported varient */
819 if (!prefix_ok(str1
,"zWrLh"))
821 if (!check_printq_info(&desc
,uLevel
,str2
,str3
)) {
823 * Patch from Scott Moomaw <scott@bridgewater.edu>
824 * to return the 'invalid info level' error if an
825 * unknown level was requested.
829 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
833 SSVALS(*rparam
,0,ERRunknownlevel
);
839 snum
= find_service(QueueName
);
840 if ( !(lp_snum_ok(snum
) && lp_print_ok(snum
)) )
844 count
= get_printerdrivernumber(snum
);
845 DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count
));
847 count
= print_queue_status(snum
, &queue
,&status
);
851 *rdata
= SMB_REALLOC_LIMIT(*rdata
,mdrcnt
);
856 desc
.buflen
= mdrcnt
;
859 * Don't return data but need to get correct length
860 * init_package will return wrong size if buflen=0
862 desc
.buflen
= getlen(desc
.format
);
863 desc
.base
= tmpdata
= (char *) SMB_MALLOC (desc
.buflen
);
866 if (init_package(&desc
,1,count
)) {
867 desc
.subcount
= count
;
868 fill_printq_info(conn
,snum
,uLevel
,&desc
,count
,queue
,&status
);
871 *rdata_len
= desc
.usedlen
;
874 * We must set the return code to ERRbuftoosmall
875 * in order to support lanman style printing with Win NT/2k
878 if (!mdrcnt
&& lp_disable_spoolss())
879 desc
.errcode
= ERRbuftoosmall
;
881 *rdata_len
= desc
.usedlen
;
883 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
887 SSVALS(*rparam
,0,desc
.errcode
);
889 SSVAL(*rparam
,4,desc
.neededlen
);
891 DEBUG(4,("printqgetinfo: errorcode %d\n",desc
.errcode
));
899 /****************************************************************************
900 View list of all print jobs on all queues.
901 ****************************************************************************/
903 static BOOL
api_DosPrintQEnum(connection_struct
*conn
, uint16 vuid
,
904 char *param
, int tpscnt
,
905 char *data
, int tdscnt
,
906 int mdrcnt
, int mprcnt
,
907 char **rdata
, char** rparam
,
908 int *rdata_len
, int *rparam_len
)
910 char *param_format
= get_safe_str_ptr(param
,tpscnt
,param
,2);
911 char *output_format1
= skip_string(param
,tpscnt
,param_format
);
912 char *p
= skip_string(param
,tpscnt
,output_format1
);
913 unsigned int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
914 char *output_format2
= get_safe_str_ptr(param
,tpscnt
,p
,4);
915 int services
= lp_numservices();
917 struct pack_desc desc
;
918 print_queue_struct
**queue
= NULL
;
919 print_status_struct
*status
= NULL
;
920 int *subcntarr
= NULL
;
921 int queuecnt
= 0, subcnt
= 0, succnt
= 0;
923 if (!param_format
|| !output_format1
|| !p
) {
927 memset((char *)&desc
,'\0',sizeof(desc
));
929 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel
));
931 if (!prefix_ok(param_format
,"WrLeh")) {
934 if (!check_printq_info(&desc
,uLevel
,output_format1
,output_format2
)) {
936 * Patch from Scott Moomaw <scott@bridgewater.edu>
937 * to return the 'invalid info level' error if an
938 * unknown level was requested.
942 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
946 SSVALS(*rparam
,0,ERRunknownlevel
);
952 for (i
= 0; i
< services
; i
++) {
953 if (lp_snum_ok(i
) && lp_print_ok(i
) && lp_browseable(i
)) {
958 if((queue
= SMB_MALLOC_ARRAY(print_queue_struct
*, queuecnt
)) == NULL
) {
959 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
962 memset(queue
,0,queuecnt
*sizeof(print_queue_struct
*));
963 if((status
= SMB_MALLOC_ARRAY(print_status_struct
,queuecnt
)) == NULL
) {
964 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
967 memset(status
,0,queuecnt
*sizeof(print_status_struct
));
968 if((subcntarr
= SMB_MALLOC_ARRAY(int,queuecnt
)) == NULL
) {
969 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
975 for (i
= 0; i
< services
; i
++) {
976 if (lp_snum_ok(i
) && lp_print_ok(i
) && lp_browseable(i
)) {
977 subcntarr
[n
] = print_queue_status(i
, &queue
[n
],&status
[n
]);
978 subcnt
+= subcntarr
[n
];
984 *rdata
= SMB_REALLOC_LIMIT(*rdata
,mdrcnt
);
990 desc
.buflen
= mdrcnt
;
992 if (init_package(&desc
,queuecnt
,subcnt
)) {
995 for (i
= 0; i
< services
; i
++) {
996 if (lp_snum_ok(i
) && lp_print_ok(i
) && lp_browseable(i
)) {
997 fill_printq_info(conn
,i
,uLevel
,&desc
,subcntarr
[n
],queue
[n
],&status
[n
]);
999 if (desc
.errcode
== NERR_Success
) {
1006 SAFE_FREE(subcntarr
);
1008 *rdata_len
= desc
.usedlen
;
1010 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
1014 SSVALS(*rparam
,0,desc
.errcode
);
1016 SSVAL(*rparam
,4,succnt
);
1017 SSVAL(*rparam
,6,queuecnt
);
1019 for (i
= 0; i
< queuecnt
; i
++) {
1021 SAFE_FREE(queue
[i
]);
1032 SAFE_FREE(subcntarr
);
1033 for (i
= 0; i
< queuecnt
; i
++) {
1035 SAFE_FREE(queue
[i
]);
1044 /****************************************************************************
1045 Get info level for a server list query.
1046 ****************************************************************************/
1048 static BOOL
check_server_info(int uLevel
, char* id
)
1052 if (strcmp(id
,"B16") != 0) {
1057 if (strcmp(id
,"B16BBDz") != 0) {
1067 struct srv_info_struct
{
1075 /*******************************************************************
1076 Get server info lists from the files saved by nmbd. Return the
1078 ******************************************************************/
1080 static int get_server_info(uint32 servertype
,
1081 struct srv_info_struct
**servers
,
1087 BOOL local_list_only
;
1090 lines
= file_lines_load(lock_path(SERVER_LIST
), NULL
, 0);
1092 DEBUG(4,("Can't open %s - %s\n",lock_path(SERVER_LIST
),strerror(errno
)));
1096 /* request for everything is code for request all servers */
1097 if (servertype
== SV_TYPE_ALL
) {
1098 servertype
&= ~(SV_TYPE_DOMAIN_ENUM
|SV_TYPE_LOCAL_LIST_ONLY
);
1101 local_list_only
= (servertype
& SV_TYPE_LOCAL_LIST_ONLY
);
1103 DEBUG(4,("Servertype search: %8x\n",servertype
));
1105 for (i
=0;lines
[i
];i
++) {
1107 struct srv_info_struct
*s
;
1108 const char *ptr
= lines
[i
];
1115 if (count
== alloced
) {
1117 *servers
= SMB_REALLOC_ARRAY(*servers
,struct srv_info_struct
, alloced
);
1119 DEBUG(0,("get_server_info: failed to enlarge servers info struct!\n"));
1120 file_lines_free(lines
);
1123 memset((char *)((*servers
)+count
),'\0',sizeof(**servers
)*(alloced
-count
));
1125 s
= &(*servers
)[count
];
1127 if (!next_token(&ptr
,s
->name
, NULL
, sizeof(s
->name
))) {
1130 if (!next_token(&ptr
,stype
, NULL
, sizeof(stype
))) {
1133 if (!next_token(&ptr
,s
->comment
, NULL
, sizeof(s
->comment
))) {
1136 if (!next_token(&ptr
,s
->domain
, NULL
, sizeof(s
->domain
))) {
1137 /* this allows us to cope with an old nmbd */
1138 fstrcpy(s
->domain
,lp_workgroup());
1141 if (sscanf(stype
,"%X",&s
->type
) != 1) {
1142 DEBUG(4,("r:host file "));
1146 /* Filter the servers/domains we return based on what was asked for. */
1148 /* Check to see if we are being asked for a local list only. */
1149 if(local_list_only
&& ((s
->type
& SV_TYPE_LOCAL_LIST_ONLY
) == 0)) {
1150 DEBUG(4,("r: local list only"));
1154 /* doesn't match up: don't want it */
1155 if (!(servertype
& s
->type
)) {
1156 DEBUG(4,("r:serv type "));
1160 if ((servertype
& SV_TYPE_DOMAIN_ENUM
) !=
1161 (s
->type
& SV_TYPE_DOMAIN_ENUM
)) {
1162 DEBUG(4,("s: dom mismatch "));
1166 if (!strequal(domain
, s
->domain
) && !(servertype
& SV_TYPE_DOMAIN_ENUM
)) {
1170 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
1171 s
->type
&= ~SV_TYPE_LOCAL_LIST_ONLY
;
1174 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
1175 s
->name
, s
->type
, s
->comment
, s
->domain
));
1176 s
->server_added
= True
;
1179 DEBUG(4,("%20s %8x %25s %15s\n",
1180 s
->name
, s
->type
, s
->comment
, s
->domain
));
1184 file_lines_free(lines
);
1188 /*******************************************************************
1189 Fill in a server info structure.
1190 ******************************************************************/
1192 static int fill_srv_info(struct srv_info_struct
*service
,
1193 int uLevel
, char **buf
, int *buflen
,
1194 char **stringbuf
, int *stringspace
, char *baseaddr
)
1217 len
= strlen(service
->comment
)+1;
1221 *buflen
= struct_len
;
1223 return struct_len
+ len
;
1228 if (*buflen
< struct_len
) {
1235 p2
= p
+ struct_len
;
1236 l2
= *buflen
- struct_len
;
1244 push_ascii(p
,service
->name
, MAX_NETBIOSNAME_LEN
, STR_TERMINATE
);
1248 push_ascii(p
,service
->name
,MAX_NETBIOSNAME_LEN
, STR_TERMINATE
);
1249 SIVAL(p
,18,service
->type
);
1250 SIVAL(p
,22,PTR_DIFF(p2
,baseaddr
));
1251 len
+= CopyAndAdvance(&p2
,service
->comment
,&l2
);
1256 *buf
= p
+ struct_len
;
1257 *buflen
-= struct_len
;
1268 static BOOL
srv_comp(struct srv_info_struct
*s1
,struct srv_info_struct
*s2
)
1270 return(strcmp(s1
->name
,s2
->name
));
1273 /****************************************************************************
1274 View list of servers available (or possibly domains). The info is
1275 extracted from lists saved by nmbd on the local host.
1276 ****************************************************************************/
1278 static BOOL
api_RNetServerEnum(connection_struct
*conn
, uint16 vuid
,
1279 char *param
, int tpscnt
,
1280 char *data
, int tdscnt
,
1281 int mdrcnt
, int mprcnt
, char **rdata
,
1282 char **rparam
, int *rdata_len
, int *rparam_len
)
1284 char *str1
= get_safe_str_ptr(param
, tpscnt
, param
, 2);
1285 char *str2
= skip_string(param
,tpscnt
,str1
);
1286 char *p
= skip_string(param
,tpscnt
,str2
);
1287 int uLevel
= get_safe_SVAL(param
, tpscnt
, p
, 0, -1);
1288 int buf_len
= get_safe_SVAL(param
,tpscnt
, p
, 2, 0);
1289 uint32 servertype
= get_safe_IVAL(param
,tpscnt
,p
,4, 0);
1291 int data_len
, fixed_len
, string_len
;
1292 int f_len
= 0, s_len
= 0;
1293 struct srv_info_struct
*servers
=NULL
;
1294 int counted
=0,total
=0;
1297 BOOL domain_request
;
1300 if (!str1
|| !str2
|| !p
) {
1304 /* If someone sets all the bits they don't really mean to set
1305 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1308 if (servertype
== SV_TYPE_ALL
) {
1309 servertype
&= ~(SV_TYPE_DOMAIN_ENUM
|SV_TYPE_LOCAL_LIST_ONLY
);
1312 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1313 any other bit (they may just set this bit on it's own) they
1314 want all the locally seen servers. However this bit can be
1315 set on its own so set the requested servers to be
1316 ALL - DOMAIN_ENUM. */
1318 if ((servertype
& SV_TYPE_LOCAL_LIST_ONLY
) && !(servertype
& SV_TYPE_DOMAIN_ENUM
)) {
1319 servertype
= SV_TYPE_ALL
& ~(SV_TYPE_DOMAIN_ENUM
);
1322 domain_request
= ((servertype
& SV_TYPE_DOMAIN_ENUM
) != 0);
1323 local_request
= ((servertype
& SV_TYPE_LOCAL_LIST_ONLY
) != 0);
1327 if (!prefix_ok(str1
,"WrLehD")) {
1330 if (!check_server_info(uLevel
,str2
)) {
1334 DEBUG(4, ("server request level: %s %8x ", str2
, servertype
));
1335 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request
)));
1336 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request
)));
1338 if (strcmp(str1
, "WrLehDz") == 0) {
1339 if (skip_string(param
,tpscnt
,p
) == NULL
) {
1342 pull_ascii_fstring(domain
, p
);
1344 fstrcpy(domain
, lp_workgroup());
1347 if (lp_browse_list()) {
1348 total
= get_server_info(servertype
,&servers
,domain
);
1351 data_len
= fixed_len
= string_len
= 0;
1355 qsort(servers
,total
,sizeof(servers
[0]),QSORT_CAST srv_comp
);
1359 char *lastname
=NULL
;
1361 for (i
=0;i
<total
;i
++) {
1362 struct srv_info_struct
*s
= &servers
[i
];
1364 if (lastname
&& strequal(lastname
,s
->name
)) {
1368 data_len
+= fill_srv_info(s
,uLevel
,0,&f_len
,0,&s_len
,0);
1369 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1370 s
->name
, s
->type
, s
->comment
, s
->domain
));
1372 if (data_len
<= buf_len
) {
1375 string_len
+= s_len
;
1382 *rdata_len
= fixed_len
+ string_len
;
1383 *rdata
= SMB_REALLOC_LIMIT(*rdata
,*rdata_len
);
1387 memset(*rdata
,'\0',*rdata_len
);
1389 p2
= (*rdata
) + fixed_len
; /* auxilliary data (strings) will go here */
1395 char *lastname
=NULL
;
1396 int count2
= counted
;
1398 for (i
= 0; i
< total
&& count2
;i
++) {
1399 struct srv_info_struct
*s
= &servers
[i
];
1401 if (lastname
&& strequal(lastname
,s
->name
)) {
1405 fill_srv_info(s
,uLevel
,&p
,&f_len
,&p2
,&s_len
,*rdata
);
1406 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1407 s
->name
, s
->type
, s
->comment
, s
->domain
));
1413 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
1417 SSVAL(*rparam
,0,(missed
== 0 ? NERR_Success
: ERRmoredata
));
1419 SSVAL(*rparam
,4,counted
);
1420 SSVAL(*rparam
,6,counted
+missed
);
1424 DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
1425 domain
,uLevel
,counted
,counted
+missed
));
1430 /****************************************************************************
1431 command 0x34 - suspected of being a "Lookup Names" stub api
1432 ****************************************************************************/
1434 static BOOL
api_RNetGroupGetUsers(connection_struct
*conn
, uint16 vuid
,
1435 char *param
, int tpscnt
,
1436 char *data
, int tdscnt
,
1437 int mdrcnt
, int mprcnt
, char **rdata
,
1438 char **rparam
, int *rdata_len
, int *rparam_len
)
1440 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
1441 char *str2
= skip_string(param
,tpscnt
,str1
);
1442 char *p
= skip_string(param
,tpscnt
,str2
);
1443 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
1444 int buf_len
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
1448 if (!str1
|| !str2
|| !p
) {
1452 DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
1453 str1
, str2
, p
, uLevel
, buf_len
));
1455 if (!prefix_ok(str1
,"zWrLeh")) {
1462 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
1467 SSVAL(*rparam
,0,0x08AC); /* informational warning message */
1469 SSVAL(*rparam
,4,counted
);
1470 SSVAL(*rparam
,6,counted
+missed
);
1475 /****************************************************************************
1476 get info about a share
1477 ****************************************************************************/
1479 static BOOL
check_share_info(int uLevel
, char* id
)
1483 if (strcmp(id
,"B13") != 0) {
1488 if (strcmp(id
,"B13BWz") != 0) {
1493 if (strcmp(id
,"B13BWzWWWzB9B") != 0) {
1498 if (strcmp(id
,"B13BWzWWWzB9BB9BWzWWzWW") != 0) {
1508 static int fill_share_info(connection_struct
*conn
, int snum
, int uLevel
,
1509 char** buf
, int* buflen
,
1510 char** stringbuf
, int* stringspace
, char* baseaddr
)
1540 len
+= StrlenExpanded(conn
,snum
,lp_comment(snum
));
1543 len
+= strlen(lp_pathname(snum
)) + 1;
1546 *buflen
= struct_len
;
1551 return struct_len
+ len
;
1556 if ((*buflen
) < struct_len
) {
1564 p2
= p
+ struct_len
;
1565 l2
= (*buflen
) - struct_len
;
1572 push_ascii(p
,lp_servicename(snum
),13, STR_TERMINATE
);
1578 type
= STYPE_DISKTREE
;
1579 if (lp_print_ok(snum
)) {
1580 type
= STYPE_PRINTQ
;
1582 if (strequal("IPC",lp_fstype(snum
))) {
1585 SSVAL(p
,14,type
); /* device type */
1586 SIVAL(p
,16,PTR_DIFF(p2
,baseaddr
));
1587 len
+= CopyExpanded(conn
,snum
,&p2
,lp_comment(snum
),&l2
);
1591 SSVAL(p
,20,ACCESS_READ
|ACCESS_WRITE
|ACCESS_CREATE
); /* permissions */
1592 SSVALS(p
,22,-1); /* max uses */
1593 SSVAL(p
,24,1); /* current uses */
1594 SIVAL(p
,26,PTR_DIFF(p2
,baseaddr
)); /* local pathname */
1595 len
+= CopyAndAdvance(&p2
,lp_pathname(snum
),&l2
);
1596 memset(p
+30,0,SHPWLEN
+2); /* passwd (reserved), pad field */
1600 memset(p
+40,0,SHPWLEN
+2);
1611 (*buf
) = p
+ struct_len
;
1612 (*buflen
) -= struct_len
;
1614 (*stringspace
) = l2
;
1623 static BOOL
api_RNetShareGetInfo(connection_struct
*conn
,uint16 vuid
,
1624 char *param
, int tpscnt
,
1625 char *data
, int tdscnt
,
1626 int mdrcnt
,int mprcnt
,
1627 char **rdata
,char **rparam
,
1628 int *rdata_len
,int *rparam_len
)
1630 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
1631 char *str2
= skip_string(param
,tpscnt
,str1
);
1632 char *netname
= skip_string(param
,tpscnt
,str2
);
1633 char *p
= skip_string(param
,tpscnt
,netname
);
1634 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
1637 if (!str1
|| !str2
|| !netname
|| !p
) {
1641 snum
= find_service(netname
);
1646 /* check it's a supported varient */
1647 if (!prefix_ok(str1
,"zWrLh")) {
1650 if (!check_share_info(uLevel
,str2
)) {
1654 *rdata
= SMB_REALLOC_LIMIT(*rdata
,mdrcnt
);
1659 *rdata_len
= fill_share_info(conn
,snum
,uLevel
,&p
,&mdrcnt
,0,0,0);
1660 if (*rdata_len
< 0) {
1665 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
1669 SSVAL(*rparam
,0,NERR_Success
);
1670 SSVAL(*rparam
,2,0); /* converter word */
1671 SSVAL(*rparam
,4,*rdata_len
);
1676 /****************************************************************************
1677 View the list of available shares.
1679 This function is the server side of the NetShareEnum() RAP call.
1680 It fills the return buffer with share names and share comments.
1681 Note that the return buffer normally (in all known cases) allows only
1682 twelve byte strings for share names (plus one for a nul terminator).
1683 Share names longer than 12 bytes must be skipped.
1684 ****************************************************************************/
1686 static BOOL
api_RNetShareEnum( connection_struct
*conn
, uint16 vuid
,
1687 char *param
, int tpscnt
,
1688 char *data
, int tdscnt
,
1696 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
1697 char *str2
= skip_string(param
,tpscnt
,str1
);
1698 char *p
= skip_string(param
,tpscnt
,str2
);
1699 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
1700 int buf_len
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
1703 int total
=0,counted
=0;
1704 BOOL missed
= False
;
1706 int data_len
, fixed_len
, string_len
;
1707 int f_len
= 0, s_len
= 0;
1709 if (!str1
|| !str2
|| !p
) {
1713 if (!prefix_ok(str1
,"WrLeh")) {
1716 if (!check_share_info(uLevel
,str2
)) {
1720 /* Ensure all the usershares are loaded. */
1722 load_registry_shares();
1723 count
= load_usershare_shares();
1726 data_len
= fixed_len
= string_len
= 0;
1727 for (i
=0;i
<count
;i
++) {
1728 fstring servicename_dos
;
1729 if (!(lp_browseable(i
) && lp_snum_ok(i
))) {
1732 push_ascii_fstring(servicename_dos
, lp_servicename(i
));
1733 /* Maximum name length = 13. */
1734 if( lp_browseable( i
) && lp_snum_ok( i
) && (strlen(servicename_dos
) < 13)) {
1736 data_len
+= fill_share_info(conn
,i
,uLevel
,0,&f_len
,0,&s_len
,0);
1737 if (data_len
<= buf_len
) {
1740 string_len
+= s_len
;
1747 *rdata_len
= fixed_len
+ string_len
;
1748 *rdata
= SMB_REALLOC_LIMIT(*rdata
,*rdata_len
);
1752 memset(*rdata
,0,*rdata_len
);
1754 p2
= (*rdata
) + fixed_len
; /* auxiliary data (strings) will go here */
1759 for( i
= 0; i
< count
; i
++ ) {
1760 fstring servicename_dos
;
1761 if (!(lp_browseable(i
) && lp_snum_ok(i
))) {
1765 push_ascii_fstring(servicename_dos
, lp_servicename(i
));
1766 if (lp_browseable(i
) && lp_snum_ok(i
) && (strlen(servicename_dos
) < 13)) {
1767 if (fill_share_info( conn
,i
,uLevel
,&p
,&f_len
,&p2
,&s_len
,*rdata
) < 0) {
1774 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
1778 SSVAL(*rparam
,0,missed
? ERRmoredata
: NERR_Success
);
1780 SSVAL(*rparam
,4,counted
);
1781 SSVAL(*rparam
,6,total
);
1783 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
1784 counted
,total
,uLevel
,
1785 buf_len
,*rdata_len
,mdrcnt
));
1790 /****************************************************************************
1792 ****************************************************************************/
1794 static BOOL
api_RNetShareAdd(connection_struct
*conn
,uint16 vuid
,
1795 char *param
, int tpscnt
,
1796 char *data
, int tdscnt
,
1797 int mdrcnt
,int mprcnt
,
1798 char **rdata
,char **rparam
,
1799 int *rdata_len
,int *rparam_len
)
1801 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
1802 char *str2
= skip_string(param
,tpscnt
,str1
);
1803 char *p
= skip_string(param
,tpscnt
,str2
);
1804 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
1808 char *command
, *cmdname
;
1809 unsigned int offset
;
1813 if (!str1
|| !str2
|| !p
) {
1817 /* check it's a supported varient */
1818 if (!prefix_ok(str1
,RAP_WShareAdd_REQ
)) {
1821 if (!check_share_info(uLevel
,str2
)) {
1828 /* Do we have a string ? */
1829 if (skip_string(data
,mdrcnt
,data
) == NULL
) {
1832 pull_ascii_fstring(sharename
,data
);
1833 snum
= find_service(sharename
);
1834 if (snum
>= 0) { /* already exists */
1843 /* only support disk share adds */
1844 if (SVAL(data
,14)!=STYPE_DISKTREE
) {
1848 offset
= IVAL(data
, 16);
1849 if (offset
>= mdrcnt
) {
1850 res
= ERRinvalidparam
;
1854 /* Do we have a string ? */
1855 if (skip_string(data
,mdrcnt
,data
+offset
) == NULL
) {
1858 pull_ascii_fstring(comment
, offset
? (data
+offset
) : "");
1860 offset
= IVAL(data
, 26);
1862 if (offset
>= mdrcnt
) {
1863 res
= ERRinvalidparam
;
1867 /* Do we have a string ? */
1868 if (skip_string(data
,mdrcnt
,data
+offset
) == NULL
) {
1871 pull_ascii_pstring(pathname
, offset
? (data
+offset
) : "");
1873 string_replace(sharename
, '"', ' ');
1874 string_replace(pathname
, '"', ' ');
1875 string_replace(comment
, '"', ' ');
1877 cmdname
= lp_add_share_cmd();
1879 if (!cmdname
|| *cmdname
== '\0') {
1883 asprintf(&command
, "%s \"%s\" \"%s\" \"%s\" \"%s\"",
1884 lp_add_share_cmd(), dyn_CONFIGFILE
, sharename
, pathname
, comment
);
1887 DEBUG(10,("api_RNetShareAdd: Running [%s]\n", command
));
1889 if ((res
= smbrun(command
, NULL
)) != 0) {
1890 DEBUG(1,("api_RNetShareAdd: Running [%s] returned (%d)\n", command
, res
));
1896 message_send_all(smbd_messaging_context(),
1897 MSG_SMB_CONF_UPDATED
, NULL
, 0, NULL
);
1904 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
1908 SSVAL(*rparam
,0,NERR_Success
);
1909 SSVAL(*rparam
,2,0); /* converter word */
1910 SSVAL(*rparam
,4,*rdata_len
);
1918 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
1923 SSVAL(*rparam
,0,res
);
1928 /****************************************************************************
1929 view list of groups available
1930 ****************************************************************************/
1932 static BOOL
api_RNetGroupEnum(connection_struct
*conn
,uint16 vuid
,
1933 char *param
, int tpscnt
,
1934 char *data
, int tdscnt
,
1935 int mdrcnt
,int mprcnt
,
1936 char **rdata
,char **rparam
,
1937 int *rdata_len
,int *rparam_len
)
1941 int resume_context
, cli_buf_size
;
1942 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
1943 char *str2
= skip_string(param
,tpscnt
,str1
);
1944 char *p
= skip_string(param
,tpscnt
,str2
);
1946 struct pdb_search
*search
;
1947 struct samr_displayentry
*entries
;
1951 if (!str1
|| !str2
|| !p
) {
1955 if (strcmp(str1
,"WrLeh") != 0) {
1960 * W-> resume context (number of users to skip)
1961 * r -> return parameter pointer to receive buffer
1962 * L -> length of receive buffer
1963 * e -> return parameter number of entries
1964 * h -> return parameter total number of users
1967 if (strcmp("B21",str2
) != 0) {
1971 /* get list of domain groups SID_DOMAIN_GRP=2 */
1973 search
= pdb_search_groups();
1976 if (search
== NULL
) {
1977 DEBUG(3,("api_RNetGroupEnum:failed to get group list"));
1981 resume_context
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
1982 cli_buf_size
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
1983 DEBUG(10,("api_RNetGroupEnum:resume context: %d, client buffer size: "
1984 "%d\n", resume_context
, cli_buf_size
));
1987 num_entries
= pdb_search_entries(search
, resume_context
, 0xffffffff,
1991 *rdata_len
= cli_buf_size
;
1992 *rdata
= SMB_REALLOC_LIMIT(*rdata
,*rdata_len
);
1999 for(i
=0; i
<num_entries
; i
++) {
2001 fstrcpy(name
, entries
[i
].account_name
);
2002 if( ((PTR_DIFF(p
,*rdata
)+21) <= *rdata_len
) ) {
2003 /* truncate the name at 21 chars. */
2004 memcpy(p
, name
, 21);
2005 DEBUG(10,("adding entry %d group %s\n", i
, p
));
2007 p
+= 5; /* Both NT4 and W2k3SP1 do padding here.
2010 /* set overflow error */
2011 DEBUG(3,("overflow on entry %d group %s\n", i
, name
));
2017 pdb_search_destroy(search
);
2019 *rdata_len
= PTR_DIFF(p
,*rdata
);
2022 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
2026 SSVAL(*rparam
, 0, errflags
);
2027 SSVAL(*rparam
, 2, 0); /* converter word */
2028 SSVAL(*rparam
, 4, i
); /* is this right?? */
2029 SSVAL(*rparam
, 6, resume_context
+num_entries
); /* is this right?? */
2034 /*******************************************************************
2035 Get groups that a user is a member of.
2036 ******************************************************************/
2038 static BOOL
api_NetUserGetGroups(connection_struct
*conn
,uint16 vuid
,
2039 char *param
, int tpscnt
,
2040 char *data
, int tdscnt
,
2041 int mdrcnt
,int mprcnt
,
2042 char **rdata
,char **rparam
,
2043 int *rdata_len
,int *rparam_len
)
2045 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2046 char *str2
= skip_string(param
,tpscnt
,str1
);
2047 char *UserName
= skip_string(param
,tpscnt
,str2
);
2048 char *p
= skip_string(param
,tpscnt
,UserName
);
2049 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2050 const char *level_string
;
2052 struct samu
*sampw
= NULL
;
2060 enum lsa_SidType type
;
2061 TALLOC_CTX
*mem_ctx
;
2063 if (!str1
|| !str2
|| !UserName
|| !p
) {
2068 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
2073 /* check it's a supported varient */
2075 if ( strcmp(str1
,"zWrLeh") != 0 )
2080 level_string
= "B21";
2086 if (strcmp(level_string
,str2
) != 0)
2089 *rdata_len
= mdrcnt
+ 1024;
2090 *rdata
= SMB_REALLOC_LIMIT(*rdata
,*rdata_len
);
2094 SSVAL(*rparam
,0,NERR_Success
);
2095 SSVAL(*rparam
,2,0); /* converter word */
2099 mem_ctx
= talloc_new(NULL
);
2100 if (mem_ctx
== NULL
) {
2101 DEBUG(0, ("talloc_new failed\n"));
2105 if ( !(sampw
= samu_new(mem_ctx
)) ) {
2106 DEBUG(0, ("samu_new() failed!\n"));
2107 TALLOC_FREE(mem_ctx
);
2111 /* Lookup the user information; This should only be one of
2112 our accounts (not remote domains) */
2114 become_root(); /* ROOT BLOCK */
2116 if (!lookup_name(mem_ctx
, UserName
, LOOKUP_NAME_ALL
,
2117 NULL
, NULL
, &user_sid
, &type
)) {
2118 DEBUG(10, ("lookup_name(%s) failed\n", UserName
));
2122 if (type
!= SID_NAME_USER
) {
2123 DEBUG(10, ("%s is a %s, not a user\n", UserName
,
2124 sid_type_lookup(type
)));
2128 if ( !pdb_getsampwsid(sampw
, &user_sid
) ) {
2129 DEBUG(10, ("pdb_getsampwsid(%s) failed for user %s\n",
2130 sid_string_static(&user_sid
), UserName
));
2138 result
= pdb_enum_group_memberships(mem_ctx
, sampw
,
2139 &sids
, &gids
, &num_groups
);
2141 if (!NT_STATUS_IS_OK(result
)) {
2142 DEBUG(10, ("pdb_enum_group_memberships failed for %s\n",
2147 for (i
=0; i
<num_groups
; i
++) {
2149 const char *grp_name
;
2151 if ( lookup_sid(mem_ctx
, &sids
[i
], NULL
, &grp_name
, NULL
) ) {
2152 pstrcpy(p
, grp_name
);
2158 *rdata_len
= PTR_DIFF(p
,*rdata
);
2160 SSVAL(*rparam
,4,count
); /* is this right?? */
2161 SSVAL(*rparam
,6,count
); /* is this right?? */
2166 unbecome_root(); /* END ROOT BLOCK */
2168 TALLOC_FREE(mem_ctx
);
2173 /*******************************************************************
2175 ******************************************************************/
2177 static BOOL
api_RNetUserEnum(connection_struct
*conn
, uint16 vuid
,
2178 char *param
, int tpscnt
,
2179 char *data
, int tdscnt
,
2180 int mdrcnt
,int mprcnt
,
2181 char **rdata
,char **rparam
,
2182 int *rdata_len
,int *rparam_len
)
2187 int i
, resume_context
, cli_buf_size
;
2188 struct pdb_search
*search
;
2189 struct samr_displayentry
*users
;
2191 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2192 char *str2
= skip_string(param
,tpscnt
,str1
);
2193 char *p
= skip_string(param
,tpscnt
,str2
);
2195 if (!str1
|| !str2
|| !p
) {
2199 if (strcmp(str1
,"WrLeh") != 0)
2202 * W-> resume context (number of users to skip)
2203 * r -> return parameter pointer to receive buffer
2204 * L -> length of receive buffer
2205 * e -> return parameter number of entries
2206 * h -> return parameter total number of users
2209 resume_context
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2210 cli_buf_size
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
2211 DEBUG(10,("api_RNetUserEnum:resume context: %d, client buffer size: %d\n",
2212 resume_context
, cli_buf_size
));
2215 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
2220 /* check it's a supported varient */
2221 if (strcmp("B21",str2
) != 0)
2224 *rdata_len
= cli_buf_size
;
2225 *rdata
= SMB_REALLOC_LIMIT(*rdata
,*rdata_len
);
2233 search
= pdb_search_users(ACB_NORMAL
);
2235 if (search
== NULL
) {
2236 DEBUG(0, ("api_RNetUserEnum:unable to open sam database.\n"));
2241 num_users
= pdb_search_entries(search
, resume_context
, 0xffffffff,
2245 errflags
=NERR_Success
;
2247 for (i
=0; i
<num_users
; i
++) {
2248 const char *name
= users
[i
].account_name
;
2250 if(((PTR_DIFF(p
,*rdata
)+21)<=*rdata_len
)&&(strlen(name
)<=21)) {
2252 DEBUG(10,("api_RNetUserEnum:adding entry %d username "
2253 "%s\n",count_sent
,p
));
2257 /* set overflow error */
2258 DEBUG(10,("api_RNetUserEnum:overflow on entry %d "
2259 "username %s\n",count_sent
,name
));
2265 pdb_search_destroy(search
);
2267 *rdata_len
= PTR_DIFF(p
,*rdata
);
2269 SSVAL(*rparam
,0,errflags
);
2270 SSVAL(*rparam
,2,0); /* converter word */
2271 SSVAL(*rparam
,4,count_sent
); /* is this right?? */
2272 SSVAL(*rparam
,6,num_users
); /* is this right?? */
2277 /****************************************************************************
2278 Get the time of day info.
2279 ****************************************************************************/
2281 static BOOL
api_NetRemoteTOD(connection_struct
*conn
,uint16 vuid
,
2282 char *param
, int tpscnt
,
2283 char *data
, int tdscnt
,
2284 int mdrcnt
,int mprcnt
,
2285 char **rdata
,char **rparam
,
2286 int *rdata_len
,int *rparam_len
)
2289 time_t unixdate
= time(NULL
);
2293 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
2299 *rdata
= SMB_REALLOC_LIMIT(*rdata
,*rdata_len
);
2304 SSVAL(*rparam
,0,NERR_Success
);
2305 SSVAL(*rparam
,2,0); /* converter word */
2309 srv_put_dos_date3(p
,0,unixdate
); /* this is the time that is looked at
2310 by NT in a "net time" operation,
2311 it seems to ignore the one below */
2313 /* the client expects to get localtime, not GMT, in this bit
2314 (I think, this needs testing) */
2315 t
= localtime(&unixdate
);
2320 SIVAL(p
,4,0); /* msecs ? */
2321 SCVAL(p
,8,t
->tm_hour
);
2322 SCVAL(p
,9,t
->tm_min
);
2323 SCVAL(p
,10,t
->tm_sec
);
2324 SCVAL(p
,11,0); /* hundredths of seconds */
2325 SSVALS(p
,12,get_time_zone(unixdate
)/60); /* timezone in minutes from GMT */
2326 SSVAL(p
,14,10000); /* timer interval in 0.0001 of sec */
2327 SCVAL(p
,16,t
->tm_mday
);
2328 SCVAL(p
,17,t
->tm_mon
+ 1);
2329 SSVAL(p
,18,1900+t
->tm_year
);
2330 SCVAL(p
,20,t
->tm_wday
);
2335 /****************************************************************************
2336 Set the user password.
2337 *****************************************************************************/
2339 static BOOL
api_SetUserPassword(connection_struct
*conn
,uint16 vuid
,
2340 char *param
, int tpscnt
,
2341 char *data
, int tdscnt
,
2342 int mdrcnt
,int mprcnt
,
2343 char **rdata
,char **rparam
,
2344 int *rdata_len
,int *rparam_len
)
2346 char *np
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2349 fstring pass1
,pass2
;
2351 /* Skip 2 strings. */
2352 p
= skip_string(param
,tpscnt
,np
);
2353 p
= skip_string(param
,tpscnt
,p
);
2359 /* Do we have a string ? */
2360 if (skip_string(param
,tpscnt
,p
) == NULL
) {
2363 pull_ascii_fstring(user
,p
);
2365 p
= skip_string(param
,tpscnt
,p
);
2370 memset(pass1
,'\0',sizeof(pass1
));
2371 memset(pass2
,'\0',sizeof(pass2
));
2373 * We use 31 here not 32 as we're checking
2374 * the last byte we want to access is safe.
2376 if (!is_offset_safe(param
,tpscnt
,p
,31)) {
2380 memcpy(pass2
,p
+16,16);
2383 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
2390 SSVAL(*rparam
,0,NERR_badpass
);
2391 SSVAL(*rparam
,2,0); /* converter word */
2393 DEBUG(3,("Set password for <%s>\n",user
));
2396 * Attempt to verify the old password against smbpasswd entries
2397 * Win98 clients send old and new password in plaintext for this call.
2401 auth_serversupplied_info
*server_info
= NULL
;
2402 DATA_BLOB password
= data_blob(pass1
, strlen(pass1
)+1);
2404 if (NT_STATUS_IS_OK(check_plaintext_password(user
,password
,&server_info
))) {
2407 if (NT_STATUS_IS_OK(change_oem_password(server_info
->sam_account
, pass1
, pass2
, False
, NULL
))) {
2408 SSVAL(*rparam
,0,NERR_Success
);
2412 TALLOC_FREE(server_info
);
2414 data_blob_clear_free(&password
);
2418 * If the plaintext change failed, attempt
2419 * the old encrypted method. NT will generate this
2420 * after trying the samr method. Note that this
2421 * method is done as a last resort as this
2422 * password change method loses the NT password hash
2423 * and cannot change the UNIX password as no plaintext
2427 if(SVAL(*rparam
,0) != NERR_Success
) {
2428 struct samu
*hnd
= NULL
;
2430 if (check_lanman_password(user
,(unsigned char *)pass1
,(unsigned char *)pass2
, &hnd
)) {
2432 if (change_lanman_password(hnd
,(uchar
*)pass2
)) {
2433 SSVAL(*rparam
,0,NERR_Success
);
2440 memset((char *)pass1
,'\0',sizeof(fstring
));
2441 memset((char *)pass2
,'\0',sizeof(fstring
));
2446 /****************************************************************************
2447 Set the user password (SamOEM version - gets plaintext).
2448 ****************************************************************************/
2450 static BOOL
api_SamOEMChangePassword(connection_struct
*conn
,uint16 vuid
,
2451 char *param
, int tpscnt
,
2452 char *data
, int tdscnt
,
2453 int mdrcnt
,int mprcnt
,
2454 char **rdata
,char **rparam
,
2455 int *rdata_len
,int *rparam_len
)
2458 char *p
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2460 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
2470 SSVAL(*rparam
,0,NERR_badpass
);
2473 * Check the parameter definition is correct.
2476 /* Do we have a string ? */
2477 if (skip_string(param
,tpscnt
,p
) == 0) {
2480 if(!strequal(p
, "zsT")) {
2481 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", p
));
2484 p
= skip_string(param
, tpscnt
, p
);
2489 /* Do we have a string ? */
2490 if (skip_string(param
,tpscnt
,p
) == 0) {
2493 if(!strequal(p
, "B516B16")) {
2494 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p
));
2497 p
= skip_string(param
,tpscnt
,p
);
2501 /* Do we have a string ? */
2502 if (skip_string(param
,tpscnt
,p
) == 0) {
2505 p
+= pull_ascii_fstring(user
,p
);
2507 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user
));
2510 * Pass the user through the NT -> unix user mapping
2514 (void)map_username(user
);
2516 if (NT_STATUS_IS_OK(pass_oem_change(user
, (uchar
*) data
, (uchar
*)&data
[516], NULL
, NULL
, NULL
))) {
2517 SSVAL(*rparam
,0,NERR_Success
);
2523 /****************************************************************************
2526 ****************************************************************************/
2528 static BOOL
api_RDosPrintJobDel(connection_struct
*conn
,uint16 vuid
,
2529 char *param
, int tpscnt
,
2530 char *data
, int tdscnt
,
2531 int mdrcnt
,int mprcnt
,
2532 char **rdata
,char **rparam
,
2533 int *rdata_len
,int *rparam_len
)
2535 int function
= get_safe_SVAL(param
,tpscnt
,param
,0,0);
2536 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2537 char *str2
= skip_string(param
,tpscnt
,str1
);
2538 char *p
= skip_string(param
,tpscnt
,str2
);
2543 WERROR werr
= WERR_OK
;
2545 if (!str1
|| !str2
|| !p
) {
2549 * We use 1 here not 2 as we're checking
2550 * the last byte we want to access is safe.
2552 if (!is_offset_safe(param
,tpscnt
,p
,1)) {
2555 if(!rap_to_pjobid(SVAL(p
,0), sharename
, &jobid
))
2558 /* check it's a supported varient */
2559 if (!(strcsequal(str1
,"W") && strcsequal(str2
,"")))
2563 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
2569 if (!print_job_exists(sharename
, jobid
)) {
2570 errcode
= NERR_JobNotFound
;
2574 snum
= lp_servicenumber( sharename
);
2576 errcode
= NERR_DestNotFound
;
2580 errcode
= NERR_notsupported
;
2583 case 81: /* delete */
2584 if (print_job_delete(¤t_user
, snum
, jobid
, &werr
))
2585 errcode
= NERR_Success
;
2587 case 82: /* pause */
2588 if (print_job_pause(¤t_user
, snum
, jobid
, &werr
))
2589 errcode
= NERR_Success
;
2591 case 83: /* resume */
2592 if (print_job_resume(¤t_user
, snum
, jobid
, &werr
))
2593 errcode
= NERR_Success
;
2597 if (!W_ERROR_IS_OK(werr
))
2598 errcode
= W_ERROR_V(werr
);
2601 SSVAL(*rparam
,0,errcode
);
2602 SSVAL(*rparam
,2,0); /* converter word */
2607 /****************************************************************************
2608 Purge a print queue - or pause or resume it.
2609 ****************************************************************************/
2611 static BOOL
api_WPrintQueueCtrl(connection_struct
*conn
,uint16 vuid
,
2612 char *param
, int tpscnt
,
2613 char *data
, int tdscnt
,
2614 int mdrcnt
,int mprcnt
,
2615 char **rdata
,char **rparam
,
2616 int *rdata_len
,int *rparam_len
)
2618 int function
= get_safe_SVAL(param
,tpscnt
,param
,0,0);
2619 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2620 char *str2
= skip_string(param
,tpscnt
,str1
);
2621 char *QueueName
= skip_string(param
,tpscnt
,str2
);
2622 int errcode
= NERR_notsupported
;
2624 WERROR werr
= WERR_OK
;
2626 if (!str1
|| !str2
|| !QueueName
) {
2630 /* check it's a supported varient */
2631 if (!(strcsequal(str1
,"z") && strcsequal(str2
,"")))
2635 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
2641 if (skip_string(param
,tpscnt
,QueueName
) == NULL
) {
2644 snum
= print_queue_snum(QueueName
);
2647 errcode
= NERR_JobNotFound
;
2652 case 74: /* Pause queue */
2653 if (print_queue_pause(¤t_user
, snum
, &werr
)) errcode
= NERR_Success
;
2655 case 75: /* Resume queue */
2656 if (print_queue_resume(¤t_user
, snum
, &werr
)) errcode
= NERR_Success
;
2658 case 103: /* Purge */
2659 if (print_queue_purge(¤t_user
, snum
, &werr
)) errcode
= NERR_Success
;
2663 if (!W_ERROR_IS_OK(werr
)) errcode
= W_ERROR_V(werr
);
2666 SSVAL(*rparam
,0,errcode
);
2667 SSVAL(*rparam
,2,0); /* converter word */
2672 /****************************************************************************
2673 set the property of a print job (undocumented?)
2674 ? function = 0xb -> set name of print job
2675 ? function = 0x6 -> move print job up/down
2676 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
2677 or <WWsTP> <WB21BB16B10zWWzDDz>
2678 ****************************************************************************/
2680 static int check_printjob_info(struct pack_desc
* desc
,
2681 int uLevel
, char* id
)
2683 desc
->subformat
= NULL
;
2685 case 0: desc
->format
= "W"; break;
2686 case 1: desc
->format
= "WB21BB16B10zWWzDDz"; break;
2687 case 2: desc
->format
= "WWzWWDDzz"; break;
2688 case 3: desc
->format
= "WWzWWDDzzzzzzzzzzlz"; break;
2689 case 4: desc
->format
= "WWzWWDDzzzzzDDDDDDD"; break;
2691 DEBUG(0,("check_printjob_info: invalid level %d\n",
2695 if (id
== NULL
|| strcmp(desc
->format
,id
) != 0) {
2696 DEBUG(0,("check_printjob_info: invalid format %s\n",
2697 id
? id
: "<NULL>" ));
2703 static BOOL
api_PrintJobInfo(connection_struct
*conn
, uint16 vuid
,
2704 char *param
, int tpscnt
,
2705 char *data
, int tdscnt
,
2706 int mdrcnt
,int mprcnt
,
2707 char **rdata
,char **rparam
,
2708 int *rdata_len
,int *rparam_len
)
2710 struct pack_desc desc
;
2711 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2712 char *str2
= skip_string(param
,tpscnt
,str1
);
2713 char *p
= skip_string(param
,tpscnt
,str2
);
2716 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,2,-1);
2717 int function
= get_safe_SVAL(param
,tpscnt
,p
,4,-1);
2720 if (!str1
|| !str2
|| !p
) {
2724 * We use 1 here not 2 as we're checking
2725 * the last byte we want to access is safe.
2727 if (!is_offset_safe(param
,tpscnt
,p
,1)) {
2730 if(!rap_to_pjobid(SVAL(p
,0), sharename
, &jobid
))
2733 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
2738 if (!share_defined(sharename
)) {
2739 DEBUG(0,("api_PrintJobInfo: sharen [%s] not defined\n",
2746 /* check it's a supported varient */
2747 if ((strcmp(str1
,"WWsTP")) ||
2748 (!check_printjob_info(&desc
,uLevel
,str2
)))
2751 if (!print_job_exists(sharename
, jobid
)) {
2752 errcode
=NERR_JobNotFound
;
2756 errcode
= NERR_notsupported
;
2760 /* change job place in the queue,
2761 data gives the new place */
2762 place
= SVAL(data
,0);
2763 if (print_job_set_place(sharename
, jobid
, place
)) {
2764 errcode
=NERR_Success
;
2769 /* change print job name, data gives the name */
2770 if (print_job_set_name(sharename
, jobid
, data
)) {
2771 errcode
=NERR_Success
;
2780 SSVALS(*rparam
,0,errcode
);
2781 SSVAL(*rparam
,2,0); /* converter word */
2787 /****************************************************************************
2788 Get info about the server.
2789 ****************************************************************************/
2791 static BOOL
api_RNetServerGetInfo(connection_struct
*conn
,uint16 vuid
,
2792 char *param
, int tpscnt
,
2793 char *data
, int tdscnt
,
2794 int mdrcnt
,int mprcnt
,
2795 char **rdata
,char **rparam
,
2796 int *rdata_len
,int *rparam_len
)
2798 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2799 char *str2
= skip_string(param
,tpscnt
,str1
);
2800 char *p
= skip_string(param
,tpscnt
,str2
);
2801 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2805 if (!str1
|| !str2
|| !p
) {
2809 DEBUG(4,("NetServerGetInfo level %d\n",uLevel
));
2811 /* check it's a supported varient */
2812 if (!prefix_ok(str1
,"WrLh")) {
2818 if (strcmp(str2
,"B16") != 0) {
2824 if (strcmp(str2
,"B16BBDz") != 0) {
2830 if (strcmp(str2
,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")!= 0) {
2836 if (strcmp(str2
,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz") != 0) {
2842 if (strcmp(str2
,"DN") != 0) {
2848 if (strcmp(str2
,"B16BBDzWWzzz") != 0) {
2857 *rdata_len
= mdrcnt
;
2858 *rdata
= SMB_REALLOC_LIMIT(*rdata
,*rdata_len
);
2864 p2
= p
+ struct_len
;
2866 srvstr_push(NULL
, p
,global_myname(),16,
2867 STR_ASCII
|STR_UPPER
|STR_TERMINATE
);
2871 struct srv_info_struct
*servers
=NULL
;
2874 uint32 servertype
= lp_default_server_announce();
2876 push_ascii(comment
,lp_serverstring(), MAX_SERVER_STRING_LENGTH
,STR_TERMINATE
);
2878 if ((count
=get_server_info(SV_TYPE_ALL
,&servers
,lp_workgroup()))>0) {
2879 for (i
=0;i
<count
;i
++) {
2880 if (strequal(servers
[i
].name
,global_myname())) {
2881 servertype
= servers
[i
].type
;
2882 push_ascii(comment
,servers
[i
].comment
,sizeof(pstring
),STR_TERMINATE
);
2889 SCVAL(p
,0,lp_major_announce_version());
2890 SCVAL(p
,1,lp_minor_announce_version());
2891 SIVAL(p
,2,servertype
);
2893 if (mdrcnt
== struct_len
) {
2896 SIVAL(p
,6,PTR_DIFF(p2
,*rdata
));
2897 standard_sub_advanced(lp_servicename(SNUM(conn
)), conn
->user
,
2898 conn
->connectpath
, conn
->gid
,
2899 get_current_username(),
2900 current_user_info
.domain
,
2901 comment
, sizeof(comment
));
2902 StrnCpy(p2
,comment
,MAX(mdrcnt
- struct_len
,0));
2903 p2
= skip_string(*rdata
,*rdata_len
,p2
);
2911 return False
; /* not yet implemented */
2914 *rdata_len
= PTR_DIFF(p2
,*rdata
);
2917 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
2921 SSVAL(*rparam
,0,NERR_Success
);
2922 SSVAL(*rparam
,2,0); /* converter word */
2923 SSVAL(*rparam
,4,*rdata_len
);
2928 /****************************************************************************
2929 Get info about the server.
2930 ****************************************************************************/
2932 static BOOL
api_NetWkstaGetInfo(connection_struct
*conn
,uint16 vuid
,
2933 char *param
, int tpscnt
,
2934 char *data
, int tdscnt
,
2935 int mdrcnt
,int mprcnt
,
2936 char **rdata
,char **rparam
,
2937 int *rdata_len
,int *rparam_len
)
2939 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2940 char *str2
= skip_string(param
,tpscnt
,str1
);
2941 char *p
= skip_string(param
,tpscnt
,str2
);
2943 int level
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2945 if (!str1
|| !str2
|| !p
) {
2949 DEBUG(4,("NetWkstaGetInfo level %d\n",level
));
2952 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
2957 /* check it's a supported varient */
2958 if (!(level
==10 && strcsequal(str1
,"WrLh") && strcsequal(str2
,"zzzBBzz"))) {
2962 *rdata_len
= mdrcnt
+ 1024;
2963 *rdata
= SMB_REALLOC_LIMIT(*rdata
,*rdata_len
);
2968 SSVAL(*rparam
,0,NERR_Success
);
2969 SSVAL(*rparam
,2,0); /* converter word */
2972 p2
= get_safe_ptr(*rdata
,*rdata_len
,p
,22);
2977 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* host name */
2978 pstrcpy(p2
,get_local_machine_name());
2980 p2
= skip_string(*rdata
,*rdata_len
,p2
);
2986 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
));
2987 pstrcpy(p2
,current_user_info
.smb_name
);
2988 p2
= skip_string(*rdata
,*rdata_len
,p2
);
2994 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* login domain */
2995 pstrcpy(p2
,lp_workgroup());
2997 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3003 SCVAL(p
,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
3004 SCVAL(p
,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
3007 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
));
3008 pstrcpy(p2
,lp_workgroup()); /* don't know. login domain?? */
3009 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3015 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* don't know */
3017 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3023 *rdata_len
= PTR_DIFF(p2
,*rdata
);
3025 SSVAL(*rparam
,4,*rdata_len
);
3030 /****************************************************************************
3031 get info about a user
3033 struct user_info_11 {
3034 char usri11_name[21]; 0-20
3036 char *usri11_comment; 22-25
3037 char *usri11_usr_comment; 26-29
3038 unsigned short usri11_priv; 30-31
3039 unsigned long usri11_auth_flags; 32-35
3040 long usri11_password_age; 36-39
3041 char *usri11_homedir; 40-43
3042 char *usri11_parms; 44-47
3043 long usri11_last_logon; 48-51
3044 long usri11_last_logoff; 52-55
3045 unsigned short usri11_bad_pw_count; 56-57
3046 unsigned short usri11_num_logons; 58-59
3047 char *usri11_logon_server; 60-63
3048 unsigned short usri11_country_code; 64-65
3049 char *usri11_workstations; 66-69
3050 unsigned long usri11_max_storage; 70-73
3051 unsigned short usri11_units_per_week; 74-75
3052 unsigned char *usri11_logon_hours; 76-79
3053 unsigned short usri11_code_page; 80-81
3058 usri11_name specifies the user name for which information is retireved
3060 usri11_pad aligns the next data structure element to a word boundary
3062 usri11_comment is a null terminated ASCII comment
3064 usri11_user_comment is a null terminated ASCII comment about the user
3066 usri11_priv specifies the level of the privilege assigned to the user.
3067 The possible values are:
3069 Name Value Description
3070 USER_PRIV_GUEST 0 Guest privilege
3071 USER_PRIV_USER 1 User privilege
3072 USER_PRV_ADMIN 2 Administrator privilege
3074 usri11_auth_flags specifies the account operator privileges. The
3075 possible values are:
3077 Name Value Description
3078 AF_OP_PRINT 0 Print operator
3081 Leach, Naik [Page 28]
3085 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
3088 AF_OP_COMM 1 Communications operator
3089 AF_OP_SERVER 2 Server operator
3090 AF_OP_ACCOUNTS 3 Accounts operator
3093 usri11_password_age specifies how many seconds have elapsed since the
3094 password was last changed.
3096 usri11_home_dir points to a null terminated ASCII string that contains
3097 the path name of the user's home directory.
3099 usri11_parms points to a null terminated ASCII string that is set
3100 aside for use by applications.
3102 usri11_last_logon specifies the time when the user last logged on.
3103 This value is stored as the number of seconds elapsed since
3104 00:00:00, January 1, 1970.
3106 usri11_last_logoff specifies the time when the user last logged off.
3107 This value is stored as the number of seconds elapsed since
3108 00:00:00, January 1, 1970. A value of 0 means the last logoff
3111 usri11_bad_pw_count specifies the number of incorrect passwords
3112 entered since the last successful logon.
3114 usri11_log1_num_logons specifies the number of times this user has
3115 logged on. A value of -1 means the number of logons is unknown.
3117 usri11_logon_server points to a null terminated ASCII string that
3118 contains the name of the server to which logon requests are sent.
3119 A null string indicates logon requests should be sent to the
3122 usri11_country_code specifies the country code for the user's language
3125 usri11_workstations points to a null terminated ASCII string that
3126 contains the names of workstations the user may log on from.
3127 There may be up to 8 workstations, with the names separated by
3128 commas. A null strings indicates there are no restrictions.
3130 usri11_max_storage specifies the maximum amount of disk space the user
3131 can occupy. A value of 0xffffffff indicates there are no
3134 usri11_units_per_week specifies the equal number of time units into
3135 which a week is divided. This value must be equal to 168.
3137 usri11_logon_hours points to a 21 byte (168 bits) string that
3138 specifies the time during which the user can log on. Each bit
3139 represents one unique hour in a week. The first bit (bit 0, word
3140 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
3144 Leach, Naik [Page 29]
3148 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
3151 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
3152 are no restrictions.
3154 usri11_code_page specifies the code page for the user's language of
3157 All of the pointers in this data structure need to be treated
3158 specially. The pointer is a 32 bit pointer. The higher 16 bits need
3159 to be ignored. The converter word returned in the parameters section
3160 needs to be subtracted from the lower 16 bits to calculate an offset
3161 into the return buffer where this ASCII string resides.
3163 There is no auxiliary data in the response.
3165 ****************************************************************************/
3167 #define usri11_name 0
3168 #define usri11_pad 21
3169 #define usri11_comment 22
3170 #define usri11_usr_comment 26
3171 #define usri11_full_name 30
3172 #define usri11_priv 34
3173 #define usri11_auth_flags 36
3174 #define usri11_password_age 40
3175 #define usri11_homedir 44
3176 #define usri11_parms 48
3177 #define usri11_last_logon 52
3178 #define usri11_last_logoff 56
3179 #define usri11_bad_pw_count 60
3180 #define usri11_num_logons 62
3181 #define usri11_logon_server 64
3182 #define usri11_country_code 68
3183 #define usri11_workstations 70
3184 #define usri11_max_storage 74
3185 #define usri11_units_per_week 78
3186 #define usri11_logon_hours 80
3187 #define usri11_code_page 84
3188 #define usri11_end 86
3190 #define USER_PRIV_GUEST 0
3191 #define USER_PRIV_USER 1
3192 #define USER_PRIV_ADMIN 2
3194 #define AF_OP_PRINT 0
3195 #define AF_OP_COMM 1
3196 #define AF_OP_SERVER 2
3197 #define AF_OP_ACCOUNTS 3
3200 static BOOL
api_RNetUserGetInfo(connection_struct
*conn
, uint16 vuid
,
3201 char *param
, int tpscnt
,
3202 char *data
, int tdscnt
,
3203 int mdrcnt
,int mprcnt
,
3204 char **rdata
,char **rparam
,
3205 int *rdata_len
,int *rparam_len
)
3207 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3208 char *str2
= skip_string(param
,tpscnt
,str1
);
3209 char *UserName
= skip_string(param
,tpscnt
,str2
);
3210 char *p
= skip_string(param
,tpscnt
,UserName
);
3211 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3213 const char *level_string
;
3215 /* get NIS home of a previously validated user - simeon */
3216 /* With share level security vuid will always be zero.
3217 Don't depend on vuser being non-null !!. JRA */
3218 user_struct
*vuser
= get_valid_user_struct(vuid
);
3220 DEBUG(3,(" Username of UID %d is %s\n", (int)vuser
->uid
,
3221 vuser
->user
.unix_name
));
3224 if (!str1
|| !str2
|| !UserName
|| !p
) {
3229 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
3234 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel
));
3236 /* check it's a supported variant */
3237 if (strcmp(str1
,"zWrLh") != 0) {
3241 case 0: level_string
= "B21"; break;
3242 case 1: level_string
= "B21BB16DWzzWz"; break;
3243 case 2: level_string
= "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
3244 case 10: level_string
= "B21Bzzz"; break;
3245 case 11: level_string
= "B21BzzzWDDzzDDWWzWzDWb21W"; break;
3246 default: return False
;
3249 if (strcmp(level_string
,str2
) != 0) {
3253 *rdata_len
= mdrcnt
+ 1024;
3254 *rdata
= SMB_REALLOC_LIMIT(*rdata
,*rdata_len
);
3259 SSVAL(*rparam
,0,NERR_Success
);
3260 SSVAL(*rparam
,2,0); /* converter word */
3263 p2
= get_safe_ptr(*rdata
,*rdata_len
,p
,usri11_end
);
3269 fstrcpy(p
+usri11_name
,UserName
); /* 21 bytes - user name */
3272 SCVAL(p
,usri11_pad
,0); /* padding - 1 byte */
3277 SIVAL(p
,usri11_comment
,PTR_DIFF(p2
,p
)); /* comment */
3278 pstrcpy(p2
,"Comment");
3279 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3284 SIVAL(p
,usri11_usr_comment
,PTR_DIFF(p2
,p
)); /* user_comment */
3285 pstrcpy(p2
,"UserComment");
3286 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3291 /* EEK! the cifsrap.txt doesn't have this in!!!! */
3292 SIVAL(p
,usri11_full_name
,PTR_DIFF(p2
,p
)); /* full name */
3293 pstrcpy(p2
,((vuser
!= NULL
) ? vuser
->user
.full_name
: UserName
));
3294 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3301 /* modelled after NTAS 3.51 reply */
3302 SSVAL(p
,usri11_priv
,conn
->admin_user
?USER_PRIV_ADMIN
:USER_PRIV_USER
);
3303 SIVAL(p
,usri11_auth_flags
,AF_OP_PRINT
); /* auth flags */
3304 SIVALS(p
,usri11_password_age
,-1); /* password age */
3305 SIVAL(p
,usri11_homedir
,PTR_DIFF(p2
,p
)); /* home dir */
3306 pstrcpy(p2
, vuser
&& vuser
->homedir
? vuser
->homedir
: "");
3307 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3311 SIVAL(p
,usri11_parms
,PTR_DIFF(p2
,p
)); /* parms */
3313 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3317 SIVAL(p
,usri11_last_logon
,0); /* last logon */
3318 SIVAL(p
,usri11_last_logoff
,0); /* last logoff */
3319 SSVALS(p
,usri11_bad_pw_count
,-1); /* bad pw counts */
3320 SSVALS(p
,usri11_num_logons
,-1); /* num logons */
3321 SIVAL(p
,usri11_logon_server
,PTR_DIFF(p2
,p
)); /* logon server */
3322 pstrcpy(p2
,"\\\\*");
3323 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3327 SSVAL(p
,usri11_country_code
,0); /* country code */
3329 SIVAL(p
,usri11_workstations
,PTR_DIFF(p2
,p
)); /* workstations */
3331 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3336 SIVALS(p
,usri11_max_storage
,-1); /* max storage */
3337 SSVAL(p
,usri11_units_per_week
,168); /* units per week */
3338 SIVAL(p
,usri11_logon_hours
,PTR_DIFF(p2
,p
)); /* logon hours */
3340 /* a simple way to get logon hours at all times. */
3342 SCVAL(p2
,21,0); /* fix zero termination */
3343 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3348 SSVAL(p
,usri11_code_page
,0); /* code page */
3351 if (uLevel
== 1 || uLevel
== 2) {
3352 memset(p
+22,' ',16); /* password */
3353 SIVALS(p
,38,-1); /* password age */
3355 conn
->admin_user
?USER_PRIV_ADMIN
:USER_PRIV_USER
);
3356 SIVAL(p
,44,PTR_DIFF(p2
,*rdata
)); /* home dir */
3357 pstrcpy(p2
, vuser
&& vuser
->homedir
? vuser
->homedir
: "");
3358 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3362 SIVAL(p
,48,PTR_DIFF(p2
,*rdata
)); /* comment */
3364 SSVAL(p
,52,0); /* flags */
3365 SIVAL(p
,54,PTR_DIFF(p2
,*rdata
)); /* script_path */
3366 pstrcpy(p2
,vuser
&& vuser
->logon_script
? vuser
->logon_script
: "");
3367 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3372 SIVAL(p
,60,0); /* auth_flags */
3373 SIVAL(p
,64,PTR_DIFF(p2
,*rdata
)); /* full_name */
3374 pstrcpy(p2
,((vuser
!= NULL
) ? vuser
->user
.full_name
: UserName
));
3375 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3379 SIVAL(p
,68,0); /* urs_comment */
3380 SIVAL(p
,72,PTR_DIFF(p2
,*rdata
)); /* parms */
3382 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3386 SIVAL(p
,76,0); /* workstations */
3387 SIVAL(p
,80,0); /* last_logon */
3388 SIVAL(p
,84,0); /* last_logoff */
3389 SIVALS(p
,88,-1); /* acct_expires */
3390 SIVALS(p
,92,-1); /* max_storage */
3391 SSVAL(p
,96,168); /* units_per_week */
3392 SIVAL(p
,98,PTR_DIFF(p2
,*rdata
)); /* logon_hours */
3395 SSVALS(p
,102,-1); /* bad_pw_count */
3396 SSVALS(p
,104,-1); /* num_logons */
3397 SIVAL(p
,106,PTR_DIFF(p2
,*rdata
)); /* logon_server */
3400 pstrcpy(tmp
, "\\\\%L");
3401 standard_sub_basic("", "", tmp
, sizeof(tmp
));
3404 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3408 SSVAL(p
,110,49); /* country_code */
3409 SSVAL(p
,112,860); /* code page */
3413 *rdata_len
= PTR_DIFF(p2
,*rdata
);
3415 SSVAL(*rparam
,4,*rdata_len
); /* is this right?? */
3420 static BOOL
api_WWkstaUserLogon(connection_struct
*conn
,uint16 vuid
,
3421 char *param
, int tpscnt
,
3422 char *data
, int tdscnt
,
3423 int mdrcnt
,int mprcnt
,
3424 char **rdata
,char **rparam
,
3425 int *rdata_len
,int *rparam_len
)
3427 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3428 char *str2
= skip_string(param
,tpscnt
,str1
);
3429 char *p
= skip_string(param
,tpscnt
,str2
);
3431 struct pack_desc desc
;
3433 /* With share level security vuid will always be zero.
3434 Don't depend on vuser being non-null !!. JRA */
3435 user_struct
*vuser
= get_valid_user_struct(vuid
);
3437 if (!str1
|| !str2
|| !p
) {
3442 DEBUG(3,(" Username of UID %d is %s\n", (int)vuser
->uid
,
3443 vuser
->user
.unix_name
));
3446 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3447 name
= get_safe_str_ptr(param
,tpscnt
,p
,2);
3452 memset((char *)&desc
,'\0',sizeof(desc
));
3454 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel
,name
));
3456 /* check it's a supported varient */
3457 if (strcmp(str1
,"OOWb54WrLh") != 0) {
3460 if (uLevel
!= 1 || strcmp(str2
,"WB21BWDWWDDDDDDDzzzD") != 0) {
3464 *rdata
= SMB_REALLOC_LIMIT(*rdata
,mdrcnt
);
3471 desc
.buflen
= mdrcnt
;
3472 desc
.subformat
= NULL
;
3475 if (init_package(&desc
,1,0)) {
3476 PACKI(&desc
,"W",0); /* code */
3477 PACKS(&desc
,"B21",name
); /* eff. name */
3478 PACKS(&desc
,"B",""); /* pad */
3479 PACKI(&desc
,"W", conn
->admin_user
?USER_PRIV_ADMIN
:USER_PRIV_USER
);
3480 PACKI(&desc
,"D",0); /* auth flags XXX */
3481 PACKI(&desc
,"W",0); /* num logons */
3482 PACKI(&desc
,"W",0); /* bad pw count */
3483 PACKI(&desc
,"D",0); /* last logon */
3484 PACKI(&desc
,"D",-1); /* last logoff */
3485 PACKI(&desc
,"D",-1); /* logoff time */
3486 PACKI(&desc
,"D",-1); /* kickoff time */
3487 PACKI(&desc
,"D",0); /* password age */
3488 PACKI(&desc
,"D",0); /* password can change */
3489 PACKI(&desc
,"D",-1); /* password must change */
3493 fstrcpy(mypath
,"\\\\");
3494 fstrcat(mypath
,get_local_machine_name());
3496 PACKS(&desc
,"z",mypath
); /* computer */
3499 PACKS(&desc
,"z",lp_workgroup());/* domain */
3500 PACKS(&desc
,"z", vuser
&& vuser
->logon_script
? vuser
->logon_script
:""); /* script path */
3501 PACKI(&desc
,"D",0x00000000); /* reserved */
3504 *rdata_len
= desc
.usedlen
;
3506 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
3510 SSVALS(*rparam
,0,desc
.errcode
);
3512 SSVAL(*rparam
,4,desc
.neededlen
);
3514 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc
.errcode
));
3519 /****************************************************************************
3520 api_WAccessGetUserPerms
3521 ****************************************************************************/
3523 static BOOL
api_WAccessGetUserPerms(connection_struct
*conn
,uint16 vuid
,
3524 char *param
, int tpscnt
,
3525 char *data
, int tdscnt
,
3526 int mdrcnt
,int mprcnt
,
3527 char **rdata
,char **rparam
,
3528 int *rdata_len
,int *rparam_len
)
3530 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3531 char *str2
= skip_string(param
,tpscnt
,str1
);
3532 char *user
= skip_string(param
,tpscnt
,str2
);
3533 char *resource
= skip_string(param
,tpscnt
,user
);
3535 if (!str1
|| !str2
|| !user
|| !resource
) {
3539 if (skip_string(param
,tpscnt
,resource
) == NULL
) {
3542 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user
,resource
));
3544 /* check it's a supported varient */
3545 if (strcmp(str1
,"zzh") != 0) {
3548 if (strcmp(str2
,"") != 0) {
3553 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
3557 SSVALS(*rparam
,0,0); /* errorcode */
3558 SSVAL(*rparam
,2,0); /* converter word */
3559 SSVAL(*rparam
,4,0x7f); /* permission flags */
3564 /****************************************************************************
3565 api_WPrintJobEnumerate
3566 ****************************************************************************/
3568 static BOOL
api_WPrintJobGetInfo(connection_struct
*conn
, uint16 vuid
,
3569 char *param
, int tpscnt
,
3570 char *data
, int tdscnt
,
3571 int mdrcnt
,int mprcnt
,
3572 char **rdata
,char **rparam
,
3573 int *rdata_len
,int *rparam_len
)
3575 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3576 char *str2
= skip_string(param
,tpscnt
,str1
);
3577 char *p
= skip_string(param
,tpscnt
,str2
);
3584 struct pack_desc desc
;
3585 print_queue_struct
*queue
=NULL
;
3586 print_status_struct status
;
3589 if (!str1
|| !str2
|| !p
) {
3593 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,2,-1);
3595 memset((char *)&desc
,'\0',sizeof(desc
));
3596 memset((char *)&status
,'\0',sizeof(status
));
3598 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel
,SVAL(p
,0)));
3600 /* check it's a supported varient */
3601 if (strcmp(str1
,"WWrLh") != 0) {
3604 if (!check_printjob_info(&desc
,uLevel
,str2
)) {
3608 if(!rap_to_pjobid(SVAL(p
,0), sharename
, &jobid
)) {
3612 snum
= lp_servicenumber( sharename
);
3613 if (snum
< 0 || !VALID_SNUM(snum
)) {
3617 count
= print_queue_status(snum
,&queue
,&status
);
3618 for (i
= 0; i
< count
; i
++) {
3619 if (queue
[i
].job
== jobid
) {
3625 *rdata
= SMB_REALLOC_LIMIT(*rdata
,mdrcnt
);
3630 desc
.buflen
= mdrcnt
;
3633 * Don't return data but need to get correct length
3634 * init_package will return wrong size if buflen=0
3636 desc
.buflen
= getlen(desc
.format
);
3637 desc
.base
= tmpdata
= (char *)SMB_MALLOC( desc
.buflen
);
3640 if (init_package(&desc
,1,0)) {
3642 fill_printjob_info(conn
,snum
,uLevel
,&desc
,&queue
[i
],i
);
3643 *rdata_len
= desc
.usedlen
;
3645 desc
.errcode
= NERR_JobNotFound
;
3651 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
3655 SSVALS(*rparam
,0,desc
.errcode
);
3657 SSVAL(*rparam
,4,desc
.neededlen
);
3662 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc
.errcode
));
3667 static BOOL
api_WPrintJobEnumerate(connection_struct
*conn
, uint16 vuid
,
3668 char *param
, int tpscnt
,
3669 char *data
, int tdscnt
,
3670 int mdrcnt
,int mprcnt
,
3671 char **rdata
,char **rparam
,
3672 int *rdata_len
,int *rparam_len
)
3674 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3675 char *str2
= skip_string(param
,tpscnt
,str1
);
3676 char *p
= skip_string(param
,tpscnt
,str2
);
3682 struct pack_desc desc
;
3683 print_queue_struct
*queue
=NULL
;
3684 print_status_struct status
;
3686 if (!str1
|| !str2
|| !p
) {
3690 memset((char *)&desc
,'\0',sizeof(desc
));
3691 memset((char *)&status
,'\0',sizeof(status
));
3693 p
= skip_string(param
,tpscnt
,p
);
3697 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3699 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel
,name
));
3701 /* check it's a supported variant */
3702 if (strcmp(str1
,"zWrLeh") != 0) {
3707 return False
; /* defined only for uLevel 0,1,2 */
3710 if (!check_printjob_info(&desc
,uLevel
,str2
)) {
3714 snum
= find_service(name
);
3715 if ( !(lp_snum_ok(snum
) && lp_print_ok(snum
)) ) {
3719 count
= print_queue_status(snum
,&queue
,&status
);
3721 *rdata
= SMB_REALLOC_LIMIT(*rdata
,mdrcnt
);
3727 desc
.buflen
= mdrcnt
;
3729 if (init_package(&desc
,count
,0)) {
3731 for (i
= 0; i
< count
; i
++) {
3732 fill_printjob_info(conn
,snum
,uLevel
,&desc
,&queue
[i
],i
);
3733 if (desc
.errcode
== NERR_Success
) {
3739 *rdata_len
= desc
.usedlen
;
3742 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
3746 SSVALS(*rparam
,0,desc
.errcode
);
3748 SSVAL(*rparam
,4,succnt
);
3749 SSVAL(*rparam
,6,count
);
3753 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc
.errcode
));
3758 static int check_printdest_info(struct pack_desc
* desc
,
3759 int uLevel
, char* id
)
3761 desc
->subformat
= NULL
;
3764 desc
->format
= "B9";
3767 desc
->format
= "B9B21WWzW";
3773 desc
->format
= "zzzWWzzzWW";
3776 DEBUG(0,("check_printdest_info: invalid level %d\n",
3780 if (id
== NULL
|| strcmp(desc
->format
,id
) != 0) {
3781 DEBUG(0,("check_printdest_info: invalid string %s\n",
3782 id
? id
: "<NULL>" ));
3788 static void fill_printdest_info(connection_struct
*conn
, int snum
, int uLevel
,
3789 struct pack_desc
* desc
)
3793 strncpy(buf
,SERVICE(snum
),sizeof(buf
)-1);
3794 buf
[sizeof(buf
)-1] = 0;
3798 PACKS(desc
,"B9",buf
); /* szName */
3800 PACKS(desc
,"B21",""); /* szUserName */
3801 PACKI(desc
,"W",0); /* uJobId */
3802 PACKI(desc
,"W",0); /* fsStatus */
3803 PACKS(desc
,"z",""); /* pszStatus */
3804 PACKI(desc
,"W",0); /* time */
3808 if (uLevel
== 2 || uLevel
== 3) {
3809 PACKS(desc
,"z",buf
); /* pszPrinterName */
3811 PACKS(desc
,"z",""); /* pszUserName */
3812 PACKS(desc
,"z",""); /* pszLogAddr */
3813 PACKI(desc
,"W",0); /* uJobId */
3814 PACKI(desc
,"W",0); /* fsStatus */
3815 PACKS(desc
,"z",""); /* pszStatus */
3816 PACKS(desc
,"z",""); /* pszComment */
3817 PACKS(desc
,"z","NULL"); /* pszDrivers */
3818 PACKI(desc
,"W",0); /* time */
3819 PACKI(desc
,"W",0); /* pad1 */
3824 static BOOL
api_WPrintDestGetInfo(connection_struct
*conn
, uint16 vuid
,
3825 char *param
, int tpscnt
,
3826 char *data
, int tdscnt
,
3827 int mdrcnt
,int mprcnt
,
3828 char **rdata
,char **rparam
,
3829 int *rdata_len
,int *rparam_len
)
3831 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3832 char *str2
= skip_string(param
,tpscnt
,str1
);
3833 char *p
= skip_string(param
,tpscnt
,str2
);
3834 char* PrinterName
= p
;
3836 struct pack_desc desc
;
3840 if (!str1
|| !str2
|| !p
) {
3844 memset((char *)&desc
,'\0',sizeof(desc
));
3846 p
= skip_string(param
,tpscnt
,p
);
3850 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3852 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel
,PrinterName
));
3854 /* check it's a supported varient */
3855 if (strcmp(str1
,"zWrLh") != 0) {
3858 if (!check_printdest_info(&desc
,uLevel
,str2
)) {
3862 snum
= find_service(PrinterName
);
3863 if ( !(lp_snum_ok(snum
) && lp_print_ok(snum
)) ) {
3865 desc
.errcode
= NERR_DestNotFound
;
3869 *rdata
= SMB_REALLOC_LIMIT(*rdata
,mdrcnt
);
3874 desc
.buflen
= mdrcnt
;
3877 * Don't return data but need to get correct length
3878 * init_package will return wrong size if buflen=0
3880 desc
.buflen
= getlen(desc
.format
);
3881 desc
.base
= tmpdata
= (char *)SMB_MALLOC( desc
.buflen
);
3883 if (init_package(&desc
,1,0)) {
3884 fill_printdest_info(conn
,snum
,uLevel
,&desc
);
3886 *rdata_len
= desc
.usedlen
;
3890 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
3894 SSVALS(*rparam
,0,desc
.errcode
);
3896 SSVAL(*rparam
,4,desc
.neededlen
);
3898 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc
.errcode
));
3904 static BOOL
api_WPrintDestEnum(connection_struct
*conn
, uint16 vuid
,
3905 char *param
, int tpscnt
,
3906 char *data
, int tdscnt
,
3907 int mdrcnt
,int mprcnt
,
3908 char **rdata
,char **rparam
,
3909 int *rdata_len
,int *rparam_len
)
3911 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3912 char *str2
= skip_string(param
,tpscnt
,str1
);
3913 char *p
= skip_string(param
,tpscnt
,str2
);
3917 struct pack_desc desc
;
3918 int services
= lp_numservices();
3920 if (!str1
|| !str2
|| !p
) {
3924 memset((char *)&desc
,'\0',sizeof(desc
));
3926 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3928 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel
));
3930 /* check it's a supported varient */
3931 if (strcmp(str1
,"WrLeh") != 0) {
3934 if (!check_printdest_info(&desc
,uLevel
,str2
)) {
3939 for (i
= 0; i
< services
; i
++) {
3940 if (lp_snum_ok(i
) && lp_print_ok(i
) && lp_browseable(i
)) {
3946 *rdata
= SMB_REALLOC_LIMIT(*rdata
,mdrcnt
);
3953 desc
.buflen
= mdrcnt
;
3954 if (init_package(&desc
,queuecnt
,0)) {
3957 for (i
= 0; i
< services
; i
++) {
3958 if (lp_snum_ok(i
) && lp_print_ok(i
) && lp_browseable(i
)) {
3959 fill_printdest_info(conn
,i
,uLevel
,&desc
);
3961 if (desc
.errcode
== NERR_Success
) {
3968 *rdata_len
= desc
.usedlen
;
3971 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
3975 SSVALS(*rparam
,0,desc
.errcode
);
3977 SSVAL(*rparam
,4,succnt
);
3978 SSVAL(*rparam
,6,queuecnt
);
3980 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc
.errcode
));
3985 static BOOL
api_WPrintDriverEnum(connection_struct
*conn
, uint16 vuid
,
3986 char *param
, int tpscnt
,
3987 char *data
, int tdscnt
,
3988 int mdrcnt
,int mprcnt
,
3989 char **rdata
,char **rparam
,
3990 int *rdata_len
,int *rparam_len
)
3992 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3993 char *str2
= skip_string(param
,tpscnt
,str1
);
3994 char *p
= skip_string(param
,tpscnt
,str2
);
3997 struct pack_desc desc
;
3999 if (!str1
|| !str2
|| !p
) {
4003 memset((char *)&desc
,'\0',sizeof(desc
));
4005 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4007 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel
));
4009 /* check it's a supported varient */
4010 if (strcmp(str1
,"WrLeh") != 0) {
4013 if (uLevel
!= 0 || strcmp(str2
,"B41") != 0) {
4018 *rdata
= SMB_REALLOC_LIMIT(*rdata
,mdrcnt
);
4024 desc
.buflen
= mdrcnt
;
4025 if (init_package(&desc
,1,0)) {
4026 PACKS(&desc
,"B41","NULL");
4029 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
4031 *rdata_len
= desc
.usedlen
;
4034 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
4038 SSVALS(*rparam
,0,desc
.errcode
);
4040 SSVAL(*rparam
,4,succnt
);
4043 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc
.errcode
));
4048 static BOOL
api_WPrintQProcEnum(connection_struct
*conn
, uint16 vuid
,
4049 char *param
, int tpscnt
,
4050 char *data
, int tdscnt
,
4051 int mdrcnt
,int mprcnt
,
4052 char **rdata
,char **rparam
,
4053 int *rdata_len
,int *rparam_len
)
4055 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4056 char *str2
= skip_string(param
,tpscnt
,str1
);
4057 char *p
= skip_string(param
,tpscnt
,str2
);
4060 struct pack_desc desc
;
4062 if (!str1
|| !str2
|| !p
) {
4065 memset((char *)&desc
,'\0',sizeof(desc
));
4067 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4069 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel
));
4071 /* check it's a supported varient */
4072 if (strcmp(str1
,"WrLeh") != 0) {
4075 if (uLevel
!= 0 || strcmp(str2
,"B13") != 0) {
4080 *rdata
= SMB_REALLOC_LIMIT(*rdata
,mdrcnt
);
4086 desc
.buflen
= mdrcnt
;
4088 if (init_package(&desc
,1,0)) {
4089 PACKS(&desc
,"B13","lpd");
4092 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
4094 *rdata_len
= desc
.usedlen
;
4097 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
4101 SSVALS(*rparam
,0,desc
.errcode
);
4103 SSVAL(*rparam
,4,succnt
);
4106 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc
.errcode
));
4111 static BOOL
api_WPrintPortEnum(connection_struct
*conn
, uint16 vuid
,
4112 char *param
, int tpscnt
,
4113 char *data
, int tdscnt
,
4114 int mdrcnt
,int mprcnt
,
4115 char **rdata
,char **rparam
,
4116 int *rdata_len
,int *rparam_len
)
4118 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4119 char *str2
= skip_string(param
,tpscnt
,str1
);
4120 char *p
= skip_string(param
,tpscnt
,str2
);
4123 struct pack_desc desc
;
4125 if (!str1
|| !str2
|| !p
) {
4129 memset((char *)&desc
,'\0',sizeof(desc
));
4131 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4133 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel
));
4135 /* check it's a supported varient */
4136 if (strcmp(str1
,"WrLeh") != 0) {
4139 if (uLevel
!= 0 || strcmp(str2
,"B9") != 0) {
4144 *rdata
= SMB_REALLOC_LIMIT(*rdata
,mdrcnt
);
4149 memset((char *)&desc
,'\0',sizeof(desc
));
4151 desc
.buflen
= mdrcnt
;
4153 if (init_package(&desc
,1,0)) {
4154 PACKS(&desc
,"B13","lp0");
4157 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
4159 *rdata_len
= desc
.usedlen
;
4162 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
4166 SSVALS(*rparam
,0,desc
.errcode
);
4168 SSVAL(*rparam
,4,succnt
);
4171 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc
.errcode
));
4176 /****************************************************************************
4178 ****************************************************************************/
4180 static BOOL
api_RNetSessionEnum(connection_struct
*conn
, uint16 vuid
,
4181 char *param
, int tpscnt
,
4182 char *data
, int tdscnt
,
4183 int mdrcnt
,int mprcnt
,
4184 char **rdata
,char **rparam
,
4185 int *rdata_len
,int *rparam_len
)
4188 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4189 char *str2
= skip_string(param
,tpscnt
,str1
);
4190 char *p
= skip_string(param
,tpscnt
,str2
);
4192 struct pack_desc desc
;
4193 struct sessionid
*session_list
;
4194 int i
, num_sessions
;
4196 if (!str1
|| !str2
|| !p
) {
4200 memset((char *)&desc
,'\0',sizeof(desc
));
4202 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4204 DEBUG(3,("RNetSessionEnum uLevel=%d\n",uLevel
));
4205 DEBUG(7,("RNetSessionEnum req string=%s\n",str1
));
4206 DEBUG(7,("RNetSessionEnum ret string=%s\n",str2
));
4208 /* check it's a supported varient */
4209 if (strcmp(str1
,RAP_NetSessionEnum_REQ
) != 0) {
4212 if (uLevel
!= 2 || strcmp(str2
,RAP_SESSION_INFO_L2
) != 0) {
4216 num_sessions
= list_sessions(tmp_talloc_ctx(), &session_list
);
4219 *rdata
= SMB_REALLOC_LIMIT(*rdata
,mdrcnt
);
4224 memset((char *)&desc
,'\0',sizeof(desc
));
4226 desc
.buflen
= mdrcnt
;
4228 if (!init_package(&desc
,num_sessions
,0)) {
4232 for(i
=0; i
<num_sessions
; i
++) {
4233 PACKS(&desc
, "z", session_list
[i
].remote_machine
);
4234 PACKS(&desc
, "z", session_list
[i
].username
);
4235 PACKI(&desc
, "W", 1); /* num conns */
4236 PACKI(&desc
, "W", 0); /* num opens */
4237 PACKI(&desc
, "W", 1); /* num users */
4238 PACKI(&desc
, "D", 0); /* session time */
4239 PACKI(&desc
, "D", 0); /* idle time */
4240 PACKI(&desc
, "D", 0); /* flags */
4241 PACKS(&desc
, "z", "Unknown Client"); /* client type string */
4244 *rdata_len
= desc
.usedlen
;
4247 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
4251 SSVALS(*rparam
,0,desc
.errcode
);
4252 SSVAL(*rparam
,2,0); /* converter */
4253 SSVAL(*rparam
,4,num_sessions
); /* count */
4255 DEBUG(4,("RNetSessionEnum: errorcode %d\n",desc
.errcode
));
4261 /****************************************************************************
4262 The buffer was too small.
4263 ****************************************************************************/
4265 static BOOL
api_TooSmall(connection_struct
*conn
,uint16 vuid
, char *param
, char *data
,
4266 int mdrcnt
, int mprcnt
,
4267 char **rdata
, char **rparam
,
4268 int *rdata_len
, int *rparam_len
)
4270 *rparam_len
= MIN(*rparam_len
,mprcnt
);
4271 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
4278 SSVAL(*rparam
,0,NERR_BufTooSmall
);
4280 DEBUG(3,("Supplied buffer too small in API command\n"));
4285 /****************************************************************************
4286 The request is not supported.
4287 ****************************************************************************/
4289 static BOOL
api_Unsupported(connection_struct
*conn
, uint16 vuid
,
4290 char *param
, int tpscnt
,
4291 char *data
, int tdscnt
,
4292 int mdrcnt
, int mprcnt
,
4293 char **rdata
, char **rparam
,
4294 int *rdata_len
, int *rparam_len
)
4297 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
4304 SSVAL(*rparam
,0,NERR_notsupported
);
4305 SSVAL(*rparam
,2,0); /* converter word */
4307 DEBUG(3,("Unsupported API command\n"));
4312 static const struct {
4315 BOOL (*fn
)(connection_struct
*, uint16
,
4318 int,int,char **,char **,int *,int *);
4319 BOOL auth_user
; /* Deny anonymous access? */
4320 } api_commands
[] = {
4321 {"RNetShareEnum", RAP_WshareEnum
, api_RNetShareEnum
, True
},
4322 {"RNetShareGetInfo", RAP_WshareGetInfo
, api_RNetShareGetInfo
},
4323 {"RNetShareAdd", RAP_WshareAdd
, api_RNetShareAdd
},
4324 {"RNetSessionEnum", RAP_WsessionEnum
, api_RNetSessionEnum
, True
},
4325 {"RNetServerGetInfo", RAP_WserverGetInfo
, api_RNetServerGetInfo
},
4326 {"RNetGroupEnum", RAP_WGroupEnum
, api_RNetGroupEnum
, True
},
4327 {"RNetGroupGetUsers", RAP_WGroupGetUsers
, api_RNetGroupGetUsers
, True
},
4328 {"RNetUserEnum", RAP_WUserEnum
, api_RNetUserEnum
, True
},
4329 {"RNetUserGetInfo", RAP_WUserGetInfo
, api_RNetUserGetInfo
},
4330 {"NetUserGetGroups", RAP_WUserGetGroups
, api_NetUserGetGroups
},
4331 {"NetWkstaGetInfo", RAP_WWkstaGetInfo
, api_NetWkstaGetInfo
},
4332 {"DosPrintQEnum", RAP_WPrintQEnum
, api_DosPrintQEnum
, True
},
4333 {"DosPrintQGetInfo", RAP_WPrintQGetInfo
, api_DosPrintQGetInfo
},
4334 {"WPrintQueuePause", RAP_WPrintQPause
, api_WPrintQueueCtrl
},
4335 {"WPrintQueueResume", RAP_WPrintQContinue
, api_WPrintQueueCtrl
},
4336 {"WPrintJobEnumerate",RAP_WPrintJobEnum
, api_WPrintJobEnumerate
},
4337 {"WPrintJobGetInfo", RAP_WPrintJobGetInfo
, api_WPrintJobGetInfo
},
4338 {"RDosPrintJobDel", RAP_WPrintJobDel
, api_RDosPrintJobDel
},
4339 {"RDosPrintJobPause", RAP_WPrintJobPause
, api_RDosPrintJobDel
},
4340 {"RDosPrintJobResume",RAP_WPrintJobContinue
, api_RDosPrintJobDel
},
4341 {"WPrintDestEnum", RAP_WPrintDestEnum
, api_WPrintDestEnum
},
4342 {"WPrintDestGetInfo", RAP_WPrintDestGetInfo
, api_WPrintDestGetInfo
},
4343 {"NetRemoteTOD", RAP_NetRemoteTOD
, api_NetRemoteTOD
},
4344 {"WPrintQueuePurge", RAP_WPrintQPurge
, api_WPrintQueueCtrl
},
4345 {"NetServerEnum", RAP_NetServerEnum2
, api_RNetServerEnum
}, /* anon OK */
4346 {"WAccessGetUserPerms",RAP_WAccessGetUserPerms
,api_WAccessGetUserPerms
},
4347 {"SetUserPassword", RAP_WUserPasswordSet2
, api_SetUserPassword
},
4348 {"WWkstaUserLogon", RAP_WWkstaUserLogon
, api_WWkstaUserLogon
},
4349 {"PrintJobInfo", RAP_WPrintJobSetInfo
, api_PrintJobInfo
},
4350 {"WPrintDriverEnum", RAP_WPrintDriverEnum
, api_WPrintDriverEnum
},
4351 {"WPrintQProcEnum", RAP_WPrintQProcessorEnum
,api_WPrintQProcEnum
},
4352 {"WPrintPortEnum", RAP_WPrintPortEnum
, api_WPrintPortEnum
},
4353 {"SamOEMChangePassword",RAP_SamOEMChgPasswordUser2_P
,api_SamOEMChangePassword
}, /* anon OK */
4354 {NULL
, -1, api_Unsupported
}
4355 /* The following RAP calls are not implemented by Samba:
4357 RAP_WFileEnum2 - anon not OK
4362 /****************************************************************************
4363 Handle remote api calls.
4364 ****************************************************************************/
4366 int api_reply(connection_struct
*conn
,
4379 char *rparam
= NULL
;
4380 const char *name1
= NULL
;
4381 const char *name2
= NULL
;
4388 DEBUG(0,("ERROR: NULL params in api_reply()\n"));
4395 api_command
= SVAL(params
,0);
4396 /* Is there a string at position params+2 ? */
4397 if (skip_string(params
,tpscnt
,params
+2)) {
4402 name2
= skip_string(params
,tpscnt
,params
+2);
4407 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
4411 tdscnt
,tpscnt
,mdrcnt
,mprcnt
));
4413 for (i
=0;api_commands
[i
].name
;i
++) {
4414 if (api_commands
[i
].id
== api_command
&& api_commands
[i
].fn
) {
4415 DEBUG(3,("Doing %s\n",api_commands
[i
].name
));
4420 /* Check whether this api call can be done anonymously */
4422 if (api_commands
[i
].auth_user
&& lp_restrict_anonymous()) {
4423 user_struct
*user
= get_valid_user_struct(vuid
);
4425 if (!user
|| user
->guest
) {
4426 return ERROR_NT(NT_STATUS_ACCESS_DENIED
);
4430 rdata
= (char *)SMB_MALLOC(1024);
4432 memset(rdata
,'\0',1024);
4435 rparam
= (char *)SMB_MALLOC(1024);
4437 memset(rparam
,'\0',1024);
4440 if(!rdata
|| !rparam
) {
4441 DEBUG(0,("api_reply: malloc fail !\n"));
4447 reply
= api_commands
[i
].fn(conn
,
4449 params
,tpscnt
, /* params + length */
4450 data
,tdscnt
, /* data + length */
4452 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
4455 if (rdata_len
> mdrcnt
|| rparam_len
> mprcnt
) {
4456 reply
= api_TooSmall(conn
,vuid
,params
,data
,mdrcnt
,mprcnt
,
4457 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
4460 /* if we get False back then it's actually unsupported */
4462 reply
= api_Unsupported(conn
,vuid
,params
,tpscnt
,data
,tdscnt
,mdrcnt
,mprcnt
,
4463 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
4466 /* If api_Unsupported returns false we can't return anything. */
4468 send_trans_reply(inbuf
,