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
35 #define NERR_Success 0
36 #define NERR_badpass 86
37 #define NERR_notsupported 50
39 #define NERR_BASE (2100)
40 #define NERR_BufTooSmall (NERR_BASE+23)
41 #define NERR_JobNotFound (NERR_BASE+51)
42 #define NERR_DestNotFound (NERR_BASE+52)
44 #define ACCESS_READ 0x01
45 #define ACCESS_WRITE 0x02
46 #define ACCESS_CREATE 0x04
48 #define SHPWLEN 8 /* share password length */
50 /* Limit size of ipc replies */
52 static char *smb_realloc_limit(void *ptr
, size_t size
)
56 size
= MAX((size
),4*1024);
57 val
= (char *)SMB_REALLOC(ptr
,size
);
59 memset(val
,'\0',size
);
64 static bool api_Unsupported(connection_struct
*conn
, uint16 vuid
,
65 char *param
, int tpscnt
,
66 char *data
, int tdscnt
,
67 int mdrcnt
, int mprcnt
,
68 char **rdata
, char **rparam
,
69 int *rdata_len
, int *rparam_len
);
71 static bool api_TooSmall(connection_struct
*conn
, uint16 vuid
, char *param
, char *data
,
72 int mdrcnt
, int mprcnt
,
73 char **rdata
, char **rparam
,
74 int *rdata_len
, int *rparam_len
);
77 static int CopyExpanded(connection_struct
*conn
,
78 int snum
, char **dst
, char *src
, int *p_space_remaining
)
80 TALLOC_CTX
*ctx
= talloc_tos();
84 if (!src
|| !dst
|| !p_space_remaining
|| !(*dst
) ||
85 *p_space_remaining
<= 0) {
89 buf
= talloc_strdup(ctx
, src
);
91 *p_space_remaining
= 0;
94 buf
= talloc_string_sub(ctx
, buf
,"%S",lp_servicename(snum
));
96 *p_space_remaining
= 0;
99 buf
= talloc_sub_advanced(ctx
,
100 lp_servicename(SNUM(conn
)),
101 conn
->server_info
->unix_name
,
103 conn
->server_info
->utok
.gid
,
104 conn
->server_info
->sanitized_username
,
105 pdb_get_domain(conn
->server_info
->sam_account
),
108 *p_space_remaining
= 0;
111 l
= push_ascii(*dst
,buf
,*p_space_remaining
, STR_TERMINATE
);
116 (*p_space_remaining
) -= l
;
120 static int CopyAndAdvance(char **dst
, char *src
, int *n
)
123 if (!src
|| !dst
|| !n
|| !(*dst
)) {
126 l
= push_ascii(*dst
,src
,*n
, STR_TERMINATE
);
135 static int StrlenExpanded(connection_struct
*conn
, int snum
, char *s
)
137 TALLOC_CTX
*ctx
= talloc_tos();
142 buf
= talloc_strdup(ctx
,s
);
146 buf
= talloc_string_sub(ctx
,buf
,"%S",lp_servicename(snum
));
150 buf
= talloc_sub_advanced(ctx
,
151 lp_servicename(SNUM(conn
)),
152 conn
->server_info
->unix_name
,
154 conn
->server_info
->utok
.gid
,
155 conn
->server_info
->sanitized_username
,
156 pdb_get_domain(conn
->server_info
->sam_account
),
161 return strlen(buf
) + 1;
164 static char *Expand(connection_struct
*conn
, int snum
, char *s
)
166 TALLOC_CTX
*ctx
= talloc_tos();
172 buf
= talloc_strdup(ctx
,s
);
176 buf
= talloc_string_sub(ctx
,buf
,"%S",lp_servicename(snum
));
180 return talloc_sub_advanced(ctx
,
181 lp_servicename(SNUM(conn
)),
182 conn
->server_info
->unix_name
,
184 conn
->server_info
->utok
.gid
,
185 conn
->server_info
->sanitized_username
,
186 pdb_get_domain(conn
->server_info
->sam_account
),
190 /*******************************************************************
191 Check a API string for validity when we only need to check the prefix.
192 ******************************************************************/
194 static bool prefix_ok(const char *str
, const char *prefix
)
196 return(strncmp(str
,prefix
,strlen(prefix
)) == 0);
200 const char *format
; /* formatstring for structure */
201 const char *subformat
; /* subformat for structure */
202 char *base
; /* baseaddress of buffer */
203 int buflen
; /* remaining size for fixed part; on init: length of base */
204 int subcount
; /* count of substructures */
205 char *structbuf
; /* pointer into buffer for remaining fixed part */
206 int stringlen
; /* remaining size for variable part */
207 char *stringbuf
; /* pointer into buffer for remaining variable part */
208 int neededlen
; /* total needed size */
209 int usedlen
; /* total used size (usedlen <= neededlen and usedlen <= buflen) */
210 const char *curpos
; /* current position; pointer into format or subformat */
214 static int get_counter(const char **p
)
220 if (!isdigit((int)**p
)) {
226 n
= 10 * n
+ (i
- '0');
234 static int getlen(const char *p
)
243 case 'W': /* word (2 byte) */
246 case 'K': /* status word? (2 byte) */
249 case 'N': /* count of substructures (word) at end */
252 case 'D': /* double word (4 byte) */
253 case 'z': /* offset to zero terminated string (4 byte) */
254 case 'l': /* offset to user data (4 byte) */
257 case 'b': /* offset to data (with counter) (4 byte) */
261 case 'B': /* byte (with optional counter) */
262 n
+= get_counter(&p
);
269 static bool init_package(struct pack_desc
*p
, int count
, int subcount
)
274 if (!p
->format
|| !p
->base
) {
278 i
= count
* getlen(p
->format
);
280 i
+= subcount
* getlen(p
->subformat
);
282 p
->structbuf
= p
->base
;
286 p
->curpos
= p
->format
;
292 * This is the old error code we used. Aparently
293 * WinNT/2k systems return ERRbuftoosmall (2123) and
294 * OS/2 needs this. I'm leaving this here so we can revert
297 p
->errcode
= ERRmoredata
;
299 p
->errcode
= ERRbuftoosmall
;
302 p
->errcode
= NERR_Success
;
306 p
->stringbuf
= p
->base
+ i
;
308 return (p
->errcode
== NERR_Success
);
311 static int package(struct pack_desc
*p
, ...)
314 int needed
=0, stringneeded
;
315 const char *str
=NULL
;
316 int is_string
=0, stringused
;
323 p
->curpos
= p
->format
;
325 p
->curpos
= p
->subformat
;
330 str
= va_arg(args
,char*);
331 SMB_ASSERT(strncmp(str
,p
->curpos
,strlen(str
)) == 0);
340 switch( *p
->curpos
++ ) {
341 case 'W': /* word (2 byte) */
343 temp
= va_arg(args
,int);
344 if (p
->buflen
>= needed
) {
345 SSVAL(p
->structbuf
,0,temp
);
348 case 'K': /* status word? (2 byte) */
350 temp
= va_arg(args
,int);
351 if (p
->buflen
>= needed
) {
352 SSVAL(p
->structbuf
,0,temp
);
355 case 'N': /* count of substructures (word) at end */
357 p
->subcount
= va_arg(args
,int);
358 if (p
->buflen
>= needed
) {
359 SSVAL(p
->structbuf
,0,p
->subcount
);
362 case 'D': /* double word (4 byte) */
364 temp
= va_arg(args
,int);
365 if (p
->buflen
>= needed
) {
366 SIVAL(p
->structbuf
,0,temp
);
369 case 'B': /* byte (with optional counter) */
370 needed
= get_counter(&p
->curpos
);
372 char *s
= va_arg(args
,char*);
373 if (p
->buflen
>= needed
) {
374 StrnCpy(p
->structbuf
,s
?s
:"",needed
-1);
378 case 'z': /* offset to zero terminated string (4 byte) */
379 str
= va_arg(args
,char*);
380 stringneeded
= (str
? strlen(str
)+1 : 0);
383 case 'l': /* offset to user data (4 byte) */
384 str
= va_arg(args
,char*);
385 stringneeded
= va_arg(args
,int);
388 case 'b': /* offset to data (with counter) (4 byte) */
389 str
= va_arg(args
,char*);
390 stringneeded
= get_counter(&p
->curpos
);
396 if (stringneeded
>= 0) {
398 if (p
->buflen
>= needed
) {
399 stringused
= stringneeded
;
400 if (stringused
> p
->stringlen
) {
401 stringused
= (is_string
? p
->stringlen
: 0);
402 if (p
->errcode
== NERR_Success
) {
403 p
->errcode
= ERRmoredata
;
407 SIVAL(p
->structbuf
,0,0);
409 SIVAL(p
->structbuf
,0,PTR_DIFF(p
->stringbuf
,p
->base
));
410 memcpy(p
->stringbuf
,str
?str
:"",stringused
);
412 p
->stringbuf
[stringused
-1] = '\0';
414 p
->stringbuf
+= stringused
;
415 p
->stringlen
-= stringused
;
416 p
->usedlen
+= stringused
;
419 p
->neededlen
+= stringneeded
;
422 p
->neededlen
+= needed
;
423 if (p
->buflen
>= needed
) {
424 p
->structbuf
+= needed
;
426 p
->usedlen
+= needed
;
428 if (p
->errcode
== NERR_Success
) {
429 p
->errcode
= ERRmoredata
;
436 #define PACK(desc,t,v) package(desc,t,v,0,0,0,0)
437 #define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0)
439 #define PACK(desc,t,v) package(desc,v)
440 #define PACKl(desc,t,v,l) package(desc,v,l)
443 static void PACKI(struct pack_desc
* desc
, const char *t
,int v
)
448 static void PACKS(struct pack_desc
* desc
,const char *t
,const char *v
)
453 /****************************************************************************
455 ****************************************************************************/
457 static void PackDriverData(struct pack_desc
* desc
)
459 char drivdata
[4+4+32];
460 SIVAL(drivdata
,0,sizeof drivdata
); /* cb */
461 SIVAL(drivdata
,4,1000); /* lVersion */
462 memset(drivdata
+8,0,32); /* szDeviceName */
463 push_ascii(drivdata
+8,"NULL",32, STR_TERMINATE
);
464 PACKl(desc
,"l",drivdata
,sizeof drivdata
); /* pDriverData */
467 static int check_printq_info(struct pack_desc
* desc
,
468 unsigned int uLevel
, char *id1
, char *id2
)
470 desc
->subformat
= NULL
;
473 desc
->format
= "B13";
476 desc
->format
= "B13BWWWzzzzzWW";
479 desc
->format
= "B13BWWWzzzzzWN";
480 desc
->subformat
= "WB21BB16B10zWWzDDz";
483 desc
->format
= "zWWWWzzzzWWzzl";
486 desc
->format
= "zWWWWzzzzWNzzl";
487 desc
->subformat
= "WWzWWDDzz";
496 desc
->format
= "WzzzzzzzzN";
497 desc
->subformat
= "z";
500 DEBUG(0,("check_printq_info: invalid level %d\n",
504 if (id1
== NULL
|| strcmp(desc
->format
,id1
) != 0) {
505 DEBUG(0,("check_printq_info: invalid format %s\n",
506 id1
? id1
: "<NULL>" ));
509 if (desc
->subformat
&& (id2
== NULL
|| strcmp(desc
->subformat
,id2
) != 0)) {
510 DEBUG(0,("check_printq_info: invalid subformat %s\n",
511 id2
? id2
: "<NULL>" ));
518 #define RAP_JOB_STATUS_QUEUED 0
519 #define RAP_JOB_STATUS_PAUSED 1
520 #define RAP_JOB_STATUS_SPOOLING 2
521 #define RAP_JOB_STATUS_PRINTING 3
522 #define RAP_JOB_STATUS_PRINTED 4
524 #define RAP_QUEUE_STATUS_PAUSED 1
525 #define RAP_QUEUE_STATUS_ERROR 2
527 /* turn a print job status into a on the wire status
529 static int printj_status(int v
)
533 return RAP_JOB_STATUS_QUEUED
;
535 return RAP_JOB_STATUS_PAUSED
;
537 return RAP_JOB_STATUS_SPOOLING
;
539 return RAP_JOB_STATUS_PRINTING
;
544 /* turn a print queue status into a on the wire status
546 static int printq_status(int v
)
552 return RAP_QUEUE_STATUS_PAUSED
;
554 return RAP_QUEUE_STATUS_ERROR
;
557 static void fill_printjob_info(connection_struct
*conn
, int snum
, int uLevel
,
558 struct pack_desc
*desc
,
559 print_queue_struct
*queue
, int n
)
561 time_t t
= queue
->time
;
563 /* the client expects localtime */
564 t
-= get_time_zone(t
);
566 PACKI(desc
,"W",pjobid_to_rap(lp_const_servicename(snum
),queue
->job
)); /* uJobId */
568 PACKS(desc
,"B21",queue
->fs_user
); /* szUserName */
569 PACKS(desc
,"B",""); /* pad */
570 PACKS(desc
,"B16",""); /* szNotifyName */
571 PACKS(desc
,"B10","PM_Q_RAW"); /* szDataType */
572 PACKS(desc
,"z",""); /* pszParms */
573 PACKI(desc
,"W",n
+1); /* uPosition */
574 PACKI(desc
,"W",printj_status(queue
->status
)); /* fsStatus */
575 PACKS(desc
,"z",""); /* pszStatus */
576 PACKI(desc
,"D",t
); /* ulSubmitted */
577 PACKI(desc
,"D",queue
->size
); /* ulSize */
578 PACKS(desc
,"z",queue
->fs_file
); /* pszComment */
580 if (uLevel
== 2 || uLevel
== 3 || uLevel
== 4) {
581 PACKI(desc
,"W",queue
->priority
); /* uPriority */
582 PACKS(desc
,"z",queue
->fs_user
); /* pszUserName */
583 PACKI(desc
,"W",n
+1); /* uPosition */
584 PACKI(desc
,"W",printj_status(queue
->status
)); /* fsStatus */
585 PACKI(desc
,"D",t
); /* ulSubmitted */
586 PACKI(desc
,"D",queue
->size
); /* ulSize */
587 PACKS(desc
,"z","Samba"); /* pszComment */
588 PACKS(desc
,"z",queue
->fs_file
); /* pszDocument */
590 PACKS(desc
,"z",""); /* pszNotifyName */
591 PACKS(desc
,"z","PM_Q_RAW"); /* pszDataType */
592 PACKS(desc
,"z",""); /* pszParms */
593 PACKS(desc
,"z",""); /* pszStatus */
594 PACKS(desc
,"z",SERVICE(snum
)); /* pszQueue */
595 PACKS(desc
,"z","lpd"); /* pszQProcName */
596 PACKS(desc
,"z",""); /* pszQProcParms */
597 PACKS(desc
,"z","NULL"); /* pszDriverName */
598 PackDriverData(desc
); /* pDriverData */
599 PACKS(desc
,"z",""); /* pszPrinterName */
600 } else if (uLevel
== 4) { /* OS2 */
601 PACKS(desc
,"z",""); /* pszSpoolFileName */
602 PACKS(desc
,"z",""); /* pszPortName */
603 PACKS(desc
,"z",""); /* pszStatus */
604 PACKI(desc
,"D",0); /* ulPagesSpooled */
605 PACKI(desc
,"D",0); /* ulPagesSent */
606 PACKI(desc
,"D",0); /* ulPagesPrinted */
607 PACKI(desc
,"D",0); /* ulTimePrinted */
608 PACKI(desc
,"D",0); /* ulExtendJobStatus */
609 PACKI(desc
,"D",0); /* ulStartPage */
610 PACKI(desc
,"D",0); /* ulEndPage */
615 /********************************************************************
616 Return a driver name given an snum.
617 Returns True if from tdb, False otherwise.
618 ********************************************************************/
620 static bool get_driver_name(int snum
, char **pp_drivername
)
622 NT_PRINTER_INFO_LEVEL
*info
= NULL
;
625 get_a_printer (NULL
, &info
, 2, lp_servicename(snum
));
627 *pp_drivername
= talloc_strdup(talloc_tos(),
628 info
->info_2
->drivername
);
630 free_a_printer(&info
, 2);
631 if (!*pp_drivername
) {
639 /********************************************************************
640 Respond to the DosPrintQInfo command with a level of 52
641 This is used to get printer driver information for Win9x clients
642 ********************************************************************/
643 static void fill_printq_info_52(connection_struct
*conn
, int snum
,
644 struct pack_desc
* desc
, int count
)
648 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
649 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
653 if ( !W_ERROR_IS_OK(get_a_printer( NULL
, &printer
, 2, lp_servicename(snum
))) ) {
654 DEBUG(3,("fill_printq_info_52: Failed to lookup printer [%s]\n",
655 lp_servicename(snum
)));
659 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
,
662 DEBUG(3,("fill_printq_info_52: Failed to lookup driver [%s]\n",
663 printer
->info_2
->drivername
));
667 trim_string(driver
.info_3
->driverpath
, "\\print$\\WIN40\\0\\", 0);
668 trim_string(driver
.info_3
->datafile
, "\\print$\\WIN40\\0\\", 0);
669 trim_string(driver
.info_3
->helpfile
, "\\print$\\WIN40\\0\\", 0);
671 PACKI(desc
, "W", 0x0400); /* don't know */
672 PACKS(desc
, "z", driver
.info_3
->name
); /* long printer name */
673 PACKS(desc
, "z", driver
.info_3
->driverpath
); /* Driverfile Name */
674 PACKS(desc
, "z", driver
.info_3
->datafile
); /* Datafile name */
675 PACKS(desc
, "z", driver
.info_3
->monitorname
); /* language monitor */
677 fstrcpy(location
, "\\\\%L\\print$\\WIN40\\0");
678 standard_sub_basic( "", "", location
, sizeof(location
)-1 );
679 PACKS(desc
,"z", location
); /* share to retrieve files */
681 PACKS(desc
,"z", driver
.info_3
->defaultdatatype
); /* default data type */
682 PACKS(desc
,"z", driver
.info_3
->helpfile
); /* helpfile name */
683 PACKS(desc
,"z", driver
.info_3
->driverpath
); /* driver name */
685 DEBUG(3,("Printer Driver Name: %s:\n",driver
.info_3
->name
));
686 DEBUG(3,("Driver: %s:\n",driver
.info_3
->driverpath
));
687 DEBUG(3,("Data File: %s:\n",driver
.info_3
->datafile
));
688 DEBUG(3,("Language Monitor: %s:\n",driver
.info_3
->monitorname
));
689 DEBUG(3,("Driver Location: %s:\n",location
));
690 DEBUG(3,("Data Type: %s:\n",driver
.info_3
->defaultdatatype
));
691 DEBUG(3,("Help File: %s:\n",driver
.info_3
->helpfile
));
692 PACKI(desc
,"N",count
); /* number of files to copy */
694 for ( i
=0; i
<count
&& driver
.info_3
->dependentfiles
&& *driver
.info_3
->dependentfiles
[i
]; i
++)
696 trim_string(driver
.info_3
->dependentfiles
[i
], "\\print$\\WIN40\\0\\", 0);
697 PACKS(desc
,"z",driver
.info_3
->dependentfiles
[i
]); /* driver files to copy */
698 DEBUG(3,("Dependent File: %s:\n",driver
.info_3
->dependentfiles
[i
]));
703 DEBUG(3,("fill_printq_info_52: file count specified by client [%d] != number of dependent files [%i]\n",
706 DEBUG(3,("fill_printq_info on <%s> gave %d entries\n", SERVICE(snum
),i
));
708 desc
->errcode
=NERR_Success
;
712 DEBUG(3,("fill_printq_info: Can't supply driver files\n"));
713 desc
->errcode
=NERR_notsupported
;
717 free_a_printer( &printer
, 2 );
720 free_a_printer_driver( driver
, 3 );
724 static void fill_printq_info(connection_struct
*conn
, int snum
, int uLevel
,
725 struct pack_desc
* desc
,
726 int count
, print_queue_struct
* queue
,
727 print_status_struct
* status
)
732 PACKS(desc
,"B13",SERVICE(snum
));
737 PACKS(desc
,"z",Expand(conn
,snum
,SERVICE(snum
)));
740 PACKI(desc
,"K",printq_status(status
->status
));
744 if (uLevel
== 1 || uLevel
== 2) {
745 PACKS(desc
,"B",""); /* alignment */
746 PACKI(desc
,"W",5); /* priority */
747 PACKI(desc
,"W",0); /* start time */
748 PACKI(desc
,"W",0); /* until time */
749 PACKS(desc
,"z",""); /* pSepFile */
750 PACKS(desc
,"z","lpd"); /* pPrProc */
751 PACKS(desc
,"z",SERVICE(snum
)); /* pDestinations */
752 PACKS(desc
,"z",""); /* pParms */
754 PACKS(desc
,"z","UNKNOWN PRINTER");
755 PACKI(desc
,"W",LPSTAT_ERROR
);
757 else if (!status
|| !status
->message
[0]) {
758 PACKS(desc
,"z",Expand(conn
,snum
,lp_comment(snum
)));
759 PACKI(desc
,"W",LPSTAT_OK
); /* status */
761 PACKS(desc
,"z",status
->message
);
762 PACKI(desc
,"W",printq_status(status
->status
)); /* status */
764 PACKI(desc
,(uLevel
== 1 ? "W" : "N"),count
);
767 if (uLevel
== 3 || uLevel
== 4) {
768 char *drivername
= NULL
;
770 PACKI(desc
,"W",5); /* uPriority */
771 PACKI(desc
,"W",0); /* uStarttime */
772 PACKI(desc
,"W",0); /* uUntiltime */
773 PACKI(desc
,"W",5); /* pad1 */
774 PACKS(desc
,"z",""); /* pszSepFile */
775 PACKS(desc
,"z","WinPrint"); /* pszPrProc */
776 PACKS(desc
,"z",NULL
); /* pszParms */
777 PACKS(desc
,"z",NULL
); /* pszComment - don't ask.... JRA */
778 /* "don't ask" that it's done this way to fix corrupted
779 Win9X/ME printer comments. */
781 PACKI(desc
,"W",LPSTAT_OK
); /* fsStatus */
783 PACKI(desc
,"W",printq_status(status
->status
)); /* fsStatus */
785 PACKI(desc
,(uLevel
== 3 ? "W" : "N"),count
); /* cJobs */
786 PACKS(desc
,"z",SERVICE(snum
)); /* pszPrinters */
787 get_driver_name(snum
,&drivername
);
791 PACKS(desc
,"z",drivername
); /* pszDriverName */
792 PackDriverData(desc
); /* pDriverData */
795 if (uLevel
== 2 || uLevel
== 4) {
797 for (i
=0;i
<count
;i
++)
798 fill_printjob_info(conn
,snum
,uLevel
== 2 ? 1 : 2,desc
,&queue
[i
],i
);
802 fill_printq_info_52( conn
, snum
, desc
, count
);
805 /* This function returns the number of files for a given driver */
806 static int get_printerdrivernumber(int snum
)
809 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
810 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
814 if ( !W_ERROR_IS_OK(get_a_printer( NULL
, &printer
, 2, lp_servicename(snum
))) ) {
815 DEBUG(3,("get_printerdrivernumber: Failed to lookup printer [%s]\n",
816 lp_servicename(snum
)));
820 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
,
823 DEBUG(3,("get_printerdrivernumber: Failed to lookup driver [%s]\n",
824 printer
->info_2
->drivername
));
828 /* count the number of files */
829 while ( driver
.info_3
->dependentfiles
&& *driver
.info_3
->dependentfiles
[result
] )
834 free_a_printer( &printer
, 2 );
837 free_a_printer_driver( driver
, 3 );
842 static bool api_DosPrintQGetInfo(connection_struct
*conn
, uint16 vuid
,
843 char *param
, int tpscnt
,
844 char *data
, int tdscnt
,
845 int mdrcnt
,int mprcnt
,
846 char **rdata
,char **rparam
,
847 int *rdata_len
,int *rparam_len
)
849 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
850 char *str2
= skip_string(param
,tpscnt
,str1
);
851 char *p
= skip_string(param
,tpscnt
,str2
);
857 struct pack_desc desc
;
858 print_queue_struct
*queue
=NULL
;
859 print_status_struct status
;
862 if (!str1
|| !str2
|| !p
) {
865 memset((char *)&status
,'\0',sizeof(status
));
866 memset((char *)&desc
,'\0',sizeof(desc
));
868 p
= skip_string(param
,tpscnt
,p
);
872 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
873 str3
= get_safe_str_ptr(param
,tpscnt
,p
,4);
874 /* str3 may be null here and is checked in check_printq_info(). */
876 /* remove any trailing username */
877 if ((p
= strchr_m(QueueName
,'%')))
880 DEBUG(3,("api_DosPrintQGetInfo uLevel=%d name=%s\n",uLevel
,QueueName
));
882 /* check it's a supported varient */
883 if (!prefix_ok(str1
,"zWrLh"))
885 if (!check_printq_info(&desc
,uLevel
,str2
,str3
)) {
887 * Patch from Scott Moomaw <scott@bridgewater.edu>
888 * to return the 'invalid info level' error if an
889 * unknown level was requested.
893 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
897 SSVALS(*rparam
,0,ERRunknownlevel
);
903 snum
= find_service(QueueName
);
904 if ( !(lp_snum_ok(snum
) && lp_print_ok(snum
)) )
908 count
= get_printerdrivernumber(snum
);
909 DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count
));
911 count
= print_queue_status(snum
, &queue
,&status
);
915 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
921 desc
.buflen
= mdrcnt
;
924 * Don't return data but need to get correct length
925 * init_package will return wrong size if buflen=0
927 desc
.buflen
= getlen(desc
.format
);
928 desc
.base
= tmpdata
= (char *) SMB_MALLOC (desc
.buflen
);
931 if (init_package(&desc
,1,count
)) {
932 desc
.subcount
= count
;
933 fill_printq_info(conn
,snum
,uLevel
,&desc
,count
,queue
,&status
);
936 *rdata_len
= desc
.usedlen
;
939 * We must set the return code to ERRbuftoosmall
940 * in order to support lanman style printing with Win NT/2k
943 if (!mdrcnt
&& lp_disable_spoolss())
944 desc
.errcode
= ERRbuftoosmall
;
946 *rdata_len
= desc
.usedlen
;
948 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
954 SSVALS(*rparam
,0,desc
.errcode
);
956 SSVAL(*rparam
,4,desc
.neededlen
);
958 DEBUG(4,("printqgetinfo: errorcode %d\n",desc
.errcode
));
966 /****************************************************************************
967 View list of all print jobs on all queues.
968 ****************************************************************************/
970 static bool api_DosPrintQEnum(connection_struct
*conn
, uint16 vuid
,
971 char *param
, int tpscnt
,
972 char *data
, int tdscnt
,
973 int mdrcnt
, int mprcnt
,
974 char **rdata
, char** rparam
,
975 int *rdata_len
, int *rparam_len
)
977 char *param_format
= get_safe_str_ptr(param
,tpscnt
,param
,2);
978 char *output_format1
= skip_string(param
,tpscnt
,param_format
);
979 char *p
= skip_string(param
,tpscnt
,output_format1
);
980 unsigned int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
981 char *output_format2
= get_safe_str_ptr(param
,tpscnt
,p
,4);
982 int services
= lp_numservices();
984 struct pack_desc desc
;
985 print_queue_struct
**queue
= NULL
;
986 print_status_struct
*status
= NULL
;
987 int *subcntarr
= NULL
;
988 int queuecnt
= 0, subcnt
= 0, succnt
= 0;
990 if (!param_format
|| !output_format1
|| !p
) {
994 memset((char *)&desc
,'\0',sizeof(desc
));
996 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel
));
998 if (!prefix_ok(param_format
,"WrLeh")) {
1001 if (!check_printq_info(&desc
,uLevel
,output_format1
,output_format2
)) {
1003 * Patch from Scott Moomaw <scott@bridgewater.edu>
1004 * to return the 'invalid info level' error if an
1005 * unknown level was requested.
1009 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1013 SSVALS(*rparam
,0,ERRunknownlevel
);
1019 for (i
= 0; i
< services
; i
++) {
1020 if (lp_snum_ok(i
) && lp_print_ok(i
) && lp_browseable(i
)) {
1025 if((queue
= SMB_MALLOC_ARRAY(print_queue_struct
*, queuecnt
)) == NULL
) {
1026 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
1029 memset(queue
,0,queuecnt
*sizeof(print_queue_struct
*));
1030 if((status
= SMB_MALLOC_ARRAY(print_status_struct
,queuecnt
)) == NULL
) {
1031 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
1034 memset(status
,0,queuecnt
*sizeof(print_status_struct
));
1035 if((subcntarr
= SMB_MALLOC_ARRAY(int,queuecnt
)) == NULL
) {
1036 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
1042 for (i
= 0; i
< services
; i
++) {
1043 if (lp_snum_ok(i
) && lp_print_ok(i
) && lp_browseable(i
)) {
1044 subcntarr
[n
] = print_queue_status(i
, &queue
[n
],&status
[n
]);
1045 subcnt
+= subcntarr
[n
];
1051 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
1057 desc
.buflen
= mdrcnt
;
1059 if (init_package(&desc
,queuecnt
,subcnt
)) {
1062 for (i
= 0; i
< services
; i
++) {
1063 if (lp_snum_ok(i
) && lp_print_ok(i
) && lp_browseable(i
)) {
1064 fill_printq_info(conn
,i
,uLevel
,&desc
,subcntarr
[n
],queue
[n
],&status
[n
]);
1066 if (desc
.errcode
== NERR_Success
) {
1073 SAFE_FREE(subcntarr
);
1075 *rdata_len
= desc
.usedlen
;
1077 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1081 SSVALS(*rparam
,0,desc
.errcode
);
1083 SSVAL(*rparam
,4,succnt
);
1084 SSVAL(*rparam
,6,queuecnt
);
1086 for (i
= 0; i
< queuecnt
; i
++) {
1088 SAFE_FREE(queue
[i
]);
1099 SAFE_FREE(subcntarr
);
1100 for (i
= 0; i
< queuecnt
; i
++) {
1102 SAFE_FREE(queue
[i
]);
1111 /****************************************************************************
1112 Get info level for a server list query.
1113 ****************************************************************************/
1115 static bool check_server_info(int uLevel
, char* id
)
1119 if (strcmp(id
,"B16") != 0) {
1124 if (strcmp(id
,"B16BBDz") != 0) {
1134 struct srv_info_struct
{
1142 /*******************************************************************
1143 Get server info lists from the files saved by nmbd. Return the
1145 ******************************************************************/
1147 static int get_server_info(uint32 servertype
,
1148 struct srv_info_struct
**servers
,
1154 bool local_list_only
;
1157 lines
= file_lines_load(lock_path(SERVER_LIST
), NULL
, 0);
1159 DEBUG(4,("Can't open %s - %s\n",lock_path(SERVER_LIST
),strerror(errno
)));
1163 /* request for everything is code for request all servers */
1164 if (servertype
== SV_TYPE_ALL
) {
1165 servertype
&= ~(SV_TYPE_DOMAIN_ENUM
|SV_TYPE_LOCAL_LIST_ONLY
);
1168 local_list_only
= (servertype
& SV_TYPE_LOCAL_LIST_ONLY
);
1170 DEBUG(4,("Servertype search: %8x\n",servertype
));
1172 for (i
=0;lines
[i
];i
++) {
1174 struct srv_info_struct
*s
;
1175 const char *ptr
= lines
[i
];
1177 TALLOC_CTX
*frame
= NULL
;
1184 if (count
== alloced
) {
1186 *servers
= SMB_REALLOC_ARRAY(*servers
,struct srv_info_struct
, alloced
);
1188 DEBUG(0,("get_server_info: failed to enlarge servers info struct!\n"));
1189 file_lines_free(lines
);
1192 memset((char *)((*servers
)+count
),'\0',sizeof(**servers
)*(alloced
-count
));
1194 s
= &(*servers
)[count
];
1196 frame
= talloc_stackframe();
1198 if (!next_token_talloc(frame
,&ptr
,&p
, NULL
)) {
1202 fstrcpy(s
->name
, p
);
1205 if (!next_token_talloc(frame
,&ptr
, &p
, NULL
)) {
1211 s
->comment
[0] = '\0';
1212 if (!next_token_talloc(frame
,&ptr
, &p
, NULL
)) {
1216 fstrcpy(s
->comment
, p
);
1217 string_truncate(s
->comment
, MAX_SERVER_STRING_LENGTH
);
1219 s
->domain
[0] = '\0';
1220 if (!next_token_talloc(frame
,&ptr
,&p
, NULL
)) {
1221 /* this allows us to cope with an old nmbd */
1222 fstrcpy(s
->domain
,lp_workgroup());
1224 fstrcpy(s
->domain
, p
);
1228 if (sscanf(stype
,"%X",&s
->type
) != 1) {
1229 DEBUG(4,("r:host file "));
1233 /* Filter the servers/domains we return based on what was asked for. */
1235 /* Check to see if we are being asked for a local list only. */
1236 if(local_list_only
&& ((s
->type
& SV_TYPE_LOCAL_LIST_ONLY
) == 0)) {
1237 DEBUG(4,("r: local list only"));
1241 /* doesn't match up: don't want it */
1242 if (!(servertype
& s
->type
)) {
1243 DEBUG(4,("r:serv type "));
1247 if ((servertype
& SV_TYPE_DOMAIN_ENUM
) !=
1248 (s
->type
& SV_TYPE_DOMAIN_ENUM
)) {
1249 DEBUG(4,("s: dom mismatch "));
1253 if (!strequal(domain
, s
->domain
) && !(servertype
& SV_TYPE_DOMAIN_ENUM
)) {
1257 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
1258 s
->type
&= ~SV_TYPE_LOCAL_LIST_ONLY
;
1261 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
1262 s
->name
, s
->type
, s
->comment
, s
->domain
));
1263 s
->server_added
= True
;
1266 DEBUG(4,("%20s %8x %25s %15s\n",
1267 s
->name
, s
->type
, s
->comment
, s
->domain
));
1271 file_lines_free(lines
);
1275 /*******************************************************************
1276 Fill in a server info structure.
1277 ******************************************************************/
1279 static int fill_srv_info(struct srv_info_struct
*service
,
1280 int uLevel
, char **buf
, int *buflen
,
1281 char **stringbuf
, int *stringspace
, char *baseaddr
)
1304 len
= strlen(service
->comment
)+1;
1308 *buflen
= struct_len
;
1310 return struct_len
+ len
;
1315 if (*buflen
< struct_len
) {
1322 p2
= p
+ struct_len
;
1323 l2
= *buflen
- struct_len
;
1331 push_ascii(p
,service
->name
, MAX_NETBIOSNAME_LEN
, STR_TERMINATE
);
1335 push_ascii(p
,service
->name
,MAX_NETBIOSNAME_LEN
, STR_TERMINATE
);
1336 SIVAL(p
,18,service
->type
);
1337 SIVAL(p
,22,PTR_DIFF(p2
,baseaddr
));
1338 len
+= CopyAndAdvance(&p2
,service
->comment
,&l2
);
1343 *buf
= p
+ struct_len
;
1344 *buflen
-= struct_len
;
1355 static int srv_comp(struct srv_info_struct
*s1
,struct srv_info_struct
*s2
)
1357 return(strcmp(s1
->name
,s2
->name
));
1360 /****************************************************************************
1361 View list of servers available (or possibly domains). The info is
1362 extracted from lists saved by nmbd on the local host.
1363 ****************************************************************************/
1365 static bool api_RNetServerEnum(connection_struct
*conn
, uint16 vuid
,
1366 char *param
, int tpscnt
,
1367 char *data
, int tdscnt
,
1368 int mdrcnt
, int mprcnt
, char **rdata
,
1369 char **rparam
, int *rdata_len
, int *rparam_len
)
1371 char *str1
= get_safe_str_ptr(param
, tpscnt
, param
, 2);
1372 char *str2
= skip_string(param
,tpscnt
,str1
);
1373 char *p
= skip_string(param
,tpscnt
,str2
);
1374 int uLevel
= get_safe_SVAL(param
, tpscnt
, p
, 0, -1);
1375 int buf_len
= get_safe_SVAL(param
,tpscnt
, p
, 2, 0);
1376 uint32 servertype
= get_safe_IVAL(param
,tpscnt
,p
,4, 0);
1378 int data_len
, fixed_len
, string_len
;
1379 int f_len
= 0, s_len
= 0;
1380 struct srv_info_struct
*servers
=NULL
;
1381 int counted
=0,total
=0;
1384 bool domain_request
;
1387 if (!str1
|| !str2
|| !p
) {
1391 /* If someone sets all the bits they don't really mean to set
1392 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1395 if (servertype
== SV_TYPE_ALL
) {
1396 servertype
&= ~(SV_TYPE_DOMAIN_ENUM
|SV_TYPE_LOCAL_LIST_ONLY
);
1399 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1400 any other bit (they may just set this bit on its own) they
1401 want all the locally seen servers. However this bit can be
1402 set on its own so set the requested servers to be
1403 ALL - DOMAIN_ENUM. */
1405 if ((servertype
& SV_TYPE_LOCAL_LIST_ONLY
) && !(servertype
& SV_TYPE_DOMAIN_ENUM
)) {
1406 servertype
= SV_TYPE_ALL
& ~(SV_TYPE_DOMAIN_ENUM
);
1409 domain_request
= ((servertype
& SV_TYPE_DOMAIN_ENUM
) != 0);
1410 local_request
= ((servertype
& SV_TYPE_LOCAL_LIST_ONLY
) != 0);
1414 if (!prefix_ok(str1
,"WrLehD")) {
1417 if (!check_server_info(uLevel
,str2
)) {
1421 DEBUG(4, ("server request level: %s %8x ", str2
, servertype
));
1422 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request
)));
1423 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request
)));
1425 if (strcmp(str1
, "WrLehDz") == 0) {
1426 if (skip_string(param
,tpscnt
,p
) == NULL
) {
1429 pull_ascii_fstring(domain
, p
);
1431 fstrcpy(domain
, lp_workgroup());
1434 if (lp_browse_list()) {
1435 total
= get_server_info(servertype
,&servers
,domain
);
1438 data_len
= fixed_len
= string_len
= 0;
1442 qsort(servers
,total
,sizeof(servers
[0]),QSORT_CAST srv_comp
);
1446 char *lastname
=NULL
;
1448 for (i
=0;i
<total
;i
++) {
1449 struct srv_info_struct
*s
= &servers
[i
];
1451 if (lastname
&& strequal(lastname
,s
->name
)) {
1455 data_len
+= fill_srv_info(s
,uLevel
,0,&f_len
,0,&s_len
,0);
1456 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1457 s
->name
, s
->type
, s
->comment
, s
->domain
));
1459 if (data_len
<= buf_len
) {
1462 string_len
+= s_len
;
1469 *rdata_len
= fixed_len
+ string_len
;
1470 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
1475 p2
= (*rdata
) + fixed_len
; /* auxilliary data (strings) will go here */
1481 char *lastname
=NULL
;
1482 int count2
= counted
;
1484 for (i
= 0; i
< total
&& count2
;i
++) {
1485 struct srv_info_struct
*s
= &servers
[i
];
1487 if (lastname
&& strequal(lastname
,s
->name
)) {
1491 fill_srv_info(s
,uLevel
,&p
,&f_len
,&p2
,&s_len
,*rdata
);
1492 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1493 s
->name
, s
->type
, s
->comment
, s
->domain
));
1499 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1503 SSVAL(*rparam
,0,(missed
== 0 ? NERR_Success
: ERRmoredata
));
1505 SSVAL(*rparam
,4,counted
);
1506 SSVAL(*rparam
,6,counted
+missed
);
1510 DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
1511 domain
,uLevel
,counted
,counted
+missed
));
1516 /****************************************************************************
1517 command 0x34 - suspected of being a "Lookup Names" stub api
1518 ****************************************************************************/
1520 static bool api_RNetGroupGetUsers(connection_struct
*conn
, uint16 vuid
,
1521 char *param
, int tpscnt
,
1522 char *data
, int tdscnt
,
1523 int mdrcnt
, int mprcnt
, char **rdata
,
1524 char **rparam
, int *rdata_len
, int *rparam_len
)
1526 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
1527 char *str2
= skip_string(param
,tpscnt
,str1
);
1528 char *p
= skip_string(param
,tpscnt
,str2
);
1529 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
1530 int buf_len
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
1534 if (!str1
|| !str2
|| !p
) {
1538 DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
1539 str1
, str2
, p
, uLevel
, buf_len
));
1541 if (!prefix_ok(str1
,"zWrLeh")) {
1548 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1553 SSVAL(*rparam
,0,0x08AC); /* informational warning message */
1555 SSVAL(*rparam
,4,counted
);
1556 SSVAL(*rparam
,6,counted
+missed
);
1561 /****************************************************************************
1562 get info about a share
1563 ****************************************************************************/
1565 static bool check_share_info(int uLevel
, char* id
)
1569 if (strcmp(id
,"B13") != 0) {
1574 if (strcmp(id
,"B13BWz") != 0) {
1579 if (strcmp(id
,"B13BWzWWWzB9B") != 0) {
1584 if (strcmp(id
,"B13BWzWWWzB9BB9BWzWWzWW") != 0) {
1594 static int fill_share_info(connection_struct
*conn
, int snum
, int uLevel
,
1595 char** buf
, int* buflen
,
1596 char** stringbuf
, int* stringspace
, char* baseaddr
)
1626 len
+= StrlenExpanded(conn
,snum
,lp_comment(snum
));
1629 len
+= strlen(lp_pathname(snum
)) + 1;
1632 *buflen
= struct_len
;
1637 return struct_len
+ len
;
1642 if ((*buflen
) < struct_len
) {
1650 p2
= p
+ struct_len
;
1651 l2
= (*buflen
) - struct_len
;
1658 push_ascii(p
,lp_servicename(snum
),13, STR_TERMINATE
);
1664 type
= STYPE_DISKTREE
;
1665 if (lp_print_ok(snum
)) {
1666 type
= STYPE_PRINTQ
;
1668 if (strequal("IPC",lp_fstype(snum
))) {
1671 SSVAL(p
,14,type
); /* device type */
1672 SIVAL(p
,16,PTR_DIFF(p2
,baseaddr
));
1673 len
+= CopyExpanded(conn
,snum
,&p2
,lp_comment(snum
),&l2
);
1677 SSVAL(p
,20,ACCESS_READ
|ACCESS_WRITE
|ACCESS_CREATE
); /* permissions */
1678 SSVALS(p
,22,-1); /* max uses */
1679 SSVAL(p
,24,1); /* current uses */
1680 SIVAL(p
,26,PTR_DIFF(p2
,baseaddr
)); /* local pathname */
1681 len
+= CopyAndAdvance(&p2
,lp_pathname(snum
),&l2
);
1682 memset(p
+30,0,SHPWLEN
+2); /* passwd (reserved), pad field */
1686 memset(p
+40,0,SHPWLEN
+2);
1697 (*buf
) = p
+ struct_len
;
1698 (*buflen
) -= struct_len
;
1700 (*stringspace
) = l2
;
1709 static bool api_RNetShareGetInfo(connection_struct
*conn
,uint16 vuid
,
1710 char *param
, int tpscnt
,
1711 char *data
, int tdscnt
,
1712 int mdrcnt
,int mprcnt
,
1713 char **rdata
,char **rparam
,
1714 int *rdata_len
,int *rparam_len
)
1716 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
1717 char *str2
= skip_string(param
,tpscnt
,str1
);
1718 char *netname
= skip_string(param
,tpscnt
,str2
);
1719 char *p
= skip_string(param
,tpscnt
,netname
);
1720 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
1723 if (!str1
|| !str2
|| !netname
|| !p
) {
1727 snum
= find_service(netname
);
1732 /* check it's a supported varient */
1733 if (!prefix_ok(str1
,"zWrLh")) {
1736 if (!check_share_info(uLevel
,str2
)) {
1740 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
1745 *rdata_len
= fill_share_info(conn
,snum
,uLevel
,&p
,&mdrcnt
,0,0,0);
1746 if (*rdata_len
< 0) {
1751 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1755 SSVAL(*rparam
,0,NERR_Success
);
1756 SSVAL(*rparam
,2,0); /* converter word */
1757 SSVAL(*rparam
,4,*rdata_len
);
1762 /****************************************************************************
1763 View the list of available shares.
1765 This function is the server side of the NetShareEnum() RAP call.
1766 It fills the return buffer with share names and share comments.
1767 Note that the return buffer normally (in all known cases) allows only
1768 twelve byte strings for share names (plus one for a nul terminator).
1769 Share names longer than 12 bytes must be skipped.
1770 ****************************************************************************/
1772 static bool api_RNetShareEnum( connection_struct
*conn
, uint16 vuid
,
1773 char *param
, int tpscnt
,
1774 char *data
, int tdscnt
,
1782 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
1783 char *str2
= skip_string(param
,tpscnt
,str1
);
1784 char *p
= skip_string(param
,tpscnt
,str2
);
1785 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
1786 int buf_len
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
1789 int total
=0,counted
=0;
1790 bool missed
= False
;
1792 int data_len
, fixed_len
, string_len
;
1793 int f_len
= 0, s_len
= 0;
1795 if (!str1
|| !str2
|| !p
) {
1799 if (!prefix_ok(str1
,"WrLeh")) {
1802 if (!check_share_info(uLevel
,str2
)) {
1806 /* Ensure all the usershares are loaded. */
1808 load_registry_shares();
1809 count
= load_usershare_shares();
1812 data_len
= fixed_len
= string_len
= 0;
1813 for (i
=0;i
<count
;i
++) {
1814 fstring servicename_dos
;
1815 if (!(lp_browseable(i
) && lp_snum_ok(i
))) {
1818 push_ascii_fstring(servicename_dos
, lp_servicename(i
));
1819 /* Maximum name length = 13. */
1820 if( lp_browseable( i
) && lp_snum_ok( i
) && (strlen(servicename_dos
) < 13)) {
1822 data_len
+= fill_share_info(conn
,i
,uLevel
,0,&f_len
,0,&s_len
,0);
1823 if (data_len
<= buf_len
) {
1826 string_len
+= s_len
;
1833 *rdata_len
= fixed_len
+ string_len
;
1834 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
1839 p2
= (*rdata
) + fixed_len
; /* auxiliary data (strings) will go here */
1844 for( i
= 0; i
< count
; i
++ ) {
1845 fstring servicename_dos
;
1846 if (!(lp_browseable(i
) && lp_snum_ok(i
))) {
1850 push_ascii_fstring(servicename_dos
, lp_servicename(i
));
1851 if (lp_browseable(i
) && lp_snum_ok(i
) && (strlen(servicename_dos
) < 13)) {
1852 if (fill_share_info( conn
,i
,uLevel
,&p
,&f_len
,&p2
,&s_len
,*rdata
) < 0) {
1859 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1863 SSVAL(*rparam
,0,missed
? ERRmoredata
: NERR_Success
);
1865 SSVAL(*rparam
,4,counted
);
1866 SSVAL(*rparam
,6,total
);
1868 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
1869 counted
,total
,uLevel
,
1870 buf_len
,*rdata_len
,mdrcnt
));
1875 /****************************************************************************
1877 ****************************************************************************/
1879 static bool api_RNetShareAdd(connection_struct
*conn
,uint16 vuid
,
1880 char *param
, int tpscnt
,
1881 char *data
, int tdscnt
,
1882 int mdrcnt
,int mprcnt
,
1883 char **rdata
,char **rparam
,
1884 int *rdata_len
,int *rparam_len
)
1886 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
1887 char *str2
= skip_string(param
,tpscnt
,str1
);
1888 char *p
= skip_string(param
,tpscnt
,str2
);
1889 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
1892 char *pathname
= NULL
;
1893 char *command
, *cmdname
;
1894 unsigned int offset
;
1897 size_t converted_size
;
1899 if (!str1
|| !str2
|| !p
) {
1903 /* check it's a supported varient */
1904 if (!prefix_ok(str1
,RAP_WShareAdd_REQ
)) {
1907 if (!check_share_info(uLevel
,str2
)) {
1914 /* Do we have a string ? */
1915 if (skip_string(data
,mdrcnt
,data
) == NULL
) {
1918 pull_ascii_fstring(sharename
,data
);
1919 snum
= find_service(sharename
);
1920 if (snum
>= 0) { /* already exists */
1929 /* only support disk share adds */
1930 if (SVAL(data
,14)!=STYPE_DISKTREE
) {
1934 offset
= IVAL(data
, 16);
1935 if (offset
>= mdrcnt
) {
1936 res
= ERRinvalidparam
;
1940 /* Do we have a string ? */
1941 if (skip_string(data
,mdrcnt
,data
+offset
) == NULL
) {
1944 pull_ascii_fstring(comment
, offset
? (data
+offset
) : "");
1946 offset
= IVAL(data
, 26);
1948 if (offset
>= mdrcnt
) {
1949 res
= ERRinvalidparam
;
1953 /* Do we have a string ? */
1954 if (skip_string(data
,mdrcnt
,data
+offset
) == NULL
) {
1958 if (!pull_ascii_talloc(talloc_tos(), &pathname
,
1959 offset
? (data
+offset
) : "", &converted_size
))
1961 DEBUG(0,("api_RNetShareAdd: pull_ascii_talloc failed: %s",
1969 string_replace(sharename
, '"', ' ');
1970 string_replace(pathname
, '"', ' ');
1971 string_replace(comment
, '"', ' ');
1973 cmdname
= lp_add_share_cmd();
1975 if (!cmdname
|| *cmdname
== '\0') {
1979 if (asprintf(&command
, "%s \"%s\" \"%s\" \"%s\" \"%s\"",
1980 lp_add_share_cmd(), get_dyn_CONFIGFILE(), sharename
,
1981 pathname
, comment
) == -1) {
1985 DEBUG(10,("api_RNetShareAdd: Running [%s]\n", command
));
1987 if ((res
= smbrun(command
, NULL
)) != 0) {
1988 DEBUG(1,("api_RNetShareAdd: Running [%s] returned (%d)\n",
1995 message_send_all(smbd_messaging_context(),
1996 MSG_SMB_CONF_UPDATED
, NULL
, 0, NULL
);
2000 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2004 SSVAL(*rparam
,0,NERR_Success
);
2005 SSVAL(*rparam
,2,0); /* converter word */
2006 SSVAL(*rparam
,4,*rdata_len
);
2014 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2019 SSVAL(*rparam
,0,res
);
2024 /****************************************************************************
2025 view list of groups available
2026 ****************************************************************************/
2028 static bool api_RNetGroupEnum(connection_struct
*conn
,uint16 vuid
,
2029 char *param
, int tpscnt
,
2030 char *data
, int tdscnt
,
2031 int mdrcnt
,int mprcnt
,
2032 char **rdata
,char **rparam
,
2033 int *rdata_len
,int *rparam_len
)
2037 int resume_context
, cli_buf_size
;
2038 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2039 char *str2
= skip_string(param
,tpscnt
,str1
);
2040 char *p
= skip_string(param
,tpscnt
,str2
);
2042 struct pdb_search
*search
;
2043 struct samr_displayentry
*entries
;
2047 if (!str1
|| !str2
|| !p
) {
2051 if (strcmp(str1
,"WrLeh") != 0) {
2056 * W-> resume context (number of users to skip)
2057 * r -> return parameter pointer to receive buffer
2058 * L -> length of receive buffer
2059 * e -> return parameter number of entries
2060 * h -> return parameter total number of users
2063 if (strcmp("B21",str2
) != 0) {
2067 /* get list of domain groups SID_DOMAIN_GRP=2 */
2069 search
= pdb_search_groups();
2072 if (search
== NULL
) {
2073 DEBUG(3,("api_RNetGroupEnum:failed to get group list"));
2077 resume_context
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2078 cli_buf_size
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
2079 DEBUG(10,("api_RNetGroupEnum:resume context: %d, client buffer size: "
2080 "%d\n", resume_context
, cli_buf_size
));
2083 num_entries
= pdb_search_entries(search
, resume_context
, 0xffffffff,
2087 *rdata_len
= cli_buf_size
;
2088 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2095 for(i
=0; i
<num_entries
; i
++) {
2097 fstrcpy(name
, entries
[i
].account_name
);
2098 if( ((PTR_DIFF(p
,*rdata
)+21) <= *rdata_len
) ) {
2099 /* truncate the name at 21 chars. */
2100 memcpy(p
, name
, 21);
2101 DEBUG(10,("adding entry %d group %s\n", i
, p
));
2103 p
+= 5; /* Both NT4 and W2k3SP1 do padding here.
2106 /* set overflow error */
2107 DEBUG(3,("overflow on entry %d group %s\n", i
, name
));
2113 pdb_search_destroy(search
);
2115 *rdata_len
= PTR_DIFF(p
,*rdata
);
2118 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2122 SSVAL(*rparam
, 0, errflags
);
2123 SSVAL(*rparam
, 2, 0); /* converter word */
2124 SSVAL(*rparam
, 4, i
); /* is this right?? */
2125 SSVAL(*rparam
, 6, resume_context
+num_entries
); /* is this right?? */
2130 /*******************************************************************
2131 Get groups that a user is a member of.
2132 ******************************************************************/
2134 static bool api_NetUserGetGroups(connection_struct
*conn
,uint16 vuid
,
2135 char *param
, int tpscnt
,
2136 char *data
, int tdscnt
,
2137 int mdrcnt
,int mprcnt
,
2138 char **rdata
,char **rparam
,
2139 int *rdata_len
,int *rparam_len
)
2141 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2142 char *str2
= skip_string(param
,tpscnt
,str1
);
2143 char *UserName
= skip_string(param
,tpscnt
,str2
);
2144 char *p
= skip_string(param
,tpscnt
,UserName
);
2145 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2146 const char *level_string
;
2148 struct samu
*sampw
= NULL
;
2156 enum lsa_SidType type
;
2158 TALLOC_CTX
*mem_ctx
;
2160 if (!str1
|| !str2
|| !UserName
|| !p
) {
2165 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2170 /* check it's a supported varient */
2172 if ( strcmp(str1
,"zWrLeh") != 0 )
2177 level_string
= "B21";
2183 if (strcmp(level_string
,str2
) != 0)
2186 *rdata_len
= mdrcnt
+ 1024;
2187 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2192 SSVAL(*rparam
,0,NERR_Success
);
2193 SSVAL(*rparam
,2,0); /* converter word */
2196 endp
= *rdata
+ *rdata_len
;
2198 mem_ctx
= talloc_new(NULL
);
2199 if (mem_ctx
== NULL
) {
2200 DEBUG(0, ("talloc_new failed\n"));
2204 if ( !(sampw
= samu_new(mem_ctx
)) ) {
2205 DEBUG(0, ("samu_new() failed!\n"));
2206 TALLOC_FREE(mem_ctx
);
2210 /* Lookup the user information; This should only be one of
2211 our accounts (not remote domains) */
2213 become_root(); /* ROOT BLOCK */
2215 if (!lookup_name(mem_ctx
, UserName
, LOOKUP_NAME_ALL
,
2216 NULL
, NULL
, &user_sid
, &type
)) {
2217 DEBUG(10, ("lookup_name(%s) failed\n", UserName
));
2221 if (type
!= SID_NAME_USER
) {
2222 DEBUG(10, ("%s is a %s, not a user\n", UserName
,
2223 sid_type_lookup(type
)));
2227 if ( !pdb_getsampwsid(sampw
, &user_sid
) ) {
2228 DEBUG(10, ("pdb_getsampwsid(%s) failed for user %s\n",
2229 sid_string_dbg(&user_sid
), UserName
));
2237 result
= pdb_enum_group_memberships(mem_ctx
, sampw
,
2238 &sids
, &gids
, &num_groups
);
2240 if (!NT_STATUS_IS_OK(result
)) {
2241 DEBUG(10, ("pdb_enum_group_memberships failed for %s\n",
2246 for (i
=0; i
<num_groups
; i
++) {
2247 const char *grp_name
;
2249 if ( lookup_sid(mem_ctx
, &sids
[i
], NULL
, &grp_name
, NULL
) ) {
2250 strlcpy(p
, grp_name
, PTR_DIFF(endp
,p
));
2256 *rdata_len
= PTR_DIFF(p
,*rdata
);
2258 SSVAL(*rparam
,4,count
); /* is this right?? */
2259 SSVAL(*rparam
,6,count
); /* is this right?? */
2264 unbecome_root(); /* END ROOT BLOCK */
2266 TALLOC_FREE(mem_ctx
);
2271 /*******************************************************************
2273 ******************************************************************/
2275 static bool api_RNetUserEnum(connection_struct
*conn
, uint16 vuid
,
2276 char *param
, int tpscnt
,
2277 char *data
, int tdscnt
,
2278 int mdrcnt
,int mprcnt
,
2279 char **rdata
,char **rparam
,
2280 int *rdata_len
,int *rparam_len
)
2285 int i
, resume_context
, cli_buf_size
;
2286 struct pdb_search
*search
;
2287 struct samr_displayentry
*users
;
2289 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2290 char *str2
= skip_string(param
,tpscnt
,str1
);
2291 char *p
= skip_string(param
,tpscnt
,str2
);
2294 if (!str1
|| !str2
|| !p
) {
2298 if (strcmp(str1
,"WrLeh") != 0)
2301 * W-> resume context (number of users to skip)
2302 * r -> return parameter pointer to receive buffer
2303 * L -> length of receive buffer
2304 * e -> return parameter number of entries
2305 * h -> return parameter total number of users
2308 resume_context
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2309 cli_buf_size
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
2310 DEBUG(10,("api_RNetUserEnum:resume context: %d, client buffer size: %d\n",
2311 resume_context
, cli_buf_size
));
2314 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2319 /* check it's a supported varient */
2320 if (strcmp("B21",str2
) != 0)
2323 *rdata_len
= cli_buf_size
;
2324 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2330 endp
= *rdata
+ *rdata_len
;
2333 search
= pdb_search_users(ACB_NORMAL
);
2335 if (search
== NULL
) {
2336 DEBUG(0, ("api_RNetUserEnum:unable to open sam database.\n"));
2341 num_users
= pdb_search_entries(search
, resume_context
, 0xffffffff,
2345 errflags
=NERR_Success
;
2347 for (i
=0; i
<num_users
; i
++) {
2348 const char *name
= users
[i
].account_name
;
2350 if(((PTR_DIFF(p
,*rdata
)+21)<=*rdata_len
)&&(strlen(name
)<=21)) {
2351 strlcpy(p
,name
,PTR_DIFF(endp
,p
));
2352 DEBUG(10,("api_RNetUserEnum:adding entry %d username "
2353 "%s\n",count_sent
,p
));
2357 /* set overflow error */
2358 DEBUG(10,("api_RNetUserEnum:overflow on entry %d "
2359 "username %s\n",count_sent
,name
));
2365 pdb_search_destroy(search
);
2367 *rdata_len
= PTR_DIFF(p
,*rdata
);
2369 SSVAL(*rparam
,0,errflags
);
2370 SSVAL(*rparam
,2,0); /* converter word */
2371 SSVAL(*rparam
,4,count_sent
); /* is this right?? */
2372 SSVAL(*rparam
,6,num_users
); /* is this right?? */
2377 /****************************************************************************
2378 Get the time of day info.
2379 ****************************************************************************/
2381 static bool api_NetRemoteTOD(connection_struct
*conn
,uint16 vuid
,
2382 char *param
, int tpscnt
,
2383 char *data
, int tdscnt
,
2384 int mdrcnt
,int mprcnt
,
2385 char **rdata
,char **rparam
,
2386 int *rdata_len
,int *rparam_len
)
2389 time_t unixdate
= time(NULL
);
2393 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2399 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2404 SSVAL(*rparam
,0,NERR_Success
);
2405 SSVAL(*rparam
,2,0); /* converter word */
2409 srv_put_dos_date3(p
,0,unixdate
); /* this is the time that is looked at
2410 by NT in a "net time" operation,
2411 it seems to ignore the one below */
2413 /* the client expects to get localtime, not GMT, in this bit
2414 (I think, this needs testing) */
2415 t
= localtime(&unixdate
);
2420 SIVAL(p
,4,0); /* msecs ? */
2421 SCVAL(p
,8,t
->tm_hour
);
2422 SCVAL(p
,9,t
->tm_min
);
2423 SCVAL(p
,10,t
->tm_sec
);
2424 SCVAL(p
,11,0); /* hundredths of seconds */
2425 SSVALS(p
,12,get_time_zone(unixdate
)/60); /* timezone in minutes from GMT */
2426 SSVAL(p
,14,10000); /* timer interval in 0.0001 of sec */
2427 SCVAL(p
,16,t
->tm_mday
);
2428 SCVAL(p
,17,t
->tm_mon
+ 1);
2429 SSVAL(p
,18,1900+t
->tm_year
);
2430 SCVAL(p
,20,t
->tm_wday
);
2435 /****************************************************************************
2436 Set the user password.
2437 *****************************************************************************/
2439 static bool api_SetUserPassword(connection_struct
*conn
,uint16 vuid
,
2440 char *param
, int tpscnt
,
2441 char *data
, int tdscnt
,
2442 int mdrcnt
,int mprcnt
,
2443 char **rdata
,char **rparam
,
2444 int *rdata_len
,int *rparam_len
)
2446 char *np
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2449 fstring pass1
,pass2
;
2451 /* Skip 2 strings. */
2452 p
= skip_string(param
,tpscnt
,np
);
2453 p
= skip_string(param
,tpscnt
,p
);
2459 /* Do we have a string ? */
2460 if (skip_string(param
,tpscnt
,p
) == NULL
) {
2463 pull_ascii_fstring(user
,p
);
2465 p
= skip_string(param
,tpscnt
,p
);
2470 memset(pass1
,'\0',sizeof(pass1
));
2471 memset(pass2
,'\0',sizeof(pass2
));
2473 * We use 31 here not 32 as we're checking
2474 * the last byte we want to access is safe.
2476 if (!is_offset_safe(param
,tpscnt
,p
,31)) {
2480 memcpy(pass2
,p
+16,16);
2483 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2490 SSVAL(*rparam
,0,NERR_badpass
);
2491 SSVAL(*rparam
,2,0); /* converter word */
2493 DEBUG(3,("Set password for <%s>\n",user
));
2496 * Attempt to verify the old password against smbpasswd entries
2497 * Win98 clients send old and new password in plaintext for this call.
2501 auth_serversupplied_info
*server_info
= NULL
;
2502 DATA_BLOB password
= data_blob(pass1
, strlen(pass1
)+1);
2504 if (NT_STATUS_IS_OK(check_plaintext_password(user
,password
,&server_info
))) {
2507 if (NT_STATUS_IS_OK(change_oem_password(server_info
->sam_account
, pass1
, pass2
, False
, NULL
))) {
2508 SSVAL(*rparam
,0,NERR_Success
);
2512 TALLOC_FREE(server_info
);
2514 data_blob_clear_free(&password
);
2518 * If the plaintext change failed, attempt
2519 * the old encrypted method. NT will generate this
2520 * after trying the samr method. Note that this
2521 * method is done as a last resort as this
2522 * password change method loses the NT password hash
2523 * and cannot change the UNIX password as no plaintext
2527 if(SVAL(*rparam
,0) != NERR_Success
) {
2528 struct samu
*hnd
= NULL
;
2530 if (check_lanman_password(user
,(unsigned char *)pass1
,(unsigned char *)pass2
, &hnd
)) {
2532 if (change_lanman_password(hnd
,(uchar
*)pass2
)) {
2533 SSVAL(*rparam
,0,NERR_Success
);
2540 memset((char *)pass1
,'\0',sizeof(fstring
));
2541 memset((char *)pass2
,'\0',sizeof(fstring
));
2546 /****************************************************************************
2547 Set the user password (SamOEM version - gets plaintext).
2548 ****************************************************************************/
2550 static bool api_SamOEMChangePassword(connection_struct
*conn
,uint16 vuid
,
2551 char *param
, int tpscnt
,
2552 char *data
, int tdscnt
,
2553 int mdrcnt
,int mprcnt
,
2554 char **rdata
,char **rparam
,
2555 int *rdata_len
,int *rparam_len
)
2558 char *p
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2560 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2570 SSVAL(*rparam
,0,NERR_badpass
);
2573 * Check the parameter definition is correct.
2576 /* Do we have a string ? */
2577 if (skip_string(param
,tpscnt
,p
) == 0) {
2580 if(!strequal(p
, "zsT")) {
2581 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", p
));
2584 p
= skip_string(param
, tpscnt
, p
);
2589 /* Do we have a string ? */
2590 if (skip_string(param
,tpscnt
,p
) == 0) {
2593 if(!strequal(p
, "B516B16")) {
2594 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p
));
2597 p
= skip_string(param
,tpscnt
,p
);
2601 /* Do we have a string ? */
2602 if (skip_string(param
,tpscnt
,p
) == 0) {
2605 p
+= pull_ascii_fstring(user
,p
);
2607 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user
));
2610 * Pass the user through the NT -> unix user mapping
2614 (void)map_username(user
);
2616 if (NT_STATUS_IS_OK(pass_oem_change(user
, (uchar
*) data
, (uchar
*)&data
[516], NULL
, NULL
, NULL
))) {
2617 SSVAL(*rparam
,0,NERR_Success
);
2623 /****************************************************************************
2626 ****************************************************************************/
2628 static bool api_RDosPrintJobDel(connection_struct
*conn
,uint16 vuid
,
2629 char *param
, int tpscnt
,
2630 char *data
, int tdscnt
,
2631 int mdrcnt
,int mprcnt
,
2632 char **rdata
,char **rparam
,
2633 int *rdata_len
,int *rparam_len
)
2635 int function
= get_safe_SVAL(param
,tpscnt
,param
,0,0);
2636 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2637 char *str2
= skip_string(param
,tpscnt
,str1
);
2638 char *p
= skip_string(param
,tpscnt
,str2
);
2643 WERROR werr
= WERR_OK
;
2645 if (!str1
|| !str2
|| !p
) {
2649 * We use 1 here not 2 as we're checking
2650 * the last byte we want to access is safe.
2652 if (!is_offset_safe(param
,tpscnt
,p
,1)) {
2655 if(!rap_to_pjobid(SVAL(p
,0), sharename
, &jobid
))
2658 /* check it's a supported varient */
2659 if (!(strcsequal(str1
,"W") && strcsequal(str2
,"")))
2663 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2669 if (!print_job_exists(sharename
, jobid
)) {
2670 errcode
= NERR_JobNotFound
;
2674 snum
= lp_servicenumber( sharename
);
2676 errcode
= NERR_DestNotFound
;
2680 errcode
= NERR_notsupported
;
2683 case 81: /* delete */
2684 if (print_job_delete(conn
->server_info
, snum
, jobid
, &werr
))
2685 errcode
= NERR_Success
;
2687 case 82: /* pause */
2688 if (print_job_pause(conn
->server_info
, snum
, jobid
, &werr
))
2689 errcode
= NERR_Success
;
2691 case 83: /* resume */
2692 if (print_job_resume(conn
->server_info
, snum
, jobid
, &werr
))
2693 errcode
= NERR_Success
;
2697 if (!W_ERROR_IS_OK(werr
))
2698 errcode
= W_ERROR_V(werr
);
2701 SSVAL(*rparam
,0,errcode
);
2702 SSVAL(*rparam
,2,0); /* converter word */
2707 /****************************************************************************
2708 Purge a print queue - or pause or resume it.
2709 ****************************************************************************/
2711 static bool api_WPrintQueueCtrl(connection_struct
*conn
,uint16 vuid
,
2712 char *param
, int tpscnt
,
2713 char *data
, int tdscnt
,
2714 int mdrcnt
,int mprcnt
,
2715 char **rdata
,char **rparam
,
2716 int *rdata_len
,int *rparam_len
)
2718 int function
= get_safe_SVAL(param
,tpscnt
,param
,0,0);
2719 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2720 char *str2
= skip_string(param
,tpscnt
,str1
);
2721 char *QueueName
= skip_string(param
,tpscnt
,str2
);
2722 int errcode
= NERR_notsupported
;
2724 WERROR werr
= WERR_OK
;
2726 if (!str1
|| !str2
|| !QueueName
) {
2730 /* check it's a supported varient */
2731 if (!(strcsequal(str1
,"z") && strcsequal(str2
,"")))
2735 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2741 if (skip_string(param
,tpscnt
,QueueName
) == NULL
) {
2744 snum
= print_queue_snum(QueueName
);
2747 errcode
= NERR_JobNotFound
;
2752 case 74: /* Pause queue */
2753 if (print_queue_pause(conn
->server_info
, snum
, &werr
)) {
2754 errcode
= NERR_Success
;
2757 case 75: /* Resume queue */
2758 if (print_queue_resume(conn
->server_info
, snum
, &werr
)) {
2759 errcode
= NERR_Success
;
2762 case 103: /* Purge */
2763 if (print_queue_purge(conn
->server_info
, snum
, &werr
)) {
2764 errcode
= NERR_Success
;
2769 if (!W_ERROR_IS_OK(werr
)) errcode
= W_ERROR_V(werr
);
2772 SSVAL(*rparam
,0,errcode
);
2773 SSVAL(*rparam
,2,0); /* converter word */
2778 /****************************************************************************
2779 set the property of a print job (undocumented?)
2780 ? function = 0xb -> set name of print job
2781 ? function = 0x6 -> move print job up/down
2782 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
2783 or <WWsTP> <WB21BB16B10zWWzDDz>
2784 ****************************************************************************/
2786 static int check_printjob_info(struct pack_desc
* desc
,
2787 int uLevel
, char* id
)
2789 desc
->subformat
= NULL
;
2791 case 0: desc
->format
= "W"; break;
2792 case 1: desc
->format
= "WB21BB16B10zWWzDDz"; break;
2793 case 2: desc
->format
= "WWzWWDDzz"; break;
2794 case 3: desc
->format
= "WWzWWDDzzzzzzzzzzlz"; break;
2795 case 4: desc
->format
= "WWzWWDDzzzzzDDDDDDD"; break;
2797 DEBUG(0,("check_printjob_info: invalid level %d\n",
2801 if (id
== NULL
|| strcmp(desc
->format
,id
) != 0) {
2802 DEBUG(0,("check_printjob_info: invalid format %s\n",
2803 id
? id
: "<NULL>" ));
2809 static bool api_PrintJobInfo(connection_struct
*conn
, uint16 vuid
,
2810 char *param
, int tpscnt
,
2811 char *data
, int tdscnt
,
2812 int mdrcnt
,int mprcnt
,
2813 char **rdata
,char **rparam
,
2814 int *rdata_len
,int *rparam_len
)
2816 struct pack_desc desc
;
2817 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2818 char *str2
= skip_string(param
,tpscnt
,str1
);
2819 char *p
= skip_string(param
,tpscnt
,str2
);
2822 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,2,-1);
2823 int function
= get_safe_SVAL(param
,tpscnt
,p
,4,-1);
2826 if (!str1
|| !str2
|| !p
) {
2830 * We use 1 here not 2 as we're checking
2831 * the last byte we want to access is safe.
2833 if (!is_offset_safe(param
,tpscnt
,p
,1)) {
2836 if(!rap_to_pjobid(SVAL(p
,0), sharename
, &jobid
))
2839 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2844 if (!share_defined(sharename
)) {
2845 DEBUG(0,("api_PrintJobInfo: sharen [%s] not defined\n",
2852 /* check it's a supported varient */
2853 if ((strcmp(str1
,"WWsTP")) ||
2854 (!check_printjob_info(&desc
,uLevel
,str2
)))
2857 if (!print_job_exists(sharename
, jobid
)) {
2858 errcode
=NERR_JobNotFound
;
2862 errcode
= NERR_notsupported
;
2866 /* change job place in the queue,
2867 data gives the new place */
2868 place
= SVAL(data
,0);
2869 if (print_job_set_place(sharename
, jobid
, place
)) {
2870 errcode
=NERR_Success
;
2875 /* change print job name, data gives the name */
2876 if (print_job_set_name(sharename
, jobid
, data
)) {
2877 errcode
=NERR_Success
;
2886 SSVALS(*rparam
,0,errcode
);
2887 SSVAL(*rparam
,2,0); /* converter word */
2893 /****************************************************************************
2894 Get info about the server.
2895 ****************************************************************************/
2897 static bool api_RNetServerGetInfo(connection_struct
*conn
,uint16 vuid
,
2898 char *param
, int tpscnt
,
2899 char *data
, int tdscnt
,
2900 int mdrcnt
,int mprcnt
,
2901 char **rdata
,char **rparam
,
2902 int *rdata_len
,int *rparam_len
)
2904 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2905 char *str2
= skip_string(param
,tpscnt
,str1
);
2906 char *p
= skip_string(param
,tpscnt
,str2
);
2907 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2911 if (!str1
|| !str2
|| !p
) {
2915 DEBUG(4,("NetServerGetInfo level %d\n",uLevel
));
2917 /* check it's a supported varient */
2918 if (!prefix_ok(str1
,"WrLh")) {
2924 if (strcmp(str2
,"B16") != 0) {
2930 if (strcmp(str2
,"B16BBDz") != 0) {
2936 if (strcmp(str2
,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")!= 0) {
2942 if (strcmp(str2
,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz") != 0) {
2948 if (strcmp(str2
,"DN") != 0) {
2954 if (strcmp(str2
,"B16BBDzWWzzz") != 0) {
2963 *rdata_len
= mdrcnt
;
2964 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2970 p2
= p
+ struct_len
;
2972 srvstr_push(NULL
, 0, p
,global_myname(),16,
2973 STR_ASCII
|STR_UPPER
|STR_TERMINATE
);
2977 struct srv_info_struct
*servers
=NULL
;
2979 char *comment
= NULL
;
2980 TALLOC_CTX
*ctx
= talloc_tos();
2981 uint32 servertype
= lp_default_server_announce();
2983 comment
= talloc_strdup(ctx
,lp_serverstring());
2988 if ((count
=get_server_info(SV_TYPE_ALL
,&servers
,lp_workgroup()))>0) {
2989 for (i
=0;i
<count
;i
++) {
2990 if (strequal(servers
[i
].name
,global_myname())) {
2991 servertype
= servers
[i
].type
;
2992 TALLOC_FREE(comment
);
2993 comment
= talloc_strdup(ctx
,
2994 servers
[i
].comment
);
3004 SCVAL(p
,0,lp_major_announce_version());
3005 SCVAL(p
,1,lp_minor_announce_version());
3006 SIVAL(p
,2,servertype
);
3008 if (mdrcnt
== struct_len
) {
3011 SIVAL(p
,6,PTR_DIFF(p2
,*rdata
));
3012 comment
= talloc_sub_advanced(
3014 lp_servicename(SNUM(conn
)),
3015 conn
->server_info
->unix_name
,
3017 conn
->server_info
->utok
.gid
,
3018 conn
->server_info
->sanitized_username
,
3019 pdb_get_domain(conn
->server_info
->sam_account
),
3024 if (mdrcnt
- struct_len
<= 0) {
3029 MIN(mdrcnt
- struct_len
,
3030 MAX_SERVER_STRING_LENGTH
),
3032 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3040 return False
; /* not yet implemented */
3043 *rdata_len
= PTR_DIFF(p2
,*rdata
);
3046 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3050 SSVAL(*rparam
,0,NERR_Success
);
3051 SSVAL(*rparam
,2,0); /* converter word */
3052 SSVAL(*rparam
,4,*rdata_len
);
3057 /****************************************************************************
3058 Get info about the server.
3059 ****************************************************************************/
3061 static bool api_NetWkstaGetInfo(connection_struct
*conn
,uint16 vuid
,
3062 char *param
, int tpscnt
,
3063 char *data
, int tdscnt
,
3064 int mdrcnt
,int mprcnt
,
3065 char **rdata
,char **rparam
,
3066 int *rdata_len
,int *rparam_len
)
3068 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3069 char *str2
= skip_string(param
,tpscnt
,str1
);
3070 char *p
= skip_string(param
,tpscnt
,str2
);
3073 int level
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3075 if (!str1
|| !str2
|| !p
) {
3079 DEBUG(4,("NetWkstaGetInfo level %d\n",level
));
3082 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3087 /* check it's a supported varient */
3088 if (!(level
==10 && strcsequal(str1
,"WrLh") && strcsequal(str2
,"zzzBBzz"))) {
3092 *rdata_len
= mdrcnt
+ 1024;
3093 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
3098 SSVAL(*rparam
,0,NERR_Success
);
3099 SSVAL(*rparam
,2,0); /* converter word */
3102 endp
= *rdata
+ *rdata_len
;
3104 p2
= get_safe_ptr(*rdata
,*rdata_len
,p
,22);
3109 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* host name */
3110 strlcpy(p2
,get_local_machine_name(),PTR_DIFF(endp
,p2
));
3112 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3118 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
));
3119 strlcpy(p2
,conn
->server_info
->sanitized_username
,PTR_DIFF(endp
,p2
));
3120 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3126 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* login domain */
3127 strlcpy(p2
,lp_workgroup(),PTR_DIFF(endp
,p2
));
3129 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3135 SCVAL(p
,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
3136 SCVAL(p
,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
3139 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
));
3140 strlcpy(p2
,lp_workgroup(),PTR_DIFF(endp
,p2
)); /* don't know. login domain?? */
3141 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3147 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* don't know */
3148 strlcpy(p2
,"",PTR_DIFF(endp
,p2
));
3149 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3155 *rdata_len
= PTR_DIFF(p2
,*rdata
);
3157 SSVAL(*rparam
,4,*rdata_len
);
3162 /****************************************************************************
3163 get info about a user
3165 struct user_info_11 {
3166 char usri11_name[21]; 0-20
3168 char *usri11_comment; 22-25
3169 char *usri11_usr_comment; 26-29
3170 unsigned short usri11_priv; 30-31
3171 unsigned long usri11_auth_flags; 32-35
3172 long usri11_password_age; 36-39
3173 char *usri11_homedir; 40-43
3174 char *usri11_parms; 44-47
3175 long usri11_last_logon; 48-51
3176 long usri11_last_logoff; 52-55
3177 unsigned short usri11_bad_pw_count; 56-57
3178 unsigned short usri11_num_logons; 58-59
3179 char *usri11_logon_server; 60-63
3180 unsigned short usri11_country_code; 64-65
3181 char *usri11_workstations; 66-69
3182 unsigned long usri11_max_storage; 70-73
3183 unsigned short usri11_units_per_week; 74-75
3184 unsigned char *usri11_logon_hours; 76-79
3185 unsigned short usri11_code_page; 80-81
3190 usri11_name specifies the user name for which information is retrieved
3192 usri11_pad aligns the next data structure element to a word boundary
3194 usri11_comment is a null terminated ASCII comment
3196 usri11_user_comment is a null terminated ASCII comment about the user
3198 usri11_priv specifies the level of the privilege assigned to the user.
3199 The possible values are:
3201 Name Value Description
3202 USER_PRIV_GUEST 0 Guest privilege
3203 USER_PRIV_USER 1 User privilege
3204 USER_PRV_ADMIN 2 Administrator privilege
3206 usri11_auth_flags specifies the account operator privileges. The
3207 possible values are:
3209 Name Value Description
3210 AF_OP_PRINT 0 Print operator
3213 Leach, Naik [Page 28]
3217 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
3220 AF_OP_COMM 1 Communications operator
3221 AF_OP_SERVER 2 Server operator
3222 AF_OP_ACCOUNTS 3 Accounts operator
3225 usri11_password_age specifies how many seconds have elapsed since the
3226 password was last changed.
3228 usri11_home_dir points to a null terminated ASCII string that contains
3229 the path name of the user's home directory.
3231 usri11_parms points to a null terminated ASCII string that is set
3232 aside for use by applications.
3234 usri11_last_logon specifies the time when the user last logged on.
3235 This value is stored as the number of seconds elapsed since
3236 00:00:00, January 1, 1970.
3238 usri11_last_logoff specifies the time when the user last logged off.
3239 This value is stored as the number of seconds elapsed since
3240 00:00:00, January 1, 1970. A value of 0 means the last logoff
3243 usri11_bad_pw_count specifies the number of incorrect passwords
3244 entered since the last successful logon.
3246 usri11_log1_num_logons specifies the number of times this user has
3247 logged on. A value of -1 means the number of logons is unknown.
3249 usri11_logon_server points to a null terminated ASCII string that
3250 contains the name of the server to which logon requests are sent.
3251 A null string indicates logon requests should be sent to the
3254 usri11_country_code specifies the country code for the user's language
3257 usri11_workstations points to a null terminated ASCII string that
3258 contains the names of workstations the user may log on from.
3259 There may be up to 8 workstations, with the names separated by
3260 commas. A null strings indicates there are no restrictions.
3262 usri11_max_storage specifies the maximum amount of disk space the user
3263 can occupy. A value of 0xffffffff indicates there are no
3266 usri11_units_per_week specifies the equal number of time units into
3267 which a week is divided. This value must be equal to 168.
3269 usri11_logon_hours points to a 21 byte (168 bits) string that
3270 specifies the time during which the user can log on. Each bit
3271 represents one unique hour in a week. The first bit (bit 0, word
3272 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
3276 Leach, Naik [Page 29]
3280 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
3283 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
3284 are no restrictions.
3286 usri11_code_page specifies the code page for the user's language of
3289 All of the pointers in this data structure need to be treated
3290 specially. The pointer is a 32 bit pointer. The higher 16 bits need
3291 to be ignored. The converter word returned in the parameters section
3292 needs to be subtracted from the lower 16 bits to calculate an offset
3293 into the return buffer where this ASCII string resides.
3295 There is no auxiliary data in the response.
3297 ****************************************************************************/
3299 #define usri11_name 0
3300 #define usri11_pad 21
3301 #define usri11_comment 22
3302 #define usri11_usr_comment 26
3303 #define usri11_full_name 30
3304 #define usri11_priv 34
3305 #define usri11_auth_flags 36
3306 #define usri11_password_age 40
3307 #define usri11_homedir 44
3308 #define usri11_parms 48
3309 #define usri11_last_logon 52
3310 #define usri11_last_logoff 56
3311 #define usri11_bad_pw_count 60
3312 #define usri11_num_logons 62
3313 #define usri11_logon_server 64
3314 #define usri11_country_code 68
3315 #define usri11_workstations 70
3316 #define usri11_max_storage 74
3317 #define usri11_units_per_week 78
3318 #define usri11_logon_hours 80
3319 #define usri11_code_page 84
3320 #define usri11_end 86
3322 #define USER_PRIV_GUEST 0
3323 #define USER_PRIV_USER 1
3324 #define USER_PRIV_ADMIN 2
3326 #define AF_OP_PRINT 0
3327 #define AF_OP_COMM 1
3328 #define AF_OP_SERVER 2
3329 #define AF_OP_ACCOUNTS 3
3332 static bool api_RNetUserGetInfo(connection_struct
*conn
, uint16 vuid
,
3333 char *param
, int tpscnt
,
3334 char *data
, int tdscnt
,
3335 int mdrcnt
,int mprcnt
,
3336 char **rdata
,char **rparam
,
3337 int *rdata_len
,int *rparam_len
)
3339 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3340 char *str2
= skip_string(param
,tpscnt
,str1
);
3341 char *UserName
= skip_string(param
,tpscnt
,str2
);
3342 char *p
= skip_string(param
,tpscnt
,UserName
);
3343 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3346 const char *level_string
;
3348 /* get NIS home of a previously validated user - simeon */
3349 /* With share level security vuid will always be zero.
3350 Don't depend on vuser being non-null !!. JRA */
3351 user_struct
*vuser
= get_valid_user_struct(vuid
);
3353 DEBUG(3,(" Username of UID %d is %s\n",
3354 (int)vuser
->server_info
->utok
.uid
,
3355 vuser
->server_info
->unix_name
));
3358 if (!str1
|| !str2
|| !UserName
|| !p
) {
3363 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3368 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel
));
3370 /* check it's a supported variant */
3371 if (strcmp(str1
,"zWrLh") != 0) {
3375 case 0: level_string
= "B21"; break;
3376 case 1: level_string
= "B21BB16DWzzWz"; break;
3377 case 2: level_string
= "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
3378 case 10: level_string
= "B21Bzzz"; break;
3379 case 11: level_string
= "B21BzzzWDDzzDDWWzWzDWb21W"; break;
3380 default: return False
;
3383 if (strcmp(level_string
,str2
) != 0) {
3387 *rdata_len
= mdrcnt
+ 1024;
3388 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
3393 SSVAL(*rparam
,0,NERR_Success
);
3394 SSVAL(*rparam
,2,0); /* converter word */
3397 endp
= *rdata
+ *rdata_len
;
3398 p2
= get_safe_ptr(*rdata
,*rdata_len
,p
,usri11_end
);
3404 fstrcpy(p
+usri11_name
,UserName
); /* 21 bytes - user name */
3407 SCVAL(p
,usri11_pad
,0); /* padding - 1 byte */
3412 SIVAL(p
,usri11_comment
,PTR_DIFF(p2
,p
)); /* comment */
3413 strlcpy(p2
,"Comment",PTR_DIFF(endp
,p2
));
3414 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3419 SIVAL(p
,usri11_usr_comment
,PTR_DIFF(p2
,p
)); /* user_comment */
3420 strlcpy(p2
,"UserComment",PTR_DIFF(endp
,p2
));
3421 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3426 /* EEK! the cifsrap.txt doesn't have this in!!!! */
3427 SIVAL(p
,usri11_full_name
,PTR_DIFF(p2
,p
)); /* full name */
3428 strlcpy(p2
,((vuser
!= NULL
)
3429 ? pdb_get_fullname(vuser
->server_info
->sam_account
)
3430 : UserName
),PTR_DIFF(endp
,p2
));
3431 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3438 const char *homedir
= "";
3439 if (vuser
!= NULL
) {
3440 homedir
= pdb_get_homedir(
3441 vuser
->server_info
->sam_account
);
3443 /* modelled after NTAS 3.51 reply */
3444 SSVAL(p
,usri11_priv
,conn
->admin_user
?USER_PRIV_ADMIN
:USER_PRIV_USER
);
3445 SIVAL(p
,usri11_auth_flags
,AF_OP_PRINT
); /* auth flags */
3446 SIVALS(p
,usri11_password_age
,-1); /* password age */
3447 SIVAL(p
,usri11_homedir
,PTR_DIFF(p2
,p
)); /* home dir */
3448 strlcpy(p2
, homedir
, PTR_DIFF(endp
,p2
));
3449 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3453 SIVAL(p
,usri11_parms
,PTR_DIFF(p2
,p
)); /* parms */
3454 strlcpy(p2
,"",PTR_DIFF(endp
,p2
));
3455 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3459 SIVAL(p
,usri11_last_logon
,0); /* last logon */
3460 SIVAL(p
,usri11_last_logoff
,0); /* last logoff */
3461 SSVALS(p
,usri11_bad_pw_count
,-1); /* bad pw counts */
3462 SSVALS(p
,usri11_num_logons
,-1); /* num logons */
3463 SIVAL(p
,usri11_logon_server
,PTR_DIFF(p2
,p
)); /* logon server */
3464 strlcpy(p2
,"\\\\*",PTR_DIFF(endp
,p2
));
3465 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3469 SSVAL(p
,usri11_country_code
,0); /* country code */
3471 SIVAL(p
,usri11_workstations
,PTR_DIFF(p2
,p
)); /* workstations */
3472 strlcpy(p2
,"",PTR_DIFF(endp
,p2
));
3473 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3478 SIVALS(p
,usri11_max_storage
,-1); /* max storage */
3479 SSVAL(p
,usri11_units_per_week
,168); /* units per week */
3480 SIVAL(p
,usri11_logon_hours
,PTR_DIFF(p2
,p
)); /* logon hours */
3482 /* a simple way to get logon hours at all times. */
3484 SCVAL(p2
,21,0); /* fix zero termination */
3485 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3490 SSVAL(p
,usri11_code_page
,0); /* code page */
3493 if (uLevel
== 1 || uLevel
== 2) {
3494 memset(p
+22,' ',16); /* password */
3495 SIVALS(p
,38,-1); /* password age */
3497 conn
->admin_user
?USER_PRIV_ADMIN
:USER_PRIV_USER
);
3498 SIVAL(p
,44,PTR_DIFF(p2
,*rdata
)); /* home dir */
3499 strlcpy(p2
, vuser
? pdb_get_homedir(
3500 vuser
->server_info
->sam_account
) : "",
3502 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3506 SIVAL(p
,48,PTR_DIFF(p2
,*rdata
)); /* comment */
3508 SSVAL(p
,52,0); /* flags */
3509 SIVAL(p
,54,PTR_DIFF(p2
,*rdata
)); /* script_path */
3510 strlcpy(p2
, vuser
? pdb_get_logon_script(
3511 vuser
->server_info
->sam_account
) : "",
3513 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3518 SIVAL(p
,60,0); /* auth_flags */
3519 SIVAL(p
,64,PTR_DIFF(p2
,*rdata
)); /* full_name */
3520 strlcpy(p2
,((vuser
!= NULL
)
3521 ? pdb_get_fullname(vuser
->server_info
->sam_account
)
3522 : UserName
),PTR_DIFF(endp
,p2
));
3523 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3527 SIVAL(p
,68,0); /* urs_comment */
3528 SIVAL(p
,72,PTR_DIFF(p2
,*rdata
)); /* parms */
3529 strlcpy(p2
,"",PTR_DIFF(endp
,p2
));
3530 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3534 SIVAL(p
,76,0); /* workstations */
3535 SIVAL(p
,80,0); /* last_logon */
3536 SIVAL(p
,84,0); /* last_logoff */
3537 SIVALS(p
,88,-1); /* acct_expires */
3538 SIVALS(p
,92,-1); /* max_storage */
3539 SSVAL(p
,96,168); /* units_per_week */
3540 SIVAL(p
,98,PTR_DIFF(p2
,*rdata
)); /* logon_hours */
3543 SSVALS(p
,102,-1); /* bad_pw_count */
3544 SSVALS(p
,104,-1); /* num_logons */
3545 SIVAL(p
,106,PTR_DIFF(p2
,*rdata
)); /* logon_server */
3547 TALLOC_CTX
*ctx
= talloc_tos();
3548 int space_rem
= *rdata_len
- (p2
- *rdata
);
3551 if (space_rem
<= 0) {
3554 tmp
= talloc_strdup(ctx
, "\\\\%L");
3558 tmp
= talloc_sub_basic(ctx
,
3571 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3575 SSVAL(p
,110,49); /* country_code */
3576 SSVAL(p
,112,860); /* code page */
3580 *rdata_len
= PTR_DIFF(p2
,*rdata
);
3582 SSVAL(*rparam
,4,*rdata_len
); /* is this right?? */
3587 static bool api_WWkstaUserLogon(connection_struct
*conn
,uint16 vuid
,
3588 char *param
, int tpscnt
,
3589 char *data
, int tdscnt
,
3590 int mdrcnt
,int mprcnt
,
3591 char **rdata
,char **rparam
,
3592 int *rdata_len
,int *rparam_len
)
3594 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3595 char *str2
= skip_string(param
,tpscnt
,str1
);
3596 char *p
= skip_string(param
,tpscnt
,str2
);
3598 struct pack_desc desc
;
3600 /* With share level security vuid will always be zero.
3601 Don't depend on vuser being non-null !!. JRA */
3602 user_struct
*vuser
= get_valid_user_struct(vuid
);
3604 if (!str1
|| !str2
|| !p
) {
3609 DEBUG(3,(" Username of UID %d is %s\n",
3610 (int)vuser
->server_info
->utok
.uid
,
3611 vuser
->server_info
->unix_name
));
3614 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3615 name
= get_safe_str_ptr(param
,tpscnt
,p
,2);
3620 memset((char *)&desc
,'\0',sizeof(desc
));
3622 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel
,name
));
3624 /* check it's a supported varient */
3625 if (strcmp(str1
,"OOWb54WrLh") != 0) {
3628 if (uLevel
!= 1 || strcmp(str2
,"WB21BWDWWDDDDDDDzzzD") != 0) {
3632 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
3639 desc
.buflen
= mdrcnt
;
3640 desc
.subformat
= NULL
;
3643 if (init_package(&desc
,1,0)) {
3644 PACKI(&desc
,"W",0); /* code */
3645 PACKS(&desc
,"B21",name
); /* eff. name */
3646 PACKS(&desc
,"B",""); /* pad */
3647 PACKI(&desc
,"W", conn
->admin_user
?USER_PRIV_ADMIN
:USER_PRIV_USER
);
3648 PACKI(&desc
,"D",0); /* auth flags XXX */
3649 PACKI(&desc
,"W",0); /* num logons */
3650 PACKI(&desc
,"W",0); /* bad pw count */
3651 PACKI(&desc
,"D",0); /* last logon */
3652 PACKI(&desc
,"D",-1); /* last logoff */
3653 PACKI(&desc
,"D",-1); /* logoff time */
3654 PACKI(&desc
,"D",-1); /* kickoff time */
3655 PACKI(&desc
,"D",0); /* password age */
3656 PACKI(&desc
,"D",0); /* password can change */
3657 PACKI(&desc
,"D",-1); /* password must change */
3661 fstrcpy(mypath
,"\\\\");
3662 fstrcat(mypath
,get_local_machine_name());
3664 PACKS(&desc
,"z",mypath
); /* computer */
3667 PACKS(&desc
,"z",lp_workgroup());/* domain */
3668 PACKS(&desc
,"z", vuser
? pdb_get_logon_script(
3669 vuser
->server_info
->sam_account
) : ""); /* script path */
3670 PACKI(&desc
,"D",0x00000000); /* reserved */
3673 *rdata_len
= desc
.usedlen
;
3675 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3679 SSVALS(*rparam
,0,desc
.errcode
);
3681 SSVAL(*rparam
,4,desc
.neededlen
);
3683 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc
.errcode
));
3688 /****************************************************************************
3689 api_WAccessGetUserPerms
3690 ****************************************************************************/
3692 static bool api_WAccessGetUserPerms(connection_struct
*conn
,uint16 vuid
,
3693 char *param
, int tpscnt
,
3694 char *data
, int tdscnt
,
3695 int mdrcnt
,int mprcnt
,
3696 char **rdata
,char **rparam
,
3697 int *rdata_len
,int *rparam_len
)
3699 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3700 char *str2
= skip_string(param
,tpscnt
,str1
);
3701 char *user
= skip_string(param
,tpscnt
,str2
);
3702 char *resource
= skip_string(param
,tpscnt
,user
);
3704 if (!str1
|| !str2
|| !user
|| !resource
) {
3708 if (skip_string(param
,tpscnt
,resource
) == NULL
) {
3711 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user
,resource
));
3713 /* check it's a supported varient */
3714 if (strcmp(str1
,"zzh") != 0) {
3717 if (strcmp(str2
,"") != 0) {
3722 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3726 SSVALS(*rparam
,0,0); /* errorcode */
3727 SSVAL(*rparam
,2,0); /* converter word */
3728 SSVAL(*rparam
,4,0x7f); /* permission flags */
3733 /****************************************************************************
3734 api_WPrintJobEnumerate
3735 ****************************************************************************/
3737 static bool api_WPrintJobGetInfo(connection_struct
*conn
, uint16 vuid
,
3738 char *param
, int tpscnt
,
3739 char *data
, int tdscnt
,
3740 int mdrcnt
,int mprcnt
,
3741 char **rdata
,char **rparam
,
3742 int *rdata_len
,int *rparam_len
)
3744 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3745 char *str2
= skip_string(param
,tpscnt
,str1
);
3746 char *p
= skip_string(param
,tpscnt
,str2
);
3753 struct pack_desc desc
;
3754 print_queue_struct
*queue
=NULL
;
3755 print_status_struct status
;
3758 if (!str1
|| !str2
|| !p
) {
3762 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,2,-1);
3764 memset((char *)&desc
,'\0',sizeof(desc
));
3765 memset((char *)&status
,'\0',sizeof(status
));
3767 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel
,SVAL(p
,0)));
3769 /* check it's a supported varient */
3770 if (strcmp(str1
,"WWrLh") != 0) {
3773 if (!check_printjob_info(&desc
,uLevel
,str2
)) {
3777 if(!rap_to_pjobid(SVAL(p
,0), sharename
, &jobid
)) {
3781 snum
= lp_servicenumber( sharename
);
3782 if (snum
< 0 || !VALID_SNUM(snum
)) {
3786 count
= print_queue_status(snum
,&queue
,&status
);
3787 for (i
= 0; i
< count
; i
++) {
3788 if (queue
[i
].job
== jobid
) {
3794 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
3799 desc
.buflen
= mdrcnt
;
3802 * Don't return data but need to get correct length
3803 * init_package will return wrong size if buflen=0
3805 desc
.buflen
= getlen(desc
.format
);
3806 desc
.base
= tmpdata
= (char *)SMB_MALLOC( desc
.buflen
);
3809 if (init_package(&desc
,1,0)) {
3811 fill_printjob_info(conn
,snum
,uLevel
,&desc
,&queue
[i
],i
);
3812 *rdata_len
= desc
.usedlen
;
3814 desc
.errcode
= NERR_JobNotFound
;
3820 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3824 SSVALS(*rparam
,0,desc
.errcode
);
3826 SSVAL(*rparam
,4,desc
.neededlen
);
3831 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc
.errcode
));
3836 static bool api_WPrintJobEnumerate(connection_struct
*conn
, uint16 vuid
,
3837 char *param
, int tpscnt
,
3838 char *data
, int tdscnt
,
3839 int mdrcnt
,int mprcnt
,
3840 char **rdata
,char **rparam
,
3841 int *rdata_len
,int *rparam_len
)
3843 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3844 char *str2
= skip_string(param
,tpscnt
,str1
);
3845 char *p
= skip_string(param
,tpscnt
,str2
);
3851 struct pack_desc desc
;
3852 print_queue_struct
*queue
=NULL
;
3853 print_status_struct status
;
3855 if (!str1
|| !str2
|| !p
) {
3859 memset((char *)&desc
,'\0',sizeof(desc
));
3860 memset((char *)&status
,'\0',sizeof(status
));
3862 p
= skip_string(param
,tpscnt
,p
);
3866 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3868 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel
,name
));
3870 /* check it's a supported variant */
3871 if (strcmp(str1
,"zWrLeh") != 0) {
3876 return False
; /* defined only for uLevel 0,1,2 */
3879 if (!check_printjob_info(&desc
,uLevel
,str2
)) {
3883 snum
= find_service(name
);
3884 if ( !(lp_snum_ok(snum
) && lp_print_ok(snum
)) ) {
3888 count
= print_queue_status(snum
,&queue
,&status
);
3890 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
3896 desc
.buflen
= mdrcnt
;
3898 if (init_package(&desc
,count
,0)) {
3900 for (i
= 0; i
< count
; i
++) {
3901 fill_printjob_info(conn
,snum
,uLevel
,&desc
,&queue
[i
],i
);
3902 if (desc
.errcode
== NERR_Success
) {
3908 *rdata_len
= desc
.usedlen
;
3911 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3915 SSVALS(*rparam
,0,desc
.errcode
);
3917 SSVAL(*rparam
,4,succnt
);
3918 SSVAL(*rparam
,6,count
);
3922 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc
.errcode
));
3927 static int check_printdest_info(struct pack_desc
* desc
,
3928 int uLevel
, char* id
)
3930 desc
->subformat
= NULL
;
3933 desc
->format
= "B9";
3936 desc
->format
= "B9B21WWzW";
3942 desc
->format
= "zzzWWzzzWW";
3945 DEBUG(0,("check_printdest_info: invalid level %d\n",
3949 if (id
== NULL
|| strcmp(desc
->format
,id
) != 0) {
3950 DEBUG(0,("check_printdest_info: invalid string %s\n",
3951 id
? id
: "<NULL>" ));
3957 static void fill_printdest_info(connection_struct
*conn
, int snum
, int uLevel
,
3958 struct pack_desc
* desc
)
3962 strncpy(buf
,SERVICE(snum
),sizeof(buf
)-1);
3963 buf
[sizeof(buf
)-1] = 0;
3967 PACKS(desc
,"B9",buf
); /* szName */
3969 PACKS(desc
,"B21",""); /* szUserName */
3970 PACKI(desc
,"W",0); /* uJobId */
3971 PACKI(desc
,"W",0); /* fsStatus */
3972 PACKS(desc
,"z",""); /* pszStatus */
3973 PACKI(desc
,"W",0); /* time */
3977 if (uLevel
== 2 || uLevel
== 3) {
3978 PACKS(desc
,"z",buf
); /* pszPrinterName */
3980 PACKS(desc
,"z",""); /* pszUserName */
3981 PACKS(desc
,"z",""); /* pszLogAddr */
3982 PACKI(desc
,"W",0); /* uJobId */
3983 PACKI(desc
,"W",0); /* fsStatus */
3984 PACKS(desc
,"z",""); /* pszStatus */
3985 PACKS(desc
,"z",""); /* pszComment */
3986 PACKS(desc
,"z","NULL"); /* pszDrivers */
3987 PACKI(desc
,"W",0); /* time */
3988 PACKI(desc
,"W",0); /* pad1 */
3993 static bool api_WPrintDestGetInfo(connection_struct
*conn
, uint16 vuid
,
3994 char *param
, int tpscnt
,
3995 char *data
, int tdscnt
,
3996 int mdrcnt
,int mprcnt
,
3997 char **rdata
,char **rparam
,
3998 int *rdata_len
,int *rparam_len
)
4000 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4001 char *str2
= skip_string(param
,tpscnt
,str1
);
4002 char *p
= skip_string(param
,tpscnt
,str2
);
4003 char* PrinterName
= p
;
4005 struct pack_desc desc
;
4009 if (!str1
|| !str2
|| !p
) {
4013 memset((char *)&desc
,'\0',sizeof(desc
));
4015 p
= skip_string(param
,tpscnt
,p
);
4019 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4021 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel
,PrinterName
));
4023 /* check it's a supported varient */
4024 if (strcmp(str1
,"zWrLh") != 0) {
4027 if (!check_printdest_info(&desc
,uLevel
,str2
)) {
4031 snum
= find_service(PrinterName
);
4032 if ( !(lp_snum_ok(snum
) && lp_print_ok(snum
)) ) {
4034 desc
.errcode
= NERR_DestNotFound
;
4038 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4043 desc
.buflen
= mdrcnt
;
4046 * Don't return data but need to get correct length
4047 * init_package will return wrong size if buflen=0
4049 desc
.buflen
= getlen(desc
.format
);
4050 desc
.base
= tmpdata
= (char *)SMB_MALLOC( desc
.buflen
);
4052 if (init_package(&desc
,1,0)) {
4053 fill_printdest_info(conn
,snum
,uLevel
,&desc
);
4055 *rdata_len
= desc
.usedlen
;
4059 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4063 SSVALS(*rparam
,0,desc
.errcode
);
4065 SSVAL(*rparam
,4,desc
.neededlen
);
4067 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc
.errcode
));
4073 static bool api_WPrintDestEnum(connection_struct
*conn
, uint16 vuid
,
4074 char *param
, int tpscnt
,
4075 char *data
, int tdscnt
,
4076 int mdrcnt
,int mprcnt
,
4077 char **rdata
,char **rparam
,
4078 int *rdata_len
,int *rparam_len
)
4080 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4081 char *str2
= skip_string(param
,tpscnt
,str1
);
4082 char *p
= skip_string(param
,tpscnt
,str2
);
4086 struct pack_desc desc
;
4087 int services
= lp_numservices();
4089 if (!str1
|| !str2
|| !p
) {
4093 memset((char *)&desc
,'\0',sizeof(desc
));
4095 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4097 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel
));
4099 /* check it's a supported varient */
4100 if (strcmp(str1
,"WrLeh") != 0) {
4103 if (!check_printdest_info(&desc
,uLevel
,str2
)) {
4108 for (i
= 0; i
< services
; i
++) {
4109 if (lp_snum_ok(i
) && lp_print_ok(i
) && lp_browseable(i
)) {
4115 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4122 desc
.buflen
= mdrcnt
;
4123 if (init_package(&desc
,queuecnt
,0)) {
4126 for (i
= 0; i
< services
; i
++) {
4127 if (lp_snum_ok(i
) && lp_print_ok(i
) && lp_browseable(i
)) {
4128 fill_printdest_info(conn
,i
,uLevel
,&desc
);
4130 if (desc
.errcode
== NERR_Success
) {
4137 *rdata_len
= desc
.usedlen
;
4140 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4144 SSVALS(*rparam
,0,desc
.errcode
);
4146 SSVAL(*rparam
,4,succnt
);
4147 SSVAL(*rparam
,6,queuecnt
);
4149 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc
.errcode
));
4154 static bool api_WPrintDriverEnum(connection_struct
*conn
, uint16 vuid
,
4155 char *param
, int tpscnt
,
4156 char *data
, int tdscnt
,
4157 int mdrcnt
,int mprcnt
,
4158 char **rdata
,char **rparam
,
4159 int *rdata_len
,int *rparam_len
)
4161 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4162 char *str2
= skip_string(param
,tpscnt
,str1
);
4163 char *p
= skip_string(param
,tpscnt
,str2
);
4166 struct pack_desc desc
;
4168 if (!str1
|| !str2
|| !p
) {
4172 memset((char *)&desc
,'\0',sizeof(desc
));
4174 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4176 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel
));
4178 /* check it's a supported varient */
4179 if (strcmp(str1
,"WrLeh") != 0) {
4182 if (uLevel
!= 0 || strcmp(str2
,"B41") != 0) {
4187 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4193 desc
.buflen
= mdrcnt
;
4194 if (init_package(&desc
,1,0)) {
4195 PACKS(&desc
,"B41","NULL");
4198 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
4200 *rdata_len
= desc
.usedlen
;
4203 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4207 SSVALS(*rparam
,0,desc
.errcode
);
4209 SSVAL(*rparam
,4,succnt
);
4212 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc
.errcode
));
4217 static bool api_WPrintQProcEnum(connection_struct
*conn
, uint16 vuid
,
4218 char *param
, int tpscnt
,
4219 char *data
, int tdscnt
,
4220 int mdrcnt
,int mprcnt
,
4221 char **rdata
,char **rparam
,
4222 int *rdata_len
,int *rparam_len
)
4224 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4225 char *str2
= skip_string(param
,tpscnt
,str1
);
4226 char *p
= skip_string(param
,tpscnt
,str2
);
4229 struct pack_desc desc
;
4231 if (!str1
|| !str2
|| !p
) {
4234 memset((char *)&desc
,'\0',sizeof(desc
));
4236 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4238 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel
));
4240 /* check it's a supported varient */
4241 if (strcmp(str1
,"WrLeh") != 0) {
4244 if (uLevel
!= 0 || strcmp(str2
,"B13") != 0) {
4249 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4255 desc
.buflen
= mdrcnt
;
4257 if (init_package(&desc
,1,0)) {
4258 PACKS(&desc
,"B13","lpd");
4261 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
4263 *rdata_len
= desc
.usedlen
;
4266 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4270 SSVALS(*rparam
,0,desc
.errcode
);
4272 SSVAL(*rparam
,4,succnt
);
4275 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc
.errcode
));
4280 static bool api_WPrintPortEnum(connection_struct
*conn
, uint16 vuid
,
4281 char *param
, int tpscnt
,
4282 char *data
, int tdscnt
,
4283 int mdrcnt
,int mprcnt
,
4284 char **rdata
,char **rparam
,
4285 int *rdata_len
,int *rparam_len
)
4287 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4288 char *str2
= skip_string(param
,tpscnt
,str1
);
4289 char *p
= skip_string(param
,tpscnt
,str2
);
4292 struct pack_desc desc
;
4294 if (!str1
|| !str2
|| !p
) {
4298 memset((char *)&desc
,'\0',sizeof(desc
));
4300 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4302 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel
));
4304 /* check it's a supported varient */
4305 if (strcmp(str1
,"WrLeh") != 0) {
4308 if (uLevel
!= 0 || strcmp(str2
,"B9") != 0) {
4313 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4318 memset((char *)&desc
,'\0',sizeof(desc
));
4320 desc
.buflen
= mdrcnt
;
4322 if (init_package(&desc
,1,0)) {
4323 PACKS(&desc
,"B13","lp0");
4326 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
4328 *rdata_len
= desc
.usedlen
;
4331 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4335 SSVALS(*rparam
,0,desc
.errcode
);
4337 SSVAL(*rparam
,4,succnt
);
4340 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc
.errcode
));
4345 /****************************************************************************
4347 ****************************************************************************/
4349 static bool api_RNetSessionEnum(connection_struct
*conn
, uint16 vuid
,
4350 char *param
, int tpscnt
,
4351 char *data
, int tdscnt
,
4352 int mdrcnt
,int mprcnt
,
4353 char **rdata
,char **rparam
,
4354 int *rdata_len
,int *rparam_len
)
4357 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4358 char *str2
= skip_string(param
,tpscnt
,str1
);
4359 char *p
= skip_string(param
,tpscnt
,str2
);
4361 struct pack_desc desc
;
4362 struct sessionid
*session_list
;
4363 int i
, num_sessions
;
4365 if (!str1
|| !str2
|| !p
) {
4369 memset((char *)&desc
,'\0',sizeof(desc
));
4371 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4373 DEBUG(3,("RNetSessionEnum uLevel=%d\n",uLevel
));
4374 DEBUG(7,("RNetSessionEnum req string=%s\n",str1
));
4375 DEBUG(7,("RNetSessionEnum ret string=%s\n",str2
));
4377 /* check it's a supported varient */
4378 if (strcmp(str1
,RAP_NetSessionEnum_REQ
) != 0) {
4381 if (uLevel
!= 2 || strcmp(str2
,RAP_SESSION_INFO_L2
) != 0) {
4385 num_sessions
= list_sessions(talloc_tos(), &session_list
);
4388 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4393 memset((char *)&desc
,'\0',sizeof(desc
));
4395 desc
.buflen
= mdrcnt
;
4397 if (!init_package(&desc
,num_sessions
,0)) {
4401 for(i
=0; i
<num_sessions
; i
++) {
4402 PACKS(&desc
, "z", session_list
[i
].remote_machine
);
4403 PACKS(&desc
, "z", session_list
[i
].username
);
4404 PACKI(&desc
, "W", 1); /* num conns */
4405 PACKI(&desc
, "W", 0); /* num opens */
4406 PACKI(&desc
, "W", 1); /* num users */
4407 PACKI(&desc
, "D", 0); /* session time */
4408 PACKI(&desc
, "D", 0); /* idle time */
4409 PACKI(&desc
, "D", 0); /* flags */
4410 PACKS(&desc
, "z", "Unknown Client"); /* client type string */
4413 *rdata_len
= desc
.usedlen
;
4416 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4420 SSVALS(*rparam
,0,desc
.errcode
);
4421 SSVAL(*rparam
,2,0); /* converter */
4422 SSVAL(*rparam
,4,num_sessions
); /* count */
4424 DEBUG(4,("RNetSessionEnum: errorcode %d\n",desc
.errcode
));
4430 /****************************************************************************
4431 The buffer was too small.
4432 ****************************************************************************/
4434 static bool api_TooSmall(connection_struct
*conn
,uint16 vuid
, char *param
, char *data
,
4435 int mdrcnt
, int mprcnt
,
4436 char **rdata
, char **rparam
,
4437 int *rdata_len
, int *rparam_len
)
4439 *rparam_len
= MIN(*rparam_len
,mprcnt
);
4440 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4447 SSVAL(*rparam
,0,NERR_BufTooSmall
);
4449 DEBUG(3,("Supplied buffer too small in API command\n"));
4454 /****************************************************************************
4455 The request is not supported.
4456 ****************************************************************************/
4458 static bool api_Unsupported(connection_struct
*conn
, uint16 vuid
,
4459 char *param
, int tpscnt
,
4460 char *data
, int tdscnt
,
4461 int mdrcnt
, int mprcnt
,
4462 char **rdata
, char **rparam
,
4463 int *rdata_len
, int *rparam_len
)
4466 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4473 SSVAL(*rparam
,0,NERR_notsupported
);
4474 SSVAL(*rparam
,2,0); /* converter word */
4476 DEBUG(3,("Unsupported API command\n"));
4481 static const struct {
4484 bool (*fn
)(connection_struct
*, uint16
,
4487 int,int,char **,char **,int *,int *);
4488 bool auth_user
; /* Deny anonymous access? */
4489 } api_commands
[] = {
4490 {"RNetShareEnum", RAP_WshareEnum
, api_RNetShareEnum
, True
},
4491 {"RNetShareGetInfo", RAP_WshareGetInfo
, api_RNetShareGetInfo
},
4492 {"RNetShareAdd", RAP_WshareAdd
, api_RNetShareAdd
},
4493 {"RNetSessionEnum", RAP_WsessionEnum
, api_RNetSessionEnum
, True
},
4494 {"RNetServerGetInfo", RAP_WserverGetInfo
, api_RNetServerGetInfo
},
4495 {"RNetGroupEnum", RAP_WGroupEnum
, api_RNetGroupEnum
, True
},
4496 {"RNetGroupGetUsers", RAP_WGroupGetUsers
, api_RNetGroupGetUsers
, True
},
4497 {"RNetUserEnum", RAP_WUserEnum
, api_RNetUserEnum
, True
},
4498 {"RNetUserGetInfo", RAP_WUserGetInfo
, api_RNetUserGetInfo
},
4499 {"NetUserGetGroups", RAP_WUserGetGroups
, api_NetUserGetGroups
},
4500 {"NetWkstaGetInfo", RAP_WWkstaGetInfo
, api_NetWkstaGetInfo
},
4501 {"DosPrintQEnum", RAP_WPrintQEnum
, api_DosPrintQEnum
, True
},
4502 {"DosPrintQGetInfo", RAP_WPrintQGetInfo
, api_DosPrintQGetInfo
},
4503 {"WPrintQueuePause", RAP_WPrintQPause
, api_WPrintQueueCtrl
},
4504 {"WPrintQueueResume", RAP_WPrintQContinue
, api_WPrintQueueCtrl
},
4505 {"WPrintJobEnumerate",RAP_WPrintJobEnum
, api_WPrintJobEnumerate
},
4506 {"WPrintJobGetInfo", RAP_WPrintJobGetInfo
, api_WPrintJobGetInfo
},
4507 {"RDosPrintJobDel", RAP_WPrintJobDel
, api_RDosPrintJobDel
},
4508 {"RDosPrintJobPause", RAP_WPrintJobPause
, api_RDosPrintJobDel
},
4509 {"RDosPrintJobResume",RAP_WPrintJobContinue
, api_RDosPrintJobDel
},
4510 {"WPrintDestEnum", RAP_WPrintDestEnum
, api_WPrintDestEnum
},
4511 {"WPrintDestGetInfo", RAP_WPrintDestGetInfo
, api_WPrintDestGetInfo
},
4512 {"NetRemoteTOD", RAP_NetRemoteTOD
, api_NetRemoteTOD
},
4513 {"WPrintQueuePurge", RAP_WPrintQPurge
, api_WPrintQueueCtrl
},
4514 {"NetServerEnum", RAP_NetServerEnum2
, api_RNetServerEnum
}, /* anon OK */
4515 {"WAccessGetUserPerms",RAP_WAccessGetUserPerms
,api_WAccessGetUserPerms
},
4516 {"SetUserPassword", RAP_WUserPasswordSet2
, api_SetUserPassword
},
4517 {"WWkstaUserLogon", RAP_WWkstaUserLogon
, api_WWkstaUserLogon
},
4518 {"PrintJobInfo", RAP_WPrintJobSetInfo
, api_PrintJobInfo
},
4519 {"WPrintDriverEnum", RAP_WPrintDriverEnum
, api_WPrintDriverEnum
},
4520 {"WPrintQProcEnum", RAP_WPrintQProcessorEnum
,api_WPrintQProcEnum
},
4521 {"WPrintPortEnum", RAP_WPrintPortEnum
, api_WPrintPortEnum
},
4522 {"SamOEMChangePassword",RAP_SamOEMChgPasswordUser2_P
,api_SamOEMChangePassword
}, /* anon OK */
4523 {NULL
, -1, api_Unsupported
}
4524 /* The following RAP calls are not implemented by Samba:
4526 RAP_WFileEnum2 - anon not OK
4531 /****************************************************************************
4532 Handle remote api calls.
4533 ****************************************************************************/
4535 void api_reply(connection_struct
*conn
, uint16 vuid
,
4536 struct smb_request
*req
,
4537 char *data
, char *params
,
4538 int tdscnt
, int tpscnt
,
4539 int mdrcnt
, int mprcnt
)
4543 char *rparam
= NULL
;
4544 const char *name1
= NULL
;
4545 const char *name2
= NULL
;
4552 DEBUG(0,("ERROR: NULL params in api_reply()\n"));
4553 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4558 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4561 api_command
= SVAL(params
,0);
4562 /* Is there a string at position params+2 ? */
4563 if (skip_string(params
,tpscnt
,params
+2)) {
4568 name2
= skip_string(params
,tpscnt
,params
+2);
4573 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
4577 tdscnt
,tpscnt
,mdrcnt
,mprcnt
));
4579 for (i
=0;api_commands
[i
].name
;i
++) {
4580 if (api_commands
[i
].id
== api_command
&& api_commands
[i
].fn
) {
4581 DEBUG(3,("Doing %s\n",api_commands
[i
].name
));
4586 /* Check whether this api call can be done anonymously */
4588 if (api_commands
[i
].auth_user
&& lp_restrict_anonymous()) {
4589 user_struct
*user
= get_valid_user_struct(vuid
);
4591 if (!user
|| user
->server_info
->guest
) {
4592 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4597 rdata
= (char *)SMB_MALLOC(1024);
4599 memset(rdata
,'\0',1024);
4602 rparam
= (char *)SMB_MALLOC(1024);
4604 memset(rparam
,'\0',1024);
4607 if(!rdata
|| !rparam
) {
4608 DEBUG(0,("api_reply: malloc fail !\n"));
4611 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4615 reply
= api_commands
[i
].fn(conn
,
4617 params
,tpscnt
, /* params + length */
4618 data
,tdscnt
, /* data + length */
4620 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
4623 if (rdata_len
> mdrcnt
|| rparam_len
> mprcnt
) {
4624 reply
= api_TooSmall(conn
,vuid
,params
,data
,mdrcnt
,mprcnt
,
4625 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
4628 /* if we get False back then it's actually unsupported */
4630 reply
= api_Unsupported(conn
,vuid
,params
,tpscnt
,data
,tdscnt
,mdrcnt
,mprcnt
,
4631 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
4634 /* If api_Unsupported returns false we can't return anything. */
4636 send_trans_reply(conn
, req
->inbuf
, rparam
, rparam_len
,
4637 rdata
, rdata_len
, False
);