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
;
37 #define NERR_Success 0
38 #define NERR_badpass 86
39 #define NERR_notsupported 50
41 #define NERR_BASE (2100)
42 #define NERR_BufTooSmall (NERR_BASE+23)
43 #define NERR_JobNotFound (NERR_BASE+51)
44 #define NERR_DestNotFound (NERR_BASE+52)
46 #define ACCESS_READ 0x01
47 #define ACCESS_WRITE 0x02
48 #define ACCESS_CREATE 0x04
50 #define SHPWLEN 8 /* share password length */
52 /* Limit size of ipc replies */
54 static char *smb_realloc_limit(void *ptr
, size_t size
)
58 size
= MAX((size
),4*1024);
59 val
= (char *)SMB_REALLOC(ptr
,size
);
61 memset(val
,'\0',size
);
66 static bool api_Unsupported(connection_struct
*conn
, uint16 vuid
,
67 char *param
, int tpscnt
,
68 char *data
, int tdscnt
,
69 int mdrcnt
, int mprcnt
,
70 char **rdata
, char **rparam
,
71 int *rdata_len
, int *rparam_len
);
73 static bool api_TooSmall(connection_struct
*conn
, uint16 vuid
, char *param
, char *data
,
74 int mdrcnt
, int mprcnt
,
75 char **rdata
, char **rparam
,
76 int *rdata_len
, int *rparam_len
);
79 static int CopyExpanded(connection_struct
*conn
,
80 int snum
, char **dst
, char *src
, int *p_space_remaining
)
82 TALLOC_CTX
*ctx
= talloc_tos();
86 if (!src
|| !dst
|| !p_space_remaining
|| !(*dst
) ||
87 *p_space_remaining
<= 0) {
91 buf
= talloc_strdup(ctx
, src
);
93 *p_space_remaining
= 0;
96 buf
= talloc_string_sub(ctx
, buf
,"%S",lp_servicename(snum
));
98 *p_space_remaining
= 0;
101 buf
= talloc_sub_advanced(ctx
,
102 lp_servicename(SNUM(conn
)),
103 conn
->server_info
->unix_name
,
105 conn
->server_info
->gid
,
106 conn
->server_info
->sanitized_username
,
107 pdb_get_domain(conn
->server_info
->sam_account
),
110 *p_space_remaining
= 0;
113 l
= push_ascii(*dst
,buf
,*p_space_remaining
, STR_TERMINATE
);
118 (*p_space_remaining
) -= l
;
122 static int CopyAndAdvance(char **dst
, char *src
, int *n
)
125 if (!src
|| !dst
|| !n
|| !(*dst
)) {
128 l
= push_ascii(*dst
,src
,*n
, STR_TERMINATE
);
137 static int StrlenExpanded(connection_struct
*conn
, int snum
, char *s
)
139 TALLOC_CTX
*ctx
= talloc_tos();
144 buf
= talloc_strdup(ctx
,s
);
148 buf
= talloc_string_sub(ctx
,buf
,"%S",lp_servicename(snum
));
152 buf
= talloc_sub_advanced(ctx
,
153 lp_servicename(SNUM(conn
)),
154 conn
->server_info
->unix_name
,
156 conn
->server_info
->gid
,
157 conn
->server_info
->sanitized_username
,
158 pdb_get_domain(conn
->server_info
->sam_account
),
163 return strlen(buf
) + 1;
166 static char *Expand(connection_struct
*conn
, int snum
, char *s
)
168 TALLOC_CTX
*ctx
= talloc_tos();
174 buf
= talloc_strdup(ctx
,s
);
178 buf
= talloc_string_sub(ctx
,buf
,"%S",lp_servicename(snum
));
182 return talloc_sub_advanced(ctx
,
183 lp_servicename(SNUM(conn
)),
184 conn
->server_info
->unix_name
,
186 conn
->server_info
->gid
,
187 conn
->server_info
->sanitized_username
,
188 pdb_get_domain(conn
->server_info
->sam_account
),
192 /*******************************************************************
193 Check a API string for validity when we only need to check the prefix.
194 ******************************************************************/
196 static bool prefix_ok(const char *str
, const char *prefix
)
198 return(strncmp(str
,prefix
,strlen(prefix
)) == 0);
202 const char *format
; /* formatstring for structure */
203 const char *subformat
; /* subformat for structure */
204 char *base
; /* baseaddress of buffer */
205 int buflen
; /* remaining size for fixed part; on init: length of base */
206 int subcount
; /* count of substructures */
207 char *structbuf
; /* pointer into buffer for remaining fixed part */
208 int stringlen
; /* remaining size for variable part */
209 char *stringbuf
; /* pointer into buffer for remaining variable part */
210 int neededlen
; /* total needed size */
211 int usedlen
; /* total used size (usedlen <= neededlen and usedlen <= buflen) */
212 const char *curpos
; /* current position; pointer into format or subformat */
216 static int get_counter(const char **p
)
222 if (!isdigit((int)**p
)) {
228 n
= 10 * n
+ (i
- '0');
236 static int getlen(const char *p
)
245 case 'W': /* word (2 byte) */
248 case 'K': /* status word? (2 byte) */
251 case 'N': /* count of substructures (word) at end */
254 case 'D': /* double word (4 byte) */
255 case 'z': /* offset to zero terminated string (4 byte) */
256 case 'l': /* offset to user data (4 byte) */
259 case 'b': /* offset to data (with counter) (4 byte) */
263 case 'B': /* byte (with optional counter) */
264 n
+= get_counter(&p
);
271 static bool init_package(struct pack_desc
*p
, int count
, int subcount
)
276 if (!p
->format
|| !p
->base
) {
280 i
= count
* getlen(p
->format
);
282 i
+= subcount
* getlen(p
->subformat
);
284 p
->structbuf
= p
->base
;
288 p
->curpos
= p
->format
;
294 * This is the old error code we used. Aparently
295 * WinNT/2k systems return ERRbuftoosmall (2123) and
296 * OS/2 needs this. I'm leaving this here so we can revert
299 p
->errcode
= ERRmoredata
;
301 p
->errcode
= ERRbuftoosmall
;
304 p
->errcode
= NERR_Success
;
308 p
->stringbuf
= p
->base
+ i
;
310 return (p
->errcode
== NERR_Success
);
313 static int package(struct pack_desc
*p
, ...)
316 int needed
=0, stringneeded
;
317 const char *str
=NULL
;
318 int is_string
=0, stringused
;
325 p
->curpos
= p
->format
;
327 p
->curpos
= p
->subformat
;
332 str
= va_arg(args
,char*);
333 SMB_ASSERT(strncmp(str
,p
->curpos
,strlen(str
)) == 0);
342 switch( *p
->curpos
++ ) {
343 case 'W': /* word (2 byte) */
345 temp
= va_arg(args
,int);
346 if (p
->buflen
>= needed
) {
347 SSVAL(p
->structbuf
,0,temp
);
350 case 'K': /* status word? (2 byte) */
352 temp
= va_arg(args
,int);
353 if (p
->buflen
>= needed
) {
354 SSVAL(p
->structbuf
,0,temp
);
357 case 'N': /* count of substructures (word) at end */
359 p
->subcount
= va_arg(args
,int);
360 if (p
->buflen
>= needed
) {
361 SSVAL(p
->structbuf
,0,p
->subcount
);
364 case 'D': /* double word (4 byte) */
366 temp
= va_arg(args
,int);
367 if (p
->buflen
>= needed
) {
368 SIVAL(p
->structbuf
,0,temp
);
371 case 'B': /* byte (with optional counter) */
372 needed
= get_counter(&p
->curpos
);
374 char *s
= va_arg(args
,char*);
375 if (p
->buflen
>= needed
) {
376 StrnCpy(p
->structbuf
,s
?s
:"",needed
-1);
380 case 'z': /* offset to zero terminated string (4 byte) */
381 str
= va_arg(args
,char*);
382 stringneeded
= (str
? strlen(str
)+1 : 0);
385 case 'l': /* offset to user data (4 byte) */
386 str
= va_arg(args
,char*);
387 stringneeded
= va_arg(args
,int);
390 case 'b': /* offset to data (with counter) (4 byte) */
391 str
= va_arg(args
,char*);
392 stringneeded
= get_counter(&p
->curpos
);
398 if (stringneeded
>= 0) {
400 if (p
->buflen
>= needed
) {
401 stringused
= stringneeded
;
402 if (stringused
> p
->stringlen
) {
403 stringused
= (is_string
? p
->stringlen
: 0);
404 if (p
->errcode
== NERR_Success
) {
405 p
->errcode
= ERRmoredata
;
409 SIVAL(p
->structbuf
,0,0);
411 SIVAL(p
->structbuf
,0,PTR_DIFF(p
->stringbuf
,p
->base
));
412 memcpy(p
->stringbuf
,str
?str
:"",stringused
);
414 p
->stringbuf
[stringused
-1] = '\0';
416 p
->stringbuf
+= stringused
;
417 p
->stringlen
-= stringused
;
418 p
->usedlen
+= stringused
;
421 p
->neededlen
+= stringneeded
;
424 p
->neededlen
+= needed
;
425 if (p
->buflen
>= needed
) {
426 p
->structbuf
+= needed
;
428 p
->usedlen
+= needed
;
430 if (p
->errcode
== NERR_Success
) {
431 p
->errcode
= ERRmoredata
;
438 #define PACK(desc,t,v) package(desc,t,v,0,0,0,0)
439 #define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0)
441 #define PACK(desc,t,v) package(desc,v)
442 #define PACKl(desc,t,v,l) package(desc,v,l)
445 static void PACKI(struct pack_desc
* desc
, const char *t
,int v
)
450 static void PACKS(struct pack_desc
* desc
,const char *t
,const char *v
)
455 /****************************************************************************
457 ****************************************************************************/
459 static void PackDriverData(struct pack_desc
* desc
)
461 char drivdata
[4+4+32];
462 SIVAL(drivdata
,0,sizeof drivdata
); /* cb */
463 SIVAL(drivdata
,4,1000); /* lVersion */
464 memset(drivdata
+8,0,32); /* szDeviceName */
465 push_ascii(drivdata
+8,"NULL",32, STR_TERMINATE
);
466 PACKl(desc
,"l",drivdata
,sizeof drivdata
); /* pDriverData */
469 static int check_printq_info(struct pack_desc
* desc
,
470 unsigned int uLevel
, char *id1
, char *id2
)
472 desc
->subformat
= NULL
;
475 desc
->format
= "B13";
478 desc
->format
= "B13BWWWzzzzzWW";
481 desc
->format
= "B13BWWWzzzzzWN";
482 desc
->subformat
= "WB21BB16B10zWWzDDz";
485 desc
->format
= "zWWWWzzzzWWzzl";
488 desc
->format
= "zWWWWzzzzWNzzl";
489 desc
->subformat
= "WWzWWDDzz";
498 desc
->format
= "WzzzzzzzzN";
499 desc
->subformat
= "z";
502 DEBUG(0,("check_printq_info: invalid level %d\n",
506 if (id1
== NULL
|| strcmp(desc
->format
,id1
) != 0) {
507 DEBUG(0,("check_printq_info: invalid format %s\n",
508 id1
? id1
: "<NULL>" ));
511 if (desc
->subformat
&& (id2
== NULL
|| strcmp(desc
->subformat
,id2
) != 0)) {
512 DEBUG(0,("check_printq_info: invalid subformat %s\n",
513 id2
? id2
: "<NULL>" ));
520 #define RAP_JOB_STATUS_QUEUED 0
521 #define RAP_JOB_STATUS_PAUSED 1
522 #define RAP_JOB_STATUS_SPOOLING 2
523 #define RAP_JOB_STATUS_PRINTING 3
524 #define RAP_JOB_STATUS_PRINTED 4
526 #define RAP_QUEUE_STATUS_PAUSED 1
527 #define RAP_QUEUE_STATUS_ERROR 2
529 /* turn a print job status into a on the wire status
531 static int printj_status(int v
)
535 return RAP_JOB_STATUS_QUEUED
;
537 return RAP_JOB_STATUS_PAUSED
;
539 return RAP_JOB_STATUS_SPOOLING
;
541 return RAP_JOB_STATUS_PRINTING
;
546 /* turn a print queue status into a on the wire status
548 static int printq_status(int v
)
554 return RAP_QUEUE_STATUS_PAUSED
;
556 return RAP_QUEUE_STATUS_ERROR
;
559 static void fill_printjob_info(connection_struct
*conn
, int snum
, int uLevel
,
560 struct pack_desc
*desc
,
561 print_queue_struct
*queue
, int n
)
563 time_t t
= queue
->time
;
565 /* the client expects localtime */
566 t
-= get_time_zone(t
);
568 PACKI(desc
,"W",pjobid_to_rap(lp_const_servicename(snum
),queue
->job
)); /* uJobId */
570 PACKS(desc
,"B21",queue
->fs_user
); /* szUserName */
571 PACKS(desc
,"B",""); /* pad */
572 PACKS(desc
,"B16",""); /* szNotifyName */
573 PACKS(desc
,"B10","PM_Q_RAW"); /* szDataType */
574 PACKS(desc
,"z",""); /* pszParms */
575 PACKI(desc
,"W",n
+1); /* uPosition */
576 PACKI(desc
,"W",printj_status(queue
->status
)); /* fsStatus */
577 PACKS(desc
,"z",""); /* pszStatus */
578 PACKI(desc
,"D",t
); /* ulSubmitted */
579 PACKI(desc
,"D",queue
->size
); /* ulSize */
580 PACKS(desc
,"z",queue
->fs_file
); /* pszComment */
582 if (uLevel
== 2 || uLevel
== 3 || uLevel
== 4) {
583 PACKI(desc
,"W",queue
->priority
); /* uPriority */
584 PACKS(desc
,"z",queue
->fs_user
); /* pszUserName */
585 PACKI(desc
,"W",n
+1); /* uPosition */
586 PACKI(desc
,"W",printj_status(queue
->status
)); /* fsStatus */
587 PACKI(desc
,"D",t
); /* ulSubmitted */
588 PACKI(desc
,"D",queue
->size
); /* ulSize */
589 PACKS(desc
,"z","Samba"); /* pszComment */
590 PACKS(desc
,"z",queue
->fs_file
); /* pszDocument */
592 PACKS(desc
,"z",""); /* pszNotifyName */
593 PACKS(desc
,"z","PM_Q_RAW"); /* pszDataType */
594 PACKS(desc
,"z",""); /* pszParms */
595 PACKS(desc
,"z",""); /* pszStatus */
596 PACKS(desc
,"z",SERVICE(snum
)); /* pszQueue */
597 PACKS(desc
,"z","lpd"); /* pszQProcName */
598 PACKS(desc
,"z",""); /* pszQProcParms */
599 PACKS(desc
,"z","NULL"); /* pszDriverName */
600 PackDriverData(desc
); /* pDriverData */
601 PACKS(desc
,"z",""); /* pszPrinterName */
602 } else if (uLevel
== 4) { /* OS2 */
603 PACKS(desc
,"z",""); /* pszSpoolFileName */
604 PACKS(desc
,"z",""); /* pszPortName */
605 PACKS(desc
,"z",""); /* pszStatus */
606 PACKI(desc
,"D",0); /* ulPagesSpooled */
607 PACKI(desc
,"D",0); /* ulPagesSent */
608 PACKI(desc
,"D",0); /* ulPagesPrinted */
609 PACKI(desc
,"D",0); /* ulTimePrinted */
610 PACKI(desc
,"D",0); /* ulExtendJobStatus */
611 PACKI(desc
,"D",0); /* ulStartPage */
612 PACKI(desc
,"D",0); /* ulEndPage */
617 /********************************************************************
618 Return a driver name given an snum.
619 Returns True if from tdb, False otherwise.
620 ********************************************************************/
622 static bool get_driver_name(int snum
, char **pp_drivername
)
624 NT_PRINTER_INFO_LEVEL
*info
= NULL
;
627 get_a_printer (NULL
, &info
, 2, lp_servicename(snum
));
629 *pp_drivername
= talloc_strdup(talloc_tos(),
630 info
->info_2
->drivername
);
632 free_a_printer(&info
, 2);
633 if (!*pp_drivername
) {
641 /********************************************************************
642 Respond to the DosPrintQInfo command with a level of 52
643 This is used to get printer driver information for Win9x clients
644 ********************************************************************/
645 static void fill_printq_info_52(connection_struct
*conn
, int snum
,
646 struct pack_desc
* desc
, int count
)
650 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
651 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
655 if ( !W_ERROR_IS_OK(get_a_printer( NULL
, &printer
, 2, lp_servicename(snum
))) ) {
656 DEBUG(3,("fill_printq_info_52: Failed to lookup printer [%s]\n",
657 lp_servicename(snum
)));
661 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
,
664 DEBUG(3,("fill_printq_info_52: Failed to lookup driver [%s]\n",
665 printer
->info_2
->drivername
));
669 trim_string(driver
.info_3
->driverpath
, "\\print$\\WIN40\\0\\", 0);
670 trim_string(driver
.info_3
->datafile
, "\\print$\\WIN40\\0\\", 0);
671 trim_string(driver
.info_3
->helpfile
, "\\print$\\WIN40\\0\\", 0);
673 PACKI(desc
, "W", 0x0400); /* don't know */
674 PACKS(desc
, "z", driver
.info_3
->name
); /* long printer name */
675 PACKS(desc
, "z", driver
.info_3
->driverpath
); /* Driverfile Name */
676 PACKS(desc
, "z", driver
.info_3
->datafile
); /* Datafile name */
677 PACKS(desc
, "z", driver
.info_3
->monitorname
); /* language monitor */
679 fstrcpy(location
, "\\\\%L\\print$\\WIN40\\0");
680 standard_sub_basic( "", "", location
, sizeof(location
)-1 );
681 PACKS(desc
,"z", location
); /* share to retrieve files */
683 PACKS(desc
,"z", driver
.info_3
->defaultdatatype
); /* default data type */
684 PACKS(desc
,"z", driver
.info_3
->helpfile
); /* helpfile name */
685 PACKS(desc
,"z", driver
.info_3
->driverpath
); /* driver name */
687 DEBUG(3,("Printer Driver Name: %s:\n",driver
.info_3
->name
));
688 DEBUG(3,("Driver: %s:\n",driver
.info_3
->driverpath
));
689 DEBUG(3,("Data File: %s:\n",driver
.info_3
->datafile
));
690 DEBUG(3,("Language Monitor: %s:\n",driver
.info_3
->monitorname
));
691 DEBUG(3,("Driver Location: %s:\n",location
));
692 DEBUG(3,("Data Type: %s:\n",driver
.info_3
->defaultdatatype
));
693 DEBUG(3,("Help File: %s:\n",driver
.info_3
->helpfile
));
694 PACKI(desc
,"N",count
); /* number of files to copy */
696 for ( i
=0; i
<count
&& driver
.info_3
->dependentfiles
&& *driver
.info_3
->dependentfiles
[i
]; i
++)
698 trim_string(driver
.info_3
->dependentfiles
[i
], "\\print$\\WIN40\\0\\", 0);
699 PACKS(desc
,"z",driver
.info_3
->dependentfiles
[i
]); /* driver files to copy */
700 DEBUG(3,("Dependent File: %s:\n",driver
.info_3
->dependentfiles
[i
]));
705 DEBUG(3,("fill_printq_info_52: file count specified by client [%d] != number of dependent files [%i]\n",
708 DEBUG(3,("fill_printq_info on <%s> gave %d entries\n", SERVICE(snum
),i
));
710 desc
->errcode
=NERR_Success
;
714 DEBUG(3,("fill_printq_info: Can't supply driver files\n"));
715 desc
->errcode
=NERR_notsupported
;
719 free_a_printer( &printer
, 2 );
722 free_a_printer_driver( driver
, 3 );
726 static void fill_printq_info(connection_struct
*conn
, int snum
, int uLevel
,
727 struct pack_desc
* desc
,
728 int count
, print_queue_struct
* queue
,
729 print_status_struct
* status
)
734 PACKS(desc
,"B13",SERVICE(snum
));
739 PACKS(desc
,"z",Expand(conn
,snum
,SERVICE(snum
)));
742 PACKI(desc
,"K",printq_status(status
->status
));
746 if (uLevel
== 1 || uLevel
== 2) {
747 PACKS(desc
,"B",""); /* alignment */
748 PACKI(desc
,"W",5); /* priority */
749 PACKI(desc
,"W",0); /* start time */
750 PACKI(desc
,"W",0); /* until time */
751 PACKS(desc
,"z",""); /* pSepFile */
752 PACKS(desc
,"z","lpd"); /* pPrProc */
753 PACKS(desc
,"z",SERVICE(snum
)); /* pDestinations */
754 PACKS(desc
,"z",""); /* pParms */
756 PACKS(desc
,"z","UNKNOWN PRINTER");
757 PACKI(desc
,"W",LPSTAT_ERROR
);
759 else if (!status
|| !status
->message
[0]) {
760 PACKS(desc
,"z",Expand(conn
,snum
,lp_comment(snum
)));
761 PACKI(desc
,"W",LPSTAT_OK
); /* status */
763 PACKS(desc
,"z",status
->message
);
764 PACKI(desc
,"W",printq_status(status
->status
)); /* status */
766 PACKI(desc
,(uLevel
== 1 ? "W" : "N"),count
);
769 if (uLevel
== 3 || uLevel
== 4) {
770 char *drivername
= NULL
;
772 PACKI(desc
,"W",5); /* uPriority */
773 PACKI(desc
,"W",0); /* uStarttime */
774 PACKI(desc
,"W",0); /* uUntiltime */
775 PACKI(desc
,"W",5); /* pad1 */
776 PACKS(desc
,"z",""); /* pszSepFile */
777 PACKS(desc
,"z","WinPrint"); /* pszPrProc */
778 PACKS(desc
,"z",NULL
); /* pszParms */
779 PACKS(desc
,"z",NULL
); /* pszComment - don't ask.... JRA */
780 /* "don't ask" that it's done this way to fix corrupted
781 Win9X/ME printer comments. */
783 PACKI(desc
,"W",LPSTAT_OK
); /* fsStatus */
785 PACKI(desc
,"W",printq_status(status
->status
)); /* fsStatus */
787 PACKI(desc
,(uLevel
== 3 ? "W" : "N"),count
); /* cJobs */
788 PACKS(desc
,"z",SERVICE(snum
)); /* pszPrinters */
789 get_driver_name(snum
,&drivername
);
793 PACKS(desc
,"z",drivername
); /* pszDriverName */
794 PackDriverData(desc
); /* pDriverData */
797 if (uLevel
== 2 || uLevel
== 4) {
799 for (i
=0;i
<count
;i
++)
800 fill_printjob_info(conn
,snum
,uLevel
== 2 ? 1 : 2,desc
,&queue
[i
],i
);
804 fill_printq_info_52( conn
, snum
, desc
, count
);
807 /* This function returns the number of files for a given driver */
808 static int get_printerdrivernumber(int snum
)
811 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
812 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
816 if ( !W_ERROR_IS_OK(get_a_printer( NULL
, &printer
, 2, lp_servicename(snum
))) ) {
817 DEBUG(3,("get_printerdrivernumber: Failed to lookup printer [%s]\n",
818 lp_servicename(snum
)));
822 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
,
825 DEBUG(3,("get_printerdrivernumber: Failed to lookup driver [%s]\n",
826 printer
->info_2
->drivername
));
830 /* count the number of files */
831 while ( driver
.info_3
->dependentfiles
&& *driver
.info_3
->dependentfiles
[result
] )
836 free_a_printer( &printer
, 2 );
839 free_a_printer_driver( driver
, 3 );
844 static bool api_DosPrintQGetInfo(connection_struct
*conn
, uint16 vuid
,
845 char *param
, int tpscnt
,
846 char *data
, int tdscnt
,
847 int mdrcnt
,int mprcnt
,
848 char **rdata
,char **rparam
,
849 int *rdata_len
,int *rparam_len
)
851 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
852 char *str2
= skip_string(param
,tpscnt
,str1
);
853 char *p
= skip_string(param
,tpscnt
,str2
);
859 struct pack_desc desc
;
860 print_queue_struct
*queue
=NULL
;
861 print_status_struct status
;
864 if (!str1
|| !str2
|| !p
) {
867 memset((char *)&status
,'\0',sizeof(status
));
868 memset((char *)&desc
,'\0',sizeof(desc
));
870 p
= skip_string(param
,tpscnt
,p
);
874 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
875 str3
= get_safe_str_ptr(param
,tpscnt
,p
,4);
876 /* str3 may be null here and is checked in check_printq_info(). */
878 /* remove any trailing username */
879 if ((p
= strchr_m(QueueName
,'%')))
882 DEBUG(3,("api_DosPrintQGetInfo uLevel=%d name=%s\n",uLevel
,QueueName
));
884 /* check it's a supported varient */
885 if (!prefix_ok(str1
,"zWrLh"))
887 if (!check_printq_info(&desc
,uLevel
,str2
,str3
)) {
889 * Patch from Scott Moomaw <scott@bridgewater.edu>
890 * to return the 'invalid info level' error if an
891 * unknown level was requested.
895 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
899 SSVALS(*rparam
,0,ERRunknownlevel
);
905 snum
= find_service(QueueName
);
906 if ( !(lp_snum_ok(snum
) && lp_print_ok(snum
)) )
910 count
= get_printerdrivernumber(snum
);
911 DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count
));
913 count
= print_queue_status(snum
, &queue
,&status
);
917 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
923 desc
.buflen
= mdrcnt
;
926 * Don't return data but need to get correct length
927 * init_package will return wrong size if buflen=0
929 desc
.buflen
= getlen(desc
.format
);
930 desc
.base
= tmpdata
= (char *) SMB_MALLOC (desc
.buflen
);
933 if (init_package(&desc
,1,count
)) {
934 desc
.subcount
= count
;
935 fill_printq_info(conn
,snum
,uLevel
,&desc
,count
,queue
,&status
);
938 *rdata_len
= desc
.usedlen
;
941 * We must set the return code to ERRbuftoosmall
942 * in order to support lanman style printing with Win NT/2k
945 if (!mdrcnt
&& lp_disable_spoolss())
946 desc
.errcode
= ERRbuftoosmall
;
948 *rdata_len
= desc
.usedlen
;
950 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
956 SSVALS(*rparam
,0,desc
.errcode
);
958 SSVAL(*rparam
,4,desc
.neededlen
);
960 DEBUG(4,("printqgetinfo: errorcode %d\n",desc
.errcode
));
968 /****************************************************************************
969 View list of all print jobs on all queues.
970 ****************************************************************************/
972 static bool api_DosPrintQEnum(connection_struct
*conn
, uint16 vuid
,
973 char *param
, int tpscnt
,
974 char *data
, int tdscnt
,
975 int mdrcnt
, int mprcnt
,
976 char **rdata
, char** rparam
,
977 int *rdata_len
, int *rparam_len
)
979 char *param_format
= get_safe_str_ptr(param
,tpscnt
,param
,2);
980 char *output_format1
= skip_string(param
,tpscnt
,param_format
);
981 char *p
= skip_string(param
,tpscnt
,output_format1
);
982 unsigned int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
983 char *output_format2
= get_safe_str_ptr(param
,tpscnt
,p
,4);
984 int services
= lp_numservices();
986 struct pack_desc desc
;
987 print_queue_struct
**queue
= NULL
;
988 print_status_struct
*status
= NULL
;
989 int *subcntarr
= NULL
;
990 int queuecnt
= 0, subcnt
= 0, succnt
= 0;
992 if (!param_format
|| !output_format1
|| !p
) {
996 memset((char *)&desc
,'\0',sizeof(desc
));
998 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel
));
1000 if (!prefix_ok(param_format
,"WrLeh")) {
1003 if (!check_printq_info(&desc
,uLevel
,output_format1
,output_format2
)) {
1005 * Patch from Scott Moomaw <scott@bridgewater.edu>
1006 * to return the 'invalid info level' error if an
1007 * unknown level was requested.
1011 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1015 SSVALS(*rparam
,0,ERRunknownlevel
);
1021 for (i
= 0; i
< services
; i
++) {
1022 if (lp_snum_ok(i
) && lp_print_ok(i
) && lp_browseable(i
)) {
1027 if((queue
= SMB_MALLOC_ARRAY(print_queue_struct
*, queuecnt
)) == NULL
) {
1028 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
1031 memset(queue
,0,queuecnt
*sizeof(print_queue_struct
*));
1032 if((status
= SMB_MALLOC_ARRAY(print_status_struct
,queuecnt
)) == NULL
) {
1033 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
1036 memset(status
,0,queuecnt
*sizeof(print_status_struct
));
1037 if((subcntarr
= SMB_MALLOC_ARRAY(int,queuecnt
)) == NULL
) {
1038 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
1044 for (i
= 0; i
< services
; i
++) {
1045 if (lp_snum_ok(i
) && lp_print_ok(i
) && lp_browseable(i
)) {
1046 subcntarr
[n
] = print_queue_status(i
, &queue
[n
],&status
[n
]);
1047 subcnt
+= subcntarr
[n
];
1053 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
1059 desc
.buflen
= mdrcnt
;
1061 if (init_package(&desc
,queuecnt
,subcnt
)) {
1064 for (i
= 0; i
< services
; i
++) {
1065 if (lp_snum_ok(i
) && lp_print_ok(i
) && lp_browseable(i
)) {
1066 fill_printq_info(conn
,i
,uLevel
,&desc
,subcntarr
[n
],queue
[n
],&status
[n
]);
1068 if (desc
.errcode
== NERR_Success
) {
1075 SAFE_FREE(subcntarr
);
1077 *rdata_len
= desc
.usedlen
;
1079 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1083 SSVALS(*rparam
,0,desc
.errcode
);
1085 SSVAL(*rparam
,4,succnt
);
1086 SSVAL(*rparam
,6,queuecnt
);
1088 for (i
= 0; i
< queuecnt
; i
++) {
1090 SAFE_FREE(queue
[i
]);
1101 SAFE_FREE(subcntarr
);
1102 for (i
= 0; i
< queuecnt
; i
++) {
1104 SAFE_FREE(queue
[i
]);
1113 /****************************************************************************
1114 Get info level for a server list query.
1115 ****************************************************************************/
1117 static bool check_server_info(int uLevel
, char* id
)
1121 if (strcmp(id
,"B16") != 0) {
1126 if (strcmp(id
,"B16BBDz") != 0) {
1136 struct srv_info_struct
{
1144 /*******************************************************************
1145 Get server info lists from the files saved by nmbd. Return the
1147 ******************************************************************/
1149 static int get_server_info(uint32 servertype
,
1150 struct srv_info_struct
**servers
,
1156 bool local_list_only
;
1159 lines
= file_lines_load(lock_path(SERVER_LIST
), NULL
, 0);
1161 DEBUG(4,("Can't open %s - %s\n",lock_path(SERVER_LIST
),strerror(errno
)));
1165 /* request for everything is code for request all servers */
1166 if (servertype
== SV_TYPE_ALL
) {
1167 servertype
&= ~(SV_TYPE_DOMAIN_ENUM
|SV_TYPE_LOCAL_LIST_ONLY
);
1170 local_list_only
= (servertype
& SV_TYPE_LOCAL_LIST_ONLY
);
1172 DEBUG(4,("Servertype search: %8x\n",servertype
));
1174 for (i
=0;lines
[i
];i
++) {
1176 struct srv_info_struct
*s
;
1177 const char *ptr
= lines
[i
];
1179 TALLOC_CTX
*frame
= NULL
;
1186 if (count
== alloced
) {
1188 *servers
= SMB_REALLOC_ARRAY(*servers
,struct srv_info_struct
, alloced
);
1190 DEBUG(0,("get_server_info: failed to enlarge servers info struct!\n"));
1191 file_lines_free(lines
);
1194 memset((char *)((*servers
)+count
),'\0',sizeof(**servers
)*(alloced
-count
));
1196 s
= &(*servers
)[count
];
1198 frame
= talloc_stackframe();
1200 if (!next_token_talloc(frame
,&ptr
,&p
, NULL
)) {
1204 fstrcpy(s
->name
, p
);
1207 if (!next_token_talloc(frame
,&ptr
, &p
, NULL
)) {
1213 s
->comment
[0] = '\0';
1214 if (!next_token_talloc(frame
,&ptr
, &p
, NULL
)) {
1218 fstrcpy(s
->comment
, p
);
1220 s
->domain
[0] = '\0';
1221 if (!next_token_talloc(frame
,&ptr
,&p
, NULL
)) {
1222 /* this allows us to cope with an old nmbd */
1223 fstrcpy(s
->domain
,lp_workgroup());
1225 fstrcpy(s
->domain
, p
);
1229 if (sscanf(stype
,"%X",&s
->type
) != 1) {
1230 DEBUG(4,("r:host file "));
1234 /* Filter the servers/domains we return based on what was asked for. */
1236 /* Check to see if we are being asked for a local list only. */
1237 if(local_list_only
&& ((s
->type
& SV_TYPE_LOCAL_LIST_ONLY
) == 0)) {
1238 DEBUG(4,("r: local list only"));
1242 /* doesn't match up: don't want it */
1243 if (!(servertype
& s
->type
)) {
1244 DEBUG(4,("r:serv type "));
1248 if ((servertype
& SV_TYPE_DOMAIN_ENUM
) !=
1249 (s
->type
& SV_TYPE_DOMAIN_ENUM
)) {
1250 DEBUG(4,("s: dom mismatch "));
1254 if (!strequal(domain
, s
->domain
) && !(servertype
& SV_TYPE_DOMAIN_ENUM
)) {
1258 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
1259 s
->type
&= ~SV_TYPE_LOCAL_LIST_ONLY
;
1262 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
1263 s
->name
, s
->type
, s
->comment
, s
->domain
));
1264 s
->server_added
= True
;
1267 DEBUG(4,("%20s %8x %25s %15s\n",
1268 s
->name
, s
->type
, s
->comment
, s
->domain
));
1272 file_lines_free(lines
);
1276 /*******************************************************************
1277 Fill in a server info structure.
1278 ******************************************************************/
1280 static int fill_srv_info(struct srv_info_struct
*service
,
1281 int uLevel
, char **buf
, int *buflen
,
1282 char **stringbuf
, int *stringspace
, char *baseaddr
)
1305 len
= strlen(service
->comment
)+1;
1309 *buflen
= struct_len
;
1311 return struct_len
+ len
;
1316 if (*buflen
< struct_len
) {
1323 p2
= p
+ struct_len
;
1324 l2
= *buflen
- struct_len
;
1332 push_ascii(p
,service
->name
, MAX_NETBIOSNAME_LEN
, STR_TERMINATE
);
1336 push_ascii(p
,service
->name
,MAX_NETBIOSNAME_LEN
, STR_TERMINATE
);
1337 SIVAL(p
,18,service
->type
);
1338 SIVAL(p
,22,PTR_DIFF(p2
,baseaddr
));
1339 len
+= CopyAndAdvance(&p2
,service
->comment
,&l2
);
1344 *buf
= p
+ struct_len
;
1345 *buflen
-= struct_len
;
1356 static bool srv_comp(struct srv_info_struct
*s1
,struct srv_info_struct
*s2
)
1358 return(strcmp(s1
->name
,s2
->name
));
1361 /****************************************************************************
1362 View list of servers available (or possibly domains). The info is
1363 extracted from lists saved by nmbd on the local host.
1364 ****************************************************************************/
1366 static bool api_RNetServerEnum(connection_struct
*conn
, uint16 vuid
,
1367 char *param
, int tpscnt
,
1368 char *data
, int tdscnt
,
1369 int mdrcnt
, int mprcnt
, char **rdata
,
1370 char **rparam
, int *rdata_len
, int *rparam_len
)
1372 char *str1
= get_safe_str_ptr(param
, tpscnt
, param
, 2);
1373 char *str2
= skip_string(param
,tpscnt
,str1
);
1374 char *p
= skip_string(param
,tpscnt
,str2
);
1375 int uLevel
= get_safe_SVAL(param
, tpscnt
, p
, 0, -1);
1376 int buf_len
= get_safe_SVAL(param
,tpscnt
, p
, 2, 0);
1377 uint32 servertype
= get_safe_IVAL(param
,tpscnt
,p
,4, 0);
1379 int data_len
, fixed_len
, string_len
;
1380 int f_len
= 0, s_len
= 0;
1381 struct srv_info_struct
*servers
=NULL
;
1382 int counted
=0,total
=0;
1385 bool domain_request
;
1388 if (!str1
|| !str2
|| !p
) {
1392 /* If someone sets all the bits they don't really mean to set
1393 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1396 if (servertype
== SV_TYPE_ALL
) {
1397 servertype
&= ~(SV_TYPE_DOMAIN_ENUM
|SV_TYPE_LOCAL_LIST_ONLY
);
1400 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1401 any other bit (they may just set this bit on its own) they
1402 want all the locally seen servers. However this bit can be
1403 set on its own so set the requested servers to be
1404 ALL - DOMAIN_ENUM. */
1406 if ((servertype
& SV_TYPE_LOCAL_LIST_ONLY
) && !(servertype
& SV_TYPE_DOMAIN_ENUM
)) {
1407 servertype
= SV_TYPE_ALL
& ~(SV_TYPE_DOMAIN_ENUM
);
1410 domain_request
= ((servertype
& SV_TYPE_DOMAIN_ENUM
) != 0);
1411 local_request
= ((servertype
& SV_TYPE_LOCAL_LIST_ONLY
) != 0);
1415 if (!prefix_ok(str1
,"WrLehD")) {
1418 if (!check_server_info(uLevel
,str2
)) {
1422 DEBUG(4, ("server request level: %s %8x ", str2
, servertype
));
1423 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request
)));
1424 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request
)));
1426 if (strcmp(str1
, "WrLehDz") == 0) {
1427 if (skip_string(param
,tpscnt
,p
) == NULL
) {
1430 pull_ascii_fstring(domain
, p
);
1432 fstrcpy(domain
, lp_workgroup());
1435 if (lp_browse_list()) {
1436 total
= get_server_info(servertype
,&servers
,domain
);
1439 data_len
= fixed_len
= string_len
= 0;
1443 qsort(servers
,total
,sizeof(servers
[0]),QSORT_CAST srv_comp
);
1447 char *lastname
=NULL
;
1449 for (i
=0;i
<total
;i
++) {
1450 struct srv_info_struct
*s
= &servers
[i
];
1452 if (lastname
&& strequal(lastname
,s
->name
)) {
1456 data_len
+= fill_srv_info(s
,uLevel
,0,&f_len
,0,&s_len
,0);
1457 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1458 s
->name
, s
->type
, s
->comment
, s
->domain
));
1460 if (data_len
<= buf_len
) {
1463 string_len
+= s_len
;
1470 *rdata_len
= fixed_len
+ string_len
;
1471 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
1476 p2
= (*rdata
) + fixed_len
; /* auxilliary data (strings) will go here */
1482 char *lastname
=NULL
;
1483 int count2
= counted
;
1485 for (i
= 0; i
< total
&& count2
;i
++) {
1486 struct srv_info_struct
*s
= &servers
[i
];
1488 if (lastname
&& strequal(lastname
,s
->name
)) {
1492 fill_srv_info(s
,uLevel
,&p
,&f_len
,&p2
,&s_len
,*rdata
);
1493 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1494 s
->name
, s
->type
, s
->comment
, s
->domain
));
1500 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1504 SSVAL(*rparam
,0,(missed
== 0 ? NERR_Success
: ERRmoredata
));
1506 SSVAL(*rparam
,4,counted
);
1507 SSVAL(*rparam
,6,counted
+missed
);
1511 DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
1512 domain
,uLevel
,counted
,counted
+missed
));
1517 /****************************************************************************
1518 command 0x34 - suspected of being a "Lookup Names" stub api
1519 ****************************************************************************/
1521 static bool api_RNetGroupGetUsers(connection_struct
*conn
, uint16 vuid
,
1522 char *param
, int tpscnt
,
1523 char *data
, int tdscnt
,
1524 int mdrcnt
, int mprcnt
, char **rdata
,
1525 char **rparam
, int *rdata_len
, int *rparam_len
)
1527 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
1528 char *str2
= skip_string(param
,tpscnt
,str1
);
1529 char *p
= skip_string(param
,tpscnt
,str2
);
1530 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
1531 int buf_len
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
1535 if (!str1
|| !str2
|| !p
) {
1539 DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
1540 str1
, str2
, p
, uLevel
, buf_len
));
1542 if (!prefix_ok(str1
,"zWrLeh")) {
1549 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1554 SSVAL(*rparam
,0,0x08AC); /* informational warning message */
1556 SSVAL(*rparam
,4,counted
);
1557 SSVAL(*rparam
,6,counted
+missed
);
1562 /****************************************************************************
1563 get info about a share
1564 ****************************************************************************/
1566 static bool check_share_info(int uLevel
, char* id
)
1570 if (strcmp(id
,"B13") != 0) {
1575 if (strcmp(id
,"B13BWz") != 0) {
1580 if (strcmp(id
,"B13BWzWWWzB9B") != 0) {
1585 if (strcmp(id
,"B13BWzWWWzB9BB9BWzWWzWW") != 0) {
1595 static int fill_share_info(connection_struct
*conn
, int snum
, int uLevel
,
1596 char** buf
, int* buflen
,
1597 char** stringbuf
, int* stringspace
, char* baseaddr
)
1627 len
+= StrlenExpanded(conn
,snum
,lp_comment(snum
));
1630 len
+= strlen(lp_pathname(snum
)) + 1;
1633 *buflen
= struct_len
;
1638 return struct_len
+ len
;
1643 if ((*buflen
) < struct_len
) {
1651 p2
= p
+ struct_len
;
1652 l2
= (*buflen
) - struct_len
;
1659 push_ascii(p
,lp_servicename(snum
),13, STR_TERMINATE
);
1665 type
= STYPE_DISKTREE
;
1666 if (lp_print_ok(snum
)) {
1667 type
= STYPE_PRINTQ
;
1669 if (strequal("IPC",lp_fstype(snum
))) {
1672 SSVAL(p
,14,type
); /* device type */
1673 SIVAL(p
,16,PTR_DIFF(p2
,baseaddr
));
1674 len
+= CopyExpanded(conn
,snum
,&p2
,lp_comment(snum
),&l2
);
1678 SSVAL(p
,20,ACCESS_READ
|ACCESS_WRITE
|ACCESS_CREATE
); /* permissions */
1679 SSVALS(p
,22,-1); /* max uses */
1680 SSVAL(p
,24,1); /* current uses */
1681 SIVAL(p
,26,PTR_DIFF(p2
,baseaddr
)); /* local pathname */
1682 len
+= CopyAndAdvance(&p2
,lp_pathname(snum
),&l2
);
1683 memset(p
+30,0,SHPWLEN
+2); /* passwd (reserved), pad field */
1687 memset(p
+40,0,SHPWLEN
+2);
1698 (*buf
) = p
+ struct_len
;
1699 (*buflen
) -= struct_len
;
1701 (*stringspace
) = l2
;
1710 static bool api_RNetShareGetInfo(connection_struct
*conn
,uint16 vuid
,
1711 char *param
, int tpscnt
,
1712 char *data
, int tdscnt
,
1713 int mdrcnt
,int mprcnt
,
1714 char **rdata
,char **rparam
,
1715 int *rdata_len
,int *rparam_len
)
1717 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
1718 char *str2
= skip_string(param
,tpscnt
,str1
);
1719 char *netname
= skip_string(param
,tpscnt
,str2
);
1720 char *p
= skip_string(param
,tpscnt
,netname
);
1721 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
1724 if (!str1
|| !str2
|| !netname
|| !p
) {
1728 snum
= find_service(netname
);
1733 /* check it's a supported varient */
1734 if (!prefix_ok(str1
,"zWrLh")) {
1737 if (!check_share_info(uLevel
,str2
)) {
1741 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
1746 *rdata_len
= fill_share_info(conn
,snum
,uLevel
,&p
,&mdrcnt
,0,0,0);
1747 if (*rdata_len
< 0) {
1752 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1756 SSVAL(*rparam
,0,NERR_Success
);
1757 SSVAL(*rparam
,2,0); /* converter word */
1758 SSVAL(*rparam
,4,*rdata_len
);
1763 /****************************************************************************
1764 View the list of available shares.
1766 This function is the server side of the NetShareEnum() RAP call.
1767 It fills the return buffer with share names and share comments.
1768 Note that the return buffer normally (in all known cases) allows only
1769 twelve byte strings for share names (plus one for a nul terminator).
1770 Share names longer than 12 bytes must be skipped.
1771 ****************************************************************************/
1773 static bool api_RNetShareEnum( connection_struct
*conn
, uint16 vuid
,
1774 char *param
, int tpscnt
,
1775 char *data
, int tdscnt
,
1783 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
1784 char *str2
= skip_string(param
,tpscnt
,str1
);
1785 char *p
= skip_string(param
,tpscnt
,str2
);
1786 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
1787 int buf_len
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
1790 int total
=0,counted
=0;
1791 bool missed
= False
;
1793 int data_len
, fixed_len
, string_len
;
1794 int f_len
= 0, s_len
= 0;
1796 if (!str1
|| !str2
|| !p
) {
1800 if (!prefix_ok(str1
,"WrLeh")) {
1803 if (!check_share_info(uLevel
,str2
)) {
1807 /* Ensure all the usershares are loaded. */
1809 load_registry_shares();
1810 count
= load_usershare_shares();
1813 data_len
= fixed_len
= string_len
= 0;
1814 for (i
=0;i
<count
;i
++) {
1815 fstring servicename_dos
;
1816 if (!(lp_browseable(i
) && lp_snum_ok(i
))) {
1819 push_ascii_fstring(servicename_dos
, lp_servicename(i
));
1820 /* Maximum name length = 13. */
1821 if( lp_browseable( i
) && lp_snum_ok( i
) && (strlen(servicename_dos
) < 13)) {
1823 data_len
+= fill_share_info(conn
,i
,uLevel
,0,&f_len
,0,&s_len
,0);
1824 if (data_len
<= buf_len
) {
1827 string_len
+= s_len
;
1834 *rdata_len
= fixed_len
+ string_len
;
1835 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
1840 p2
= (*rdata
) + fixed_len
; /* auxiliary data (strings) will go here */
1845 for( i
= 0; i
< count
; i
++ ) {
1846 fstring servicename_dos
;
1847 if (!(lp_browseable(i
) && lp_snum_ok(i
))) {
1851 push_ascii_fstring(servicename_dos
, lp_servicename(i
));
1852 if (lp_browseable(i
) && lp_snum_ok(i
) && (strlen(servicename_dos
) < 13)) {
1853 if (fill_share_info( conn
,i
,uLevel
,&p
,&f_len
,&p2
,&s_len
,*rdata
) < 0) {
1860 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1864 SSVAL(*rparam
,0,missed
? ERRmoredata
: NERR_Success
);
1866 SSVAL(*rparam
,4,counted
);
1867 SSVAL(*rparam
,6,total
);
1869 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
1870 counted
,total
,uLevel
,
1871 buf_len
,*rdata_len
,mdrcnt
));
1876 /****************************************************************************
1878 ****************************************************************************/
1880 static bool api_RNetShareAdd(connection_struct
*conn
,uint16 vuid
,
1881 char *param
, int tpscnt
,
1882 char *data
, int tdscnt
,
1883 int mdrcnt
,int mprcnt
,
1884 char **rdata
,char **rparam
,
1885 int *rdata_len
,int *rparam_len
)
1887 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
1888 char *str2
= skip_string(param
,tpscnt
,str1
);
1889 char *p
= skip_string(param
,tpscnt
,str2
);
1890 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
1893 char *pathname
= NULL
;
1894 char *command
, *cmdname
;
1895 unsigned int offset
;
1898 size_t converted_size
;
1900 if (!str1
|| !str2
|| !p
) {
1904 /* check it's a supported varient */
1905 if (!prefix_ok(str1
,RAP_WShareAdd_REQ
)) {
1908 if (!check_share_info(uLevel
,str2
)) {
1915 /* Do we have a string ? */
1916 if (skip_string(data
,mdrcnt
,data
) == NULL
) {
1919 pull_ascii_fstring(sharename
,data
);
1920 snum
= find_service(sharename
);
1921 if (snum
>= 0) { /* already exists */
1930 /* only support disk share adds */
1931 if (SVAL(data
,14)!=STYPE_DISKTREE
) {
1935 offset
= IVAL(data
, 16);
1936 if (offset
>= mdrcnt
) {
1937 res
= ERRinvalidparam
;
1941 /* Do we have a string ? */
1942 if (skip_string(data
,mdrcnt
,data
+offset
) == NULL
) {
1945 pull_ascii_fstring(comment
, offset
? (data
+offset
) : "");
1947 offset
= IVAL(data
, 26);
1949 if (offset
>= mdrcnt
) {
1950 res
= ERRinvalidparam
;
1954 /* Do we have a string ? */
1955 if (skip_string(data
,mdrcnt
,data
+offset
) == NULL
) {
1959 if (!pull_ascii_talloc(talloc_tos(), &pathname
,
1960 offset
? (data
+offset
) : "", &converted_size
))
1962 DEBUG(0,("api_RNetShareAdd: pull_ascii_talloc failed: %s",
1970 string_replace(sharename
, '"', ' ');
1971 string_replace(pathname
, '"', ' ');
1972 string_replace(comment
, '"', ' ');
1974 cmdname
= lp_add_share_cmd();
1976 if (!cmdname
|| *cmdname
== '\0') {
1980 if (asprintf(&command
, "%s \"%s\" \"%s\" \"%s\" \"%s\"",
1981 lp_add_share_cmd(), get_dyn_CONFIGFILE(), sharename
,
1982 pathname
, comment
) == -1) {
1986 DEBUG(10,("api_RNetShareAdd: Running [%s]\n", command
));
1988 if ((res
= smbrun(command
, NULL
)) != 0) {
1989 DEBUG(1,("api_RNetShareAdd: Running [%s] returned (%d)\n",
1996 message_send_all(smbd_messaging_context(),
1997 MSG_SMB_CONF_UPDATED
, NULL
, 0, NULL
);
2001 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2005 SSVAL(*rparam
,0,NERR_Success
);
2006 SSVAL(*rparam
,2,0); /* converter word */
2007 SSVAL(*rparam
,4,*rdata_len
);
2015 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2020 SSVAL(*rparam
,0,res
);
2025 /****************************************************************************
2026 view list of groups available
2027 ****************************************************************************/
2029 static bool api_RNetGroupEnum(connection_struct
*conn
,uint16 vuid
,
2030 char *param
, int tpscnt
,
2031 char *data
, int tdscnt
,
2032 int mdrcnt
,int mprcnt
,
2033 char **rdata
,char **rparam
,
2034 int *rdata_len
,int *rparam_len
)
2038 int resume_context
, cli_buf_size
;
2039 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2040 char *str2
= skip_string(param
,tpscnt
,str1
);
2041 char *p
= skip_string(param
,tpscnt
,str2
);
2043 struct pdb_search
*search
;
2044 struct samr_displayentry
*entries
;
2048 if (!str1
|| !str2
|| !p
) {
2052 if (strcmp(str1
,"WrLeh") != 0) {
2057 * W-> resume context (number of users to skip)
2058 * r -> return parameter pointer to receive buffer
2059 * L -> length of receive buffer
2060 * e -> return parameter number of entries
2061 * h -> return parameter total number of users
2064 if (strcmp("B21",str2
) != 0) {
2068 /* get list of domain groups SID_DOMAIN_GRP=2 */
2070 search
= pdb_search_groups();
2073 if (search
== NULL
) {
2074 DEBUG(3,("api_RNetGroupEnum:failed to get group list"));
2078 resume_context
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2079 cli_buf_size
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
2080 DEBUG(10,("api_RNetGroupEnum:resume context: %d, client buffer size: "
2081 "%d\n", resume_context
, cli_buf_size
));
2084 num_entries
= pdb_search_entries(search
, resume_context
, 0xffffffff,
2088 *rdata_len
= cli_buf_size
;
2089 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2096 for(i
=0; i
<num_entries
; i
++) {
2098 fstrcpy(name
, entries
[i
].account_name
);
2099 if( ((PTR_DIFF(p
,*rdata
)+21) <= *rdata_len
) ) {
2100 /* truncate the name at 21 chars. */
2101 memcpy(p
, name
, 21);
2102 DEBUG(10,("adding entry %d group %s\n", i
, p
));
2104 p
+= 5; /* Both NT4 and W2k3SP1 do padding here.
2107 /* set overflow error */
2108 DEBUG(3,("overflow on entry %d group %s\n", i
, name
));
2114 pdb_search_destroy(search
);
2116 *rdata_len
= PTR_DIFF(p
,*rdata
);
2119 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2123 SSVAL(*rparam
, 0, errflags
);
2124 SSVAL(*rparam
, 2, 0); /* converter word */
2125 SSVAL(*rparam
, 4, i
); /* is this right?? */
2126 SSVAL(*rparam
, 6, resume_context
+num_entries
); /* is this right?? */
2131 /*******************************************************************
2132 Get groups that a user is a member of.
2133 ******************************************************************/
2135 static bool api_NetUserGetGroups(connection_struct
*conn
,uint16 vuid
,
2136 char *param
, int tpscnt
,
2137 char *data
, int tdscnt
,
2138 int mdrcnt
,int mprcnt
,
2139 char **rdata
,char **rparam
,
2140 int *rdata_len
,int *rparam_len
)
2142 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2143 char *str2
= skip_string(param
,tpscnt
,str1
);
2144 char *UserName
= skip_string(param
,tpscnt
,str2
);
2145 char *p
= skip_string(param
,tpscnt
,UserName
);
2146 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2147 const char *level_string
;
2149 struct samu
*sampw
= NULL
;
2157 enum lsa_SidType type
;
2159 TALLOC_CTX
*mem_ctx
;
2161 if (!str1
|| !str2
|| !UserName
|| !p
) {
2166 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2171 /* check it's a supported varient */
2173 if ( strcmp(str1
,"zWrLeh") != 0 )
2178 level_string
= "B21";
2184 if (strcmp(level_string
,str2
) != 0)
2187 *rdata_len
= mdrcnt
+ 1024;
2188 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2193 SSVAL(*rparam
,0,NERR_Success
);
2194 SSVAL(*rparam
,2,0); /* converter word */
2197 endp
= *rdata
+ *rdata_len
;
2199 mem_ctx
= talloc_new(NULL
);
2200 if (mem_ctx
== NULL
) {
2201 DEBUG(0, ("talloc_new failed\n"));
2205 if ( !(sampw
= samu_new(mem_ctx
)) ) {
2206 DEBUG(0, ("samu_new() failed!\n"));
2207 TALLOC_FREE(mem_ctx
);
2211 /* Lookup the user information; This should only be one of
2212 our accounts (not remote domains) */
2214 become_root(); /* ROOT BLOCK */
2216 if (!lookup_name(mem_ctx
, UserName
, LOOKUP_NAME_ALL
,
2217 NULL
, NULL
, &user_sid
, &type
)) {
2218 DEBUG(10, ("lookup_name(%s) failed\n", UserName
));
2222 if (type
!= SID_NAME_USER
) {
2223 DEBUG(10, ("%s is a %s, not a user\n", UserName
,
2224 sid_type_lookup(type
)));
2228 if ( !pdb_getsampwsid(sampw
, &user_sid
) ) {
2229 DEBUG(10, ("pdb_getsampwsid(%s) failed for user %s\n",
2230 sid_string_dbg(&user_sid
), UserName
));
2238 result
= pdb_enum_group_memberships(mem_ctx
, sampw
,
2239 &sids
, &gids
, &num_groups
);
2241 if (!NT_STATUS_IS_OK(result
)) {
2242 DEBUG(10, ("pdb_enum_group_memberships failed for %s\n",
2247 for (i
=0; i
<num_groups
; i
++) {
2248 const char *grp_name
;
2250 if ( lookup_sid(mem_ctx
, &sids
[i
], NULL
, &grp_name
, NULL
) ) {
2251 strlcpy(p
, grp_name
, PTR_DIFF(endp
,p
));
2257 *rdata_len
= PTR_DIFF(p
,*rdata
);
2259 SSVAL(*rparam
,4,count
); /* is this right?? */
2260 SSVAL(*rparam
,6,count
); /* is this right?? */
2265 unbecome_root(); /* END ROOT BLOCK */
2267 TALLOC_FREE(mem_ctx
);
2272 /*******************************************************************
2274 ******************************************************************/
2276 static bool api_RNetUserEnum(connection_struct
*conn
, uint16 vuid
,
2277 char *param
, int tpscnt
,
2278 char *data
, int tdscnt
,
2279 int mdrcnt
,int mprcnt
,
2280 char **rdata
,char **rparam
,
2281 int *rdata_len
,int *rparam_len
)
2286 int i
, resume_context
, cli_buf_size
;
2287 struct pdb_search
*search
;
2288 struct samr_displayentry
*users
;
2290 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2291 char *str2
= skip_string(param
,tpscnt
,str1
);
2292 char *p
= skip_string(param
,tpscnt
,str2
);
2295 if (!str1
|| !str2
|| !p
) {
2299 if (strcmp(str1
,"WrLeh") != 0)
2302 * W-> resume context (number of users to skip)
2303 * r -> return parameter pointer to receive buffer
2304 * L -> length of receive buffer
2305 * e -> return parameter number of entries
2306 * h -> return parameter total number of users
2309 resume_context
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2310 cli_buf_size
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
2311 DEBUG(10,("api_RNetUserEnum:resume context: %d, client buffer size: %d\n",
2312 resume_context
, cli_buf_size
));
2315 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2320 /* check it's a supported varient */
2321 if (strcmp("B21",str2
) != 0)
2324 *rdata_len
= cli_buf_size
;
2325 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2331 endp
= *rdata
+ *rdata_len
;
2334 search
= pdb_search_users(ACB_NORMAL
);
2336 if (search
== NULL
) {
2337 DEBUG(0, ("api_RNetUserEnum:unable to open sam database.\n"));
2342 num_users
= pdb_search_entries(search
, resume_context
, 0xffffffff,
2346 errflags
=NERR_Success
;
2348 for (i
=0; i
<num_users
; i
++) {
2349 const char *name
= users
[i
].account_name
;
2351 if(((PTR_DIFF(p
,*rdata
)+21)<=*rdata_len
)&&(strlen(name
)<=21)) {
2352 strlcpy(p
,name
,PTR_DIFF(endp
,p
));
2353 DEBUG(10,("api_RNetUserEnum:adding entry %d username "
2354 "%s\n",count_sent
,p
));
2358 /* set overflow error */
2359 DEBUG(10,("api_RNetUserEnum:overflow on entry %d "
2360 "username %s\n",count_sent
,name
));
2366 pdb_search_destroy(search
);
2368 *rdata_len
= PTR_DIFF(p
,*rdata
);
2370 SSVAL(*rparam
,0,errflags
);
2371 SSVAL(*rparam
,2,0); /* converter word */
2372 SSVAL(*rparam
,4,count_sent
); /* is this right?? */
2373 SSVAL(*rparam
,6,num_users
); /* is this right?? */
2378 /****************************************************************************
2379 Get the time of day info.
2380 ****************************************************************************/
2382 static bool api_NetRemoteTOD(connection_struct
*conn
,uint16 vuid
,
2383 char *param
, int tpscnt
,
2384 char *data
, int tdscnt
,
2385 int mdrcnt
,int mprcnt
,
2386 char **rdata
,char **rparam
,
2387 int *rdata_len
,int *rparam_len
)
2390 time_t unixdate
= time(NULL
);
2394 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2400 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2405 SSVAL(*rparam
,0,NERR_Success
);
2406 SSVAL(*rparam
,2,0); /* converter word */
2410 srv_put_dos_date3(p
,0,unixdate
); /* this is the time that is looked at
2411 by NT in a "net time" operation,
2412 it seems to ignore the one below */
2414 /* the client expects to get localtime, not GMT, in this bit
2415 (I think, this needs testing) */
2416 t
= localtime(&unixdate
);
2421 SIVAL(p
,4,0); /* msecs ? */
2422 SCVAL(p
,8,t
->tm_hour
);
2423 SCVAL(p
,9,t
->tm_min
);
2424 SCVAL(p
,10,t
->tm_sec
);
2425 SCVAL(p
,11,0); /* hundredths of seconds */
2426 SSVALS(p
,12,get_time_zone(unixdate
)/60); /* timezone in minutes from GMT */
2427 SSVAL(p
,14,10000); /* timer interval in 0.0001 of sec */
2428 SCVAL(p
,16,t
->tm_mday
);
2429 SCVAL(p
,17,t
->tm_mon
+ 1);
2430 SSVAL(p
,18,1900+t
->tm_year
);
2431 SCVAL(p
,20,t
->tm_wday
);
2436 /****************************************************************************
2437 Set the user password.
2438 *****************************************************************************/
2440 static bool api_SetUserPassword(connection_struct
*conn
,uint16 vuid
,
2441 char *param
, int tpscnt
,
2442 char *data
, int tdscnt
,
2443 int mdrcnt
,int mprcnt
,
2444 char **rdata
,char **rparam
,
2445 int *rdata_len
,int *rparam_len
)
2447 char *np
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2450 fstring pass1
,pass2
;
2452 /* Skip 2 strings. */
2453 p
= skip_string(param
,tpscnt
,np
);
2454 p
= skip_string(param
,tpscnt
,p
);
2460 /* Do we have a string ? */
2461 if (skip_string(param
,tpscnt
,p
) == NULL
) {
2464 pull_ascii_fstring(user
,p
);
2466 p
= skip_string(param
,tpscnt
,p
);
2471 memset(pass1
,'\0',sizeof(pass1
));
2472 memset(pass2
,'\0',sizeof(pass2
));
2474 * We use 31 here not 32 as we're checking
2475 * the last byte we want to access is safe.
2477 if (!is_offset_safe(param
,tpscnt
,p
,31)) {
2481 memcpy(pass2
,p
+16,16);
2484 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2491 SSVAL(*rparam
,0,NERR_badpass
);
2492 SSVAL(*rparam
,2,0); /* converter word */
2494 DEBUG(3,("Set password for <%s>\n",user
));
2497 * Attempt to verify the old password against smbpasswd entries
2498 * Win98 clients send old and new password in plaintext for this call.
2502 auth_serversupplied_info
*server_info
= NULL
;
2503 DATA_BLOB password
= data_blob(pass1
, strlen(pass1
)+1);
2505 if (NT_STATUS_IS_OK(check_plaintext_password(user
,password
,&server_info
))) {
2508 if (NT_STATUS_IS_OK(change_oem_password(server_info
->sam_account
, pass1
, pass2
, False
, NULL
))) {
2509 SSVAL(*rparam
,0,NERR_Success
);
2513 TALLOC_FREE(server_info
);
2515 data_blob_clear_free(&password
);
2519 * If the plaintext change failed, attempt
2520 * the old encrypted method. NT will generate this
2521 * after trying the samr method. Note that this
2522 * method is done as a last resort as this
2523 * password change method loses the NT password hash
2524 * and cannot change the UNIX password as no plaintext
2528 if(SVAL(*rparam
,0) != NERR_Success
) {
2529 struct samu
*hnd
= NULL
;
2531 if (check_lanman_password(user
,(unsigned char *)pass1
,(unsigned char *)pass2
, &hnd
)) {
2533 if (change_lanman_password(hnd
,(uchar
*)pass2
)) {
2534 SSVAL(*rparam
,0,NERR_Success
);
2541 memset((char *)pass1
,'\0',sizeof(fstring
));
2542 memset((char *)pass2
,'\0',sizeof(fstring
));
2547 /****************************************************************************
2548 Set the user password (SamOEM version - gets plaintext).
2549 ****************************************************************************/
2551 static bool api_SamOEMChangePassword(connection_struct
*conn
,uint16 vuid
,
2552 char *param
, int tpscnt
,
2553 char *data
, int tdscnt
,
2554 int mdrcnt
,int mprcnt
,
2555 char **rdata
,char **rparam
,
2556 int *rdata_len
,int *rparam_len
)
2559 char *p
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2561 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2571 SSVAL(*rparam
,0,NERR_badpass
);
2574 * Check the parameter definition is correct.
2577 /* Do we have a string ? */
2578 if (skip_string(param
,tpscnt
,p
) == 0) {
2581 if(!strequal(p
, "zsT")) {
2582 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", p
));
2585 p
= skip_string(param
, tpscnt
, p
);
2590 /* Do we have a string ? */
2591 if (skip_string(param
,tpscnt
,p
) == 0) {
2594 if(!strequal(p
, "B516B16")) {
2595 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p
));
2598 p
= skip_string(param
,tpscnt
,p
);
2602 /* Do we have a string ? */
2603 if (skip_string(param
,tpscnt
,p
) == 0) {
2606 p
+= pull_ascii_fstring(user
,p
);
2608 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user
));
2611 * Pass the user through the NT -> unix user mapping
2615 (void)map_username(user
);
2617 if (NT_STATUS_IS_OK(pass_oem_change(user
, (uchar
*) data
, (uchar
*)&data
[516], NULL
, NULL
, NULL
))) {
2618 SSVAL(*rparam
,0,NERR_Success
);
2624 /****************************************************************************
2627 ****************************************************************************/
2629 static bool api_RDosPrintJobDel(connection_struct
*conn
,uint16 vuid
,
2630 char *param
, int tpscnt
,
2631 char *data
, int tdscnt
,
2632 int mdrcnt
,int mprcnt
,
2633 char **rdata
,char **rparam
,
2634 int *rdata_len
,int *rparam_len
)
2636 int function
= get_safe_SVAL(param
,tpscnt
,param
,0,0);
2637 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2638 char *str2
= skip_string(param
,tpscnt
,str1
);
2639 char *p
= skip_string(param
,tpscnt
,str2
);
2644 WERROR werr
= WERR_OK
;
2646 if (!str1
|| !str2
|| !p
) {
2650 * We use 1 here not 2 as we're checking
2651 * the last byte we want to access is safe.
2653 if (!is_offset_safe(param
,tpscnt
,p
,1)) {
2656 if(!rap_to_pjobid(SVAL(p
,0), sharename
, &jobid
))
2659 /* check it's a supported varient */
2660 if (!(strcsequal(str1
,"W") && strcsequal(str2
,"")))
2664 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2670 if (!print_job_exists(sharename
, jobid
)) {
2671 errcode
= NERR_JobNotFound
;
2675 snum
= lp_servicenumber( sharename
);
2677 errcode
= NERR_DestNotFound
;
2681 errcode
= NERR_notsupported
;
2684 case 81: /* delete */
2685 if (print_job_delete(¤t_user
, snum
, jobid
, &werr
))
2686 errcode
= NERR_Success
;
2688 case 82: /* pause */
2689 if (print_job_pause(¤t_user
, snum
, jobid
, &werr
))
2690 errcode
= NERR_Success
;
2692 case 83: /* resume */
2693 if (print_job_resume(¤t_user
, snum
, jobid
, &werr
))
2694 errcode
= NERR_Success
;
2698 if (!W_ERROR_IS_OK(werr
))
2699 errcode
= W_ERROR_V(werr
);
2702 SSVAL(*rparam
,0,errcode
);
2703 SSVAL(*rparam
,2,0); /* converter word */
2708 /****************************************************************************
2709 Purge a print queue - or pause or resume it.
2710 ****************************************************************************/
2712 static bool api_WPrintQueueCtrl(connection_struct
*conn
,uint16 vuid
,
2713 char *param
, int tpscnt
,
2714 char *data
, int tdscnt
,
2715 int mdrcnt
,int mprcnt
,
2716 char **rdata
,char **rparam
,
2717 int *rdata_len
,int *rparam_len
)
2719 int function
= get_safe_SVAL(param
,tpscnt
,param
,0,0);
2720 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2721 char *str2
= skip_string(param
,tpscnt
,str1
);
2722 char *QueueName
= skip_string(param
,tpscnt
,str2
);
2723 int errcode
= NERR_notsupported
;
2725 WERROR werr
= WERR_OK
;
2727 if (!str1
|| !str2
|| !QueueName
) {
2731 /* check it's a supported varient */
2732 if (!(strcsequal(str1
,"z") && strcsequal(str2
,"")))
2736 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2742 if (skip_string(param
,tpscnt
,QueueName
) == NULL
) {
2745 snum
= print_queue_snum(QueueName
);
2748 errcode
= NERR_JobNotFound
;
2753 case 74: /* Pause queue */
2754 if (print_queue_pause(¤t_user
, snum
, &werr
)) errcode
= NERR_Success
;
2756 case 75: /* Resume queue */
2757 if (print_queue_resume(¤t_user
, snum
, &werr
)) errcode
= NERR_Success
;
2759 case 103: /* Purge */
2760 if (print_queue_purge(¤t_user
, snum
, &werr
)) errcode
= NERR_Success
;
2764 if (!W_ERROR_IS_OK(werr
)) errcode
= W_ERROR_V(werr
);
2767 SSVAL(*rparam
,0,errcode
);
2768 SSVAL(*rparam
,2,0); /* converter word */
2773 /****************************************************************************
2774 set the property of a print job (undocumented?)
2775 ? function = 0xb -> set name of print job
2776 ? function = 0x6 -> move print job up/down
2777 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
2778 or <WWsTP> <WB21BB16B10zWWzDDz>
2779 ****************************************************************************/
2781 static int check_printjob_info(struct pack_desc
* desc
,
2782 int uLevel
, char* id
)
2784 desc
->subformat
= NULL
;
2786 case 0: desc
->format
= "W"; break;
2787 case 1: desc
->format
= "WB21BB16B10zWWzDDz"; break;
2788 case 2: desc
->format
= "WWzWWDDzz"; break;
2789 case 3: desc
->format
= "WWzWWDDzzzzzzzzzzlz"; break;
2790 case 4: desc
->format
= "WWzWWDDzzzzzDDDDDDD"; break;
2792 DEBUG(0,("check_printjob_info: invalid level %d\n",
2796 if (id
== NULL
|| strcmp(desc
->format
,id
) != 0) {
2797 DEBUG(0,("check_printjob_info: invalid format %s\n",
2798 id
? id
: "<NULL>" ));
2804 static bool api_PrintJobInfo(connection_struct
*conn
, uint16 vuid
,
2805 char *param
, int tpscnt
,
2806 char *data
, int tdscnt
,
2807 int mdrcnt
,int mprcnt
,
2808 char **rdata
,char **rparam
,
2809 int *rdata_len
,int *rparam_len
)
2811 struct pack_desc desc
;
2812 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2813 char *str2
= skip_string(param
,tpscnt
,str1
);
2814 char *p
= skip_string(param
,tpscnt
,str2
);
2817 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,2,-1);
2818 int function
= get_safe_SVAL(param
,tpscnt
,p
,4,-1);
2821 if (!str1
|| !str2
|| !p
) {
2825 * We use 1 here not 2 as we're checking
2826 * the last byte we want to access is safe.
2828 if (!is_offset_safe(param
,tpscnt
,p
,1)) {
2831 if(!rap_to_pjobid(SVAL(p
,0), sharename
, &jobid
))
2834 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2839 if (!share_defined(sharename
)) {
2840 DEBUG(0,("api_PrintJobInfo: sharen [%s] not defined\n",
2847 /* check it's a supported varient */
2848 if ((strcmp(str1
,"WWsTP")) ||
2849 (!check_printjob_info(&desc
,uLevel
,str2
)))
2852 if (!print_job_exists(sharename
, jobid
)) {
2853 errcode
=NERR_JobNotFound
;
2857 errcode
= NERR_notsupported
;
2861 /* change job place in the queue,
2862 data gives the new place */
2863 place
= SVAL(data
,0);
2864 if (print_job_set_place(sharename
, jobid
, place
)) {
2865 errcode
=NERR_Success
;
2870 /* change print job name, data gives the name */
2871 if (print_job_set_name(sharename
, jobid
, data
)) {
2872 errcode
=NERR_Success
;
2881 SSVALS(*rparam
,0,errcode
);
2882 SSVAL(*rparam
,2,0); /* converter word */
2888 /****************************************************************************
2889 Get info about the server.
2890 ****************************************************************************/
2892 static bool api_RNetServerGetInfo(connection_struct
*conn
,uint16 vuid
,
2893 char *param
, int tpscnt
,
2894 char *data
, int tdscnt
,
2895 int mdrcnt
,int mprcnt
,
2896 char **rdata
,char **rparam
,
2897 int *rdata_len
,int *rparam_len
)
2899 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2900 char *str2
= skip_string(param
,tpscnt
,str1
);
2901 char *p
= skip_string(param
,tpscnt
,str2
);
2902 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2906 if (!str1
|| !str2
|| !p
) {
2910 DEBUG(4,("NetServerGetInfo level %d\n",uLevel
));
2912 /* check it's a supported varient */
2913 if (!prefix_ok(str1
,"WrLh")) {
2919 if (strcmp(str2
,"B16") != 0) {
2925 if (strcmp(str2
,"B16BBDz") != 0) {
2931 if (strcmp(str2
,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")!= 0) {
2937 if (strcmp(str2
,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz") != 0) {
2943 if (strcmp(str2
,"DN") != 0) {
2949 if (strcmp(str2
,"B16BBDzWWzzz") != 0) {
2958 *rdata_len
= mdrcnt
;
2959 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2965 p2
= p
+ struct_len
;
2967 srvstr_push(NULL
, 0, p
,global_myname(),16,
2968 STR_ASCII
|STR_UPPER
|STR_TERMINATE
);
2972 struct srv_info_struct
*servers
=NULL
;
2974 char *comment
= NULL
;
2975 TALLOC_CTX
*ctx
= talloc_tos();
2976 uint32 servertype
= lp_default_server_announce();
2978 comment
= talloc_strdup(ctx
,lp_serverstring());
2983 if ((count
=get_server_info(SV_TYPE_ALL
,&servers
,lp_workgroup()))>0) {
2984 for (i
=0;i
<count
;i
++) {
2985 if (strequal(servers
[i
].name
,global_myname())) {
2986 servertype
= servers
[i
].type
;
2987 TALLOC_FREE(comment
);
2988 comment
= talloc_strdup(ctx
,
2989 servers
[i
].comment
);
2999 SCVAL(p
,0,lp_major_announce_version());
3000 SCVAL(p
,1,lp_minor_announce_version());
3001 SIVAL(p
,2,servertype
);
3003 if (mdrcnt
== struct_len
) {
3006 SIVAL(p
,6,PTR_DIFF(p2
,*rdata
));
3007 comment
= talloc_sub_advanced(
3009 lp_servicename(SNUM(conn
)),
3010 conn
->server_info
->unix_name
,
3012 conn
->server_info
->gid
,
3013 conn
->server_info
->sanitized_username
,
3014 pdb_get_domain(conn
->server_info
->sam_account
),
3019 if (mdrcnt
- struct_len
<= 0) {
3024 MIN(mdrcnt
- struct_len
,
3025 MAX_SERVER_STRING_LENGTH
),
3027 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3035 return False
; /* not yet implemented */
3038 *rdata_len
= PTR_DIFF(p2
,*rdata
);
3041 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3045 SSVAL(*rparam
,0,NERR_Success
);
3046 SSVAL(*rparam
,2,0); /* converter word */
3047 SSVAL(*rparam
,4,*rdata_len
);
3052 /****************************************************************************
3053 Get info about the server.
3054 ****************************************************************************/
3056 static bool api_NetWkstaGetInfo(connection_struct
*conn
,uint16 vuid
,
3057 char *param
, int tpscnt
,
3058 char *data
, int tdscnt
,
3059 int mdrcnt
,int mprcnt
,
3060 char **rdata
,char **rparam
,
3061 int *rdata_len
,int *rparam_len
)
3063 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3064 char *str2
= skip_string(param
,tpscnt
,str1
);
3065 char *p
= skip_string(param
,tpscnt
,str2
);
3068 int level
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3070 if (!str1
|| !str2
|| !p
) {
3074 DEBUG(4,("NetWkstaGetInfo level %d\n",level
));
3077 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3082 /* check it's a supported varient */
3083 if (!(level
==10 && strcsequal(str1
,"WrLh") && strcsequal(str2
,"zzzBBzz"))) {
3087 *rdata_len
= mdrcnt
+ 1024;
3088 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
3093 SSVAL(*rparam
,0,NERR_Success
);
3094 SSVAL(*rparam
,2,0); /* converter word */
3097 endp
= *rdata
+ *rdata_len
;
3099 p2
= get_safe_ptr(*rdata
,*rdata_len
,p
,22);
3104 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* host name */
3105 strlcpy(p2
,get_local_machine_name(),PTR_DIFF(endp
,p2
));
3107 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3113 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
));
3114 strlcpy(p2
,conn
->server_info
->sanitized_username
,PTR_DIFF(endp
,p2
));
3115 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3121 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* login domain */
3122 strlcpy(p2
,lp_workgroup(),PTR_DIFF(endp
,p2
));
3124 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3130 SCVAL(p
,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
3131 SCVAL(p
,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
3134 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
));
3135 strlcpy(p2
,lp_workgroup(),PTR_DIFF(endp
,p2
)); /* don't know. login domain?? */
3136 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3142 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* don't know */
3143 strlcpy(p2
,"",PTR_DIFF(endp
,p2
));
3144 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3150 *rdata_len
= PTR_DIFF(p2
,*rdata
);
3152 SSVAL(*rparam
,4,*rdata_len
);
3157 /****************************************************************************
3158 get info about a user
3160 struct user_info_11 {
3161 char usri11_name[21]; 0-20
3163 char *usri11_comment; 22-25
3164 char *usri11_usr_comment; 26-29
3165 unsigned short usri11_priv; 30-31
3166 unsigned long usri11_auth_flags; 32-35
3167 long usri11_password_age; 36-39
3168 char *usri11_homedir; 40-43
3169 char *usri11_parms; 44-47
3170 long usri11_last_logon; 48-51
3171 long usri11_last_logoff; 52-55
3172 unsigned short usri11_bad_pw_count; 56-57
3173 unsigned short usri11_num_logons; 58-59
3174 char *usri11_logon_server; 60-63
3175 unsigned short usri11_country_code; 64-65
3176 char *usri11_workstations; 66-69
3177 unsigned long usri11_max_storage; 70-73
3178 unsigned short usri11_units_per_week; 74-75
3179 unsigned char *usri11_logon_hours; 76-79
3180 unsigned short usri11_code_page; 80-81
3185 usri11_name specifies the user name for which information is retrieved
3187 usri11_pad aligns the next data structure element to a word boundary
3189 usri11_comment is a null terminated ASCII comment
3191 usri11_user_comment is a null terminated ASCII comment about the user
3193 usri11_priv specifies the level of the privilege assigned to the user.
3194 The possible values are:
3196 Name Value Description
3197 USER_PRIV_GUEST 0 Guest privilege
3198 USER_PRIV_USER 1 User privilege
3199 USER_PRV_ADMIN 2 Administrator privilege
3201 usri11_auth_flags specifies the account operator privileges. The
3202 possible values are:
3204 Name Value Description
3205 AF_OP_PRINT 0 Print operator
3208 Leach, Naik [Page 28]
3212 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
3215 AF_OP_COMM 1 Communications operator
3216 AF_OP_SERVER 2 Server operator
3217 AF_OP_ACCOUNTS 3 Accounts operator
3220 usri11_password_age specifies how many seconds have elapsed since the
3221 password was last changed.
3223 usri11_home_dir points to a null terminated ASCII string that contains
3224 the path name of the user's home directory.
3226 usri11_parms points to a null terminated ASCII string that is set
3227 aside for use by applications.
3229 usri11_last_logon specifies the time when the user last logged on.
3230 This value is stored as the number of seconds elapsed since
3231 00:00:00, January 1, 1970.
3233 usri11_last_logoff specifies the time when the user last logged off.
3234 This value is stored as the number of seconds elapsed since
3235 00:00:00, January 1, 1970. A value of 0 means the last logoff
3238 usri11_bad_pw_count specifies the number of incorrect passwords
3239 entered since the last successful logon.
3241 usri11_log1_num_logons specifies the number of times this user has
3242 logged on. A value of -1 means the number of logons is unknown.
3244 usri11_logon_server points to a null terminated ASCII string that
3245 contains the name of the server to which logon requests are sent.
3246 A null string indicates logon requests should be sent to the
3249 usri11_country_code specifies the country code for the user's language
3252 usri11_workstations points to a null terminated ASCII string that
3253 contains the names of workstations the user may log on from.
3254 There may be up to 8 workstations, with the names separated by
3255 commas. A null strings indicates there are no restrictions.
3257 usri11_max_storage specifies the maximum amount of disk space the user
3258 can occupy. A value of 0xffffffff indicates there are no
3261 usri11_units_per_week specifies the equal number of time units into
3262 which a week is divided. This value must be equal to 168.
3264 usri11_logon_hours points to a 21 byte (168 bits) string that
3265 specifies the time during which the user can log on. Each bit
3266 represents one unique hour in a week. The first bit (bit 0, word
3267 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
3271 Leach, Naik [Page 29]
3275 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
3278 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
3279 are no restrictions.
3281 usri11_code_page specifies the code page for the user's language of
3284 All of the pointers in this data structure need to be treated
3285 specially. The pointer is a 32 bit pointer. The higher 16 bits need
3286 to be ignored. The converter word returned in the parameters section
3287 needs to be subtracted from the lower 16 bits to calculate an offset
3288 into the return buffer where this ASCII string resides.
3290 There is no auxiliary data in the response.
3292 ****************************************************************************/
3294 #define usri11_name 0
3295 #define usri11_pad 21
3296 #define usri11_comment 22
3297 #define usri11_usr_comment 26
3298 #define usri11_full_name 30
3299 #define usri11_priv 34
3300 #define usri11_auth_flags 36
3301 #define usri11_password_age 40
3302 #define usri11_homedir 44
3303 #define usri11_parms 48
3304 #define usri11_last_logon 52
3305 #define usri11_last_logoff 56
3306 #define usri11_bad_pw_count 60
3307 #define usri11_num_logons 62
3308 #define usri11_logon_server 64
3309 #define usri11_country_code 68
3310 #define usri11_workstations 70
3311 #define usri11_max_storage 74
3312 #define usri11_units_per_week 78
3313 #define usri11_logon_hours 80
3314 #define usri11_code_page 84
3315 #define usri11_end 86
3317 #define USER_PRIV_GUEST 0
3318 #define USER_PRIV_USER 1
3319 #define USER_PRIV_ADMIN 2
3321 #define AF_OP_PRINT 0
3322 #define AF_OP_COMM 1
3323 #define AF_OP_SERVER 2
3324 #define AF_OP_ACCOUNTS 3
3327 static bool api_RNetUserGetInfo(connection_struct
*conn
, uint16 vuid
,
3328 char *param
, int tpscnt
,
3329 char *data
, int tdscnt
,
3330 int mdrcnt
,int mprcnt
,
3331 char **rdata
,char **rparam
,
3332 int *rdata_len
,int *rparam_len
)
3334 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3335 char *str2
= skip_string(param
,tpscnt
,str1
);
3336 char *UserName
= skip_string(param
,tpscnt
,str2
);
3337 char *p
= skip_string(param
,tpscnt
,UserName
);
3338 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3341 const char *level_string
;
3343 /* get NIS home of a previously validated user - simeon */
3344 /* With share level security vuid will always be zero.
3345 Don't depend on vuser being non-null !!. JRA */
3346 user_struct
*vuser
= get_valid_user_struct(vuid
);
3348 DEBUG(3,(" Username of UID %d is %s\n",
3349 (int)vuser
->server_info
->uid
,
3350 vuser
->server_info
->unix_name
));
3353 if (!str1
|| !str2
|| !UserName
|| !p
) {
3358 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3363 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel
));
3365 /* check it's a supported variant */
3366 if (strcmp(str1
,"zWrLh") != 0) {
3370 case 0: level_string
= "B21"; break;
3371 case 1: level_string
= "B21BB16DWzzWz"; break;
3372 case 2: level_string
= "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
3373 case 10: level_string
= "B21Bzzz"; break;
3374 case 11: level_string
= "B21BzzzWDDzzDDWWzWzDWb21W"; break;
3375 default: return False
;
3378 if (strcmp(level_string
,str2
) != 0) {
3382 *rdata_len
= mdrcnt
+ 1024;
3383 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
3388 SSVAL(*rparam
,0,NERR_Success
);
3389 SSVAL(*rparam
,2,0); /* converter word */
3392 endp
= *rdata
+ *rdata_len
;
3393 p2
= get_safe_ptr(*rdata
,*rdata_len
,p
,usri11_end
);
3399 fstrcpy(p
+usri11_name
,UserName
); /* 21 bytes - user name */
3402 SCVAL(p
,usri11_pad
,0); /* padding - 1 byte */
3407 SIVAL(p
,usri11_comment
,PTR_DIFF(p2
,p
)); /* comment */
3408 strlcpy(p2
,"Comment",PTR_DIFF(endp
,p2
));
3409 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3414 SIVAL(p
,usri11_usr_comment
,PTR_DIFF(p2
,p
)); /* user_comment */
3415 strlcpy(p2
,"UserComment",PTR_DIFF(endp
,p2
));
3416 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3421 /* EEK! the cifsrap.txt doesn't have this in!!!! */
3422 SIVAL(p
,usri11_full_name
,PTR_DIFF(p2
,p
)); /* full name */
3423 strlcpy(p2
,((vuser
!= NULL
)
3424 ? pdb_get_fullname(vuser
->server_info
->sam_account
)
3425 : UserName
),PTR_DIFF(endp
,p2
));
3426 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3433 const char *homedir
= "";
3434 if (vuser
!= NULL
) {
3435 homedir
= pdb_get_homedir(
3436 vuser
->server_info
->sam_account
);
3438 /* modelled after NTAS 3.51 reply */
3439 SSVAL(p
,usri11_priv
,conn
->admin_user
?USER_PRIV_ADMIN
:USER_PRIV_USER
);
3440 SIVAL(p
,usri11_auth_flags
,AF_OP_PRINT
); /* auth flags */
3441 SIVALS(p
,usri11_password_age
,-1); /* password age */
3442 SIVAL(p
,usri11_homedir
,PTR_DIFF(p2
,p
)); /* home dir */
3443 strlcpy(p2
, homedir
, PTR_DIFF(endp
,p2
));
3444 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3448 SIVAL(p
,usri11_parms
,PTR_DIFF(p2
,p
)); /* parms */
3449 strlcpy(p2
,"",PTR_DIFF(endp
,p2
));
3450 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3454 SIVAL(p
,usri11_last_logon
,0); /* last logon */
3455 SIVAL(p
,usri11_last_logoff
,0); /* last logoff */
3456 SSVALS(p
,usri11_bad_pw_count
,-1); /* bad pw counts */
3457 SSVALS(p
,usri11_num_logons
,-1); /* num logons */
3458 SIVAL(p
,usri11_logon_server
,PTR_DIFF(p2
,p
)); /* logon server */
3459 strlcpy(p2
,"\\\\*",PTR_DIFF(endp
,p2
));
3460 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3464 SSVAL(p
,usri11_country_code
,0); /* country code */
3466 SIVAL(p
,usri11_workstations
,PTR_DIFF(p2
,p
)); /* workstations */
3467 strlcpy(p2
,"",PTR_DIFF(endp
,p2
));
3468 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3473 SIVALS(p
,usri11_max_storage
,-1); /* max storage */
3474 SSVAL(p
,usri11_units_per_week
,168); /* units per week */
3475 SIVAL(p
,usri11_logon_hours
,PTR_DIFF(p2
,p
)); /* logon hours */
3477 /* a simple way to get logon hours at all times. */
3479 SCVAL(p2
,21,0); /* fix zero termination */
3480 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3485 SSVAL(p
,usri11_code_page
,0); /* code page */
3488 if (uLevel
== 1 || uLevel
== 2) {
3489 memset(p
+22,' ',16); /* password */
3490 SIVALS(p
,38,-1); /* password age */
3492 conn
->admin_user
?USER_PRIV_ADMIN
:USER_PRIV_USER
);
3493 SIVAL(p
,44,PTR_DIFF(p2
,*rdata
)); /* home dir */
3494 strlcpy(p2
, vuser
? pdb_get_homedir(
3495 vuser
->server_info
->sam_account
) : "",
3497 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3501 SIVAL(p
,48,PTR_DIFF(p2
,*rdata
)); /* comment */
3503 SSVAL(p
,52,0); /* flags */
3504 SIVAL(p
,54,PTR_DIFF(p2
,*rdata
)); /* script_path */
3505 strlcpy(p2
, vuser
? pdb_get_logon_script(
3506 vuser
->server_info
->sam_account
) : "",
3508 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3513 SIVAL(p
,60,0); /* auth_flags */
3514 SIVAL(p
,64,PTR_DIFF(p2
,*rdata
)); /* full_name */
3515 strlcpy(p2
,((vuser
!= NULL
)
3516 ? pdb_get_fullname(vuser
->server_info
->sam_account
)
3517 : UserName
),PTR_DIFF(endp
,p2
));
3518 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3522 SIVAL(p
,68,0); /* urs_comment */
3523 SIVAL(p
,72,PTR_DIFF(p2
,*rdata
)); /* parms */
3524 strlcpy(p2
,"",PTR_DIFF(endp
,p2
));
3525 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3529 SIVAL(p
,76,0); /* workstations */
3530 SIVAL(p
,80,0); /* last_logon */
3531 SIVAL(p
,84,0); /* last_logoff */
3532 SIVALS(p
,88,-1); /* acct_expires */
3533 SIVALS(p
,92,-1); /* max_storage */
3534 SSVAL(p
,96,168); /* units_per_week */
3535 SIVAL(p
,98,PTR_DIFF(p2
,*rdata
)); /* logon_hours */
3538 SSVALS(p
,102,-1); /* bad_pw_count */
3539 SSVALS(p
,104,-1); /* num_logons */
3540 SIVAL(p
,106,PTR_DIFF(p2
,*rdata
)); /* logon_server */
3542 TALLOC_CTX
*ctx
= talloc_tos();
3543 int space_rem
= *rdata_len
- (p2
- *rdata
);
3546 if (space_rem
<= 0) {
3549 tmp
= talloc_strdup(ctx
, "\\\\%L");
3553 tmp
= talloc_sub_basic(ctx
,
3566 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3570 SSVAL(p
,110,49); /* country_code */
3571 SSVAL(p
,112,860); /* code page */
3575 *rdata_len
= PTR_DIFF(p2
,*rdata
);
3577 SSVAL(*rparam
,4,*rdata_len
); /* is this right?? */
3582 static bool api_WWkstaUserLogon(connection_struct
*conn
,uint16 vuid
,
3583 char *param
, int tpscnt
,
3584 char *data
, int tdscnt
,
3585 int mdrcnt
,int mprcnt
,
3586 char **rdata
,char **rparam
,
3587 int *rdata_len
,int *rparam_len
)
3589 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3590 char *str2
= skip_string(param
,tpscnt
,str1
);
3591 char *p
= skip_string(param
,tpscnt
,str2
);
3593 struct pack_desc desc
;
3595 /* With share level security vuid will always be zero.
3596 Don't depend on vuser being non-null !!. JRA */
3597 user_struct
*vuser
= get_valid_user_struct(vuid
);
3599 if (!str1
|| !str2
|| !p
) {
3604 DEBUG(3,(" Username of UID %d is %s\n",
3605 (int)vuser
->server_info
->uid
,
3606 vuser
->server_info
->unix_name
));
3609 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3610 name
= get_safe_str_ptr(param
,tpscnt
,p
,2);
3615 memset((char *)&desc
,'\0',sizeof(desc
));
3617 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel
,name
));
3619 /* check it's a supported varient */
3620 if (strcmp(str1
,"OOWb54WrLh") != 0) {
3623 if (uLevel
!= 1 || strcmp(str2
,"WB21BWDWWDDDDDDDzzzD") != 0) {
3627 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
3634 desc
.buflen
= mdrcnt
;
3635 desc
.subformat
= NULL
;
3638 if (init_package(&desc
,1,0)) {
3639 PACKI(&desc
,"W",0); /* code */
3640 PACKS(&desc
,"B21",name
); /* eff. name */
3641 PACKS(&desc
,"B",""); /* pad */
3642 PACKI(&desc
,"W", conn
->admin_user
?USER_PRIV_ADMIN
:USER_PRIV_USER
);
3643 PACKI(&desc
,"D",0); /* auth flags XXX */
3644 PACKI(&desc
,"W",0); /* num logons */
3645 PACKI(&desc
,"W",0); /* bad pw count */
3646 PACKI(&desc
,"D",0); /* last logon */
3647 PACKI(&desc
,"D",-1); /* last logoff */
3648 PACKI(&desc
,"D",-1); /* logoff time */
3649 PACKI(&desc
,"D",-1); /* kickoff time */
3650 PACKI(&desc
,"D",0); /* password age */
3651 PACKI(&desc
,"D",0); /* password can change */
3652 PACKI(&desc
,"D",-1); /* password must change */
3656 fstrcpy(mypath
,"\\\\");
3657 fstrcat(mypath
,get_local_machine_name());
3659 PACKS(&desc
,"z",mypath
); /* computer */
3662 PACKS(&desc
,"z",lp_workgroup());/* domain */
3663 PACKS(&desc
,"z", vuser
? pdb_get_logon_script(
3664 vuser
->server_info
->sam_account
) : ""); /* script path */
3665 PACKI(&desc
,"D",0x00000000); /* reserved */
3668 *rdata_len
= desc
.usedlen
;
3670 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3674 SSVALS(*rparam
,0,desc
.errcode
);
3676 SSVAL(*rparam
,4,desc
.neededlen
);
3678 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc
.errcode
));
3683 /****************************************************************************
3684 api_WAccessGetUserPerms
3685 ****************************************************************************/
3687 static bool api_WAccessGetUserPerms(connection_struct
*conn
,uint16 vuid
,
3688 char *param
, int tpscnt
,
3689 char *data
, int tdscnt
,
3690 int mdrcnt
,int mprcnt
,
3691 char **rdata
,char **rparam
,
3692 int *rdata_len
,int *rparam_len
)
3694 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3695 char *str2
= skip_string(param
,tpscnt
,str1
);
3696 char *user
= skip_string(param
,tpscnt
,str2
);
3697 char *resource
= skip_string(param
,tpscnt
,user
);
3699 if (!str1
|| !str2
|| !user
|| !resource
) {
3703 if (skip_string(param
,tpscnt
,resource
) == NULL
) {
3706 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user
,resource
));
3708 /* check it's a supported varient */
3709 if (strcmp(str1
,"zzh") != 0) {
3712 if (strcmp(str2
,"") != 0) {
3717 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3721 SSVALS(*rparam
,0,0); /* errorcode */
3722 SSVAL(*rparam
,2,0); /* converter word */
3723 SSVAL(*rparam
,4,0x7f); /* permission flags */
3728 /****************************************************************************
3729 api_WPrintJobEnumerate
3730 ****************************************************************************/
3732 static bool api_WPrintJobGetInfo(connection_struct
*conn
, uint16 vuid
,
3733 char *param
, int tpscnt
,
3734 char *data
, int tdscnt
,
3735 int mdrcnt
,int mprcnt
,
3736 char **rdata
,char **rparam
,
3737 int *rdata_len
,int *rparam_len
)
3739 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3740 char *str2
= skip_string(param
,tpscnt
,str1
);
3741 char *p
= skip_string(param
,tpscnt
,str2
);
3748 struct pack_desc desc
;
3749 print_queue_struct
*queue
=NULL
;
3750 print_status_struct status
;
3753 if (!str1
|| !str2
|| !p
) {
3757 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,2,-1);
3759 memset((char *)&desc
,'\0',sizeof(desc
));
3760 memset((char *)&status
,'\0',sizeof(status
));
3762 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel
,SVAL(p
,0)));
3764 /* check it's a supported varient */
3765 if (strcmp(str1
,"WWrLh") != 0) {
3768 if (!check_printjob_info(&desc
,uLevel
,str2
)) {
3772 if(!rap_to_pjobid(SVAL(p
,0), sharename
, &jobid
)) {
3776 snum
= lp_servicenumber( sharename
);
3777 if (snum
< 0 || !VALID_SNUM(snum
)) {
3781 count
= print_queue_status(snum
,&queue
,&status
);
3782 for (i
= 0; i
< count
; i
++) {
3783 if (queue
[i
].job
== jobid
) {
3789 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
3794 desc
.buflen
= mdrcnt
;
3797 * Don't return data but need to get correct length
3798 * init_package will return wrong size if buflen=0
3800 desc
.buflen
= getlen(desc
.format
);
3801 desc
.base
= tmpdata
= (char *)SMB_MALLOC( desc
.buflen
);
3804 if (init_package(&desc
,1,0)) {
3806 fill_printjob_info(conn
,snum
,uLevel
,&desc
,&queue
[i
],i
);
3807 *rdata_len
= desc
.usedlen
;
3809 desc
.errcode
= NERR_JobNotFound
;
3815 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3819 SSVALS(*rparam
,0,desc
.errcode
);
3821 SSVAL(*rparam
,4,desc
.neededlen
);
3826 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc
.errcode
));
3831 static bool api_WPrintJobEnumerate(connection_struct
*conn
, uint16 vuid
,
3832 char *param
, int tpscnt
,
3833 char *data
, int tdscnt
,
3834 int mdrcnt
,int mprcnt
,
3835 char **rdata
,char **rparam
,
3836 int *rdata_len
,int *rparam_len
)
3838 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3839 char *str2
= skip_string(param
,tpscnt
,str1
);
3840 char *p
= skip_string(param
,tpscnt
,str2
);
3846 struct pack_desc desc
;
3847 print_queue_struct
*queue
=NULL
;
3848 print_status_struct status
;
3850 if (!str1
|| !str2
|| !p
) {
3854 memset((char *)&desc
,'\0',sizeof(desc
));
3855 memset((char *)&status
,'\0',sizeof(status
));
3857 p
= skip_string(param
,tpscnt
,p
);
3861 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3863 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel
,name
));
3865 /* check it's a supported variant */
3866 if (strcmp(str1
,"zWrLeh") != 0) {
3871 return False
; /* defined only for uLevel 0,1,2 */
3874 if (!check_printjob_info(&desc
,uLevel
,str2
)) {
3878 snum
= find_service(name
);
3879 if ( !(lp_snum_ok(snum
) && lp_print_ok(snum
)) ) {
3883 count
= print_queue_status(snum
,&queue
,&status
);
3885 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
3891 desc
.buflen
= mdrcnt
;
3893 if (init_package(&desc
,count
,0)) {
3895 for (i
= 0; i
< count
; i
++) {
3896 fill_printjob_info(conn
,snum
,uLevel
,&desc
,&queue
[i
],i
);
3897 if (desc
.errcode
== NERR_Success
) {
3903 *rdata_len
= desc
.usedlen
;
3906 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3910 SSVALS(*rparam
,0,desc
.errcode
);
3912 SSVAL(*rparam
,4,succnt
);
3913 SSVAL(*rparam
,6,count
);
3917 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc
.errcode
));
3922 static int check_printdest_info(struct pack_desc
* desc
,
3923 int uLevel
, char* id
)
3925 desc
->subformat
= NULL
;
3928 desc
->format
= "B9";
3931 desc
->format
= "B9B21WWzW";
3937 desc
->format
= "zzzWWzzzWW";
3940 DEBUG(0,("check_printdest_info: invalid level %d\n",
3944 if (id
== NULL
|| strcmp(desc
->format
,id
) != 0) {
3945 DEBUG(0,("check_printdest_info: invalid string %s\n",
3946 id
? id
: "<NULL>" ));
3952 static void fill_printdest_info(connection_struct
*conn
, int snum
, int uLevel
,
3953 struct pack_desc
* desc
)
3957 strncpy(buf
,SERVICE(snum
),sizeof(buf
)-1);
3958 buf
[sizeof(buf
)-1] = 0;
3962 PACKS(desc
,"B9",buf
); /* szName */
3964 PACKS(desc
,"B21",""); /* szUserName */
3965 PACKI(desc
,"W",0); /* uJobId */
3966 PACKI(desc
,"W",0); /* fsStatus */
3967 PACKS(desc
,"z",""); /* pszStatus */
3968 PACKI(desc
,"W",0); /* time */
3972 if (uLevel
== 2 || uLevel
== 3) {
3973 PACKS(desc
,"z",buf
); /* pszPrinterName */
3975 PACKS(desc
,"z",""); /* pszUserName */
3976 PACKS(desc
,"z",""); /* pszLogAddr */
3977 PACKI(desc
,"W",0); /* uJobId */
3978 PACKI(desc
,"W",0); /* fsStatus */
3979 PACKS(desc
,"z",""); /* pszStatus */
3980 PACKS(desc
,"z",""); /* pszComment */
3981 PACKS(desc
,"z","NULL"); /* pszDrivers */
3982 PACKI(desc
,"W",0); /* time */
3983 PACKI(desc
,"W",0); /* pad1 */
3988 static bool api_WPrintDestGetInfo(connection_struct
*conn
, uint16 vuid
,
3989 char *param
, int tpscnt
,
3990 char *data
, int tdscnt
,
3991 int mdrcnt
,int mprcnt
,
3992 char **rdata
,char **rparam
,
3993 int *rdata_len
,int *rparam_len
)
3995 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3996 char *str2
= skip_string(param
,tpscnt
,str1
);
3997 char *p
= skip_string(param
,tpscnt
,str2
);
3998 char* PrinterName
= p
;
4000 struct pack_desc desc
;
4004 if (!str1
|| !str2
|| !p
) {
4008 memset((char *)&desc
,'\0',sizeof(desc
));
4010 p
= skip_string(param
,tpscnt
,p
);
4014 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4016 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel
,PrinterName
));
4018 /* check it's a supported varient */
4019 if (strcmp(str1
,"zWrLh") != 0) {
4022 if (!check_printdest_info(&desc
,uLevel
,str2
)) {
4026 snum
= find_service(PrinterName
);
4027 if ( !(lp_snum_ok(snum
) && lp_print_ok(snum
)) ) {
4029 desc
.errcode
= NERR_DestNotFound
;
4033 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4038 desc
.buflen
= mdrcnt
;
4041 * Don't return data but need to get correct length
4042 * init_package will return wrong size if buflen=0
4044 desc
.buflen
= getlen(desc
.format
);
4045 desc
.base
= tmpdata
= (char *)SMB_MALLOC( desc
.buflen
);
4047 if (init_package(&desc
,1,0)) {
4048 fill_printdest_info(conn
,snum
,uLevel
,&desc
);
4050 *rdata_len
= desc
.usedlen
;
4054 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4058 SSVALS(*rparam
,0,desc
.errcode
);
4060 SSVAL(*rparam
,4,desc
.neededlen
);
4062 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc
.errcode
));
4068 static bool api_WPrintDestEnum(connection_struct
*conn
, uint16 vuid
,
4069 char *param
, int tpscnt
,
4070 char *data
, int tdscnt
,
4071 int mdrcnt
,int mprcnt
,
4072 char **rdata
,char **rparam
,
4073 int *rdata_len
,int *rparam_len
)
4075 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4076 char *str2
= skip_string(param
,tpscnt
,str1
);
4077 char *p
= skip_string(param
,tpscnt
,str2
);
4081 struct pack_desc desc
;
4082 int services
= lp_numservices();
4084 if (!str1
|| !str2
|| !p
) {
4088 memset((char *)&desc
,'\0',sizeof(desc
));
4090 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4092 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel
));
4094 /* check it's a supported varient */
4095 if (strcmp(str1
,"WrLeh") != 0) {
4098 if (!check_printdest_info(&desc
,uLevel
,str2
)) {
4103 for (i
= 0; i
< services
; i
++) {
4104 if (lp_snum_ok(i
) && lp_print_ok(i
) && lp_browseable(i
)) {
4110 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4117 desc
.buflen
= mdrcnt
;
4118 if (init_package(&desc
,queuecnt
,0)) {
4121 for (i
= 0; i
< services
; i
++) {
4122 if (lp_snum_ok(i
) && lp_print_ok(i
) && lp_browseable(i
)) {
4123 fill_printdest_info(conn
,i
,uLevel
,&desc
);
4125 if (desc
.errcode
== NERR_Success
) {
4132 *rdata_len
= desc
.usedlen
;
4135 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4139 SSVALS(*rparam
,0,desc
.errcode
);
4141 SSVAL(*rparam
,4,succnt
);
4142 SSVAL(*rparam
,6,queuecnt
);
4144 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc
.errcode
));
4149 static bool api_WPrintDriverEnum(connection_struct
*conn
, uint16 vuid
,
4150 char *param
, int tpscnt
,
4151 char *data
, int tdscnt
,
4152 int mdrcnt
,int mprcnt
,
4153 char **rdata
,char **rparam
,
4154 int *rdata_len
,int *rparam_len
)
4156 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4157 char *str2
= skip_string(param
,tpscnt
,str1
);
4158 char *p
= skip_string(param
,tpscnt
,str2
);
4161 struct pack_desc desc
;
4163 if (!str1
|| !str2
|| !p
) {
4167 memset((char *)&desc
,'\0',sizeof(desc
));
4169 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4171 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel
));
4173 /* check it's a supported varient */
4174 if (strcmp(str1
,"WrLeh") != 0) {
4177 if (uLevel
!= 0 || strcmp(str2
,"B41") != 0) {
4182 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4188 desc
.buflen
= mdrcnt
;
4189 if (init_package(&desc
,1,0)) {
4190 PACKS(&desc
,"B41","NULL");
4193 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
4195 *rdata_len
= desc
.usedlen
;
4198 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4202 SSVALS(*rparam
,0,desc
.errcode
);
4204 SSVAL(*rparam
,4,succnt
);
4207 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc
.errcode
));
4212 static bool api_WPrintQProcEnum(connection_struct
*conn
, uint16 vuid
,
4213 char *param
, int tpscnt
,
4214 char *data
, int tdscnt
,
4215 int mdrcnt
,int mprcnt
,
4216 char **rdata
,char **rparam
,
4217 int *rdata_len
,int *rparam_len
)
4219 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4220 char *str2
= skip_string(param
,tpscnt
,str1
);
4221 char *p
= skip_string(param
,tpscnt
,str2
);
4224 struct pack_desc desc
;
4226 if (!str1
|| !str2
|| !p
) {
4229 memset((char *)&desc
,'\0',sizeof(desc
));
4231 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4233 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel
));
4235 /* check it's a supported varient */
4236 if (strcmp(str1
,"WrLeh") != 0) {
4239 if (uLevel
!= 0 || strcmp(str2
,"B13") != 0) {
4244 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4250 desc
.buflen
= mdrcnt
;
4252 if (init_package(&desc
,1,0)) {
4253 PACKS(&desc
,"B13","lpd");
4256 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
4258 *rdata_len
= desc
.usedlen
;
4261 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4265 SSVALS(*rparam
,0,desc
.errcode
);
4267 SSVAL(*rparam
,4,succnt
);
4270 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc
.errcode
));
4275 static bool api_WPrintPortEnum(connection_struct
*conn
, uint16 vuid
,
4276 char *param
, int tpscnt
,
4277 char *data
, int tdscnt
,
4278 int mdrcnt
,int mprcnt
,
4279 char **rdata
,char **rparam
,
4280 int *rdata_len
,int *rparam_len
)
4282 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4283 char *str2
= skip_string(param
,tpscnt
,str1
);
4284 char *p
= skip_string(param
,tpscnt
,str2
);
4287 struct pack_desc desc
;
4289 if (!str1
|| !str2
|| !p
) {
4293 memset((char *)&desc
,'\0',sizeof(desc
));
4295 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4297 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel
));
4299 /* check it's a supported varient */
4300 if (strcmp(str1
,"WrLeh") != 0) {
4303 if (uLevel
!= 0 || strcmp(str2
,"B9") != 0) {
4308 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4313 memset((char *)&desc
,'\0',sizeof(desc
));
4315 desc
.buflen
= mdrcnt
;
4317 if (init_package(&desc
,1,0)) {
4318 PACKS(&desc
,"B13","lp0");
4321 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
4323 *rdata_len
= desc
.usedlen
;
4326 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4330 SSVALS(*rparam
,0,desc
.errcode
);
4332 SSVAL(*rparam
,4,succnt
);
4335 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc
.errcode
));
4340 /****************************************************************************
4342 ****************************************************************************/
4344 static bool api_RNetSessionEnum(connection_struct
*conn
, uint16 vuid
,
4345 char *param
, int tpscnt
,
4346 char *data
, int tdscnt
,
4347 int mdrcnt
,int mprcnt
,
4348 char **rdata
,char **rparam
,
4349 int *rdata_len
,int *rparam_len
)
4352 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4353 char *str2
= skip_string(param
,tpscnt
,str1
);
4354 char *p
= skip_string(param
,tpscnt
,str2
);
4356 struct pack_desc desc
;
4357 struct sessionid
*session_list
;
4358 int i
, num_sessions
;
4360 if (!str1
|| !str2
|| !p
) {
4364 memset((char *)&desc
,'\0',sizeof(desc
));
4366 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4368 DEBUG(3,("RNetSessionEnum uLevel=%d\n",uLevel
));
4369 DEBUG(7,("RNetSessionEnum req string=%s\n",str1
));
4370 DEBUG(7,("RNetSessionEnum ret string=%s\n",str2
));
4372 /* check it's a supported varient */
4373 if (strcmp(str1
,RAP_NetSessionEnum_REQ
) != 0) {
4376 if (uLevel
!= 2 || strcmp(str2
,RAP_SESSION_INFO_L2
) != 0) {
4380 num_sessions
= list_sessions(talloc_tos(), &session_list
);
4383 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4388 memset((char *)&desc
,'\0',sizeof(desc
));
4390 desc
.buflen
= mdrcnt
;
4392 if (!init_package(&desc
,num_sessions
,0)) {
4396 for(i
=0; i
<num_sessions
; i
++) {
4397 PACKS(&desc
, "z", session_list
[i
].remote_machine
);
4398 PACKS(&desc
, "z", session_list
[i
].username
);
4399 PACKI(&desc
, "W", 1); /* num conns */
4400 PACKI(&desc
, "W", 0); /* num opens */
4401 PACKI(&desc
, "W", 1); /* num users */
4402 PACKI(&desc
, "D", 0); /* session time */
4403 PACKI(&desc
, "D", 0); /* idle time */
4404 PACKI(&desc
, "D", 0); /* flags */
4405 PACKS(&desc
, "z", "Unknown Client"); /* client type string */
4408 *rdata_len
= desc
.usedlen
;
4411 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4415 SSVALS(*rparam
,0,desc
.errcode
);
4416 SSVAL(*rparam
,2,0); /* converter */
4417 SSVAL(*rparam
,4,num_sessions
); /* count */
4419 DEBUG(4,("RNetSessionEnum: errorcode %d\n",desc
.errcode
));
4425 /****************************************************************************
4426 The buffer was too small.
4427 ****************************************************************************/
4429 static bool api_TooSmall(connection_struct
*conn
,uint16 vuid
, char *param
, char *data
,
4430 int mdrcnt
, int mprcnt
,
4431 char **rdata
, char **rparam
,
4432 int *rdata_len
, int *rparam_len
)
4434 *rparam_len
= MIN(*rparam_len
,mprcnt
);
4435 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4442 SSVAL(*rparam
,0,NERR_BufTooSmall
);
4444 DEBUG(3,("Supplied buffer too small in API command\n"));
4449 /****************************************************************************
4450 The request is not supported.
4451 ****************************************************************************/
4453 static bool api_Unsupported(connection_struct
*conn
, uint16 vuid
,
4454 char *param
, int tpscnt
,
4455 char *data
, int tdscnt
,
4456 int mdrcnt
, int mprcnt
,
4457 char **rdata
, char **rparam
,
4458 int *rdata_len
, int *rparam_len
)
4461 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4468 SSVAL(*rparam
,0,NERR_notsupported
);
4469 SSVAL(*rparam
,2,0); /* converter word */
4471 DEBUG(3,("Unsupported API command\n"));
4476 static const struct {
4479 bool (*fn
)(connection_struct
*, uint16
,
4482 int,int,char **,char **,int *,int *);
4483 bool auth_user
; /* Deny anonymous access? */
4484 } api_commands
[] = {
4485 {"RNetShareEnum", RAP_WshareEnum
, api_RNetShareEnum
, True
},
4486 {"RNetShareGetInfo", RAP_WshareGetInfo
, api_RNetShareGetInfo
},
4487 {"RNetShareAdd", RAP_WshareAdd
, api_RNetShareAdd
},
4488 {"RNetSessionEnum", RAP_WsessionEnum
, api_RNetSessionEnum
, True
},
4489 {"RNetServerGetInfo", RAP_WserverGetInfo
, api_RNetServerGetInfo
},
4490 {"RNetGroupEnum", RAP_WGroupEnum
, api_RNetGroupEnum
, True
},
4491 {"RNetGroupGetUsers", RAP_WGroupGetUsers
, api_RNetGroupGetUsers
, True
},
4492 {"RNetUserEnum", RAP_WUserEnum
, api_RNetUserEnum
, True
},
4493 {"RNetUserGetInfo", RAP_WUserGetInfo
, api_RNetUserGetInfo
},
4494 {"NetUserGetGroups", RAP_WUserGetGroups
, api_NetUserGetGroups
},
4495 {"NetWkstaGetInfo", RAP_WWkstaGetInfo
, api_NetWkstaGetInfo
},
4496 {"DosPrintQEnum", RAP_WPrintQEnum
, api_DosPrintQEnum
, True
},
4497 {"DosPrintQGetInfo", RAP_WPrintQGetInfo
, api_DosPrintQGetInfo
},
4498 {"WPrintQueuePause", RAP_WPrintQPause
, api_WPrintQueueCtrl
},
4499 {"WPrintQueueResume", RAP_WPrintQContinue
, api_WPrintQueueCtrl
},
4500 {"WPrintJobEnumerate",RAP_WPrintJobEnum
, api_WPrintJobEnumerate
},
4501 {"WPrintJobGetInfo", RAP_WPrintJobGetInfo
, api_WPrintJobGetInfo
},
4502 {"RDosPrintJobDel", RAP_WPrintJobDel
, api_RDosPrintJobDel
},
4503 {"RDosPrintJobPause", RAP_WPrintJobPause
, api_RDosPrintJobDel
},
4504 {"RDosPrintJobResume",RAP_WPrintJobContinue
, api_RDosPrintJobDel
},
4505 {"WPrintDestEnum", RAP_WPrintDestEnum
, api_WPrintDestEnum
},
4506 {"WPrintDestGetInfo", RAP_WPrintDestGetInfo
, api_WPrintDestGetInfo
},
4507 {"NetRemoteTOD", RAP_NetRemoteTOD
, api_NetRemoteTOD
},
4508 {"WPrintQueuePurge", RAP_WPrintQPurge
, api_WPrintQueueCtrl
},
4509 {"NetServerEnum", RAP_NetServerEnum2
, api_RNetServerEnum
}, /* anon OK */
4510 {"WAccessGetUserPerms",RAP_WAccessGetUserPerms
,api_WAccessGetUserPerms
},
4511 {"SetUserPassword", RAP_WUserPasswordSet2
, api_SetUserPassword
},
4512 {"WWkstaUserLogon", RAP_WWkstaUserLogon
, api_WWkstaUserLogon
},
4513 {"PrintJobInfo", RAP_WPrintJobSetInfo
, api_PrintJobInfo
},
4514 {"WPrintDriverEnum", RAP_WPrintDriverEnum
, api_WPrintDriverEnum
},
4515 {"WPrintQProcEnum", RAP_WPrintQProcessorEnum
,api_WPrintQProcEnum
},
4516 {"WPrintPortEnum", RAP_WPrintPortEnum
, api_WPrintPortEnum
},
4517 {"SamOEMChangePassword",RAP_SamOEMChgPasswordUser2_P
,api_SamOEMChangePassword
}, /* anon OK */
4518 {NULL
, -1, api_Unsupported
}
4519 /* The following RAP calls are not implemented by Samba:
4521 RAP_WFileEnum2 - anon not OK
4526 /****************************************************************************
4527 Handle remote api calls.
4528 ****************************************************************************/
4530 void api_reply(connection_struct
*conn
, uint16 vuid
,
4531 struct smb_request
*req
,
4532 char *data
, char *params
,
4533 int tdscnt
, int tpscnt
,
4534 int mdrcnt
, int mprcnt
)
4538 char *rparam
= NULL
;
4539 const char *name1
= NULL
;
4540 const char *name2
= NULL
;
4547 DEBUG(0,("ERROR: NULL params in api_reply()\n"));
4548 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4553 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4556 api_command
= SVAL(params
,0);
4557 /* Is there a string at position params+2 ? */
4558 if (skip_string(params
,tpscnt
,params
+2)) {
4563 name2
= skip_string(params
,tpscnt
,params
+2);
4568 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
4572 tdscnt
,tpscnt
,mdrcnt
,mprcnt
));
4574 for (i
=0;api_commands
[i
].name
;i
++) {
4575 if (api_commands
[i
].id
== api_command
&& api_commands
[i
].fn
) {
4576 DEBUG(3,("Doing %s\n",api_commands
[i
].name
));
4581 /* Check whether this api call can be done anonymously */
4583 if (api_commands
[i
].auth_user
&& lp_restrict_anonymous()) {
4584 user_struct
*user
= get_valid_user_struct(vuid
);
4586 if (!user
|| user
->server_info
->guest
) {
4587 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4592 rdata
= (char *)SMB_MALLOC(1024);
4594 memset(rdata
,'\0',1024);
4597 rparam
= (char *)SMB_MALLOC(1024);
4599 memset(rparam
,'\0',1024);
4602 if(!rdata
|| !rparam
) {
4603 DEBUG(0,("api_reply: malloc fail !\n"));
4606 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4610 reply
= api_commands
[i
].fn(conn
,
4612 params
,tpscnt
, /* params + length */
4613 data
,tdscnt
, /* data + length */
4615 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
4618 if (rdata_len
> mdrcnt
|| rparam_len
> mprcnt
) {
4619 reply
= api_TooSmall(conn
,vuid
,params
,data
,mdrcnt
,mprcnt
,
4620 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
4623 /* if we get False back then it's actually unsupported */
4625 reply
= api_Unsupported(conn
,vuid
,params
,tpscnt
,data
,tdscnt
,mdrcnt
,mprcnt
,
4626 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
4629 /* If api_Unsupported returns false we can't return anything. */
4631 send_trans_reply(conn
, req
, rparam
, rparam_len
,
4632 rdata
, rdata_len
, False
);