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
29 #include "smbd/globals.h"
36 #define NERR_Success 0
37 #define NERR_badpass 86
38 #define NERR_notsupported 50
40 #define NERR_BASE (2100)
41 #define NERR_BufTooSmall (NERR_BASE+23)
42 #define NERR_JobNotFound (NERR_BASE+51)
43 #define NERR_DestNotFound (NERR_BASE+52)
45 #define ACCESS_READ 0x01
46 #define ACCESS_WRITE 0x02
47 #define ACCESS_CREATE 0x04
49 #define SHPWLEN 8 /* share password length */
51 /* Limit size of ipc replies */
53 static char *smb_realloc_limit(void *ptr
, size_t size
)
57 size
= MAX((size
),4*1024);
58 val
= (char *)SMB_REALLOC(ptr
,size
);
60 memset(val
,'\0',size
);
65 static bool api_Unsupported(connection_struct
*conn
, uint16 vuid
,
66 char *param
, int tpscnt
,
67 char *data
, int tdscnt
,
68 int mdrcnt
, int mprcnt
,
69 char **rdata
, char **rparam
,
70 int *rdata_len
, int *rparam_len
);
72 static bool api_TooSmall(connection_struct
*conn
, uint16 vuid
, char *param
, char *data
,
73 int mdrcnt
, int mprcnt
,
74 char **rdata
, char **rparam
,
75 int *rdata_len
, int *rparam_len
);
78 static int CopyExpanded(connection_struct
*conn
,
79 int snum
, char **dst
, char *src
, int *p_space_remaining
)
81 TALLOC_CTX
*ctx
= talloc_tos();
85 if (!src
|| !dst
|| !p_space_remaining
|| !(*dst
) ||
86 *p_space_remaining
<= 0) {
90 buf
= talloc_strdup(ctx
, src
);
92 *p_space_remaining
= 0;
95 buf
= talloc_string_sub(ctx
, buf
,"%S",lp_servicename(snum
));
97 *p_space_remaining
= 0;
100 buf
= talloc_sub_advanced(ctx
,
101 lp_servicename(SNUM(conn
)),
102 conn
->server_info
->unix_name
,
104 conn
->server_info
->utok
.gid
,
105 conn
->server_info
->sanitized_username
,
106 pdb_get_domain(conn
->server_info
->sam_account
),
109 *p_space_remaining
= 0;
112 l
= push_ascii(*dst
,buf
,*p_space_remaining
, STR_TERMINATE
);
117 (*p_space_remaining
) -= l
;
121 static int CopyAndAdvance(char **dst
, char *src
, int *n
)
124 if (!src
|| !dst
|| !n
|| !(*dst
)) {
127 l
= push_ascii(*dst
,src
,*n
, STR_TERMINATE
);
136 static int StrlenExpanded(connection_struct
*conn
, int snum
, char *s
)
138 TALLOC_CTX
*ctx
= talloc_tos();
143 buf
= talloc_strdup(ctx
,s
);
147 buf
= talloc_string_sub(ctx
,buf
,"%S",lp_servicename(snum
));
151 buf
= talloc_sub_advanced(ctx
,
152 lp_servicename(SNUM(conn
)),
153 conn
->server_info
->unix_name
,
155 conn
->server_info
->utok
.gid
,
156 conn
->server_info
->sanitized_username
,
157 pdb_get_domain(conn
->server_info
->sam_account
),
162 return strlen(buf
) + 1;
165 static char *Expand(connection_struct
*conn
, int snum
, char *s
)
167 TALLOC_CTX
*ctx
= talloc_tos();
173 buf
= talloc_strdup(ctx
,s
);
177 buf
= talloc_string_sub(ctx
,buf
,"%S",lp_servicename(snum
));
181 return talloc_sub_advanced(ctx
,
182 lp_servicename(SNUM(conn
)),
183 conn
->server_info
->unix_name
,
185 conn
->server_info
->utok
.gid
,
186 conn
->server_info
->sanitized_username
,
187 pdb_get_domain(conn
->server_info
->sam_account
),
191 /*******************************************************************
192 Check a API string for validity when we only need to check the prefix.
193 ******************************************************************/
195 static bool prefix_ok(const char *str
, const char *prefix
)
197 return(strncmp(str
,prefix
,strlen(prefix
)) == 0);
201 const char *format
; /* formatstring for structure */
202 const char *subformat
; /* subformat for structure */
203 char *base
; /* baseaddress of buffer */
204 int buflen
; /* remaining size for fixed part; on init: length of base */
205 int subcount
; /* count of substructures */
206 char *structbuf
; /* pointer into buffer for remaining fixed part */
207 int stringlen
; /* remaining size for variable part */
208 char *stringbuf
; /* pointer into buffer for remaining variable part */
209 int neededlen
; /* total needed size */
210 int usedlen
; /* total used size (usedlen <= neededlen and usedlen <= buflen) */
211 const char *curpos
; /* current position; pointer into format or subformat */
215 static int get_counter(const char **p
)
221 if (!isdigit((int)**p
)) {
227 n
= 10 * n
+ (i
- '0');
235 static int getlen(const char *p
)
244 case 'W': /* word (2 byte) */
247 case 'K': /* status word? (2 byte) */
250 case 'N': /* count of substructures (word) at end */
253 case 'D': /* double word (4 byte) */
254 case 'z': /* offset to zero terminated string (4 byte) */
255 case 'l': /* offset to user data (4 byte) */
258 case 'b': /* offset to data (with counter) (4 byte) */
262 case 'B': /* byte (with optional counter) */
263 n
+= get_counter(&p
);
270 static bool init_package(struct pack_desc
*p
, int count
, int subcount
)
275 if (!p
->format
|| !p
->base
) {
279 i
= count
* getlen(p
->format
);
281 i
+= subcount
* getlen(p
->subformat
);
283 p
->structbuf
= p
->base
;
287 p
->curpos
= p
->format
;
293 * This is the old error code we used. Aparently
294 * WinNT/2k systems return ERRbuftoosmall (2123) and
295 * OS/2 needs this. I'm leaving this here so we can revert
298 p
->errcode
= ERRmoredata
;
300 p
->errcode
= ERRbuftoosmall
;
303 p
->errcode
= NERR_Success
;
307 p
->stringbuf
= p
->base
+ i
;
309 return (p
->errcode
== NERR_Success
);
312 static int package(struct pack_desc
*p
, ...)
315 int needed
=0, stringneeded
;
316 const char *str
=NULL
;
317 int is_string
=0, stringused
;
324 p
->curpos
= p
->format
;
326 p
->curpos
= p
->subformat
;
331 str
= va_arg(args
,char*);
332 SMB_ASSERT(strncmp(str
,p
->curpos
,strlen(str
)) == 0);
341 switch( *p
->curpos
++ ) {
342 case 'W': /* word (2 byte) */
344 temp
= va_arg(args
,int);
345 if (p
->buflen
>= needed
) {
346 SSVAL(p
->structbuf
,0,temp
);
349 case 'K': /* status word? (2 byte) */
351 temp
= va_arg(args
,int);
352 if (p
->buflen
>= needed
) {
353 SSVAL(p
->structbuf
,0,temp
);
356 case 'N': /* count of substructures (word) at end */
358 p
->subcount
= va_arg(args
,int);
359 if (p
->buflen
>= needed
) {
360 SSVAL(p
->structbuf
,0,p
->subcount
);
363 case 'D': /* double word (4 byte) */
365 temp
= va_arg(args
,int);
366 if (p
->buflen
>= needed
) {
367 SIVAL(p
->structbuf
,0,temp
);
370 case 'B': /* byte (with optional counter) */
371 needed
= get_counter(&p
->curpos
);
373 char *s
= va_arg(args
,char*);
374 if (p
->buflen
>= needed
) {
375 StrnCpy(p
->structbuf
,s
?s
:"",needed
-1);
379 case 'z': /* offset to zero terminated string (4 byte) */
380 str
= va_arg(args
,char*);
381 stringneeded
= (str
? strlen(str
)+1 : 0);
384 case 'l': /* offset to user data (4 byte) */
385 str
= va_arg(args
,char*);
386 stringneeded
= va_arg(args
,int);
389 case 'b': /* offset to data (with counter) (4 byte) */
390 str
= va_arg(args
,char*);
391 stringneeded
= get_counter(&p
->curpos
);
397 if (stringneeded
>= 0) {
399 if (p
->buflen
>= needed
) {
400 stringused
= stringneeded
;
401 if (stringused
> p
->stringlen
) {
402 stringused
= (is_string
? p
->stringlen
: 0);
403 if (p
->errcode
== NERR_Success
) {
404 p
->errcode
= ERRmoredata
;
408 SIVAL(p
->structbuf
,0,0);
410 SIVAL(p
->structbuf
,0,PTR_DIFF(p
->stringbuf
,p
->base
));
411 memcpy(p
->stringbuf
,str
?str
:"",stringused
);
413 p
->stringbuf
[stringused
-1] = '\0';
415 p
->stringbuf
+= stringused
;
416 p
->stringlen
-= stringused
;
417 p
->usedlen
+= stringused
;
420 p
->neededlen
+= stringneeded
;
423 p
->neededlen
+= needed
;
424 if (p
->buflen
>= needed
) {
425 p
->structbuf
+= needed
;
427 p
->usedlen
+= needed
;
429 if (p
->errcode
== NERR_Success
) {
430 p
->errcode
= ERRmoredata
;
437 #define PACK(desc,t,v) package(desc,t,v,0,0,0,0)
438 #define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0)
440 #define PACK(desc,t,v) package(desc,v)
441 #define PACKl(desc,t,v,l) package(desc,v,l)
444 static void PACKI(struct pack_desc
* desc
, const char *t
,int v
)
449 static void PACKS(struct pack_desc
* desc
,const char *t
,const char *v
)
454 /****************************************************************************
456 ****************************************************************************/
458 static void PackDriverData(struct pack_desc
* desc
)
460 char drivdata
[4+4+32];
461 SIVAL(drivdata
,0,sizeof drivdata
); /* cb */
462 SIVAL(drivdata
,4,1000); /* lVersion */
463 memset(drivdata
+8,0,32); /* szDeviceName */
464 push_ascii(drivdata
+8,"NULL",32, STR_TERMINATE
);
465 PACKl(desc
,"l",drivdata
,sizeof drivdata
); /* pDriverData */
468 static int check_printq_info(struct pack_desc
* desc
,
469 unsigned int uLevel
, char *id1
, char *id2
)
471 desc
->subformat
= NULL
;
474 desc
->format
= "B13";
477 desc
->format
= "B13BWWWzzzzzWW";
480 desc
->format
= "B13BWWWzzzzzWN";
481 desc
->subformat
= "WB21BB16B10zWWzDDz";
484 desc
->format
= "zWWWWzzzzWWzzl";
487 desc
->format
= "zWWWWzzzzWNzzl";
488 desc
->subformat
= "WWzWWDDzz";
497 desc
->format
= "WzzzzzzzzN";
498 desc
->subformat
= "z";
501 DEBUG(0,("check_printq_info: invalid level %d\n",
505 if (id1
== NULL
|| strcmp(desc
->format
,id1
) != 0) {
506 DEBUG(0,("check_printq_info: invalid format %s\n",
507 id1
? id1
: "<NULL>" ));
510 if (desc
->subformat
&& (id2
== NULL
|| strcmp(desc
->subformat
,id2
) != 0)) {
511 DEBUG(0,("check_printq_info: invalid subformat %s\n",
512 id2
? id2
: "<NULL>" ));
519 #define RAP_JOB_STATUS_QUEUED 0
520 #define RAP_JOB_STATUS_PAUSED 1
521 #define RAP_JOB_STATUS_SPOOLING 2
522 #define RAP_JOB_STATUS_PRINTING 3
523 #define RAP_JOB_STATUS_PRINTED 4
525 #define RAP_QUEUE_STATUS_PAUSED 1
526 #define RAP_QUEUE_STATUS_ERROR 2
528 /* turn a print job status into a on the wire status
530 static int printj_status(int v
)
534 return RAP_JOB_STATUS_QUEUED
;
536 return RAP_JOB_STATUS_PAUSED
;
538 return RAP_JOB_STATUS_SPOOLING
;
540 return RAP_JOB_STATUS_PRINTING
;
545 /* turn a print queue status into a on the wire status
547 static int printq_status(int v
)
553 return RAP_QUEUE_STATUS_PAUSED
;
555 return RAP_QUEUE_STATUS_ERROR
;
558 static void fill_printjob_info(connection_struct
*conn
, int snum
, int uLevel
,
559 struct pack_desc
*desc
,
560 print_queue_struct
*queue
, int n
)
562 time_t t
= queue
->time
;
564 /* the client expects localtime */
565 t
-= get_time_zone(t
);
567 PACKI(desc
,"W",pjobid_to_rap(lp_const_servicename(snum
),queue
->job
)); /* uJobId */
569 PACKS(desc
,"B21",queue
->fs_user
); /* szUserName */
570 PACKS(desc
,"B",""); /* pad */
571 PACKS(desc
,"B16",""); /* szNotifyName */
572 PACKS(desc
,"B10","PM_Q_RAW"); /* szDataType */
573 PACKS(desc
,"z",""); /* pszParms */
574 PACKI(desc
,"W",n
+1); /* uPosition */
575 PACKI(desc
,"W",printj_status(queue
->status
)); /* fsStatus */
576 PACKS(desc
,"z",""); /* pszStatus */
577 PACKI(desc
,"D",t
); /* ulSubmitted */
578 PACKI(desc
,"D",queue
->size
); /* ulSize */
579 PACKS(desc
,"z",queue
->fs_file
); /* pszComment */
581 if (uLevel
== 2 || uLevel
== 3 || uLevel
== 4) {
582 PACKI(desc
,"W",queue
->priority
); /* uPriority */
583 PACKS(desc
,"z",queue
->fs_user
); /* pszUserName */
584 PACKI(desc
,"W",n
+1); /* uPosition */
585 PACKI(desc
,"W",printj_status(queue
->status
)); /* fsStatus */
586 PACKI(desc
,"D",t
); /* ulSubmitted */
587 PACKI(desc
,"D",queue
->size
); /* ulSize */
588 PACKS(desc
,"z","Samba"); /* pszComment */
589 PACKS(desc
,"z",queue
->fs_file
); /* pszDocument */
591 PACKS(desc
,"z",""); /* pszNotifyName */
592 PACKS(desc
,"z","PM_Q_RAW"); /* pszDataType */
593 PACKS(desc
,"z",""); /* pszParms */
594 PACKS(desc
,"z",""); /* pszStatus */
595 PACKS(desc
,"z",SERVICE(snum
)); /* pszQueue */
596 PACKS(desc
,"z","lpd"); /* pszQProcName */
597 PACKS(desc
,"z",""); /* pszQProcParms */
598 PACKS(desc
,"z","NULL"); /* pszDriverName */
599 PackDriverData(desc
); /* pDriverData */
600 PACKS(desc
,"z",""); /* pszPrinterName */
601 } else if (uLevel
== 4) { /* OS2 */
602 PACKS(desc
,"z",""); /* pszSpoolFileName */
603 PACKS(desc
,"z",""); /* pszPortName */
604 PACKS(desc
,"z",""); /* pszStatus */
605 PACKI(desc
,"D",0); /* ulPagesSpooled */
606 PACKI(desc
,"D",0); /* ulPagesSent */
607 PACKI(desc
,"D",0); /* ulPagesPrinted */
608 PACKI(desc
,"D",0); /* ulTimePrinted */
609 PACKI(desc
,"D",0); /* ulExtendJobStatus */
610 PACKI(desc
,"D",0); /* ulStartPage */
611 PACKI(desc
,"D",0); /* ulEndPage */
616 /********************************************************************
617 Return a driver name given an snum.
618 Returns True if from tdb, False otherwise.
619 ********************************************************************/
621 static bool get_driver_name(int snum
, char **pp_drivername
)
623 NT_PRINTER_INFO_LEVEL
*info
= NULL
;
626 get_a_printer (NULL
, &info
, 2, lp_servicename(snum
));
628 *pp_drivername
= talloc_strdup(talloc_tos(),
629 info
->info_2
->drivername
);
631 free_a_printer(&info
, 2);
632 if (!*pp_drivername
) {
640 /********************************************************************
641 Respond to the DosPrintQInfo command with a level of 52
642 This is used to get printer driver information for Win9x clients
643 ********************************************************************/
644 static void fill_printq_info_52(connection_struct
*conn
, int snum
,
645 struct pack_desc
* desc
, int count
)
649 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
650 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
654 if ( !W_ERROR_IS_OK(get_a_printer( NULL
, &printer
, 2, lp_servicename(snum
))) ) {
655 DEBUG(3,("fill_printq_info_52: Failed to lookup printer [%s]\n",
656 lp_servicename(snum
)));
660 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
,
663 DEBUG(3,("fill_printq_info_52: Failed to lookup driver [%s]\n",
664 printer
->info_2
->drivername
));
668 trim_string(driver
.info_3
->driverpath
, "\\print$\\WIN40\\0\\", 0);
669 trim_string(driver
.info_3
->datafile
, "\\print$\\WIN40\\0\\", 0);
670 trim_string(driver
.info_3
->helpfile
, "\\print$\\WIN40\\0\\", 0);
672 PACKI(desc
, "W", 0x0400); /* don't know */
673 PACKS(desc
, "z", driver
.info_3
->name
); /* long printer name */
674 PACKS(desc
, "z", driver
.info_3
->driverpath
); /* Driverfile Name */
675 PACKS(desc
, "z", driver
.info_3
->datafile
); /* Datafile name */
676 PACKS(desc
, "z", driver
.info_3
->monitorname
); /* language monitor */
678 fstrcpy(location
, "\\\\%L\\print$\\WIN40\\0");
679 standard_sub_basic( "", "", location
, sizeof(location
)-1 );
680 PACKS(desc
,"z", location
); /* share to retrieve files */
682 PACKS(desc
,"z", driver
.info_3
->defaultdatatype
); /* default data type */
683 PACKS(desc
,"z", driver
.info_3
->helpfile
); /* helpfile name */
684 PACKS(desc
,"z", driver
.info_3
->driverpath
); /* driver name */
686 DEBUG(3,("Printer Driver Name: %s:\n",driver
.info_3
->name
));
687 DEBUG(3,("Driver: %s:\n",driver
.info_3
->driverpath
));
688 DEBUG(3,("Data File: %s:\n",driver
.info_3
->datafile
));
689 DEBUG(3,("Language Monitor: %s:\n",driver
.info_3
->monitorname
));
690 DEBUG(3,("Driver Location: %s:\n",location
));
691 DEBUG(3,("Data Type: %s:\n",driver
.info_3
->defaultdatatype
));
692 DEBUG(3,("Help File: %s:\n",driver
.info_3
->helpfile
));
693 PACKI(desc
,"N",count
); /* number of files to copy */
695 for ( i
=0; i
<count
&& driver
.info_3
->dependentfiles
&& *driver
.info_3
->dependentfiles
[i
]; i
++)
697 trim_string(driver
.info_3
->dependentfiles
[i
], "\\print$\\WIN40\\0\\", 0);
698 PACKS(desc
,"z",driver
.info_3
->dependentfiles
[i
]); /* driver files to copy */
699 DEBUG(3,("Dependent File: %s:\n",driver
.info_3
->dependentfiles
[i
]));
704 DEBUG(3,("fill_printq_info_52: file count specified by client [%d] != number of dependent files [%i]\n",
707 DEBUG(3,("fill_printq_info on <%s> gave %d entries\n", SERVICE(snum
),i
));
709 desc
->errcode
=NERR_Success
;
713 DEBUG(3,("fill_printq_info: Can't supply driver files\n"));
714 desc
->errcode
=NERR_notsupported
;
718 free_a_printer( &printer
, 2 );
721 free_a_printer_driver( driver
, 3 );
725 static void fill_printq_info(connection_struct
*conn
, int snum
, int uLevel
,
726 struct pack_desc
* desc
,
727 int count
, print_queue_struct
* queue
,
728 print_status_struct
* status
)
733 PACKS(desc
,"B13",SERVICE(snum
));
738 PACKS(desc
,"z",Expand(conn
,snum
,SERVICE(snum
)));
741 PACKI(desc
,"K",printq_status(status
->status
));
745 if (uLevel
== 1 || uLevel
== 2) {
746 PACKS(desc
,"B",""); /* alignment */
747 PACKI(desc
,"W",5); /* priority */
748 PACKI(desc
,"W",0); /* start time */
749 PACKI(desc
,"W",0); /* until time */
750 PACKS(desc
,"z",""); /* pSepFile */
751 PACKS(desc
,"z","lpd"); /* pPrProc */
752 PACKS(desc
,"z",SERVICE(snum
)); /* pDestinations */
753 PACKS(desc
,"z",""); /* pParms */
755 PACKS(desc
,"z","UNKNOWN PRINTER");
756 PACKI(desc
,"W",LPSTAT_ERROR
);
758 else if (!status
|| !status
->message
[0]) {
759 PACKS(desc
,"z",Expand(conn
,snum
,lp_comment(snum
)));
760 PACKI(desc
,"W",LPSTAT_OK
); /* status */
762 PACKS(desc
,"z",status
->message
);
763 PACKI(desc
,"W",printq_status(status
->status
)); /* status */
765 PACKI(desc
,(uLevel
== 1 ? "W" : "N"),count
);
768 if (uLevel
== 3 || uLevel
== 4) {
769 char *drivername
= NULL
;
771 PACKI(desc
,"W",5); /* uPriority */
772 PACKI(desc
,"W",0); /* uStarttime */
773 PACKI(desc
,"W",0); /* uUntiltime */
774 PACKI(desc
,"W",5); /* pad1 */
775 PACKS(desc
,"z",""); /* pszSepFile */
776 PACKS(desc
,"z","WinPrint"); /* pszPrProc */
777 PACKS(desc
,"z",NULL
); /* pszParms */
778 PACKS(desc
,"z",NULL
); /* pszComment - don't ask.... JRA */
779 /* "don't ask" that it's done this way to fix corrupted
780 Win9X/ME printer comments. */
782 PACKI(desc
,"W",LPSTAT_OK
); /* fsStatus */
784 PACKI(desc
,"W",printq_status(status
->status
)); /* fsStatus */
786 PACKI(desc
,(uLevel
== 3 ? "W" : "N"),count
); /* cJobs */
787 PACKS(desc
,"z",SERVICE(snum
)); /* pszPrinters */
788 get_driver_name(snum
,&drivername
);
792 PACKS(desc
,"z",drivername
); /* pszDriverName */
793 PackDriverData(desc
); /* pDriverData */
796 if (uLevel
== 2 || uLevel
== 4) {
798 for (i
=0;i
<count
;i
++)
799 fill_printjob_info(conn
,snum
,uLevel
== 2 ? 1 : 2,desc
,&queue
[i
],i
);
803 fill_printq_info_52( conn
, snum
, desc
, count
);
806 /* This function returns the number of files for a given driver */
807 static int get_printerdrivernumber(int snum
)
810 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
811 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
815 if ( !W_ERROR_IS_OK(get_a_printer( NULL
, &printer
, 2, lp_servicename(snum
))) ) {
816 DEBUG(3,("get_printerdrivernumber: Failed to lookup printer [%s]\n",
817 lp_servicename(snum
)));
821 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
,
824 DEBUG(3,("get_printerdrivernumber: Failed to lookup driver [%s]\n",
825 printer
->info_2
->drivername
));
829 /* count the number of files */
830 while ( driver
.info_3
->dependentfiles
&& *driver
.info_3
->dependentfiles
[result
] )
835 free_a_printer( &printer
, 2 );
838 free_a_printer_driver( driver
, 3 );
843 static bool api_DosPrintQGetInfo(connection_struct
*conn
, uint16 vuid
,
844 char *param
, int tpscnt
,
845 char *data
, int tdscnt
,
846 int mdrcnt
,int mprcnt
,
847 char **rdata
,char **rparam
,
848 int *rdata_len
,int *rparam_len
)
850 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
851 char *str2
= skip_string(param
,tpscnt
,str1
);
852 char *p
= skip_string(param
,tpscnt
,str2
);
858 struct pack_desc desc
;
859 print_queue_struct
*queue
=NULL
;
860 print_status_struct status
;
863 if (!str1
|| !str2
|| !p
) {
866 memset((char *)&status
,'\0',sizeof(status
));
867 memset((char *)&desc
,'\0',sizeof(desc
));
869 p
= skip_string(param
,tpscnt
,p
);
873 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
874 str3
= get_safe_str_ptr(param
,tpscnt
,p
,4);
875 /* str3 may be null here and is checked in check_printq_info(). */
877 /* remove any trailing username */
878 if ((p
= strchr_m(QueueName
,'%')))
881 DEBUG(3,("api_DosPrintQGetInfo uLevel=%d name=%s\n",uLevel
,QueueName
));
883 /* check it's a supported varient */
884 if (!prefix_ok(str1
,"zWrLh"))
886 if (!check_printq_info(&desc
,uLevel
,str2
,str3
)) {
888 * Patch from Scott Moomaw <scott@bridgewater.edu>
889 * to return the 'invalid info level' error if an
890 * unknown level was requested.
894 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
898 SSVALS(*rparam
,0,ERRunknownlevel
);
904 snum
= find_service(QueueName
);
905 if ( !(lp_snum_ok(snum
) && lp_print_ok(snum
)) )
909 count
= get_printerdrivernumber(snum
);
910 DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count
));
912 count
= print_queue_status(snum
, &queue
,&status
);
916 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
922 desc
.buflen
= mdrcnt
;
925 * Don't return data but need to get correct length
926 * init_package will return wrong size if buflen=0
928 desc
.buflen
= getlen(desc
.format
);
929 desc
.base
= tmpdata
= (char *) SMB_MALLOC (desc
.buflen
);
932 if (init_package(&desc
,1,count
)) {
933 desc
.subcount
= count
;
934 fill_printq_info(conn
,snum
,uLevel
,&desc
,count
,queue
,&status
);
937 *rdata_len
= desc
.usedlen
;
940 * We must set the return code to ERRbuftoosmall
941 * in order to support lanman style printing with Win NT/2k
944 if (!mdrcnt
&& lp_disable_spoolss())
945 desc
.errcode
= ERRbuftoosmall
;
947 *rdata_len
= desc
.usedlen
;
949 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
955 SSVALS(*rparam
,0,desc
.errcode
);
957 SSVAL(*rparam
,4,desc
.neededlen
);
959 DEBUG(4,("printqgetinfo: errorcode %d\n",desc
.errcode
));
967 /****************************************************************************
968 View list of all print jobs on all queues.
969 ****************************************************************************/
971 static bool api_DosPrintQEnum(connection_struct
*conn
, uint16 vuid
,
972 char *param
, int tpscnt
,
973 char *data
, int tdscnt
,
974 int mdrcnt
, int mprcnt
,
975 char **rdata
, char** rparam
,
976 int *rdata_len
, int *rparam_len
)
978 char *param_format
= get_safe_str_ptr(param
,tpscnt
,param
,2);
979 char *output_format1
= skip_string(param
,tpscnt
,param_format
);
980 char *p
= skip_string(param
,tpscnt
,output_format1
);
981 unsigned int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
982 char *output_format2
= get_safe_str_ptr(param
,tpscnt
,p
,4);
983 int services
= lp_numservices();
985 struct pack_desc desc
;
986 print_queue_struct
**queue
= NULL
;
987 print_status_struct
*status
= NULL
;
988 int *subcntarr
= NULL
;
989 int queuecnt
= 0, subcnt
= 0, succnt
= 0;
991 if (!param_format
|| !output_format1
|| !p
) {
995 memset((char *)&desc
,'\0',sizeof(desc
));
997 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel
));
999 if (!prefix_ok(param_format
,"WrLeh")) {
1002 if (!check_printq_info(&desc
,uLevel
,output_format1
,output_format2
)) {
1004 * Patch from Scott Moomaw <scott@bridgewater.edu>
1005 * to return the 'invalid info level' error if an
1006 * unknown level was requested.
1010 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1014 SSVALS(*rparam
,0,ERRunknownlevel
);
1020 for (i
= 0; i
< services
; i
++) {
1021 if (lp_snum_ok(i
) && lp_print_ok(i
) && lp_browseable(i
)) {
1026 if((queue
= SMB_MALLOC_ARRAY(print_queue_struct
*, queuecnt
)) == NULL
) {
1027 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
1030 memset(queue
,0,queuecnt
*sizeof(print_queue_struct
*));
1031 if((status
= SMB_MALLOC_ARRAY(print_status_struct
,queuecnt
)) == NULL
) {
1032 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
1035 memset(status
,0,queuecnt
*sizeof(print_status_struct
));
1036 if((subcntarr
= SMB_MALLOC_ARRAY(int,queuecnt
)) == NULL
) {
1037 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
1043 for (i
= 0; i
< services
; i
++) {
1044 if (lp_snum_ok(i
) && lp_print_ok(i
) && lp_browseable(i
)) {
1045 subcntarr
[n
] = print_queue_status(i
, &queue
[n
],&status
[n
]);
1046 subcnt
+= subcntarr
[n
];
1052 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
1058 desc
.buflen
= mdrcnt
;
1060 if (init_package(&desc
,queuecnt
,subcnt
)) {
1063 for (i
= 0; i
< services
; i
++) {
1064 if (lp_snum_ok(i
) && lp_print_ok(i
) && lp_browseable(i
)) {
1065 fill_printq_info(conn
,i
,uLevel
,&desc
,subcntarr
[n
],queue
[n
],&status
[n
]);
1067 if (desc
.errcode
== NERR_Success
) {
1074 SAFE_FREE(subcntarr
);
1076 *rdata_len
= desc
.usedlen
;
1078 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1082 SSVALS(*rparam
,0,desc
.errcode
);
1084 SSVAL(*rparam
,4,succnt
);
1085 SSVAL(*rparam
,6,queuecnt
);
1087 for (i
= 0; i
< queuecnt
; i
++) {
1089 SAFE_FREE(queue
[i
]);
1100 SAFE_FREE(subcntarr
);
1101 for (i
= 0; i
< queuecnt
; i
++) {
1103 SAFE_FREE(queue
[i
]);
1112 /****************************************************************************
1113 Get info level for a server list query.
1114 ****************************************************************************/
1116 static bool check_server_info(int uLevel
, char* id
)
1120 if (strcmp(id
,"B16") != 0) {
1125 if (strcmp(id
,"B16BBDz") != 0) {
1135 struct srv_info_struct
{
1143 /*******************************************************************
1144 Get server info lists from the files saved by nmbd. Return the
1146 ******************************************************************/
1148 static int get_server_info(uint32 servertype
,
1149 struct srv_info_struct
**servers
,
1155 bool local_list_only
;
1158 lines
= file_lines_load(cache_path(SERVER_LIST
), NULL
, 0, NULL
);
1160 DEBUG(4,("Can't open %s - %s\n",cache_path(SERVER_LIST
),strerror(errno
)));
1164 /* request for everything is code for request all servers */
1165 if (servertype
== SV_TYPE_ALL
) {
1166 servertype
&= ~(SV_TYPE_DOMAIN_ENUM
|SV_TYPE_LOCAL_LIST_ONLY
);
1169 local_list_only
= (servertype
& SV_TYPE_LOCAL_LIST_ONLY
);
1171 DEBUG(4,("Servertype search: %8x\n",servertype
));
1173 for (i
=0;lines
[i
];i
++) {
1175 struct srv_info_struct
*s
;
1176 const char *ptr
= lines
[i
];
1178 TALLOC_CTX
*frame
= NULL
;
1185 if (count
== alloced
) {
1187 *servers
= SMB_REALLOC_ARRAY(*servers
,struct srv_info_struct
, alloced
);
1189 DEBUG(0,("get_server_info: failed to enlarge servers info struct!\n"));
1193 memset((char *)((*servers
)+count
),'\0',sizeof(**servers
)*(alloced
-count
));
1195 s
= &(*servers
)[count
];
1197 frame
= talloc_stackframe();
1199 if (!next_token_talloc(frame
,&ptr
,&p
, NULL
)) {
1203 fstrcpy(s
->name
, p
);
1206 if (!next_token_talloc(frame
,&ptr
, &p
, NULL
)) {
1212 s
->comment
[0] = '\0';
1213 if (!next_token_talloc(frame
,&ptr
, &p
, NULL
)) {
1217 fstrcpy(s
->comment
, p
);
1218 string_truncate(s
->comment
, MAX_SERVER_STRING_LENGTH
);
1220 s
->domain
[0] = '\0';
1221 if (!next_token_talloc(frame
,&ptr
,&p
, NULL
)) {
1222 /* this allows us to cope with an old nmbd */
1223 fstrcpy(s
->domain
,lp_workgroup());
1225 fstrcpy(s
->domain
, p
);
1229 if (sscanf(stype
,"%X",&s
->type
) != 1) {
1230 DEBUG(4,("r:host file "));
1234 /* Filter the servers/domains we return based on what was asked for. */
1236 /* Check to see if we are being asked for a local list only. */
1237 if(local_list_only
&& ((s
->type
& SV_TYPE_LOCAL_LIST_ONLY
) == 0)) {
1238 DEBUG(4,("r: local list only"));
1242 /* doesn't match up: don't want it */
1243 if (!(servertype
& s
->type
)) {
1244 DEBUG(4,("r:serv type "));
1248 if ((servertype
& SV_TYPE_DOMAIN_ENUM
) !=
1249 (s
->type
& SV_TYPE_DOMAIN_ENUM
)) {
1250 DEBUG(4,("s: dom mismatch "));
1254 if (!strequal(domain
, s
->domain
) && !(servertype
& SV_TYPE_DOMAIN_ENUM
)) {
1258 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
1259 s
->type
&= ~SV_TYPE_LOCAL_LIST_ONLY
;
1262 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
1263 s
->name
, s
->type
, s
->comment
, s
->domain
));
1264 s
->server_added
= True
;
1267 DEBUG(4,("%20s %8x %25s %15s\n",
1268 s
->name
, s
->type
, s
->comment
, s
->domain
));
1276 /*******************************************************************
1277 Fill in a server info structure.
1278 ******************************************************************/
1280 static int fill_srv_info(struct srv_info_struct
*service
,
1281 int uLevel
, char **buf
, int *buflen
,
1282 char **stringbuf
, int *stringspace
, char *baseaddr
)
1305 len
= strlen(service
->comment
)+1;
1309 *buflen
= struct_len
;
1311 return struct_len
+ len
;
1316 if (*buflen
< struct_len
) {
1323 p2
= p
+ struct_len
;
1324 l2
= *buflen
- struct_len
;
1332 push_ascii(p
,service
->name
, MAX_NETBIOSNAME_LEN
, STR_TERMINATE
);
1336 push_ascii(p
,service
->name
,MAX_NETBIOSNAME_LEN
, STR_TERMINATE
);
1337 SIVAL(p
,18,service
->type
);
1338 SIVAL(p
,22,PTR_DIFF(p2
,baseaddr
));
1339 len
+= CopyAndAdvance(&p2
,service
->comment
,&l2
);
1344 *buf
= p
+ struct_len
;
1345 *buflen
-= struct_len
;
1356 static bool srv_comp(struct srv_info_struct
*s1
,struct srv_info_struct
*s2
)
1358 return(strcmp(s1
->name
,s2
->name
));
1361 /****************************************************************************
1362 View list of servers available (or possibly domains). The info is
1363 extracted from lists saved by nmbd on the local host.
1364 ****************************************************************************/
1366 static bool api_RNetServerEnum(connection_struct
*conn
, uint16 vuid
,
1367 char *param
, int tpscnt
,
1368 char *data
, int tdscnt
,
1369 int mdrcnt
, int mprcnt
, char **rdata
,
1370 char **rparam
, int *rdata_len
, int *rparam_len
)
1372 char *str1
= get_safe_str_ptr(param
, tpscnt
, param
, 2);
1373 char *str2
= skip_string(param
,tpscnt
,str1
);
1374 char *p
= skip_string(param
,tpscnt
,str2
);
1375 int uLevel
= get_safe_SVAL(param
, tpscnt
, p
, 0, -1);
1376 int buf_len
= get_safe_SVAL(param
,tpscnt
, p
, 2, 0);
1377 uint32 servertype
= get_safe_IVAL(param
,tpscnt
,p
,4, 0);
1379 int data_len
, fixed_len
, string_len
;
1380 int f_len
= 0, s_len
= 0;
1381 struct srv_info_struct
*servers
=NULL
;
1382 int counted
=0,total
=0;
1385 bool domain_request
;
1388 if (!str1
|| !str2
|| !p
) {
1392 /* If someone sets all the bits they don't really mean to set
1393 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1396 if (servertype
== SV_TYPE_ALL
) {
1397 servertype
&= ~(SV_TYPE_DOMAIN_ENUM
|SV_TYPE_LOCAL_LIST_ONLY
);
1400 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1401 any other bit (they may just set this bit on its own) they
1402 want all the locally seen servers. However this bit can be
1403 set on its own so set the requested servers to be
1404 ALL - DOMAIN_ENUM. */
1406 if ((servertype
& SV_TYPE_LOCAL_LIST_ONLY
) && !(servertype
& SV_TYPE_DOMAIN_ENUM
)) {
1407 servertype
= SV_TYPE_ALL
& ~(SV_TYPE_DOMAIN_ENUM
);
1410 domain_request
= ((servertype
& SV_TYPE_DOMAIN_ENUM
) != 0);
1411 local_request
= ((servertype
& SV_TYPE_LOCAL_LIST_ONLY
) != 0);
1415 if (!prefix_ok(str1
,"WrLehD")) {
1418 if (!check_server_info(uLevel
,str2
)) {
1422 DEBUG(4, ("server request level: %s %8x ", str2
, servertype
));
1423 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request
)));
1424 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request
)));
1426 if (strcmp(str1
, "WrLehDz") == 0) {
1427 if (skip_string(param
,tpscnt
,p
) == NULL
) {
1430 pull_ascii_fstring(domain
, p
);
1432 fstrcpy(domain
, lp_workgroup());
1435 if (lp_browse_list()) {
1436 total
= get_server_info(servertype
,&servers
,domain
);
1439 data_len
= fixed_len
= string_len
= 0;
1443 qsort(servers
,total
,sizeof(servers
[0]),QSORT_CAST srv_comp
);
1447 char *lastname
=NULL
;
1449 for (i
=0;i
<total
;i
++) {
1450 struct srv_info_struct
*s
= &servers
[i
];
1452 if (lastname
&& strequal(lastname
,s
->name
)) {
1456 data_len
+= fill_srv_info(s
,uLevel
,0,&f_len
,0,&s_len
,0);
1457 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1458 s
->name
, s
->type
, s
->comment
, s
->domain
));
1460 if (data_len
<= buf_len
) {
1463 string_len
+= s_len
;
1470 *rdata_len
= fixed_len
+ string_len
;
1471 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
1476 p2
= (*rdata
) + fixed_len
; /* auxilliary data (strings) will go here */
1482 char *lastname
=NULL
;
1483 int count2
= counted
;
1485 for (i
= 0; i
< total
&& count2
;i
++) {
1486 struct srv_info_struct
*s
= &servers
[i
];
1488 if (lastname
&& strequal(lastname
,s
->name
)) {
1492 fill_srv_info(s
,uLevel
,&p
,&f_len
,&p2
,&s_len
,*rdata
);
1493 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1494 s
->name
, s
->type
, s
->comment
, s
->domain
));
1500 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1504 SSVAL(*rparam
,0,(missed
== 0 ? NERR_Success
: ERRmoredata
));
1506 SSVAL(*rparam
,4,counted
);
1507 SSVAL(*rparam
,6,counted
+missed
);
1511 DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
1512 domain
,uLevel
,counted
,counted
+missed
));
1517 /****************************************************************************
1518 command 0x34 - suspected of being a "Lookup Names" stub api
1519 ****************************************************************************/
1521 static bool api_RNetGroupGetUsers(connection_struct
*conn
, uint16 vuid
,
1522 char *param
, int tpscnt
,
1523 char *data
, int tdscnt
,
1524 int mdrcnt
, int mprcnt
, char **rdata
,
1525 char **rparam
, int *rdata_len
, int *rparam_len
)
1527 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
1528 char *str2
= skip_string(param
,tpscnt
,str1
);
1529 char *p
= skip_string(param
,tpscnt
,str2
);
1530 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
1531 int buf_len
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
1535 if (!str1
|| !str2
|| !p
) {
1539 DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
1540 str1
, str2
, p
, uLevel
, buf_len
));
1542 if (!prefix_ok(str1
,"zWrLeh")) {
1549 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1554 SSVAL(*rparam
,0,0x08AC); /* informational warning message */
1556 SSVAL(*rparam
,4,counted
);
1557 SSVAL(*rparam
,6,counted
+missed
);
1562 /****************************************************************************
1563 get info about a share
1564 ****************************************************************************/
1566 static bool check_share_info(int uLevel
, char* id
)
1570 if (strcmp(id
,"B13") != 0) {
1575 if (strcmp(id
,"B13BWz") != 0) {
1580 if (strcmp(id
,"B13BWzWWWzB9B") != 0) {
1585 if (strcmp(id
,"B13BWzWWWzB9BB9BWzWWzWW") != 0) {
1595 static int fill_share_info(connection_struct
*conn
, int snum
, int uLevel
,
1596 char** buf
, int* buflen
,
1597 char** stringbuf
, int* stringspace
, char* baseaddr
)
1626 len
+= StrlenExpanded(conn
,snum
,lp_comment(snum
));
1629 len
+= strlen(lp_pathname(snum
)) + 1;
1632 *buflen
= struct_len
;
1637 return struct_len
+ len
;
1642 if ((*buflen
) < struct_len
) {
1650 p2
= p
+ struct_len
;
1651 l2
= (*buflen
) - struct_len
;
1658 push_ascii(p
,lp_servicename(snum
),13, STR_TERMINATE
);
1664 type
= STYPE_DISKTREE
;
1665 if (lp_print_ok(snum
)) {
1666 type
= STYPE_PRINTQ
;
1668 if (strequal("IPC",lp_fstype(snum
))) {
1671 SSVAL(p
,14,type
); /* device type */
1672 SIVAL(p
,16,PTR_DIFF(p2
,baseaddr
));
1673 len
+= CopyExpanded(conn
,snum
,&p2
,lp_comment(snum
),&l2
);
1677 SSVAL(p
,20,ACCESS_READ
|ACCESS_WRITE
|ACCESS_CREATE
); /* permissions */
1678 SSVALS(p
,22,-1); /* max uses */
1679 SSVAL(p
,24,1); /* current uses */
1680 SIVAL(p
,26,PTR_DIFF(p2
,baseaddr
)); /* local pathname */
1681 len
+= CopyAndAdvance(&p2
,lp_pathname(snum
),&l2
);
1682 memset(p
+30,0,SHPWLEN
+2); /* passwd (reserved), pad field */
1686 memset(p
+40,0,SHPWLEN
+2);
1697 (*buf
) = p
+ struct_len
;
1698 (*buflen
) -= struct_len
;
1700 (*stringspace
) = l2
;
1709 static bool api_RNetShareGetInfo(connection_struct
*conn
,uint16 vuid
,
1710 char *param
, int tpscnt
,
1711 char *data
, int tdscnt
,
1712 int mdrcnt
,int mprcnt
,
1713 char **rdata
,char **rparam
,
1714 int *rdata_len
,int *rparam_len
)
1716 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
1717 char *str2
= skip_string(param
,tpscnt
,str1
);
1718 char *netname
= skip_string(param
,tpscnt
,str2
);
1719 char *p
= skip_string(param
,tpscnt
,netname
);
1720 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
1723 if (!str1
|| !str2
|| !netname
|| !p
) {
1727 snum
= find_service(netname
);
1732 /* check it's a supported varient */
1733 if (!prefix_ok(str1
,"zWrLh")) {
1736 if (!check_share_info(uLevel
,str2
)) {
1740 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
1745 *rdata_len
= fill_share_info(conn
,snum
,uLevel
,&p
,&mdrcnt
,0,0,0);
1746 if (*rdata_len
< 0) {
1751 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1755 SSVAL(*rparam
,0,NERR_Success
);
1756 SSVAL(*rparam
,2,0); /* converter word */
1757 SSVAL(*rparam
,4,*rdata_len
);
1762 /****************************************************************************
1763 View the list of available shares.
1765 This function is the server side of the NetShareEnum() RAP call.
1766 It fills the return buffer with share names and share comments.
1767 Note that the return buffer normally (in all known cases) allows only
1768 twelve byte strings for share names (plus one for a nul terminator).
1769 Share names longer than 12 bytes must be skipped.
1770 ****************************************************************************/
1772 static bool api_RNetShareEnum( connection_struct
*conn
, uint16 vuid
,
1773 char *param
, int tpscnt
,
1774 char *data
, int tdscnt
,
1782 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
1783 char *str2
= skip_string(param
,tpscnt
,str1
);
1784 char *p
= skip_string(param
,tpscnt
,str2
);
1785 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
1786 int buf_len
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
1789 int total
=0,counted
=0;
1790 bool missed
= False
;
1792 int data_len
, fixed_len
, string_len
;
1793 int f_len
= 0, s_len
= 0;
1795 if (!str1
|| !str2
|| !p
) {
1799 if (!prefix_ok(str1
,"WrLeh")) {
1802 if (!check_share_info(uLevel
,str2
)) {
1806 /* Ensure all the usershares are loaded. */
1808 load_registry_shares();
1809 count
= load_usershare_shares();
1812 data_len
= fixed_len
= string_len
= 0;
1813 for (i
=0;i
<count
;i
++) {
1814 fstring servicename_dos
;
1815 if (!(lp_browseable(i
) && lp_snum_ok(i
))) {
1818 push_ascii_fstring(servicename_dos
, lp_servicename(i
));
1819 /* Maximum name length = 13. */
1820 if( lp_browseable( i
) && lp_snum_ok( i
) && (strlen(servicename_dos
) < 13)) {
1822 data_len
+= fill_share_info(conn
,i
,uLevel
,0,&f_len
,0,&s_len
,0);
1823 if (data_len
<= buf_len
) {
1826 string_len
+= s_len
;
1833 *rdata_len
= fixed_len
+ string_len
;
1834 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
1839 p2
= (*rdata
) + fixed_len
; /* auxiliary data (strings) will go here */
1844 for( i
= 0; i
< count
; i
++ ) {
1845 fstring servicename_dos
;
1846 if (!(lp_browseable(i
) && lp_snum_ok(i
))) {
1850 push_ascii_fstring(servicename_dos
, lp_servicename(i
));
1851 if (lp_browseable(i
) && lp_snum_ok(i
) && (strlen(servicename_dos
) < 13)) {
1852 if (fill_share_info( conn
,i
,uLevel
,&p
,&f_len
,&p2
,&s_len
,*rdata
) < 0) {
1859 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1863 SSVAL(*rparam
,0,missed
? ERRmoredata
: NERR_Success
);
1865 SSVAL(*rparam
,4,counted
);
1866 SSVAL(*rparam
,6,total
);
1868 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
1869 counted
,total
,uLevel
,
1870 buf_len
,*rdata_len
,mdrcnt
));
1875 /****************************************************************************
1877 ****************************************************************************/
1879 static bool api_RNetShareAdd(connection_struct
*conn
,uint16 vuid
,
1880 char *param
, int tpscnt
,
1881 char *data
, int tdscnt
,
1882 int mdrcnt
,int mprcnt
,
1883 char **rdata
,char **rparam
,
1884 int *rdata_len
,int *rparam_len
)
1886 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
1887 char *str2
= skip_string(param
,tpscnt
,str1
);
1888 char *p
= skip_string(param
,tpscnt
,str2
);
1889 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
1892 char *pathname
= NULL
;
1893 char *command
, *cmdname
;
1894 unsigned int offset
;
1897 size_t converted_size
;
1899 if (!str1
|| !str2
|| !p
) {
1903 /* check it's a supported varient */
1904 if (!prefix_ok(str1
,RAP_WShareAdd_REQ
)) {
1907 if (!check_share_info(uLevel
,str2
)) {
1914 /* Do we have a string ? */
1915 if (skip_string(data
,mdrcnt
,data
) == NULL
) {
1918 pull_ascii_fstring(sharename
,data
);
1919 snum
= find_service(sharename
);
1920 if (snum
>= 0) { /* already exists */
1929 /* only support disk share adds */
1930 if (SVAL(data
,14)!=STYPE_DISKTREE
) {
1934 offset
= IVAL(data
, 16);
1935 if (offset
>= mdrcnt
) {
1936 res
= ERRinvalidparam
;
1940 /* Do we have a string ? */
1941 if (skip_string(data
,mdrcnt
,data
+offset
) == NULL
) {
1944 pull_ascii_fstring(comment
, offset
? (data
+offset
) : "");
1946 offset
= IVAL(data
, 26);
1948 if (offset
>= mdrcnt
) {
1949 res
= ERRinvalidparam
;
1953 /* Do we have a string ? */
1954 if (skip_string(data
,mdrcnt
,data
+offset
) == NULL
) {
1958 if (!pull_ascii_talloc(talloc_tos(), &pathname
,
1959 offset
? (data
+offset
) : "", &converted_size
))
1961 DEBUG(0,("api_RNetShareAdd: pull_ascii_talloc failed: %s",
1969 string_replace(sharename
, '"', ' ');
1970 string_replace(pathname
, '"', ' ');
1971 string_replace(comment
, '"', ' ');
1973 cmdname
= lp_add_share_cmd();
1975 if (!cmdname
|| *cmdname
== '\0') {
1979 if (asprintf(&command
, "%s \"%s\" \"%s\" \"%s\" \"%s\"",
1980 lp_add_share_cmd(), get_dyn_CONFIGFILE(), sharename
,
1981 pathname
, comment
) == -1) {
1985 DEBUG(10,("api_RNetShareAdd: Running [%s]\n", command
));
1987 if ((res
= smbrun(command
, NULL
)) != 0) {
1988 DEBUG(1,("api_RNetShareAdd: Running [%s] returned (%d)\n",
1995 message_send_all(smbd_messaging_context(),
1996 MSG_SMB_CONF_UPDATED
, NULL
, 0, NULL
);
2000 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2004 SSVAL(*rparam
,0,NERR_Success
);
2005 SSVAL(*rparam
,2,0); /* converter word */
2006 SSVAL(*rparam
,4,*rdata_len
);
2014 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2019 SSVAL(*rparam
,0,res
);
2024 /****************************************************************************
2025 view list of groups available
2026 ****************************************************************************/
2028 static bool api_RNetGroupEnum(connection_struct
*conn
,uint16 vuid
,
2029 char *param
, int tpscnt
,
2030 char *data
, int tdscnt
,
2031 int mdrcnt
,int mprcnt
,
2032 char **rdata
,char **rparam
,
2033 int *rdata_len
,int *rparam_len
)
2037 int resume_context
, cli_buf_size
;
2038 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2039 char *str2
= skip_string(param
,tpscnt
,str1
);
2040 char *p
= skip_string(param
,tpscnt
,str2
);
2042 uint32_t num_groups
;
2043 uint32_t resume_handle
;
2044 struct rpc_pipe_client
*samr_pipe
;
2045 struct policy_handle samr_handle
, domain_handle
;
2048 if (!str1
|| !str2
|| !p
) {
2052 if (strcmp(str1
,"WrLeh") != 0) {
2057 * W-> resume context (number of users to skip)
2058 * r -> return parameter pointer to receive buffer
2059 * L -> length of receive buffer
2060 * e -> return parameter number of entries
2061 * h -> return parameter total number of users
2064 if (strcmp("B21",str2
) != 0) {
2068 status
= rpc_pipe_open_internal(
2069 talloc_tos(), &ndr_table_samr
.syntax_id
, rpc_samr_dispatch
,
2070 conn
->server_info
, &samr_pipe
);
2071 if (!NT_STATUS_IS_OK(status
)) {
2072 DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
2073 nt_errstr(status
)));
2077 status
= rpccli_samr_Connect2(samr_pipe
, talloc_tos(), global_myname(),
2078 SAMR_ACCESS_LOOKUP_DOMAIN
, &samr_handle
);
2079 if (!NT_STATUS_IS_OK(status
)) {
2080 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2081 nt_errstr(status
)));
2085 status
= rpccli_samr_OpenDomain(samr_pipe
, talloc_tos(), &samr_handle
,
2086 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS
,
2087 get_global_sam_sid(), &domain_handle
);
2088 if (!NT_STATUS_IS_OK(status
)) {
2089 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2090 nt_errstr(status
)));
2091 rpccli_samr_Close(samr_pipe
, talloc_tos(), &samr_handle
);
2095 resume_context
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2096 cli_buf_size
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
2097 DEBUG(10,("api_RNetGroupEnum:resume context: %d, client buffer size: "
2098 "%d\n", resume_context
, cli_buf_size
));
2100 *rdata_len
= cli_buf_size
;
2101 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2108 errflags
= NERR_Success
;
2113 struct samr_SamArray
*sam_entries
;
2114 uint32_t num_entries
;
2116 status
= rpccli_samr_EnumDomainGroups(samr_pipe
, talloc_tos(),
2121 if (!NT_STATUS_IS_OK(status
)) {
2122 DEBUG(10, ("rpccli_samr_EnumDomainGroups returned "
2123 "%s\n", nt_errstr(status
)));
2127 if (num_entries
== 0) {
2128 DEBUG(10, ("rpccli_samr_EnumDomainGroups returned "
2129 "no entries -- done\n"));
2133 for(i
=0; i
<num_entries
; i
++) {
2136 name
= sam_entries
->entries
[i
].name
.string
;
2138 if( ((PTR_DIFF(p
,*rdata
)+21) > *rdata_len
) ) {
2139 /* set overflow error */
2140 DEBUG(3,("overflow on entry %d group %s\n", i
,
2146 /* truncate the name at 21 chars. */
2148 strlcpy(p
, name
, 21);
2149 DEBUG(10,("adding entry %d group %s\n", i
, p
));
2151 p
+= 5; /* Both NT4 and W2k3SP1 do padding here. No
2156 if (errflags
!= NERR_Success
) {
2160 TALLOC_FREE(sam_entries
);
2163 rpccli_samr_Close(samr_pipe
, talloc_tos(), &domain_handle
);
2164 rpccli_samr_Close(samr_pipe
, talloc_tos(), &samr_handle
);
2166 *rdata_len
= PTR_DIFF(p
,*rdata
);
2169 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2173 SSVAL(*rparam
, 0, errflags
);
2174 SSVAL(*rparam
, 2, 0); /* converter word */
2175 SSVAL(*rparam
, 4, num_groups
); /* is this right?? */
2176 SSVAL(*rparam
, 6, resume_context
+num_groups
); /* is this right?? */
2181 /*******************************************************************
2182 Get groups that a user is a member of.
2183 ******************************************************************/
2185 static bool api_NetUserGetGroups(connection_struct
*conn
,uint16 vuid
,
2186 char *param
, int tpscnt
,
2187 char *data
, int tdscnt
,
2188 int mdrcnt
,int mprcnt
,
2189 char **rdata
,char **rparam
,
2190 int *rdata_len
,int *rparam_len
)
2192 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2193 char *str2
= skip_string(param
,tpscnt
,str1
);
2194 char *UserName
= skip_string(param
,tpscnt
,str2
);
2195 char *p
= skip_string(param
,tpscnt
,UserName
);
2196 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2197 const char *level_string
;
2203 struct rpc_pipe_client
*samr_pipe
;
2204 struct policy_handle samr_handle
, domain_handle
, user_handle
;
2205 struct lsa_String name
;
2206 struct lsa_Strings names
;
2207 struct samr_Ids type
, rid
;
2208 struct samr_RidWithAttributeArray
*rids
;
2211 if (!str1
|| !str2
|| !UserName
|| !p
) {
2216 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2221 /* check it's a supported varient */
2223 if ( strcmp(str1
,"zWrLeh") != 0 )
2228 level_string
= "B21";
2234 if (strcmp(level_string
,str2
) != 0)
2237 *rdata_len
= mdrcnt
+ 1024;
2238 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2243 SSVAL(*rparam
,0,NERR_Success
);
2244 SSVAL(*rparam
,2,0); /* converter word */
2247 endp
= *rdata
+ *rdata_len
;
2249 status
= rpc_pipe_open_internal(
2250 talloc_tos(), &ndr_table_samr
.syntax_id
, rpc_samr_dispatch
,
2251 conn
->server_info
, &samr_pipe
);
2252 if (!NT_STATUS_IS_OK(status
)) {
2253 DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
2254 nt_errstr(status
)));
2258 status
= rpccli_samr_Connect2(samr_pipe
, talloc_tos(), global_myname(),
2259 SAMR_ACCESS_LOOKUP_DOMAIN
, &samr_handle
);
2260 if (!NT_STATUS_IS_OK(status
)) {
2261 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2262 nt_errstr(status
)));
2266 status
= rpccli_samr_OpenDomain(samr_pipe
, talloc_tos(), &samr_handle
,
2267 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT
,
2268 get_global_sam_sid(), &domain_handle
);
2269 if (!NT_STATUS_IS_OK(status
)) {
2270 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2271 nt_errstr(status
)));
2275 name
.string
= UserName
;
2277 status
= rpccli_samr_LookupNames(samr_pipe
, talloc_tos(),
2278 &domain_handle
, 1, &name
,
2280 if (!NT_STATUS_IS_OK(status
)) {
2281 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2282 nt_errstr(status
)));
2286 if (type
.ids
[0] != SID_NAME_USER
) {
2287 DEBUG(10, ("%s is a %s, not a user\n", UserName
,
2288 sid_type_lookup(type
.ids
[0])));
2292 status
= rpccli_samr_OpenUser(samr_pipe
, talloc_tos(),
2294 SAMR_USER_ACCESS_GET_GROUPS
,
2295 rid
.ids
[0], &user_handle
);
2296 if (!NT_STATUS_IS_OK(status
)) {
2297 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2298 nt_errstr(status
)));
2302 status
= rpccli_samr_GetGroupsForUser(samr_pipe
, talloc_tos(),
2303 &user_handle
, &rids
);
2304 if (!NT_STATUS_IS_OK(status
)) {
2305 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2306 nt_errstr(status
)));
2310 for (i
=0; i
<rids
->count
; i
++) {
2312 status
= rpccli_samr_LookupRids(samr_pipe
, talloc_tos(),
2314 1, &rids
->rids
[i
].rid
,
2316 if (NT_STATUS_IS_OK(status
) && (names
.count
== 1)) {
2317 strlcpy(p
, names
.names
[0].string
, PTR_DIFF(endp
,p
));
2323 *rdata_len
= PTR_DIFF(p
,*rdata
);
2325 SSVAL(*rparam
,4,count
); /* is this right?? */
2326 SSVAL(*rparam
,6,count
); /* is this right?? */
2331 rpccli_samr_Close(samr_pipe
, talloc_tos(), &user_handle
);
2333 rpccli_samr_Close(samr_pipe
, talloc_tos(), &domain_handle
);
2335 rpccli_samr_Close(samr_pipe
, talloc_tos(), &samr_handle
);
2340 /*******************************************************************
2342 ******************************************************************/
2344 static bool api_RNetUserEnum(connection_struct
*conn
, uint16 vuid
,
2345 char *param
, int tpscnt
,
2346 char *data
, int tdscnt
,
2347 int mdrcnt
,int mprcnt
,
2348 char **rdata
,char **rparam
,
2349 int *rdata_len
,int *rparam_len
)
2354 int i
, resume_context
, cli_buf_size
;
2355 uint32_t resume_handle
;
2357 struct rpc_pipe_client
*samr_pipe
;
2358 struct policy_handle samr_handle
, domain_handle
;
2361 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2362 char *str2
= skip_string(param
,tpscnt
,str1
);
2363 char *p
= skip_string(param
,tpscnt
,str2
);
2366 if (!str1
|| !str2
|| !p
) {
2370 if (strcmp(str1
,"WrLeh") != 0)
2373 * W-> resume context (number of users to skip)
2374 * r -> return parameter pointer to receive buffer
2375 * L -> length of receive buffer
2376 * e -> return parameter number of entries
2377 * h -> return parameter total number of users
2380 resume_context
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2381 cli_buf_size
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
2382 DEBUG(10,("api_RNetUserEnum:resume context: %d, client buffer size: %d\n",
2383 resume_context
, cli_buf_size
));
2386 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2391 /* check it's a supported varient */
2392 if (strcmp("B21",str2
) != 0)
2395 *rdata_len
= cli_buf_size
;
2396 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2402 endp
= *rdata
+ *rdata_len
;
2404 status
= rpc_pipe_open_internal(
2405 talloc_tos(), &ndr_table_samr
.syntax_id
, rpc_samr_dispatch
,
2406 conn
->server_info
, &samr_pipe
);
2407 if (!NT_STATUS_IS_OK(status
)) {
2408 DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
2409 nt_errstr(status
)));
2413 status
= rpccli_samr_Connect2(samr_pipe
, talloc_tos(), global_myname(),
2414 SAMR_ACCESS_LOOKUP_DOMAIN
, &samr_handle
);
2415 if (!NT_STATUS_IS_OK(status
)) {
2416 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2417 nt_errstr(status
)));
2421 status
= rpccli_samr_OpenDomain(samr_pipe
, talloc_tos(), &samr_handle
,
2422 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS
,
2423 get_global_sam_sid(), &domain_handle
);
2424 if (!NT_STATUS_IS_OK(status
)) {
2425 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2426 nt_errstr(status
)));
2427 rpccli_samr_Close(samr_pipe
, talloc_tos(), &samr_handle
);
2431 errflags
=NERR_Success
;
2436 struct samr_SamArray
*sam_entries
;
2437 uint32_t num_entries
;
2439 status
= rpccli_samr_EnumDomainUsers(samr_pipe
, talloc_tos(),
2445 if (!NT_STATUS_IS_OK(status
)) {
2446 DEBUG(10, ("rpccli_samr_EnumDomainUsers returned "
2447 "%s\n", nt_errstr(status
)));
2451 if (num_entries
== 0) {
2452 DEBUG(10, ("rpccli_samr_EnumDomainUsers returned "
2453 "no entries -- done\n"));
2457 for (i
=0; i
<num_entries
; i
++) {
2460 name
= sam_entries
->entries
[i
].name
.string
;
2462 if(((PTR_DIFF(p
,*rdata
)+21)<=*rdata_len
)
2463 &&(strlen(name
)<=21)) {
2464 strlcpy(p
,name
,PTR_DIFF(endp
,p
));
2465 DEBUG(10,("api_RNetUserEnum:adding entry %d "
2466 "username %s\n",count_sent
,p
));
2470 /* set overflow error */
2471 DEBUG(10,("api_RNetUserEnum:overflow on entry %d "
2472 "username %s\n",count_sent
,name
));
2478 if (errflags
!= NERR_Success
) {
2482 TALLOC_FREE(sam_entries
);
2485 rpccli_samr_Close(samr_pipe
, talloc_tos(), &domain_handle
);
2486 rpccli_samr_Close(samr_pipe
, talloc_tos(), &samr_handle
);
2488 *rdata_len
= PTR_DIFF(p
,*rdata
);
2490 SSVAL(*rparam
,0,errflags
);
2491 SSVAL(*rparam
,2,0); /* converter word */
2492 SSVAL(*rparam
,4,count_sent
); /* is this right?? */
2493 SSVAL(*rparam
,6,num_users
); /* is this right?? */
2498 /****************************************************************************
2499 Get the time of day info.
2500 ****************************************************************************/
2502 static bool api_NetRemoteTOD(connection_struct
*conn
,uint16 vuid
,
2503 char *param
, int tpscnt
,
2504 char *data
, int tdscnt
,
2505 int mdrcnt
,int mprcnt
,
2506 char **rdata
,char **rparam
,
2507 int *rdata_len
,int *rparam_len
)
2510 time_t unixdate
= time(NULL
);
2514 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2520 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2525 SSVAL(*rparam
,0,NERR_Success
);
2526 SSVAL(*rparam
,2,0); /* converter word */
2530 srv_put_dos_date3(p
,0,unixdate
); /* this is the time that is looked at
2531 by NT in a "net time" operation,
2532 it seems to ignore the one below */
2534 /* the client expects to get localtime, not GMT, in this bit
2535 (I think, this needs testing) */
2536 t
= localtime(&unixdate
);
2541 SIVAL(p
,4,0); /* msecs ? */
2542 SCVAL(p
,8,t
->tm_hour
);
2543 SCVAL(p
,9,t
->tm_min
);
2544 SCVAL(p
,10,t
->tm_sec
);
2545 SCVAL(p
,11,0); /* hundredths of seconds */
2546 SSVALS(p
,12,get_time_zone(unixdate
)/60); /* timezone in minutes from GMT */
2547 SSVAL(p
,14,10000); /* timer interval in 0.0001 of sec */
2548 SCVAL(p
,16,t
->tm_mday
);
2549 SCVAL(p
,17,t
->tm_mon
+ 1);
2550 SSVAL(p
,18,1900+t
->tm_year
);
2551 SCVAL(p
,20,t
->tm_wday
);
2556 /****************************************************************************
2557 Set the user password.
2558 *****************************************************************************/
2560 static bool api_SetUserPassword(connection_struct
*conn
,uint16 vuid
,
2561 char *param
, int tpscnt
,
2562 char *data
, int tdscnt
,
2563 int mdrcnt
,int mprcnt
,
2564 char **rdata
,char **rparam
,
2565 int *rdata_len
,int *rparam_len
)
2567 char *np
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2570 fstring pass1
,pass2
;
2572 /* Skip 2 strings. */
2573 p
= skip_string(param
,tpscnt
,np
);
2574 p
= skip_string(param
,tpscnt
,p
);
2580 /* Do we have a string ? */
2581 if (skip_string(param
,tpscnt
,p
) == NULL
) {
2584 pull_ascii_fstring(user
,p
);
2586 p
= skip_string(param
,tpscnt
,p
);
2591 memset(pass1
,'\0',sizeof(pass1
));
2592 memset(pass2
,'\0',sizeof(pass2
));
2594 * We use 31 here not 32 as we're checking
2595 * the last byte we want to access is safe.
2597 if (!is_offset_safe(param
,tpscnt
,p
,31)) {
2601 memcpy(pass2
,p
+16,16);
2604 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2611 SSVAL(*rparam
,0,NERR_badpass
);
2612 SSVAL(*rparam
,2,0); /* converter word */
2614 DEBUG(3,("Set password for <%s>\n",user
));
2617 * Attempt to verify the old password against smbpasswd entries
2618 * Win98 clients send old and new password in plaintext for this call.
2622 auth_serversupplied_info
*server_info
= NULL
;
2623 DATA_BLOB password
= data_blob(pass1
, strlen(pass1
)+1);
2625 if (NT_STATUS_IS_OK(check_plaintext_password(user
,password
,&server_info
))) {
2628 if (NT_STATUS_IS_OK(change_oem_password(server_info
->sam_account
, pass1
, pass2
, False
, NULL
))) {
2629 SSVAL(*rparam
,0,NERR_Success
);
2633 TALLOC_FREE(server_info
);
2635 data_blob_clear_free(&password
);
2639 * If the plaintext change failed, attempt
2640 * the old encrypted method. NT will generate this
2641 * after trying the samr method. Note that this
2642 * method is done as a last resort as this
2643 * password change method loses the NT password hash
2644 * and cannot change the UNIX password as no plaintext
2648 if(SVAL(*rparam
,0) != NERR_Success
) {
2649 struct samu
*hnd
= NULL
;
2651 if (check_lanman_password(user
,(unsigned char *)pass1
,(unsigned char *)pass2
, &hnd
)) {
2653 if (change_lanman_password(hnd
,(uchar
*)pass2
)) {
2654 SSVAL(*rparam
,0,NERR_Success
);
2661 memset((char *)pass1
,'\0',sizeof(fstring
));
2662 memset((char *)pass2
,'\0',sizeof(fstring
));
2667 /****************************************************************************
2668 Set the user password (SamOEM version - gets plaintext).
2669 ****************************************************************************/
2671 static bool api_SamOEMChangePassword(connection_struct
*conn
,uint16 vuid
,
2672 char *param
, int tpscnt
,
2673 char *data
, int tdscnt
,
2674 int mdrcnt
,int mprcnt
,
2675 char **rdata
,char **rparam
,
2676 int *rdata_len
,int *rparam_len
)
2678 struct smbd_server_connection
*sconn
= smbd_server_conn
;
2680 char *p
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2682 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2692 SSVAL(*rparam
,0,NERR_badpass
);
2695 * Check the parameter definition is correct.
2698 /* Do we have a string ? */
2699 if (skip_string(param
,tpscnt
,p
) == 0) {
2702 if(!strequal(p
, "zsT")) {
2703 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", p
));
2706 p
= skip_string(param
, tpscnt
, p
);
2711 /* Do we have a string ? */
2712 if (skip_string(param
,tpscnt
,p
) == 0) {
2715 if(!strequal(p
, "B516B16")) {
2716 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p
));
2719 p
= skip_string(param
,tpscnt
,p
);
2723 /* Do we have a string ? */
2724 if (skip_string(param
,tpscnt
,p
) == 0) {
2727 p
+= pull_ascii_fstring(user
,p
);
2729 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user
));
2732 * Pass the user through the NT -> unix user mapping
2736 (void)map_username(sconn
, user
);
2738 if (NT_STATUS_IS_OK(pass_oem_change(user
, (uchar
*) data
, (uchar
*)&data
[516], NULL
, NULL
, NULL
))) {
2739 SSVAL(*rparam
,0,NERR_Success
);
2745 /****************************************************************************
2748 ****************************************************************************/
2750 static bool api_RDosPrintJobDel(connection_struct
*conn
,uint16 vuid
,
2751 char *param
, int tpscnt
,
2752 char *data
, int tdscnt
,
2753 int mdrcnt
,int mprcnt
,
2754 char **rdata
,char **rparam
,
2755 int *rdata_len
,int *rparam_len
)
2757 int function
= get_safe_SVAL(param
,tpscnt
,param
,0,0);
2758 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2759 char *str2
= skip_string(param
,tpscnt
,str1
);
2760 char *p
= skip_string(param
,tpscnt
,str2
);
2765 WERROR werr
= WERR_OK
;
2767 if (!str1
|| !str2
|| !p
) {
2771 * We use 1 here not 2 as we're checking
2772 * the last byte we want to access is safe.
2774 if (!is_offset_safe(param
,tpscnt
,p
,1)) {
2777 if(!rap_to_pjobid(SVAL(p
,0), sharename
, &jobid
))
2780 /* check it's a supported varient */
2781 if (!(strcsequal(str1
,"W") && strcsequal(str2
,"")))
2785 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2791 if (!print_job_exists(sharename
, jobid
)) {
2792 errcode
= NERR_JobNotFound
;
2796 snum
= lp_servicenumber( sharename
);
2798 errcode
= NERR_DestNotFound
;
2802 errcode
= NERR_notsupported
;
2805 case 81: /* delete */
2806 if (print_job_delete(conn
->server_info
, snum
, jobid
, &werr
))
2807 errcode
= NERR_Success
;
2809 case 82: /* pause */
2810 if (print_job_pause(conn
->server_info
, snum
, jobid
, &werr
))
2811 errcode
= NERR_Success
;
2813 case 83: /* resume */
2814 if (print_job_resume(conn
->server_info
, snum
, jobid
, &werr
))
2815 errcode
= NERR_Success
;
2819 if (!W_ERROR_IS_OK(werr
))
2820 errcode
= W_ERROR_V(werr
);
2823 SSVAL(*rparam
,0,errcode
);
2824 SSVAL(*rparam
,2,0); /* converter word */
2829 /****************************************************************************
2830 Purge a print queue - or pause or resume it.
2831 ****************************************************************************/
2833 static bool api_WPrintQueueCtrl(connection_struct
*conn
,uint16 vuid
,
2834 char *param
, int tpscnt
,
2835 char *data
, int tdscnt
,
2836 int mdrcnt
,int mprcnt
,
2837 char **rdata
,char **rparam
,
2838 int *rdata_len
,int *rparam_len
)
2840 int function
= get_safe_SVAL(param
,tpscnt
,param
,0,0);
2841 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2842 char *str2
= skip_string(param
,tpscnt
,str1
);
2843 char *QueueName
= skip_string(param
,tpscnt
,str2
);
2844 int errcode
= NERR_notsupported
;
2846 WERROR werr
= WERR_OK
;
2848 if (!str1
|| !str2
|| !QueueName
) {
2852 /* check it's a supported varient */
2853 if (!(strcsequal(str1
,"z") && strcsequal(str2
,"")))
2857 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2863 if (skip_string(param
,tpscnt
,QueueName
) == NULL
) {
2866 snum
= print_queue_snum(QueueName
);
2869 errcode
= NERR_JobNotFound
;
2874 case 74: /* Pause queue */
2875 werr
= print_queue_pause(conn
->server_info
, snum
);
2877 case 75: /* Resume queue */
2878 werr
= print_queue_resume(conn
->server_info
, snum
);
2880 case 103: /* Purge */
2881 werr
= print_queue_purge(conn
->server_info
, snum
);
2884 werr
= WERR_NOT_SUPPORTED
;
2888 errcode
= W_ERROR_V(werr
);
2891 SSVAL(*rparam
,0,errcode
);
2892 SSVAL(*rparam
,2,0); /* converter word */
2897 /****************************************************************************
2898 set the property of a print job (undocumented?)
2899 ? function = 0xb -> set name of print job
2900 ? function = 0x6 -> move print job up/down
2901 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
2902 or <WWsTP> <WB21BB16B10zWWzDDz>
2903 ****************************************************************************/
2905 static int check_printjob_info(struct pack_desc
* desc
,
2906 int uLevel
, char* id
)
2908 desc
->subformat
= NULL
;
2910 case 0: desc
->format
= "W"; break;
2911 case 1: desc
->format
= "WB21BB16B10zWWzDDz"; break;
2912 case 2: desc
->format
= "WWzWWDDzz"; break;
2913 case 3: desc
->format
= "WWzWWDDzzzzzzzzzzlz"; break;
2914 case 4: desc
->format
= "WWzWWDDzzzzzDDDDDDD"; break;
2916 DEBUG(0,("check_printjob_info: invalid level %d\n",
2920 if (id
== NULL
|| strcmp(desc
->format
,id
) != 0) {
2921 DEBUG(0,("check_printjob_info: invalid format %s\n",
2922 id
? id
: "<NULL>" ));
2928 static bool api_PrintJobInfo(connection_struct
*conn
, uint16 vuid
,
2929 char *param
, int tpscnt
,
2930 char *data
, int tdscnt
,
2931 int mdrcnt
,int mprcnt
,
2932 char **rdata
,char **rparam
,
2933 int *rdata_len
,int *rparam_len
)
2935 struct pack_desc desc
;
2936 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2937 char *str2
= skip_string(param
,tpscnt
,str1
);
2938 char *p
= skip_string(param
,tpscnt
,str2
);
2941 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,2,-1);
2942 int function
= get_safe_SVAL(param
,tpscnt
,p
,4,-1);
2945 if (!str1
|| !str2
|| !p
) {
2949 * We use 1 here not 2 as we're checking
2950 * the last byte we want to access is safe.
2952 if (!is_offset_safe(param
,tpscnt
,p
,1)) {
2955 if(!rap_to_pjobid(SVAL(p
,0), sharename
, &jobid
))
2958 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2963 if (!share_defined(sharename
)) {
2964 DEBUG(0,("api_PrintJobInfo: sharen [%s] not defined\n",
2971 /* check it's a supported varient */
2972 if ((strcmp(str1
,"WWsTP")) ||
2973 (!check_printjob_info(&desc
,uLevel
,str2
)))
2976 if (!print_job_exists(sharename
, jobid
)) {
2977 errcode
=NERR_JobNotFound
;
2981 errcode
= NERR_notsupported
;
2985 /* change job place in the queue,
2986 data gives the new place */
2987 place
= SVAL(data
,0);
2988 if (print_job_set_place(sharename
, jobid
, place
)) {
2989 errcode
=NERR_Success
;
2994 /* change print job name, data gives the name */
2995 if (print_job_set_name(sharename
, jobid
, data
)) {
2996 errcode
=NERR_Success
;
3005 SSVALS(*rparam
,0,errcode
);
3006 SSVAL(*rparam
,2,0); /* converter word */
3012 /****************************************************************************
3013 Get info about the server.
3014 ****************************************************************************/
3016 static bool api_RNetServerGetInfo(connection_struct
*conn
,uint16 vuid
,
3017 char *param
, int tpscnt
,
3018 char *data
, int tdscnt
,
3019 int mdrcnt
,int mprcnt
,
3020 char **rdata
,char **rparam
,
3021 int *rdata_len
,int *rparam_len
)
3023 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3024 char *str2
= skip_string(param
,tpscnt
,str1
);
3025 char *p
= skip_string(param
,tpscnt
,str2
);
3026 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3030 if (!str1
|| !str2
|| !p
) {
3034 DEBUG(4,("NetServerGetInfo level %d\n",uLevel
));
3036 /* check it's a supported varient */
3037 if (!prefix_ok(str1
,"WrLh")) {
3043 if (strcmp(str2
,"B16") != 0) {
3049 if (strcmp(str2
,"B16BBDz") != 0) {
3055 if (strcmp(str2
,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")!= 0) {
3061 if (strcmp(str2
,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz") != 0) {
3067 if (strcmp(str2
,"DN") != 0) {
3073 if (strcmp(str2
,"B16BBDzWWzzz") != 0) {
3082 *rdata_len
= mdrcnt
;
3083 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
3089 p2
= p
+ struct_len
;
3091 srvstr_push(NULL
, 0, p
,global_myname(),16,
3092 STR_ASCII
|STR_UPPER
|STR_TERMINATE
);
3096 struct srv_info_struct
*servers
=NULL
;
3098 char *comment
= NULL
;
3099 TALLOC_CTX
*ctx
= talloc_tos();
3100 uint32 servertype
= lp_default_server_announce();
3102 comment
= talloc_strdup(ctx
,lp_serverstring());
3107 if ((count
=get_server_info(SV_TYPE_ALL
,&servers
,lp_workgroup()))>0) {
3108 for (i
=0;i
<count
;i
++) {
3109 if (strequal(servers
[i
].name
,global_myname())) {
3110 servertype
= servers
[i
].type
;
3111 TALLOC_FREE(comment
);
3112 comment
= talloc_strdup(ctx
,
3113 servers
[i
].comment
);
3123 SCVAL(p
,0,lp_major_announce_version());
3124 SCVAL(p
,1,lp_minor_announce_version());
3125 SIVAL(p
,2,servertype
);
3127 if (mdrcnt
== struct_len
) {
3130 SIVAL(p
,6,PTR_DIFF(p2
,*rdata
));
3131 comment
= talloc_sub_advanced(
3133 lp_servicename(SNUM(conn
)),
3134 conn
->server_info
->unix_name
,
3136 conn
->server_info
->utok
.gid
,
3137 conn
->server_info
->sanitized_username
,
3138 pdb_get_domain(conn
->server_info
->sam_account
),
3143 if (mdrcnt
- struct_len
<= 0) {
3148 MIN(mdrcnt
- struct_len
,
3149 MAX_SERVER_STRING_LENGTH
),
3151 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3159 return False
; /* not yet implemented */
3162 *rdata_len
= PTR_DIFF(p2
,*rdata
);
3165 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3169 SSVAL(*rparam
,0,NERR_Success
);
3170 SSVAL(*rparam
,2,0); /* converter word */
3171 SSVAL(*rparam
,4,*rdata_len
);
3176 /****************************************************************************
3177 Get info about the server.
3178 ****************************************************************************/
3180 static bool api_NetWkstaGetInfo(connection_struct
*conn
,uint16 vuid
,
3181 char *param
, int tpscnt
,
3182 char *data
, int tdscnt
,
3183 int mdrcnt
,int mprcnt
,
3184 char **rdata
,char **rparam
,
3185 int *rdata_len
,int *rparam_len
)
3187 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3188 char *str2
= skip_string(param
,tpscnt
,str1
);
3189 char *p
= skip_string(param
,tpscnt
,str2
);
3192 int level
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3194 if (!str1
|| !str2
|| !p
) {
3198 DEBUG(4,("NetWkstaGetInfo level %d\n",level
));
3201 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3206 /* check it's a supported varient */
3207 if (!(level
==10 && strcsequal(str1
,"WrLh") && strcsequal(str2
,"zzzBBzz"))) {
3211 *rdata_len
= mdrcnt
+ 1024;
3212 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
3217 SSVAL(*rparam
,0,NERR_Success
);
3218 SSVAL(*rparam
,2,0); /* converter word */
3221 endp
= *rdata
+ *rdata_len
;
3223 p2
= get_safe_ptr(*rdata
,*rdata_len
,p
,22);
3228 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* host name */
3229 strlcpy(p2
,get_local_machine_name(),PTR_DIFF(endp
,p2
));
3231 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3237 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
));
3238 strlcpy(p2
,conn
->server_info
->sanitized_username
,PTR_DIFF(endp
,p2
));
3239 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3245 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* login domain */
3246 strlcpy(p2
,lp_workgroup(),PTR_DIFF(endp
,p2
));
3248 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3254 SCVAL(p
,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
3255 SCVAL(p
,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
3258 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
));
3259 strlcpy(p2
,lp_workgroup(),PTR_DIFF(endp
,p2
)); /* don't know. login domain?? */
3260 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3266 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* don't know */
3267 strlcpy(p2
,"",PTR_DIFF(endp
,p2
));
3268 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3274 *rdata_len
= PTR_DIFF(p2
,*rdata
);
3276 SSVAL(*rparam
,4,*rdata_len
);
3281 /****************************************************************************
3282 get info about a user
3284 struct user_info_11 {
3285 char usri11_name[21]; 0-20
3287 char *usri11_comment; 22-25
3288 char *usri11_usr_comment; 26-29
3289 unsigned short usri11_priv; 30-31
3290 unsigned long usri11_auth_flags; 32-35
3291 long usri11_password_age; 36-39
3292 char *usri11_homedir; 40-43
3293 char *usri11_parms; 44-47
3294 long usri11_last_logon; 48-51
3295 long usri11_last_logoff; 52-55
3296 unsigned short usri11_bad_pw_count; 56-57
3297 unsigned short usri11_num_logons; 58-59
3298 char *usri11_logon_server; 60-63
3299 unsigned short usri11_country_code; 64-65
3300 char *usri11_workstations; 66-69
3301 unsigned long usri11_max_storage; 70-73
3302 unsigned short usri11_units_per_week; 74-75
3303 unsigned char *usri11_logon_hours; 76-79
3304 unsigned short usri11_code_page; 80-81
3309 usri11_name specifies the user name for which information is retrieved
3311 usri11_pad aligns the next data structure element to a word boundary
3313 usri11_comment is a null terminated ASCII comment
3315 usri11_user_comment is a null terminated ASCII comment about the user
3317 usri11_priv specifies the level of the privilege assigned to the user.
3318 The possible values are:
3320 Name Value Description
3321 USER_PRIV_GUEST 0 Guest privilege
3322 USER_PRIV_USER 1 User privilege
3323 USER_PRV_ADMIN 2 Administrator privilege
3325 usri11_auth_flags specifies the account operator privileges. The
3326 possible values are:
3328 Name Value Description
3329 AF_OP_PRINT 0 Print operator
3332 Leach, Naik [Page 28]
3336 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
3339 AF_OP_COMM 1 Communications operator
3340 AF_OP_SERVER 2 Server operator
3341 AF_OP_ACCOUNTS 3 Accounts operator
3344 usri11_password_age specifies how many seconds have elapsed since the
3345 password was last changed.
3347 usri11_home_dir points to a null terminated ASCII string that contains
3348 the path name of the user's home directory.
3350 usri11_parms points to a null terminated ASCII string that is set
3351 aside for use by applications.
3353 usri11_last_logon specifies the time when the user last logged on.
3354 This value is stored as the number of seconds elapsed since
3355 00:00:00, January 1, 1970.
3357 usri11_last_logoff specifies the time when the user last logged off.
3358 This value is stored as the number of seconds elapsed since
3359 00:00:00, January 1, 1970. A value of 0 means the last logoff
3362 usri11_bad_pw_count specifies the number of incorrect passwords
3363 entered since the last successful logon.
3365 usri11_log1_num_logons specifies the number of times this user has
3366 logged on. A value of -1 means the number of logons is unknown.
3368 usri11_logon_server points to a null terminated ASCII string that
3369 contains the name of the server to which logon requests are sent.
3370 A null string indicates logon requests should be sent to the
3373 usri11_country_code specifies the country code for the user's language
3376 usri11_workstations points to a null terminated ASCII string that
3377 contains the names of workstations the user may log on from.
3378 There may be up to 8 workstations, with the names separated by
3379 commas. A null strings indicates there are no restrictions.
3381 usri11_max_storage specifies the maximum amount of disk space the user
3382 can occupy. A value of 0xffffffff indicates there are no
3385 usri11_units_per_week specifies the equal number of time units into
3386 which a week is divided. This value must be equal to 168.
3388 usri11_logon_hours points to a 21 byte (168 bits) string that
3389 specifies the time during which the user can log on. Each bit
3390 represents one unique hour in a week. The first bit (bit 0, word
3391 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
3395 Leach, Naik [Page 29]
3399 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
3402 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
3403 are no restrictions.
3405 usri11_code_page specifies the code page for the user's language of
3408 All of the pointers in this data structure need to be treated
3409 specially. The pointer is a 32 bit pointer. The higher 16 bits need
3410 to be ignored. The converter word returned in the parameters section
3411 needs to be subtracted from the lower 16 bits to calculate an offset
3412 into the return buffer where this ASCII string resides.
3414 There is no auxiliary data in the response.
3416 ****************************************************************************/
3418 #define usri11_name 0
3419 #define usri11_pad 21
3420 #define usri11_comment 22
3421 #define usri11_usr_comment 26
3422 #define usri11_full_name 30
3423 #define usri11_priv 34
3424 #define usri11_auth_flags 36
3425 #define usri11_password_age 40
3426 #define usri11_homedir 44
3427 #define usri11_parms 48
3428 #define usri11_last_logon 52
3429 #define usri11_last_logoff 56
3430 #define usri11_bad_pw_count 60
3431 #define usri11_num_logons 62
3432 #define usri11_logon_server 64
3433 #define usri11_country_code 68
3434 #define usri11_workstations 70
3435 #define usri11_max_storage 74
3436 #define usri11_units_per_week 78
3437 #define usri11_logon_hours 80
3438 #define usri11_code_page 84
3439 #define usri11_end 86
3441 #define USER_PRIV_GUEST 0
3442 #define USER_PRIV_USER 1
3443 #define USER_PRIV_ADMIN 2
3445 #define AF_OP_PRINT 0
3446 #define AF_OP_COMM 1
3447 #define AF_OP_SERVER 2
3448 #define AF_OP_ACCOUNTS 3
3451 static bool api_RNetUserGetInfo(connection_struct
*conn
, uint16 vuid
,
3452 char *param
, int tpscnt
,
3453 char *data
, int tdscnt
,
3454 int mdrcnt
,int mprcnt
,
3455 char **rdata
,char **rparam
,
3456 int *rdata_len
,int *rparam_len
)
3458 struct smbd_server_connection
*sconn
= smbd_server_conn
;
3459 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3460 char *str2
= skip_string(param
,tpscnt
,str1
);
3461 char *UserName
= skip_string(param
,tpscnt
,str2
);
3462 char *p
= skip_string(param
,tpscnt
,UserName
);
3463 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3466 const char *level_string
;
3468 /* get NIS home of a previously validated user - simeon */
3469 /* With share level security vuid will always be zero.
3470 Don't depend on vuser being non-null !!. JRA */
3471 user_struct
*vuser
= get_valid_user_struct(sconn
, vuid
);
3473 DEBUG(3,(" Username of UID %d is %s\n",
3474 (int)vuser
->server_info
->utok
.uid
,
3475 vuser
->server_info
->unix_name
));
3478 if (!str1
|| !str2
|| !UserName
|| !p
) {
3483 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3488 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel
));
3490 /* check it's a supported variant */
3491 if (strcmp(str1
,"zWrLh") != 0) {
3495 case 0: level_string
= "B21"; break;
3496 case 1: level_string
= "B21BB16DWzzWz"; break;
3497 case 2: level_string
= "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
3498 case 10: level_string
= "B21Bzzz"; break;
3499 case 11: level_string
= "B21BzzzWDDzzDDWWzWzDWb21W"; break;
3500 default: return False
;
3503 if (strcmp(level_string
,str2
) != 0) {
3507 *rdata_len
= mdrcnt
+ 1024;
3508 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
3513 SSVAL(*rparam
,0,NERR_Success
);
3514 SSVAL(*rparam
,2,0); /* converter word */
3517 endp
= *rdata
+ *rdata_len
;
3518 p2
= get_safe_ptr(*rdata
,*rdata_len
,p
,usri11_end
);
3524 fstrcpy(p
+usri11_name
,UserName
); /* 21 bytes - user name */
3527 SCVAL(p
,usri11_pad
,0); /* padding - 1 byte */
3532 SIVAL(p
,usri11_comment
,PTR_DIFF(p2
,p
)); /* comment */
3533 strlcpy(p2
,"Comment",PTR_DIFF(endp
,p2
));
3534 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3539 SIVAL(p
,usri11_usr_comment
,PTR_DIFF(p2
,p
)); /* user_comment */
3540 strlcpy(p2
,"UserComment",PTR_DIFF(endp
,p2
));
3541 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3546 /* EEK! the cifsrap.txt doesn't have this in!!!! */
3547 SIVAL(p
,usri11_full_name
,PTR_DIFF(p2
,p
)); /* full name */
3548 strlcpy(p2
,((vuser
!= NULL
)
3549 ? pdb_get_fullname(vuser
->server_info
->sam_account
)
3550 : UserName
),PTR_DIFF(endp
,p2
));
3551 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3558 const char *homedir
= "";
3559 if (vuser
!= NULL
) {
3560 homedir
= pdb_get_homedir(
3561 vuser
->server_info
->sam_account
);
3563 /* modelled after NTAS 3.51 reply */
3564 SSVAL(p
,usri11_priv
,conn
->admin_user
?USER_PRIV_ADMIN
:USER_PRIV_USER
);
3565 SIVAL(p
,usri11_auth_flags
,AF_OP_PRINT
); /* auth flags */
3566 SIVALS(p
,usri11_password_age
,-1); /* password age */
3567 SIVAL(p
,usri11_homedir
,PTR_DIFF(p2
,p
)); /* home dir */
3568 strlcpy(p2
, homedir
, PTR_DIFF(endp
,p2
));
3569 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3573 SIVAL(p
,usri11_parms
,PTR_DIFF(p2
,p
)); /* parms */
3574 strlcpy(p2
,"",PTR_DIFF(endp
,p2
));
3575 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3579 SIVAL(p
,usri11_last_logon
,0); /* last logon */
3580 SIVAL(p
,usri11_last_logoff
,0); /* last logoff */
3581 SSVALS(p
,usri11_bad_pw_count
,-1); /* bad pw counts */
3582 SSVALS(p
,usri11_num_logons
,-1); /* num logons */
3583 SIVAL(p
,usri11_logon_server
,PTR_DIFF(p2
,p
)); /* logon server */
3584 strlcpy(p2
,"\\\\*",PTR_DIFF(endp
,p2
));
3585 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3589 SSVAL(p
,usri11_country_code
,0); /* country code */
3591 SIVAL(p
,usri11_workstations
,PTR_DIFF(p2
,p
)); /* workstations */
3592 strlcpy(p2
,"",PTR_DIFF(endp
,p2
));
3593 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3598 SIVALS(p
,usri11_max_storage
,-1); /* max storage */
3599 SSVAL(p
,usri11_units_per_week
,168); /* units per week */
3600 SIVAL(p
,usri11_logon_hours
,PTR_DIFF(p2
,p
)); /* logon hours */
3602 /* a simple way to get logon hours at all times. */
3604 SCVAL(p2
,21,0); /* fix zero termination */
3605 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3610 SSVAL(p
,usri11_code_page
,0); /* code page */
3613 if (uLevel
== 1 || uLevel
== 2) {
3614 memset(p
+22,' ',16); /* password */
3615 SIVALS(p
,38,-1); /* password age */
3617 conn
->admin_user
?USER_PRIV_ADMIN
:USER_PRIV_USER
);
3618 SIVAL(p
,44,PTR_DIFF(p2
,*rdata
)); /* home dir */
3619 strlcpy(p2
, vuser
? pdb_get_homedir(
3620 vuser
->server_info
->sam_account
) : "",
3622 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3626 SIVAL(p
,48,PTR_DIFF(p2
,*rdata
)); /* comment */
3628 SSVAL(p
,52,0); /* flags */
3629 SIVAL(p
,54,PTR_DIFF(p2
,*rdata
)); /* script_path */
3630 strlcpy(p2
, vuser
? pdb_get_logon_script(
3631 vuser
->server_info
->sam_account
) : "",
3633 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3638 SIVAL(p
,60,0); /* auth_flags */
3639 SIVAL(p
,64,PTR_DIFF(p2
,*rdata
)); /* full_name */
3640 strlcpy(p2
,((vuser
!= NULL
)
3641 ? pdb_get_fullname(vuser
->server_info
->sam_account
)
3642 : UserName
),PTR_DIFF(endp
,p2
));
3643 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3647 SIVAL(p
,68,0); /* urs_comment */
3648 SIVAL(p
,72,PTR_DIFF(p2
,*rdata
)); /* parms */
3649 strlcpy(p2
,"",PTR_DIFF(endp
,p2
));
3650 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3654 SIVAL(p
,76,0); /* workstations */
3655 SIVAL(p
,80,0); /* last_logon */
3656 SIVAL(p
,84,0); /* last_logoff */
3657 SIVALS(p
,88,-1); /* acct_expires */
3658 SIVALS(p
,92,-1); /* max_storage */
3659 SSVAL(p
,96,168); /* units_per_week */
3660 SIVAL(p
,98,PTR_DIFF(p2
,*rdata
)); /* logon_hours */
3663 SSVALS(p
,102,-1); /* bad_pw_count */
3664 SSVALS(p
,104,-1); /* num_logons */
3665 SIVAL(p
,106,PTR_DIFF(p2
,*rdata
)); /* logon_server */
3667 TALLOC_CTX
*ctx
= talloc_tos();
3668 int space_rem
= *rdata_len
- (p2
- *rdata
);
3671 if (space_rem
<= 0) {
3674 tmp
= talloc_strdup(ctx
, "\\\\%L");
3678 tmp
= talloc_sub_basic(ctx
,
3691 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3695 SSVAL(p
,110,49); /* country_code */
3696 SSVAL(p
,112,860); /* code page */
3700 *rdata_len
= PTR_DIFF(p2
,*rdata
);
3702 SSVAL(*rparam
,4,*rdata_len
); /* is this right?? */
3707 static bool api_WWkstaUserLogon(connection_struct
*conn
,uint16 vuid
,
3708 char *param
, int tpscnt
,
3709 char *data
, int tdscnt
,
3710 int mdrcnt
,int mprcnt
,
3711 char **rdata
,char **rparam
,
3712 int *rdata_len
,int *rparam_len
)
3714 struct smbd_server_connection
*sconn
= smbd_server_conn
;
3715 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3716 char *str2
= skip_string(param
,tpscnt
,str1
);
3717 char *p
= skip_string(param
,tpscnt
,str2
);
3719 struct pack_desc desc
;
3721 /* With share level security vuid will always be zero.
3722 Don't depend on vuser being non-null !!. JRA */
3723 user_struct
*vuser
= get_valid_user_struct(sconn
, vuid
);
3725 if (!str1
|| !str2
|| !p
) {
3730 DEBUG(3,(" Username of UID %d is %s\n",
3731 (int)vuser
->server_info
->utok
.uid
,
3732 vuser
->server_info
->unix_name
));
3735 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3736 name
= get_safe_str_ptr(param
,tpscnt
,p
,2);
3741 memset((char *)&desc
,'\0',sizeof(desc
));
3743 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel
,name
));
3745 /* check it's a supported varient */
3746 if (strcmp(str1
,"OOWb54WrLh") != 0) {
3749 if (uLevel
!= 1 || strcmp(str2
,"WB21BWDWWDDDDDDDzzzD") != 0) {
3753 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
3760 desc
.buflen
= mdrcnt
;
3761 desc
.subformat
= NULL
;
3764 if (init_package(&desc
,1,0)) {
3765 PACKI(&desc
,"W",0); /* code */
3766 PACKS(&desc
,"B21",name
); /* eff. name */
3767 PACKS(&desc
,"B",""); /* pad */
3768 PACKI(&desc
,"W", conn
->admin_user
?USER_PRIV_ADMIN
:USER_PRIV_USER
);
3769 PACKI(&desc
,"D",0); /* auth flags XXX */
3770 PACKI(&desc
,"W",0); /* num logons */
3771 PACKI(&desc
,"W",0); /* bad pw count */
3772 PACKI(&desc
,"D",0); /* last logon */
3773 PACKI(&desc
,"D",-1); /* last logoff */
3774 PACKI(&desc
,"D",-1); /* logoff time */
3775 PACKI(&desc
,"D",-1); /* kickoff time */
3776 PACKI(&desc
,"D",0); /* password age */
3777 PACKI(&desc
,"D",0); /* password can change */
3778 PACKI(&desc
,"D",-1); /* password must change */
3782 fstrcpy(mypath
,"\\\\");
3783 fstrcat(mypath
,get_local_machine_name());
3785 PACKS(&desc
,"z",mypath
); /* computer */
3788 PACKS(&desc
,"z",lp_workgroup());/* domain */
3789 PACKS(&desc
,"z", vuser
? pdb_get_logon_script(
3790 vuser
->server_info
->sam_account
) : ""); /* script path */
3791 PACKI(&desc
,"D",0x00000000); /* reserved */
3794 *rdata_len
= desc
.usedlen
;
3796 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3800 SSVALS(*rparam
,0,desc
.errcode
);
3802 SSVAL(*rparam
,4,desc
.neededlen
);
3804 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc
.errcode
));
3809 /****************************************************************************
3810 api_WAccessGetUserPerms
3811 ****************************************************************************/
3813 static bool api_WAccessGetUserPerms(connection_struct
*conn
,uint16 vuid
,
3814 char *param
, int tpscnt
,
3815 char *data
, int tdscnt
,
3816 int mdrcnt
,int mprcnt
,
3817 char **rdata
,char **rparam
,
3818 int *rdata_len
,int *rparam_len
)
3820 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3821 char *str2
= skip_string(param
,tpscnt
,str1
);
3822 char *user
= skip_string(param
,tpscnt
,str2
);
3823 char *resource
= skip_string(param
,tpscnt
,user
);
3825 if (!str1
|| !str2
|| !user
|| !resource
) {
3829 if (skip_string(param
,tpscnt
,resource
) == NULL
) {
3832 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user
,resource
));
3834 /* check it's a supported varient */
3835 if (strcmp(str1
,"zzh") != 0) {
3838 if (strcmp(str2
,"") != 0) {
3843 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3847 SSVALS(*rparam
,0,0); /* errorcode */
3848 SSVAL(*rparam
,2,0); /* converter word */
3849 SSVAL(*rparam
,4,0x7f); /* permission flags */
3854 /****************************************************************************
3855 api_WPrintJobEnumerate
3856 ****************************************************************************/
3858 static bool api_WPrintJobGetInfo(connection_struct
*conn
, uint16 vuid
,
3859 char *param
, int tpscnt
,
3860 char *data
, int tdscnt
,
3861 int mdrcnt
,int mprcnt
,
3862 char **rdata
,char **rparam
,
3863 int *rdata_len
,int *rparam_len
)
3865 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3866 char *str2
= skip_string(param
,tpscnt
,str1
);
3867 char *p
= skip_string(param
,tpscnt
,str2
);
3874 struct pack_desc desc
;
3875 print_queue_struct
*queue
=NULL
;
3876 print_status_struct status
;
3879 if (!str1
|| !str2
|| !p
) {
3883 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,2,-1);
3885 memset((char *)&desc
,'\0',sizeof(desc
));
3886 memset((char *)&status
,'\0',sizeof(status
));
3888 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel
,SVAL(p
,0)));
3890 /* check it's a supported varient */
3891 if (strcmp(str1
,"WWrLh") != 0) {
3894 if (!check_printjob_info(&desc
,uLevel
,str2
)) {
3898 if(!rap_to_pjobid(SVAL(p
,0), sharename
, &jobid
)) {
3902 snum
= lp_servicenumber( sharename
);
3903 if (snum
< 0 || !VALID_SNUM(snum
)) {
3907 count
= print_queue_status(snum
,&queue
,&status
);
3908 for (i
= 0; i
< count
; i
++) {
3909 if (queue
[i
].job
== jobid
) {
3915 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
3920 desc
.buflen
= mdrcnt
;
3923 * Don't return data but need to get correct length
3924 * init_package will return wrong size if buflen=0
3926 desc
.buflen
= getlen(desc
.format
);
3927 desc
.base
= tmpdata
= (char *)SMB_MALLOC( desc
.buflen
);
3930 if (init_package(&desc
,1,0)) {
3932 fill_printjob_info(conn
,snum
,uLevel
,&desc
,&queue
[i
],i
);
3933 *rdata_len
= desc
.usedlen
;
3935 desc
.errcode
= NERR_JobNotFound
;
3941 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3945 SSVALS(*rparam
,0,desc
.errcode
);
3947 SSVAL(*rparam
,4,desc
.neededlen
);
3952 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc
.errcode
));
3957 static bool api_WPrintJobEnumerate(connection_struct
*conn
, uint16 vuid
,
3958 char *param
, int tpscnt
,
3959 char *data
, int tdscnt
,
3960 int mdrcnt
,int mprcnt
,
3961 char **rdata
,char **rparam
,
3962 int *rdata_len
,int *rparam_len
)
3964 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3965 char *str2
= skip_string(param
,tpscnt
,str1
);
3966 char *p
= skip_string(param
,tpscnt
,str2
);
3972 struct pack_desc desc
;
3973 print_queue_struct
*queue
=NULL
;
3974 print_status_struct status
;
3976 if (!str1
|| !str2
|| !p
) {
3980 memset((char *)&desc
,'\0',sizeof(desc
));
3981 memset((char *)&status
,'\0',sizeof(status
));
3983 p
= skip_string(param
,tpscnt
,p
);
3987 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3989 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel
,name
));
3991 /* check it's a supported variant */
3992 if (strcmp(str1
,"zWrLeh") != 0) {
3997 return False
; /* defined only for uLevel 0,1,2 */
4000 if (!check_printjob_info(&desc
,uLevel
,str2
)) {
4004 snum
= find_service(name
);
4005 if ( !(lp_snum_ok(snum
) && lp_print_ok(snum
)) ) {
4009 count
= print_queue_status(snum
,&queue
,&status
);
4011 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4017 desc
.buflen
= mdrcnt
;
4019 if (init_package(&desc
,count
,0)) {
4021 for (i
= 0; i
< count
; i
++) {
4022 fill_printjob_info(conn
,snum
,uLevel
,&desc
,&queue
[i
],i
);
4023 if (desc
.errcode
== NERR_Success
) {
4029 *rdata_len
= desc
.usedlen
;
4032 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4036 SSVALS(*rparam
,0,desc
.errcode
);
4038 SSVAL(*rparam
,4,succnt
);
4039 SSVAL(*rparam
,6,count
);
4043 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc
.errcode
));
4048 static int check_printdest_info(struct pack_desc
* desc
,
4049 int uLevel
, char* id
)
4051 desc
->subformat
= NULL
;
4054 desc
->format
= "B9";
4057 desc
->format
= "B9B21WWzW";
4063 desc
->format
= "zzzWWzzzWW";
4066 DEBUG(0,("check_printdest_info: invalid level %d\n",
4070 if (id
== NULL
|| strcmp(desc
->format
,id
) != 0) {
4071 DEBUG(0,("check_printdest_info: invalid string %s\n",
4072 id
? id
: "<NULL>" ));
4078 static void fill_printdest_info(connection_struct
*conn
, int snum
, int uLevel
,
4079 struct pack_desc
* desc
)
4083 strncpy(buf
,SERVICE(snum
),sizeof(buf
)-1);
4084 buf
[sizeof(buf
)-1] = 0;
4088 PACKS(desc
,"B9",buf
); /* szName */
4090 PACKS(desc
,"B21",""); /* szUserName */
4091 PACKI(desc
,"W",0); /* uJobId */
4092 PACKI(desc
,"W",0); /* fsStatus */
4093 PACKS(desc
,"z",""); /* pszStatus */
4094 PACKI(desc
,"W",0); /* time */
4098 if (uLevel
== 2 || uLevel
== 3) {
4099 PACKS(desc
,"z",buf
); /* pszPrinterName */
4101 PACKS(desc
,"z",""); /* pszUserName */
4102 PACKS(desc
,"z",""); /* pszLogAddr */
4103 PACKI(desc
,"W",0); /* uJobId */
4104 PACKI(desc
,"W",0); /* fsStatus */
4105 PACKS(desc
,"z",""); /* pszStatus */
4106 PACKS(desc
,"z",""); /* pszComment */
4107 PACKS(desc
,"z","NULL"); /* pszDrivers */
4108 PACKI(desc
,"W",0); /* time */
4109 PACKI(desc
,"W",0); /* pad1 */
4114 static bool api_WPrintDestGetInfo(connection_struct
*conn
, uint16 vuid
,
4115 char *param
, int tpscnt
,
4116 char *data
, int tdscnt
,
4117 int mdrcnt
,int mprcnt
,
4118 char **rdata
,char **rparam
,
4119 int *rdata_len
,int *rparam_len
)
4121 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4122 char *str2
= skip_string(param
,tpscnt
,str1
);
4123 char *p
= skip_string(param
,tpscnt
,str2
);
4124 char* PrinterName
= p
;
4126 struct pack_desc desc
;
4130 if (!str1
|| !str2
|| !p
) {
4134 memset((char *)&desc
,'\0',sizeof(desc
));
4136 p
= skip_string(param
,tpscnt
,p
);
4140 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4142 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel
,PrinterName
));
4144 /* check it's a supported varient */
4145 if (strcmp(str1
,"zWrLh") != 0) {
4148 if (!check_printdest_info(&desc
,uLevel
,str2
)) {
4152 snum
= find_service(PrinterName
);
4153 if ( !(lp_snum_ok(snum
) && lp_print_ok(snum
)) ) {
4155 desc
.errcode
= NERR_DestNotFound
;
4159 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4164 desc
.buflen
= mdrcnt
;
4167 * Don't return data but need to get correct length
4168 * init_package will return wrong size if buflen=0
4170 desc
.buflen
= getlen(desc
.format
);
4171 desc
.base
= tmpdata
= (char *)SMB_MALLOC( desc
.buflen
);
4173 if (init_package(&desc
,1,0)) {
4174 fill_printdest_info(conn
,snum
,uLevel
,&desc
);
4176 *rdata_len
= desc
.usedlen
;
4180 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4184 SSVALS(*rparam
,0,desc
.errcode
);
4186 SSVAL(*rparam
,4,desc
.neededlen
);
4188 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc
.errcode
));
4194 static bool api_WPrintDestEnum(connection_struct
*conn
, uint16 vuid
,
4195 char *param
, int tpscnt
,
4196 char *data
, int tdscnt
,
4197 int mdrcnt
,int mprcnt
,
4198 char **rdata
,char **rparam
,
4199 int *rdata_len
,int *rparam_len
)
4201 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4202 char *str2
= skip_string(param
,tpscnt
,str1
);
4203 char *p
= skip_string(param
,tpscnt
,str2
);
4207 struct pack_desc desc
;
4208 int services
= lp_numservices();
4210 if (!str1
|| !str2
|| !p
) {
4214 memset((char *)&desc
,'\0',sizeof(desc
));
4216 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4218 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel
));
4220 /* check it's a supported varient */
4221 if (strcmp(str1
,"WrLeh") != 0) {
4224 if (!check_printdest_info(&desc
,uLevel
,str2
)) {
4229 for (i
= 0; i
< services
; i
++) {
4230 if (lp_snum_ok(i
) && lp_print_ok(i
) && lp_browseable(i
)) {
4236 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4243 desc
.buflen
= mdrcnt
;
4244 if (init_package(&desc
,queuecnt
,0)) {
4247 for (i
= 0; i
< services
; i
++) {
4248 if (lp_snum_ok(i
) && lp_print_ok(i
) && lp_browseable(i
)) {
4249 fill_printdest_info(conn
,i
,uLevel
,&desc
);
4251 if (desc
.errcode
== NERR_Success
) {
4258 *rdata_len
= desc
.usedlen
;
4261 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4265 SSVALS(*rparam
,0,desc
.errcode
);
4267 SSVAL(*rparam
,4,succnt
);
4268 SSVAL(*rparam
,6,queuecnt
);
4270 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc
.errcode
));
4275 static bool api_WPrintDriverEnum(connection_struct
*conn
, uint16 vuid
,
4276 char *param
, int tpscnt
,
4277 char *data
, int tdscnt
,
4278 int mdrcnt
,int mprcnt
,
4279 char **rdata
,char **rparam
,
4280 int *rdata_len
,int *rparam_len
)
4282 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4283 char *str2
= skip_string(param
,tpscnt
,str1
);
4284 char *p
= skip_string(param
,tpscnt
,str2
);
4287 struct pack_desc desc
;
4289 if (!str1
|| !str2
|| !p
) {
4293 memset((char *)&desc
,'\0',sizeof(desc
));
4295 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4297 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel
));
4299 /* check it's a supported varient */
4300 if (strcmp(str1
,"WrLeh") != 0) {
4303 if (uLevel
!= 0 || strcmp(str2
,"B41") != 0) {
4308 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4314 desc
.buflen
= mdrcnt
;
4315 if (init_package(&desc
,1,0)) {
4316 PACKS(&desc
,"B41","NULL");
4319 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
4321 *rdata_len
= desc
.usedlen
;
4324 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4328 SSVALS(*rparam
,0,desc
.errcode
);
4330 SSVAL(*rparam
,4,succnt
);
4333 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc
.errcode
));
4338 static bool api_WPrintQProcEnum(connection_struct
*conn
, uint16 vuid
,
4339 char *param
, int tpscnt
,
4340 char *data
, int tdscnt
,
4341 int mdrcnt
,int mprcnt
,
4342 char **rdata
,char **rparam
,
4343 int *rdata_len
,int *rparam_len
)
4345 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4346 char *str2
= skip_string(param
,tpscnt
,str1
);
4347 char *p
= skip_string(param
,tpscnt
,str2
);
4350 struct pack_desc desc
;
4352 if (!str1
|| !str2
|| !p
) {
4355 memset((char *)&desc
,'\0',sizeof(desc
));
4357 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4359 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel
));
4361 /* check it's a supported varient */
4362 if (strcmp(str1
,"WrLeh") != 0) {
4365 if (uLevel
!= 0 || strcmp(str2
,"B13") != 0) {
4370 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4376 desc
.buflen
= mdrcnt
;
4378 if (init_package(&desc
,1,0)) {
4379 PACKS(&desc
,"B13","lpd");
4382 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
4384 *rdata_len
= desc
.usedlen
;
4387 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4391 SSVALS(*rparam
,0,desc
.errcode
);
4393 SSVAL(*rparam
,4,succnt
);
4396 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc
.errcode
));
4401 static bool api_WPrintPortEnum(connection_struct
*conn
, uint16 vuid
,
4402 char *param
, int tpscnt
,
4403 char *data
, int tdscnt
,
4404 int mdrcnt
,int mprcnt
,
4405 char **rdata
,char **rparam
,
4406 int *rdata_len
,int *rparam_len
)
4408 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4409 char *str2
= skip_string(param
,tpscnt
,str1
);
4410 char *p
= skip_string(param
,tpscnt
,str2
);
4413 struct pack_desc desc
;
4415 if (!str1
|| !str2
|| !p
) {
4419 memset((char *)&desc
,'\0',sizeof(desc
));
4421 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4423 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel
));
4425 /* check it's a supported varient */
4426 if (strcmp(str1
,"WrLeh") != 0) {
4429 if (uLevel
!= 0 || strcmp(str2
,"B9") != 0) {
4434 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4439 memset((char *)&desc
,'\0',sizeof(desc
));
4441 desc
.buflen
= mdrcnt
;
4443 if (init_package(&desc
,1,0)) {
4444 PACKS(&desc
,"B13","lp0");
4447 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
4449 *rdata_len
= desc
.usedlen
;
4452 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4456 SSVALS(*rparam
,0,desc
.errcode
);
4458 SSVAL(*rparam
,4,succnt
);
4461 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc
.errcode
));
4466 /****************************************************************************
4468 ****************************************************************************/
4470 static bool api_RNetSessionEnum(connection_struct
*conn
, uint16 vuid
,
4471 char *param
, int tpscnt
,
4472 char *data
, int tdscnt
,
4473 int mdrcnt
,int mprcnt
,
4474 char **rdata
,char **rparam
,
4475 int *rdata_len
,int *rparam_len
)
4478 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4479 char *str2
= skip_string(param
,tpscnt
,str1
);
4480 char *p
= skip_string(param
,tpscnt
,str2
);
4482 struct pack_desc desc
;
4483 struct sessionid
*session_list
;
4484 int i
, num_sessions
;
4486 if (!str1
|| !str2
|| !p
) {
4490 memset((char *)&desc
,'\0',sizeof(desc
));
4492 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4494 DEBUG(3,("RNetSessionEnum uLevel=%d\n",uLevel
));
4495 DEBUG(7,("RNetSessionEnum req string=%s\n",str1
));
4496 DEBUG(7,("RNetSessionEnum ret string=%s\n",str2
));
4498 /* check it's a supported varient */
4499 if (strcmp(str1
,RAP_NetSessionEnum_REQ
) != 0) {
4502 if (uLevel
!= 2 || strcmp(str2
,RAP_SESSION_INFO_L2
) != 0) {
4506 num_sessions
= list_sessions(talloc_tos(), &session_list
);
4509 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4514 memset((char *)&desc
,'\0',sizeof(desc
));
4516 desc
.buflen
= mdrcnt
;
4518 if (!init_package(&desc
,num_sessions
,0)) {
4522 for(i
=0; i
<num_sessions
; i
++) {
4523 PACKS(&desc
, "z", session_list
[i
].remote_machine
);
4524 PACKS(&desc
, "z", session_list
[i
].username
);
4525 PACKI(&desc
, "W", 1); /* num conns */
4526 PACKI(&desc
, "W", 0); /* num opens */
4527 PACKI(&desc
, "W", 1); /* num users */
4528 PACKI(&desc
, "D", 0); /* session time */
4529 PACKI(&desc
, "D", 0); /* idle time */
4530 PACKI(&desc
, "D", 0); /* flags */
4531 PACKS(&desc
, "z", "Unknown Client"); /* client type string */
4534 *rdata_len
= desc
.usedlen
;
4537 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4541 SSVALS(*rparam
,0,desc
.errcode
);
4542 SSVAL(*rparam
,2,0); /* converter */
4543 SSVAL(*rparam
,4,num_sessions
); /* count */
4545 DEBUG(4,("RNetSessionEnum: errorcode %d\n",desc
.errcode
));
4551 /****************************************************************************
4552 The buffer was too small.
4553 ****************************************************************************/
4555 static bool api_TooSmall(connection_struct
*conn
,uint16 vuid
, char *param
, char *data
,
4556 int mdrcnt
, int mprcnt
,
4557 char **rdata
, char **rparam
,
4558 int *rdata_len
, int *rparam_len
)
4560 *rparam_len
= MIN(*rparam_len
,mprcnt
);
4561 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4568 SSVAL(*rparam
,0,NERR_BufTooSmall
);
4570 DEBUG(3,("Supplied buffer too small in API command\n"));
4575 /****************************************************************************
4576 The request is not supported.
4577 ****************************************************************************/
4579 static bool api_Unsupported(connection_struct
*conn
, uint16 vuid
,
4580 char *param
, int tpscnt
,
4581 char *data
, int tdscnt
,
4582 int mdrcnt
, int mprcnt
,
4583 char **rdata
, char **rparam
,
4584 int *rdata_len
, int *rparam_len
)
4587 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4594 SSVAL(*rparam
,0,NERR_notsupported
);
4595 SSVAL(*rparam
,2,0); /* converter word */
4597 DEBUG(3,("Unsupported API command\n"));
4602 static const struct {
4605 bool (*fn
)(connection_struct
*, uint16
,
4608 int,int,char **,char **,int *,int *);
4609 bool auth_user
; /* Deny anonymous access? */
4610 } api_commands
[] = {
4611 {"RNetShareEnum", RAP_WshareEnum
, api_RNetShareEnum
, True
},
4612 {"RNetShareGetInfo", RAP_WshareGetInfo
, api_RNetShareGetInfo
},
4613 {"RNetShareAdd", RAP_WshareAdd
, api_RNetShareAdd
},
4614 {"RNetSessionEnum", RAP_WsessionEnum
, api_RNetSessionEnum
, True
},
4615 {"RNetServerGetInfo", RAP_WserverGetInfo
, api_RNetServerGetInfo
},
4616 {"RNetGroupEnum", RAP_WGroupEnum
, api_RNetGroupEnum
, True
},
4617 {"RNetGroupGetUsers", RAP_WGroupGetUsers
, api_RNetGroupGetUsers
, True
},
4618 {"RNetUserEnum", RAP_WUserEnum
, api_RNetUserEnum
, True
},
4619 {"RNetUserGetInfo", RAP_WUserGetInfo
, api_RNetUserGetInfo
},
4620 {"NetUserGetGroups", RAP_WUserGetGroups
, api_NetUserGetGroups
},
4621 {"NetWkstaGetInfo", RAP_WWkstaGetInfo
, api_NetWkstaGetInfo
},
4622 {"DosPrintQEnum", RAP_WPrintQEnum
, api_DosPrintQEnum
, True
},
4623 {"DosPrintQGetInfo", RAP_WPrintQGetInfo
, api_DosPrintQGetInfo
},
4624 {"WPrintQueuePause", RAP_WPrintQPause
, api_WPrintQueueCtrl
},
4625 {"WPrintQueueResume", RAP_WPrintQContinue
, api_WPrintQueueCtrl
},
4626 {"WPrintJobEnumerate",RAP_WPrintJobEnum
, api_WPrintJobEnumerate
},
4627 {"WPrintJobGetInfo", RAP_WPrintJobGetInfo
, api_WPrintJobGetInfo
},
4628 {"RDosPrintJobDel", RAP_WPrintJobDel
, api_RDosPrintJobDel
},
4629 {"RDosPrintJobPause", RAP_WPrintJobPause
, api_RDosPrintJobDel
},
4630 {"RDosPrintJobResume",RAP_WPrintJobContinue
, api_RDosPrintJobDel
},
4631 {"WPrintDestEnum", RAP_WPrintDestEnum
, api_WPrintDestEnum
},
4632 {"WPrintDestGetInfo", RAP_WPrintDestGetInfo
, api_WPrintDestGetInfo
},
4633 {"NetRemoteTOD", RAP_NetRemoteTOD
, api_NetRemoteTOD
},
4634 {"WPrintQueuePurge", RAP_WPrintQPurge
, api_WPrintQueueCtrl
},
4635 {"NetServerEnum", RAP_NetServerEnum2
, api_RNetServerEnum
}, /* anon OK */
4636 {"WAccessGetUserPerms",RAP_WAccessGetUserPerms
,api_WAccessGetUserPerms
},
4637 {"SetUserPassword", RAP_WUserPasswordSet2
, api_SetUserPassword
},
4638 {"WWkstaUserLogon", RAP_WWkstaUserLogon
, api_WWkstaUserLogon
},
4639 {"PrintJobInfo", RAP_WPrintJobSetInfo
, api_PrintJobInfo
},
4640 {"WPrintDriverEnum", RAP_WPrintDriverEnum
, api_WPrintDriverEnum
},
4641 {"WPrintQProcEnum", RAP_WPrintQProcessorEnum
,api_WPrintQProcEnum
},
4642 {"WPrintPortEnum", RAP_WPrintPortEnum
, api_WPrintPortEnum
},
4643 {"SamOEMChangePassword",RAP_SamOEMChgPasswordUser2_P
,api_SamOEMChangePassword
}, /* anon OK */
4644 {NULL
, -1, api_Unsupported
}
4645 /* The following RAP calls are not implemented by Samba:
4647 RAP_WFileEnum2 - anon not OK
4652 /****************************************************************************
4653 Handle remote api calls.
4654 ****************************************************************************/
4656 void api_reply(connection_struct
*conn
, uint16 vuid
,
4657 struct smb_request
*req
,
4658 char *data
, char *params
,
4659 int tdscnt
, int tpscnt
,
4660 int mdrcnt
, int mprcnt
)
4662 struct smbd_server_connection
*sconn
= smbd_server_conn
;
4665 char *rparam
= NULL
;
4666 const char *name1
= NULL
;
4667 const char *name2
= NULL
;
4674 DEBUG(0,("ERROR: NULL params in api_reply()\n"));
4675 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4680 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4683 api_command
= SVAL(params
,0);
4684 /* Is there a string at position params+2 ? */
4685 if (skip_string(params
,tpscnt
,params
+2)) {
4690 name2
= skip_string(params
,tpscnt
,params
+2);
4695 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
4699 tdscnt
,tpscnt
,mdrcnt
,mprcnt
));
4701 for (i
=0;api_commands
[i
].name
;i
++) {
4702 if (api_commands
[i
].id
== api_command
&& api_commands
[i
].fn
) {
4703 DEBUG(3,("Doing %s\n",api_commands
[i
].name
));
4708 /* Check whether this api call can be done anonymously */
4710 if (api_commands
[i
].auth_user
&& lp_restrict_anonymous()) {
4711 user_struct
*user
= get_valid_user_struct(sconn
, vuid
);
4713 if (!user
|| user
->server_info
->guest
) {
4714 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4719 rdata
= (char *)SMB_MALLOC(1024);
4721 memset(rdata
,'\0',1024);
4724 rparam
= (char *)SMB_MALLOC(1024);
4726 memset(rparam
,'\0',1024);
4729 if(!rdata
|| !rparam
) {
4730 DEBUG(0,("api_reply: malloc fail !\n"));
4733 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4737 reply
= api_commands
[i
].fn(conn
,
4739 params
,tpscnt
, /* params + length */
4740 data
,tdscnt
, /* data + length */
4742 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
4745 if (rdata_len
> mdrcnt
|| rparam_len
> mprcnt
) {
4746 reply
= api_TooSmall(conn
,vuid
,params
,data
,mdrcnt
,mprcnt
,
4747 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
4750 /* if we get False back then it's actually unsupported */
4752 reply
= api_Unsupported(conn
,vuid
,params
,tpscnt
,data
,tdscnt
,mdrcnt
,mprcnt
,
4753 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
4756 /* If api_Unsupported returns false we can't return anything. */
4758 send_trans_reply(conn
, req
, rparam
, rparam_len
,
4759 rdata
, rdata_len
, False
);