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
);
1218 s
->domain
[0] = '\0';
1219 if (!next_token_talloc(frame
,&ptr
,&p
, NULL
)) {
1220 /* this allows us to cope with an old nmbd */
1221 fstrcpy(s
->domain
,lp_workgroup());
1223 fstrcpy(s
->domain
, p
);
1227 if (sscanf(stype
,"%X",&s
->type
) != 1) {
1228 DEBUG(4,("r:host file "));
1232 /* Filter the servers/domains we return based on what was asked for. */
1234 /* Check to see if we are being asked for a local list only. */
1235 if(local_list_only
&& ((s
->type
& SV_TYPE_LOCAL_LIST_ONLY
) == 0)) {
1236 DEBUG(4,("r: local list only"));
1240 /* doesn't match up: don't want it */
1241 if (!(servertype
& s
->type
)) {
1242 DEBUG(4,("r:serv type "));
1246 if ((servertype
& SV_TYPE_DOMAIN_ENUM
) !=
1247 (s
->type
& SV_TYPE_DOMAIN_ENUM
)) {
1248 DEBUG(4,("s: dom mismatch "));
1252 if (!strequal(domain
, s
->domain
) && !(servertype
& SV_TYPE_DOMAIN_ENUM
)) {
1256 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
1257 s
->type
&= ~SV_TYPE_LOCAL_LIST_ONLY
;
1260 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
1261 s
->name
, s
->type
, s
->comment
, s
->domain
));
1262 s
->server_added
= True
;
1265 DEBUG(4,("%20s %8x %25s %15s\n",
1266 s
->name
, s
->type
, s
->comment
, s
->domain
));
1270 file_lines_free(lines
);
1274 /*******************************************************************
1275 Fill in a server info structure.
1276 ******************************************************************/
1278 static int fill_srv_info(struct srv_info_struct
*service
,
1279 int uLevel
, char **buf
, int *buflen
,
1280 char **stringbuf
, int *stringspace
, char *baseaddr
)
1303 len
= strlen(service
->comment
)+1;
1307 *buflen
= struct_len
;
1309 return struct_len
+ len
;
1314 if (*buflen
< struct_len
) {
1321 p2
= p
+ struct_len
;
1322 l2
= *buflen
- struct_len
;
1330 push_ascii(p
,service
->name
, MAX_NETBIOSNAME_LEN
, STR_TERMINATE
);
1334 push_ascii(p
,service
->name
,MAX_NETBIOSNAME_LEN
, STR_TERMINATE
);
1335 SIVAL(p
,18,service
->type
);
1336 SIVAL(p
,22,PTR_DIFF(p2
,baseaddr
));
1337 len
+= CopyAndAdvance(&p2
,service
->comment
,&l2
);
1342 *buf
= p
+ struct_len
;
1343 *buflen
-= struct_len
;
1354 static bool srv_comp(struct srv_info_struct
*s1
,struct srv_info_struct
*s2
)
1356 return(strcmp(s1
->name
,s2
->name
));
1359 /****************************************************************************
1360 View list of servers available (or possibly domains). The info is
1361 extracted from lists saved by nmbd on the local host.
1362 ****************************************************************************/
1364 static bool api_RNetServerEnum(connection_struct
*conn
, uint16 vuid
,
1365 char *param
, int tpscnt
,
1366 char *data
, int tdscnt
,
1367 int mdrcnt
, int mprcnt
, char **rdata
,
1368 char **rparam
, int *rdata_len
, int *rparam_len
)
1370 char *str1
= get_safe_str_ptr(param
, tpscnt
, param
, 2);
1371 char *str2
= skip_string(param
,tpscnt
,str1
);
1372 char *p
= skip_string(param
,tpscnt
,str2
);
1373 int uLevel
= get_safe_SVAL(param
, tpscnt
, p
, 0, -1);
1374 int buf_len
= get_safe_SVAL(param
,tpscnt
, p
, 2, 0);
1375 uint32 servertype
= get_safe_IVAL(param
,tpscnt
,p
,4, 0);
1377 int data_len
, fixed_len
, string_len
;
1378 int f_len
= 0, s_len
= 0;
1379 struct srv_info_struct
*servers
=NULL
;
1380 int counted
=0,total
=0;
1383 bool domain_request
;
1386 if (!str1
|| !str2
|| !p
) {
1390 /* If someone sets all the bits they don't really mean to set
1391 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1394 if (servertype
== SV_TYPE_ALL
) {
1395 servertype
&= ~(SV_TYPE_DOMAIN_ENUM
|SV_TYPE_LOCAL_LIST_ONLY
);
1398 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1399 any other bit (they may just set this bit on its own) they
1400 want all the locally seen servers. However this bit can be
1401 set on its own so set the requested servers to be
1402 ALL - DOMAIN_ENUM. */
1404 if ((servertype
& SV_TYPE_LOCAL_LIST_ONLY
) && !(servertype
& SV_TYPE_DOMAIN_ENUM
)) {
1405 servertype
= SV_TYPE_ALL
& ~(SV_TYPE_DOMAIN_ENUM
);
1408 domain_request
= ((servertype
& SV_TYPE_DOMAIN_ENUM
) != 0);
1409 local_request
= ((servertype
& SV_TYPE_LOCAL_LIST_ONLY
) != 0);
1413 if (!prefix_ok(str1
,"WrLehD")) {
1416 if (!check_server_info(uLevel
,str2
)) {
1420 DEBUG(4, ("server request level: %s %8x ", str2
, servertype
));
1421 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request
)));
1422 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request
)));
1424 if (strcmp(str1
, "WrLehDz") == 0) {
1425 if (skip_string(param
,tpscnt
,p
) == NULL
) {
1428 pull_ascii_fstring(domain
, p
);
1430 fstrcpy(domain
, lp_workgroup());
1433 if (lp_browse_list()) {
1434 total
= get_server_info(servertype
,&servers
,domain
);
1437 data_len
= fixed_len
= string_len
= 0;
1441 qsort(servers
,total
,sizeof(servers
[0]),QSORT_CAST srv_comp
);
1445 char *lastname
=NULL
;
1447 for (i
=0;i
<total
;i
++) {
1448 struct srv_info_struct
*s
= &servers
[i
];
1450 if (lastname
&& strequal(lastname
,s
->name
)) {
1454 data_len
+= fill_srv_info(s
,uLevel
,0,&f_len
,0,&s_len
,0);
1455 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1456 s
->name
, s
->type
, s
->comment
, s
->domain
));
1458 if (data_len
<= buf_len
) {
1461 string_len
+= s_len
;
1468 *rdata_len
= fixed_len
+ string_len
;
1469 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
1474 p2
= (*rdata
) + fixed_len
; /* auxilliary data (strings) will go here */
1480 char *lastname
=NULL
;
1481 int count2
= counted
;
1483 for (i
= 0; i
< total
&& count2
;i
++) {
1484 struct srv_info_struct
*s
= &servers
[i
];
1486 if (lastname
&& strequal(lastname
,s
->name
)) {
1490 fill_srv_info(s
,uLevel
,&p
,&f_len
,&p2
,&s_len
,*rdata
);
1491 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1492 s
->name
, s
->type
, s
->comment
, s
->domain
));
1498 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1502 SSVAL(*rparam
,0,(missed
== 0 ? NERR_Success
: ERRmoredata
));
1504 SSVAL(*rparam
,4,counted
);
1505 SSVAL(*rparam
,6,counted
+missed
);
1509 DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
1510 domain
,uLevel
,counted
,counted
+missed
));
1515 /****************************************************************************
1516 command 0x34 - suspected of being a "Lookup Names" stub api
1517 ****************************************************************************/
1519 static bool api_RNetGroupGetUsers(connection_struct
*conn
, uint16 vuid
,
1520 char *param
, int tpscnt
,
1521 char *data
, int tdscnt
,
1522 int mdrcnt
, int mprcnt
, char **rdata
,
1523 char **rparam
, int *rdata_len
, int *rparam_len
)
1525 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
1526 char *str2
= skip_string(param
,tpscnt
,str1
);
1527 char *p
= skip_string(param
,tpscnt
,str2
);
1528 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
1529 int buf_len
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
1533 if (!str1
|| !str2
|| !p
) {
1537 DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
1538 str1
, str2
, p
, uLevel
, buf_len
));
1540 if (!prefix_ok(str1
,"zWrLeh")) {
1547 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1552 SSVAL(*rparam
,0,0x08AC); /* informational warning message */
1554 SSVAL(*rparam
,4,counted
);
1555 SSVAL(*rparam
,6,counted
+missed
);
1560 /****************************************************************************
1561 get info about a share
1562 ****************************************************************************/
1564 static bool check_share_info(int uLevel
, char* id
)
1568 if (strcmp(id
,"B13") != 0) {
1573 if (strcmp(id
,"B13BWz") != 0) {
1578 if (strcmp(id
,"B13BWzWWWzB9B") != 0) {
1583 if (strcmp(id
,"B13BWzWWWzB9BB9BWzWWzWW") != 0) {
1593 static int fill_share_info(connection_struct
*conn
, int snum
, int uLevel
,
1594 char** buf
, int* buflen
,
1595 char** stringbuf
, int* stringspace
, char* baseaddr
)
1625 len
+= StrlenExpanded(conn
,snum
,lp_comment(snum
));
1628 len
+= strlen(lp_pathname(snum
)) + 1;
1631 *buflen
= struct_len
;
1636 return struct_len
+ len
;
1641 if ((*buflen
) < struct_len
) {
1649 p2
= p
+ struct_len
;
1650 l2
= (*buflen
) - struct_len
;
1657 push_ascii(p
,lp_servicename(snum
),13, STR_TERMINATE
);
1663 type
= STYPE_DISKTREE
;
1664 if (lp_print_ok(snum
)) {
1665 type
= STYPE_PRINTQ
;
1667 if (strequal("IPC",lp_fstype(snum
))) {
1670 SSVAL(p
,14,type
); /* device type */
1671 SIVAL(p
,16,PTR_DIFF(p2
,baseaddr
));
1672 len
+= CopyExpanded(conn
,snum
,&p2
,lp_comment(snum
),&l2
);
1676 SSVAL(p
,20,ACCESS_READ
|ACCESS_WRITE
|ACCESS_CREATE
); /* permissions */
1677 SSVALS(p
,22,-1); /* max uses */
1678 SSVAL(p
,24,1); /* current uses */
1679 SIVAL(p
,26,PTR_DIFF(p2
,baseaddr
)); /* local pathname */
1680 len
+= CopyAndAdvance(&p2
,lp_pathname(snum
),&l2
);
1681 memset(p
+30,0,SHPWLEN
+2); /* passwd (reserved), pad field */
1685 memset(p
+40,0,SHPWLEN
+2);
1696 (*buf
) = p
+ struct_len
;
1697 (*buflen
) -= struct_len
;
1699 (*stringspace
) = l2
;
1708 static bool api_RNetShareGetInfo(connection_struct
*conn
,uint16 vuid
,
1709 char *param
, int tpscnt
,
1710 char *data
, int tdscnt
,
1711 int mdrcnt
,int mprcnt
,
1712 char **rdata
,char **rparam
,
1713 int *rdata_len
,int *rparam_len
)
1715 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
1716 char *str2
= skip_string(param
,tpscnt
,str1
);
1717 char *netname
= skip_string(param
,tpscnt
,str2
);
1718 char *p
= skip_string(param
,tpscnt
,netname
);
1719 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
1722 if (!str1
|| !str2
|| !netname
|| !p
) {
1726 snum
= find_service(netname
);
1731 /* check it's a supported varient */
1732 if (!prefix_ok(str1
,"zWrLh")) {
1735 if (!check_share_info(uLevel
,str2
)) {
1739 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
1744 *rdata_len
= fill_share_info(conn
,snum
,uLevel
,&p
,&mdrcnt
,0,0,0);
1745 if (*rdata_len
< 0) {
1750 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1754 SSVAL(*rparam
,0,NERR_Success
);
1755 SSVAL(*rparam
,2,0); /* converter word */
1756 SSVAL(*rparam
,4,*rdata_len
);
1761 /****************************************************************************
1762 View the list of available shares.
1764 This function is the server side of the NetShareEnum() RAP call.
1765 It fills the return buffer with share names and share comments.
1766 Note that the return buffer normally (in all known cases) allows only
1767 twelve byte strings for share names (plus one for a nul terminator).
1768 Share names longer than 12 bytes must be skipped.
1769 ****************************************************************************/
1771 static bool api_RNetShareEnum( connection_struct
*conn
, uint16 vuid
,
1772 char *param
, int tpscnt
,
1773 char *data
, int tdscnt
,
1781 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
1782 char *str2
= skip_string(param
,tpscnt
,str1
);
1783 char *p
= skip_string(param
,tpscnt
,str2
);
1784 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
1785 int buf_len
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
1788 int total
=0,counted
=0;
1789 bool missed
= False
;
1791 int data_len
, fixed_len
, string_len
;
1792 int f_len
= 0, s_len
= 0;
1794 if (!str1
|| !str2
|| !p
) {
1798 if (!prefix_ok(str1
,"WrLeh")) {
1801 if (!check_share_info(uLevel
,str2
)) {
1805 /* Ensure all the usershares are loaded. */
1807 load_registry_shares();
1808 count
= load_usershare_shares();
1811 data_len
= fixed_len
= string_len
= 0;
1812 for (i
=0;i
<count
;i
++) {
1813 fstring servicename_dos
;
1814 if (!(lp_browseable(i
) && lp_snum_ok(i
))) {
1817 push_ascii_fstring(servicename_dos
, lp_servicename(i
));
1818 /* Maximum name length = 13. */
1819 if( lp_browseable( i
) && lp_snum_ok( i
) && (strlen(servicename_dos
) < 13)) {
1821 data_len
+= fill_share_info(conn
,i
,uLevel
,0,&f_len
,0,&s_len
,0);
1822 if (data_len
<= buf_len
) {
1825 string_len
+= s_len
;
1832 *rdata_len
= fixed_len
+ string_len
;
1833 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
1838 p2
= (*rdata
) + fixed_len
; /* auxiliary data (strings) will go here */
1843 for( i
= 0; i
< count
; i
++ ) {
1844 fstring servicename_dos
;
1845 if (!(lp_browseable(i
) && lp_snum_ok(i
))) {
1849 push_ascii_fstring(servicename_dos
, lp_servicename(i
));
1850 if (lp_browseable(i
) && lp_snum_ok(i
) && (strlen(servicename_dos
) < 13)) {
1851 if (fill_share_info( conn
,i
,uLevel
,&p
,&f_len
,&p2
,&s_len
,*rdata
) < 0) {
1858 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1862 SSVAL(*rparam
,0,missed
? ERRmoredata
: NERR_Success
);
1864 SSVAL(*rparam
,4,counted
);
1865 SSVAL(*rparam
,6,total
);
1867 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
1868 counted
,total
,uLevel
,
1869 buf_len
,*rdata_len
,mdrcnt
));
1874 /****************************************************************************
1876 ****************************************************************************/
1878 static bool api_RNetShareAdd(connection_struct
*conn
,uint16 vuid
,
1879 char *param
, int tpscnt
,
1880 char *data
, int tdscnt
,
1881 int mdrcnt
,int mprcnt
,
1882 char **rdata
,char **rparam
,
1883 int *rdata_len
,int *rparam_len
)
1885 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
1886 char *str2
= skip_string(param
,tpscnt
,str1
);
1887 char *p
= skip_string(param
,tpscnt
,str2
);
1888 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
1891 char *pathname
= NULL
;
1892 char *command
, *cmdname
;
1893 unsigned int offset
;
1896 size_t converted_size
;
1898 if (!str1
|| !str2
|| !p
) {
1902 /* check it's a supported varient */
1903 if (!prefix_ok(str1
,RAP_WShareAdd_REQ
)) {
1906 if (!check_share_info(uLevel
,str2
)) {
1913 /* Do we have a string ? */
1914 if (skip_string(data
,mdrcnt
,data
) == NULL
) {
1917 pull_ascii_fstring(sharename
,data
);
1918 snum
= find_service(sharename
);
1919 if (snum
>= 0) { /* already exists */
1928 /* only support disk share adds */
1929 if (SVAL(data
,14)!=STYPE_DISKTREE
) {
1933 offset
= IVAL(data
, 16);
1934 if (offset
>= mdrcnt
) {
1935 res
= ERRinvalidparam
;
1939 /* Do we have a string ? */
1940 if (skip_string(data
,mdrcnt
,data
+offset
) == NULL
) {
1943 pull_ascii_fstring(comment
, offset
? (data
+offset
) : "");
1945 offset
= IVAL(data
, 26);
1947 if (offset
>= mdrcnt
) {
1948 res
= ERRinvalidparam
;
1952 /* Do we have a string ? */
1953 if (skip_string(data
,mdrcnt
,data
+offset
) == NULL
) {
1957 if (!pull_ascii_talloc(talloc_tos(), &pathname
,
1958 offset
? (data
+offset
) : "", &converted_size
))
1960 DEBUG(0,("api_RNetShareAdd: pull_ascii_talloc failed: %s",
1968 string_replace(sharename
, '"', ' ');
1969 string_replace(pathname
, '"', ' ');
1970 string_replace(comment
, '"', ' ');
1972 cmdname
= lp_add_share_cmd();
1974 if (!cmdname
|| *cmdname
== '\0') {
1978 if (asprintf(&command
, "%s \"%s\" \"%s\" \"%s\" \"%s\"",
1979 lp_add_share_cmd(), get_dyn_CONFIGFILE(), sharename
,
1980 pathname
, comment
) == -1) {
1984 DEBUG(10,("api_RNetShareAdd: Running [%s]\n", command
));
1986 if ((res
= smbrun(command
, NULL
)) != 0) {
1987 DEBUG(1,("api_RNetShareAdd: Running [%s] returned (%d)\n",
1994 message_send_all(smbd_messaging_context(),
1995 MSG_SMB_CONF_UPDATED
, NULL
, 0, NULL
);
1999 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2003 SSVAL(*rparam
,0,NERR_Success
);
2004 SSVAL(*rparam
,2,0); /* converter word */
2005 SSVAL(*rparam
,4,*rdata_len
);
2013 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2018 SSVAL(*rparam
,0,res
);
2023 /****************************************************************************
2024 view list of groups available
2025 ****************************************************************************/
2027 static bool api_RNetGroupEnum(connection_struct
*conn
,uint16 vuid
,
2028 char *param
, int tpscnt
,
2029 char *data
, int tdscnt
,
2030 int mdrcnt
,int mprcnt
,
2031 char **rdata
,char **rparam
,
2032 int *rdata_len
,int *rparam_len
)
2036 int resume_context
, cli_buf_size
;
2037 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2038 char *str2
= skip_string(param
,tpscnt
,str1
);
2039 char *p
= skip_string(param
,tpscnt
,str2
);
2041 struct pdb_search
*search
;
2042 struct samr_displayentry
*entries
;
2046 if (!str1
|| !str2
|| !p
) {
2050 if (strcmp(str1
,"WrLeh") != 0) {
2055 * W-> resume context (number of users to skip)
2056 * r -> return parameter pointer to receive buffer
2057 * L -> length of receive buffer
2058 * e -> return parameter number of entries
2059 * h -> return parameter total number of users
2062 if (strcmp("B21",str2
) != 0) {
2066 /* get list of domain groups SID_DOMAIN_GRP=2 */
2068 search
= pdb_search_groups();
2071 if (search
== NULL
) {
2072 DEBUG(3,("api_RNetGroupEnum:failed to get group list"));
2076 resume_context
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2077 cli_buf_size
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
2078 DEBUG(10,("api_RNetGroupEnum:resume context: %d, client buffer size: "
2079 "%d\n", resume_context
, cli_buf_size
));
2082 num_entries
= pdb_search_entries(search
, resume_context
, 0xffffffff,
2086 *rdata_len
= cli_buf_size
;
2087 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2094 for(i
=0; i
<num_entries
; i
++) {
2096 fstrcpy(name
, entries
[i
].account_name
);
2097 if( ((PTR_DIFF(p
,*rdata
)+21) <= *rdata_len
) ) {
2098 /* truncate the name at 21 chars. */
2099 memcpy(p
, name
, 21);
2100 DEBUG(10,("adding entry %d group %s\n", i
, p
));
2102 p
+= 5; /* Both NT4 and W2k3SP1 do padding here.
2105 /* set overflow error */
2106 DEBUG(3,("overflow on entry %d group %s\n", i
, name
));
2112 pdb_search_destroy(search
);
2114 *rdata_len
= PTR_DIFF(p
,*rdata
);
2117 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2121 SSVAL(*rparam
, 0, errflags
);
2122 SSVAL(*rparam
, 2, 0); /* converter word */
2123 SSVAL(*rparam
, 4, i
); /* is this right?? */
2124 SSVAL(*rparam
, 6, resume_context
+num_entries
); /* is this right?? */
2129 /*******************************************************************
2130 Get groups that a user is a member of.
2131 ******************************************************************/
2133 static bool api_NetUserGetGroups(connection_struct
*conn
,uint16 vuid
,
2134 char *param
, int tpscnt
,
2135 char *data
, int tdscnt
,
2136 int mdrcnt
,int mprcnt
,
2137 char **rdata
,char **rparam
,
2138 int *rdata_len
,int *rparam_len
)
2140 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2141 char *str2
= skip_string(param
,tpscnt
,str1
);
2142 char *UserName
= skip_string(param
,tpscnt
,str2
);
2143 char *p
= skip_string(param
,tpscnt
,UserName
);
2144 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2145 const char *level_string
;
2147 struct samu
*sampw
= NULL
;
2155 enum lsa_SidType type
;
2157 TALLOC_CTX
*mem_ctx
;
2159 if (!str1
|| !str2
|| !UserName
|| !p
) {
2164 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2169 /* check it's a supported varient */
2171 if ( strcmp(str1
,"zWrLeh") != 0 )
2176 level_string
= "B21";
2182 if (strcmp(level_string
,str2
) != 0)
2185 *rdata_len
= mdrcnt
+ 1024;
2186 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2191 SSVAL(*rparam
,0,NERR_Success
);
2192 SSVAL(*rparam
,2,0); /* converter word */
2195 endp
= *rdata
+ *rdata_len
;
2197 mem_ctx
= talloc_new(NULL
);
2198 if (mem_ctx
== NULL
) {
2199 DEBUG(0, ("talloc_new failed\n"));
2203 if ( !(sampw
= samu_new(mem_ctx
)) ) {
2204 DEBUG(0, ("samu_new() failed!\n"));
2205 TALLOC_FREE(mem_ctx
);
2209 /* Lookup the user information; This should only be one of
2210 our accounts (not remote domains) */
2212 become_root(); /* ROOT BLOCK */
2214 if (!lookup_name(mem_ctx
, UserName
, LOOKUP_NAME_ALL
,
2215 NULL
, NULL
, &user_sid
, &type
)) {
2216 DEBUG(10, ("lookup_name(%s) failed\n", UserName
));
2220 if (type
!= SID_NAME_USER
) {
2221 DEBUG(10, ("%s is a %s, not a user\n", UserName
,
2222 sid_type_lookup(type
)));
2226 if ( !pdb_getsampwsid(sampw
, &user_sid
) ) {
2227 DEBUG(10, ("pdb_getsampwsid(%s) failed for user %s\n",
2228 sid_string_dbg(&user_sid
), UserName
));
2236 result
= pdb_enum_group_memberships(mem_ctx
, sampw
,
2237 &sids
, &gids
, &num_groups
);
2239 if (!NT_STATUS_IS_OK(result
)) {
2240 DEBUG(10, ("pdb_enum_group_memberships failed for %s\n",
2245 for (i
=0; i
<num_groups
; i
++) {
2246 const char *grp_name
;
2248 if ( lookup_sid(mem_ctx
, &sids
[i
], NULL
, &grp_name
, NULL
) ) {
2249 strlcpy(p
, grp_name
, PTR_DIFF(endp
,p
));
2255 *rdata_len
= PTR_DIFF(p
,*rdata
);
2257 SSVAL(*rparam
,4,count
); /* is this right?? */
2258 SSVAL(*rparam
,6,count
); /* is this right?? */
2263 unbecome_root(); /* END ROOT BLOCK */
2265 TALLOC_FREE(mem_ctx
);
2270 /*******************************************************************
2272 ******************************************************************/
2274 static bool api_RNetUserEnum(connection_struct
*conn
, uint16 vuid
,
2275 char *param
, int tpscnt
,
2276 char *data
, int tdscnt
,
2277 int mdrcnt
,int mprcnt
,
2278 char **rdata
,char **rparam
,
2279 int *rdata_len
,int *rparam_len
)
2284 int i
, resume_context
, cli_buf_size
;
2285 struct pdb_search
*search
;
2286 struct samr_displayentry
*users
;
2288 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2289 char *str2
= skip_string(param
,tpscnt
,str1
);
2290 char *p
= skip_string(param
,tpscnt
,str2
);
2293 if (!str1
|| !str2
|| !p
) {
2297 if (strcmp(str1
,"WrLeh") != 0)
2300 * W-> resume context (number of users to skip)
2301 * r -> return parameter pointer to receive buffer
2302 * L -> length of receive buffer
2303 * e -> return parameter number of entries
2304 * h -> return parameter total number of users
2307 resume_context
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2308 cli_buf_size
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
2309 DEBUG(10,("api_RNetUserEnum:resume context: %d, client buffer size: %d\n",
2310 resume_context
, cli_buf_size
));
2313 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2318 /* check it's a supported varient */
2319 if (strcmp("B21",str2
) != 0)
2322 *rdata_len
= cli_buf_size
;
2323 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2329 endp
= *rdata
+ *rdata_len
;
2332 search
= pdb_search_users(ACB_NORMAL
);
2334 if (search
== NULL
) {
2335 DEBUG(0, ("api_RNetUserEnum:unable to open sam database.\n"));
2340 num_users
= pdb_search_entries(search
, resume_context
, 0xffffffff,
2344 errflags
=NERR_Success
;
2346 for (i
=0; i
<num_users
; i
++) {
2347 const char *name
= users
[i
].account_name
;
2349 if(((PTR_DIFF(p
,*rdata
)+21)<=*rdata_len
)&&(strlen(name
)<=21)) {
2350 strlcpy(p
,name
,PTR_DIFF(endp
,p
));
2351 DEBUG(10,("api_RNetUserEnum:adding entry %d username "
2352 "%s\n",count_sent
,p
));
2356 /* set overflow error */
2357 DEBUG(10,("api_RNetUserEnum:overflow on entry %d "
2358 "username %s\n",count_sent
,name
));
2364 pdb_search_destroy(search
);
2366 *rdata_len
= PTR_DIFF(p
,*rdata
);
2368 SSVAL(*rparam
,0,errflags
);
2369 SSVAL(*rparam
,2,0); /* converter word */
2370 SSVAL(*rparam
,4,count_sent
); /* is this right?? */
2371 SSVAL(*rparam
,6,num_users
); /* is this right?? */
2376 /****************************************************************************
2377 Get the time of day info.
2378 ****************************************************************************/
2380 static bool api_NetRemoteTOD(connection_struct
*conn
,uint16 vuid
,
2381 char *param
, int tpscnt
,
2382 char *data
, int tdscnt
,
2383 int mdrcnt
,int mprcnt
,
2384 char **rdata
,char **rparam
,
2385 int *rdata_len
,int *rparam_len
)
2388 time_t unixdate
= time(NULL
);
2392 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2398 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2403 SSVAL(*rparam
,0,NERR_Success
);
2404 SSVAL(*rparam
,2,0); /* converter word */
2408 srv_put_dos_date3(p
,0,unixdate
); /* this is the time that is looked at
2409 by NT in a "net time" operation,
2410 it seems to ignore the one below */
2412 /* the client expects to get localtime, not GMT, in this bit
2413 (I think, this needs testing) */
2414 t
= localtime(&unixdate
);
2419 SIVAL(p
,4,0); /* msecs ? */
2420 SCVAL(p
,8,t
->tm_hour
);
2421 SCVAL(p
,9,t
->tm_min
);
2422 SCVAL(p
,10,t
->tm_sec
);
2423 SCVAL(p
,11,0); /* hundredths of seconds */
2424 SSVALS(p
,12,get_time_zone(unixdate
)/60); /* timezone in minutes from GMT */
2425 SSVAL(p
,14,10000); /* timer interval in 0.0001 of sec */
2426 SCVAL(p
,16,t
->tm_mday
);
2427 SCVAL(p
,17,t
->tm_mon
+ 1);
2428 SSVAL(p
,18,1900+t
->tm_year
);
2429 SCVAL(p
,20,t
->tm_wday
);
2434 /****************************************************************************
2435 Set the user password.
2436 *****************************************************************************/
2438 static bool api_SetUserPassword(connection_struct
*conn
,uint16 vuid
,
2439 char *param
, int tpscnt
,
2440 char *data
, int tdscnt
,
2441 int mdrcnt
,int mprcnt
,
2442 char **rdata
,char **rparam
,
2443 int *rdata_len
,int *rparam_len
)
2445 char *np
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2448 fstring pass1
,pass2
;
2450 /* Skip 2 strings. */
2451 p
= skip_string(param
,tpscnt
,np
);
2452 p
= skip_string(param
,tpscnt
,p
);
2458 /* Do we have a string ? */
2459 if (skip_string(param
,tpscnt
,p
) == NULL
) {
2462 pull_ascii_fstring(user
,p
);
2464 p
= skip_string(param
,tpscnt
,p
);
2469 memset(pass1
,'\0',sizeof(pass1
));
2470 memset(pass2
,'\0',sizeof(pass2
));
2472 * We use 31 here not 32 as we're checking
2473 * the last byte we want to access is safe.
2475 if (!is_offset_safe(param
,tpscnt
,p
,31)) {
2479 memcpy(pass2
,p
+16,16);
2482 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2489 SSVAL(*rparam
,0,NERR_badpass
);
2490 SSVAL(*rparam
,2,0); /* converter word */
2492 DEBUG(3,("Set password for <%s>\n",user
));
2495 * Attempt to verify the old password against smbpasswd entries
2496 * Win98 clients send old and new password in plaintext for this call.
2500 auth_serversupplied_info
*server_info
= NULL
;
2501 DATA_BLOB password
= data_blob(pass1
, strlen(pass1
)+1);
2503 if (NT_STATUS_IS_OK(check_plaintext_password(user
,password
,&server_info
))) {
2506 if (NT_STATUS_IS_OK(change_oem_password(server_info
->sam_account
, pass1
, pass2
, False
, NULL
))) {
2507 SSVAL(*rparam
,0,NERR_Success
);
2511 TALLOC_FREE(server_info
);
2513 data_blob_clear_free(&password
);
2517 * If the plaintext change failed, attempt
2518 * the old encrypted method. NT will generate this
2519 * after trying the samr method. Note that this
2520 * method is done as a last resort as this
2521 * password change method loses the NT password hash
2522 * and cannot change the UNIX password as no plaintext
2526 if(SVAL(*rparam
,0) != NERR_Success
) {
2527 struct samu
*hnd
= NULL
;
2529 if (check_lanman_password(user
,(unsigned char *)pass1
,(unsigned char *)pass2
, &hnd
)) {
2531 if (change_lanman_password(hnd
,(uchar
*)pass2
)) {
2532 SSVAL(*rparam
,0,NERR_Success
);
2539 memset((char *)pass1
,'\0',sizeof(fstring
));
2540 memset((char *)pass2
,'\0',sizeof(fstring
));
2545 /****************************************************************************
2546 Set the user password (SamOEM version - gets plaintext).
2547 ****************************************************************************/
2549 static bool api_SamOEMChangePassword(connection_struct
*conn
,uint16 vuid
,
2550 char *param
, int tpscnt
,
2551 char *data
, int tdscnt
,
2552 int mdrcnt
,int mprcnt
,
2553 char **rdata
,char **rparam
,
2554 int *rdata_len
,int *rparam_len
)
2557 char *p
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2559 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2569 SSVAL(*rparam
,0,NERR_badpass
);
2572 * Check the parameter definition is correct.
2575 /* Do we have a string ? */
2576 if (skip_string(param
,tpscnt
,p
) == 0) {
2579 if(!strequal(p
, "zsT")) {
2580 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", p
));
2583 p
= skip_string(param
, tpscnt
, p
);
2588 /* Do we have a string ? */
2589 if (skip_string(param
,tpscnt
,p
) == 0) {
2592 if(!strequal(p
, "B516B16")) {
2593 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p
));
2596 p
= skip_string(param
,tpscnt
,p
);
2600 /* Do we have a string ? */
2601 if (skip_string(param
,tpscnt
,p
) == 0) {
2604 p
+= pull_ascii_fstring(user
,p
);
2606 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user
));
2609 * Pass the user through the NT -> unix user mapping
2613 (void)map_username(user
);
2615 if (NT_STATUS_IS_OK(pass_oem_change(user
, (uchar
*) data
, (uchar
*)&data
[516], NULL
, NULL
, NULL
))) {
2616 SSVAL(*rparam
,0,NERR_Success
);
2622 /****************************************************************************
2625 ****************************************************************************/
2627 static bool api_RDosPrintJobDel(connection_struct
*conn
,uint16 vuid
,
2628 char *param
, int tpscnt
,
2629 char *data
, int tdscnt
,
2630 int mdrcnt
,int mprcnt
,
2631 char **rdata
,char **rparam
,
2632 int *rdata_len
,int *rparam_len
)
2634 int function
= get_safe_SVAL(param
,tpscnt
,param
,0,0);
2635 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2636 char *str2
= skip_string(param
,tpscnt
,str1
);
2637 char *p
= skip_string(param
,tpscnt
,str2
);
2642 WERROR werr
= WERR_OK
;
2644 if (!str1
|| !str2
|| !p
) {
2648 * We use 1 here not 2 as we're checking
2649 * the last byte we want to access is safe.
2651 if (!is_offset_safe(param
,tpscnt
,p
,1)) {
2654 if(!rap_to_pjobid(SVAL(p
,0), sharename
, &jobid
))
2657 /* check it's a supported varient */
2658 if (!(strcsequal(str1
,"W") && strcsequal(str2
,"")))
2662 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2668 if (!print_job_exists(sharename
, jobid
)) {
2669 errcode
= NERR_JobNotFound
;
2673 snum
= lp_servicenumber( sharename
);
2675 errcode
= NERR_DestNotFound
;
2679 errcode
= NERR_notsupported
;
2682 case 81: /* delete */
2683 if (print_job_delete(conn
->server_info
, snum
, jobid
, &werr
))
2684 errcode
= NERR_Success
;
2686 case 82: /* pause */
2687 if (print_job_pause(conn
->server_info
, snum
, jobid
, &werr
))
2688 errcode
= NERR_Success
;
2690 case 83: /* resume */
2691 if (print_job_resume(conn
->server_info
, snum
, jobid
, &werr
))
2692 errcode
= NERR_Success
;
2696 if (!W_ERROR_IS_OK(werr
))
2697 errcode
= W_ERROR_V(werr
);
2700 SSVAL(*rparam
,0,errcode
);
2701 SSVAL(*rparam
,2,0); /* converter word */
2706 /****************************************************************************
2707 Purge a print queue - or pause or resume it.
2708 ****************************************************************************/
2710 static bool api_WPrintQueueCtrl(connection_struct
*conn
,uint16 vuid
,
2711 char *param
, int tpscnt
,
2712 char *data
, int tdscnt
,
2713 int mdrcnt
,int mprcnt
,
2714 char **rdata
,char **rparam
,
2715 int *rdata_len
,int *rparam_len
)
2717 int function
= get_safe_SVAL(param
,tpscnt
,param
,0,0);
2718 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2719 char *str2
= skip_string(param
,tpscnt
,str1
);
2720 char *QueueName
= skip_string(param
,tpscnt
,str2
);
2721 int errcode
= NERR_notsupported
;
2723 WERROR werr
= WERR_OK
;
2725 if (!str1
|| !str2
|| !QueueName
) {
2729 /* check it's a supported varient */
2730 if (!(strcsequal(str1
,"z") && strcsequal(str2
,"")))
2734 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2740 if (skip_string(param
,tpscnt
,QueueName
) == NULL
) {
2743 snum
= print_queue_snum(QueueName
);
2746 errcode
= NERR_JobNotFound
;
2751 case 74: /* Pause queue */
2752 if (print_queue_pause(conn
->server_info
, snum
, &werr
)) {
2753 errcode
= NERR_Success
;
2756 case 75: /* Resume queue */
2757 if (print_queue_resume(conn
->server_info
, snum
, &werr
)) {
2758 errcode
= NERR_Success
;
2761 case 103: /* Purge */
2762 if (print_queue_purge(conn
->server_info
, snum
, &werr
)) {
2763 errcode
= NERR_Success
;
2768 if (!W_ERROR_IS_OK(werr
)) errcode
= W_ERROR_V(werr
);
2771 SSVAL(*rparam
,0,errcode
);
2772 SSVAL(*rparam
,2,0); /* converter word */
2777 /****************************************************************************
2778 set the property of a print job (undocumented?)
2779 ? function = 0xb -> set name of print job
2780 ? function = 0x6 -> move print job up/down
2781 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
2782 or <WWsTP> <WB21BB16B10zWWzDDz>
2783 ****************************************************************************/
2785 static int check_printjob_info(struct pack_desc
* desc
,
2786 int uLevel
, char* id
)
2788 desc
->subformat
= NULL
;
2790 case 0: desc
->format
= "W"; break;
2791 case 1: desc
->format
= "WB21BB16B10zWWzDDz"; break;
2792 case 2: desc
->format
= "WWzWWDDzz"; break;
2793 case 3: desc
->format
= "WWzWWDDzzzzzzzzzzlz"; break;
2794 case 4: desc
->format
= "WWzWWDDzzzzzDDDDDDD"; break;
2796 DEBUG(0,("check_printjob_info: invalid level %d\n",
2800 if (id
== NULL
|| strcmp(desc
->format
,id
) != 0) {
2801 DEBUG(0,("check_printjob_info: invalid format %s\n",
2802 id
? id
: "<NULL>" ));
2808 static bool api_PrintJobInfo(connection_struct
*conn
, uint16 vuid
,
2809 char *param
, int tpscnt
,
2810 char *data
, int tdscnt
,
2811 int mdrcnt
,int mprcnt
,
2812 char **rdata
,char **rparam
,
2813 int *rdata_len
,int *rparam_len
)
2815 struct pack_desc desc
;
2816 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2817 char *str2
= skip_string(param
,tpscnt
,str1
);
2818 char *p
= skip_string(param
,tpscnt
,str2
);
2821 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,2,-1);
2822 int function
= get_safe_SVAL(param
,tpscnt
,p
,4,-1);
2825 if (!str1
|| !str2
|| !p
) {
2829 * We use 1 here not 2 as we're checking
2830 * the last byte we want to access is safe.
2832 if (!is_offset_safe(param
,tpscnt
,p
,1)) {
2835 if(!rap_to_pjobid(SVAL(p
,0), sharename
, &jobid
))
2838 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2843 if (!share_defined(sharename
)) {
2844 DEBUG(0,("api_PrintJobInfo: sharen [%s] not defined\n",
2851 /* check it's a supported varient */
2852 if ((strcmp(str1
,"WWsTP")) ||
2853 (!check_printjob_info(&desc
,uLevel
,str2
)))
2856 if (!print_job_exists(sharename
, jobid
)) {
2857 errcode
=NERR_JobNotFound
;
2861 errcode
= NERR_notsupported
;
2865 /* change job place in the queue,
2866 data gives the new place */
2867 place
= SVAL(data
,0);
2868 if (print_job_set_place(sharename
, jobid
, place
)) {
2869 errcode
=NERR_Success
;
2874 /* change print job name, data gives the name */
2875 if (print_job_set_name(sharename
, jobid
, data
)) {
2876 errcode
=NERR_Success
;
2885 SSVALS(*rparam
,0,errcode
);
2886 SSVAL(*rparam
,2,0); /* converter word */
2892 /****************************************************************************
2893 Get info about the server.
2894 ****************************************************************************/
2896 static bool api_RNetServerGetInfo(connection_struct
*conn
,uint16 vuid
,
2897 char *param
, int tpscnt
,
2898 char *data
, int tdscnt
,
2899 int mdrcnt
,int mprcnt
,
2900 char **rdata
,char **rparam
,
2901 int *rdata_len
,int *rparam_len
)
2903 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2904 char *str2
= skip_string(param
,tpscnt
,str1
);
2905 char *p
= skip_string(param
,tpscnt
,str2
);
2906 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2910 if (!str1
|| !str2
|| !p
) {
2914 DEBUG(4,("NetServerGetInfo level %d\n",uLevel
));
2916 /* check it's a supported varient */
2917 if (!prefix_ok(str1
,"WrLh")) {
2923 if (strcmp(str2
,"B16") != 0) {
2929 if (strcmp(str2
,"B16BBDz") != 0) {
2935 if (strcmp(str2
,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")!= 0) {
2941 if (strcmp(str2
,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz") != 0) {
2947 if (strcmp(str2
,"DN") != 0) {
2953 if (strcmp(str2
,"B16BBDzWWzzz") != 0) {
2962 *rdata_len
= mdrcnt
;
2963 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2969 p2
= p
+ struct_len
;
2971 srvstr_push(NULL
, 0, p
,global_myname(),16,
2972 STR_ASCII
|STR_UPPER
|STR_TERMINATE
);
2976 struct srv_info_struct
*servers
=NULL
;
2978 char *comment
= NULL
;
2979 TALLOC_CTX
*ctx
= talloc_tos();
2980 uint32 servertype
= lp_default_server_announce();
2982 comment
= talloc_strdup(ctx
,lp_serverstring());
2987 if ((count
=get_server_info(SV_TYPE_ALL
,&servers
,lp_workgroup()))>0) {
2988 for (i
=0;i
<count
;i
++) {
2989 if (strequal(servers
[i
].name
,global_myname())) {
2990 servertype
= servers
[i
].type
;
2991 TALLOC_FREE(comment
);
2992 comment
= talloc_strdup(ctx
,
2993 servers
[i
].comment
);
3003 SCVAL(p
,0,lp_major_announce_version());
3004 SCVAL(p
,1,lp_minor_announce_version());
3005 SIVAL(p
,2,servertype
);
3007 if (mdrcnt
== struct_len
) {
3010 SIVAL(p
,6,PTR_DIFF(p2
,*rdata
));
3011 comment
= talloc_sub_advanced(
3013 lp_servicename(SNUM(conn
)),
3014 conn
->server_info
->unix_name
,
3016 conn
->server_info
->utok
.gid
,
3017 conn
->server_info
->sanitized_username
,
3018 pdb_get_domain(conn
->server_info
->sam_account
),
3023 if (mdrcnt
- struct_len
<= 0) {
3028 MIN(mdrcnt
- struct_len
,
3029 MAX_SERVER_STRING_LENGTH
),
3031 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3039 return False
; /* not yet implemented */
3042 *rdata_len
= PTR_DIFF(p2
,*rdata
);
3045 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3049 SSVAL(*rparam
,0,NERR_Success
);
3050 SSVAL(*rparam
,2,0); /* converter word */
3051 SSVAL(*rparam
,4,*rdata_len
);
3056 /****************************************************************************
3057 Get info about the server.
3058 ****************************************************************************/
3060 static bool api_NetWkstaGetInfo(connection_struct
*conn
,uint16 vuid
,
3061 char *param
, int tpscnt
,
3062 char *data
, int tdscnt
,
3063 int mdrcnt
,int mprcnt
,
3064 char **rdata
,char **rparam
,
3065 int *rdata_len
,int *rparam_len
)
3067 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3068 char *str2
= skip_string(param
,tpscnt
,str1
);
3069 char *p
= skip_string(param
,tpscnt
,str2
);
3072 int level
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3074 if (!str1
|| !str2
|| !p
) {
3078 DEBUG(4,("NetWkstaGetInfo level %d\n",level
));
3081 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3086 /* check it's a supported varient */
3087 if (!(level
==10 && strcsequal(str1
,"WrLh") && strcsequal(str2
,"zzzBBzz"))) {
3091 *rdata_len
= mdrcnt
+ 1024;
3092 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
3097 SSVAL(*rparam
,0,NERR_Success
);
3098 SSVAL(*rparam
,2,0); /* converter word */
3101 endp
= *rdata
+ *rdata_len
;
3103 p2
= get_safe_ptr(*rdata
,*rdata_len
,p
,22);
3108 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* host name */
3109 strlcpy(p2
,get_local_machine_name(),PTR_DIFF(endp
,p2
));
3111 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3117 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
));
3118 strlcpy(p2
,conn
->server_info
->sanitized_username
,PTR_DIFF(endp
,p2
));
3119 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3125 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* login domain */
3126 strlcpy(p2
,lp_workgroup(),PTR_DIFF(endp
,p2
));
3128 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3134 SCVAL(p
,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
3135 SCVAL(p
,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
3138 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
));
3139 strlcpy(p2
,lp_workgroup(),PTR_DIFF(endp
,p2
)); /* don't know. login domain?? */
3140 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3146 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* don't know */
3147 strlcpy(p2
,"",PTR_DIFF(endp
,p2
));
3148 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3154 *rdata_len
= PTR_DIFF(p2
,*rdata
);
3156 SSVAL(*rparam
,4,*rdata_len
);
3161 /****************************************************************************
3162 get info about a user
3164 struct user_info_11 {
3165 char usri11_name[21]; 0-20
3167 char *usri11_comment; 22-25
3168 char *usri11_usr_comment; 26-29
3169 unsigned short usri11_priv; 30-31
3170 unsigned long usri11_auth_flags; 32-35
3171 long usri11_password_age; 36-39
3172 char *usri11_homedir; 40-43
3173 char *usri11_parms; 44-47
3174 long usri11_last_logon; 48-51
3175 long usri11_last_logoff; 52-55
3176 unsigned short usri11_bad_pw_count; 56-57
3177 unsigned short usri11_num_logons; 58-59
3178 char *usri11_logon_server; 60-63
3179 unsigned short usri11_country_code; 64-65
3180 char *usri11_workstations; 66-69
3181 unsigned long usri11_max_storage; 70-73
3182 unsigned short usri11_units_per_week; 74-75
3183 unsigned char *usri11_logon_hours; 76-79
3184 unsigned short usri11_code_page; 80-81
3189 usri11_name specifies the user name for which information is retrieved
3191 usri11_pad aligns the next data structure element to a word boundary
3193 usri11_comment is a null terminated ASCII comment
3195 usri11_user_comment is a null terminated ASCII comment about the user
3197 usri11_priv specifies the level of the privilege assigned to the user.
3198 The possible values are:
3200 Name Value Description
3201 USER_PRIV_GUEST 0 Guest privilege
3202 USER_PRIV_USER 1 User privilege
3203 USER_PRV_ADMIN 2 Administrator privilege
3205 usri11_auth_flags specifies the account operator privileges. The
3206 possible values are:
3208 Name Value Description
3209 AF_OP_PRINT 0 Print operator
3212 Leach, Naik [Page 28]
3216 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
3219 AF_OP_COMM 1 Communications operator
3220 AF_OP_SERVER 2 Server operator
3221 AF_OP_ACCOUNTS 3 Accounts operator
3224 usri11_password_age specifies how many seconds have elapsed since the
3225 password was last changed.
3227 usri11_home_dir points to a null terminated ASCII string that contains
3228 the path name of the user's home directory.
3230 usri11_parms points to a null terminated ASCII string that is set
3231 aside for use by applications.
3233 usri11_last_logon specifies the time when the user last logged on.
3234 This value is stored as the number of seconds elapsed since
3235 00:00:00, January 1, 1970.
3237 usri11_last_logoff specifies the time when the user last logged off.
3238 This value is stored as the number of seconds elapsed since
3239 00:00:00, January 1, 1970. A value of 0 means the last logoff
3242 usri11_bad_pw_count specifies the number of incorrect passwords
3243 entered since the last successful logon.
3245 usri11_log1_num_logons specifies the number of times this user has
3246 logged on. A value of -1 means the number of logons is unknown.
3248 usri11_logon_server points to a null terminated ASCII string that
3249 contains the name of the server to which logon requests are sent.
3250 A null string indicates logon requests should be sent to the
3253 usri11_country_code specifies the country code for the user's language
3256 usri11_workstations points to a null terminated ASCII string that
3257 contains the names of workstations the user may log on from.
3258 There may be up to 8 workstations, with the names separated by
3259 commas. A null strings indicates there are no restrictions.
3261 usri11_max_storage specifies the maximum amount of disk space the user
3262 can occupy. A value of 0xffffffff indicates there are no
3265 usri11_units_per_week specifies the equal number of time units into
3266 which a week is divided. This value must be equal to 168.
3268 usri11_logon_hours points to a 21 byte (168 bits) string that
3269 specifies the time during which the user can log on. Each bit
3270 represents one unique hour in a week. The first bit (bit 0, word
3271 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
3275 Leach, Naik [Page 29]
3279 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
3282 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
3283 are no restrictions.
3285 usri11_code_page specifies the code page for the user's language of
3288 All of the pointers in this data structure need to be treated
3289 specially. The pointer is a 32 bit pointer. The higher 16 bits need
3290 to be ignored. The converter word returned in the parameters section
3291 needs to be subtracted from the lower 16 bits to calculate an offset
3292 into the return buffer where this ASCII string resides.
3294 There is no auxiliary data in the response.
3296 ****************************************************************************/
3298 #define usri11_name 0
3299 #define usri11_pad 21
3300 #define usri11_comment 22
3301 #define usri11_usr_comment 26
3302 #define usri11_full_name 30
3303 #define usri11_priv 34
3304 #define usri11_auth_flags 36
3305 #define usri11_password_age 40
3306 #define usri11_homedir 44
3307 #define usri11_parms 48
3308 #define usri11_last_logon 52
3309 #define usri11_last_logoff 56
3310 #define usri11_bad_pw_count 60
3311 #define usri11_num_logons 62
3312 #define usri11_logon_server 64
3313 #define usri11_country_code 68
3314 #define usri11_workstations 70
3315 #define usri11_max_storage 74
3316 #define usri11_units_per_week 78
3317 #define usri11_logon_hours 80
3318 #define usri11_code_page 84
3319 #define usri11_end 86
3321 #define USER_PRIV_GUEST 0
3322 #define USER_PRIV_USER 1
3323 #define USER_PRIV_ADMIN 2
3325 #define AF_OP_PRINT 0
3326 #define AF_OP_COMM 1
3327 #define AF_OP_SERVER 2
3328 #define AF_OP_ACCOUNTS 3
3331 static bool api_RNetUserGetInfo(connection_struct
*conn
, uint16 vuid
,
3332 char *param
, int tpscnt
,
3333 char *data
, int tdscnt
,
3334 int mdrcnt
,int mprcnt
,
3335 char **rdata
,char **rparam
,
3336 int *rdata_len
,int *rparam_len
)
3338 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3339 char *str2
= skip_string(param
,tpscnt
,str1
);
3340 char *UserName
= skip_string(param
,tpscnt
,str2
);
3341 char *p
= skip_string(param
,tpscnt
,UserName
);
3342 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3345 const char *level_string
;
3347 /* get NIS home of a previously validated user - simeon */
3348 /* With share level security vuid will always be zero.
3349 Don't depend on vuser being non-null !!. JRA */
3350 user_struct
*vuser
= get_valid_user_struct(vuid
);
3352 DEBUG(3,(" Username of UID %d is %s\n",
3353 (int)vuser
->server_info
->utok
.uid
,
3354 vuser
->server_info
->unix_name
));
3357 if (!str1
|| !str2
|| !UserName
|| !p
) {
3362 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3367 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel
));
3369 /* check it's a supported variant */
3370 if (strcmp(str1
,"zWrLh") != 0) {
3374 case 0: level_string
= "B21"; break;
3375 case 1: level_string
= "B21BB16DWzzWz"; break;
3376 case 2: level_string
= "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
3377 case 10: level_string
= "B21Bzzz"; break;
3378 case 11: level_string
= "B21BzzzWDDzzDDWWzWzDWb21W"; break;
3379 default: return False
;
3382 if (strcmp(level_string
,str2
) != 0) {
3386 *rdata_len
= mdrcnt
+ 1024;
3387 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
3392 SSVAL(*rparam
,0,NERR_Success
);
3393 SSVAL(*rparam
,2,0); /* converter word */
3396 endp
= *rdata
+ *rdata_len
;
3397 p2
= get_safe_ptr(*rdata
,*rdata_len
,p
,usri11_end
);
3403 fstrcpy(p
+usri11_name
,UserName
); /* 21 bytes - user name */
3406 SCVAL(p
,usri11_pad
,0); /* padding - 1 byte */
3411 SIVAL(p
,usri11_comment
,PTR_DIFF(p2
,p
)); /* comment */
3412 strlcpy(p2
,"Comment",PTR_DIFF(endp
,p2
));
3413 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3418 SIVAL(p
,usri11_usr_comment
,PTR_DIFF(p2
,p
)); /* user_comment */
3419 strlcpy(p2
,"UserComment",PTR_DIFF(endp
,p2
));
3420 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3425 /* EEK! the cifsrap.txt doesn't have this in!!!! */
3426 SIVAL(p
,usri11_full_name
,PTR_DIFF(p2
,p
)); /* full name */
3427 strlcpy(p2
,((vuser
!= NULL
)
3428 ? pdb_get_fullname(vuser
->server_info
->sam_account
)
3429 : UserName
),PTR_DIFF(endp
,p2
));
3430 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3437 const char *homedir
= "";
3438 if (vuser
!= NULL
) {
3439 homedir
= pdb_get_homedir(
3440 vuser
->server_info
->sam_account
);
3442 /* modelled after NTAS 3.51 reply */
3443 SSVAL(p
,usri11_priv
,conn
->admin_user
?USER_PRIV_ADMIN
:USER_PRIV_USER
);
3444 SIVAL(p
,usri11_auth_flags
,AF_OP_PRINT
); /* auth flags */
3445 SIVALS(p
,usri11_password_age
,-1); /* password age */
3446 SIVAL(p
,usri11_homedir
,PTR_DIFF(p2
,p
)); /* home dir */
3447 strlcpy(p2
, homedir
, PTR_DIFF(endp
,p2
));
3448 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3452 SIVAL(p
,usri11_parms
,PTR_DIFF(p2
,p
)); /* parms */
3453 strlcpy(p2
,"",PTR_DIFF(endp
,p2
));
3454 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3458 SIVAL(p
,usri11_last_logon
,0); /* last logon */
3459 SIVAL(p
,usri11_last_logoff
,0); /* last logoff */
3460 SSVALS(p
,usri11_bad_pw_count
,-1); /* bad pw counts */
3461 SSVALS(p
,usri11_num_logons
,-1); /* num logons */
3462 SIVAL(p
,usri11_logon_server
,PTR_DIFF(p2
,p
)); /* logon server */
3463 strlcpy(p2
,"\\\\*",PTR_DIFF(endp
,p2
));
3464 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3468 SSVAL(p
,usri11_country_code
,0); /* country code */
3470 SIVAL(p
,usri11_workstations
,PTR_DIFF(p2
,p
)); /* workstations */
3471 strlcpy(p2
,"",PTR_DIFF(endp
,p2
));
3472 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3477 SIVALS(p
,usri11_max_storage
,-1); /* max storage */
3478 SSVAL(p
,usri11_units_per_week
,168); /* units per week */
3479 SIVAL(p
,usri11_logon_hours
,PTR_DIFF(p2
,p
)); /* logon hours */
3481 /* a simple way to get logon hours at all times. */
3483 SCVAL(p2
,21,0); /* fix zero termination */
3484 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3489 SSVAL(p
,usri11_code_page
,0); /* code page */
3492 if (uLevel
== 1 || uLevel
== 2) {
3493 memset(p
+22,' ',16); /* password */
3494 SIVALS(p
,38,-1); /* password age */
3496 conn
->admin_user
?USER_PRIV_ADMIN
:USER_PRIV_USER
);
3497 SIVAL(p
,44,PTR_DIFF(p2
,*rdata
)); /* home dir */
3498 strlcpy(p2
, vuser
? pdb_get_homedir(
3499 vuser
->server_info
->sam_account
) : "",
3501 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3505 SIVAL(p
,48,PTR_DIFF(p2
,*rdata
)); /* comment */
3507 SSVAL(p
,52,0); /* flags */
3508 SIVAL(p
,54,PTR_DIFF(p2
,*rdata
)); /* script_path */
3509 strlcpy(p2
, vuser
? pdb_get_logon_script(
3510 vuser
->server_info
->sam_account
) : "",
3512 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3517 SIVAL(p
,60,0); /* auth_flags */
3518 SIVAL(p
,64,PTR_DIFF(p2
,*rdata
)); /* full_name */
3519 strlcpy(p2
,((vuser
!= NULL
)
3520 ? pdb_get_fullname(vuser
->server_info
->sam_account
)
3521 : UserName
),PTR_DIFF(endp
,p2
));
3522 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3526 SIVAL(p
,68,0); /* urs_comment */
3527 SIVAL(p
,72,PTR_DIFF(p2
,*rdata
)); /* parms */
3528 strlcpy(p2
,"",PTR_DIFF(endp
,p2
));
3529 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3533 SIVAL(p
,76,0); /* workstations */
3534 SIVAL(p
,80,0); /* last_logon */
3535 SIVAL(p
,84,0); /* last_logoff */
3536 SIVALS(p
,88,-1); /* acct_expires */
3537 SIVALS(p
,92,-1); /* max_storage */
3538 SSVAL(p
,96,168); /* units_per_week */
3539 SIVAL(p
,98,PTR_DIFF(p2
,*rdata
)); /* logon_hours */
3542 SSVALS(p
,102,-1); /* bad_pw_count */
3543 SSVALS(p
,104,-1); /* num_logons */
3544 SIVAL(p
,106,PTR_DIFF(p2
,*rdata
)); /* logon_server */
3546 TALLOC_CTX
*ctx
= talloc_tos();
3547 int space_rem
= *rdata_len
- (p2
- *rdata
);
3550 if (space_rem
<= 0) {
3553 tmp
= talloc_strdup(ctx
, "\\\\%L");
3557 tmp
= talloc_sub_basic(ctx
,
3570 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3574 SSVAL(p
,110,49); /* country_code */
3575 SSVAL(p
,112,860); /* code page */
3579 *rdata_len
= PTR_DIFF(p2
,*rdata
);
3581 SSVAL(*rparam
,4,*rdata_len
); /* is this right?? */
3586 static bool api_WWkstaUserLogon(connection_struct
*conn
,uint16 vuid
,
3587 char *param
, int tpscnt
,
3588 char *data
, int tdscnt
,
3589 int mdrcnt
,int mprcnt
,
3590 char **rdata
,char **rparam
,
3591 int *rdata_len
,int *rparam_len
)
3593 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3594 char *str2
= skip_string(param
,tpscnt
,str1
);
3595 char *p
= skip_string(param
,tpscnt
,str2
);
3597 struct pack_desc desc
;
3599 /* With share level security vuid will always be zero.
3600 Don't depend on vuser being non-null !!. JRA */
3601 user_struct
*vuser
= get_valid_user_struct(vuid
);
3603 if (!str1
|| !str2
|| !p
) {
3608 DEBUG(3,(" Username of UID %d is %s\n",
3609 (int)vuser
->server_info
->utok
.uid
,
3610 vuser
->server_info
->unix_name
));
3613 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3614 name
= get_safe_str_ptr(param
,tpscnt
,p
,2);
3619 memset((char *)&desc
,'\0',sizeof(desc
));
3621 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel
,name
));
3623 /* check it's a supported varient */
3624 if (strcmp(str1
,"OOWb54WrLh") != 0) {
3627 if (uLevel
!= 1 || strcmp(str2
,"WB21BWDWWDDDDDDDzzzD") != 0) {
3631 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
3638 desc
.buflen
= mdrcnt
;
3639 desc
.subformat
= NULL
;
3642 if (init_package(&desc
,1,0)) {
3643 PACKI(&desc
,"W",0); /* code */
3644 PACKS(&desc
,"B21",name
); /* eff. name */
3645 PACKS(&desc
,"B",""); /* pad */
3646 PACKI(&desc
,"W", conn
->admin_user
?USER_PRIV_ADMIN
:USER_PRIV_USER
);
3647 PACKI(&desc
,"D",0); /* auth flags XXX */
3648 PACKI(&desc
,"W",0); /* num logons */
3649 PACKI(&desc
,"W",0); /* bad pw count */
3650 PACKI(&desc
,"D",0); /* last logon */
3651 PACKI(&desc
,"D",-1); /* last logoff */
3652 PACKI(&desc
,"D",-1); /* logoff time */
3653 PACKI(&desc
,"D",-1); /* kickoff time */
3654 PACKI(&desc
,"D",0); /* password age */
3655 PACKI(&desc
,"D",0); /* password can change */
3656 PACKI(&desc
,"D",-1); /* password must change */
3660 fstrcpy(mypath
,"\\\\");
3661 fstrcat(mypath
,get_local_machine_name());
3663 PACKS(&desc
,"z",mypath
); /* computer */
3666 PACKS(&desc
,"z",lp_workgroup());/* domain */
3667 PACKS(&desc
,"z", vuser
? pdb_get_logon_script(
3668 vuser
->server_info
->sam_account
) : ""); /* script path */
3669 PACKI(&desc
,"D",0x00000000); /* reserved */
3672 *rdata_len
= desc
.usedlen
;
3674 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3678 SSVALS(*rparam
,0,desc
.errcode
);
3680 SSVAL(*rparam
,4,desc
.neededlen
);
3682 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc
.errcode
));
3687 /****************************************************************************
3688 api_WAccessGetUserPerms
3689 ****************************************************************************/
3691 static bool api_WAccessGetUserPerms(connection_struct
*conn
,uint16 vuid
,
3692 char *param
, int tpscnt
,
3693 char *data
, int tdscnt
,
3694 int mdrcnt
,int mprcnt
,
3695 char **rdata
,char **rparam
,
3696 int *rdata_len
,int *rparam_len
)
3698 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3699 char *str2
= skip_string(param
,tpscnt
,str1
);
3700 char *user
= skip_string(param
,tpscnt
,str2
);
3701 char *resource
= skip_string(param
,tpscnt
,user
);
3703 if (!str1
|| !str2
|| !user
|| !resource
) {
3707 if (skip_string(param
,tpscnt
,resource
) == NULL
) {
3710 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user
,resource
));
3712 /* check it's a supported varient */
3713 if (strcmp(str1
,"zzh") != 0) {
3716 if (strcmp(str2
,"") != 0) {
3721 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3725 SSVALS(*rparam
,0,0); /* errorcode */
3726 SSVAL(*rparam
,2,0); /* converter word */
3727 SSVAL(*rparam
,4,0x7f); /* permission flags */
3732 /****************************************************************************
3733 api_WPrintJobEnumerate
3734 ****************************************************************************/
3736 static bool api_WPrintJobGetInfo(connection_struct
*conn
, uint16 vuid
,
3737 char *param
, int tpscnt
,
3738 char *data
, int tdscnt
,
3739 int mdrcnt
,int mprcnt
,
3740 char **rdata
,char **rparam
,
3741 int *rdata_len
,int *rparam_len
)
3743 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3744 char *str2
= skip_string(param
,tpscnt
,str1
);
3745 char *p
= skip_string(param
,tpscnt
,str2
);
3752 struct pack_desc desc
;
3753 print_queue_struct
*queue
=NULL
;
3754 print_status_struct status
;
3757 if (!str1
|| !str2
|| !p
) {
3761 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,2,-1);
3763 memset((char *)&desc
,'\0',sizeof(desc
));
3764 memset((char *)&status
,'\0',sizeof(status
));
3766 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel
,SVAL(p
,0)));
3768 /* check it's a supported varient */
3769 if (strcmp(str1
,"WWrLh") != 0) {
3772 if (!check_printjob_info(&desc
,uLevel
,str2
)) {
3776 if(!rap_to_pjobid(SVAL(p
,0), sharename
, &jobid
)) {
3780 snum
= lp_servicenumber( sharename
);
3781 if (snum
< 0 || !VALID_SNUM(snum
)) {
3785 count
= print_queue_status(snum
,&queue
,&status
);
3786 for (i
= 0; i
< count
; i
++) {
3787 if (queue
[i
].job
== jobid
) {
3793 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
3798 desc
.buflen
= mdrcnt
;
3801 * Don't return data but need to get correct length
3802 * init_package will return wrong size if buflen=0
3804 desc
.buflen
= getlen(desc
.format
);
3805 desc
.base
= tmpdata
= (char *)SMB_MALLOC( desc
.buflen
);
3808 if (init_package(&desc
,1,0)) {
3810 fill_printjob_info(conn
,snum
,uLevel
,&desc
,&queue
[i
],i
);
3811 *rdata_len
= desc
.usedlen
;
3813 desc
.errcode
= NERR_JobNotFound
;
3819 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3823 SSVALS(*rparam
,0,desc
.errcode
);
3825 SSVAL(*rparam
,4,desc
.neededlen
);
3830 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc
.errcode
));
3835 static bool api_WPrintJobEnumerate(connection_struct
*conn
, uint16 vuid
,
3836 char *param
, int tpscnt
,
3837 char *data
, int tdscnt
,
3838 int mdrcnt
,int mprcnt
,
3839 char **rdata
,char **rparam
,
3840 int *rdata_len
,int *rparam_len
)
3842 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3843 char *str2
= skip_string(param
,tpscnt
,str1
);
3844 char *p
= skip_string(param
,tpscnt
,str2
);
3850 struct pack_desc desc
;
3851 print_queue_struct
*queue
=NULL
;
3852 print_status_struct status
;
3854 if (!str1
|| !str2
|| !p
) {
3858 memset((char *)&desc
,'\0',sizeof(desc
));
3859 memset((char *)&status
,'\0',sizeof(status
));
3861 p
= skip_string(param
,tpscnt
,p
);
3865 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3867 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel
,name
));
3869 /* check it's a supported variant */
3870 if (strcmp(str1
,"zWrLeh") != 0) {
3875 return False
; /* defined only for uLevel 0,1,2 */
3878 if (!check_printjob_info(&desc
,uLevel
,str2
)) {
3882 snum
= find_service(name
);
3883 if ( !(lp_snum_ok(snum
) && lp_print_ok(snum
)) ) {
3887 count
= print_queue_status(snum
,&queue
,&status
);
3889 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
3895 desc
.buflen
= mdrcnt
;
3897 if (init_package(&desc
,count
,0)) {
3899 for (i
= 0; i
< count
; i
++) {
3900 fill_printjob_info(conn
,snum
,uLevel
,&desc
,&queue
[i
],i
);
3901 if (desc
.errcode
== NERR_Success
) {
3907 *rdata_len
= desc
.usedlen
;
3910 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3914 SSVALS(*rparam
,0,desc
.errcode
);
3916 SSVAL(*rparam
,4,succnt
);
3917 SSVAL(*rparam
,6,count
);
3921 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc
.errcode
));
3926 static int check_printdest_info(struct pack_desc
* desc
,
3927 int uLevel
, char* id
)
3929 desc
->subformat
= NULL
;
3932 desc
->format
= "B9";
3935 desc
->format
= "B9B21WWzW";
3941 desc
->format
= "zzzWWzzzWW";
3944 DEBUG(0,("check_printdest_info: invalid level %d\n",
3948 if (id
== NULL
|| strcmp(desc
->format
,id
) != 0) {
3949 DEBUG(0,("check_printdest_info: invalid string %s\n",
3950 id
? id
: "<NULL>" ));
3956 static void fill_printdest_info(connection_struct
*conn
, int snum
, int uLevel
,
3957 struct pack_desc
* desc
)
3961 strncpy(buf
,SERVICE(snum
),sizeof(buf
)-1);
3962 buf
[sizeof(buf
)-1] = 0;
3966 PACKS(desc
,"B9",buf
); /* szName */
3968 PACKS(desc
,"B21",""); /* szUserName */
3969 PACKI(desc
,"W",0); /* uJobId */
3970 PACKI(desc
,"W",0); /* fsStatus */
3971 PACKS(desc
,"z",""); /* pszStatus */
3972 PACKI(desc
,"W",0); /* time */
3976 if (uLevel
== 2 || uLevel
== 3) {
3977 PACKS(desc
,"z",buf
); /* pszPrinterName */
3979 PACKS(desc
,"z",""); /* pszUserName */
3980 PACKS(desc
,"z",""); /* pszLogAddr */
3981 PACKI(desc
,"W",0); /* uJobId */
3982 PACKI(desc
,"W",0); /* fsStatus */
3983 PACKS(desc
,"z",""); /* pszStatus */
3984 PACKS(desc
,"z",""); /* pszComment */
3985 PACKS(desc
,"z","NULL"); /* pszDrivers */
3986 PACKI(desc
,"W",0); /* time */
3987 PACKI(desc
,"W",0); /* pad1 */
3992 static bool api_WPrintDestGetInfo(connection_struct
*conn
, uint16 vuid
,
3993 char *param
, int tpscnt
,
3994 char *data
, int tdscnt
,
3995 int mdrcnt
,int mprcnt
,
3996 char **rdata
,char **rparam
,
3997 int *rdata_len
,int *rparam_len
)
3999 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4000 char *str2
= skip_string(param
,tpscnt
,str1
);
4001 char *p
= skip_string(param
,tpscnt
,str2
);
4002 char* PrinterName
= p
;
4004 struct pack_desc desc
;
4008 if (!str1
|| !str2
|| !p
) {
4012 memset((char *)&desc
,'\0',sizeof(desc
));
4014 p
= skip_string(param
,tpscnt
,p
);
4018 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4020 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel
,PrinterName
));
4022 /* check it's a supported varient */
4023 if (strcmp(str1
,"zWrLh") != 0) {
4026 if (!check_printdest_info(&desc
,uLevel
,str2
)) {
4030 snum
= find_service(PrinterName
);
4031 if ( !(lp_snum_ok(snum
) && lp_print_ok(snum
)) ) {
4033 desc
.errcode
= NERR_DestNotFound
;
4037 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4042 desc
.buflen
= mdrcnt
;
4045 * Don't return data but need to get correct length
4046 * init_package will return wrong size if buflen=0
4048 desc
.buflen
= getlen(desc
.format
);
4049 desc
.base
= tmpdata
= (char *)SMB_MALLOC( desc
.buflen
);
4051 if (init_package(&desc
,1,0)) {
4052 fill_printdest_info(conn
,snum
,uLevel
,&desc
);
4054 *rdata_len
= desc
.usedlen
;
4058 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4062 SSVALS(*rparam
,0,desc
.errcode
);
4064 SSVAL(*rparam
,4,desc
.neededlen
);
4066 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc
.errcode
));
4072 static bool api_WPrintDestEnum(connection_struct
*conn
, uint16 vuid
,
4073 char *param
, int tpscnt
,
4074 char *data
, int tdscnt
,
4075 int mdrcnt
,int mprcnt
,
4076 char **rdata
,char **rparam
,
4077 int *rdata_len
,int *rparam_len
)
4079 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4080 char *str2
= skip_string(param
,tpscnt
,str1
);
4081 char *p
= skip_string(param
,tpscnt
,str2
);
4085 struct pack_desc desc
;
4086 int services
= lp_numservices();
4088 if (!str1
|| !str2
|| !p
) {
4092 memset((char *)&desc
,'\0',sizeof(desc
));
4094 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4096 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel
));
4098 /* check it's a supported varient */
4099 if (strcmp(str1
,"WrLeh") != 0) {
4102 if (!check_printdest_info(&desc
,uLevel
,str2
)) {
4107 for (i
= 0; i
< services
; i
++) {
4108 if (lp_snum_ok(i
) && lp_print_ok(i
) && lp_browseable(i
)) {
4114 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4121 desc
.buflen
= mdrcnt
;
4122 if (init_package(&desc
,queuecnt
,0)) {
4125 for (i
= 0; i
< services
; i
++) {
4126 if (lp_snum_ok(i
) && lp_print_ok(i
) && lp_browseable(i
)) {
4127 fill_printdest_info(conn
,i
,uLevel
,&desc
);
4129 if (desc
.errcode
== NERR_Success
) {
4136 *rdata_len
= desc
.usedlen
;
4139 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4143 SSVALS(*rparam
,0,desc
.errcode
);
4145 SSVAL(*rparam
,4,succnt
);
4146 SSVAL(*rparam
,6,queuecnt
);
4148 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc
.errcode
));
4153 static bool api_WPrintDriverEnum(connection_struct
*conn
, uint16 vuid
,
4154 char *param
, int tpscnt
,
4155 char *data
, int tdscnt
,
4156 int mdrcnt
,int mprcnt
,
4157 char **rdata
,char **rparam
,
4158 int *rdata_len
,int *rparam_len
)
4160 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4161 char *str2
= skip_string(param
,tpscnt
,str1
);
4162 char *p
= skip_string(param
,tpscnt
,str2
);
4165 struct pack_desc desc
;
4167 if (!str1
|| !str2
|| !p
) {
4171 memset((char *)&desc
,'\0',sizeof(desc
));
4173 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4175 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel
));
4177 /* check it's a supported varient */
4178 if (strcmp(str1
,"WrLeh") != 0) {
4181 if (uLevel
!= 0 || strcmp(str2
,"B41") != 0) {
4186 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4192 desc
.buflen
= mdrcnt
;
4193 if (init_package(&desc
,1,0)) {
4194 PACKS(&desc
,"B41","NULL");
4197 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
4199 *rdata_len
= desc
.usedlen
;
4202 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4206 SSVALS(*rparam
,0,desc
.errcode
);
4208 SSVAL(*rparam
,4,succnt
);
4211 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc
.errcode
));
4216 static bool api_WPrintQProcEnum(connection_struct
*conn
, uint16 vuid
,
4217 char *param
, int tpscnt
,
4218 char *data
, int tdscnt
,
4219 int mdrcnt
,int mprcnt
,
4220 char **rdata
,char **rparam
,
4221 int *rdata_len
,int *rparam_len
)
4223 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4224 char *str2
= skip_string(param
,tpscnt
,str1
);
4225 char *p
= skip_string(param
,tpscnt
,str2
);
4228 struct pack_desc desc
;
4230 if (!str1
|| !str2
|| !p
) {
4233 memset((char *)&desc
,'\0',sizeof(desc
));
4235 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4237 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel
));
4239 /* check it's a supported varient */
4240 if (strcmp(str1
,"WrLeh") != 0) {
4243 if (uLevel
!= 0 || strcmp(str2
,"B13") != 0) {
4248 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4254 desc
.buflen
= mdrcnt
;
4256 if (init_package(&desc
,1,0)) {
4257 PACKS(&desc
,"B13","lpd");
4260 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
4262 *rdata_len
= desc
.usedlen
;
4265 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4269 SSVALS(*rparam
,0,desc
.errcode
);
4271 SSVAL(*rparam
,4,succnt
);
4274 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc
.errcode
));
4279 static bool api_WPrintPortEnum(connection_struct
*conn
, uint16 vuid
,
4280 char *param
, int tpscnt
,
4281 char *data
, int tdscnt
,
4282 int mdrcnt
,int mprcnt
,
4283 char **rdata
,char **rparam
,
4284 int *rdata_len
,int *rparam_len
)
4286 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4287 char *str2
= skip_string(param
,tpscnt
,str1
);
4288 char *p
= skip_string(param
,tpscnt
,str2
);
4291 struct pack_desc desc
;
4293 if (!str1
|| !str2
|| !p
) {
4297 memset((char *)&desc
,'\0',sizeof(desc
));
4299 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4301 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel
));
4303 /* check it's a supported varient */
4304 if (strcmp(str1
,"WrLeh") != 0) {
4307 if (uLevel
!= 0 || strcmp(str2
,"B9") != 0) {
4312 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4317 memset((char *)&desc
,'\0',sizeof(desc
));
4319 desc
.buflen
= mdrcnt
;
4321 if (init_package(&desc
,1,0)) {
4322 PACKS(&desc
,"B13","lp0");
4325 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
4327 *rdata_len
= desc
.usedlen
;
4330 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4334 SSVALS(*rparam
,0,desc
.errcode
);
4336 SSVAL(*rparam
,4,succnt
);
4339 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc
.errcode
));
4344 /****************************************************************************
4346 ****************************************************************************/
4348 static bool api_RNetSessionEnum(connection_struct
*conn
, uint16 vuid
,
4349 char *param
, int tpscnt
,
4350 char *data
, int tdscnt
,
4351 int mdrcnt
,int mprcnt
,
4352 char **rdata
,char **rparam
,
4353 int *rdata_len
,int *rparam_len
)
4356 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4357 char *str2
= skip_string(param
,tpscnt
,str1
);
4358 char *p
= skip_string(param
,tpscnt
,str2
);
4360 struct pack_desc desc
;
4361 struct sessionid
*session_list
;
4362 int i
, num_sessions
;
4364 if (!str1
|| !str2
|| !p
) {
4368 memset((char *)&desc
,'\0',sizeof(desc
));
4370 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4372 DEBUG(3,("RNetSessionEnum uLevel=%d\n",uLevel
));
4373 DEBUG(7,("RNetSessionEnum req string=%s\n",str1
));
4374 DEBUG(7,("RNetSessionEnum ret string=%s\n",str2
));
4376 /* check it's a supported varient */
4377 if (strcmp(str1
,RAP_NetSessionEnum_REQ
) != 0) {
4380 if (uLevel
!= 2 || strcmp(str2
,RAP_SESSION_INFO_L2
) != 0) {
4384 num_sessions
= list_sessions(talloc_tos(), &session_list
);
4387 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4392 memset((char *)&desc
,'\0',sizeof(desc
));
4394 desc
.buflen
= mdrcnt
;
4396 if (!init_package(&desc
,num_sessions
,0)) {
4400 for(i
=0; i
<num_sessions
; i
++) {
4401 PACKS(&desc
, "z", session_list
[i
].remote_machine
);
4402 PACKS(&desc
, "z", session_list
[i
].username
);
4403 PACKI(&desc
, "W", 1); /* num conns */
4404 PACKI(&desc
, "W", 0); /* num opens */
4405 PACKI(&desc
, "W", 1); /* num users */
4406 PACKI(&desc
, "D", 0); /* session time */
4407 PACKI(&desc
, "D", 0); /* idle time */
4408 PACKI(&desc
, "D", 0); /* flags */
4409 PACKS(&desc
, "z", "Unknown Client"); /* client type string */
4412 *rdata_len
= desc
.usedlen
;
4415 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4419 SSVALS(*rparam
,0,desc
.errcode
);
4420 SSVAL(*rparam
,2,0); /* converter */
4421 SSVAL(*rparam
,4,num_sessions
); /* count */
4423 DEBUG(4,("RNetSessionEnum: errorcode %d\n",desc
.errcode
));
4429 /****************************************************************************
4430 The buffer was too small.
4431 ****************************************************************************/
4433 static bool api_TooSmall(connection_struct
*conn
,uint16 vuid
, char *param
, char *data
,
4434 int mdrcnt
, int mprcnt
,
4435 char **rdata
, char **rparam
,
4436 int *rdata_len
, int *rparam_len
)
4438 *rparam_len
= MIN(*rparam_len
,mprcnt
);
4439 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4446 SSVAL(*rparam
,0,NERR_BufTooSmall
);
4448 DEBUG(3,("Supplied buffer too small in API command\n"));
4453 /****************************************************************************
4454 The request is not supported.
4455 ****************************************************************************/
4457 static bool api_Unsupported(connection_struct
*conn
, uint16 vuid
,
4458 char *param
, int tpscnt
,
4459 char *data
, int tdscnt
,
4460 int mdrcnt
, int mprcnt
,
4461 char **rdata
, char **rparam
,
4462 int *rdata_len
, int *rparam_len
)
4465 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4472 SSVAL(*rparam
,0,NERR_notsupported
);
4473 SSVAL(*rparam
,2,0); /* converter word */
4475 DEBUG(3,("Unsupported API command\n"));
4480 static const struct {
4483 bool (*fn
)(connection_struct
*, uint16
,
4486 int,int,char **,char **,int *,int *);
4487 bool auth_user
; /* Deny anonymous access? */
4488 } api_commands
[] = {
4489 {"RNetShareEnum", RAP_WshareEnum
, api_RNetShareEnum
, True
},
4490 {"RNetShareGetInfo", RAP_WshareGetInfo
, api_RNetShareGetInfo
},
4491 {"RNetShareAdd", RAP_WshareAdd
, api_RNetShareAdd
},
4492 {"RNetSessionEnum", RAP_WsessionEnum
, api_RNetSessionEnum
, True
},
4493 {"RNetServerGetInfo", RAP_WserverGetInfo
, api_RNetServerGetInfo
},
4494 {"RNetGroupEnum", RAP_WGroupEnum
, api_RNetGroupEnum
, True
},
4495 {"RNetGroupGetUsers", RAP_WGroupGetUsers
, api_RNetGroupGetUsers
, True
},
4496 {"RNetUserEnum", RAP_WUserEnum
, api_RNetUserEnum
, True
},
4497 {"RNetUserGetInfo", RAP_WUserGetInfo
, api_RNetUserGetInfo
},
4498 {"NetUserGetGroups", RAP_WUserGetGroups
, api_NetUserGetGroups
},
4499 {"NetWkstaGetInfo", RAP_WWkstaGetInfo
, api_NetWkstaGetInfo
},
4500 {"DosPrintQEnum", RAP_WPrintQEnum
, api_DosPrintQEnum
, True
},
4501 {"DosPrintQGetInfo", RAP_WPrintQGetInfo
, api_DosPrintQGetInfo
},
4502 {"WPrintQueuePause", RAP_WPrintQPause
, api_WPrintQueueCtrl
},
4503 {"WPrintQueueResume", RAP_WPrintQContinue
, api_WPrintQueueCtrl
},
4504 {"WPrintJobEnumerate",RAP_WPrintJobEnum
, api_WPrintJobEnumerate
},
4505 {"WPrintJobGetInfo", RAP_WPrintJobGetInfo
, api_WPrintJobGetInfo
},
4506 {"RDosPrintJobDel", RAP_WPrintJobDel
, api_RDosPrintJobDel
},
4507 {"RDosPrintJobPause", RAP_WPrintJobPause
, api_RDosPrintJobDel
},
4508 {"RDosPrintJobResume",RAP_WPrintJobContinue
, api_RDosPrintJobDel
},
4509 {"WPrintDestEnum", RAP_WPrintDestEnum
, api_WPrintDestEnum
},
4510 {"WPrintDestGetInfo", RAP_WPrintDestGetInfo
, api_WPrintDestGetInfo
},
4511 {"NetRemoteTOD", RAP_NetRemoteTOD
, api_NetRemoteTOD
},
4512 {"WPrintQueuePurge", RAP_WPrintQPurge
, api_WPrintQueueCtrl
},
4513 {"NetServerEnum", RAP_NetServerEnum2
, api_RNetServerEnum
}, /* anon OK */
4514 {"WAccessGetUserPerms",RAP_WAccessGetUserPerms
,api_WAccessGetUserPerms
},
4515 {"SetUserPassword", RAP_WUserPasswordSet2
, api_SetUserPassword
},
4516 {"WWkstaUserLogon", RAP_WWkstaUserLogon
, api_WWkstaUserLogon
},
4517 {"PrintJobInfo", RAP_WPrintJobSetInfo
, api_PrintJobInfo
},
4518 {"WPrintDriverEnum", RAP_WPrintDriverEnum
, api_WPrintDriverEnum
},
4519 {"WPrintQProcEnum", RAP_WPrintQProcessorEnum
,api_WPrintQProcEnum
},
4520 {"WPrintPortEnum", RAP_WPrintPortEnum
, api_WPrintPortEnum
},
4521 {"SamOEMChangePassword",RAP_SamOEMChgPasswordUser2_P
,api_SamOEMChangePassword
}, /* anon OK */
4522 {NULL
, -1, api_Unsupported
}
4523 /* The following RAP calls are not implemented by Samba:
4525 RAP_WFileEnum2 - anon not OK
4530 /****************************************************************************
4531 Handle remote api calls.
4532 ****************************************************************************/
4534 void api_reply(connection_struct
*conn
, uint16 vuid
,
4535 struct smb_request
*req
,
4536 char *data
, char *params
,
4537 int tdscnt
, int tpscnt
,
4538 int mdrcnt
, int mprcnt
)
4542 char *rparam
= NULL
;
4543 const char *name1
= NULL
;
4544 const char *name2
= NULL
;
4551 DEBUG(0,("ERROR: NULL params in api_reply()\n"));
4552 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4557 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4560 api_command
= SVAL(params
,0);
4561 /* Is there a string at position params+2 ? */
4562 if (skip_string(params
,tpscnt
,params
+2)) {
4567 name2
= skip_string(params
,tpscnt
,params
+2);
4572 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
4576 tdscnt
,tpscnt
,mdrcnt
,mprcnt
));
4578 for (i
=0;api_commands
[i
].name
;i
++) {
4579 if (api_commands
[i
].id
== api_command
&& api_commands
[i
].fn
) {
4580 DEBUG(3,("Doing %s\n",api_commands
[i
].name
));
4585 /* Check whether this api call can be done anonymously */
4587 if (api_commands
[i
].auth_user
&& lp_restrict_anonymous()) {
4588 user_struct
*user
= get_valid_user_struct(vuid
);
4590 if (!user
|| user
->server_info
->guest
) {
4591 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4596 rdata
= (char *)SMB_MALLOC(1024);
4598 memset(rdata
,'\0',1024);
4601 rparam
= (char *)SMB_MALLOC(1024);
4603 memset(rparam
,'\0',1024);
4606 if(!rdata
|| !rparam
) {
4607 DEBUG(0,("api_reply: malloc fail !\n"));
4610 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4614 reply
= api_commands
[i
].fn(conn
,
4616 params
,tpscnt
, /* params + length */
4617 data
,tdscnt
, /* data + length */
4619 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
4622 if (rdata_len
> mdrcnt
|| rparam_len
> mprcnt
) {
4623 reply
= api_TooSmall(conn
,vuid
,params
,data
,mdrcnt
,mprcnt
,
4624 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
4627 /* if we get False back then it's actually unsupported */
4629 reply
= api_Unsupported(conn
,vuid
,params
,tpscnt
,data
,tdscnt
,mdrcnt
,mprcnt
,
4630 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
4633 /* If api_Unsupported returns false we can't return anything. */
4635 send_trans_reply(conn
, req
->inbuf
, rparam
, rparam_len
,
4636 rdata
, rdata_len
, False
);